diff mbox series

[next,v3,2/3] utils/check-package: support inline flags

Message ID 20230903163509.614740-3-ricardo.martincoski@gmail.com
State New
Headers show
Series check-package: support inline flags v3 | expand

Commit Message

Ricardo Martincoski Sept. 3, 2023, 4:35 p.m. UTC
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(-)
diff mbox series

Patch

diff --git a/utils/checkpackagelib/base.py b/utils/checkpackagelib/base.py
index 15a304acf3..d17b9d899f 100644
--- a/utils/checkpackagelib/base.py
+++ b/utils/checkpackagelib/base.py
@@ -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):
diff --git a/utils/checkpackagelib/test_base.py b/utils/checkpackagelib/test_base.py
index ef266d542c..bbe9285466 100644
--- a/utils/checkpackagelib/test_base.py
+++ b/utils/checkpackagelib/test_base.py
@@ -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