commit: 8abeb154ed6047cd730ceb242a2fa08a486f739f Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> AuthorDate: Tue Sep 19 18:09:54 2023 +0000 Commit: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> CommitDate: Sat Sep 23 15:36:03 2023 +0000 URL: https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=8abeb154
DuplicateFunctionDefinition: new check for duplicate global functions Closes: https://bugs.gentoo.org/365691 Resolves: https://github.com/pkgcore/pkgcheck/issues/624 Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org> src/pkgcheck/checks/codingstyle.py | 28 ++++++++++++++++++---- .../DuplicateFunctionDefinition/expected.json | 2 ++ .../DuplicateFunctionDefinition-0.ebuild | 21 ++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/pkgcheck/checks/codingstyle.py b/src/pkgcheck/checks/codingstyle.py index 58634515..d0b5d861 100644 --- a/src/pkgcheck/checks/codingstyle.py +++ b/src/pkgcheck/checks/codingstyle.py @@ -1457,14 +1457,27 @@ class VariableShadowed(results.LinesResult, results.Warning): return f"variable {self.var_name!r} may be shadowed, {self.lines_str}" +class DuplicateFunctionDefinition(results.LinesResult, results.Error): + """Function is defined multiple times. This is a definetly typo.""" + + def __init__(self, func_name, *args, **kwargs): + super().__init__(*args, **kwargs) + self.func_name = func_name + + @property + def desc(self): + return f"multiple definitions of function {self.func_name!r} were found, {self.lines_str}" + + class DeclarationShadowedCheck(Check): """Scan ebuilds for shadowed variable assignments in global scope.""" _source = sources.EbuildParseRepoSource - known_results = frozenset({VariableShadowed}) + known_results = frozenset({VariableShadowed, DuplicateFunctionDefinition}) def feed(self, pkg: bash.ParseTree): - assigns = defaultdict(list) + var_assigns = defaultdict(list) + func_declares = defaultdict(list) for node in pkg.tree.root_node.children: if node.type == "variable_assignment": @@ -1477,9 +1490,16 @@ class DeclarationShadowedCheck(Check): for node, _ in bash.var_query.captures(value_node) ): continue - assigns[used_name].append(node) + var_assigns[used_name].append(node) + elif node.type == "function_definition": + used_name = pkg.node_str(node.child_by_field_name("name")) + func_declares[used_name].append(node) - for var_name, nodes in assigns.items(): + for var_name, nodes in var_assigns.items(): if len(nodes) > 1: lines = sorted(node.start_point[0] + 1 for node in nodes) yield VariableShadowed(var_name, lines=lines, pkg=pkg) + for func_name, nodes in func_declares.items(): + if len(nodes) > 1: + lines = sorted(node.start_point[0] + 1 for node in nodes) + yield DuplicateFunctionDefinition(func_name, lines=lines, pkg=pkg) diff --git a/testdata/data/repos/standalone/DeclarationShadowedCheck/DuplicateFunctionDefinition/expected.json b/testdata/data/repos/standalone/DeclarationShadowedCheck/DuplicateFunctionDefinition/expected.json new file mode 100644 index 00000000..c560713b --- /dev/null +++ b/testdata/data/repos/standalone/DeclarationShadowedCheck/DuplicateFunctionDefinition/expected.json @@ -0,0 +1,2 @@ +{"__class__": "DuplicateFunctionDefinition", "category": "DeclarationShadowedCheck", "package": "DuplicateFunctionDefinition", "version": "0", "lines": [11, 15], "func_name": "any_function"} +{"__class__": "DuplicateFunctionDefinition", "category": "DeclarationShadowedCheck", "package": "DuplicateFunctionDefinition", "version": "0", "lines": [7, 19], "func_name": "pkg_preinst"} diff --git a/testdata/repos/standalone/DeclarationShadowedCheck/DuplicateFunctionDefinition/DuplicateFunctionDefinition-0.ebuild b/testdata/repos/standalone/DeclarationShadowedCheck/DuplicateFunctionDefinition/DuplicateFunctionDefinition-0.ebuild new file mode 100644 index 00000000..ad8ec8b7 --- /dev/null +++ b/testdata/repos/standalone/DeclarationShadowedCheck/DuplicateFunctionDefinition/DuplicateFunctionDefinition-0.ebuild @@ -0,0 +1,21 @@ + +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +DESCRIPTION="ebuild with shadowed variables" +SLOT="0" +LICENSE="BSD" + +pkg_preinst() { + : +} + +any_function() { + : +} + +any_function() { + : +} + +pkg_preinst() { + any_function +}
