Skip to content

fix(extraction): fix Ruby call edge extraction for local vars and chained .new#684

Open
ricobl wants to merge 2 commits into
colbymchenry:mainfrom
ricobl:fix/ruby-call-edge-extraction
Open

fix(extraction): fix Ruby call edge extraction for local vars and chained .new#684
ricobl wants to merge 2 commits into
colbymchenry:mainfrom
ricobl:fix/ruby-call-edge-extraction

Conversation

@ricobl
Copy link
Copy Markdown

@ricobl ricobl commented Jun 4, 2026

Summary

  • Ruby call nodes use receiver + method fields rather than a function field, causing two common patterns to produce unresolvable references: obj = SomeClass.new(...); obj.method emitted obj.method, and SomeClass.new(...).method emitted only the method name — neither could be matched by the resolver, so codegraph_callers and codegraph_callees both returned incomplete results.
  • Added handling in tree-sitter.ts for call nodes that use a method field: chained receivers (class/namespace) emit the class name; bare method receivers emit receiver.method; complex receivers (e.g. a chained call) emit just the method name.
  • Added a buildLocalScope hook to LanguageExtractor that lets a language pre-scan a function body and return a var → "ClassName::" prefix map. The engine uses this during call extraction to resolve var.method to ClassName::method. Ruby implements it by scanning var = ClassName.new(...) assignments. The hook is separator-agnostic so other languages can adopt it without engine changes.

Test plan

  • npx vitest run __tests__/extraction.test.ts -t "Ruby calls" — 5 tests covering bare .new, namespaced .new, chained .new(...).method, local var assignment with simple class, and local var assignment with namespaced class
  • npx vitest run — full suite, no new regressions
    • there seems to be a failing MCP PPID watchdog test: shuts down when its parent is SIGKILL'd and stdin stays open

ricobl and others added 2 commits June 5, 2026 00:18
…ined .new

Ruby call nodes use receiver + method fields instead of a function field,
causing the generic extractor to miss two common patterns:

- `var = SomeClass.new(...); var.method` emitted `var.method` which the
  resolver couldn't match to `SomeClass::method`
- `SomeClass.new(...).method` emitted only the method name without its class

Both the caller and callee sides of these edges were broken as a result.

Fixes:
- Extract the `method` field from Ruby call nodes in the generic extractor
  so chained `.new(...).method` correctly emits the method name
- Add a `buildLocalScope` hook to `LanguageExtractor` that lets a language
  pre-scan a function body and return a var → class prefix map; the engine
  uses this to resolve `var.method` to `ClassName::method` at extraction time
- Ruby implements the hook by scanning for `var = ClassName.new(...)` assignments

The hook is separator-agnostic (map values include the separator, e.g. `"Foo::"`),
so other languages can implement it without engine changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ricobl ricobl force-pushed the fix/ruby-call-edge-extraction branch from 4a342b2 to ccd6617 Compare June 4, 2026 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant