From 823cc02f82382814fef2a6390b1d20d16fa88d00 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 05:32:06 +0000 Subject: [PATCH] refactor: clarify TS capture helpers after validation feedback Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/0e53743e-0600-4690-bd0d-198894daef58 --- .../languages/typescript/captures.ts | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/gitnexus/src/core/ingestion/languages/typescript/captures.ts b/gitnexus/src/core/ingestion/languages/typescript/captures.ts index 06ff691a0..93eb4f599 100644 --- a/gitnexus/src/core/ingestion/languages/typescript/captures.ts +++ b/gitnexus/src/core/ingestion/languages/typescript/captures.ts @@ -64,10 +64,7 @@ const CALL_TAGS = [ '@reference.call.constructor', ] as const; -function pickFirstDefined( - grouped: Record, - tags: readonly string[], -): T | undefined { +function pickFirstCapture(grouped: CaptureMatch, tags: readonly string[]): Capture | undefined { for (const tag of tags) { const cap = grouped[tag]; if (cap !== undefined) return cap; @@ -75,6 +72,17 @@ function pickFirstDefined( return undefined; } +function pickFirstNode( + grouped: Record, + tags: readonly string[], +): SyntaxNode | undefined { + for (const tag of tags) { + const node = grouped[tag]; + if (node !== undefined) return node; + } + return undefined; +} + /** * Drop `@reference.read.member` matches whose underlying `member_expression` * is NOT actually a read context: @@ -117,8 +125,9 @@ function shouldEmitReadMember(memberNode: SyntaxNode): boolean { } function findSelfOrAncestorOfType(node: SyntaxNode | undefined, type: string): SyntaxNode | null { - let current: SyntaxNode | null | undefined = node; - while (current !== undefined && current !== null) { + if (node === undefined) return null; + let current: SyntaxNode | null = node; + while (current !== null) { if (current.type === type) return current; current = current.parent; } @@ -129,8 +138,9 @@ function findSelfOrAncestorOfTypes( node: SyntaxNode | undefined, types: readonly string[], ): SyntaxNode | null { - let current: SyntaxNode | null | undefined = node; - while (current !== undefined && current !== null) { + if (node === undefined) return null; + let current: SyntaxNode | null = node; + while (current !== null) { if (types.includes(current.type)) return current; current = current.parent; } @@ -242,8 +252,8 @@ export function emitTsScopeCaptures( // overloads — TypeScript supports overload signatures via // function_signature, so `parameterTypes` is populated when // available. - const declAnchor = pickFirstDefined(grouped, FUNCTION_DECL_TAGS); - const declAnchorNode = pickFirstDefined(groupedNodes, FUNCTION_DECL_TAGS); + const declAnchor = pickFirstCapture(grouped, FUNCTION_DECL_TAGS); + const declAnchorNode = pickFirstNode(groupedNodes, FUNCTION_DECL_TAGS); if (declAnchor !== undefined) { const fnNode = findFunctionNode(tree.rootNode, declAnchor.range, declAnchorNode); if (fnNode !== null) { @@ -290,8 +300,8 @@ export function emitTsScopeCaptures( // calls to disambiguate by props-arity, a JSX-aware arity // synthesizer would need to count `jsx_attribute` children of the // opening tag instead of `arguments`. - const callAnchor = pickFirstDefined(grouped, CALL_TAGS); - const callAnchorNode = pickFirstDefined(groupedNodes, CALL_TAGS); + const callAnchor = pickFirstCapture(grouped, CALL_TAGS); + const callAnchorNode = pickFirstNode(groupedNodes, CALL_TAGS); if (callAnchor !== undefined && grouped['@reference.arity'] === undefined) { const callNode = findSelfOrAncestorOfTypes(callAnchorNode, ['call_expression', 'new_expression']) ??