utils/checkpackagelib: warn about redefined config

Warn the developer in the case the same config is declared more than
once in the same Config.in file.
But take into account the conditional code that lets the config be
visible and warn only when it is declared more than once in the same
conditions.
For instance, do not warn for:
 if BR2_PACKAGE_BUSYBOX
 config BR2_PACKAGE_BUSYBOX_SHOW_OTHERS
 endif
 if !BR2_PACKAGE_BUSYBOX # kconfig doesn't support else
 config BR2_PACKAGE_BUSYBOX_SHOW_OTHERS
 endif

Signed-off-by: Ricardo Martincoski <ricardo.martincoski@gmail.com>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
This commit is contained in:
Ricardo Martincoski 2022-11-27 10:07:18 -03:00 committed by Peter Korsgaard
parent 316e149611
commit 4bbda72743
2 changed files with 116 additions and 0 deletions

View File

@ -233,3 +233,41 @@ class Indent(_CheckFunction):
return ["{}:{}: should not be indented" return ["{}:{}: should not be indented"
.format(self.filename, lineno), .format(self.filename, lineno),
text] text]
class RedefinedConfig(_CheckFunction):
CONFIG = re.compile(r"^\s*(menu|)config\s+(BR2_\w+)\b")
IF = re.compile(r"^\s*if\s+([^#]*)\b")
ENDIF = re.compile(r"^\s*endif\b")
def before(self):
self.configs = {}
self.conditional = []
def check_line(self, lineno, text):
if _empty_or_comment(text) or _part_of_help_text(text):
return
m = self.IF.search(text)
if m is not None:
condition = m.group(1)
self.conditional.append(condition)
return
m = self.ENDIF.search(text)
if m is not None:
self.conditional.pop()
return
m = self.CONFIG.search(text)
if m is None:
return
config = m.group(2)
key = (config, ' AND '.join(self.conditional))
if key in self.configs.keys():
previous_line = self.configs[key]
return ["{}:{}: config {} redeclared (previous line: {})"
.format(self.filename, lineno, config, previous_line),
text]
self.configs[key] = lineno

View File

@ -385,3 +385,81 @@ Indent = [
def test_Indent(testname, filename, string, expected): def test_Indent(testname, filename, string, expected):
warnings = util.check_file(m.Indent, filename, string) warnings = util.check_file(m.Indent, filename, string)
assert warnings == expected assert warnings == expected
RedefinedConfig = [
('no redefinition',
'any',
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'config BR2_PACKAGE_FOO_BAR\n'
'bool "foo"\n',
[]),
('no conditional',
'any',
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'config BR2_PACKAGE_BAR\n'
'bool "bar"\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n',
[['any:5: config BR2_PACKAGE_FOO redeclared (previous line: 1)',
'config BR2_PACKAGE_FOO\n']]),
('three times',
'any',
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n',
[['any:3: config BR2_PACKAGE_FOO redeclared (previous line: 1)',
'config BR2_PACKAGE_FOO\n'],
['any:5: config BR2_PACKAGE_FOO redeclared (previous line: 1)',
'config BR2_PACKAGE_FOO\n']]),
('same conditional',
'any',
'if BR2_PACKAGE_BAZ\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'config BR2_PACKAGE_BAR\n'
'bool "bar"\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'endif\n',
[['any:6: config BR2_PACKAGE_FOO redeclared (previous line: 2)',
'config BR2_PACKAGE_FOO\n']]),
('equivalent conditional',
'any',
'if BR2_PACKAGE_BAZ\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'endif\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'if BR2_PACKAGE_BAZ\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'endif\n',
[['any:8: config BR2_PACKAGE_FOO redeclared (previous line: 2)',
'config BR2_PACKAGE_FOO\n']]),
('not equivalent conditional',
'any',
'if BR2_PACKAGE_BAZ\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'endif\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'if !BR2_PACKAGE_BAZ\n'
'config BR2_PACKAGE_FOO\n'
'bool "foo"\n'
'endif\n',
[]),
]
@pytest.mark.parametrize('testname,filename,string,expected', RedefinedConfig)
def test_RedefinedConfig(testname, filename, string, expected):
warnings = util.check_file(m.RedefinedConfig, filename, string)
assert warnings == expected