@@ -3,14 +3,28 @@ import re
class _CheckFunction(object):
+ flags = []
+
def __init__(self, filename, url_to_manual):
self.filename = filename
self.url_to_manual = url_to_manual
- self.disable = re.compile(r"^\s*# check-package .*\b{}\b".format(self.__class__.__name__))
+ if self.flags:
+ flags_pattern = '|_' + '|_'.join(self.flags)
+ else:
+ flags_pattern = ''
+ self.disable = re.compile(r"^\s*# check-package .*\b{}({})\b".format(self.__class__.__name__, flags_pattern))
+ self.enabled_flags = {f: False for f in self.flags}
def check_disabled(self, line_before):
- if self.disable.search(line_before):
- return True
+ found = self.disable.findall(line_before)
+ if found:
+ # catch flags to be used by CheckFunction for a source file, for all lines below
+ flags_found = [f[1:] for f in found if (f != '' and f[0] == '_')]
+ for f in flags_found:
+ self.enabled_flags[f] = True
+
+ ignore_this_line = '' in found
+ return ignore_this_line
return False
def before(self):
@@ -47,3 +47,85 @@ def test_IgnoreNextLine(testname, filename, string, expected):
warnings = util.check_file(CheckFunctionUnderTest, filename, string)
assert warnings == expected
+
+
+SpecialCheckForThisFile = [
+ ('without special comment',
+ 'any',
+ 'content to test\n'
+ '# commented content to test\n'
+ 'content to test\n'
+ 'content to test\n'
+ 'content to test\n',
+ [1, 2, 3, 4, 5]), # set of line numbers for all lines not ignored while testing
+ ('ignore next line (CheckFunction with flags)',
+ 'any',
+ 'content to test\n'
+ '# check-package CheckFunctionUnderTest\n'
+ 'content to ignore\n'
+ 'content to test\n'
+ 'content to test\n',
+ [1, 2, 4, 5]),
+ ('comment to ignore one CheckFunction does not affect another one (CheckFunction with flags)',
+ 'any',
+ 'content to test\n'
+ '# check-package AnotherCheckFunction\n'
+ 'content to test\n'
+ 'content to test\n'
+ 'content to test\n',
+ [1, 2, 3, 4, 5]),
+ ('ignore 2 CheckFunctions for next line (CheckFunction with flags)',
+ 'any',
+ '# check-package CheckFunctionUnderTest, AnotherCheckFunction\n'
+ 'content to ignore\n'
+ '# check-package AnotherCheckFunction, CheckFunctionUnderTest\n'
+ 'content to ignore\n'
+ 'content to test\n',
+ [1, 3, 5]),
+ ('one flag',
+ 'any',
+ 'content to test using default code\n'
+ '# check-package CheckFunctionUnderTest_flag-2\n'
+ 'content to test using flag-2\n'
+ 'content to test using flag-2\n',
+ [1, 2, [3, [-2]], [4, [-2]]]),
+ ('flag and ignore next line in the same file',
+ 'any',
+ 'content to test using default code\n'
+ '# check-package CheckFunctionUnderTest\n'
+ 'content to ignore\n'
+ '# check-package CheckFunctionUnderTest_flag-2\n'
+ 'content to test using flag-2\n'
+ '# check-package CheckFunctionUnderTest\n'
+ 'content to ignore\n'
+ 'content to test using flag-2\n',
+ [1, 2, 4, [5, [-2]], [6, [-2]], [8, [-2]]]),
+ ('2 flags',
+ 'any',
+ 'content to test using default code\n'
+ '# check-package CheckFunctionUnderTest_flag-2\n'
+ 'content to test using flag-2\n'
+ '# check-package CheckFunctionUnderTest_flag-1\n'
+ 'content to test using flag-1 and flag-2\n'
+ 'content to test using flag-1 and flag-2\n',
+ [1, 2, [3, [-2]], [4, [-2]], [5, [-1, -2]], [6, [-1, -2]]]),
+ ]
+
+
+@pytest.mark.parametrize('testname,filename,string,expected', SpecialCheckForThisFile)
+def test_SpecialCheckForThisFile(testname, filename, string, expected):
+ class CheckFunctionUnderTest(m._CheckFunction):
+ flags = ['flag-1', 'flag-2']
+
+ def check_line(self, lineno, text):
+ flags = []
+ if self.enabled_flags['flag-1']:
+ flags.append(-1)
+ if self.enabled_flags['flag-2']:
+ flags.append(-2)
+ if flags:
+ return [lineno, flags]
+ return lineno
+
+ warnings = util.check_file(CheckFunctionUnderTest, filename, string)
+ assert warnings == expected
Currently source files analysed by check-package can use a special comment to hint the script to completely ignore a CheckFunction for the next line of the source file: # check-package Indent Extend that functionality to also support flags that will trigger special behaviour. For instance, by adding the line to a Config.in file: # check-package Indent_ignore-menu-indent-below makes the CheckFunction named Indent to set a flag named ignore-menu-indent-below and use it until the end of the source file under test. One example of use for this new special comment is Indent() from lib_config.py, that currently keeps a list of 4 intree Config.in files that have a special but legitimate indentation rule. Instead of keeping the list inside the code, now a special comment can be used in each of these 4 Config.in files. A great side effect of this new type of special comment is that it can also be used in source files from br2-external trees. Concept reused from James Knight's work in [1] and [2]. [1] http://patchwork.ozlabs.org/project/buildroot/patch/SN4P221MB0682AE13FB1ACA5A755024F1A0689@SN4P221MB0682.NAMP221.PROD.OUTLOOK.COM/ [2] http://patchwork.ozlabs.org/project/buildroot/patch/SN4P221MB06823B0F7326D27ECD5E0FAEA0689@SN4P221MB0682.NAMP221.PROD.OUTLOOK.COM/ Cc: James Knight <james.d.knight@live.com> Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Signed-off-by: Ricardo Martincoski <ricardo.martincoski@gmail.com> --- Changes v1 -> v3: - rewrite the code from scratch for patches 2/4 and 3/4, moving it to the base class - add unit tests https://gitlab.com/RicardoMartincoski/buildroot/-/pipelines/990309342 --- utils/checkpackagelib/base.py | 20 ++++++-- utils/checkpackagelib/test_base.py | 82 ++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-)