From 51d06de71e313fdcbc737ff86964e49ee981402b Mon Sep 17 00:00:00 2001 From: azizur100389 Date: Tue, 2 Jun 2026 11:38:41 +0100 Subject: [PATCH] fix(cpp): capture uninitialized multi-declarators (#1965) --- gitnexus/bench/scope-capture/baselines.json | 5 +++-- gitnexus/src/core/ingestion/languages/c/query.ts | 9 +++++++++ .../src/core/ingestion/languages/cpp/query.ts | 9 +++++++++ .../unit/scope-resolution/c/c-captures.test.ts | 8 ++++++++ .../scope-resolution/cpp/cpp-captures.test.ts | 15 +++++++++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/gitnexus/bench/scope-capture/baselines.json b/gitnexus/bench/scope-capture/baselines.json index 704e9381db..a1d4fbea41 100644 --- a/gitnexus/bench/scope-capture/baselines.json +++ b/gitnexus/bench/scope-capture/baselines.json @@ -16,9 +16,10 @@ "_added": "#1956: c added to the scope-capture bench (was UNBENCHED). C has no inheritance — flat scale source. Adding it exposed + fixed a pre-existing O(n^2) findNodeAtRange root-walk in c/captures.ts (threaded c.node, byte-identical over c-* fixtures); scaling 3.475 -> 0.96." }, "cpp": { - "fingerprint": "a571d260559fa48994d12970965b4f9df93efd087541ca31dc7818ac4cd2a2a6", + "fingerprint": "4022f436885d15fd2d419e38e0674115e1c5daa7dcb9578de2633160bed94446", "scaling_budget": 1.5, - "_added": "#1956: cpp added to the scope-capture bench (was UNBENCHED). Heritage-bearing scale source (: public Base, public Mixin) drives emitCppInheritanceCaptures at scale. Adding it exposed + fixed a pre-existing O(n^2) findNodeAtRange root-walk in cpp/captures.ts (~12 sites, threaded c.node, byte-identical over 263 cpp-* fixtures); scaling 2.30 -> 1.12." + "_added": "#1956: cpp added to the scope-capture bench (was UNBENCHED). Heritage-bearing scale source (: public Base, public Mixin) drives emitCppInheritanceCaptures at scale. Adding it exposed + fixed a pre-existing O(n^2) findNodeAtRange root-walk in cpp/captures.ts (~12 sites, threaded c.node, byte-identical over 263 cpp-* fixtures); scaling 2.30 -> 1.12.", + "_rebaselined": "#1965 / #1923 F4: uninitialized non-leading multi-declarators now emit @declaration.variable captures; cpp-adl-inner-callable-outer-noncallable data::Pair a, b adds the legitimate fixture drift. Linear (~1.06)." }, "csharp": { "_rebaselined": "#1956 synth-widening: + csharp-qualified-base fixture; the synth now walks record_declaration + struct_declaration base_lists and handles alias_qualified_name (matching the #1940 legacy leg), so record/struct heritage now emits. csharp-record-base gains a record inherits capture. (record->record SAME-namespace EXTENDS is a separate registry resolution gap, tracked as follow-up.) Linear (~1.00). (Earlier #1956: heritage-bearing scale source.)", diff --git a/gitnexus/src/core/ingestion/languages/c/query.ts b/gitnexus/src/core/ingestion/languages/c/query.ts index 41feb8ad5e..373e1e7a7d 100644 --- a/gitnexus/src/core/ingestion/languages/c/query.ts +++ b/gitnexus/src/core/ingestion/languages/c/query.ts @@ -99,6 +99,15 @@ const C_SCOPE_QUERY = ` declarator: (init_declarator declarator: (identifier) @declaration.name)) @declaration.variable +;; Declarations — variables (without initializer), including non-leading +;; declarators in mixed declaration lists. +(declaration + declarator: (identifier) @declaration.name) @declaration.variable + +(declaration + declarator: (pointer_declarator + declarator: (identifier) @declaration.name)) @declaration.variable + ;; Declarations — macro definitions (preproc_def name: (identifier) @declaration.name) @declaration.macro diff --git a/gitnexus/src/core/ingestion/languages/cpp/query.ts b/gitnexus/src/core/ingestion/languages/cpp/query.ts index 90803b866f..aa3202abeb 100644 --- a/gitnexus/src/core/ingestion/languages/cpp/query.ts +++ b/gitnexus/src/core/ingestion/languages/cpp/query.ts @@ -273,6 +273,15 @@ const CPP_SCOPE_QUERY = ` declarator: (init_declarator declarator: (identifier) @declaration.name)) @declaration.variable +;; ─── Declarations — variables (without initializer) ───────────────── +;; Covers non-leading declarators in mixed declaration lists. +(declaration + declarator: (identifier) @declaration.name) @declaration.variable + +(declaration + declarator: (pointer_declarator + declarator: (identifier) @declaration.name)) @declaration.variable + ;; ─── Declarations — macro definitions ─────────────────────────────── (preproc_def name: (identifier) @declaration.name) @declaration.macro diff --git a/gitnexus/test/unit/scope-resolution/c/c-captures.test.ts b/gitnexus/test/unit/scope-resolution/c/c-captures.test.ts index 7da7031526..170620d5e0 100644 --- a/gitnexus/test/unit/scope-resolution/c/c-captures.test.ts +++ b/gitnexus/test/unit/scope-resolution/c/c-captures.test.ts @@ -198,6 +198,14 @@ describe('emitCScopeCaptures — other declarations', () => { expect(m!['@declaration.name'].text).toBe('x'); }); + it('captures all names in mixed initialized and uninitialized declarations', () => { + const matches = allMatches('void f(void) { int a = 1, b, *p, c = 3, d; }', (t) => + t.includes('@declaration.variable'), + ); + const names = matches.map((m) => m['@declaration.name'].text).sort(); + expect(names).toEqual(['a', 'b', 'c', 'd', 'p']); + }); + it('captures macro as @declaration.macro', () => { const m = findMatch('#define MAX 100', (t) => t.includes('@declaration.macro')); expect(m).toBeDefined(); diff --git a/gitnexus/test/unit/scope-resolution/cpp/cpp-captures.test.ts b/gitnexus/test/unit/scope-resolution/cpp/cpp-captures.test.ts index 0697ea155e..37b6de8427 100644 --- a/gitnexus/test/unit/scope-resolution/cpp/cpp-captures.test.ts +++ b/gitnexus/test/unit/scope-resolution/cpp/cpp-captures.test.ts @@ -222,6 +222,21 @@ describe('emitCppScopeCaptures — variable declarations', () => { expect(m).toBeDefined(); expect(m!['@declaration.name'].text).toBe('x'); }); + + it('captures all names in mixed initialized and uninitialized declarations', () => { + const matches = allMatches('void f() { int a = 1, b, *p, c = 3, d; }', (t) => + t.includes('@declaration.variable'), + ); + const names = matches.map((m) => m['@declaration.name'].text).sort(); + expect(names).toEqual(['a', 'b', 'c', 'd', 'p']); + }); + + it('captures qualified-type multi-declarator variables', () => { + const src = 'namespace data { struct Pair {}; } void f() { data::Pair a, b; }'; + const matches = allMatches(src, (t) => t.includes('@declaration.variable')); + const names = matches.map((m) => m['@declaration.name'].text).sort(); + expect(names).toEqual(['a', 'b']); + }); }); // ── Declarations — enums ────────────────────────────────────────────────────