Skip to content

Ruby: receiver.method calls drop the method name, so instance method calls produce no edge #1110

Description

@colbymchenry

Summary

The Ruby extractor drops the method name from a receiver.method call: lg.log() was recorded as a call to lg (the bare receiver), not lg.log. Since lg matches no symbol, the reference resolved to nothing and no method-call edge was ever produced — so a Ruby method invoked through a receiver had no recorded callers and was invisible to impact/blast-radius and codegraph_explore flow traces.

This is the Ruby-specific blocker noted while adding local-variable receiver-type inference (#1108): that fix couldn't help Ruby because the call reference itself was missing.

Root cause

extractCall (src/extraction/tree-sitter.ts) recognizes receiver-bearing calls by the object/name/function fields used by Java/JS/Python/etc. tree-sitter grammars. tree-sitter-ruby's call node instead uses receiver + method fields, so it fell through to the generic fallback, which takes the first named child (the receiver) as the callee. The method name was discarded:

lg.log()   ->  calls "lg"       (should be "lg.log")
Logger.new ->  calls "Logger"   (relied on calls->instantiates promotion)

Fix

Handle Ruby's call/method_call nodes explicitly in extractCall: build receiver.method (so the resolver and local-variable type inference can link it), keep bare foo(...) as just the method name, and emit Foo.new as an instantiates reference to the class. A capitalized (constant) receiver also gets a references edge so a class used only via its class methods still records a dependent.

With this plus #1108, lg = Logger.new; lg.log() resolves lg.log to Logger#log, and the two-file same-name case is same-file-correct (#1079).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions