From e93f332d58e525ba55e876ae49e2cd01f4d4a93b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 16 May 2026 10:47:43 +0000 Subject: [PATCH] feat(LANG-rust): add scope-resolution hooks and register Rust ScopeResolver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements RFC #909 Ring 3 deliverables: - query.ts: tree-sitter scope query for Rust - captures.ts: emitRustScopeCaptures with method reclassification - import-decomposer.ts: use statement decomposition (groups, renames, globs) - interpret.ts: interpretRustImport + interpretRustTypeBinding - import-target.ts: crate/module/super/self path resolution - receiver-binding.ts: self/&self/&mut self receiver synthesis - method-owners.ts: impl block → struct ownership bridging - arity.ts: no-overloading arity check - merge-bindings.ts: local > import > wildcard binding precedence - simple-hooks.ts: binding/import scope, receiver binding - scope-resolver.ts: ScopeResolver contract implementation - Wired into rustProvider (rust.ts) with scope hooks - Registered in SCOPE_RESOLVERS (pipeline/registry.ts) - NOT yet added to MIGRATED_LANGUAGES (29 advanced pattern tests pending) Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/8f14b730-79d4-4356-9505-325750d71f84 Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> --- .../src/core/ingestion/languages/rust/captures.ts | 14 ++++++++++++++ .../ingestion/languages/rust/import-decomposer.ts | 13 +++++++------ .../core/ingestion/languages/rust/interpret.ts | 3 +-- .../ingestion/languages/rust/method-owners.ts | 15 ++++++++++++--- .../src/core/ingestion/registry-primary-flag.ts | 1 - 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/gitnexus/src/core/ingestion/languages/rust/captures.ts b/gitnexus/src/core/ingestion/languages/rust/captures.ts index 90452db12..379b7e564 100644 --- a/gitnexus/src/core/ingestion/languages/rust/captures.ts +++ b/gitnexus/src/core/ingestion/languages/rust/captures.ts @@ -65,6 +65,20 @@ export function emitRustScopeCaptures( if (declAnchor !== undefined) { const fnNode = findNodeAtRange(tree.rootNode, declAnchor.range, 'function_item'); if (fnNode !== null) { + // Reclassify as method if inside an impl block + if (findEnclosingImpl(fnNode) !== null) { + const nameCap = grouped['@declaration.name']; + delete (grouped as Record)['@declaration.function']; + grouped['@declaration.method'] = syntheticCapture( + '@declaration.method', + fnNode, + fnNode.text, + ); + if (nameCap !== undefined) { + grouped['@declaration.name'] = nameCap; + } + } + const arity = computeRustDeclarationArity(fnNode); if (arity.parameterCount !== undefined) { grouped['@declaration.parameter-count'] = syntheticCapture( diff --git a/gitnexus/src/core/ingestion/languages/rust/import-decomposer.ts b/gitnexus/src/core/ingestion/languages/rust/import-decomposer.ts index b7a92fb9f..d87b94057 100644 --- a/gitnexus/src/core/ingestion/languages/rust/import-decomposer.ts +++ b/gitnexus/src/core/ingestion/languages/rust/import-decomposer.ts @@ -194,15 +194,16 @@ function makeImportCapture( name: string, alias: string | undefined, ): CaptureMatch { - const result: CaptureMatch = { + return { '@import.statement': syntheticCapture('@import.statement', anchor, anchor.text), '@import.kind': syntheticCapture('@import.kind', anchor, kind), '@import.source': syntheticCapture('@import.source', anchor, source), '@import.name': syntheticCapture('@import.name', anchor, alias ?? name), + ...(alias !== undefined + ? { + '@import.alias': syntheticCapture('@import.alias', anchor, alias), + '@import.original-name': syntheticCapture('@import.original-name', anchor, name), + } + : {}), }; - if (alias !== undefined) { - result['@import.alias'] = syntheticCapture('@import.alias', anchor, alias); - result['@import.original-name'] = syntheticCapture('@import.original-name', anchor, name); - } - return result; } diff --git a/gitnexus/src/core/ingestion/languages/rust/interpret.ts b/gitnexus/src/core/ingestion/languages/rust/interpret.ts index 3bbb8c204..5ce0f4aec 100644 --- a/gitnexus/src/core/ingestion/languages/rust/interpret.ts +++ b/gitnexus/src/core/ingestion/languages/rust/interpret.ts @@ -18,11 +18,10 @@ export function interpretRustImport(captures: CaptureMatch): ParsedImport | null if (name === undefined) return null; const originalName = captures['@import.original-name']?.text; return { - kind: 'named', + kind: 'reexport', localName: alias ?? name, importedName: originalName ?? name, targetRaw: source, - isReexport: true, }; } // kind === 'named' diff --git a/gitnexus/src/core/ingestion/languages/rust/method-owners.ts b/gitnexus/src/core/ingestion/languages/rust/method-owners.ts index 897dc5865..ad39c6bca 100644 --- a/gitnexus/src/core/ingestion/languages/rust/method-owners.ts +++ b/gitnexus/src/core/ingestion/languages/rust/method-owners.ts @@ -28,8 +28,8 @@ function populateRustImplOwners(parsed: ParsedFile): void { const structByName = new Map(); for (const scope of parsed.scopes) { for (const def of scope.ownedDefs) { - if (isClassLike(def.type) && (def.type === 'Struct' || def.type === 'Trait')) { - structByName.set(def.name, def.nodeId); + if (isClassLike(def.type) && def.qualifiedName) { + structByName.set(def.qualifiedName, def.nodeId); } } } @@ -53,7 +53,16 @@ function populateRustImplOwners(parsed: ParsedFile): void { } if (receiverType === undefined) continue; - const ownerId = structByName.get(receiverType); + let ownerId = structByName.get(receiverType); + if (ownerId === undefined) { + // Try suffix match (qualifiedName might be `module.StructName`) + for (const [qname, nodeId] of structByName) { + if (qname.endsWith('.' + receiverType) || qname === receiverType) { + ownerId = nodeId; + break; + } + } + } if (ownerId !== undefined) { for (const def of methodDefs) { (def as { ownerId?: string }).ownerId = ownerId; diff --git a/gitnexus/src/core/ingestion/registry-primary-flag.ts b/gitnexus/src/core/ingestion/registry-primary-flag.ts index be8ffd109..869157adb 100644 --- a/gitnexus/src/core/ingestion/registry-primary-flag.ts +++ b/gitnexus/src/core/ingestion/registry-primary-flag.ts @@ -74,7 +74,6 @@ export const MIGRATED_LANGUAGES: ReadonlySet = new Set