Repro
polyglot-piranha==0.4.8, Python 3.12.13, macOS arm64. The same scope_config shape (or trivially simpler) works for Java and Ruby but panics with "Failed to create scope query" at crates/core/src/models/scopes.rs:80 for TypeScript whenever a Method-scoped edge actually fires.
Minimal repro:
import tempfile
from polyglot_piranha import execute_piranha, PiranhaArguments
tmpdir = tempfile.mkdtemp()
with open(f'{tmpdir}/rules.toml', 'w') as f:
f.write('''
[[rules]]
name = "delete_const_true"
query = """
(
(lexical_declaration
(variable_declarator
name: (identifier) @variable_name
value: (true) @init
)
) @decl
)
"""
replace = ""
replace_node = "decl"
is_seed_rule = true
[[rules]]
name = "replace_identifier"
query = """((identifier) @id (#eq? @id "@variable_name"))"""
replace = "@init"
replace_node = "id"
holes = ["variable_name", "init"]
is_seed_rule = false
''')
with open(f'{tmpdir}/edges.toml', 'w') as f:
f.write('''
[[edges]]
scope = "Method"
from = "delete_const_true"
to = ["replace_identifier"]
''')
with open(f'{tmpdir}/scope_config.toml', 'w') as f:
f.write('''
[[scopes]]
name = "Method"
[[scopes.rules]]
enclosing_node = "(function_declaration name: (identifier) @n) @method"
scope = """((function_declaration name: (identifier) @z) @scope (#eq? @z "@n"))"""
''')
source = '''function foo(): void {
const x = true;
if (x) { doIt(); }
}
function bar(): void {
const x = somethingElse();
if (x) { doBar(); }
}
'''
args = PiranhaArguments(
code_snippet=source,
language='typescript',
path_to_configurations=tmpdir,
substitutions={'stale_flag_name': 'x'},
)
execute_piranha(args)
Expected
Cleanup runs: delete_const_true matches foo's const x = true, deletes it. The Method-scoped edge then routes to replace_identifier, which substitutes references to x inside foo (only) with true. bar's const x = somethingElse() and its if (x) are untouched. Final output:
function foo(): void {
if (true) { doIt(); }
}
function bar(): void {
const x = somethingElse();
if (x) { doBar(); }
}
Actual
thread '<unnamed>' panicked at crates/core/src/models/scopes.rs:80:5:
=====================================
ERROR: Failed to create scope query
=====================================
Scope Level: Method
Source Code:
[…file dump showing const x = true already deleted from foo()…]
AST S-expression:
[…AST shows both function_declarations still present after the deletion…]
The scope-walk loop runs to completion without matching any ancestor against the enclosing_node query — even though function_declaration nodes exist in the AST and the change happened inside one. (Verified by removing the predicate, simplifying the query to just (function_declaration) @method, and even using the verbatim Java pack shape; all four variants panic.)
Notes
- The same minimal
scope_config for Java ((method_declaration …) @xdn) and Ruby ((method) @md) works fine on equivalent fixtures.
- Without firing any Method-scoped edge, the scope_config compiles fine — i.e. the TOML itself is valid. The panic happens during runtime scope query construction on the TS source.
- Switching
scope = "Method" to scope = "Parent" in edges.toml removes the panic, but loses scope safety: replace_identifier then pollutes bar()'s same-named binding.
- Tree-sitter version inside the
polyglot_piranha-0.4.8-cp312-cp312-macosx_10_13_universal2.whl is whatever upstream 0.4.8 bundles — I don't know whether tree-sitter-typescript upstream changed a node-type name in a way that breaks the ancestor-walk, but the AST dump clearly contains the function_declaration we expect to match.
If this is a known limitation of TS support, a documented note would help — currently nothing in the README or POLYGLOT_README suggests Method scope is unimplemented for the language.
Happy to provide more diagnostics. PR-able if you can point at where the scope-rule lookup fails to match — I tried adding (program) @method as a fallback rule, same panic, so the issue isn't the query itself but rather the loop never finding a successful match.
Repro
polyglot-piranha==0.4.8, Python 3.12.13, macOS arm64. The same scope_config shape (or trivially simpler) works for Java and Ruby but panics with"Failed to create scope query"atcrates/core/src/models/scopes.rs:80for TypeScript whenever a Method-scoped edge actually fires.Minimal repro:
Expected
Cleanup runs:
delete_const_truematchesfoo'sconst x = true, deletes it. The Method-scoped edge then routes toreplace_identifier, which substitutes references toxinsidefoo(only) withtrue.bar'sconst x = somethingElse()and itsif (x)are untouched. Final output:Actual
The scope-walk loop runs to completion without matching any ancestor against the
enclosing_nodequery — even thoughfunction_declarationnodes exist in the AST and the change happened inside one. (Verified by removing the predicate, simplifying the query to just(function_declaration) @method, and even using the verbatim Java pack shape; all four variants panic.)Notes
scope_configfor Java ((method_declaration …) @xdn) and Ruby ((method) @md) works fine on equivalent fixtures.scope = "Method"toscope = "Parent"inedges.tomlremoves the panic, but loses scope safety:replace_identifierthen pollutesbar()'s same-named binding.polyglot_piranha-0.4.8-cp312-cp312-macosx_10_13_universal2.whlis whatever upstream 0.4.8 bundles — I don't know whethertree-sitter-typescriptupstream changed a node-type name in a way that breaks the ancestor-walk, but the AST dump clearly contains thefunction_declarationwe expect to match.If this is a known limitation of TS support, a documented note would help — currently nothing in the README or POLYGLOT_README suggests Method scope is unimplemented for the language.
Happy to provide more diagnostics. PR-able if you can point at where the scope-rule lookup fails to match — I tried adding
(program) @methodas a fallback rule, same panic, so the issue isn't the query itself but rather the loop never finding a successful match.