gitnexus 1.6.8-rc.47 → 1.6.8-rc.49
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.
- package/dist/_shared/scope-resolution/symbol-definition.d.ts +2 -0
- package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
- package/dist/core/ingestion/languages/cpp/arity-metadata.js +35 -0
- package/dist/core/ingestion/languages/cpp/captures.js +24 -0
- package/dist/core/ingestion/languages/cpp/conversion-rank.d.ts +2 -0
- package/dist/core/ingestion/languages/cpp/conversion-rank.js +89 -0
- package/dist/core/ingestion/languages/cpp/inline-namespaces.js +7 -2
- package/dist/core/ingestion/languages/cpp/member-lookup.js +2 -1
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +2 -1
- package/dist/core/ingestion/scope-extractor.js +9 -2
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +9 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +3 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +9 -2
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +4 -0
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +9 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +1 -1
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +4 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +1 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +21 -0
- package/dist/core/wiki/generator.js +3 -1
- package/dist/core/wiki/graph-queries.d.ts +6 -0
- package/dist/core/wiki/graph-queries.js +9 -1
- package/package.json +1 -1
|
@@ -18,6 +18,8 @@ export interface ParameterTypeClass {
|
|
|
18
18
|
indirection: 'value' | 'lvalue-ref' | 'rvalue-ref' | 'pointer' | 'unknown';
|
|
19
19
|
/** Number of pointer markers when indirection is `pointer`; otherwise 0. */
|
|
20
20
|
pointerDepth: number;
|
|
21
|
+
/** Normalized top-level template arguments, when a language preserves them. */
|
|
22
|
+
templateArguments?: string[];
|
|
21
23
|
}
|
|
22
24
|
export interface SymbolDefinition {
|
|
23
25
|
nodeId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symbol-definition.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/symbol-definition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,gBAAgB,GAAG,SAAS,CAAC;IACjE,4CAA4C;IAC5C,WAAW,EAAE,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3E,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"symbol-definition.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/symbol-definition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,gBAAgB,GAAG,SAAS,CAAC;IACjE,4CAA4C;IAC5C,WAAW,EAAE,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3E,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB;;+FAE2F;IAC3F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;iHAC6G;IAC7G,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;uFACmF;IACnF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;4FACwF;IACxF,oBAAoB,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC5C,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gGAAgG;IAChG,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;yEAKqE;IACrE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;4DAEwD;IACxD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;mEAE+D;IAC/D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;iEAO6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
|
|
@@ -173,6 +173,7 @@ export function classifyCppParameterType(rawType, declaratorText, fullParameterT
|
|
|
173
173
|
cv,
|
|
174
174
|
indirection,
|
|
175
175
|
pointerDepth,
|
|
176
|
+
...templateArgumentsFor(`${source} ${rawType} ${declaratorText ?? ''}`),
|
|
176
177
|
};
|
|
177
178
|
}
|
|
178
179
|
function unknownTypeClass(base) {
|
|
@@ -183,6 +184,40 @@ function unknownTypeClass(base) {
|
|
|
183
184
|
pointerDepth: 0,
|
|
184
185
|
};
|
|
185
186
|
}
|
|
187
|
+
function templateArgumentsFor(rawType) {
|
|
188
|
+
const args = parseTopLevelTemplateArguments(rawType);
|
|
189
|
+
return args === undefined ? {} : { templateArguments: args };
|
|
190
|
+
}
|
|
191
|
+
function parseTopLevelTemplateArguments(rawType) {
|
|
192
|
+
const start = rawType.indexOf('<');
|
|
193
|
+
if (start < 0)
|
|
194
|
+
return undefined;
|
|
195
|
+
const args = [];
|
|
196
|
+
let depth = 0;
|
|
197
|
+
let argStart = start + 1;
|
|
198
|
+
for (let i = start + 1; i < rawType.length; i++) {
|
|
199
|
+
const ch = rawType[i];
|
|
200
|
+
if (ch === '<') {
|
|
201
|
+
depth++;
|
|
202
|
+
}
|
|
203
|
+
else if (ch === '>') {
|
|
204
|
+
if (depth === 0) {
|
|
205
|
+
const finalArg = rawType.slice(argStart, i).trim();
|
|
206
|
+
if (finalArg.length > 0)
|
|
207
|
+
args.push(normalizeCppParamType(finalArg));
|
|
208
|
+
return args.length > 0 ? args : undefined;
|
|
209
|
+
}
|
|
210
|
+
depth--;
|
|
211
|
+
}
|
|
212
|
+
else if (ch === ',' && depth === 0) {
|
|
213
|
+
const arg = rawType.slice(argStart, i).trim();
|
|
214
|
+
if (arg.length > 0)
|
|
215
|
+
args.push(normalizeCppParamType(arg));
|
|
216
|
+
argStart = i + 1;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
186
221
|
function findFuncDeclarator(node) {
|
|
187
222
|
let decl = node.childForFieldName('declarator');
|
|
188
223
|
if (decl === null) {
|
|
@@ -11,6 +11,7 @@ import { markCppAdlSiteArgs, markCppAdlSiteNoAdl } from './adl.js';
|
|
|
11
11
|
import { markCppInlineNamespaceRange } from './inline-namespaces.js';
|
|
12
12
|
import { extractCppTemplateConstraints } from './constraint-extractor.js';
|
|
13
13
|
import { captureCppMemberLookupFacts } from './member-lookup.js';
|
|
14
|
+
import { CPP_BRACED_INIT_TYPE_PREFIX } from './conversion-rank.js';
|
|
14
15
|
export function emitCppScopeCaptures(sourceText, filePath, cachedTree) {
|
|
15
16
|
let tree = cachedTree;
|
|
16
17
|
if (tree === undefined) {
|
|
@@ -906,6 +907,8 @@ function unknownTypeClass(base) {
|
|
|
906
907
|
*/
|
|
907
908
|
function inferCppLiteralType(node) {
|
|
908
909
|
switch (node.type) {
|
|
910
|
+
case 'initializer_list':
|
|
911
|
+
return inferCppBracedInitType(node);
|
|
909
912
|
case 'number_literal': {
|
|
910
913
|
const text = node.text;
|
|
911
914
|
// Floating-point literals contain '.', 'e', 'E', or end with 'f'/'F'
|
|
@@ -934,6 +937,27 @@ function inferCppLiteralType(node) {
|
|
|
934
937
|
return '';
|
|
935
938
|
}
|
|
936
939
|
}
|
|
940
|
+
function inferCppBracedInitType(node) {
|
|
941
|
+
const elementTypes = [];
|
|
942
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
943
|
+
const child = node.child(i);
|
|
944
|
+
if (child === null)
|
|
945
|
+
continue;
|
|
946
|
+
if (child.type === ',' || child.type === '{' || child.type === '}')
|
|
947
|
+
continue;
|
|
948
|
+
const elementType = inferCppLiteralType(child);
|
|
949
|
+
if (elementType === '' || elementType.startsWith(CPP_BRACED_INIT_TYPE_PREFIX)) {
|
|
950
|
+
return `${CPP_BRACED_INIT_TYPE_PREFIX}unknown:${elementTypes.length + 1}`;
|
|
951
|
+
}
|
|
952
|
+
elementTypes.push(elementType);
|
|
953
|
+
}
|
|
954
|
+
if (elementTypes.length === 0)
|
|
955
|
+
return `${CPP_BRACED_INIT_TYPE_PREFIX}unknown:0`;
|
|
956
|
+
const first = elementTypes[0];
|
|
957
|
+
return elementTypes.every((type) => type === first)
|
|
958
|
+
? `${CPP_BRACED_INIT_TYPE_PREFIX}${first}:${elementTypes.length}`
|
|
959
|
+
: `${CPP_BRACED_INIT_TYPE_PREFIX}unknown:${elementTypes.length}`;
|
|
960
|
+
}
|
|
937
961
|
/**
|
|
938
962
|
* Look up the declared type of a variable by scanning sibling declarations
|
|
939
963
|
* in the enclosing compound_statement (function body). Handles:
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
* their own `ConversionRankFn` in the future.
|
|
21
21
|
*/
|
|
22
22
|
import type { ParameterTypeClass } from '../../../../_shared/index.js';
|
|
23
|
+
export declare const CPP_BRACED_INIT_TYPE_PREFIX = "braced-init:";
|
|
24
|
+
export declare const CPP_CONVERSION_ONLY_ARG_TYPE_PREFIXES: readonly ["braced-init:"];
|
|
23
25
|
/**
|
|
24
26
|
* Return the conversion rank from `argType` to `paramType`.
|
|
25
27
|
*
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* This function is intentionally C++-specific. Other languages may define
|
|
20
20
|
* their own `ConversionRankFn` in the future.
|
|
21
21
|
*/
|
|
22
|
+
import { normalizeCppParamType } from './arity-metadata.js';
|
|
22
23
|
import { hasCppUserDefinedConversion } from './user-defined-conversions.js';
|
|
23
24
|
/** Set of normalized arithmetic types that support implicit conversion. */
|
|
24
25
|
const ARITHMETIC = new Set(['int', 'double', 'char', 'bool']);
|
|
@@ -27,6 +28,22 @@ const INTEGRAL_PROMOTION = new Map([
|
|
|
27
28
|
['char', 'int'],
|
|
28
29
|
['bool', 'int'],
|
|
29
30
|
]);
|
|
31
|
+
export const CPP_BRACED_INIT_TYPE_PREFIX = 'braced-init:';
|
|
32
|
+
export const CPP_CONVERSION_ONLY_ARG_TYPE_PREFIXES = [CPP_BRACED_INIT_TYPE_PREFIX];
|
|
33
|
+
const BRACED_INIT_CONTAINER_TYPES = new Set([
|
|
34
|
+
'array',
|
|
35
|
+
'deque',
|
|
36
|
+
'list',
|
|
37
|
+
'set',
|
|
38
|
+
'std::array',
|
|
39
|
+
'std::deque',
|
|
40
|
+
'std::list',
|
|
41
|
+
'std::set',
|
|
42
|
+
'std::unordered_set',
|
|
43
|
+
'std::vector',
|
|
44
|
+
'unordered_set',
|
|
45
|
+
'vector',
|
|
46
|
+
]);
|
|
30
47
|
/**
|
|
31
48
|
* Return the conversion rank from `argType` to `paramType`.
|
|
32
49
|
*
|
|
@@ -36,6 +53,17 @@ const INTEGRAL_PROMOTION = new Map([
|
|
|
36
53
|
* for mismatch.
|
|
37
54
|
*/
|
|
38
55
|
export function cppConversionRank(argType, paramType, argTypeClass, paramTypeClass) {
|
|
56
|
+
const bracedInitType = parseBracedInitArgType(argType);
|
|
57
|
+
if (bracedInitType !== undefined) {
|
|
58
|
+
if (bracedInitType.elementType === 'unknown')
|
|
59
|
+
return Infinity;
|
|
60
|
+
if (bracedInitType.elementCount === 1) {
|
|
61
|
+
const scalarRank = cppConversionRank(bracedInitType.elementType, paramType, undefined, paramTypeClass);
|
|
62
|
+
if (isFinite(scalarRank))
|
|
63
|
+
return scalarRank;
|
|
64
|
+
}
|
|
65
|
+
return bracedInitConversionRank(paramType, bracedInitType, paramTypeClass);
|
|
66
|
+
}
|
|
39
67
|
if (argType === paramType) {
|
|
40
68
|
return exactShapeCompatible(argTypeClass, paramTypeClass) ? 0 : Infinity;
|
|
41
69
|
}
|
|
@@ -57,6 +85,67 @@ export function cppConversionRank(argType, paramType, argTypeClass, paramTypeCla
|
|
|
57
85
|
return 4;
|
|
58
86
|
return Infinity;
|
|
59
87
|
}
|
|
88
|
+
function parseBracedInitArgType(argType) {
|
|
89
|
+
if (!argType.startsWith(CPP_BRACED_INIT_TYPE_PREFIX))
|
|
90
|
+
return undefined;
|
|
91
|
+
const payload = argType.slice(CPP_BRACED_INIT_TYPE_PREFIX.length);
|
|
92
|
+
if (payload === '')
|
|
93
|
+
return undefined;
|
|
94
|
+
const separator = payload.lastIndexOf(':');
|
|
95
|
+
if (separator > 0) {
|
|
96
|
+
const countText = payload.slice(separator + 1);
|
|
97
|
+
if (/^\d+$/.test(countText)) {
|
|
98
|
+
return {
|
|
99
|
+
elementType: payload.slice(0, separator),
|
|
100
|
+
elementCount: Number(countText),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return { elementType: payload };
|
|
105
|
+
}
|
|
106
|
+
function bracedInitConversionRank(paramType, argType, paramTypeClass) {
|
|
107
|
+
const targetBase = bracedInitTargetBase(paramType);
|
|
108
|
+
if (targetBase === 'initializer_list' || targetBase === 'std::initializer_list') {
|
|
109
|
+
return bracedInitValueTypeMatches(paramType, argType, paramTypeClass) ? 0 : Infinity;
|
|
110
|
+
}
|
|
111
|
+
if (BRACED_INIT_CONTAINER_TYPES.has(targetBase)) {
|
|
112
|
+
return bracedInitValueTypeMatches(paramType, argType, paramTypeClass) ? 4 : Infinity;
|
|
113
|
+
}
|
|
114
|
+
return Infinity;
|
|
115
|
+
}
|
|
116
|
+
function bracedInitValueTypeMatches(paramType, argType, paramTypeClass) {
|
|
117
|
+
const valueType = bracedInitTargetValueType(paramType, paramTypeClass);
|
|
118
|
+
if (valueType === undefined)
|
|
119
|
+
return false;
|
|
120
|
+
return isFinite(cppConversionRank(argType.elementType, valueType));
|
|
121
|
+
}
|
|
122
|
+
function bracedInitTargetValueType(paramType, paramTypeClass) {
|
|
123
|
+
return firstTemplateArgument(paramType) ?? paramTypeClass?.templateArguments?.[0];
|
|
124
|
+
}
|
|
125
|
+
function firstTemplateArgument(rawType) {
|
|
126
|
+
const start = rawType.indexOf('<');
|
|
127
|
+
if (start < 0)
|
|
128
|
+
return undefined;
|
|
129
|
+
let depth = 0;
|
|
130
|
+
for (let i = start + 1; i < rawType.length; i++) {
|
|
131
|
+
const ch = rawType[i];
|
|
132
|
+
if (ch === '<') {
|
|
133
|
+
depth++;
|
|
134
|
+
}
|
|
135
|
+
else if (ch === '>') {
|
|
136
|
+
if (depth === 0)
|
|
137
|
+
return bracedInitTargetBase(rawType.slice(start + 1, i));
|
|
138
|
+
depth--;
|
|
139
|
+
}
|
|
140
|
+
else if (ch === ',' && depth === 0) {
|
|
141
|
+
return bracedInitTargetBase(rawType.slice(start + 1, i));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
function bracedInitTargetBase(paramType) {
|
|
147
|
+
return normalizeCppParamType(paramType);
|
|
148
|
+
}
|
|
60
149
|
function isPointer(typeClass) {
|
|
61
150
|
return typeClass?.indirection === 'pointer' && typeClass.pointerDepth > 0;
|
|
62
151
|
}
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* declaration transparently.
|
|
28
28
|
*/
|
|
29
29
|
import { isOverloadAmbiguousAfterNormalization, narrowOverloadCandidates, } from '../../scope-resolution/passes/overload-narrowing.js';
|
|
30
|
-
import { cppConversionRank } from './conversion-rank.js';
|
|
30
|
+
import { CPP_CONVERSION_ONLY_ARG_TYPE_PREFIXES, cppConversionRank } from './conversion-rank.js';
|
|
31
31
|
const inlineNamespaceRangesByFile = new Map();
|
|
32
32
|
const inlineNamespaceScopeIds = new Set();
|
|
33
33
|
function rangeKey(r) {
|
|
@@ -142,7 +142,12 @@ export function resolveCppQualifiedNamespaceMember(receiverName, memberName, par
|
|
|
142
142
|
// can disambiguate via exact-type match and, when available, conversion-rank
|
|
143
143
|
// scoring (`cppConversionRank`). Same-signature ambiguity is still detected
|
|
144
144
|
// by `isOverloadAmbiguousAfterNormalization` below.
|
|
145
|
-
const narrowed = narrowOverloadCandidates(allHits, callsite?.arity, callsite?.argumentTypes, callsite !== undefined
|
|
145
|
+
const narrowed = narrowOverloadCandidates(allHits, callsite?.arity, callsite?.argumentTypes, callsite !== undefined
|
|
146
|
+
? {
|
|
147
|
+
conversionRankFn: cppConversionRank,
|
|
148
|
+
conversionOnlyArgTypePrefixes: CPP_CONVERSION_ONLY_ARG_TYPE_PREFIXES,
|
|
149
|
+
}
|
|
150
|
+
: undefined);
|
|
146
151
|
if (narrowed.length === 1)
|
|
147
152
|
return narrowed[0];
|
|
148
153
|
if (narrowed.length === 0)
|
|
@@ -3,7 +3,7 @@ import { buildMro, defaultLinearize } from '../../scope-resolution/passes/mro.js
|
|
|
3
3
|
import { isOverloadAmbiguousAfterNormalization, narrowOverloadCandidates, } from '../../scope-resolution/passes/overload-narrowing.js';
|
|
4
4
|
import { isClassLike } from '../../scope-resolution/scope/walkers.js';
|
|
5
5
|
import { cppConstraintCompatibility } from './constraint-filter.js';
|
|
6
|
-
import { cppConversionRank } from './conversion-rank.js';
|
|
6
|
+
import { CPP_CONVERSION_ONLY_ARG_TYPE_PREFIXES, cppConversionRank } from './conversion-rank.js';
|
|
7
7
|
const capturedByFile = new Map();
|
|
8
8
|
let directParentsByDefId = new Map();
|
|
9
9
|
let virtualEdges = new Set();
|
|
@@ -193,6 +193,7 @@ function chooseOverload(candidates, callsite) {
|
|
|
193
193
|
const narrowed = narrowOverloadCandidates(candidates, callsite.arity, callsite.argumentTypes, {
|
|
194
194
|
argumentTypeClasses: callsite.argumentTypeClasses,
|
|
195
195
|
conversionRankFn: cppConversionRank,
|
|
196
|
+
conversionOnlyArgTypePrefixes: CPP_CONVERSION_ONLY_ARG_TYPE_PREFIXES,
|
|
196
197
|
constraintCompatibility: cppConstraintCompatibility,
|
|
197
198
|
});
|
|
198
199
|
if (narrowed.length === 1)
|
|
@@ -3,7 +3,7 @@ import { SupportedLanguages } from '../../../../_shared/index.js';
|
|
|
3
3
|
import { populateClassOwnedMembers, tagNamespacePrefixes, } from '../../scope-resolution/scope/walkers.js';
|
|
4
4
|
import { cppProvider } from '../c-cpp.js';
|
|
5
5
|
import { cppArityCompatibility } from './arity.js';
|
|
6
|
-
import { cppConversionRank } from './conversion-rank.js';
|
|
6
|
+
import { CPP_CONVERSION_ONLY_ARG_TYPE_PREFIXES, cppConversionRank } from './conversion-rank.js';
|
|
7
7
|
import { cppMergeBindings } from './merge-bindings.js';
|
|
8
8
|
import { resolveCppImportTarget } from './import-target.js';
|
|
9
9
|
import { scanCppHeaderFiles } from './header-scan.js';
|
|
@@ -205,6 +205,7 @@ export const cppScopeResolver = {
|
|
|
205
205
|
// Disambiguates `f(int)` vs `f(double)` called with `f(2.5)` by scoring
|
|
206
206
|
// each candidate's conversion cost; exact match wins over standard conversion.
|
|
207
207
|
conversionRankFn: cppConversionRank,
|
|
208
|
+
conversionOnlyArgTypePrefixes: CPP_CONVERSION_ONLY_ARG_TYPE_PREFIXES,
|
|
208
209
|
// Range-for element type inference: for (auto& user : users) → bind user to User
|
|
209
210
|
populateRangeBindings: populateCppRangeBindings,
|
|
210
211
|
// C++ method return-type bindings need to be visible from module scope
|
|
@@ -477,12 +477,19 @@ function parseJsonParameterTypeClassesCapture(cap) {
|
|
|
477
477
|
if (typeof o.pointerDepth !== 'number' || !Number.isFinite(o.pointerDepth)) {
|
|
478
478
|
return undefined;
|
|
479
479
|
}
|
|
480
|
-
|
|
480
|
+
const shape = {
|
|
481
481
|
base: o.base,
|
|
482
482
|
cv: o.cv,
|
|
483
483
|
indirection: o.indirection,
|
|
484
484
|
pointerDepth: o.pointerDepth,
|
|
485
|
-
}
|
|
485
|
+
};
|
|
486
|
+
if (Array.isArray(o.templateArguments)) {
|
|
487
|
+
if (!o.templateArguments.every((x) => typeof x === 'string')) {
|
|
488
|
+
return undefined;
|
|
489
|
+
}
|
|
490
|
+
shape.templateArguments = [...o.templateArguments];
|
|
491
|
+
}
|
|
492
|
+
out.push(shape);
|
|
486
493
|
}
|
|
487
494
|
return out;
|
|
488
495
|
}
|
|
@@ -618,6 +618,15 @@ export interface ScopeResolver {
|
|
|
618
618
|
* `cppConversionRank`; other languages define their own if needed.
|
|
619
619
|
*/
|
|
620
620
|
readonly conversionRankFn?: ConversionRankFn;
|
|
621
|
+
/**
|
|
622
|
+
* Optional per-language argument-type prefixes for conversion-only
|
|
623
|
+
* argument sentinels. When ranking cannot find any viable candidate
|
|
624
|
+
* for a multi-overload set containing one of these sentinels, shared
|
|
625
|
+
* narrowing suppresses the ambiguous set instead of falling back to
|
|
626
|
+
* arity-only candidates. Languages without such sentinels leave this
|
|
627
|
+
* undefined.
|
|
628
|
+
*/
|
|
629
|
+
readonly conversionOnlyArgTypePrefixes?: readonly string[];
|
|
621
630
|
/**
|
|
622
631
|
* Optional predicate to identify definitions with file-local linkage
|
|
623
632
|
* (e.g. C `static` functions). When provided, `pickUniqueGlobalCallable`
|
|
@@ -49,6 +49,7 @@ export declare function emitFreeCallFallback(graph: KnowledgeGraph, scopes: Scop
|
|
|
49
49
|
};
|
|
50
50
|
}, callerParsed: ParsedFile, scopes: ScopeResolutionIndexes, parsedFiles: readonly ParsedFile[]) => readonly SymbolDefinition[] | undefined;
|
|
51
51
|
readonly conversionRankFn?: ConversionRankFn;
|
|
52
|
+
readonly conversionOnlyArgTypePrefixes?: readonly string[];
|
|
52
53
|
/** Optional per-language constraint hook threaded into
|
|
53
54
|
* `narrowOverloadCandidates`. Drops candidates whose template
|
|
54
55
|
* constraints (e.g. C++ `enable_if_t`, C++20 `requires`) provably
|
|
@@ -99,7 +100,7 @@ export declare function buildGlobalClassIndex(scopes: ScopeResolutionIndexes): R
|
|
|
99
100
|
* order. Exported for unit testing — the `scopeDefsCache` equivalence is
|
|
100
101
|
* exercised via synthetic stubs in `pick-unique-global-callable.test.ts`.
|
|
101
102
|
*/
|
|
102
|
-
export declare function pickUniqueGlobalCallable(name: string, model: SemanticModel, globalCallablesBySimpleName: ReadonlyMap<string, readonly SymbolDefinition[]>, callerFilePath: string, isFileLocalDef?: (def: SymbolDefinition) => boolean, callArity?: number, isCallerVisible?: (candidate: SymbolDefinition) => boolean, callArgTypes?: readonly string[], callArgTypeClasses?: readonly ParameterTypeClass[], conversionRankFn?: ConversionRankFn, scopeDefsCache?: Map<string, readonly SymbolDefinition[]
|
|
103
|
+
export declare function pickUniqueGlobalCallable(name: string, model: SemanticModel, globalCallablesBySimpleName: ReadonlyMap<string, readonly SymbolDefinition[]>, callerFilePath: string, isFileLocalDef?: (def: SymbolDefinition) => boolean, callArity?: number, isCallerVisible?: (candidate: SymbolDefinition) => boolean, callArgTypes?: readonly string[], callArgTypeClasses?: readonly ParameterTypeClass[], conversionRankFn?: ConversionRankFn, scopeDefsCache?: Map<string, readonly SymbolDefinition[]>, conversionOnlyArgTypePrefixes?: readonly string[]): SymbolDefinition | undefined;
|
|
103
104
|
/** Find a unique workspace-wide class-like def by simple name, for a
|
|
104
105
|
* constructor-form call `Type(...)` whose type lives outside the call
|
|
105
106
|
* site's lexical bindings (a sibling/imported file). Returns the def
|
|
@@ -142,5 +143,6 @@ export declare function pickImplicitThisOverload(site: {
|
|
|
142
143
|
readonly argumentTypeClasses?: readonly import('../../../../_shared/index.js').ParameterTypeClass[];
|
|
143
144
|
}, scopes: ScopeResolutionIndexes, workspaceIndex: WorkspaceResolutionIndex, model: SemanticModel, hookCtx?: {
|
|
144
145
|
readonly conversionRankFn?: ConversionRankFn;
|
|
146
|
+
readonly conversionOnlyArgTypePrefixes?: readonly string[];
|
|
145
147
|
readonly constraintCompatibility?: ScopeResolver['constraintCompatibility'];
|
|
146
148
|
}): SymbolDefinition | undefined;
|
|
@@ -89,6 +89,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
|
|
|
89
89
|
if (fnDef === undefined) {
|
|
90
90
|
fnDef = pickImplicitThisOverload(site, scopes, workspaceIndex, model, {
|
|
91
91
|
conversionRankFn: options.conversionRankFn,
|
|
92
|
+
conversionOnlyArgTypePrefixes: options.conversionOnlyArgTypePrefixes,
|
|
92
93
|
constraintCompatibility: options.constraintCompatibility,
|
|
93
94
|
});
|
|
94
95
|
fnDefFromImplicitThis = fnDef !== undefined;
|
|
@@ -112,6 +113,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
|
|
|
112
113
|
const narrowed = narrowOverloadCandidates(allCallables, site.arity, site.argumentTypes, {
|
|
113
114
|
argumentTypeClasses: site.argumentTypeClasses,
|
|
114
115
|
conversionRankFn: options.conversionRankFn,
|
|
116
|
+
conversionOnlyArgTypePrefixes: options.conversionOnlyArgTypePrefixes,
|
|
115
117
|
constraintCompatibility: options.constraintCompatibility,
|
|
116
118
|
});
|
|
117
119
|
if (narrowed.length === 1) {
|
|
@@ -190,6 +192,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
|
|
|
190
192
|
const narrowed = narrowOverloadCandidates(ordinary, site.arity, site.argumentTypes, {
|
|
191
193
|
argumentTypeClasses: site.argumentTypeClasses,
|
|
192
194
|
conversionRankFn: options.conversionRankFn,
|
|
195
|
+
conversionOnlyArgTypePrefixes: options.conversionOnlyArgTypePrefixes,
|
|
193
196
|
constraintCompatibility: options.constraintCompatibility,
|
|
194
197
|
});
|
|
195
198
|
if (narrowed.length === 1) {
|
|
@@ -240,6 +243,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
|
|
|
240
243
|
const narrowed = narrowOverloadCandidates(merged, site.arity, site.argumentTypes, {
|
|
241
244
|
argumentTypeClasses: site.argumentTypeClasses,
|
|
242
245
|
conversionRankFn: options.conversionRankFn,
|
|
246
|
+
conversionOnlyArgTypePrefixes: options.conversionOnlyArgTypePrefixes,
|
|
243
247
|
constraintCompatibility: options.constraintCompatibility,
|
|
244
248
|
});
|
|
245
249
|
if (narrowed.length === 1) {
|
|
@@ -285,7 +289,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
|
|
|
285
289
|
callerScope: site.inScope,
|
|
286
290
|
scopes,
|
|
287
291
|
})
|
|
288
|
-
: undefined, site.argumentTypes, site.argumentTypeClasses, options.conversionRankFn, scopeDefsCache);
|
|
292
|
+
: undefined, site.argumentTypes, site.argumentTypeClasses, options.conversionRankFn, scopeDefsCache, options.conversionOnlyArgTypePrefixes);
|
|
289
293
|
}
|
|
290
294
|
if (fnDef === undefined)
|
|
291
295
|
continue;
|
|
@@ -442,7 +446,7 @@ export function buildGlobalClassIndex(scopes) {
|
|
|
442
446
|
* order. Exported for unit testing — the `scopeDefsCache` equivalence is
|
|
443
447
|
* exercised via synthetic stubs in `pick-unique-global-callable.test.ts`.
|
|
444
448
|
*/
|
|
445
|
-
export function pickUniqueGlobalCallable(name, model, globalCallablesBySimpleName, callerFilePath, isFileLocalDef, callArity, isCallerVisible, callArgTypes, callArgTypeClasses, conversionRankFn, scopeDefsCache) {
|
|
449
|
+
export function pickUniqueGlobalCallable(name, model, globalCallablesBySimpleName, callerFilePath, isFileLocalDef, callArity, isCallerVisible, callArgTypes, callArgTypeClasses, conversionRankFn, scopeDefsCache, conversionOnlyArgTypePrefixes) {
|
|
446
450
|
// The scope-index candidate list is a pure function of (name, callerFilePath):
|
|
447
451
|
// the same-name bucket is fixed for the pass, the file-local filter depends
|
|
448
452
|
// only on the candidate + callerFilePath, and the logical-key dedup is
|
|
@@ -504,6 +508,7 @@ export function pickUniqueGlobalCallable(name, model, globalCallablesBySimpleNam
|
|
|
504
508
|
const narrowed = narrowOverloadCandidates(scopeDefs, callArity, callArgTypes, {
|
|
505
509
|
argumentTypeClasses: callArgTypeClasses,
|
|
506
510
|
conversionRankFn,
|
|
511
|
+
conversionOnlyArgTypePrefixes,
|
|
507
512
|
});
|
|
508
513
|
if (narrowed.length === 1)
|
|
509
514
|
return narrowed[0];
|
|
@@ -545,6 +550,7 @@ export function pickUniqueGlobalCallable(name, model, globalCallablesBySimpleNam
|
|
|
545
550
|
const narrowed = narrowOverloadCandidates(defs, callArity, callArgTypes, {
|
|
546
551
|
argumentTypeClasses: callArgTypeClasses,
|
|
547
552
|
conversionRankFn,
|
|
553
|
+
conversionOnlyArgTypePrefixes,
|
|
548
554
|
});
|
|
549
555
|
if (narrowed.length === 1)
|
|
550
556
|
return narrowed[0];
|
|
@@ -687,6 +693,7 @@ export function pickImplicitThisOverload(site, scopes, workspaceIndex, model, ho
|
|
|
687
693
|
const candidates = narrowOverloadCandidates(overloads, site.arity, site.argumentTypes, {
|
|
688
694
|
argumentTypeClasses: site.argumentTypeClasses,
|
|
689
695
|
conversionRankFn: hookCtx?.conversionRankFn,
|
|
696
|
+
conversionOnlyArgTypePrefixes: hookCtx?.conversionOnlyArgTypePrefixes,
|
|
690
697
|
constraintCompatibility: hookCtx?.constraintCompatibility,
|
|
691
698
|
});
|
|
692
699
|
if (candidates.length !== 1)
|
|
@@ -69,6 +69,10 @@ export interface OverloadNarrowingHookCtx {
|
|
|
69
69
|
/** Conversion-rank scoring fallback (step 4b). Engages when the
|
|
70
70
|
* exact-type filter rejects every candidate. */
|
|
71
71
|
readonly conversionRankFn?: ConversionRankFn;
|
|
72
|
+
/** Per-language argument-type prefixes whose conversion-rank failures
|
|
73
|
+
* should suppress genuinely ambiguous multi-overload sets instead of
|
|
74
|
+
* falling back to arity-only candidates. */
|
|
75
|
+
readonly conversionOnlyArgTypePrefixes?: readonly string[];
|
|
72
76
|
/** Constraint filter (step 4c). Drops candidates whose template
|
|
73
77
|
* guards (SFINAE `enable_if_t`, C++20 `requires`, future Rust
|
|
74
78
|
* trait bounds, etc.) provably fail at the call site. Three-valued
|
|
@@ -106,6 +106,10 @@ export function narrowOverloadCandidates(overloads, argCount, argTypes, hookCtx)
|
|
|
106
106
|
const ranked = rankByConversion(candidates, argTypes, hookCtx.conversionRankFn, hookCtx.argumentTypeClasses);
|
|
107
107
|
if (ranked.length > 0)
|
|
108
108
|
result = ranked;
|
|
109
|
+
else if (candidates.length > 1 &&
|
|
110
|
+
hasConversionOnlyArgType(argTypes, hookCtx.conversionOnlyArgTypePrefixes)) {
|
|
111
|
+
result = [];
|
|
112
|
+
}
|
|
109
113
|
}
|
|
110
114
|
}
|
|
111
115
|
// Constraint filter (step 4c; Tier-A — SFINAE / `requires` clauses).
|
|
@@ -145,6 +149,11 @@ export function narrowOverloadCandidates(overloads, argCount, argTypes, hookCtx)
|
|
|
145
149
|
}
|
|
146
150
|
return result;
|
|
147
151
|
}
|
|
152
|
+
function hasConversionOnlyArgType(argTypes, prefixes) {
|
|
153
|
+
if (prefixes === undefined || prefixes.length === 0)
|
|
154
|
+
return false;
|
|
155
|
+
return argTypes.some((type) => prefixes.some((prefix) => type.startsWith(prefix)));
|
|
156
|
+
}
|
|
148
157
|
function exactTypeSlotMatches(argType, paramType, argTypeClass, paramTypeClass) {
|
|
149
158
|
if (argType !== paramType)
|
|
150
159
|
return false;
|
|
@@ -47,7 +47,7 @@ import type { ResolutionOutcomeRecorder } from '../resolution-outcome.js';
|
|
|
47
47
|
/** Subset of `ScopeResolver` consumed by this pass. Accepting the
|
|
48
48
|
* subset rather than the full provider keeps tests and partial
|
|
49
49
|
* refactors lighter — callers only need to populate what we read. */
|
|
50
|
-
type ReceiverBoundProviderSubset = Pick<ScopeResolver, 'isSuperReceiver' | 'isSuperReceiverInContext' | 'fieldFallbackOnMethodLookup' | 'collapseMemberCallsByCallerTarget' | 'unwrapCollectionAccessor' | 'hoistTypeBindingsToModule' | 'resolveQualifiedReceiverMember' | 'resolveReceiverMember' | 'resolveThisViaEnclosingClass' | 'conversionRankFn' | 'constraintCompatibility' | 'isStaticOnly'>;
|
|
50
|
+
type ReceiverBoundProviderSubset = Pick<ScopeResolver, 'isSuperReceiver' | 'isSuperReceiverInContext' | 'fieldFallbackOnMethodLookup' | 'collapseMemberCallsByCallerTarget' | 'unwrapCollectionAccessor' | 'hoistTypeBindingsToModule' | 'resolveQualifiedReceiverMember' | 'resolveReceiverMember' | 'resolveThisViaEnclosingClass' | 'conversionRankFn' | 'conversionOnlyArgTypePrefixes' | 'constraintCompatibility' | 'isStaticOnly'>;
|
|
51
51
|
export declare function emitReceiverBoundCalls(graph: KnowledgeGraph, scopes: ScopeResolutionIndexes, parsedFiles: readonly ParsedFile[], nodeLookup: GraphNodeLookup, handledSites: Set<string>, provider: ReceiverBoundProviderSubset, index: WorkspaceResolutionIndex, model: SemanticModel, options?: {
|
|
52
52
|
readonly recordResolutionOutcome?: ResolutionOutcomeRecorder;
|
|
53
53
|
}): number;
|
|
@@ -352,6 +352,7 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
352
352
|
const narrowed = narrowOverloadCandidates(methodOverloads, site.arity, site.argumentTypes, {
|
|
353
353
|
argumentTypeClasses: site.argumentTypeClasses,
|
|
354
354
|
conversionRankFn: provider.conversionRankFn,
|
|
355
|
+
conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
|
|
355
356
|
constraintCompatibility: provider.constraintCompatibility,
|
|
356
357
|
});
|
|
357
358
|
if (isOverloadAmbiguousAfterNormalization(narrowed, site.arity)) {
|
|
@@ -867,6 +868,7 @@ function pickOverload(ownerId, memberName, site, model, provider) {
|
|
|
867
868
|
const candidates = narrowOverloadCandidates(overloads, site.arity, site.argumentTypes, {
|
|
868
869
|
argumentTypeClasses: site.argumentTypeClasses,
|
|
869
870
|
conversionRankFn: provider.conversionRankFn,
|
|
871
|
+
conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
|
|
870
872
|
constraintCompatibility: provider.constraintCompatibility,
|
|
871
873
|
});
|
|
872
874
|
// When narrowing leaves >1 candidate that share identical normalized
|
|
@@ -967,6 +969,7 @@ function pickFirstNonStaticOnly(ownerId, memberName, site, model, provider) {
|
|
|
967
969
|
const candidates = narrowOverloadCandidates(overloads, site.arity, site.argumentTypes, {
|
|
968
970
|
argumentTypeClasses: site.argumentTypeClasses,
|
|
969
971
|
conversionRankFn: provider.conversionRankFn,
|
|
972
|
+
conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
|
|
970
973
|
constraintCompatibility: provider.constraintCompatibility,
|
|
971
974
|
});
|
|
972
975
|
// Same ambiguity handling as `pickOverload`: when normalization
|
|
@@ -1001,6 +1004,7 @@ function recordReceiverOverloadSuppression(record, filePath, site, ownerId, memb
|
|
|
1001
1004
|
const candidates = narrowOverloadCandidates(overloads, site.arity, site.argumentTypes, {
|
|
1002
1005
|
argumentTypeClasses: site.argumentTypeClasses,
|
|
1003
1006
|
conversionRankFn: provider.conversionRankFn,
|
|
1007
|
+
conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
|
|
1004
1008
|
constraintCompatibility: provider.constraintCompatibility,
|
|
1005
1009
|
});
|
|
1006
1010
|
const reason = isOverloadAmbiguousAfterNormalization(candidates, site.arity)
|
|
@@ -446,6 +446,7 @@ export function runScopeResolution(input, provider) {
|
|
|
446
446
|
isCallableVisibleFromCaller: provider.isCallableVisibleFromCaller,
|
|
447
447
|
resolveAdlCandidates: provider.resolveAdlCandidates,
|
|
448
448
|
conversionRankFn: provider.conversionRankFn,
|
|
449
|
+
conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
|
|
449
450
|
constraintCompatibility: provider.constraintCompatibility,
|
|
450
451
|
recordResolutionOutcome,
|
|
451
452
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { extractSimpleTypeName, extractVarName, resolveIterableElementType, methodToTypeArgPosition, } from './shared.js';
|
|
2
|
+
import { CPP_BRACED_INIT_TYPE_PREFIX } from '../languages/cpp/conversion-rank.js';
|
|
2
3
|
const DECLARATION_NODE_TYPES = new Set(['declaration']);
|
|
3
4
|
/** Smart pointer factory function names that create a typed object. */
|
|
4
5
|
const SMART_PTR_FACTORIES = new Set(['make_shared', 'make_unique', 'make_shared_for_overwrite']);
|
|
@@ -447,6 +448,8 @@ const extractForLoopBinding = (node, { scopeEnv, declarationTypeNodes, scope })
|
|
|
447
448
|
/** Infer the type of a literal AST node for C++ overload disambiguation. */
|
|
448
449
|
const inferLiteralType = (node) => {
|
|
449
450
|
switch (node.type) {
|
|
451
|
+
case 'initializer_list':
|
|
452
|
+
return inferBracedInitLiteralType(node);
|
|
450
453
|
case 'number_literal': {
|
|
451
454
|
const t = node.text;
|
|
452
455
|
// Float suffixes
|
|
@@ -475,6 +478,24 @@ const inferLiteralType = (node) => {
|
|
|
475
478
|
return undefined;
|
|
476
479
|
}
|
|
477
480
|
};
|
|
481
|
+
function inferBracedInitLiteralType(node) {
|
|
482
|
+
const elementTypes = [];
|
|
483
|
+
for (const child of node.children) {
|
|
484
|
+
if (child.type === ',' || child.type === '{' || child.type === '}')
|
|
485
|
+
continue;
|
|
486
|
+
const elementType = inferLiteralType(child);
|
|
487
|
+
if (elementType === undefined || elementType.startsWith(CPP_BRACED_INIT_TYPE_PREFIX)) {
|
|
488
|
+
return `${CPP_BRACED_INIT_TYPE_PREFIX}unknown:${elementTypes.length + 1}`;
|
|
489
|
+
}
|
|
490
|
+
elementTypes.push(elementType);
|
|
491
|
+
}
|
|
492
|
+
if (elementTypes.length === 0)
|
|
493
|
+
return `${CPP_BRACED_INIT_TYPE_PREFIX}unknown:0`;
|
|
494
|
+
const first = elementTypes[0];
|
|
495
|
+
return elementTypes.every((type) => type === first)
|
|
496
|
+
? `${CPP_BRACED_INIT_TYPE_PREFIX}${first}:${elementTypes.length}`
|
|
497
|
+
: `${CPP_BRACED_INIT_TYPE_PREFIX}unknown:${elementTypes.length}`;
|
|
498
|
+
}
|
|
478
499
|
/** C++: detect constructor type from smart pointer factory calls (make_shared<Dog>()).
|
|
479
500
|
* Extracts the template type argument as the constructor type for virtual dispatch. */
|
|
480
501
|
const detectCppConstructorType = (node, classNames) => {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import fs from 'fs/promises';
|
|
13
13
|
import path from 'path';
|
|
14
14
|
import { execSync, execFileSync } from 'child_process';
|
|
15
|
-
import { initWikiDb, closeWikiDb, touchWikiDb, getFilesWithExports, getAllFiles, getIntraModuleCallEdges, getInterModuleCallEdges, getProcessesForFiles, getAllProcesses, getInterModuleEdgesForOverview, } from './graph-queries.js';
|
|
15
|
+
import { initWikiDb, closeWikiDb, touchWikiDb, pinWikiDb, getFilesWithExports, getAllFiles, getIntraModuleCallEdges, getInterModuleCallEdges, getProcessesForFiles, getAllProcesses, getInterModuleEdgesForOverview, } from './graph-queries.js';
|
|
16
16
|
import { generateHTMLViewer } from './html-viewer.js';
|
|
17
17
|
import { sanitizeMermaidMarkdown } from './mermaid-sanitizer.js';
|
|
18
18
|
import { callLLM, estimateTokens, } from './llm-client.js';
|
|
@@ -183,6 +183,7 @@ export class WikiGenerator {
|
|
|
183
183
|
}
|
|
184
184
|
// Init graph
|
|
185
185
|
this.onProgress('init', 2, 'Connecting to knowledge graph...');
|
|
186
|
+
const releaseWikiDbPin = pinWikiDb();
|
|
186
187
|
await initWikiDb(this.lbugPath);
|
|
187
188
|
let result;
|
|
188
189
|
try {
|
|
@@ -201,6 +202,7 @@ export class WikiGenerator {
|
|
|
201
202
|
}
|
|
202
203
|
}
|
|
203
204
|
finally {
|
|
205
|
+
releaseWikiDbPin();
|
|
204
206
|
await closeWikiDb();
|
|
205
207
|
}
|
|
206
208
|
// Always generate the HTML viewer after wiki content changes
|
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
* Touch the wiki DB connection to prevent idle timeout during long LLM calls.
|
|
9
9
|
*/
|
|
10
10
|
export declare function touchWikiDb(): void;
|
|
11
|
+
/**
|
|
12
|
+
* Keep the wiki DB resident for a full generation run. Wiki generation can spend
|
|
13
|
+
* minutes inside LLM calls, and the pooled DB must survive both idle cleanup and
|
|
14
|
+
* unrelated LRU pressure until the run reaches its final graph queries.
|
|
15
|
+
*/
|
|
16
|
+
export declare function pinWikiDb(): () => void;
|
|
11
17
|
export interface FileWithExports {
|
|
12
18
|
filePath: string;
|
|
13
19
|
symbols: Array<{
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Encapsulated Cypher queries against the GitNexus knowledge graph.
|
|
5
5
|
* Uses the MCP-style pooled lbug-adapter for connection management.
|
|
6
6
|
*/
|
|
7
|
-
import { initLbug, executeQuery, closeLbug, touchRepo } from '../lbug/pool-adapter.js';
|
|
7
|
+
import { initLbug, executeQuery, closeLbug, touchRepo, pinRepo } from '../lbug/pool-adapter.js';
|
|
8
8
|
const REPO_ID = '__wiki__';
|
|
9
9
|
/**
|
|
10
10
|
* Touch the wiki DB connection to prevent idle timeout during long LLM calls.
|
|
@@ -12,6 +12,14 @@ const REPO_ID = '__wiki__';
|
|
|
12
12
|
export function touchWikiDb() {
|
|
13
13
|
touchRepo(REPO_ID);
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Keep the wiki DB resident for a full generation run. Wiki generation can spend
|
|
17
|
+
* minutes inside LLM calls, and the pooled DB must survive both idle cleanup and
|
|
18
|
+
* unrelated LRU pressure until the run reaches its final graph queries.
|
|
19
|
+
*/
|
|
20
|
+
export function pinWikiDb() {
|
|
21
|
+
return pinRepo(REPO_ID);
|
|
22
|
+
}
|
|
15
23
|
/**
|
|
16
24
|
* Initialize the LadybugDB connection for wiki generation.
|
|
17
25
|
*/
|
package/package.json
CHANGED