@lzehrung/codegraph 2.3.27 → 2.3.29
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/codegraph-skill/codegraph/SKILL.md +1 -0
- package/dist/agent/explain.d.ts +9 -1
- package/dist/agent/explain.d.ts.map +1 -1
- package/dist/agent/explain.js +18 -1
- package/dist/agent/explain.js.map +1 -1
- package/dist/agent/refactor-plan.d.ts +2 -0
- package/dist/agent/refactor-plan.d.ts.map +1 -1
- package/dist/agent/refactor-plan.js +11 -0
- package/dist/agent/refactor-plan.js.map +1 -1
- package/dist/agent/rename-preview.d.ts.map +1 -1
- package/dist/agent/rename-preview.js +49 -11
- package/dist/agent/rename-preview.js.map +1 -1
- package/dist/agent-tools.d.ts +2 -1
- package/dist/agent-tools.d.ts.map +1 -1
- package/dist/agent-tools.js +8 -0
- package/dist/agent-tools.js.map +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js.map +1 -1
- package/dist/bin/cli.js +3236 -1275
- package/dist/bin/query-index-worker.js +151 -29
- package/dist/cli/navigation.d.ts.map +1 -1
- package/dist/cli/navigation.js +4 -0
- package/dist/cli/navigation.js.map +1 -1
- package/dist/graphs/edge-resolution.d.ts.map +1 -1
- package/dist/graphs/edge-resolution.js +5 -0
- package/dist/graphs/edge-resolution.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/ast.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/ast.js +3 -0
- package/dist/graphs/symbol-graph-detailed/ast.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/edge-passes.js +40 -6
- package/dist/graphs/symbol-graph-detailed/edge-passes.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/receiver-calls.js +8 -1
- package/dist/graphs/symbol-graph-detailed/receiver-calls.js.map +1 -1
- package/dist/impact/analyzer.d.ts.map +1 -1
- package/dist/impact/analyzer.js +82 -4
- package/dist/impact/analyzer.js.map +1 -1
- package/dist/impact/call-compatibility.js +3 -3
- package/dist/impact/call-compatibility.js.map +1 -1
- package/dist/impact/direct.js +1 -1
- package/dist/impact/direct.js.map +1 -1
- package/dist/impact/map.d.ts.map +1 -1
- package/dist/impact/map.js +58 -1
- package/dist/impact/map.js.map +1 -1
- package/dist/impact/member-resolution-coverage.d.ts.map +1 -1
- package/dist/impact/member-resolution-coverage.js +1 -4
- package/dist/impact/member-resolution-coverage.js.map +1 -1
- package/dist/impact/reference-cache.d.ts +1 -0
- package/dist/impact/reference-cache.d.ts.map +1 -1
- package/dist/impact/reference-cache.js +44 -18
- package/dist/impact/reference-cache.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
- package/dist/indexer/build-cache/module-cache.js +30 -0
- package/dist/indexer/build-cache/module-cache.js.map +1 -1
- package/dist/indexer/build-cache/options.d.ts +17 -2
- package/dist/indexer/build-cache/options.d.ts.map +1 -1
- package/dist/indexer/build-cache/options.js +17 -2
- package/dist/indexer/build-cache/options.js.map +1 -1
- package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
- package/dist/indexer/build-cache/project-snapshot.js +60 -5
- package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
- package/dist/indexer/import-types.d.ts +14 -1
- package/dist/indexer/import-types.d.ts.map +1 -1
- package/dist/indexer/imports/binding-ranges.d.ts +50 -0
- package/dist/indexer/imports/binding-ranges.d.ts.map +1 -0
- package/dist/indexer/imports/binding-ranges.js +297 -0
- package/dist/indexer/imports/binding-ranges.js.map +1 -0
- package/dist/indexer/imports/js-text-imports.d.ts +4 -0
- package/dist/indexer/imports/js-text-imports.d.ts.map +1 -1
- package/dist/indexer/imports/js-text-imports.js +210 -48
- package/dist/indexer/imports/js-text-imports.js.map +1 -1
- package/dist/indexer/imports/language-specific.d.ts +3 -0
- package/dist/indexer/imports/language-specific.d.ts.map +1 -1
- package/dist/indexer/imports/language-specific.js +127 -24
- package/dist/indexer/imports/language-specific.js.map +1 -1
- package/dist/indexer/imports/native-captures.d.ts.map +1 -1
- package/dist/indexer/imports/native-captures.js +52 -30
- package/dist/indexer/imports/native-captures.js.map +1 -1
- package/dist/indexer/imports/python.d.ts +2 -0
- package/dist/indexer/imports/python.d.ts.map +1 -1
- package/dist/indexer/imports/python.js +55 -18
- package/dist/indexer/imports/python.js.map +1 -1
- package/dist/indexer/imports.d.ts.map +1 -1
- package/dist/indexer/imports.js +15 -1
- package/dist/indexer/imports.js.map +1 -1
- package/dist/indexer/locals-and-exports.d.ts.map +1 -1
- package/dist/indexer/locals-and-exports.js +3 -0
- package/dist/indexer/locals-and-exports.js.map +1 -1
- package/dist/indexer/navigation-goto.d.ts +1 -1
- package/dist/indexer/navigation-goto.d.ts.map +1 -1
- package/dist/indexer/navigation-goto.js +397 -17
- package/dist/indexer/navigation-goto.js.map +1 -1
- package/dist/indexer/navigation-references.d.ts +23 -2
- package/dist/indexer/navigation-references.d.ts.map +1 -1
- package/dist/indexer/navigation-references.js +196 -4
- package/dist/indexer/navigation-references.js.map +1 -1
- package/dist/indexer/navigation.d.ts +9 -3
- package/dist/indexer/navigation.d.ts.map +1 -1
- package/dist/indexer/navigation.js +164 -41
- package/dist/indexer/navigation.js.map +1 -1
- package/dist/indexer/scope.d.ts.map +1 -1
- package/dist/indexer/scope.js +18 -0
- package/dist/indexer/scope.js.map +1 -1
- package/dist/indexer/symbols.d.ts +1 -0
- package/dist/indexer/symbols.d.ts.map +1 -1
- package/dist/indexer/types.d.ts +10 -0
- package/dist/indexer/types.d.ts.map +1 -1
- package/dist/indexer.d.ts +1 -1
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js.map +1 -1
- package/dist/languages/definitions/cpp.d.ts.map +1 -1
- package/dist/languages/definitions/cpp.js +28 -1
- package/dist/languages/definitions/cpp.js.map +1 -1
- package/dist/languages/definitions/csharp.js +1 -1
- package/dist/languages/definitions/csharp.js.map +1 -1
- package/dist/languages/definitions/javascript.d.ts.map +1 -1
- package/dist/languages/definitions/javascript.js +10 -2
- package/dist/languages/definitions/javascript.js.map +1 -1
- package/dist/languages/definitions/php.d.ts.map +1 -1
- package/dist/languages/definitions/php.js +15 -8
- package/dist/languages/definitions/php.js.map +1 -1
- package/dist/languages/definitions/python.d.ts +5 -1
- package/dist/languages/definitions/python.d.ts.map +1 -1
- package/dist/languages/definitions/python.js +50 -1
- package/dist/languages/definitions/python.js.map +1 -1
- package/dist/languages/definitions/scss.d.ts.map +1 -1
- package/dist/languages/definitions/scss.js +23 -1
- package/dist/languages/definitions/scss.js.map +1 -1
- package/dist/languages/definitions/typescript.d.ts.map +1 -1
- package/dist/languages/definitions/typescript.js +43 -6
- package/dist/languages/definitions/typescript.js.map +1 -1
- package/dist/languages/definitions/zig.d.ts.map +1 -1
- package/dist/languages/definitions/zig.js +10 -3
- package/dist/languages/definitions/zig.js.map +1 -1
- package/dist/languages/import-statement-parsers.d.ts +3 -0
- package/dist/languages/import-statement-parsers.d.ts.map +1 -1
- package/dist/languages/import-statement-parsers.js +4 -0
- package/dist/languages/import-statement-parsers.js.map +1 -1
- package/dist/mcp/handlers.d.ts +2 -1
- package/dist/mcp/handlers.d.ts.map +1 -1
- package/dist/mcp/handlers.js +15 -1
- package/dist/mcp/handlers.js.map +1 -1
- package/dist/review/summaries.d.ts.map +1 -1
- package/dist/review/summaries.js +11 -19
- package/dist/review/summaries.js.map +1 -1
- package/dist/review/types.d.ts +2 -1
- package/dist/review/types.d.ts.map +1 -1
- package/dist/review/types.js.map +1 -1
- package/dist/session.d.ts +2 -9
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/dist/sql/graph.d.ts +1 -1
- package/dist/sql/graph.d.ts.map +1 -1
- package/dist/sql/graph.js.map +1 -1
- package/dist/sql/lookup.d.ts +7 -0
- package/dist/sql/lookup.d.ts.map +1 -1
- package/dist/sql/lookup.js +17 -0
- package/dist/sql/lookup.js.map +1 -1
- package/dist/sql/navigation.d.ts +6 -1
- package/dist/sql/navigation.d.ts.map +1 -1
- package/dist/sql/navigation.js +35 -3
- package/dist/sql/navigation.js.map +1 -1
- package/dist/sql/source-graph.d.ts +2 -0
- package/dist/sql/source-graph.d.ts.map +1 -1
- package/dist/sql/source-graph.js +20 -1
- package/dist/sql/source-graph.js.map +1 -1
- package/dist/util/comments.d.ts +10 -0
- package/dist/util/comments.d.ts.map +1 -1
- package/dist/util/comments.js +43 -2
- package/dist/util/comments.js.map +1 -1
- package/dist/util/lines.d.ts +2 -0
- package/dist/util/lines.d.ts.map +1 -1
- package/dist/util/lines.js +14 -0
- package/dist/util/lines.js.map +1 -1
- package/dist/util/resolution/csharp.d.ts +7 -0
- package/dist/util/resolution/csharp.d.ts.map +1 -0
- package/dist/util/resolution/csharp.js +189 -0
- package/dist/util/resolution/csharp.js.map +1 -0
- package/dist/util/resolution.d.ts.map +1 -1
- package/dist/util/resolution.js +2 -0
- package/dist/util/resolution.js.map +1 -1
- package/docs/mcp.md +1 -1
- package/package.json +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isJsTsLanguage } from "../languages/js-family.js";
|
|
2
|
+
import { isPythonReceiverAttributeAssignmentName } from "../languages/definitions/python.js";
|
|
2
3
|
import { sliceText } from "../util/ast.js";
|
|
3
4
|
import { fileIdentityKey } from "../util/paths.js";
|
|
4
5
|
import { getMemberAccessParts, getNavigationExpressionProperty, isMemberAccessNode, memberAccessTraversalTypes, } from "../util/member-access.js";
|
|
@@ -6,6 +7,7 @@ import { CSHARP_IDENTIFIER_SOURCE, JAVA_IDENTIFIER_SOURCE, XID_IDENTIFIER_SOURCE
|
|
|
6
7
|
import { ensureParsedContext } from "./parse-context.js";
|
|
7
8
|
import { okGoToResult } from "./navigation-provenance.js";
|
|
8
9
|
import { resolveExport, resolveImported } from "./navigation-resolve.js";
|
|
10
|
+
import { SymbolKind, } from "./types.js";
|
|
9
11
|
const RUBY_CONSTANT_SOURCE = String.raw `(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
|
|
10
12
|
const CSHARP_CONSTANT_SOURCE = String.raw `(?=@?\p{Lu})${CSHARP_IDENTIFIER_SOURCE}`;
|
|
11
13
|
const JAVA_CONSTANT_SOURCE = String.raw `(?=\p{Lu})${JAVA_IDENTIFIER_SOURCE}`;
|
|
@@ -133,6 +135,16 @@ export async function resolveMemberAccessDefinition(params) {
|
|
|
133
135
|
(sup.id === "rust" && /^(?:self|Self)$/.test(receiverName));
|
|
134
136
|
if (obj && prop && node.id === prop.id && (supportsReceiverMemberResolution(sup.id) || implicitClassReceiver)) {
|
|
135
137
|
const member = sliceText(prop, source);
|
|
138
|
+
if (sup.id === "python") {
|
|
139
|
+
const memberDef = await resolvePythonReceiverMember(index, mod, node, obj, member, source, sup, resolveExpression);
|
|
140
|
+
if (!memberDef)
|
|
141
|
+
return null;
|
|
142
|
+
return okGoToResult(index, memberDef, {
|
|
143
|
+
via: { exportedName: member },
|
|
144
|
+
resolution: "member-access",
|
|
145
|
+
confidence: "medium",
|
|
146
|
+
});
|
|
147
|
+
}
|
|
136
148
|
if (!sup.membersAreImplicitlyInScope && implicitClassReceiver) {
|
|
137
149
|
const classContainer = findEnclosingClassContainer(node);
|
|
138
150
|
const memberDef = classContainer
|
|
@@ -146,8 +158,9 @@ export async function resolveMemberAccessDefinition(params) {
|
|
|
146
158
|
});
|
|
147
159
|
}
|
|
148
160
|
}
|
|
149
|
-
const
|
|
150
|
-
if (
|
|
161
|
+
const receiver = await resolveReceiverDefinition(obj, source, sup, resolveExpression);
|
|
162
|
+
if (receiver) {
|
|
163
|
+
const objDef = receiver.def;
|
|
151
164
|
const targetContext = await ensureParsedContext(objDef.file, undefined, index.languageExtensions);
|
|
152
165
|
const start = objDef.range.start;
|
|
153
166
|
const targetPosition = {
|
|
@@ -156,13 +169,27 @@ export async function resolveMemberAccessDefinition(params) {
|
|
|
156
169
|
};
|
|
157
170
|
const nameNode = targetContext.tree.rootNode.descendantForPosition(targetPosition, targetPosition);
|
|
158
171
|
const container = nameNode.parent;
|
|
172
|
+
if (receiver.runtimeTypeOnly &&
|
|
173
|
+
container &&
|
|
174
|
+
container.type !== "enum_declaration" &&
|
|
175
|
+
container.type !== "internal_module" &&
|
|
176
|
+
container.type !== "module") {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
159
179
|
if (container) {
|
|
160
180
|
const targetModule = index.byFile.get(fileIdentityKey(objDef.file));
|
|
161
181
|
if (targetModule) {
|
|
162
182
|
const normalizeIdentifier = targetContext.sup.normalizeIdentifier;
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
183
|
+
let memberDef;
|
|
184
|
+
if (receiver.runtimeTypeOnly) {
|
|
185
|
+
memberDef = findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier);
|
|
186
|
+
}
|
|
187
|
+
else if (targetContext.sup.id === "java") {
|
|
188
|
+
memberDef = findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
memberDef = findReceiverMemberDefinition(targetModule.locals, member, objDef, container, targetContext, normalizeIdentifier, receiver.memberScope);
|
|
192
|
+
}
|
|
166
193
|
if (memberDef) {
|
|
167
194
|
return okGoToResult(index, memberDef, {
|
|
168
195
|
via: { exportedName: member },
|
|
@@ -206,17 +233,24 @@ async function resolveReceiverDefinition(obj, source, sup, resolveExpression) {
|
|
|
206
233
|
if (constructor) {
|
|
207
234
|
const result = await resolveExpression(constructor);
|
|
208
235
|
if (result?.kind === "resolved") {
|
|
209
|
-
return
|
|
236
|
+
return {
|
|
237
|
+
def: result.def,
|
|
238
|
+
memberScope: isJsTsLanguage(sup.id) ? "instance" : "any",
|
|
239
|
+
};
|
|
210
240
|
}
|
|
211
241
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
242
|
+
const direct = await resolveExpression(obj);
|
|
243
|
+
if (isJsTsLanguage(sup.id) && sup.nodeTypes.identifier.includes(obj.type)) {
|
|
244
|
+
if (direct?.kind === "resolved" && direct.def.kind === SymbolKind.Class) {
|
|
245
|
+
return { def: direct.def, memberScope: "static" };
|
|
215
246
|
}
|
|
247
|
+
if (direct?.kind === "resolved" && direct.def.kind === SymbolKind.TypeAlias) {
|
|
248
|
+
return { def: direct.def, memberScope: "any", runtimeTypeOnly: true };
|
|
249
|
+
}
|
|
250
|
+
return null;
|
|
216
251
|
}
|
|
217
|
-
const direct = await resolveExpression(obj);
|
|
218
252
|
if (direct?.kind === "resolved") {
|
|
219
|
-
return direct.def;
|
|
253
|
+
return { def: direct.def, memberScope: "any" };
|
|
220
254
|
}
|
|
221
255
|
return null;
|
|
222
256
|
}
|
|
@@ -275,6 +309,7 @@ const BINDING_CONTAINER_TYPES = new Set([
|
|
|
275
309
|
"block",
|
|
276
310
|
"function_declaration",
|
|
277
311
|
"function_item",
|
|
312
|
+
"function_definition",
|
|
278
313
|
"function",
|
|
279
314
|
"function_expression",
|
|
280
315
|
"arrow_function",
|
|
@@ -289,6 +324,9 @@ const BINDING_DECLARATION_TYPES = new Set([
|
|
|
289
324
|
"formal_parameter",
|
|
290
325
|
"required_parameter",
|
|
291
326
|
"optional_parameter",
|
|
327
|
+
"parameter_declaration",
|
|
328
|
+
"short_var_declaration",
|
|
329
|
+
"var_spec",
|
|
292
330
|
]);
|
|
293
331
|
function findVisiblePriorNewConstructor(receiver, receiverName, source, sup) {
|
|
294
332
|
let current = receiver;
|
|
@@ -355,6 +393,16 @@ function findPriorNewConstructorInContainer(node, receiver, receiverName, source
|
|
|
355
393
|
constructor = candidate;
|
|
356
394
|
}
|
|
357
395
|
}
|
|
396
|
+
if (sup.id === "go" && (current.type === "short_var_declaration" || current.type === "var_spec")) {
|
|
397
|
+
const candidate = constructorFromGoBinding(current, receiverName, source, sup);
|
|
398
|
+
if (candidate) {
|
|
399
|
+
if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
|
|
400
|
+
constructor = null;
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
403
|
+
constructor = candidate;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
358
406
|
for (const child of current.namedChildren) {
|
|
359
407
|
if (!visit(child)) {
|
|
360
408
|
return false;
|
|
@@ -383,6 +431,8 @@ function bindingContainerDeclaresNameBefore(node, receiver, receiverName, source
|
|
|
383
431
|
return false;
|
|
384
432
|
}
|
|
385
433
|
if (BINDING_DECLARATION_TYPES.has(current.type)) {
|
|
434
|
+
if (goBindingDeclaresName(current, receiverName, source, sup))
|
|
435
|
+
return true;
|
|
386
436
|
const name = current.childForFieldName("name") ?? current.child(0);
|
|
387
437
|
if (name && sup.nodeTypes.identifier.includes(name.type) && sliceText(name, source) === receiverName) {
|
|
388
438
|
return true;
|
|
@@ -419,8 +469,88 @@ function constructorFromAssignmentLike(node, receiverName, source, sup) {
|
|
|
419
469
|
return null;
|
|
420
470
|
return findNamedChildText(node, match[1], source, sup);
|
|
421
471
|
}
|
|
472
|
+
if (sup.id === "python") {
|
|
473
|
+
return pythonConstructorFromAssignment(node, receiverName, source, sup);
|
|
474
|
+
}
|
|
422
475
|
return null;
|
|
423
476
|
}
|
|
477
|
+
function goBindingNameNodes(node) {
|
|
478
|
+
if (node.type === "short_var_declaration") {
|
|
479
|
+
const left = node.childForFieldName("left");
|
|
480
|
+
return (left?.namedChildren ?? []).filter((child) => child.type === "identifier");
|
|
481
|
+
}
|
|
482
|
+
if (node.type === "var_spec") {
|
|
483
|
+
return (node.namedChildren ?? []).filter((child) => child.type === "identifier");
|
|
484
|
+
}
|
|
485
|
+
return [];
|
|
486
|
+
}
|
|
487
|
+
function goBindingDeclaresName(node, receiverName, source, sup) {
|
|
488
|
+
if (sup.id !== "go")
|
|
489
|
+
return false;
|
|
490
|
+
return goBindingNameNodes(node).some((name) => sliceText(name, source) === receiverName);
|
|
491
|
+
}
|
|
492
|
+
function constructorFromGoBinding(node, receiverName, source, sup) {
|
|
493
|
+
if (!goBindingDeclaresName(node, receiverName, source, sup))
|
|
494
|
+
return null;
|
|
495
|
+
if (node.type === "short_var_declaration") {
|
|
496
|
+
const left = node.childForFieldName("left");
|
|
497
|
+
const right = node.childForFieldName("right");
|
|
498
|
+
if (!left || !right)
|
|
499
|
+
return null;
|
|
500
|
+
const names = (left.namedChildren ?? []).filter((child) => child.type === "identifier");
|
|
501
|
+
const values = right.namedChildren ?? [];
|
|
502
|
+
const index = names.findIndex((name) => sliceText(name, source) === receiverName);
|
|
503
|
+
if (index < 0)
|
|
504
|
+
return null;
|
|
505
|
+
const value = values[index] ?? null;
|
|
506
|
+
return value ? goCompositeLiteralTypeName(value, source) : null;
|
|
507
|
+
}
|
|
508
|
+
if (node.type !== "var_spec")
|
|
509
|
+
return null;
|
|
510
|
+
const value = node.childForFieldName("value");
|
|
511
|
+
if (value) {
|
|
512
|
+
const first = value.type === "expression_list" ? (value.namedChildren[0] ?? null) : value;
|
|
513
|
+
const fromValue = first ? goCompositeLiteralTypeName(first, source) : null;
|
|
514
|
+
if (fromValue)
|
|
515
|
+
return fromValue;
|
|
516
|
+
}
|
|
517
|
+
const typeNode = node.childForFieldName("type");
|
|
518
|
+
return typeNode ? unwrapGoConstructorType(typeNode) : null;
|
|
519
|
+
}
|
|
520
|
+
function goCompositeLiteralTypeName(expr, source) {
|
|
521
|
+
let current = expr;
|
|
522
|
+
if (current.type === "unary_expression") {
|
|
523
|
+
const operand = current.childForFieldName("operand");
|
|
524
|
+
if (!operand)
|
|
525
|
+
return null;
|
|
526
|
+
const operator = current.childForFieldName("operator");
|
|
527
|
+
let isAddr = sliceText(current, source).startsWith("&");
|
|
528
|
+
if (operator)
|
|
529
|
+
isAddr = sliceText(operator, source) === "&";
|
|
530
|
+
if (!isAddr)
|
|
531
|
+
return null;
|
|
532
|
+
current = operand;
|
|
533
|
+
}
|
|
534
|
+
if (current.type !== "composite_literal")
|
|
535
|
+
return null;
|
|
536
|
+
const typeNode = current.childForFieldName("type");
|
|
537
|
+
return typeNode ? unwrapGoConstructorType(typeNode) : null;
|
|
538
|
+
}
|
|
539
|
+
function unwrapGoConstructorType(node) {
|
|
540
|
+
let current = node;
|
|
541
|
+
while (current) {
|
|
542
|
+
if (current.type === "parenthesized_type" || current.type === "pointer_type") {
|
|
543
|
+
current = current.namedChildren[0] ?? null;
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
if (current.type === "generic_type") {
|
|
547
|
+
current = current.childForFieldName("type") ?? current.namedChildren[0] ?? null;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
break;
|
|
551
|
+
}
|
|
552
|
+
return current?.type === "type_identifier" ? current : null;
|
|
553
|
+
}
|
|
424
554
|
function findNamedChildText(node, name, source, sup) {
|
|
425
555
|
const isNameNode = (candidate) => (sup.nodeTypes.identifier.includes(candidate.type) ||
|
|
426
556
|
candidate.type === "type_identifier" ||
|
|
@@ -460,8 +590,13 @@ async function resolveMemberDefinitionForBase(index, baseDef, member) {
|
|
|
460
590
|
return undefined;
|
|
461
591
|
return findReceiverMemberDefinition(targetModule.locals, member, baseDef, container, targetContext, normalizeIdentifier);
|
|
462
592
|
}
|
|
463
|
-
function findReceiverMemberDefinition(locals, member, receiverDef, container, targetContext, normalizeIdentifier) {
|
|
464
|
-
const
|
|
593
|
+
function findReceiverMemberDefinition(locals, member, receiverDef, container, targetContext, normalizeIdentifier, memberScope = "any") {
|
|
594
|
+
const memberPredicate = memberScope === "any"
|
|
595
|
+
? undefined
|
|
596
|
+
: (local) => hasStaticModifier(local, targetContext, container) === (memberScope === "static");
|
|
597
|
+
const containerHit = memberScope === "any"
|
|
598
|
+
? findLocalWithinNode(locals, member, container, normalizeIdentifier)
|
|
599
|
+
: findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier, memberPredicate);
|
|
465
600
|
if (containerHit)
|
|
466
601
|
return containerHit;
|
|
467
602
|
if (targetContext.sup.id !== "rust")
|
|
@@ -469,7 +604,7 @@ function findReceiverMemberDefinition(locals, member, receiverDef, container, ta
|
|
|
469
604
|
const implNode = findRustImplForType(targetContext.tree.rootNode, receiverDef.localName, targetContext.source);
|
|
470
605
|
return implNode ? findLocalWithinNode(locals, member, implNode, normalizeIdentifier) : undefined;
|
|
471
606
|
}
|
|
472
|
-
function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name) => name) {
|
|
607
|
+
function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name) => name, predicate) {
|
|
473
608
|
const containerStart = node.startIndex;
|
|
474
609
|
const containerEnd = node.endIndex;
|
|
475
610
|
const normalizedMember = normalizeIdentifier(member);
|
|
@@ -480,9 +615,28 @@ function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name)
|
|
|
480
615
|
startIndex !== undefined &&
|
|
481
616
|
endIndex !== undefined &&
|
|
482
617
|
startIndex >= containerStart &&
|
|
483
|
-
endIndex <= containerEnd
|
|
618
|
+
endIndex <= containerEnd &&
|
|
619
|
+
(!predicate || predicate(local)));
|
|
484
620
|
});
|
|
485
621
|
}
|
|
622
|
+
function hasStaticModifier(local, targetContext, container) {
|
|
623
|
+
const position = {
|
|
624
|
+
row: local.range.start.line - 1,
|
|
625
|
+
column: local.range.start.column - 1,
|
|
626
|
+
};
|
|
627
|
+
let current = targetContext.tree.rootNode.descendantForPosition(position, position);
|
|
628
|
+
while (current && current !== container) {
|
|
629
|
+
for (let childIndex = 0;; childIndex += 1) {
|
|
630
|
+
const child = current.child(childIndex);
|
|
631
|
+
if (!child)
|
|
632
|
+
break;
|
|
633
|
+
if (child.type === "static")
|
|
634
|
+
return true;
|
|
635
|
+
}
|
|
636
|
+
current = current.parent;
|
|
637
|
+
}
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
486
640
|
const NESTED_MEMBER_LOCAL_CONTAINERS = new Set([
|
|
487
641
|
"block",
|
|
488
642
|
"class",
|
|
@@ -502,7 +656,7 @@ const NESTED_MEMBER_LOCAL_CONTAINERS = new Set([
|
|
|
502
656
|
"module",
|
|
503
657
|
"statement_block",
|
|
504
658
|
]);
|
|
505
|
-
function findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier) {
|
|
659
|
+
function findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier, predicate) {
|
|
506
660
|
const containerStart = container.startIndex;
|
|
507
661
|
const containerEnd = container.endIndex;
|
|
508
662
|
const normalizedMember = normalizeIdentifier(member);
|
|
@@ -524,7 +678,9 @@ function findDirectLocalWithinNode(locals, member, container, targetContext, nor
|
|
|
524
678
|
let current = targetContext.tree.rootNode.descendantForPosition(position, position).parent;
|
|
525
679
|
let isDeclarationParent = true;
|
|
526
680
|
while (current && current !== container) {
|
|
681
|
+
const isDirectBody = (current.type === "statement_block" || current.type === "block") && current.parent === container;
|
|
527
682
|
if (!isDeclarationParent &&
|
|
683
|
+
!isDirectBody &&
|
|
528
684
|
((current.type === "class_body" && current.parent !== container) ||
|
|
529
685
|
NESTED_MEMBER_LOCAL_CONTAINERS.has(current.type))) {
|
|
530
686
|
current = null;
|
|
@@ -533,7 +689,7 @@ function findDirectLocalWithinNode(locals, member, container, targetContext, nor
|
|
|
533
689
|
isDeclarationParent = false;
|
|
534
690
|
current = current.parent;
|
|
535
691
|
}
|
|
536
|
-
if (current)
|
|
692
|
+
if (current && (!predicate || predicate(local)))
|
|
537
693
|
return local;
|
|
538
694
|
}
|
|
539
695
|
return undefined;
|
|
@@ -557,6 +713,230 @@ function findRustImplForType(root, typeName, source) {
|
|
|
557
713
|
visit(root);
|
|
558
714
|
return found;
|
|
559
715
|
}
|
|
716
|
+
function pythonConstructorFromAssignment(node, receiverName, source, sup) {
|
|
717
|
+
const left = node.childForFieldName("left");
|
|
718
|
+
if (!left || !sup.nodeTypes.identifier.includes(left.type) || sliceText(left, source) !== receiverName) {
|
|
719
|
+
return null;
|
|
720
|
+
}
|
|
721
|
+
const right = node.childForFieldName("right");
|
|
722
|
+
if (!right || right.type !== "call")
|
|
723
|
+
return null;
|
|
724
|
+
const callee = right.childForFieldName("function") ?? right.namedChildren[0] ?? null;
|
|
725
|
+
if (!callee || !sup.nodeTypes.identifier.includes(callee.type))
|
|
726
|
+
return null;
|
|
727
|
+
return callee;
|
|
728
|
+
}
|
|
729
|
+
const PYTHON_SUPERTYPE_DEPTH = 16;
|
|
730
|
+
function pythonClassKey(def) {
|
|
731
|
+
const start = def.range.start;
|
|
732
|
+
return `${fileIdentityKey(def.file)}:${start.index ?? `${start.line}:${start.column}`}`;
|
|
733
|
+
}
|
|
734
|
+
async function resolvePythonReceiverMember(index, mod, node, obj, member, source, sup, resolveExpression) {
|
|
735
|
+
const classRef = await pythonReceiverClassRef(index, mod, node, obj, source, sup, resolveExpression);
|
|
736
|
+
if (!classRef)
|
|
737
|
+
return undefined;
|
|
738
|
+
return lookupPythonClassMember(index, classRef, member);
|
|
739
|
+
}
|
|
740
|
+
async function pythonReceiverClassRef(index, mod, node, obj, source, sup, resolveExpression) {
|
|
741
|
+
const receiverName = sliceText(obj, source);
|
|
742
|
+
if (receiverName === "self" || receiverName === "cls") {
|
|
743
|
+
const container = findEnclosingClassContainer(node);
|
|
744
|
+
if (!container)
|
|
745
|
+
return null;
|
|
746
|
+
const nameNode = container.childForFieldName("name");
|
|
747
|
+
if (!nameNode)
|
|
748
|
+
return null;
|
|
749
|
+
const className = sliceText(nameNode, source);
|
|
750
|
+
const def = mod.locals.find((local) => {
|
|
751
|
+
const startIndex = local.range.start.index;
|
|
752
|
+
const endIndex = local.range.end.index;
|
|
753
|
+
return (local.kind === SymbolKind.Class &&
|
|
754
|
+
local.localName === className &&
|
|
755
|
+
startIndex !== undefined &&
|
|
756
|
+
endIndex !== undefined &&
|
|
757
|
+
startIndex >= container.startIndex &&
|
|
758
|
+
endIndex <= container.endIndex);
|
|
759
|
+
});
|
|
760
|
+
if (!def)
|
|
761
|
+
return null;
|
|
762
|
+
return pythonClassRefFromDef(index, def);
|
|
763
|
+
}
|
|
764
|
+
let classDef;
|
|
765
|
+
const constructor = receiverConstructorExpression(obj, source, sup);
|
|
766
|
+
if (constructor) {
|
|
767
|
+
const result = await resolveExpression(constructor);
|
|
768
|
+
if (result?.kind === "resolved" && result.def.kind === SymbolKind.Class) {
|
|
769
|
+
classDef = result.def;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
if (!classDef) {
|
|
773
|
+
const direct = await resolveExpression(obj);
|
|
774
|
+
if (direct?.kind === "resolved" && direct.def.kind === SymbolKind.Class) {
|
|
775
|
+
classDef = direct.def;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
if (!classDef)
|
|
779
|
+
return null;
|
|
780
|
+
return pythonClassRefFromDef(index, classDef);
|
|
781
|
+
}
|
|
782
|
+
async function pythonClassRefFromDef(index, def) {
|
|
783
|
+
const module = index.byFile.get(fileIdentityKey(def.file));
|
|
784
|
+
if (!module)
|
|
785
|
+
return null;
|
|
786
|
+
const context = await ensureParsedContext(def.file, undefined, index.languageExtensions);
|
|
787
|
+
const start = def.range.start;
|
|
788
|
+
const position = {
|
|
789
|
+
row: start.line - 1,
|
|
790
|
+
column: start.column - 1,
|
|
791
|
+
};
|
|
792
|
+
let current = context.tree.rootNode.descendantForPosition(position, position);
|
|
793
|
+
while (current && current.type !== "class_definition") {
|
|
794
|
+
current = current.parent;
|
|
795
|
+
}
|
|
796
|
+
if (!current)
|
|
797
|
+
return null;
|
|
798
|
+
return { def, container: current, context, module };
|
|
799
|
+
}
|
|
800
|
+
function pythonMembersOnClass(classRef, member) {
|
|
801
|
+
const normalizeIdentifier = classRef.context.sup.normalizeIdentifier;
|
|
802
|
+
const direct = findDirectLocalWithinNode(classRef.module.locals, member, classRef.container, classRef.context, normalizeIdentifier);
|
|
803
|
+
if (direct)
|
|
804
|
+
return [direct];
|
|
805
|
+
const attribute = findPythonInstanceAttributeWithinClass(classRef.module.locals, member, classRef.container, classRef.context, normalizeIdentifier);
|
|
806
|
+
return attribute ? [attribute] : [];
|
|
807
|
+
}
|
|
808
|
+
function findPythonInstanceAttributeWithinClass(locals, member, container, targetContext, normalizeIdentifier) {
|
|
809
|
+
const containerStart = container.startIndex;
|
|
810
|
+
const containerEnd = container.endIndex;
|
|
811
|
+
const normalizedMember = normalizeIdentifier(member);
|
|
812
|
+
for (const local of locals) {
|
|
813
|
+
const startIndex = local.range.start.index;
|
|
814
|
+
const endIndex = local.range.end.index;
|
|
815
|
+
if (normalizeIdentifier(local.localName) !== normalizedMember ||
|
|
816
|
+
startIndex === undefined ||
|
|
817
|
+
endIndex === undefined ||
|
|
818
|
+
startIndex < containerStart ||
|
|
819
|
+
endIndex > containerEnd) {
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
const start = local.range.start;
|
|
823
|
+
const position = {
|
|
824
|
+
row: start.line - 1,
|
|
825
|
+
column: start.column - 1,
|
|
826
|
+
};
|
|
827
|
+
const nameNode = targetContext.tree.rootNode.descendantForPosition(position, position);
|
|
828
|
+
if (isPythonReceiverAttributeAssignmentName(nameNode))
|
|
829
|
+
return local;
|
|
830
|
+
}
|
|
831
|
+
return undefined;
|
|
832
|
+
}
|
|
833
|
+
function pythonBaseIdentifierNodes(classNode) {
|
|
834
|
+
const bases = classNode.childForFieldName("superclasses") ??
|
|
835
|
+
(classNode.namedChildren ?? []).find((child) => child.type === "argument_list");
|
|
836
|
+
if (!bases)
|
|
837
|
+
return [];
|
|
838
|
+
const names = [];
|
|
839
|
+
const visit = (node) => {
|
|
840
|
+
if (node.type === "keyword_argument" || node.type === "dictionary_splat" || node.type === "list_splat") {
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
if (node.type === "identifier") {
|
|
844
|
+
names.push(node);
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
if (node.type === "subscript") {
|
|
848
|
+
const value = node.childForFieldName("value");
|
|
849
|
+
if (value)
|
|
850
|
+
visit(value);
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
for (const child of node.namedChildren)
|
|
854
|
+
visit(child);
|
|
855
|
+
};
|
|
856
|
+
visit(bases);
|
|
857
|
+
return names;
|
|
858
|
+
}
|
|
859
|
+
function resolvePythonNamedClass(index, mod, name) {
|
|
860
|
+
const classes = mod.locals.filter((local) => local.kind === SymbolKind.Class && local.localName === name);
|
|
861
|
+
const topLevel = classes.filter((local) => !local.isMember);
|
|
862
|
+
const candidates = topLevel.length ? topLevel : classes;
|
|
863
|
+
if (candidates.length === 1)
|
|
864
|
+
return candidates[0];
|
|
865
|
+
if (candidates.length > 1)
|
|
866
|
+
return undefined;
|
|
867
|
+
for (const imp of mod.imports) {
|
|
868
|
+
if (imp.kind === "named" && imp.local === name) {
|
|
869
|
+
const result = resolveImported(index, imp, imp.imported);
|
|
870
|
+
if (result && !("namespace" in result) && result.kind === SymbolKind.Class)
|
|
871
|
+
return result;
|
|
872
|
+
}
|
|
873
|
+
if (imp.kind === "star") {
|
|
874
|
+
const result = resolveImported(index, imp, name);
|
|
875
|
+
if (result && !("namespace" in result) && result.kind === SymbolKind.Class)
|
|
876
|
+
return result;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
const exported = resolveExport(index, mod.file, name, { preferredKind: SymbolKind.Class, allowLocalFallback: false });
|
|
880
|
+
if (exported?.kind === "resolved" && exported.def.kind === SymbolKind.Class)
|
|
881
|
+
return exported.def;
|
|
882
|
+
return undefined;
|
|
883
|
+
}
|
|
884
|
+
async function pythonBaseClassRefs(index, classRef) {
|
|
885
|
+
const names = pythonBaseIdentifierNodes(classRef.container);
|
|
886
|
+
const refs = [];
|
|
887
|
+
const seen = new Set();
|
|
888
|
+
for (const nameNode of names) {
|
|
889
|
+
const def = resolvePythonNamedClass(index, classRef.module, sliceText(nameNode, classRef.context.source));
|
|
890
|
+
if (!def)
|
|
891
|
+
continue;
|
|
892
|
+
const key = pythonClassKey(def);
|
|
893
|
+
if (seen.has(key))
|
|
894
|
+
continue;
|
|
895
|
+
seen.add(key);
|
|
896
|
+
const ref = await pythonClassRefFromDef(index, def);
|
|
897
|
+
if (ref)
|
|
898
|
+
refs.push(ref);
|
|
899
|
+
}
|
|
900
|
+
return refs;
|
|
901
|
+
}
|
|
902
|
+
async function lookupPythonClassMember(index, start, member) {
|
|
903
|
+
const own = pythonMembersOnClass(start, member);
|
|
904
|
+
if (own.length === 1)
|
|
905
|
+
return own[0];
|
|
906
|
+
if (own.length > 1)
|
|
907
|
+
return undefined;
|
|
908
|
+
let level = await pythonBaseClassRefs(index, start);
|
|
909
|
+
const visited = new Set([pythonClassKey(start.def), ...level.map((base) => pythonClassKey(base.def))]);
|
|
910
|
+
for (let depth = 0; depth < PYTHON_SUPERTYPE_DEPTH && level.length; depth += 1) {
|
|
911
|
+
const matches = [];
|
|
912
|
+
const seenMatch = new Set();
|
|
913
|
+
for (const base of level) {
|
|
914
|
+
for (const hit of pythonMembersOnClass(base, member)) {
|
|
915
|
+
const key = pythonClassKey(hit);
|
|
916
|
+
if (seenMatch.has(key))
|
|
917
|
+
continue;
|
|
918
|
+
seenMatch.add(key);
|
|
919
|
+
matches.push(hit);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
if (matches.length === 1)
|
|
923
|
+
return matches[0];
|
|
924
|
+
if (matches.length > 1)
|
|
925
|
+
return undefined;
|
|
926
|
+
const next = [];
|
|
927
|
+
for (const base of level) {
|
|
928
|
+
for (const parent of await pythonBaseClassRefs(index, base)) {
|
|
929
|
+
const key = pythonClassKey(parent.def);
|
|
930
|
+
if (visited.has(key))
|
|
931
|
+
continue;
|
|
932
|
+
visited.add(key);
|
|
933
|
+
next.push(parent);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
level = next;
|
|
937
|
+
}
|
|
938
|
+
return undefined;
|
|
939
|
+
}
|
|
560
940
|
function escapeRegExp(value) {
|
|
561
941
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
562
942
|
}
|