commit:     357f6104cb08913d840b749659096eeb2d0fa325
Author:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Thu Jan 12 20:40:27 2023 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Thu Jan 12 20:40:27 2023 +0000
URL:        
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=357f6104

EclassUsageCheck: check for setting user variables in ebuilds

Check ebuilds for overriding eclass' user variables.

Resolves: https://github.com/pkgcore/pkgcheck/issues/512
Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>

 src/pkgcheck/checks/eclass.py                      | 37 +++++++++++++++++++++-
 .../EclassUserVariableUsage/expected.json          |  1 +
 .../EclassUserVariableUsage-0.ebuild               | 12 +++++++
 3 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/src/pkgcheck/checks/eclass.py b/src/pkgcheck/checks/eclass.py
index 862dbb91..935ed960 100644
--- a/src/pkgcheck/checks/eclass.py
+++ b/src/pkgcheck/checks/eclass.py
@@ -47,6 +47,18 @@ class DeprecatedEclassVariable(results.LineResult, 
results.Warning):
         return f"uses deprecated variable on line {self.lineno}: 
{self.variable} ({replacement})"
 
 
+class EclassUserVariableUsage(results.LineResult, results.Warning):
+    """Package uses a user variable from an eclass."""
+
+    def __init__(self, eclass, **kwargs):
+        super().__init__(**kwargs)
+        self.eclass = eclass
+
+    @property
+    def desc(self):
+        return f"line {self.lineno}: uses user variable {self.line!r} from 
eclass {self.eclass!r}"
+
+
 class DeprecatedEclassFunction(results.LineResult, results.Warning):
     """Package uses a deprecated function from an eclass."""
 
@@ -125,6 +137,7 @@ class EclassUsageCheck(Check):
             DeprecatedEclassVariable,
             DeprecatedEclassFunction,
             DuplicateEclassInherit,
+            EclassUserVariableUsage,
             MisplacedEclassVar,
             ProvidedEclassInherit,
         }
@@ -156,6 +169,27 @@ class EclassUsageCheck(Check):
                     line = pkg.node_str(node)
                     yield MisplacedEclassVar(var_name, line=line, 
lineno=lineno + 1, pkg=pkg)
 
+    def check_user_variables(self, pkg: bash.ParseTree, inherits: 
list[tuple[list[str], int]]):
+        """Check for usage of @USER_VARIABLE variables."""
+        # determine if any inherited eclasses have @USER_VARIABLE variables
+        user_variables = {
+            var.name: eclass
+            for eclasses, _ in inherits
+            for eclass in eclasses
+            for var in self.eclass_cache[eclass].variables
+            if var.user_variable
+        }
+
+        # scan for usage of @USER_VARIABLE variables
+        if user_variables:
+            for node, _ in bash.var_assign_query.captures(pkg.tree.root_node):
+                var_name = pkg.node_str(node.child_by_field_name("name"))
+                if var_name in user_variables:
+                    lineno, _colno = node.start_point
+                    yield EclassUserVariableUsage(
+                        user_variables[var_name], line=var_name, lineno=lineno 
+ 1, pkg=pkg
+                    )
+
     def check_deprecated_variables(self, pkg, inherits: list[tuple[list[str], 
int]]):
         """Check for usage of @DEPRECATED variables."""
         # determine if any inherited eclasses have @DEPRECATED variables
@@ -220,7 +254,7 @@ class EclassUsageCheck(Check):
 
     def feed(self, pkg):
         if pkg.inherit:
-            inherited = set()
+            inherited: set[str] = set()
             inherits: list[tuple[list[str], int]] = []
             for node, _ in bash.cmd_query.captures(pkg.tree.root_node):
                 name = pkg.node_str(node.child_by_field_name("name"))
@@ -241,6 +275,7 @@ class EclassUsageCheck(Check):
                                 )
 
             yield from self.check_provided_eclasses(pkg, inherits)
+            yield from self.check_user_variables(pkg, inherits)
             # verify @PRE_INHERIT variable placement
             yield from self.check_pre_inherits(pkg, inherits)
             # verify @DEPRECATED variables or functions

diff --git 
a/testdata/data/repos/eclass/EclassUsageCheck/EclassUserVariableUsage/expected.json
 
b/testdata/data/repos/eclass/EclassUsageCheck/EclassUserVariableUsage/expected.json
new file mode 100644
index 00000000..03b11f6a
--- /dev/null
+++ 
b/testdata/data/repos/eclass/EclassUsageCheck/EclassUserVariableUsage/expected.json
@@ -0,0 +1 @@
+{"__class__": "EclassUserVariableUsage", "category": "EclassUsageCheck", 
"package": "EclassUserVariableUsage", "version": "0", "line": "EBZR_STORE_DIR", 
"lineno": 8, "eclass": "unquotedvariable"}

diff --git 
a/testdata/repos/eclass/EclassUsageCheck/EclassUserVariableUsage/EclassUserVariableUsage-0.ebuild
 
b/testdata/repos/eclass/EclassUsageCheck/EclassUserVariableUsage/EclassUserVariableUsage-0.ebuild
new file mode 100644
index 00000000..dae4c7d1
--- /dev/null
+++ 
b/testdata/repos/eclass/EclassUsageCheck/EclassUserVariableUsage/EclassUserVariableUsage-0.ebuild
@@ -0,0 +1,12 @@
+EAPI=8
+inherit unquotedvariable
+DESCRIPTION="Ebuild with user variable override"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck";
+SLOT="0"
+LICENSE="BSD"
+
+EBZR_STORE_DIR="/var/tmp/portage" # FAIL
+
+src_prepare() {
+    echo "${EBZR_STORE_DIR}" # ok
+}

Reply via email to