gitnexus 1.6.5-rc.33 → 1.6.5-rc.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -68,15 +68,19 @@ export const cppScopeResolver = {
|
|
|
68
68
|
// fallback and wildcard expansion can suppress them as unqualified
|
|
69
69
|
// cross-file callables.
|
|
70
70
|
populateCppNonGloballyVisible(parsed);
|
|
71
|
-
// Resolve recorded template-class → dependent-base simple names to
|
|
72
|
-
// class nodeIds for two-phase template lookup (U3 of plan
|
|
73
|
-
// 2026-05-13-001).
|
|
74
|
-
populateCppDependentBases(parsed);
|
|
75
71
|
// Build the class-def → enclosing-namespace-qualified-name map used
|
|
76
72
|
// by ADL (U2 of plan 2026-05-13-001) to identify each argument type's
|
|
77
73
|
// associated namespace for Koenig lookup.
|
|
78
74
|
populateCppAssociatedNamespaces(parsed);
|
|
79
75
|
},
|
|
76
|
+
// Resolve recorded template-class → dependent-base simple names to
|
|
77
|
+
// class nodeIds for two-phase template lookup (U3 of plan
|
|
78
|
+
// 2026-05-13-001). Runs AFTER all files have had `populateOwners`
|
|
79
|
+
// applied so that cross-file base classes (e.g. Base in base.h,
|
|
80
|
+
// Derived in derived.h) are reachable in the workspace index.
|
|
81
|
+
populateWorkspaceOwners: (parsedFiles) => {
|
|
82
|
+
populateCppDependentBases(parsedFiles);
|
|
83
|
+
},
|
|
80
84
|
// Simple `isSuperReceiver` returns false for C++. Real super
|
|
81
85
|
// classification is caller-context-dependent and lives in
|
|
82
86
|
// `isSuperReceiverInContext` below — without scope context the
|
|
@@ -11,8 +11,20 @@
|
|
|
11
11
|
* This module records — during `emitCppScopeCaptures` — which template
|
|
12
12
|
* class declarations have which dependent base class names (per file).
|
|
13
13
|
* `populateCppDependentBases` then resolves those names to class nodeIds
|
|
14
|
-
* using
|
|
15
|
-
* `
|
|
14
|
+
* using a workspace-wide registry, building the per-class set the
|
|
15
|
+
* `isCppDependentBaseMember` predicate consumes.
|
|
16
|
+
*
|
|
17
|
+
* Cross-file resolution: `Base<T>` may be declared in a different header
|
|
18
|
+
* than `Derived<T>`. `populateCppDependentBases` therefore runs as a
|
|
19
|
+
* workspace-wide pass (`populateWorkspaceOwners` hook) after every file
|
|
20
|
+
* has had `populateOwners` applied, so all class defs are reachable.
|
|
21
|
+
*
|
|
22
|
+
* Namespace disambiguation: when multiple classes share a simple name
|
|
23
|
+
* (e.g., `Box` in two namespaces), the resolver prefers the candidate
|
|
24
|
+
* whose qualified-name prefix (namespace path) matches the deriving
|
|
25
|
+
* class's prefix. If no namespace match is found, a unique simple-name
|
|
26
|
+
* match is accepted; ambiguous matches (multiple candidates, no
|
|
27
|
+
* namespace winner) are skipped conservatively.
|
|
16
28
|
*
|
|
17
29
|
* NOTE: module-level state, single-process-single-repo use only.
|
|
18
30
|
* `clearFileLocalNames()` clears this state alongside file-local linkage
|
|
@@ -33,15 +45,19 @@ export declare function markCppDependentBase(filePath: string, className: string
|
|
|
33
45
|
/** Clear two-phase-lookup state. Called from `clearFileLocalNames`. */
|
|
34
46
|
export declare function clearCppDependentBases(): void;
|
|
35
47
|
/**
|
|
36
|
-
* Resolve recorded dependent-base simple names to class nodeIds using
|
|
37
|
-
*
|
|
38
|
-
*
|
|
48
|
+
* Resolve recorded dependent-base simple names to class nodeIds using a
|
|
49
|
+
* workspace-wide index. Run as `populateWorkspaceOwners` after every
|
|
50
|
+
* file has had `populateOwners` applied, so class defs from ALL files
|
|
51
|
+
* are reachable.
|
|
39
52
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
53
|
+
* Disambiguation strategy (multiple classes sharing a simple name):
|
|
54
|
+
* 1. Prefer the candidate whose qualified-name namespace prefix matches
|
|
55
|
+
* the deriving class's namespace prefix (same-namespace bias).
|
|
56
|
+
* 2. Fall back to accepting a unique simple-name match.
|
|
57
|
+
* 3. Skip when multiple candidates exist and no namespace match is
|
|
58
|
+
* found (conservative: avoids false associations).
|
|
43
59
|
*/
|
|
44
|
-
export declare function populateCppDependentBases(
|
|
60
|
+
export declare function populateCppDependentBases(parsedFiles: readonly ParsedFile[]): void;
|
|
45
61
|
/**
|
|
46
62
|
* Two-phase lookup predicate: is the candidate def a member of a
|
|
47
63
|
* dependent base of the caller's enclosing template class?
|
|
@@ -11,8 +11,20 @@
|
|
|
11
11
|
* This module records — during `emitCppScopeCaptures` — which template
|
|
12
12
|
* class declarations have which dependent base class names (per file).
|
|
13
13
|
* `populateCppDependentBases` then resolves those names to class nodeIds
|
|
14
|
-
* using
|
|
15
|
-
* `
|
|
14
|
+
* using a workspace-wide registry, building the per-class set the
|
|
15
|
+
* `isCppDependentBaseMember` predicate consumes.
|
|
16
|
+
*
|
|
17
|
+
* Cross-file resolution: `Base<T>` may be declared in a different header
|
|
18
|
+
* than `Derived<T>`. `populateCppDependentBases` therefore runs as a
|
|
19
|
+
* workspace-wide pass (`populateWorkspaceOwners` hook) after every file
|
|
20
|
+
* has had `populateOwners` applied, so all class defs are reachable.
|
|
21
|
+
*
|
|
22
|
+
* Namespace disambiguation: when multiple classes share a simple name
|
|
23
|
+
* (e.g., `Box` in two namespaces), the resolver prefers the candidate
|
|
24
|
+
* whose qualified-name prefix (namespace path) matches the deriving
|
|
25
|
+
* class's prefix. If no namespace match is found, a unique simple-name
|
|
26
|
+
* match is accepted; ambiguous matches (multiple candidates, no
|
|
27
|
+
* namespace winner) are skipped conservatively.
|
|
16
28
|
*
|
|
17
29
|
* NOTE: module-level state, single-process-single-repo use only.
|
|
18
30
|
* `clearFileLocalNames()` clears this state alongside file-local linkage
|
|
@@ -61,40 +73,97 @@ export function clearCppDependentBases() {
|
|
|
61
73
|
dependentBaseNodeIds.clear();
|
|
62
74
|
}
|
|
63
75
|
/**
|
|
64
|
-
* Resolve recorded dependent-base simple names to class nodeIds using
|
|
65
|
-
*
|
|
66
|
-
*
|
|
76
|
+
* Resolve recorded dependent-base simple names to class nodeIds using a
|
|
77
|
+
* workspace-wide index. Run as `populateWorkspaceOwners` after every
|
|
78
|
+
* file has had `populateOwners` applied, so class defs from ALL files
|
|
79
|
+
* are reachable.
|
|
67
80
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
81
|
+
* Disambiguation strategy (multiple classes sharing a simple name):
|
|
82
|
+
* 1. Prefer the candidate whose qualified-name namespace prefix matches
|
|
83
|
+
* the deriving class's namespace prefix (same-namespace bias).
|
|
84
|
+
* 2. Fall back to accepting a unique simple-name match.
|
|
85
|
+
* 3. Skip when multiple candidates exist and no namespace match is
|
|
86
|
+
* found (conservative: avoids false associations).
|
|
71
87
|
*/
|
|
72
|
-
export function populateCppDependentBases(
|
|
73
|
-
|
|
74
|
-
if (perFile === undefined)
|
|
88
|
+
export function populateCppDependentBases(parsedFiles) {
|
|
89
|
+
if (dependentBasesByFile.size === 0)
|
|
75
90
|
return;
|
|
76
|
-
// Build
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
// Build workspace-wide index: simpleName → {nodeId, nsPrefix}[]
|
|
92
|
+
// nsPrefix is the dot-joined namespace path (qualifiedName without the
|
|
93
|
+
// last segment). Classes at global scope have nsPrefix = ''.
|
|
94
|
+
const classesBySimpleName = new Map();
|
|
95
|
+
for (const parsed of parsedFiles) {
|
|
96
|
+
for (const def of parsed.localDefs) {
|
|
97
|
+
if (def.type !== 'Class' && def.type !== 'Struct' && def.type !== 'Interface')
|
|
98
|
+
continue;
|
|
99
|
+
const qn = def.qualifiedName ?? '';
|
|
100
|
+
const lastDot = qn.lastIndexOf('.');
|
|
101
|
+
const simple = lastDot >= 0 ? qn.slice(lastDot + 1) : qn;
|
|
102
|
+
if (simple === '')
|
|
103
|
+
continue;
|
|
104
|
+
const nsPrefix = lastDot >= 0 ? qn.slice(0, lastDot) : '';
|
|
105
|
+
let entries = classesBySimpleName.get(simple);
|
|
106
|
+
if (entries === undefined) {
|
|
107
|
+
entries = [];
|
|
108
|
+
classesBySimpleName.set(simple, entries);
|
|
109
|
+
}
|
|
110
|
+
entries.push({ nodeId: def.nodeId, nsPrefix });
|
|
111
|
+
}
|
|
84
112
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
113
|
+
// Build a filePath → ParsedFile lookup for fast per-file access.
|
|
114
|
+
const parsedByFile = new Map();
|
|
115
|
+
for (const parsed of parsedFiles)
|
|
116
|
+
parsedByFile.set(parsed.filePath, parsed);
|
|
117
|
+
for (const [filePath, perFile] of dependentBasesByFile) {
|
|
118
|
+
const parsed = parsedByFile.get(filePath);
|
|
119
|
+
if (parsed === undefined)
|
|
88
120
|
continue;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
121
|
+
// Build a simple-name → {nodeId, nsPrefix} map for THIS file's
|
|
122
|
+
// class-like defs so we can identify each template class precisely
|
|
123
|
+
// (avoids cross-file name collisions for the deriving class itself).
|
|
124
|
+
const localClassByName = new Map();
|
|
125
|
+
for (const def of parsed.localDefs) {
|
|
126
|
+
if (def.type !== 'Class' && def.type !== 'Struct' && def.type !== 'Interface')
|
|
127
|
+
continue;
|
|
128
|
+
const qn = def.qualifiedName ?? '';
|
|
129
|
+
const lastDot = qn.lastIndexOf('.');
|
|
130
|
+
const simple = lastDot >= 0 ? qn.slice(lastDot + 1) : qn;
|
|
131
|
+
if (simple === '')
|
|
132
|
+
continue;
|
|
133
|
+
const nsPrefix = lastDot >= 0 ? qn.slice(0, lastDot) : '';
|
|
134
|
+
localClassByName.set(simple, { nodeId: def.nodeId, nsPrefix });
|
|
93
135
|
}
|
|
94
|
-
for (const
|
|
95
|
-
const
|
|
96
|
-
if (
|
|
97
|
-
|
|
136
|
+
for (const [className, baseNames] of perFile) {
|
|
137
|
+
const classEntry = localClassByName.get(className);
|
|
138
|
+
if (classEntry === undefined)
|
|
139
|
+
continue;
|
|
140
|
+
let bases = dependentBaseNodeIds.get(classEntry.nodeId);
|
|
141
|
+
if (bases === undefined) {
|
|
142
|
+
bases = new Set();
|
|
143
|
+
dependentBaseNodeIds.set(classEntry.nodeId, bases);
|
|
144
|
+
}
|
|
145
|
+
for (const baseName of baseNames) {
|
|
146
|
+
const candidates = classesBySimpleName.get(baseName);
|
|
147
|
+
if (candidates === undefined || candidates.length === 0)
|
|
148
|
+
continue;
|
|
149
|
+
if (candidates.length === 1) {
|
|
150
|
+
// Unique simple-name match — accept regardless of namespace.
|
|
151
|
+
bases.add(candidates[0].nodeId);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
// Multiple classes share the same simple name — prefer the one
|
|
155
|
+
// whose namespace matches the deriving class's namespace.
|
|
156
|
+
// V1: exact dot-prefix match only. Cross-namespace inheritance
|
|
157
|
+
// (e.g., `ns::outer::Derived` extending bare `Inner` defined in
|
|
158
|
+
// `ns::outer::inner`) and inline-namespace cases are deferred to
|
|
159
|
+
// V2; the conservative skip-on-ambiguity below avoids false
|
|
160
|
+
// associations in those edge cases.
|
|
161
|
+
const nsMatch = candidates.find((c) => c.nsPrefix === classEntry.nsPrefix);
|
|
162
|
+
if (nsMatch !== undefined) {
|
|
163
|
+
bases.add(nsMatch.nodeId);
|
|
164
|
+
}
|
|
165
|
+
// else: ambiguous (multiple candidates, no namespace match) → skip.
|
|
166
|
+
}
|
|
98
167
|
}
|
|
99
168
|
}
|
|
100
169
|
}
|
package/package.json
CHANGED