gitnexus 1.6.6-rc.120 → 1.6.6-rc.121
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/core/ingestion/languages/go/captures.js +18 -1
- package/dist/core/ingestion/languages/go/interface-impls.js +36 -5
- package/dist/core/ingestion/languages/go/query.js +3 -3
- package/dist/core/ingestion/languages/go/type-binding.d.ts +1 -0
- package/dist/core/ingestion/languages/go/type-binding.js +12 -3
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import { recordGoCacheHit, recordGoCacheMiss } from './cache-stats.js';
|
|
|
4
4
|
import { computeGoCallArity, computeGoDeclarationArity } from './arity-metadata.js';
|
|
5
5
|
import { splitGoImportStatement } from './import-decomposer.js';
|
|
6
6
|
import { synthesizeGoReceiverBinding } from './receiver-binding.js';
|
|
7
|
-
import { synthesizeGoTypeBindings } from './type-binding.js';
|
|
7
|
+
import { synthesizeGoTypeBindings, extractSimpleTypeNameText } from './type-binding.js';
|
|
8
8
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
9
9
|
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
10
10
|
export function emitGoScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
@@ -69,6 +69,7 @@ export function emitGoScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
|
69
69
|
}
|
|
70
70
|
if (isRawMultiAssignTypeBinding(nodeMap))
|
|
71
71
|
continue;
|
|
72
|
+
normalizeGenericConstructorCapture(nodeMap, grouped);
|
|
72
73
|
const declAnchorNode = nodeMap['@declaration.function'] ?? nodeMap['@declaration.method'];
|
|
73
74
|
if (declAnchorNode !== undefined) {
|
|
74
75
|
// @declaration.function / @declaration.method are captured directly on
|
|
@@ -306,6 +307,22 @@ function nodeRangeEquals(a, b) {
|
|
|
306
307
|
a.endPosition.row === b.endPosition.row &&
|
|
307
308
|
a.endPosition.column === b.endPosition.column);
|
|
308
309
|
}
|
|
310
|
+
function normalizeGenericConstructorCapture(nodeMap, grouped) {
|
|
311
|
+
const typeNode = grouped['@type-binding.constructor'] !== undefined ? nodeMap['@type-binding.type'] : undefined;
|
|
312
|
+
if (typeNode !== undefined && typeNode.type === 'generic_type') {
|
|
313
|
+
const base = typeNode.childForFieldName('type');
|
|
314
|
+
if (base !== null) {
|
|
315
|
+
grouped['@type-binding.type'] = syntheticCapture('@type-binding.type', base, extractSimpleTypeNameText(base));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const referenceNode = grouped['@reference.call.constructor'] !== undefined ? nodeMap['@reference.name'] : undefined;
|
|
319
|
+
if (referenceNode !== undefined && referenceNode.type === 'generic_type') {
|
|
320
|
+
const base = referenceNode.childForFieldName('type');
|
|
321
|
+
if (base !== null) {
|
|
322
|
+
grouped['@reference.name'] = syntheticCapture('@reference.name', base, extractSimpleTypeNameText(base));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
309
326
|
function isRawMultiAssignTypeBinding(nodeMap) {
|
|
310
327
|
const anchor = nodeMap['@type-binding.constructor'] ??
|
|
311
328
|
nodeMap['@type-binding.call-return'] ??
|
|
@@ -203,8 +203,13 @@ function collectStructMethodEntries(structId, indexes, visiting, cache) {
|
|
|
203
203
|
}
|
|
204
204
|
function collectInterfaceMethodSet(iface, indexes, visiting, cache) {
|
|
205
205
|
const cached = cache.get(iface.nodeId);
|
|
206
|
+
// NOTE: Returns a direct reference to the cached map. Callers (the detection
|
|
207
|
+
// loop in detectGoInterfaceImplementationsFromIndexes) only READ the result
|
|
208
|
+
// (keys/values passed to candidateStructIdsFor and methodSetSatisfies). If a
|
|
209
|
+
// future caller needs to mutate the returned map, it must clone first — the
|
|
210
|
+
// cache entry is shared and must remain immutable after this function returns.
|
|
206
211
|
if (cached !== undefined)
|
|
207
|
-
return
|
|
212
|
+
return cached;
|
|
208
213
|
if (visiting.has(iface.nodeId))
|
|
209
214
|
return undefined;
|
|
210
215
|
visiting.add(iface.nodeId);
|
|
@@ -224,6 +229,8 @@ function collectInterfaceMethodSet(iface, indexes, visiting, cache) {
|
|
|
224
229
|
mergeMethodSet(merged, embeddedMethods);
|
|
225
230
|
}
|
|
226
231
|
visiting.delete(iface.nodeId);
|
|
232
|
+
// Store a clone in the cache so the returned `merged` reference is independent.
|
|
233
|
+
// This protects the cache from mutation if a caller modifies the return value.
|
|
227
234
|
cache.set(iface.nodeId, cloneMethodSet(merged));
|
|
228
235
|
return merged;
|
|
229
236
|
}
|
|
@@ -238,15 +245,31 @@ function embeddedInterfacesFor(iface, indexes) {
|
|
|
238
245
|
return embedded;
|
|
239
246
|
}
|
|
240
247
|
function candidateStructIdsFor(required, indexes) {
|
|
241
|
-
let
|
|
248
|
+
let result;
|
|
242
249
|
for (const name of required.keys()) {
|
|
243
250
|
const candidates = indexes.structIdsByMethodName.get(name);
|
|
244
251
|
if (candidates === undefined)
|
|
245
252
|
return [];
|
|
246
|
-
if (
|
|
247
|
-
|
|
253
|
+
if (result === undefined) {
|
|
254
|
+
// First method name: start with its full candidate set (copy to avoid
|
|
255
|
+
// corrupting the shared index).
|
|
256
|
+
result = new Set(candidates);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
// Intersect: keep only struct IDs present in this method's candidate set.
|
|
260
|
+
// Iterate a snapshot to avoid mutating while iterating.
|
|
261
|
+
const toDelete = [];
|
|
262
|
+
for (const id of result) {
|
|
263
|
+
if (!candidates.has(id))
|
|
264
|
+
toDelete.push(id);
|
|
265
|
+
}
|
|
266
|
+
for (const id of toDelete)
|
|
267
|
+
result.delete(id);
|
|
268
|
+
}
|
|
269
|
+
if (result.size === 0)
|
|
270
|
+
return []; // Early exit: no struct has all required methods
|
|
248
271
|
}
|
|
249
|
-
return
|
|
272
|
+
return result === undefined ? indexes.structsById.keys() : result;
|
|
250
273
|
}
|
|
251
274
|
function resolveEmbeddedInterface(site, indexes) {
|
|
252
275
|
const bound = resolveInheritanceBaseInScope(site.inScope, site.name, indexes.scopeIndexes);
|
|
@@ -322,6 +345,14 @@ function methodSetSatisfies(actual, required, signatureContextByDefId) {
|
|
|
322
345
|
if (actualOverloads === undefined)
|
|
323
346
|
return false;
|
|
324
347
|
for (const requiredMethod of requiredOverloads) {
|
|
348
|
+
// Fast arity pre-filter: if the required method has a known parameter
|
|
349
|
+
// count, reject immediately when no actual overload matches it. This
|
|
350
|
+
// avoids the expensive signature normalization loop for obvious mismatches.
|
|
351
|
+
if (requiredMethod.parameterCount !== undefined) {
|
|
352
|
+
if (!actualOverloads.some((a) => a.parameterCount === requiredMethod.parameterCount)) {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
325
356
|
if (!hasCompatibleMethod(actualOverloads, requiredMethod, signatureContextByDefId)) {
|
|
326
357
|
return false;
|
|
327
358
|
}
|
|
@@ -84,7 +84,7 @@ const GO_SCOPE_QUERY = `
|
|
|
84
84
|
left: (expression_list (identifier) @type-binding.name)
|
|
85
85
|
right: (expression_list
|
|
86
86
|
(composite_literal
|
|
87
|
-
type: [(type_identifier) (qualified_type)] @type-binding.type))) @type-binding.constructor
|
|
87
|
+
type: [(type_identifier) (qualified_type) (generic_type)] @type-binding.type))) @type-binding.constructor
|
|
88
88
|
|
|
89
89
|
;; Type bindings — pointer constructor (:= &T{})
|
|
90
90
|
(short_var_declaration
|
|
@@ -93,7 +93,7 @@ const GO_SCOPE_QUERY = `
|
|
|
93
93
|
(unary_expression
|
|
94
94
|
"&"
|
|
95
95
|
operand: (composite_literal
|
|
96
|
-
type: [(type_identifier) (qualified_type)] @type-binding.type)))) @type-binding.constructor
|
|
96
|
+
type: [(type_identifier) (qualified_type) (generic_type)] @type-binding.type)))) @type-binding.constructor
|
|
97
97
|
|
|
98
98
|
;; Type bindings — type assertion (:= s.(T))
|
|
99
99
|
(short_var_declaration
|
|
@@ -168,7 +168,7 @@ const GO_SCOPE_QUERY = `
|
|
|
168
168
|
|
|
169
169
|
;; References — constructor calls (T{})
|
|
170
170
|
(composite_literal
|
|
171
|
-
type: [(type_identifier) (qualified_type)] @reference.name) @reference.call.constructor
|
|
171
|
+
type: [(type_identifier) (qualified_type) (generic_type)] @reference.name) @reference.call.constructor
|
|
172
172
|
|
|
173
173
|
;; References — field reads
|
|
174
174
|
(selector_expression
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { CaptureMatch } from '../../../../_shared/index.js';
|
|
2
2
|
import { type SyntaxNode } from '../../utils/ast-helpers.js';
|
|
3
3
|
export declare function synthesizeGoTypeBindings(rootNode: SyntaxNode): CaptureMatch[];
|
|
4
|
+
export declare function extractSimpleTypeNameText(node: SyntaxNode): string;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { syntheticCapture } from '../../utils/ast-helpers.js';
|
|
2
|
+
const COMPOSITE_LITERAL_TYPE_NODE_TYPES = new Set([
|
|
3
|
+
'type_identifier',
|
|
4
|
+
'qualified_type',
|
|
5
|
+
'generic_type',
|
|
6
|
+
]);
|
|
2
7
|
export function synthesizeGoTypeBindings(rootNode) {
|
|
3
8
|
const out = [];
|
|
4
9
|
for (const node of rootNode.descendantsOfType('var_spec')) {
|
|
@@ -206,18 +211,22 @@ function synthesizeElementAccessBindings(rootNode, out) {
|
|
|
206
211
|
}
|
|
207
212
|
}
|
|
208
213
|
}
|
|
209
|
-
function extractSimpleTypeNameText(node) {
|
|
214
|
+
export function extractSimpleTypeNameText(node) {
|
|
210
215
|
if (node.type === 'qualified_type') {
|
|
211
216
|
const parts = node.text.split('.');
|
|
212
217
|
return parts[parts.length - 1] ?? node.text;
|
|
213
218
|
}
|
|
219
|
+
if (node.type === 'generic_type') {
|
|
220
|
+
const base = node.childForFieldName('type');
|
|
221
|
+
return base === null ? node.text : extractSimpleTypeNameText(base);
|
|
222
|
+
}
|
|
214
223
|
return node.text;
|
|
215
224
|
}
|
|
216
225
|
/** Extract the type/signature node from a RHS expression. */
|
|
217
226
|
function extractCompositeLiteralTypeNode(expr) {
|
|
218
227
|
if (expr.type === 'composite_literal') {
|
|
219
228
|
return (expr.childForFieldName('type') ??
|
|
220
|
-
expr.namedChildren.find((c) =>
|
|
229
|
+
expr.namedChildren.find((c) => COMPOSITE_LITERAL_TYPE_NODE_TYPES.has(c.type)) ??
|
|
221
230
|
null);
|
|
222
231
|
}
|
|
223
232
|
if (expr.type === 'unary_expression') {
|
|
@@ -229,7 +238,7 @@ function extractCompositeLiteralTypeNode(expr) {
|
|
|
229
238
|
function extractTypeNode(expr) {
|
|
230
239
|
if (expr.type === 'composite_literal') {
|
|
231
240
|
return (expr.childForFieldName('type') ??
|
|
232
|
-
expr.namedChildren.find((c) =>
|
|
241
|
+
expr.namedChildren.find((c) => COMPOSITE_LITERAL_TYPE_NODE_TYPES.has(c.type)) ??
|
|
233
242
|
null);
|
|
234
243
|
}
|
|
235
244
|
if (expr.type === 'unary_expression') {
|
package/package.json
CHANGED