fix(ruby-extractor): capture keyword params and members of nested classes/modules#439
fix(ruby-extractor): capture keyword params and members of nested classes/modules#439tirth8205 wants to merge 2 commits into
Conversation
…sses/modules extractParams had no case for `keyword_parameter`, so Ruby keyword args (`name:`, `age: 30`) were silently dropped from method signatures. extractClassBody also only inspected method/singleton_method/call members, so classes/modules nested inside a module (the standard namespacing idiom) and their methods vanished from the structural analysis. Add a `keyword_parameter` case (emitting `name:`) and thread the shared `classes` array through extractClassBody so nested class/module members recurse into extractClass/extractModule. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
thejesh23
left a comment
There was a problem hiding this comment.
A few concerns before this lands.
1. Nested classes lose namespace context in the flat classes[]. module Outer; class Inner; end; end now produces two entries named "Outer" and "Inner" — not "Outer::Inner". Two modules each defining class Config will both register as "Config" and become indistinguishable downstream (no way to attribute methods/functions back to the right namespace). Compare with the existing namespaced-class path which preserves "Foo::Bar" via scope_resolution. Either qualify on push ("${outerName}::${innerName}") or document the ambiguity. Same shape will hit the Dart extractor in #435 once it grows nested-class handling.
2. Exports drift from classes[]. extractStructure's top-level switch is the only place that appends to exports. Pre-fix that was fine because nested classes were dropped from classes too; now classes contains Inner but exports does not. Anything that joins exports against the class list (or treats classes[] as the export surface for Ruby) will see a mismatch. Worth either also surfacing nested decls as exports or noting this is intentional.
3. Test uses arrayContaining, so ordering regressions slip through. Because classes.push happens after the body recursion, the inner class is pushed before its enclosing module — order in classes[] is [Inner, Outer], not source order. The new test is order-agnostic, so a future change that fixes (or further breaks) ordering won't be caught. Also no assertion that Outer.methods does NOT contain foo — the current code is correct on this point but it's the most likely regression vector if someone later folds the class/module branches back into the method path.
Nit: the extractParams JSDoc still lists the handled cases exhaustively; please add keyword_parameter to the comment so the next reader doesn't think it's missing.
…k test invariants Document at the nested class/module recursion site that nested declarations are surfaced into classes[] with their bare name only (no namespace qualification, matching python-extractor) and are intentionally omitted from exports[] (only top-level decls are exports). Add keyword_parameter to the extractParams JSDoc handled-cases list. Strengthen the nested-class test: assert exact classes[] order [Inner, Outer] and that the nested method `foo` lands on Inner.methods, not Outer.methods. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Addressed all four points. 1 — Nested classes lose namespace context. Kept bare names but documented the contract at the nested recursion site in 2 — Exports drift from 3 — Order-agnostic test + missing negative assertion. Replaced Nit. Added Full core suite green (695 passed); |
Problem
The Ruby extractor dropped two common constructs from structural analysis:
Keyword parameters.
extractParamsswitched on the parameter node type but had no case forkeyword_parameter— the tree-sitter node for Ruby keyword args (name:,age: 30). Sodef configure(name:, age: 30)producedparams: [], and a mixed signaturedef build(a, b, name:, opts: {})producedparams: ["a","b"], losing every keyword arg. Keyword arguments are pervasive in modern Ruby, so this dropped a large fraction of real method signatures.Members of nested classes/modules.
extractClassBodyonly inspectedmethod,singleton_method, andcallmembers of a class/module body. It never handled nestedclassormodulemembers, somodule Outer; class Inner; def foo; end; end; endproducedclasses: ['Outer']andfunctions: []— theInnerclass and itsfoomethod vanished. Nesting a class inside a module is the standard Ruby namespacing idiom.Fix
In
understand-anything-plugin/packages/core/src/plugins/extractors/ruby-extractor.ts:keyword_parametercase inextractParamsthat pushesident.text + ":"(the trailing:distinguishes keyword args from positional ones).classesarray intoextractClassBodyand addedclass/modulemember handling that recurses through the existingextractClass/extractModulehelpers, appending nested declarations and their methods to the top-levelclasses/functionsarrays.Testing
Added three test cases to
ruby-extractor.test.ts(extracts keyword parameters, extracts mixed positional and keyword parameters, extracts classes/modules nested inside a module). All three fail before the fix (keyword params dropped;Innermissing) and pass after. The full core Vitest suite (695 tests across all extractors) is green,tsc --noEmitexits 0, and ESLint is clean on both changed files.🤖 Generated with Claude Code