fix(ruby): emit mixes_in for include/prepend inside class << self#1816
Open
Synvoya wants to merge 1 commit into
Open
fix(ruby): emit mixes_in for include/prepend inside class << self#1816Synvoya wants to merge 1 commit into
class << self#1816Synvoya wants to merge 1 commit into
Conversation
An `include`/`prepend` inside a `class << self` block injects the module's instance methods as the enclosing class's own singleton (class) methods — the very mixin relationship `extend <Mod>` expresses in the class body, which the extractor already captures (Graphify-Labs#1668). The mixin scan only walked the class/module body's direct children, so the `class << self` form was silently dropped and emitted no `mixes_in` edge. Scan `class << self` blocks as well, reusing the existing constant-argument filter and the single-owner resolver guard. Only `self` counts: `class << other` opens a different object's singleton, not the enclosing class's, so an include there stays unlinked.
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.
Bug
An
include/prependinside aclass << selfblock injects the module's instance methods as the enclosing class's own singleton (class) methods — the exact mixin relationship thatextend <Mod>expresses in the class body, which the extractor already captures as amixes_inedge (#1668).The Ruby mixin scan in
_extract_genericonly walked the class/module body's direct children, so aninclude/prependnested one level down inside aclass << selfsingleton-class block was silently skipped and produced no edge. This drops the heritage link for the canonical "add class methods via a module" idiom.Minimal repro
mixes_inedge —_mixes_in(graph) == set()("Broadcaster", "Announceable")inmixes_in, identical to the semantically-equivalentextend Announceablesingleton_classwas previously unreferenced anywhere in the codebase, so this form had no handling at all.Fix
Scan
class << selfblocks in addition to the class/module body, reusing the existing constant-argument filter and the single-owner resolver guard — no new resolution path. The inner statement loop is unchanged; only the set of statements it iterates is widened.Guard: only
selfcounts.class << otheropens a different object's singleton class, not the enclosing class's, so anincludethere stays unlinked (covered by a negative test).Tests
Added to
tests/test_ruby_resolution.py(alongside the #1668 mixin specs):test_include_in_singleton_class_emits_mixes_in— the fix; fails before, passes after.test_include_in_other_object_singleton_class_emits_no_mixin— locks theclass << otherguard (no over-emission).tests/test_ruby_resolution.py+tests/test_languages.py: 338 passed, 13 skipped (skips are the optionaltree-sitter-dmgrammar). No cross-language impact — the changed block is inside theconfig.ts_module == "tree_sitter_ruby"guard.