commit: 9b6446766f42a829f2a07a55989f4e404531fd3e Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> AuthorDate: Fri Sep 15 10:16:01 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=9b644676
VariableShadowed: new check to detect shadowed variables Resolves: https://github.com/pkgcore/pkgcheck/issues/622 Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org> src/pkgcheck/checks/codingstyle.py | 40 ++++++++++++++++++++++ .../VariableShadowed/expected.json | 3 ++ .../VariableShadowed/fix.patch | 21 ++++++++++++ .../VariableShadowed/VariableShadowed-0.ebuild | 16 +++++++++ 4 files changed, 80 insertions(+) diff --git a/src/pkgcheck/checks/codingstyle.py b/src/pkgcheck/checks/codingstyle.py index 1838be28..58634515 100644 --- a/src/pkgcheck/checks/codingstyle.py +++ b/src/pkgcheck/checks/codingstyle.py @@ -1443,3 +1443,43 @@ class GlobCheck(Check): lineno, _colno = node.start_point yield GlobDistdir(line=pkg.node_str(node), lineno=lineno + 1, pkg=pkg) break + + +class VariableShadowed(results.LinesResult, results.Warning): + """Variable is shadowed or repeatedly declared. This is a possible typo.""" + + def __init__(self, var_name, *args, **kwargs): + super().__init__(*args, **kwargs) + self.var_name = var_name + + @property + def desc(self): + return f"variable {self.var_name!r} may be shadowed, {self.lines_str}" + + +class DeclarationShadowedCheck(Check): + """Scan ebuilds for shadowed variable assignments in global scope.""" + + _source = sources.EbuildParseRepoSource + known_results = frozenset({VariableShadowed}) + + def feed(self, pkg: bash.ParseTree): + assigns = defaultdict(list) + + for node in pkg.tree.root_node.children: + if node.type == "variable_assignment": + used_name = pkg.node_str(node.child_by_field_name("name")) + if pkg.node_str(node).startswith(used_name + "+="): + continue + if value_node := node.child_by_field_name("value"): + if any( + pkg.node_str(node) == used_name + for node, _ in bash.var_query.captures(value_node) + ): + continue + assigns[used_name].append(node) + + for var_name, nodes in 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) diff --git a/testdata/data/repos/standalone/DeclarationShadowedCheck/VariableShadowed/expected.json b/testdata/data/repos/standalone/DeclarationShadowedCheck/VariableShadowed/expected.json new file mode 100644 index 00000000..91e303eb --- /dev/null +++ b/testdata/data/repos/standalone/DeclarationShadowedCheck/VariableShadowed/expected.json @@ -0,0 +1,3 @@ +{"__class__": "VariableShadowed", "category": "DeclarationShadowedCheck", "package": "VariableShadowed", "version": "0", "lines": [11, 13], "var_name": "RDEPEND"} +{"__class__": "VariableShadowed", "category": "DeclarationShadowedCheck", "package": "VariableShadowed", "version": "0", "lines": [9, 15], "var_name": "RESTRICT"} +{"__class__": "VariableShadowed", "category": "DeclarationShadowedCheck", "package": "VariableShadowed", "version": "0", "lines": [5, 16], "var_name": "VAL"} diff --git a/testdata/data/repos/standalone/DeclarationShadowedCheck/VariableShadowed/fix.patch b/testdata/data/repos/standalone/DeclarationShadowedCheck/VariableShadowed/fix.patch new file mode 100644 index 00000000..2c184ed9 --- /dev/null +++ b/testdata/data/repos/standalone/DeclarationShadowedCheck/VariableShadowed/fix.patch @@ -0,0 +1,21 @@ +diff -Naur standalone/DeclarationShadowedCheck/VariableShadowed/VariableShadowed-0.ebuild fixed/DeclarationShadowedCheck/VariableShadowed/VariableShadowed-0.ebuild +--- standalone/DeclarationShadowedCheck/VariableShadowed/VariableShadowed-0.ebuild ++++ fixed/DeclarationShadowedCheck/VariableShadowed/VariableShadowed-0.ebuild +@@ -2,15 +2,12 @@ HOMEPAGE="https://github.com/pkgcore/pkgcheck" + DESCRIPTION="ebuild with shadowed variables" + S=${WORKDIR} + +-VAL= +- + SLOT="0" + LICENSE="BSD" +-RESTRICT="!test? ( test )" ++RESTRICT="test" + + RDEPEND="dev-lang/ruby" + DEPEND="${RDEPEND}" +-RDEPEND="dev-ruby/stub" ++RDEPEND+="dev-ruby/stub" + +-RESTRICT="test" + VAL=5 diff --git a/testdata/repos/standalone/DeclarationShadowedCheck/VariableShadowed/VariableShadowed-0.ebuild b/testdata/repos/standalone/DeclarationShadowedCheck/VariableShadowed/VariableShadowed-0.ebuild new file mode 100644 index 00000000..11dd30ce --- /dev/null +++ b/testdata/repos/standalone/DeclarationShadowedCheck/VariableShadowed/VariableShadowed-0.ebuild @@ -0,0 +1,16 @@ +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +DESCRIPTION="ebuild with shadowed variables" +S=${WORKDIR} + +VAL= + +SLOT="0" +LICENSE="BSD" +RESTRICT="!test? ( test )" + +RDEPEND="dev-lang/ruby" +DEPEND="${RDEPEND}" +RDEPEND="dev-ruby/stub" + +RESTRICT="test" +VAL=5
