diff options
author | Arthur Zamarin <arthurzam@gentoo.org> | 2024-09-01 23:46:08 +0300 |
---|---|---|
committer | Arthur Zamarin <arthurzam@gentoo.org> | 2024-09-02 00:14:10 +0300 |
commit | e645712580e245615099ca4138ebc8d1647b6a1f (patch) | |
tree | 06c713e8ab6b53e044e17440b951cd0854416f45 | |
parent | EmptyGlobalAssignment: ignore empty KEYWORDS (diff) | |
download | pkgcheck-e645712580e245615099ca4138ebc8d1647b6a1f.tar.gz pkgcheck-e645712580e245615099ca4138ebc8d1647b6a1f.tar.bz2 pkgcheck-e645712580e245615099ca4138ebc8d1647b6a1f.zip |
fix with tree-sitter 0.23
Once again they broke the API, this time around the .captures() call.
They changed it by a lot, returning a dict of capture names to captures.
Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
-rw-r--r-- | pyproject.toml | 4 | ||||
-rw-r--r-- | src/pkgcheck/bash/__init__.py | 8 | ||||
-rw-r--r-- | src/pkgcheck/checks/codingstyle.py | 57 | ||||
-rw-r--r-- | src/pkgcheck/checks/eclass.py | 14 | ||||
-rw-r--r-- | src/pkgcheck/checks/python.py | 14 | ||||
-rw-r--r-- | src/pkgcheck/checks/reserved.py | 8 | ||||
-rw-r--r-- | src/pkgcheck/checks/rust.py | 4 |
7 files changed, 53 insertions, 56 deletions
diff --git a/pyproject.toml b/pyproject.toml index 0b7e20fd..bf20ce94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ requires = [ "lazy-object-proxy", "lxml", "pathspec", - "tree-sitter>=0.21.0", + "tree-sitter>=0.23.0", "tree-sitter-bash>=0.21.0", "snakeoil~=0.10.8", "pkgcore~=0.12.25", @@ -46,7 +46,7 @@ dependencies = [ "lazy-object-proxy", "lxml", "pathspec", - "tree-sitter>=0.22.2", + "tree-sitter>=0.23.2", "tree-sitter-bash>=0.21.0", "snakeoil~=0.10.8", "pkgcore~=0.12.25", diff --git a/src/pkgcheck/bash/__init__.py b/src/pkgcheck/bash/__init__.py index 0c8a7a13..1b47881c 100644 --- a/src/pkgcheck/bash/__init__.py +++ b/src/pkgcheck/bash/__init__.py @@ -1,5 +1,7 @@ """bash parsing support""" +from itertools import chain + import tree_sitter_bash from tree_sitter import Language, Parser, Query @@ -31,13 +33,11 @@ class ParseTree: for x in self.tree.root_node.children: # skip nodes in function scope if x.type != "function_definition": - for node, _ in query.captures(x): - yield node + yield from chain.from_iterable(query.captures(x).values()) def func_query(self, query: Query): """Run a given parse tree query returning only those nodes in function scope.""" for x in self.tree.root_node.children: # only return nodes in function scope if x.type == "function_definition": - for node, _ in query.captures(x): - yield node + yield from chain.from_iterable(query.captures(x).values()) diff --git a/src/pkgcheck/checks/codingstyle.py b/src/pkgcheck/checks/codingstyle.py index 42bd0004..20628481 100644 --- a/src/pkgcheck/checks/codingstyle.py +++ b/src/pkgcheck/checks/codingstyle.py @@ -89,8 +89,8 @@ class BadCommandsCheck(Check): ) def feed(self, pkg): - for func_node, _ in bash.func_query.captures(pkg.tree.root_node): - for node, _ in bash.cmd_query.captures(func_node): + for func_node in bash.func_query.captures(pkg.tree.root_node).get("func", ()): + for node in bash.cmd_query.captures(func_node).get("call", ()): call = pkg.node_str(node) name = pkg.node_str(node.child_by_field_name("name")) lineno, _colno = node.start_point @@ -134,8 +134,8 @@ class EendMissingArgCheck(Check): known_results = frozenset([EendMissingArg]) def feed(self, pkg): - for func_node, _ in bash.func_query.captures(pkg.tree.root_node): - for node, _ in bash.cmd_query.captures(func_node): + for func_node in bash.func_query.captures(pkg.tree.root_node).get("func", ()): + for node in bash.cmd_query.captures(func_node).get("call", ()): line = pkg.node_str(node) if line == "eend": lineno, _ = node.start_point @@ -639,7 +639,7 @@ class MetadataVarCheck(Check): @verify_vars("HOMEPAGE", "KEYWORDS") def _raw_text(self, var, node, value, pkg): matches = [] - for var_node, _ in bash.var_query.captures(node): + for var_node in bash.var_query.captures(node).get("var", ()): matches.append(pkg.node_str(var_node.parent)) if matches: yield ReferenceInMetadataVar(var, stable_unique(matches), pkg=pkg) @@ -647,7 +647,7 @@ class MetadataVarCheck(Check): @verify_vars("LICENSE") def _raw_text_license(self, var, node, value, pkg): matches = [] - for var_node, _ in bash.var_query.captures(node): + for var_node in bash.var_query.captures(node).get("var", ()): var_str = pkg.node_str(var_node.parent).strip() if var_str in ["$LICENSE", "${LICENSE}"]: continue # LICENSE in LICENSE is ok @@ -718,7 +718,7 @@ class MetadataVarCheck(Check): line=pkg.node_str(node), lineno=lineno + 1, pkg=pkg ) elif pkg.node_str(value_node.prev_sibling) == "=": - for var_node, _ in bash.var_query.captures(value_node): + for var_node in bash.var_query.captures(value_node).get("var", ()): if ( pkg.node_str(var_node) == name and self.canonicalize_assign(pkg.node_str(var_node.parent)) == value_str @@ -878,12 +878,12 @@ class InheritsCheck(Check): # collect globally defined functions in ebuild defined_funcs = { pkg.node_str(func_node.child_by_field_name("name")) - for func_node, _ in bash.func_query.captures(pkg.tree.root_node) + for func_node in bash.func_query.captures(pkg.tree.root_node).get("func", ()) } # register variables assigned in ebuilds assigned_vars = dict() - for node, _ in bash.var_assign_query.captures(pkg.tree.root_node): + for node in bash.var_assign_query.captures(pkg.tree.root_node).get("assign", ()): name = pkg.node_str(node.child_by_field_name("name")) if eclass := self.get_eclass(name, pkg): assigned_vars[name] = eclass @@ -892,7 +892,7 @@ class InheritsCheck(Check): weak_used_eclasses = set() # match captured commands with eclasses used = defaultdict(list) - for node, _ in bash.cmd_query.captures(pkg.tree.root_node): + for node in bash.cmd_query.captures(pkg.tree.root_node).get("call", ()): call = pkg.node_str(node) name = pkg.node_str(node.child_by_field_name("name")) if name == "inherit": @@ -914,7 +914,7 @@ class InheritsCheck(Check): weak_used_eclasses.add(eclass) # match captured variables with eclasses - for node, _ in bash.var_query.captures(pkg.tree.root_node): + for node in bash.var_query.captures(pkg.tree.root_node).get("var", ()): name = pkg.node_str(node) if node.parent.type == "unset_command": continue @@ -1114,12 +1114,12 @@ class VariableScopeCheck(Check): scoped_vars.setdefault(eapi, {}).setdefault(phase, set()).add(variable) scoped_vars = ImmutableDict(scoped_vars) - def feed(self, pkg): - for func_node, _ in bash.func_query.captures(pkg.tree.root_node): + def feed(self, pkg: bash.ParseTree): + for func_node in bash.func_query.captures(pkg.tree.root_node).get("func", ()): func_name = pkg.node_str(func_node.child_by_field_name("name")) if variables := self.scoped_vars[pkg.eapi].get(func_name): usage = defaultdict(set) - for var_node, _ in bash.var_query.captures(func_node): + for var_node in bash.var_query.captures(func_node).get("var", ()): var_name = pkg.node_str(var_node) if var_name in variables: lineno, _colno = var_node.start_point @@ -1130,7 +1130,7 @@ class VariableScopeCheck(Check): global_usage = defaultdict(set) for global_node in pkg.tree.root_node.children: if global_node.type not in ("function_definition", "ERROR"): - for var_node, _ in bash.var_query.captures(global_node): + for var_node in bash.var_query.captures(global_node).get("var", ()): var_name = pkg.node_str(var_node) if var_name in self.not_global_scope: lineno, _colno = var_node.start_point @@ -1271,14 +1271,14 @@ class _UnquotedVariablesCheck(Check): # Default: The variable should be quoted return True - def _feed(self, item): + def _feed(self, item: bash.ParseTree): if item.tree.root_node.has_error: # Do not run this check if the parse tree contains errors, as it # might result in false positives. This check appears to be quite # expensive though... return hits = defaultdict(set) - for var_node, _ in bash.var_query.captures(item.tree.root_node): + for var_node in bash.var_query.captures(item.tree.root_node).get("var", ()): var_name = item.node_str(var_node) if var_name in self.var_names: if self._var_needs_quotes(item, var_node): @@ -1390,7 +1390,7 @@ class DoCompressedFilesCheck(Check): ) def feed(self, pkg): - for node, _ in bash.cmd_query.captures(pkg.tree.root_node): + for node in bash.cmd_query.captures(pkg.tree.root_node).get("call", ()): call_name = pkg.node_str(node.child_by_field_name("name")) if call_name not in self.functions: continue @@ -1446,7 +1446,7 @@ class NonPosixCheck(Check): prev_arg = arg def feed(self, pkg): - for call_node, _ in bash.cmd_query.captures(pkg.tree.root_node): + for call_node in bash.cmd_query.captures(pkg.tree.root_node).get("call", ()): call_name = pkg.node_str(call_node.child_by_field_name("name")) if call_name in ("head", "tail"): yield from self.check_head_tail(pkg, call_node, call_name) @@ -1476,14 +1476,13 @@ class GlobCheck(Check): self.glob_query = bash.query('(concatenation (word) @word (.match? @word "[*?]")) @usage') def feed(self, pkg): - for node, capture in self.glob_query.captures(pkg.tree.root_node): - if capture == "usage": - for var_node, _ in bash.var_query.captures(node): - var_name = pkg.node_str(var_node) - if var_name == "DISTDIR": - lineno, _colno = node.start_point - yield GlobDistdir(line=pkg.node_str(node), lineno=lineno + 1, pkg=pkg) - break + for node in self.glob_query.captures(pkg.tree.root_node).get("usage", ()): + for var_node in bash.var_query.captures(node).get("var", ()): + var_name = pkg.node_str(var_node) + if var_name == "DISTDIR": + lineno, _colno = node.start_point + yield GlobDistdir(line=pkg.node_str(node), lineno=lineno + 1, pkg=pkg) + break class VariableShadowed(results.LinesResult, results.Warning): @@ -1528,7 +1527,7 @@ class DeclarationShadowedCheck(Check): 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) + for node in bash.var_query.captures(value_node).get("var", ()) ): continue var_assigns[used_name].append(node) @@ -1570,7 +1569,7 @@ class SandboxCallCheck(Check): functions = frozenset({"addread", "addwrite", "adddeny", "addpredict"}) def feed(self, pkg: bash.ParseTree): - for node, _ in bash.cmd_query.captures(pkg.tree.root_node): + for node in bash.cmd_query.captures(pkg.tree.root_node).get("call", ()): name = pkg.node_str(node.child_by_field_name("name")) if name in self.functions: args = node.children_by_field_name("argument") diff --git a/src/pkgcheck/checks/eclass.py b/src/pkgcheck/checks/eclass.py index 394ef192..52bcea6e 100644 --- a/src/pkgcheck/checks/eclass.py +++ b/src/pkgcheck/checks/eclass.py @@ -164,7 +164,7 @@ class EclassUsageCheck(Check): # scan for any misplaced @PRE_INHERIT variables if pre_inherits: - for node, _ in bash.var_assign_query.captures(pkg.tree.root_node): + for node in bash.var_assign_query.captures(pkg.tree.root_node).get("assign", ()): var_name = pkg.node_str(node.child_by_field_name("name")) lineno, _colno = node.start_point if var_name in pre_inherits and lineno > pre_inherits[var_name]: @@ -184,7 +184,7 @@ class EclassUsageCheck(Check): # scan for usage of @USER_VARIABLE variables if user_variables: - for node, _ in bash.var_assign_query.captures(pkg.tree.root_node): + for node in bash.var_assign_query.captures(pkg.tree.root_node).get("assign", ()): var_name = pkg.node_str(node.child_by_field_name("name")) if var_name in user_variables: lineno, _colno = node.start_point @@ -205,7 +205,7 @@ class EclassUsageCheck(Check): # scan for usage of @DEPRECATED variables if deprecated: - for node, _ in bash.var_query.captures(pkg.tree.root_node): + for node in bash.var_query.captures(pkg.tree.root_node).get("var", ()): var_name = pkg.node_str(node) if var_name in deprecated: lineno, _colno = node.start_point @@ -230,7 +230,7 @@ class EclassUsageCheck(Check): # scan for usage of @DEPRECATED functions if deprecated: - for node, _ in bash.cmd_query.captures(pkg.tree.root_node): + for node in bash.cmd_query.captures(pkg.tree.root_node).get("call", ()): func_name = pkg.node_str(node.child_by_field_name("name")) if func_name in deprecated: lineno, _colno = node.start_point @@ -258,7 +258,7 @@ class EclassUsageCheck(Check): if pkg.inherit: inherited: set[str] = set() inherits: list[tuple[list[str], int]] = [] - for node, _ in bash.cmd_query.captures(pkg.tree.root_node): + for node in bash.cmd_query.captures(pkg.tree.root_node).get("call", ()): name = pkg.node_str(node.child_by_field_name("name")) if name == "inherit": call = pkg.node_str(node) @@ -342,14 +342,14 @@ class EclassParseCheck(Check): def feed(self, eclass): func_prefix = f"{eclass.name}_" - for func_node, _ in bash.func_query.captures(eclass.tree.root_node): + for func_node in bash.func_query.captures(eclass.tree.root_node).get("func", ()): func_name = eclass.node_str(func_node.child_by_field_name("name")) if not func_name.startswith(func_prefix): continue phase = func_name[len(func_prefix) :] if variables := self.eclass_phase_vars(eclass, phase): usage = defaultdict(set) - for var_node, _ in bash.var_query.captures(func_node): + for var_node in bash.var_query.captures(func_node).get("var", ()): var_name = eclass.node_str(var_node) if var_name in variables: lineno, _colno = var_node.start_point diff --git a/src/pkgcheck/checks/python.py b/src/pkgcheck/checks/python.py index 13ec6311..2c46885a 100644 --- a/src/pkgcheck/checks/python.py +++ b/src/pkgcheck/checks/python.py @@ -1,7 +1,7 @@ -import itertools import re import typing from collections import defaultdict +from itertools import takewhile from operator import attrgetter from pkgcore import fetch @@ -358,7 +358,7 @@ class PythonCheck(Check): uses_setuptools_scm = False pep517_value = None - for var_node, _ in bash.var_assign_query.captures(pkg.tree.root_node): + for var_node in bash.var_assign_query.captures(pkg.tree.root_node).get("assign", ()): var_name = pkg.node_str(var_node.child_by_field_name("name")) if var_name == "DISTUTILS_OPTIONAL": @@ -407,7 +407,7 @@ class PythonCheck(Check): for var_node in pkg.global_query(bash.var_assign_query): name = pkg.node_str(var_node.child_by_field_name("name")) if name in {"DEPEND", "BDEPEND"}: - for call_node, _ in bash.cmd_query.captures(var_node): + for call_node in bash.cmd_query.captures(var_node).get("call", ()): call_name = pkg.node_str(call_node.child_by_field_name("name")) if call_name == any_dep_func and len(call_node.children) > 1: check_deps[name].update( @@ -457,7 +457,7 @@ class PythonCheck(Check): def check_python_check_deps(self, pkg, func_node, python_check_deps, any_dep_func): has_version_checked_deps = defaultdict(set) has_version_lines = set() - for node, _ in bash.cmd_query.captures(func_node): + for node in bash.cmd_query.captures(func_node).get("call", ()): call_name = pkg.node_str(node.child_by_field_name("name")) if call_name == "has_version": lineno, _ = node.start_point @@ -548,7 +548,7 @@ class PythonCheck(Check): any_dep_func = self.eclass_any_dep_func[eclass] python_check_deps = self.build_python_gen_any_dep_calls(pkg, any_dep_func) - for func_node, _ in bash.func_query.captures(pkg.tree.root_node): + for func_node in bash.func_query.captures(pkg.tree.root_node).get("func", ()): func_name = pkg.node_str(func_node.child_by_field_name("name")) if func_name == "python_check_deps": yield from self.check_python_check_deps( @@ -664,9 +664,7 @@ class PythonCompatCheck(Check): return # determine python impls to target - targets = set( - itertools.takewhile(lambda x: x != latest_target, reversed(available_targets)) - ) + targets = set(takewhile(lambda x: x != latest_target, reversed(available_targets))) if targets: try: diff --git a/src/pkgcheck/checks/reserved.py b/src/pkgcheck/checks/reserved.py index f99a9050..78f4e357 100644 --- a/src/pkgcheck/checks/reserved.py +++ b/src/pkgcheck/checks/reserved.py @@ -42,14 +42,14 @@ class _ReservedNameCheck(Check): "function", { item.node_str(node.child_by_field_name("name")): node.start_point - for node, _ in bash.func_query.captures(item.tree.root_node) + for node in bash.func_query.captures(item.tree.root_node).get("func", ()) }, ) used_variables = { item.node_str(node.child_by_field_name("name")): node.start_point - for node, _ in bash.var_assign_query.captures(item.tree.root_node) + for node in bash.var_assign_query.captures(item.tree.root_node).get("assign", ()) } - for node, _ in bash.var_query.captures(item.tree.root_node): + for node in bash.var_query.captures(item.tree.root_node).get("var", ()): if (name := item.node_str(node)) not in self.variables_usage_whitelist: used_variables.setdefault(name, node.start_point) yield from self._check("variable", used_variables) @@ -144,7 +144,7 @@ class EbuildReservedCheck(_ReservedNameCheck): for used_name, *args, lineno in self._feed(pkg): yield EbuildReservedName(*args, lineno=lineno, line=used_name, pkg=pkg) - for node, _ in bash.func_query.captures(pkg.tree.root_node): + for node in bash.func_query.captures(pkg.tree.root_node).get("func", ()): used_name = pkg.node_str(node.child_by_field_name("name")) if used_name in self.phases_hooks[str(pkg.eapi)]: lineno, _ = node.start_point diff --git a/src/pkgcheck/checks/rust.py b/src/pkgcheck/checks/rust.py index 397738b9..7a5cbdad 100644 --- a/src/pkgcheck/checks/rust.py +++ b/src/pkgcheck/checks/rust.py @@ -60,7 +60,7 @@ class RustCheck(Check): return def _verify_cargo_crate_uris(self, pkg: bash.ParseTree): - for node, _ in bash.cmd_query.captures(pkg.tree.root_node): + for node in bash.cmd_query.captures(pkg.tree.root_node).get("call", ()): call_name = pkg.node_str(node.child_by_field_name("name")) if call_name == "cargo_crate_uris": row, _ = node.start_point @@ -69,7 +69,7 @@ class RustCheck(Check): node.child_count == 2 and any( pkg.node_str(var_node) == "CRATES" - for var_node, _ in bash.var_query.captures(node.children[1]) + for var_node in bash.var_query.captures(node.children[1]).get("var", ()) ) ): yield SuboptimalCratesURICall( |