fix(ingestion): qualify Ruby same-tail nested mixin modules + route IMPLEMENTS by scope (#1991)#1999
Closed
magyargergo wants to merge 2 commits into
Closed
Conversation
…MPLEMENTS by scope (abhigyanpatwari#1991) A Ruby `module` maps to the Trait label but is not a typeDeclaration, so the structure phase never qualified its node id: two same-tail nested mixin modules (App::Loggable / Web::Loggable) collapsed onto one Trait:f.rb:Loggable node and the bare-name `include Loggable` cross-wired IMPLEMENTS (first-wins tail). Structure phase: expose buildQualifiedName as a `qualifyScopeName` ClassExtractor hook and thread it for Trait nodes in parsing-processor + parse-worker (lockstep), so a module node keys by its qualified scope path (App.Loggable). Not Option A — `Trait` is not in CLASS_LIKE_LABELS and the qualified-id selection gates it out; qualifyScopeName bypasses the typeDeclaration gate that makes extractQualifiedName bail on modules. getQualifiedOwnerName also falls back to qualifyScopeName so methods inside a nested module own through the same qualified Trait id (no dangling HAS_METHOD). Resolution: emitRubyMixinEdges resolves a bare mixin reference lexically by the including class's enclosing scope (`App::S` + `Loggable` -> `App::Loggable`), and the simple-tail fallback is now delete-on-collision (refuse to guess on a same-tail tie) instead of first-wins. New single-file fixture + tests: two distinct Trait nodes, S IMPLEMENTS App.Loggable only, T IMPLEMENTS Web.Loggable only, no dangling HAS_METHOD; both resolver legs + worker path. Module->Trait preserved; Trait NOT added to CLASS_LIKE_LABELS. ruby-captures-golden regenerated additively. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@magyargergo is attempting to deploy a commit to the NexusCore Team on Vercel. A member of the Team first needs to authorize it. |
Contributor
CI Report❌ Some checks failed Pipeline Status
Test Results
✅ All 11044 tests passed 16 test(s) skipped — expand for details
Code CoverageTests
📋 View full run · Generated by CI |
Collaborator
Author
|
Superseded by same-repo stacked PR #2006. |
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.
Summary
Follow-up to #1981 / #1982. A Ruby
modulemaps to theTraitlabel but is not a typeDeclaration, so the structure phase never qualified its node id. Two same-tail nested mixin modules (App::Loggable+Web::Loggable) collapsed onto oneTrait:f.rb:Loggablenode, and the bare-nameinclude Loggablereference cross-wiredIMPLEMENTSvia the first-wins tail fallback (dangle-free but wrong).Fix
Structure phase (node identity). Exposed
buildQualifiedNameas aqualifyScopeNameClassExtractorhook and threaded it forTraitnodes inparsing-processor.ts+parse-worker.ts(lockstep), so a module node keys by its qualified scope path (App.Loggable). This is not Option A —Traitis not inCLASS_LIKE_LABELSand the qualified-id selection gates it out, andextractQualifiedNamebails on non-typeDeclarations;qualifyScopeNamebypasses that gate.getQualifiedOwnerNamealso falls back toqualifyScopeName, so methods inside a nested module own through the same qualified Trait id (no danglingHAS_METHOD).Resolution (cross-wire).
emitRubyMixinEdgesnow resolves a bare mixin reference lexically by the including class's enclosing scope (App::S+Loggable→App::Loggable), and the simple-tail fallback is delete-on-collision (refuse to guess on a same-tail tie) instead of first-wins.Module → Traitis preserved;Traitis not added toCLASS_LIKE_LABELS. No language-specific names in shared code —qualifyScopeNameis a neutral hook gated onqualifiedNodeId+ theTraitlabel.Tests
New single-file
ruby-nested-mixin-tail-collisionfixture + tests:Traitnodes (App.Loggable/Web.Loggable).SIMPLEMENTSApp.Loggableonly,TIMPLEMENTSWeb.Loggableonly; one edge each; no danglingIMPLEMENTS/HAS_METHOD.Verification
rubyresolver suite: registry-primary 149/149, legacy 137 + 12 by-design skips (the registry-primary-only mixin routing is listed inLEGACY_RESOLVER_PARITY_EXPECTED_FAILURES, like the Qualified nested-type node identity — resolution-side follow-up (Ruby same-tail routed-props/mixins + Rust inherent impls) #1982 mixin tests) — both green, including the worker path.tsc --noEmitclean; prettier clean;ruby-captures-goldenregenerated additively (4 insertions — the new fixture only);ruby-scope-capture-tripwireunaffected;ruby-nested-mixin-shortname/ruby-qualified-mixin/ruby-nested-tail-collisionstay green.Closes #1991.
🤖 Generated with Claude Code