lib_config.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. # See utils/checkpackagelib/readme.txt before editing this file.
  2. # Kconfig generates errors if someone introduces a typo like "boool" instead of
  3. # "bool", so below check functions don't need to check for things already
  4. # checked by running "make menuconfig".
  5. import re
  6. from checkpackagelib.base import _CheckFunction
  7. from checkpackagelib.lib import ConsecutiveEmptyLines # noqa: F401
  8. from checkpackagelib.lib import EmptyLastLine # noqa: F401
  9. from checkpackagelib.lib import NewlineAtEof # noqa: F401
  10. from checkpackagelib.lib import TrailingSpace # noqa: F401
  11. def _empty_or_comment(text):
  12. line = text.strip()
  13. # ignore empty lines and comment lines indented or not
  14. return line == "" or line.startswith("#")
  15. def _part_of_help_text(text):
  16. return text.startswith("\t ")
  17. # used in more than one check
  18. entries_that_should_not_be_indented = [
  19. "choice", "comment", "config", "endchoice", "endif", "endmenu", "if",
  20. "menu", "menuconfig", "source"]
  21. class AttributesOrder(_CheckFunction):
  22. attributes_order_convention = {
  23. "bool": 1, "prompt": 1, "string": 1, "default": 2, "depends": 3,
  24. "select": 4, "help": 5}
  25. def before(self):
  26. self.state = 0
  27. def check_line(self, lineno, text):
  28. if _empty_or_comment(text) or _part_of_help_text(text):
  29. return
  30. attribute = text.split()[0]
  31. if attribute in entries_that_should_not_be_indented:
  32. self.state = 0
  33. return
  34. if attribute not in self.attributes_order_convention.keys():
  35. return
  36. new_state = self.attributes_order_convention[attribute]
  37. wrong_order = self.state > new_state
  38. # save to process next line
  39. self.state = new_state
  40. if wrong_order:
  41. return ["{}:{}: attributes order: type, default, depends on,"
  42. " select, help ({}#_config_files)"
  43. .format(self.filename, lineno, self.url_to_manual),
  44. text]
  45. class HelpText(_CheckFunction):
  46. HELP_TEXT_FORMAT = re.compile("^\t .{,62}$")
  47. URL_ONLY = re.compile("^(http|https|git)://\S*$")
  48. def before(self):
  49. self.help_text = False
  50. def check_line(self, lineno, text):
  51. if _empty_or_comment(text):
  52. return
  53. entry = text.split()[0]
  54. if entry in entries_that_should_not_be_indented:
  55. self.help_text = False
  56. return
  57. if text.strip() == "help":
  58. self.help_text = True
  59. return
  60. if not self.help_text:
  61. return
  62. if self.HELP_TEXT_FORMAT.match(text.rstrip()):
  63. return
  64. if self.URL_ONLY.match(text.strip()):
  65. return
  66. return ["{}:{}: help text: <tab><2 spaces><62 chars>"
  67. " ({}#writing-rules-config-in)"
  68. .format(self.filename, lineno, self.url_to_manual),
  69. text,
  70. "\t " + "123456789 " * 6 + "12"]
  71. class Indent(_CheckFunction):
  72. ENDS_WITH_BACKSLASH = re.compile(r"^[^#].*\\$")
  73. entries_that_should_be_indented = [
  74. "bool", "default", "depends", "help", "prompt", "select", "string"]
  75. def before(self):
  76. self.backslash = False
  77. def check_line(self, lineno, text):
  78. if _empty_or_comment(text) or _part_of_help_text(text):
  79. self.backslash = False
  80. return
  81. entry = text.split()[0]
  82. last_line_ends_in_backslash = self.backslash
  83. # calculate for next line
  84. if self.ENDS_WITH_BACKSLASH.search(text):
  85. self.backslash = True
  86. else:
  87. self.backslash = False
  88. if last_line_ends_in_backslash:
  89. if text.startswith("\t"):
  90. return
  91. return ["{}:{}: continuation line should be indented using tabs"
  92. .format(self.filename, lineno),
  93. text]
  94. if entry in self.entries_that_should_be_indented:
  95. if not text.startswith("\t{}".format(entry)):
  96. return ["{}:{}: should be indented with one tab"
  97. " ({}#_config_files)"
  98. .format(self.filename, lineno, self.url_to_manual),
  99. text]
  100. elif entry in entries_that_should_not_be_indented:
  101. if not text.startswith(entry):
  102. # four Config.in files have a special but legitimate indentation rule
  103. if self.filename in ["package/Config.in",
  104. "package/Config.in.host",
  105. "package/kodi/Config.in",
  106. "package/x11r7/Config.in"]:
  107. return
  108. return ["{}:{}: should not be indented"
  109. .format(self.filename, lineno),
  110. text]