Skip to content

feat(ruby): isStatic, attr_accessor synthesis, brace-block calls Prism dispatcher fan-out#1404

Open
sadfuzzy wants to merge 1 commit into
colbymchenry:mainfrom
sadfuzzy:fix_ruby_parser
Open

feat(ruby): isStatic, attr_accessor synthesis, brace-block calls Prism dispatcher fan-out#1404
sadfuzzy wants to merge 1 commit into
colbymchenry:mainfrom
sadfuzzy:fix_ruby_parser

Conversation

@sadfuzzy

@sadfuzzy sadfuzzy commented Jul 22, 2026

Copy link
Copy Markdown

CodeGraph's Ruby support had real gaps an agent hits constantly: def self.x/class << self methods indistinguishable from instance methods, attr_accessor/attr_reader/attr_writer invisible (calls to them resolved
to nothing), brace-block bodies (5.times { beep }) blind to bare-call extraction while do...end wasn't, and Prism-dispatcher visitor architectures (ruby-lsp's core pattern: dispatcher.register(self, :on_x)
dispatcher.dispatch(...)) had zero dynamic-dispatch bridging — an agent tracing "hover request → handler" had no static path and had to grep every listener file.

Root cause

  • isStatic hook never implemented for Ruby in either extractor.
  • attr_* calls fell into the importTypes:['call'] funnel (only require/require_relative produce anything).
  • Brace-block grammar node (block_body) missing from the bare-call parent set (only body_statement for do...end was there).
  • No synthesizer existed for Prism's register/dispatch fan-out — an external-gem-mediated callback with no static call site from dispatch to on_x.

Fix

  • Added isStatic to ruby.ts + ruby.rs (singleton_method object field check, class << self parent-chain check).
  • Added synthesizeRubyAttrMembers/synthesize_attr_members — getter/setter method nodes for attr_*, wired for both classes and modules (Concern pattern), explicit methods never overridden.
  • Added block_body to the allowed-parent set in both extractors.
  • New prismDispatchEdges synthesizer in callback-synthesizer.ts: matches register(self, :on_x, ...) symbol lists, resolves listener classes (namespace-suffix aware for Ruby's lexical scoping), follows a two-hop
    Request-wrapper indirection, and handles instance-variable-threaded dispatchers (@dispatcher set in initialize, read in a sibling perform) — while keeping sibling methods with same-named unrelated local
    dispatcher vars from cross-linking.

Validated

  • Full suite: 161 files / 2706 tests green.
  • kernel-ruby-parity.test.ts green — TS/wasm and Rust kernel byte-identical on all new constructs.
  • Indexed real ruby-lsp repo fresh: node count stable (4,987 before/after), 575 synthesized Prism edges, no runaway fan-out (max 101/site vs 400 cap), no cross-contamination.
  • codegraph_explore and scripts/agent-eval/probe-explore.mjs against ruby-lsp confirm the target flow (textDocument/hover → Hover#on_call_node_enter) resolves end-to-end with the synthesized edge correctly
    labeled and sited.
  • Not run: full agent A/B (run-all.sh, Sonnet, with-vs-without codegraph).

…Prism dispatcher fan-out — closes hover/listener flow end-to-end, validated on ruby-lsp
@sadfuzzy
sadfuzzy marked this pull request as draft July 22, 2026 07:15
@sadfuzzy
sadfuzzy marked this pull request as ready for review July 22, 2026 13:20
@sadfuzzy

Copy link
Copy Markdown
Author

#648

@sadfuzzy

Copy link
Copy Markdown
Author

@colbymchenry please, review this fix for ruby language support

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