@lzehrung/codegraph 2.3.28 → 2.3.30
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/bin/cli.js +7008 -4340
- package/dist/bin/query-index-worker.js +1357 -724
- package/dist/document-links/asciidoc.d.ts.map +1 -1
- package/dist/document-links/asciidoc.js +3 -4
- package/dist/document-links/asciidoc.js.map +1 -1
- package/dist/document-links/html-forms.d.ts +39 -0
- package/dist/document-links/html-forms.d.ts.map +1 -0
- package/dist/document-links/html-forms.js +94 -0
- package/dist/document-links/html-forms.js.map +1 -0
- package/dist/document-links/html.d.ts +8 -0
- package/dist/document-links/html.d.ts.map +1 -1
- package/dist/document-links/html.js +30 -15
- package/dist/document-links/html.js.map +1 -1
- package/dist/document-links/markdown.d.ts.map +1 -1
- package/dist/document-links/markdown.js +6 -7
- package/dist/document-links/markdown.js.map +1 -1
- package/dist/document-links/rst.d.ts.map +1 -1
- package/dist/document-links/rst.js +6 -0
- package/dist/document-links/rst.js.map +1 -1
- package/dist/document-links/sfc.d.ts.map +1 -1
- package/dist/document-links/sfc.js +4 -4
- package/dist/document-links/sfc.js.map +1 -1
- package/dist/graphs/angularjs.d.ts.map +1 -1
- package/dist/graphs/angularjs.js +9 -1
- package/dist/graphs/angularjs.js.map +1 -1
- package/dist/graphs/edge-resolution.d.ts.map +1 -1
- package/dist/graphs/edge-resolution.js +12 -2
- package/dist/graphs/edge-resolution.js.map +1 -1
- package/dist/graphs/specifiers.d.ts.map +1 -1
- package/dist/graphs/specifiers.js +62 -104
- package/dist/graphs/specifiers.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 +157 -91
- package/dist/graphs/symbol-graph-detailed/edge-passes.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts +34 -0
- package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/receiver-calls.js +531 -24
- 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/providers/index.d.ts +3 -1
- package/dist/impact/call-compatibility/providers/index.d.ts.map +1 -1
- package/dist/impact/call-compatibility/providers/index.js +11 -4
- package/dist/impact/call-compatibility/providers/index.js.map +1 -1
- package/dist/impact/call-compatibility.d.ts.map +1 -1
- package/dist/impact/call-compatibility.js +2 -7
- package/dist/impact/call-compatibility.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 +2 -5
- package/dist/impact/member-resolution-coverage.js.map +1 -1
- package/dist/indexer/build-cache/manifest.d.ts +7 -0
- package/dist/indexer/build-cache/manifest.d.ts.map +1 -1
- package/dist/indexer/build-cache/manifest.js +32 -1
- package/dist/indexer/build-cache/manifest.js.map +1 -1
- package/dist/indexer/build-cache/options.d.ts +20 -2
- package/dist/indexer/build-cache/options.d.ts.map +1 -1
- package/dist/indexer/build-cache/options.js +21 -3
- 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 +1 -0
- package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
- package/dist/indexer/build-index.d.ts.map +1 -1
- package/dist/indexer/build-index.js +80 -2
- package/dist/indexer/build-index.js.map +1 -1
- package/dist/indexer/build-manifest.d.ts +1 -0
- package/dist/indexer/build-manifest.d.ts.map +1 -1
- package/dist/indexer/build-manifest.js +18 -0
- package/dist/indexer/build-manifest.js.map +1 -1
- package/dist/indexer/build-workers.js +1 -1
- package/dist/indexer/build-workers.js.map +1 -1
- package/dist/indexer/declaration-visibility.d.ts +43 -0
- package/dist/indexer/declaration-visibility.d.ts.map +1 -0
- package/dist/indexer/declaration-visibility.js +202 -0
- package/dist/indexer/declaration-visibility.js.map +1 -0
- package/dist/indexer/imports/binding-ranges.d.ts +1 -1
- package/dist/indexer/imports/binding-ranges.d.ts.map +1 -1
- package/dist/indexer/imports/binding-ranges.js +2 -123
- package/dist/indexer/imports/binding-ranges.js.map +1 -1
- package/dist/indexer/imports/js-text-imports.d.ts.map +1 -1
- package/dist/indexer/imports/js-text-imports.js +5 -2
- package/dist/indexer/imports/js-text-imports.js.map +1 -1
- package/dist/indexer/imports/language-specific.d.ts.map +1 -1
- package/dist/indexer/imports/language-specific.js +58 -215
- 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 +23 -32
- package/dist/indexer/imports/native-captures.js.map +1 -1
- package/dist/indexer/imports/text-import-extractors.d.ts +37 -0
- package/dist/indexer/imports/text-import-extractors.d.ts.map +1 -0
- package/dist/indexer/imports/text-import-extractors.js +358 -0
- package/dist/indexer/imports/text-import-extractors.js.map +1 -0
- package/dist/indexer/locals-and-exports.d.ts.map +1 -1
- package/dist/indexer/locals-and-exports.js +26 -27
- package/dist/indexer/locals-and-exports.js.map +1 -1
- package/dist/indexer/navigation-goto.d.ts +1 -7
- package/dist/indexer/navigation-goto.d.ts.map +1 -1
- package/dist/indexer/navigation-goto.js +406 -276
- package/dist/indexer/navigation-goto.js.map +1 -1
- package/dist/indexer/navigation-resolve.d.ts.map +1 -1
- package/dist/indexer/navigation-resolve.js +20 -1
- package/dist/indexer/navigation-resolve.js.map +1 -1
- package/dist/indexer/navigation.d.ts.map +1 -1
- package/dist/indexer/navigation.js +49 -7
- package/dist/indexer/navigation.js.map +1 -1
- package/dist/indexer/parse-context.js +2 -2
- package/dist/indexer/parse-context.js.map +1 -1
- package/dist/indexer/scope-nodes.d.ts +108 -0
- package/dist/indexer/scope-nodes.d.ts.map +1 -0
- package/dist/indexer/scope-nodes.js +238 -0
- package/dist/indexer/scope-nodes.js.map +1 -0
- package/dist/indexer/scope.d.ts.map +1 -1
- package/dist/indexer/scope.js +70 -130
- package/dist/indexer/scope.js.map +1 -1
- package/dist/indexer/types.d.ts +7 -0
- package/dist/indexer/types.d.ts.map +1 -1
- package/dist/languages/definitions/c-family.d.ts +18 -4
- package/dist/languages/definitions/c-family.d.ts.map +1 -1
- package/dist/languages/definitions/c-family.js +51 -13
- package/dist/languages/definitions/c-family.js.map +1 -1
- package/dist/languages/definitions/c.d.ts.map +1 -1
- package/dist/languages/definitions/c.js +7 -43
- package/dist/languages/definitions/c.js.map +1 -1
- package/dist/languages/definitions/cpp.d.ts.map +1 -1
- package/dist/languages/definitions/cpp.js +34 -53
- package/dist/languages/definitions/cpp.js.map +1 -1
- package/dist/languages/definitions/csharp.d.ts.map +1 -1
- package/dist/languages/definitions/csharp.js +47 -53
- package/dist/languages/definitions/csharp.js.map +1 -1
- package/dist/languages/definitions/css-like.d.ts.map +1 -1
- package/dist/languages/definitions/css-like.js +13 -10
- package/dist/languages/definitions/css-like.js.map +1 -1
- package/dist/languages/definitions/go.d.ts.map +1 -1
- package/dist/languages/definitions/go.js +29 -42
- package/dist/languages/definitions/go.js.map +1 -1
- package/dist/languages/definitions/html.d.ts.map +1 -1
- package/dist/languages/definitions/html.js +15 -14
- package/dist/languages/definitions/html.js.map +1 -1
- package/dist/languages/definitions/java.d.ts.map +1 -1
- package/dist/languages/definitions/java.js +42 -48
- package/dist/languages/definitions/java.js.map +1 -1
- package/dist/languages/definitions/javascript.d.ts.map +1 -1
- package/dist/languages/definitions/javascript.js +26 -54
- package/dist/languages/definitions/javascript.js.map +1 -1
- package/dist/languages/definitions/js-family.d.ts +15 -1
- package/dist/languages/definitions/js-family.d.ts.map +1 -1
- package/dist/languages/definitions/js-family.js +51 -0
- package/dist/languages/definitions/js-family.js.map +1 -1
- package/dist/languages/definitions/kotlin.d.ts.map +1 -1
- package/dist/languages/definitions/kotlin.js +26 -43
- package/dist/languages/definitions/kotlin.js.map +1 -1
- package/dist/languages/definitions/php.d.ts.map +1 -1
- package/dist/languages/definitions/php.js +50 -60
- 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 +62 -14
- package/dist/languages/definitions/python.js.map +1 -1
- package/dist/languages/definitions/ruby.d.ts.map +1 -1
- package/dist/languages/definitions/ruby.js +14 -17
- package/dist/languages/definitions/ruby.js.map +1 -1
- package/dist/languages/definitions/rust.d.ts.map +1 -1
- package/dist/languages/definitions/rust.js +30 -52
- package/dist/languages/definitions/rust.js.map +1 -1
- package/dist/languages/definitions/scss.d.ts.map +1 -1
- package/dist/languages/definitions/scss.js +36 -30
- package/dist/languages/definitions/scss.js.map +1 -1
- package/dist/languages/definitions/sfc-graph.d.ts +4 -0
- package/dist/languages/definitions/sfc-graph.d.ts.map +1 -0
- package/dist/languages/definitions/sfc-graph.js +16 -0
- package/dist/languages/definitions/sfc-graph.js.map +1 -0
- package/dist/languages/definitions/shared.d.ts +33 -0
- package/dist/languages/definitions/shared.d.ts.map +1 -0
- package/dist/languages/definitions/shared.js +63 -0
- package/dist/languages/definitions/shared.js.map +1 -0
- package/dist/languages/definitions/sql.d.ts.map +1 -1
- package/dist/languages/definitions/sql.js +1 -0
- package/dist/languages/definitions/sql.js.map +1 -1
- package/dist/languages/definitions/svelte.d.ts.map +1 -1
- package/dist/languages/definitions/svelte.js +2 -10
- package/dist/languages/definitions/svelte.js.map +1 -1
- package/dist/languages/definitions/swift.d.ts.map +1 -1
- package/dist/languages/definitions/swift.js +37 -31
- package/dist/languages/definitions/swift.js.map +1 -1
- package/dist/languages/definitions/typescript.d.ts.map +1 -1
- package/dist/languages/definitions/typescript.js +65 -79
- package/dist/languages/definitions/typescript.js.map +1 -1
- package/dist/languages/definitions/vue.d.ts.map +1 -1
- package/dist/languages/definitions/vue.js +2 -10
- package/dist/languages/definitions/vue.js.map +1 -1
- package/dist/languages/definitions/zig.d.ts.map +1 -1
- package/dist/languages/definitions/zig.js +9 -15
- package/dist/languages/definitions/zig.js.map +1 -1
- package/dist/languages/graph-captures.d.ts +40 -0
- package/dist/languages/graph-captures.d.ts.map +1 -0
- package/dist/languages/graph-captures.js +46 -0
- package/dist/languages/graph-captures.js.map +1 -0
- package/dist/languages/import-statement-parsers.d.ts +17 -0
- package/dist/languages/import-statement-parsers.d.ts.map +1 -1
- package/dist/languages/import-statement-parsers.js +108 -0
- package/dist/languages/import-statement-parsers.js.map +1 -1
- package/dist/languages/js-family.d.ts +2 -0
- package/dist/languages/js-family.d.ts.map +1 -1
- package/dist/languages/js-family.js +15 -6
- package/dist/languages/js-family.js.map +1 -1
- package/dist/languages/types.d.ts +4 -0
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/types.js +1 -1
- package/dist/languages/types.js.map +1 -1
- package/dist/languages.js +1 -1
- package/dist/languages.js.map +1 -1
- package/dist/native/contracts.d.ts +1 -1
- package/dist/native/contracts.d.ts.map +1 -1
- package/dist/native/js-bridge.d.ts +10 -0
- package/dist/native/js-bridge.d.ts.map +1 -1
- package/dist/native/js-bridge.js +10 -0
- package/dist/native/js-bridge.js.map +1 -1
- package/dist/native/native-backend-report.d.ts.map +1 -1
- package/dist/native/native-backend-report.js +2 -0
- package/dist/native/native-backend-report.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/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 +7 -7
- package/dist/util/comments.d.ts.map +1 -1
- package/dist/util/comments.js +15 -214
- package/dist/util/comments.js.map +1 -1
- package/dist/util/lines.d.ts.map +1 -1
- package/dist/util/lines.js +4 -1
- package/dist/util/lines.js.map +1 -1
- package/dist/util/member-access.d.ts +2 -0
- package/dist/util/member-access.d.ts.map +1 -1
- package/dist/util/member-access.js +18 -5
- package/dist/util/member-access.js.map +1 -1
- package/dist/util/paths.d.ts +4 -0
- package/dist/util/paths.d.ts.map +1 -1
- package/dist/util/paths.js +26 -0
- package/dist/util/paths.js.map +1 -1
- package/dist/util/project-files.js +1 -1
- package/dist/util/project-files.js.map +1 -1
- package/dist/util/resolution/cargo-targets.d.ts.map +1 -1
- package/dist/util/resolution/cargo-targets.js +17 -14
- package/dist/util/resolution/cargo-targets.js.map +1 -1
- package/dist/util/resolution/cpp.d.ts +6 -0
- package/dist/util/resolution/cpp.d.ts.map +1 -0
- package/dist/util/resolution/cpp.js +69 -0
- package/dist/util/resolution/cpp.js.map +1 -0
- package/dist/util/resolution/csharp.d.ts +8 -0
- package/dist/util/resolution/csharp.d.ts.map +1 -0
- package/dist/util/resolution/csharp.js +103 -0
- package/dist/util/resolution/csharp.js.map +1 -0
- package/dist/util/resolution/files.d.ts +6 -0
- package/dist/util/resolution/files.d.ts.map +1 -1
- package/dist/util/resolution/files.js +108 -4
- package/dist/util/resolution/files.js.map +1 -1
- package/dist/util/resolution/go.d.ts +1 -0
- package/dist/util/resolution/go.d.ts.map +1 -1
- package/dist/util/resolution/go.js +4 -3
- package/dist/util/resolution/go.js.map +1 -1
- package/dist/util/resolution/jvm.d.ts +3 -3
- package/dist/util/resolution/jvm.d.ts.map +1 -1
- package/dist/util/resolution/jvm.js +90 -54
- package/dist/util/resolution/jvm.js.map +1 -1
- package/dist/util/resolution/node.js +2 -2
- package/dist/util/resolution/node.js.map +1 -1
- package/dist/util/resolution/php-composer.d.ts.map +1 -1
- package/dist/util/resolution/php-composer.js +8 -7
- package/dist/util/resolution/php-composer.js.map +1 -1
- package/dist/util/resolution/php.d.ts.map +1 -1
- package/dist/util/resolution/php.js +30 -43
- package/dist/util/resolution/php.js.map +1 -1
- package/dist/util/resolution/project-symbols.d.ts +5 -7
- package/dist/util/resolution/project-symbols.d.ts.map +1 -1
- package/dist/util/resolution/project-symbols.js +23 -9
- package/dist/util/resolution/project-symbols.js.map +1 -1
- package/dist/util/resolution/python.d.ts.map +1 -1
- package/dist/util/resolution/python.js +107 -62
- package/dist/util/resolution/python.js.map +1 -1
- package/dist/util/resolution/rust.d.ts.map +1 -1
- package/dist/util/resolution/rust.js +45 -34
- package/dist/util/resolution/rust.js.map +1 -1
- package/dist/util/resolution/tsconfig.d.ts.map +1 -1
- package/dist/util/resolution/tsconfig.js +3 -9
- package/dist/util/resolution/tsconfig.js.map +1 -1
- package/dist/util/resolution-candidates.d.ts +5 -1
- package/dist/util/resolution-candidates.d.ts.map +1 -1
- package/dist/util/resolution-candidates.js +18 -0
- package/dist/util/resolution-candidates.js.map +1 -1
- package/dist/util/resolution.d.ts.map +1 -1
- package/dist/util/resolution.js +95 -49
- package/dist/util/resolution.js.map +1 -1
- package/dist/util/specifiers.d.ts +4 -10
- package/dist/util/specifiers.d.ts.map +1 -1
- package/dist/util/specifiers.js +213 -164
- package/dist/util/specifiers.js.map +1 -1
- package/dist/util/trivia-tables.d.ts +69 -0
- package/dist/util/trivia-tables.d.ts.map +1 -0
- package/dist/util/trivia-tables.js +186 -0
- package/dist/util/trivia-tables.js.map +1 -0
- package/dist/util/trivia.d.ts +24 -0
- package/dist/util/trivia.d.ts.map +1 -0
- package/dist/util/trivia.js +621 -0
- package/dist/util/trivia.js.map +1 -0
- package/dist/util.d.ts +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +1 -1
- package/dist/util.js.map +1 -1
- package/dist/worker/native-extract-worker.d.ts.map +1 -1
- package/dist/worker/native-extract-worker.js +4 -4
- package/dist/worker/native-extract-worker.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,29 +1,33 @@
|
|
|
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
|
-
import { getMemberAccessParts, getNavigationExpressionProperty, isMemberAccessNode, memberAccessTraversalTypes, } from "../util/member-access.js";
|
|
5
|
-
import {
|
|
5
|
+
import { getMemberAccessParts, getNavigationExpressionProperty, isMemberAccessNode, isReceiverNameNode, memberAccessTraversalTypes, } from "../util/member-access.js";
|
|
6
|
+
import { declaresMembers, hasStaticMemberDistinction, isKeywordReceiver, nearestMemberContainer, receiverConstructorExpression, supportsReceiverMemberNavigation, unwrapNamedType, } from "../graphs/symbol-graph-detailed/receiver-calls.js";
|
|
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";
|
|
9
10
|
import { SymbolKind, } from "./types.js";
|
|
10
|
-
const RUBY_CONSTANT_SOURCE = String.raw `(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
|
|
11
|
-
const CSHARP_CONSTANT_SOURCE = String.raw `(?=@?\p{Lu})${CSHARP_IDENTIFIER_SOURCE}`;
|
|
12
|
-
const JAVA_CONSTANT_SOURCE = String.raw `(?=\p{Lu})${JAVA_IDENTIFIER_SOURCE}`;
|
|
13
|
-
const RUST_CONSTANT_SOURCE = String.raw `(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
|
|
14
|
-
const IDENTIFIER_BOUNDARY_SOURCE = String.raw `[$_\p{ID_Continue}\u200c\u200d]`;
|
|
15
11
|
export async function resolveMemberAccessDefinition(params) {
|
|
16
12
|
const { index, mod, node, source, sup, resolveLexicalBinding } = params;
|
|
17
13
|
const parent = node.parent;
|
|
18
|
-
if (!parent || !sup.supportsCrossModuleSymbols
|
|
14
|
+
if (!parent || !sup.supportsCrossModuleSymbols) {
|
|
19
15
|
return null;
|
|
20
16
|
}
|
|
21
|
-
|
|
17
|
+
let memberNode = null;
|
|
18
|
+
if (isMemberAccessNode(sup, parent)) {
|
|
19
|
+
memberNode = parent;
|
|
20
|
+
}
|
|
21
|
+
else if (parent.parent && isMemberAccessNode(sup, parent.parent)) {
|
|
22
|
+
memberNode = parent.parent;
|
|
23
|
+
}
|
|
24
|
+
if (!memberNode)
|
|
25
|
+
return null;
|
|
22
26
|
const { object: obj, property: prop } = getMemberAccessParts(sup, memberNode);
|
|
23
27
|
const optionalMemberTypes = memberAccessTraversalTypes(sup);
|
|
24
28
|
const resolveExpression = async (expr) => {
|
|
25
|
-
const exprIsId = sup
|
|
26
|
-
if (exprIsId
|
|
29
|
+
const exprIsId = isReceiverNameNode(sup, expr.type) && !isMemberAccessNode(sup, expr);
|
|
30
|
+
if (exprIsId) {
|
|
27
31
|
const lexicalBinding = resolveLexicalBinding?.(expr);
|
|
28
32
|
if (lexicalBinding)
|
|
29
33
|
return { kind: "resolved", def: lexicalBinding };
|
|
@@ -129,11 +133,19 @@ export async function resolveMemberAccessDefinition(params) {
|
|
|
129
133
|
}
|
|
130
134
|
}
|
|
131
135
|
const receiverName = obj ? sliceText(obj, source) : "";
|
|
132
|
-
const implicitClassReceiver = (
|
|
133
|
-
|
|
134
|
-
(sup.id === "rust" && /^(?:self|Self)$/.test(receiverName));
|
|
135
|
-
if (obj && prop && node.id === prop.id && (supportsReceiverMemberResolution(sup.id) || implicitClassReceiver)) {
|
|
136
|
+
const implicitClassReceiver = isKeywordReceiver(sup.id, receiverName);
|
|
137
|
+
if (obj && prop && node.id === prop.id && (supportsReceiverMemberNavigation(sup.id) || implicitClassReceiver)) {
|
|
136
138
|
const member = sliceText(prop, source);
|
|
139
|
+
if (sup.id === "python") {
|
|
140
|
+
const memberDef = await resolvePythonReceiverMember(index, mod, node, obj, member, source, sup, resolveExpression);
|
|
141
|
+
if (!memberDef)
|
|
142
|
+
return null;
|
|
143
|
+
return okGoToResult(index, memberDef, {
|
|
144
|
+
via: { exportedName: member },
|
|
145
|
+
resolution: "member-access",
|
|
146
|
+
confidence: "medium",
|
|
147
|
+
});
|
|
148
|
+
}
|
|
137
149
|
if (!sup.membersAreImplicitlyInScope && implicitClassReceiver) {
|
|
138
150
|
const classContainer = findEnclosingClassContainer(node);
|
|
139
151
|
const memberDef = classContainer
|
|
@@ -147,7 +159,7 @@ export async function resolveMemberAccessDefinition(params) {
|
|
|
147
159
|
});
|
|
148
160
|
}
|
|
149
161
|
}
|
|
150
|
-
const receiver = await resolveReceiverDefinition(obj, source, sup, resolveExpression);
|
|
162
|
+
const receiver = await resolveReceiverDefinition(obj, source, sup, resolveExpression, mod);
|
|
151
163
|
if (receiver) {
|
|
152
164
|
const objDef = receiver.def;
|
|
153
165
|
const targetContext = await ensureParsedContext(objDef.file, undefined, index.languageExtensions);
|
|
@@ -169,12 +181,12 @@ export async function resolveMemberAccessDefinition(params) {
|
|
|
169
181
|
const targetModule = index.byFile.get(fileIdentityKey(objDef.file));
|
|
170
182
|
if (targetModule) {
|
|
171
183
|
const normalizeIdentifier = targetContext.sup.normalizeIdentifier;
|
|
184
|
+
const memberPredicate = receiver.memberScope === "any"
|
|
185
|
+
? undefined
|
|
186
|
+
: (local) => matchesReceiverMemberScope(local, receiver.memberScope, targetContext, container);
|
|
172
187
|
let memberDef;
|
|
173
|
-
if (receiver.runtimeTypeOnly) {
|
|
174
|
-
memberDef = findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier);
|
|
175
|
-
}
|
|
176
|
-
else if (targetContext.sup.id === "java") {
|
|
177
|
-
memberDef = findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier);
|
|
188
|
+
if (receiver.runtimeTypeOnly || targetContext.sup.id === "java") {
|
|
189
|
+
memberDef = findDirectLocalWithinNode(targetModule.locals, member, container, targetContext, normalizeIdentifier, memberPredicate);
|
|
178
190
|
}
|
|
179
191
|
else {
|
|
180
192
|
memberDef = findReceiverMemberDefinition(targetModule.locals, member, objDef, container, targetContext, normalizeIdentifier, receiver.memberScope);
|
|
@@ -193,49 +205,47 @@ export async function resolveMemberAccessDefinition(params) {
|
|
|
193
205
|
return null;
|
|
194
206
|
}
|
|
195
207
|
function findEnclosingClassContainer(node) {
|
|
196
|
-
|
|
197
|
-
while (current) {
|
|
198
|
-
if (current.type === "class_declaration" ||
|
|
199
|
-
current.type === "abstract_class_declaration" ||
|
|
200
|
-
current.type === "class_definition" ||
|
|
201
|
-
current.type === "impl_item") {
|
|
202
|
-
return current;
|
|
203
|
-
}
|
|
204
|
-
current = current.parent;
|
|
205
|
-
}
|
|
206
|
-
return null;
|
|
208
|
+
return nearestMemberContainer(node);
|
|
207
209
|
}
|
|
208
|
-
export
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
languageId === "java" ||
|
|
213
|
-
languageId === "javascript" ||
|
|
214
|
-
languageId === "jsx" ||
|
|
215
|
-
languageId === "rust" ||
|
|
216
|
-
languageId === "ts" ||
|
|
217
|
-
languageId === "typescript" ||
|
|
218
|
-
languageId === "tsx");
|
|
210
|
+
export { supportsReceiverCallEdges, supportsReceiverMemberNavigation, } from "../graphs/symbol-graph-detailed/receiver-calls.js";
|
|
211
|
+
function memberDeclaringLocals(mod, typeName, normalize) {
|
|
212
|
+
const normalized = normalize(typeName);
|
|
213
|
+
return mod.locals.filter((local) => normalize(local.localName) === normalized && declaresMembers(local));
|
|
219
214
|
}
|
|
220
|
-
async function resolveReceiverDefinition(obj, source, sup, resolveExpression) {
|
|
215
|
+
async function resolveReceiverDefinition(obj, source, sup, resolveExpression, mod) {
|
|
221
216
|
const constructor = receiverConstructorExpression(obj, source, sup);
|
|
222
217
|
if (constructor) {
|
|
218
|
+
const typeName = sliceText(constructor, source);
|
|
219
|
+
const typedLocals = memberDeclaringLocals(mod, typeName, sup.normalizeIdentifier);
|
|
220
|
+
if (typedLocals.length === 1) {
|
|
221
|
+
return {
|
|
222
|
+
def: typedLocals[0],
|
|
223
|
+
memberScope: hasStaticMemberDistinction(sup.id) ? "instance" : "any",
|
|
224
|
+
};
|
|
225
|
+
}
|
|
223
226
|
const result = await resolveExpression(constructor);
|
|
224
|
-
if (result?.kind === "resolved") {
|
|
227
|
+
if (result?.kind === "resolved" && declaresMembers(result.def)) {
|
|
225
228
|
return {
|
|
226
229
|
def: result.def,
|
|
227
|
-
memberScope:
|
|
230
|
+
memberScope: hasStaticMemberDistinction(sup.id) ? "instance" : "any",
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
if (typedLocals[0]) {
|
|
234
|
+
return {
|
|
235
|
+
def: typedLocals[0],
|
|
236
|
+
memberScope: hasStaticMemberDistinction(sup.id) ? "instance" : "any",
|
|
228
237
|
};
|
|
229
238
|
}
|
|
230
239
|
}
|
|
231
240
|
const direct = await resolveExpression(obj);
|
|
232
|
-
if (
|
|
233
|
-
if (
|
|
234
|
-
return { def: direct.def, memberScope: "static" };
|
|
235
|
-
}
|
|
236
|
-
if (direct?.kind === "resolved" && direct.def.kind === SymbolKind.TypeAlias) {
|
|
241
|
+
if (direct?.kind === "resolved" && declaresMembers(direct.def)) {
|
|
242
|
+
if (isJsTsLanguage(sup.id) && direct.def.kind === SymbolKind.TypeAlias) {
|
|
237
243
|
return { def: direct.def, memberScope: "any", runtimeTypeOnly: true };
|
|
238
244
|
}
|
|
245
|
+
const memberScope = hasStaticMemberDistinction(sup.id) ? "static" : "any";
|
|
246
|
+
return { def: direct.def, memberScope };
|
|
247
|
+
}
|
|
248
|
+
if (isJsTsLanguage(sup.id) && isReceiverNameNode(sup, obj.type)) {
|
|
239
249
|
return null;
|
|
240
250
|
}
|
|
241
251
|
if (direct?.kind === "resolved") {
|
|
@@ -243,224 +253,6 @@ async function resolveReceiverDefinition(obj, source, sup, resolveExpression) {
|
|
|
243
253
|
}
|
|
244
254
|
return null;
|
|
245
255
|
}
|
|
246
|
-
/**
|
|
247
|
-
* Resolves the node naming the type a receiver expression was constructed from, or
|
|
248
|
-
* null when no constructor is proven for it. Shared with detailed symbol-graph call
|
|
249
|
-
* extraction so `goto` and resolved `calls` edges accept the same receiver forms.
|
|
250
|
-
*/
|
|
251
|
-
export function receiverConstructorExpression(obj, source, sup) {
|
|
252
|
-
if (obj.type === "new_expression" || obj.type === "object_creation_expression") {
|
|
253
|
-
return constructorNameNode(obj, sup);
|
|
254
|
-
}
|
|
255
|
-
if (sup.id === "ruby" && obj.type === "call") {
|
|
256
|
-
const rubyConstructor = rubyNewReceiverNameNode(obj, source, sup);
|
|
257
|
-
if (rubyConstructor)
|
|
258
|
-
return rubyConstructor;
|
|
259
|
-
}
|
|
260
|
-
if (!sup.nodeTypes.identifier.includes(obj.type)) {
|
|
261
|
-
return null;
|
|
262
|
-
}
|
|
263
|
-
const receiverName = sliceText(obj, source);
|
|
264
|
-
return findVisiblePriorNewConstructor(obj, receiverName, source, sup);
|
|
265
|
-
}
|
|
266
|
-
function constructorNameNode(node, sup) {
|
|
267
|
-
const constructor = node.childForFieldName("constructor") ?? node.child(0);
|
|
268
|
-
if (constructor && sup.nodeTypes.identifier.includes(constructor.type)) {
|
|
269
|
-
return constructor;
|
|
270
|
-
}
|
|
271
|
-
for (const child of node.namedChildren) {
|
|
272
|
-
if (sup.nodeTypes.identifier.includes(child.type) ||
|
|
273
|
-
child.type === "type_identifier" ||
|
|
274
|
-
child.type === "constant") {
|
|
275
|
-
return child;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
return null;
|
|
279
|
-
}
|
|
280
|
-
function rubyNewReceiverNameNode(node, source, sup) {
|
|
281
|
-
if (!new RegExp(String.raw `^(?:${RUBY_CONSTANT_SOURCE})\.new$`, "u").test(sliceText(node, source)))
|
|
282
|
-
return null;
|
|
283
|
-
return (node.namedChildren.find((child) => sup.nodeTypes.identifier.includes(child.type) || child.type === "constant") ??
|
|
284
|
-
null);
|
|
285
|
-
}
|
|
286
|
-
function rootOf(node) {
|
|
287
|
-
let current = node;
|
|
288
|
-
while (current.parent) {
|
|
289
|
-
current = current.parent;
|
|
290
|
-
}
|
|
291
|
-
return current;
|
|
292
|
-
}
|
|
293
|
-
const BINDING_CONTAINER_TYPES = new Set([
|
|
294
|
-
"program",
|
|
295
|
-
"compilation_unit",
|
|
296
|
-
"source_file",
|
|
297
|
-
"statement_block",
|
|
298
|
-
"block",
|
|
299
|
-
"function_declaration",
|
|
300
|
-
"function_item",
|
|
301
|
-
"function",
|
|
302
|
-
"function_expression",
|
|
303
|
-
"arrow_function",
|
|
304
|
-
"method_definition",
|
|
305
|
-
"method_declaration",
|
|
306
|
-
"method",
|
|
307
|
-
]);
|
|
308
|
-
const BINDING_DECLARATION_TYPES = new Set([
|
|
309
|
-
"variable_declarator",
|
|
310
|
-
"let_declaration",
|
|
311
|
-
"assignment",
|
|
312
|
-
"formal_parameter",
|
|
313
|
-
"required_parameter",
|
|
314
|
-
"optional_parameter",
|
|
315
|
-
]);
|
|
316
|
-
function findVisiblePriorNewConstructor(receiver, receiverName, source, sup) {
|
|
317
|
-
let current = receiver;
|
|
318
|
-
while (current) {
|
|
319
|
-
if (BINDING_CONTAINER_TYPES.has(current.type)) {
|
|
320
|
-
const constructor = findPriorNewConstructorInContainer(current, receiver, receiverName, source, sup);
|
|
321
|
-
if (constructor || bindingContainerDeclaresNameBefore(current, receiver, receiverName, source, sup)) {
|
|
322
|
-
return constructor;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
current = current.parent;
|
|
326
|
-
}
|
|
327
|
-
return findPriorNewConstructorInContainer(rootOf(receiver), receiver, receiverName, source, sup);
|
|
328
|
-
}
|
|
329
|
-
function findPriorNewConstructorInContainer(node, receiver, receiverName, source, sup) {
|
|
330
|
-
let constructor = null;
|
|
331
|
-
const visit = (current) => {
|
|
332
|
-
if (current.startIndex >= receiver.startIndex) {
|
|
333
|
-
return true;
|
|
334
|
-
}
|
|
335
|
-
if (current !== node && isSkippableBindingContainer(current, receiver)) {
|
|
336
|
-
return true;
|
|
337
|
-
}
|
|
338
|
-
if (current.type === "variable_declarator") {
|
|
339
|
-
const name = current.childForFieldName("name") ?? current.child(0);
|
|
340
|
-
const value = current.childForFieldName("value");
|
|
341
|
-
if (name &&
|
|
342
|
-
value &&
|
|
343
|
-
(value.type === "new_expression" ||
|
|
344
|
-
value.type === "object_creation_expression" ||
|
|
345
|
-
sup.nodeTypes.identifier.includes(value.type)) &&
|
|
346
|
-
sup.nodeTypes.identifier.includes(name.type) &&
|
|
347
|
-
sliceText(name, source) === receiverName) {
|
|
348
|
-
const candidate = constructorNameNode(value, sup);
|
|
349
|
-
if (!candidate) {
|
|
350
|
-
return true;
|
|
351
|
-
}
|
|
352
|
-
if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
|
|
353
|
-
constructor = null;
|
|
354
|
-
return false;
|
|
355
|
-
}
|
|
356
|
-
constructor = candidate;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
if (current.type === "assignment" || current.type === "let_declaration") {
|
|
360
|
-
const candidate = constructorFromAssignmentLike(current, receiverName, source, sup);
|
|
361
|
-
if (candidate) {
|
|
362
|
-
if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
|
|
363
|
-
constructor = null;
|
|
364
|
-
return false;
|
|
365
|
-
}
|
|
366
|
-
constructor = candidate;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
if (current.type === "local_variable_declaration" ||
|
|
370
|
-
current.type === "local_declaration_statement" ||
|
|
371
|
-
current.type === "variable_declaration") {
|
|
372
|
-
const candidate = constructorFromTypedLocalDeclaration(current, receiverName, source, sup);
|
|
373
|
-
if (candidate) {
|
|
374
|
-
if (constructor && sliceText(constructor, source) !== sliceText(candidate, source)) {
|
|
375
|
-
constructor = null;
|
|
376
|
-
return false;
|
|
377
|
-
}
|
|
378
|
-
constructor = candidate;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
for (const child of current.namedChildren) {
|
|
382
|
-
if (!visit(child)) {
|
|
383
|
-
return false;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
return true;
|
|
387
|
-
};
|
|
388
|
-
visit(node);
|
|
389
|
-
return constructor;
|
|
390
|
-
}
|
|
391
|
-
function constructorFromTypedLocalDeclaration(node, receiverName, source, sup) {
|
|
392
|
-
if (sup.id !== "csharp" && sup.id !== "java")
|
|
393
|
-
return null;
|
|
394
|
-
const text = sliceText(node, source);
|
|
395
|
-
const typeNameSource = sup.id === "java" ? JAVA_CONSTANT_SOURCE : CSHARP_CONSTANT_SOURCE;
|
|
396
|
-
const match = text.match(new RegExp(String.raw `^\s*(${typeNameSource})\s+${escapeRegExp(receiverName)}\s*=\s*new\s+(${typeNameSource})(?![\p{L}\p{Nl}\p{Sc}\p{Pc}\p{Nd}\p{Mn}\p{Mc}\p{Cf}])`, "u"));
|
|
397
|
-
const typeName = match?.[2] ?? match?.[1];
|
|
398
|
-
return typeName ? findNamedChildText(node, typeName, source, sup) : null;
|
|
399
|
-
}
|
|
400
|
-
function bindingContainerDeclaresNameBefore(node, receiver, receiverName, source, sup) {
|
|
401
|
-
const visit = (current) => {
|
|
402
|
-
if (current.startIndex >= receiver.startIndex) {
|
|
403
|
-
return false;
|
|
404
|
-
}
|
|
405
|
-
if (current !== node && isSkippableBindingContainer(current, receiver)) {
|
|
406
|
-
return false;
|
|
407
|
-
}
|
|
408
|
-
if (BINDING_DECLARATION_TYPES.has(current.type)) {
|
|
409
|
-
const name = current.childForFieldName("name") ?? current.child(0);
|
|
410
|
-
if (name && sup.nodeTypes.identifier.includes(name.type) && sliceText(name, source) === receiverName) {
|
|
411
|
-
return true;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
for (const child of current.namedChildren) {
|
|
415
|
-
if (visit(child)) {
|
|
416
|
-
return true;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
return false;
|
|
420
|
-
};
|
|
421
|
-
return visit(node);
|
|
422
|
-
}
|
|
423
|
-
function isSkippableBindingContainer(node, receiver) {
|
|
424
|
-
return BINDING_CONTAINER_TYPES.has(node.type) && !nodeContainsIndex(node, receiver.startIndex);
|
|
425
|
-
}
|
|
426
|
-
function nodeContainsIndex(node, index) {
|
|
427
|
-
return node.startIndex <= index && node.endIndex >= index;
|
|
428
|
-
}
|
|
429
|
-
function constructorFromAssignmentLike(node, receiverName, source, sup) {
|
|
430
|
-
const text = sliceText(node, source);
|
|
431
|
-
if (!new RegExp(String.raw `(?<!${IDENTIFIER_BOUNDARY_SOURCE})${escapeRegExp(receiverName)}(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u").test(text))
|
|
432
|
-
return null;
|
|
433
|
-
if (sup.id === "ruby") {
|
|
434
|
-
const match = text.match(new RegExp(String.raw `^\s*${escapeRegExp(receiverName)}\s*=\s*(${RUBY_CONSTANT_SOURCE})\.new(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u"));
|
|
435
|
-
if (!match?.[1])
|
|
436
|
-
return null;
|
|
437
|
-
return findNamedChildText(node, match[1], source, sup);
|
|
438
|
-
}
|
|
439
|
-
if (sup.id === "rust") {
|
|
440
|
-
const match = text.match(new RegExp(String.raw `^\s*(?:let\s+)?${escapeRegExp(receiverName)}\s*=\s*(${RUST_CONSTANT_SOURCE})(?!${IDENTIFIER_BOUNDARY_SOURCE})`, "u"));
|
|
441
|
-
if (!match?.[1])
|
|
442
|
-
return null;
|
|
443
|
-
return findNamedChildText(node, match[1], source, sup);
|
|
444
|
-
}
|
|
445
|
-
return null;
|
|
446
|
-
}
|
|
447
|
-
function findNamedChildText(node, name, source, sup) {
|
|
448
|
-
const isNameNode = (candidate) => (sup.nodeTypes.identifier.includes(candidate.type) ||
|
|
449
|
-
candidate.type === "type_identifier" ||
|
|
450
|
-
candidate.type === "constant") &&
|
|
451
|
-
sliceText(candidate, source) === name;
|
|
452
|
-
const visit = (current) => {
|
|
453
|
-
if (isNameNode(current))
|
|
454
|
-
return current;
|
|
455
|
-
for (const child of current.namedChildren) {
|
|
456
|
-
const hit = visit(child);
|
|
457
|
-
if (hit)
|
|
458
|
-
return hit;
|
|
459
|
-
}
|
|
460
|
-
return null;
|
|
461
|
-
};
|
|
462
|
-
return visit(node);
|
|
463
|
-
}
|
|
464
256
|
async function resolveMemberDefinitionForBase(index, baseDef, member) {
|
|
465
257
|
const targetContext = await ensureParsedContext(baseDef.file, undefined, index.languageExtensions);
|
|
466
258
|
const start = baseDef.range.start;
|
|
@@ -486,16 +278,20 @@ async function resolveMemberDefinitionForBase(index, baseDef, member) {
|
|
|
486
278
|
function findReceiverMemberDefinition(locals, member, receiverDef, container, targetContext, normalizeIdentifier, memberScope = "any") {
|
|
487
279
|
const memberPredicate = memberScope === "any"
|
|
488
280
|
? undefined
|
|
489
|
-
: (local) =>
|
|
281
|
+
: (local) => matchesReceiverMemberScope(local, memberScope, targetContext, container);
|
|
490
282
|
const containerHit = memberScope === "any"
|
|
491
283
|
? findLocalWithinNode(locals, member, container, normalizeIdentifier)
|
|
492
284
|
: findDirectLocalWithinNode(locals, member, container, targetContext, normalizeIdentifier, memberPredicate);
|
|
493
285
|
if (containerHit)
|
|
494
286
|
return containerHit;
|
|
495
|
-
if (targetContext.sup.id
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
287
|
+
if (targetContext.sup.id === "rust") {
|
|
288
|
+
const implNode = findRustImplForType(targetContext.tree.rootNode, receiverDef.localName, targetContext.source);
|
|
289
|
+
return implNode ? findLocalWithinNode(locals, member, implNode, normalizeIdentifier) : undefined;
|
|
290
|
+
}
|
|
291
|
+
if (targetContext.sup.id === "go") {
|
|
292
|
+
return findGoReceiverMember(locals, member, receiverDef.localName, targetContext, normalizeIdentifier);
|
|
293
|
+
}
|
|
294
|
+
return undefined;
|
|
499
295
|
}
|
|
500
296
|
function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name) => name, predicate) {
|
|
501
297
|
const containerStart = node.startIndex;
|
|
@@ -512,6 +308,28 @@ function findLocalWithinNode(locals, member, node, normalizeIdentifier = (name)
|
|
|
512
308
|
(!predicate || predicate(local)));
|
|
513
309
|
});
|
|
514
310
|
}
|
|
311
|
+
function matchesReceiverMemberScope(local, memberScope, targetContext, container) {
|
|
312
|
+
if (memberScope === "any")
|
|
313
|
+
return true;
|
|
314
|
+
return hasStaticModifier(local, targetContext, container) === (memberScope === "static");
|
|
315
|
+
}
|
|
316
|
+
function nodeDeclaresStatic(node, source) {
|
|
317
|
+
if (node.type === "static" || node.type === "static_modifier")
|
|
318
|
+
return true;
|
|
319
|
+
if (node.type === "storage_class_specifier" || node.type === "modifier" || node.type === "property_modifier") {
|
|
320
|
+
return sliceText(node, source).trim() === "static";
|
|
321
|
+
}
|
|
322
|
+
if (node.type === "modifiers") {
|
|
323
|
+
for (let childIndex = 0;; childIndex += 1) {
|
|
324
|
+
const child = node.child(childIndex);
|
|
325
|
+
if (!child)
|
|
326
|
+
break;
|
|
327
|
+
if (nodeDeclaresStatic(child, source))
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
515
333
|
function hasStaticModifier(local, targetContext, container) {
|
|
516
334
|
const position = {
|
|
517
335
|
row: local.range.start.line - 1,
|
|
@@ -523,7 +341,7 @@ function hasStaticModifier(local, targetContext, container) {
|
|
|
523
341
|
const child = current.child(childIndex);
|
|
524
342
|
if (!child)
|
|
525
343
|
break;
|
|
526
|
-
if (child.
|
|
344
|
+
if (nodeDeclaresStatic(child, targetContext.source))
|
|
527
345
|
return true;
|
|
528
346
|
}
|
|
529
347
|
current = current.parent;
|
|
@@ -571,7 +389,7 @@ function findDirectLocalWithinNode(locals, member, container, targetContext, nor
|
|
|
571
389
|
let current = targetContext.tree.rootNode.descendantForPosition(position, position).parent;
|
|
572
390
|
let isDeclarationParent = true;
|
|
573
391
|
while (current && current !== container) {
|
|
574
|
-
const isDirectBody = current.type === "statement_block" && current.parent === container;
|
|
392
|
+
const isDirectBody = (current.type === "statement_block" || current.type === "block") && current.parent === container;
|
|
575
393
|
if (!isDeclarationParent &&
|
|
576
394
|
!isDirectBody &&
|
|
577
395
|
((current.type === "class_body" && current.parent !== container) ||
|
|
@@ -606,6 +424,318 @@ function findRustImplForType(root, typeName, source) {
|
|
|
606
424
|
visit(root);
|
|
607
425
|
return found;
|
|
608
426
|
}
|
|
427
|
+
const GO_EMBED_DEPTH = 16;
|
|
428
|
+
function goMethodReceiverTypeName(methodNode, source, sup) {
|
|
429
|
+
const receiver = methodNode.childForFieldName("receiver");
|
|
430
|
+
if (!receiver)
|
|
431
|
+
return null;
|
|
432
|
+
const parameter = receiver.namedChildren.find((child) => child.type === "parameter_declaration") ?? receiver.namedChildren[0] ?? null;
|
|
433
|
+
const typeNode = parameter?.childForFieldName("type") ?? null;
|
|
434
|
+
if (!typeNode)
|
|
435
|
+
return null;
|
|
436
|
+
const named = unwrapNamedType(typeNode, sup);
|
|
437
|
+
return named ? sliceText(named, source) : null;
|
|
438
|
+
}
|
|
439
|
+
function goTypeSpecNamed(root, typeName, source, normalizeIdentifier) {
|
|
440
|
+
const normalized = normalizeIdentifier(typeName);
|
|
441
|
+
let found = null;
|
|
442
|
+
const visit = (node) => {
|
|
443
|
+
if (node.type === "type_spec") {
|
|
444
|
+
const name = node.childForFieldName("name");
|
|
445
|
+
if (name && normalizeIdentifier(sliceText(name, source)) === normalized) {
|
|
446
|
+
found = node;
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
for (const child of node.namedChildren) {
|
|
451
|
+
if (!visit(child))
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
return true;
|
|
455
|
+
};
|
|
456
|
+
visit(root);
|
|
457
|
+
return found;
|
|
458
|
+
}
|
|
459
|
+
function goEmbeddedTypeNames(typeName, targetContext, normalizeIdentifier) {
|
|
460
|
+
const spec = goTypeSpecNamed(targetContext.tree.rootNode, typeName, targetContext.source, normalizeIdentifier);
|
|
461
|
+
if (!spec)
|
|
462
|
+
return [];
|
|
463
|
+
const typeNode = spec.childForFieldName("type");
|
|
464
|
+
if (!typeNode)
|
|
465
|
+
return [];
|
|
466
|
+
const names = [];
|
|
467
|
+
const visit = (node) => {
|
|
468
|
+
if (node.type === "field_declaration") {
|
|
469
|
+
if (node.childForFieldName("name"))
|
|
470
|
+
return;
|
|
471
|
+
const fieldType = node.childForFieldName("type");
|
|
472
|
+
const named = fieldType ? unwrapNamedType(fieldType, targetContext.sup) : null;
|
|
473
|
+
if (named)
|
|
474
|
+
names.push(sliceText(named, targetContext.source));
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
for (const child of node.namedChildren)
|
|
478
|
+
visit(child);
|
|
479
|
+
};
|
|
480
|
+
visit(typeNode);
|
|
481
|
+
return names;
|
|
482
|
+
}
|
|
483
|
+
function goMethodsNamedOnType(locals, member, typeName, targetContext, normalizeIdentifier) {
|
|
484
|
+
const matches = [];
|
|
485
|
+
const visit = (node) => {
|
|
486
|
+
if (node.type === "method_declaration") {
|
|
487
|
+
const receiverType = goMethodReceiverTypeName(node, targetContext.source, targetContext.sup);
|
|
488
|
+
if (receiverType && normalizeIdentifier(receiverType) === normalizeIdentifier(typeName)) {
|
|
489
|
+
const local = findLocalWithinNode(locals, member, node, normalizeIdentifier);
|
|
490
|
+
if (local && !matches.includes(local))
|
|
491
|
+
matches.push(local);
|
|
492
|
+
}
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
for (const child of node.namedChildren)
|
|
496
|
+
visit(child);
|
|
497
|
+
};
|
|
498
|
+
visit(targetContext.tree.rootNode);
|
|
499
|
+
return matches;
|
|
500
|
+
}
|
|
501
|
+
function findGoReceiverMember(locals, member, typeName, targetContext, normalizeIdentifier) {
|
|
502
|
+
const visited = new Set();
|
|
503
|
+
let level = [typeName];
|
|
504
|
+
for (let depth = 0; depth < GO_EMBED_DEPTH && level.length; depth += 1) {
|
|
505
|
+
const matches = [];
|
|
506
|
+
const next = [];
|
|
507
|
+
for (const currentType of level) {
|
|
508
|
+
if (visited.has(currentType))
|
|
509
|
+
continue;
|
|
510
|
+
visited.add(currentType);
|
|
511
|
+
for (const method of goMethodsNamedOnType(locals, member, currentType, targetContext, normalizeIdentifier)) {
|
|
512
|
+
if (!matches.includes(method))
|
|
513
|
+
matches.push(method);
|
|
514
|
+
}
|
|
515
|
+
for (const embedded of goEmbeddedTypeNames(currentType, targetContext, normalizeIdentifier)) {
|
|
516
|
+
if (!visited.has(embedded) && !next.includes(embedded))
|
|
517
|
+
next.push(embedded);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
if (matches.length === 1)
|
|
521
|
+
return matches[0];
|
|
522
|
+
if (matches.length > 1)
|
|
523
|
+
return undefined;
|
|
524
|
+
level = next;
|
|
525
|
+
}
|
|
526
|
+
return undefined;
|
|
527
|
+
}
|
|
528
|
+
const PYTHON_SUPERTYPE_DEPTH = 16;
|
|
529
|
+
function pythonClassKey(def) {
|
|
530
|
+
const start = def.range.start;
|
|
531
|
+
return `${fileIdentityKey(def.file)}:${start.index ?? `${start.line}:${start.column}`}`;
|
|
532
|
+
}
|
|
533
|
+
async function resolvePythonReceiverMember(index, mod, node, obj, member, source, sup, resolveExpression) {
|
|
534
|
+
const classRef = await pythonReceiverClassRef(index, mod, node, obj, source, sup, resolveExpression);
|
|
535
|
+
if (!classRef)
|
|
536
|
+
return undefined;
|
|
537
|
+
return lookupPythonClassMember(index, classRef, member);
|
|
538
|
+
}
|
|
539
|
+
async function pythonReceiverClassRef(index, mod, node, obj, source, sup, resolveExpression) {
|
|
540
|
+
const receiverName = sliceText(obj, source);
|
|
541
|
+
if (receiverName === "self" || receiverName === "cls") {
|
|
542
|
+
const container = findEnclosingClassContainer(node);
|
|
543
|
+
if (!container)
|
|
544
|
+
return null;
|
|
545
|
+
const nameNode = container.childForFieldName("name");
|
|
546
|
+
if (!nameNode)
|
|
547
|
+
return null;
|
|
548
|
+
const className = sliceText(nameNode, source);
|
|
549
|
+
const def = mod.locals.find((local) => {
|
|
550
|
+
const startIndex = local.range.start.index;
|
|
551
|
+
const endIndex = local.range.end.index;
|
|
552
|
+
return (local.kind === SymbolKind.Class &&
|
|
553
|
+
local.localName === className &&
|
|
554
|
+
startIndex !== undefined &&
|
|
555
|
+
endIndex !== undefined &&
|
|
556
|
+
startIndex >= container.startIndex &&
|
|
557
|
+
endIndex <= container.endIndex);
|
|
558
|
+
});
|
|
559
|
+
if (!def)
|
|
560
|
+
return null;
|
|
561
|
+
return pythonClassRefFromDef(index, def);
|
|
562
|
+
}
|
|
563
|
+
let classDef;
|
|
564
|
+
const constructor = receiverConstructorExpression(obj, source, sup);
|
|
565
|
+
if (constructor) {
|
|
566
|
+
const result = await resolveExpression(constructor);
|
|
567
|
+
if (result?.kind === "resolved" && result.def.kind === SymbolKind.Class) {
|
|
568
|
+
classDef = result.def;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
if (!classDef) {
|
|
572
|
+
const direct = await resolveExpression(obj);
|
|
573
|
+
if (direct?.kind === "resolved" && direct.def.kind === SymbolKind.Class) {
|
|
574
|
+
classDef = direct.def;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (!classDef)
|
|
578
|
+
return null;
|
|
579
|
+
return pythonClassRefFromDef(index, classDef);
|
|
580
|
+
}
|
|
581
|
+
async function pythonClassRefFromDef(index, def) {
|
|
582
|
+
const module = index.byFile.get(fileIdentityKey(def.file));
|
|
583
|
+
if (!module)
|
|
584
|
+
return null;
|
|
585
|
+
const context = await ensureParsedContext(def.file, undefined, index.languageExtensions);
|
|
586
|
+
const start = def.range.start;
|
|
587
|
+
const position = {
|
|
588
|
+
row: start.line - 1,
|
|
589
|
+
column: start.column - 1,
|
|
590
|
+
};
|
|
591
|
+
let current = context.tree.rootNode.descendantForPosition(position, position);
|
|
592
|
+
while (current && current.type !== "class_definition") {
|
|
593
|
+
current = current.parent;
|
|
594
|
+
}
|
|
595
|
+
if (!current)
|
|
596
|
+
return null;
|
|
597
|
+
return { def, container: current, context, module };
|
|
598
|
+
}
|
|
599
|
+
function pythonMembersOnClass(classRef, member) {
|
|
600
|
+
const normalizeIdentifier = classRef.context.sup.normalizeIdentifier;
|
|
601
|
+
const direct = findDirectLocalWithinNode(classRef.module.locals, member, classRef.container, classRef.context, normalizeIdentifier);
|
|
602
|
+
if (direct)
|
|
603
|
+
return [direct];
|
|
604
|
+
const attribute = findPythonInstanceAttributeWithinClass(classRef.module.locals, member, classRef.container, classRef.context, normalizeIdentifier);
|
|
605
|
+
return attribute ? [attribute] : [];
|
|
606
|
+
}
|
|
607
|
+
function findPythonInstanceAttributeWithinClass(locals, member, container, targetContext, normalizeIdentifier) {
|
|
608
|
+
const containerStart = container.startIndex;
|
|
609
|
+
const containerEnd = container.endIndex;
|
|
610
|
+
const normalizedMember = normalizeIdentifier(member);
|
|
611
|
+
for (const local of locals) {
|
|
612
|
+
const startIndex = local.range.start.index;
|
|
613
|
+
const endIndex = local.range.end.index;
|
|
614
|
+
if (normalizeIdentifier(local.localName) !== normalizedMember ||
|
|
615
|
+
startIndex === undefined ||
|
|
616
|
+
endIndex === undefined ||
|
|
617
|
+
startIndex < containerStart ||
|
|
618
|
+
endIndex > containerEnd) {
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
621
|
+
const start = local.range.start;
|
|
622
|
+
const position = {
|
|
623
|
+
row: start.line - 1,
|
|
624
|
+
column: start.column - 1,
|
|
625
|
+
};
|
|
626
|
+
const nameNode = targetContext.tree.rootNode.descendantForPosition(position, position);
|
|
627
|
+
if (isPythonReceiverAttributeAssignmentName(nameNode))
|
|
628
|
+
return local;
|
|
629
|
+
}
|
|
630
|
+
return undefined;
|
|
631
|
+
}
|
|
632
|
+
function pythonBaseIdentifierNodes(classNode) {
|
|
633
|
+
const bases = classNode.childForFieldName("superclasses") ??
|
|
634
|
+
(classNode.namedChildren ?? []).find((child) => child.type === "argument_list");
|
|
635
|
+
if (!bases)
|
|
636
|
+
return [];
|
|
637
|
+
const names = [];
|
|
638
|
+
const visit = (node) => {
|
|
639
|
+
if (node.type === "keyword_argument" || node.type === "dictionary_splat" || node.type === "list_splat") {
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
if (node.type === "identifier") {
|
|
643
|
+
names.push(node);
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
if (node.type === "subscript") {
|
|
647
|
+
const value = node.childForFieldName("value");
|
|
648
|
+
if (value)
|
|
649
|
+
visit(value);
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
for (const child of node.namedChildren)
|
|
653
|
+
visit(child);
|
|
654
|
+
};
|
|
655
|
+
visit(bases);
|
|
656
|
+
return names;
|
|
657
|
+
}
|
|
658
|
+
function resolvePythonNamedClass(index, mod, name) {
|
|
659
|
+
const classes = mod.locals.filter((local) => local.kind === SymbolKind.Class && local.localName === name);
|
|
660
|
+
const topLevel = classes.filter((local) => !local.isMember);
|
|
661
|
+
const candidates = topLevel.length ? topLevel : classes;
|
|
662
|
+
if (candidates.length === 1)
|
|
663
|
+
return candidates[0];
|
|
664
|
+
if (candidates.length > 1)
|
|
665
|
+
return undefined;
|
|
666
|
+
for (const imp of mod.imports) {
|
|
667
|
+
if (imp.kind === "named" && imp.local === name) {
|
|
668
|
+
const result = resolveImported(index, imp, imp.imported);
|
|
669
|
+
if (result && !("namespace" in result) && result.kind === SymbolKind.Class)
|
|
670
|
+
return result;
|
|
671
|
+
}
|
|
672
|
+
if (imp.kind === "star") {
|
|
673
|
+
const result = resolveImported(index, imp, name);
|
|
674
|
+
if (result && !("namespace" in result) && result.kind === SymbolKind.Class)
|
|
675
|
+
return result;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
const exported = resolveExport(index, mod.file, name, { preferredKind: SymbolKind.Class, allowLocalFallback: false });
|
|
679
|
+
if (exported?.kind === "resolved" && exported.def.kind === SymbolKind.Class)
|
|
680
|
+
return exported.def;
|
|
681
|
+
return undefined;
|
|
682
|
+
}
|
|
683
|
+
async function pythonBaseClassRefs(index, classRef) {
|
|
684
|
+
const names = pythonBaseIdentifierNodes(classRef.container);
|
|
685
|
+
const refs = [];
|
|
686
|
+
const seen = new Set();
|
|
687
|
+
for (const nameNode of names) {
|
|
688
|
+
const def = resolvePythonNamedClass(index, classRef.module, sliceText(nameNode, classRef.context.source));
|
|
689
|
+
if (!def)
|
|
690
|
+
continue;
|
|
691
|
+
const key = pythonClassKey(def);
|
|
692
|
+
if (seen.has(key))
|
|
693
|
+
continue;
|
|
694
|
+
seen.add(key);
|
|
695
|
+
const ref = await pythonClassRefFromDef(index, def);
|
|
696
|
+
if (ref)
|
|
697
|
+
refs.push(ref);
|
|
698
|
+
}
|
|
699
|
+
return refs;
|
|
700
|
+
}
|
|
701
|
+
async function lookupPythonClassMember(index, start, member) {
|
|
702
|
+
const own = pythonMembersOnClass(start, member);
|
|
703
|
+
if (own.length === 1)
|
|
704
|
+
return own[0];
|
|
705
|
+
if (own.length > 1)
|
|
706
|
+
return undefined;
|
|
707
|
+
let level = await pythonBaseClassRefs(index, start);
|
|
708
|
+
const visited = new Set([pythonClassKey(start.def), ...level.map((base) => pythonClassKey(base.def))]);
|
|
709
|
+
for (let depth = 0; depth < PYTHON_SUPERTYPE_DEPTH && level.length; depth += 1) {
|
|
710
|
+
const matches = [];
|
|
711
|
+
const seenMatch = new Set();
|
|
712
|
+
for (const base of level) {
|
|
713
|
+
for (const hit of pythonMembersOnClass(base, member)) {
|
|
714
|
+
const key = pythonClassKey(hit);
|
|
715
|
+
if (seenMatch.has(key))
|
|
716
|
+
continue;
|
|
717
|
+
seenMatch.add(key);
|
|
718
|
+
matches.push(hit);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
if (matches.length === 1)
|
|
722
|
+
return matches[0];
|
|
723
|
+
if (matches.length > 1)
|
|
724
|
+
return undefined;
|
|
725
|
+
const next = [];
|
|
726
|
+
for (const base of level) {
|
|
727
|
+
for (const parent of await pythonBaseClassRefs(index, base)) {
|
|
728
|
+
const key = pythonClassKey(parent.def);
|
|
729
|
+
if (visited.has(key))
|
|
730
|
+
continue;
|
|
731
|
+
visited.add(key);
|
|
732
|
+
next.push(parent);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
level = next;
|
|
736
|
+
}
|
|
737
|
+
return undefined;
|
|
738
|
+
}
|
|
609
739
|
function escapeRegExp(value) {
|
|
610
740
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
611
741
|
}
|