fix(parser): close symbol-extraction gaps across 8 languages#520
Merged
Conversation
Adds previously-missing symbol captures so the graph stops dropping real
nodes/edges that `ecp impact`/`find` rely on. Each language ships a
dedicated test bin (happy path + regression):
- Java: record_declaration -> Class + components -> Property
- PHP: in-class `use Trait;` -> class->trait heritage edge
- C#: operator/conversion-operator/event/event-field/indexer/destructor
-> Method nodes so body-calls attach via enclosing_containers
- Rust: `extern "C"` foreign_mod function_signature_item captured
- Swift: protocol_property_declaration captured
- Kotlin: type_alias -> Typedef; companion-object methods -> Method
- Python: `X: TypeAlias = ...` (PEP 613) -> Typedef, not Variable
- C++: constexpr/const globals -> Const, not Variable
Ruby (`class << self`) was investigated and is a verified no-op: the
schema has no class-vs-instance method distinction (`RawNode` carries no
is_static flag), so `def self.foo` and `class << self; def foo` already
produce byte-identical output (Method, owner=EnclosingClass). Promoting
the distinction would be a schema-append with no impact/find benefit, so
it is intentionally left unchanged.
All touched-language regression suites pass (python/csharp/kotlin full
bins, 0 failures); clippy clean on ecp-analyzer.
The FU-2026-05-29-001 entry flagged Ruby `class << self` methods as producing instance Methods (missing class-level marking). Investigation shows `function_meta::ruby` already sets FLAG_STATIC for both forms — `singleton_method` (`def self.foo`) directly, and methods nested under `singleton_class` (`class << self`) via a parent().parent() walk. The bug was already fixed; what was missing is a regression test. This pins the behaviour: both class-level forms are is_static, instance methods are not. The parent-chain walk in ruby.rs:53-58 is the fragile part — this test fails loudly if a grammar-handling change breaks it.
simplify pass findings: - destructor.name / event_field.name were resolved via capture_index_for_name inside parse_file (once per file, 50k string scans over a 25k-file index). Moved into CSharpCaptureIndices, resolved once at construction like every other index the struct documents. - canonical_name was built and cloned outside or_insert_with, allocating a String on every match including dedup hits that never insert. Moved the name construction into the closure so it allocates only on actual node insertion.
Contributor
ecp impact cache (0 symbols) — internal, used by
|
coseto6125
added a commit
that referenced
this pull request
May 31, 2026
The v0.6.2 section was generated by the release-PR (#524) bump before #523/#525/#526 merged, so it listed only #520/#521/#522. Backfill the three before tagging v0.6.2 so the release notes match what the tag actually ships: - #525 field-reassign collision fix (Bug Fixes) - #523 cypher prop-filter refactor (Refactor) - #526 `--file` flag rename (Chore)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the bulk of FU-2026-05-29-001 (symbol-parse completeness audit).
Each language adds the previously-missing capture so the graph stops dropping real nodes/edges that
ecp impact/finddepend on. One dedicated test bin per language (happy path + regression):record_declaration→ Class + components → Propertyuse Trait;→ class→trait heritage edgeenclosing_containers)extern "C"foreign_modfunction_signature_itemcapturedprotocol_property_declarationcapturedtype_alias→ Typedef; companion-object methods → MethodX: TypeAlias = …(PEP 613) → Typedef, not Variableconstexpr/constglobals → Const, not VariableRuby: already fixed → regression test only
The FU listed
class << selfmethods as a kind-bug ("instance Method, should be class-level"). Investigation (direct probe of theis_staticflag) shows the bug was already fixed:function_meta::rubysetsFLAG_STATICfor both class-level forms —def self.foo(singleton_method) directly, and methods nested undersingleton_class(class << self) via aparent().parent() == singleton_classwalk. The FU entry was stale.What was missing is a regression test, so this PR adds
ruby_singleton_static.rspinning: both class-level forms areis_static, instance methods are not. The parent-chain walk inruby.rs:53-58is the fragile part the test guards. (FU entry to be marked resolved in the separatechore/followups-*PR.)Verification
clippy -p ecp-analyzer --testsclean.Per CLAUDE.md, the per-lang
queries.scmadditions map to existing NodeKinds and do not touch shared primitives, so the 14-lang-parity rule does not gate them; coverage is per-affected-language instead.