@lzehrung/codegraph 2.3.31 → 3.0.0
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/README.md +33 -141
- package/codegraph-skill/codegraph/SKILL.md +8 -6
- package/dist/agent/artifact.d.ts +2 -0
- package/dist/agent/artifact.d.ts.map +1 -1
- package/dist/agent/artifact.js.map +1 -1
- package/dist/agent/call-hierarchy.js +2 -4
- package/dist/agent/call-hierarchy.js.map +1 -1
- package/dist/agent/explore.d.ts +1 -1
- package/dist/agent/explore.d.ts.map +1 -1
- package/dist/agent/explore.js +3 -2
- package/dist/agent/explore.js.map +1 -1
- package/dist/agent/refactor-plan.js +2 -4
- 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 +4 -3
- package/dist/agent/rename-preview.js.map +1 -1
- package/dist/agent/search.d.ts.map +1 -1
- package/dist/agent/search.js +5 -3
- package/dist/agent/search.js.map +1 -1
- package/dist/agent/semantic-symbols.d.ts.map +1 -1
- package/dist/agent/semantic-symbols.js +2 -3
- package/dist/agent/semantic-symbols.js.map +1 -1
- package/dist/agent/session.d.ts +3 -0
- package/dist/agent/session.d.ts.map +1 -1
- package/dist/agent/session.js +10 -2
- package/dist/agent/session.js.map +1 -1
- package/dist/agent/type-hierarchy.js +2 -4
- package/dist/agent/type-hierarchy.js.map +1 -1
- package/dist/agent/workspace-symbols.d.ts.map +1 -1
- package/dist/agent/workspace-symbols.js +2 -3
- package/dist/agent/workspace-symbols.js.map +1 -1
- package/dist/agent-tools.d.ts +0 -4
- package/dist/agent-tools.d.ts.map +1 -1
- package/dist/agent-tools.js +3 -6
- package/dist/agent-tools.js.map +1 -1
- package/dist/analysis-summary.d.ts +8 -4
- package/dist/analysis-summary.d.ts.map +1 -1
- package/dist/analysis-summary.js +15 -66
- package/dist/analysis-summary.js.map +1 -1
- package/dist/bin/cli.js +51145 -41770
- package/dist/bin/query-index-worker.js +122 -82
- package/dist/cli/affected.d.ts.map +1 -1
- package/dist/cli/affected.js +4 -1
- package/dist/cli/affected.js.map +1 -1
- package/dist/cli/command-catalog.js +1 -1
- package/dist/cli/command-catalog.js.map +1 -1
- package/dist/cli/command-table.d.ts.map +1 -1
- package/dist/cli/command-table.js +9 -17
- package/dist/cli/command-table.js.map +1 -1
- package/dist/cli/context.js +10 -10
- package/dist/cli/context.js.map +1 -1
- package/dist/cli/drift.d.ts +0 -2
- package/dist/cli/drift.d.ts.map +1 -1
- package/dist/cli/drift.js +0 -1
- package/dist/cli/drift.js.map +1 -1
- package/dist/cli/graph-delta.d.ts +0 -2
- package/dist/cli/graph-delta.d.ts.map +1 -1
- package/dist/cli/graph-delta.js +0 -4
- package/dist/cli/graph-delta.js.map +1 -1
- package/dist/cli/graph-queries.d.ts.map +1 -1
- package/dist/cli/graph-queries.js +27 -1
- package/dist/cli/graph-queries.js.map +1 -1
- package/dist/cli/graph.d.ts +0 -3
- package/dist/cli/graph.d.ts.map +1 -1
- package/dist/cli/graph.js +4 -14
- package/dist/cli/graph.js.map +1 -1
- package/dist/cli/help.d.ts +34 -34
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +9 -14
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/impact.d.ts +0 -2
- package/dist/cli/impact.d.ts.map +1 -1
- package/dist/cli/impact.js +0 -1
- package/dist/cli/impact.js.map +1 -1
- package/dist/cli/index.d.ts +0 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +5 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/inspect.d.ts +0 -2
- package/dist/cli/inspect.d.ts.map +1 -1
- package/dist/cli/inspect.js +5 -8
- package/dist/cli/inspect.js.map +1 -1
- package/dist/cli/invocation-context.d.ts +0 -3
- package/dist/cli/invocation-context.d.ts.map +1 -1
- package/dist/cli/invocation-context.js +4 -16
- package/dist/cli/invocation-context.js.map +1 -1
- package/dist/cli/navigation.d.ts +0 -2
- package/dist/cli/navigation.d.ts.map +1 -1
- package/dist/cli/navigation.js +0 -1
- package/dist/cli/navigation.js.map +1 -1
- package/dist/cli/options.d.ts.map +1 -1
- package/dist/cli/options.js +4 -14
- package/dist/cli/options.js.map +1 -1
- package/dist/cli/review.d.ts +0 -2
- package/dist/cli/review.d.ts.map +1 -1
- package/dist/cli/review.js +0 -5
- package/dist/cli/review.js.map +1 -1
- package/dist/cli/root-policy.d.ts +0 -2
- package/dist/cli/root-policy.d.ts.map +1 -1
- package/dist/cli/root-policy.js +0 -8
- package/dist/cli/root-policy.js.map +1 -1
- package/dist/cli/server.d.ts.map +1 -1
- package/dist/cli/server.js +0 -2
- package/dist/cli/server.js.map +1 -1
- package/dist/drift/artifact.d.ts.map +1 -1
- package/dist/drift/artifact.js +15 -18
- package/dist/drift/artifact.js.map +1 -1
- package/dist/drift/compare.js +1 -1
- package/dist/drift/compare.js.map +1 -1
- package/dist/drift/git.d.ts.map +1 -1
- package/dist/drift/git.js +0 -1
- package/dist/drift/git.js.map +1 -1
- package/dist/drift/snapshot.d.ts.map +1 -1
- package/dist/drift/snapshot.js +5 -7
- package/dist/drift/snapshot.js.map +1 -1
- package/dist/drift/types.d.ts +2 -2
- package/dist/drift/types.d.ts.map +1 -1
- package/dist/drift/types.js.map +1 -1
- package/dist/duplicates/unit-cache.d.ts +0 -1
- package/dist/duplicates/unit-cache.d.ts.map +1 -1
- package/dist/duplicates/unit-cache.js +3 -11
- package/dist/duplicates/unit-cache.js.map +1 -1
- package/dist/duplicates/units.d.ts +5 -5
- package/dist/duplicates/units.d.ts.map +1 -1
- package/dist/duplicates/units.js +25 -88
- package/dist/duplicates/units.js.map +1 -1
- package/dist/graph-builder.d.ts +0 -6
- package/dist/graph-builder.d.ts.map +1 -1
- package/dist/graph-builder.js +6 -11
- package/dist/graph-builder.js.map +1 -1
- package/dist/graph-edge-collector.d.ts +4 -6
- package/dist/graph-edge-collector.d.ts.map +1 -1
- package/dist/graph-edge-collector.js +31 -26
- package/dist/graph-edge-collector.js.map +1 -1
- package/dist/graphs/angularjs.d.ts.map +1 -1
- package/dist/graphs/angularjs.js +2 -1
- package/dist/graphs/angularjs.js.map +1 -1
- package/dist/graphs/edge-resolution.d.ts +4 -1
- package/dist/graphs/edge-resolution.d.ts.map +1 -1
- package/dist/graphs/edge-resolution.js +24 -76
- package/dist/graphs/edge-resolution.js.map +1 -1
- package/dist/graphs/specifiers.d.ts +4 -13
- package/dist/graphs/specifiers.d.ts.map +1 -1
- package/dist/graphs/specifiers.js +80 -173
- package/dist/graphs/specifiers.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/ast.d.ts +20 -0
- package/dist/graphs/symbol-graph-detailed/ast.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/ast.js +154 -15
- package/dist/graphs/symbol-graph-detailed/ast.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts +60 -8
- package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/edge-passes.js +997 -168
- package/dist/graphs/symbol-graph-detailed/edge-passes.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/import-aliases.d.ts +2 -1
- package/dist/graphs/symbol-graph-detailed/import-aliases.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/import-aliases.js +150 -7
- package/dist/graphs/symbol-graph-detailed/import-aliases.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/member-chains.d.ts +1 -0
- package/dist/graphs/symbol-graph-detailed/member-chains.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/member-chains.js +3 -1
- package/dist/graphs/symbol-graph-detailed/member-chains.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts +141 -25
- package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/receiver-calls.js +1015 -166
- package/dist/graphs/symbol-graph-detailed/receiver-calls.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed.js +449 -46
- package/dist/graphs/symbol-graph-detailed.js.map +1 -1
- package/dist/graphs/symbol-graph.d.ts +2 -0
- package/dist/graphs/symbol-graph.d.ts.map +1 -1
- package/dist/graphs/symbol-graph.js +34 -16
- package/dist/graphs/symbol-graph.js.map +1 -1
- package/dist/graphs/types.d.ts +0 -4
- package/dist/graphs/types.d.ts.map +1 -1
- package/dist/graphs.d.ts +1 -1
- package/dist/graphs.d.ts.map +1 -1
- package/dist/impact/call-compatibility/providers/index.d.ts +4 -4
- package/dist/impact/call-compatibility/providers/index.d.ts.map +1 -1
- package/dist/impact/call-compatibility/providers/index.js +6 -6
- package/dist/impact/call-compatibility/providers/index.js.map +1 -1
- package/dist/impact/call-compatibility/providers/types.d.ts +2 -0
- package/dist/impact/call-compatibility/providers/types.d.ts.map +1 -1
- package/dist/impact/call-compatibility/types.d.ts +6 -0
- package/dist/impact/call-compatibility/types.d.ts.map +1 -1
- package/dist/impact/call-compatibility.d.ts.map +1 -1
- package/dist/impact/call-compatibility.js +316 -526
- package/dist/impact/call-compatibility.js.map +1 -1
- package/dist/impact/map.js +1 -0
- package/dist/impact/map.js.map +1 -1
- package/dist/impact/reference-cache.d.ts.map +1 -1
- package/dist/impact/reference-cache.js +2 -2
- package/dist/impact/reference-cache.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/indexer/ambiguous-resolution.d.ts +11 -0
- package/dist/indexer/ambiguous-resolution.d.ts.map +1 -0
- package/dist/indexer/ambiguous-resolution.js +19 -0
- package/dist/indexer/ambiguous-resolution.js.map +1 -0
- package/dist/indexer/build-cache/module-cache.d.ts +39 -1
- package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
- package/dist/indexer/build-cache/module-cache.js +218 -21
- package/dist/indexer/build-cache/module-cache.js.map +1 -1
- package/dist/indexer/build-cache/options.d.ts +30 -44
- package/dist/indexer/build-cache/options.d.ts.map +1 -1
- package/dist/indexer/build-cache/options.js +32 -71
- package/dist/indexer/build-cache/options.js.map +1 -1
- package/dist/indexer/build-cache/project-snapshot.d.ts +3 -3
- package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
- package/dist/indexer/build-cache/project-snapshot.js +164 -84
- package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
- package/dist/indexer/build-cache/reports.d.ts +0 -2
- package/dist/indexer/build-cache/reports.d.ts.map +1 -1
- package/dist/indexer/build-cache/reports.js +0 -97
- package/dist/indexer/build-cache/reports.js.map +1 -1
- package/dist/indexer/build-cache/resolver-environment.d.ts.map +1 -1
- package/dist/indexer/build-cache/resolver-environment.js +32 -2
- package/dist/indexer/build-cache/resolver-environment.js.map +1 -1
- package/dist/indexer/build-cache.d.ts +2 -2
- package/dist/indexer/build-cache.d.ts.map +1 -1
- package/dist/indexer/build-cache.js +2 -2
- package/dist/indexer/build-cache.js.map +1 -1
- package/dist/indexer/build-index.d.ts.map +1 -1
- package/dist/indexer/build-index.js +656 -71
- package/dist/indexer/build-index.js.map +1 -1
- package/dist/indexer/build-workers.d.ts.map +1 -1
- package/dist/indexer/build-workers.js +9 -9
- package/dist/indexer/build-workers.js.map +1 -1
- package/dist/indexer/call-hierarchy.js +1 -1
- package/dist/indexer/call-hierarchy.js.map +1 -1
- package/dist/indexer/callable-identity.d.ts +24 -0
- package/dist/indexer/callable-identity.d.ts.map +1 -0
- package/dist/indexer/callable-identity.js +111 -0
- package/dist/indexer/callable-identity.js.map +1 -0
- package/dist/indexer/compilation-units.d.ts +103 -0
- package/dist/indexer/compilation-units.d.ts.map +1 -0
- package/dist/indexer/compilation-units.js +607 -0
- package/dist/indexer/compilation-units.js.map +1 -0
- package/dist/indexer/cpp-callables.d.ts +25 -0
- package/dist/indexer/cpp-callables.d.ts.map +1 -0
- package/dist/indexer/cpp-callables.js +562 -0
- package/dist/indexer/cpp-callables.js.map +1 -0
- package/dist/indexer/declaration-visibility.d.ts +43 -2
- package/dist/indexer/declaration-visibility.d.ts.map +1 -1
- package/dist/indexer/declaration-visibility.js +158 -2
- package/dist/indexer/declaration-visibility.js.map +1 -1
- package/dist/indexer/expand-star-imports.d.ts +6 -1
- package/dist/indexer/expand-star-imports.d.ts.map +1 -1
- package/dist/indexer/expand-star-imports.js +131 -37
- package/dist/indexer/expand-star-imports.js.map +1 -1
- package/dist/indexer/finalize.d.ts.map +1 -1
- package/dist/indexer/finalize.js +0 -1
- package/dist/indexer/finalize.js.map +1 -1
- package/dist/indexer/import-resolution-tables.d.ts +72 -0
- package/dist/indexer/import-resolution-tables.d.ts.map +1 -0
- package/dist/indexer/import-resolution-tables.js +137 -0
- package/dist/indexer/import-resolution-tables.js.map +1 -0
- package/dist/indexer/import-types.d.ts +54 -0
- package/dist/indexer/import-types.d.ts.map +1 -1
- package/dist/indexer/import-types.js +24 -1
- package/dist/indexer/import-types.js.map +1 -1
- package/dist/indexer/imports/context.d.ts +16 -1
- package/dist/indexer/imports/context.d.ts.map +1 -1
- package/dist/indexer/imports/import-binding-tables.d.ts +13 -1
- package/dist/indexer/imports/import-binding-tables.d.ts.map +1 -1
- package/dist/indexer/imports/import-binding-tables.js +149 -30
- package/dist/indexer/imports/import-binding-tables.js.map +1 -1
- package/dist/indexer/imports/js-text-imports.js +4 -4
- package/dist/indexer/imports/js-text-imports.js.map +1 -1
- package/dist/indexer/imports/native-captures.d.ts.map +1 -1
- package/dist/indexer/imports/native-captures.js +24 -6
- package/dist/indexer/imports/native-captures.js.map +1 -1
- package/dist/indexer/imports/python.d.ts +10 -2
- package/dist/indexer/imports/python.d.ts.map +1 -1
- package/dist/indexer/imports/python.js +128 -112
- package/dist/indexer/imports/python.js.map +1 -1
- package/dist/indexer/imports/text-import-extractors.d.ts.map +1 -1
- package/dist/indexer/imports/text-import-extractors.js +68 -19
- package/dist/indexer/imports/text-import-extractors.js.map +1 -1
- package/dist/indexer/imports.d.ts +3 -4
- package/dist/indexer/imports.d.ts.map +1 -1
- package/dist/indexer/imports.js +116 -72
- package/dist/indexer/imports.js.map +1 -1
- package/dist/indexer/incremental-plan.d.ts +33 -0
- package/dist/indexer/incremental-plan.d.ts.map +1 -1
- package/dist/indexer/incremental-plan.js +203 -1
- package/dist/indexer/incremental-plan.js.map +1 -1
- package/dist/indexer/locals-and-exports.d.ts +3 -2
- package/dist/indexer/locals-and-exports.d.ts.map +1 -1
- package/dist/indexer/locals-and-exports.js +659 -78
- package/dist/indexer/locals-and-exports.js.map +1 -1
- package/dist/indexer/member-selection.d.ts +46 -0
- package/dist/indexer/member-selection.d.ts.map +1 -0
- package/dist/indexer/member-selection.js +169 -0
- package/dist/indexer/member-selection.js.map +1 -0
- package/dist/indexer/name-lookup-policies/c-family.d.ts +7 -0
- package/dist/indexer/name-lookup-policies/c-family.d.ts.map +1 -0
- package/dist/indexer/name-lookup-policies/c-family.js +137 -0
- package/dist/indexer/name-lookup-policies/c-family.js.map +1 -0
- package/dist/indexer/name-lookup-policies/csharp-using-static.d.ts +11 -0
- package/dist/indexer/name-lookup-policies/csharp-using-static.d.ts.map +1 -0
- package/dist/indexer/name-lookup-policies/csharp-using-static.js +136 -0
- package/dist/indexer/name-lookup-policies/csharp-using-static.js.map +1 -0
- package/dist/indexer/name-lookup-policies/implicit-self.d.ts +10 -0
- package/dist/indexer/name-lookup-policies/implicit-self.d.ts.map +1 -0
- package/dist/indexer/name-lookup-policies/implicit-self.js +119 -0
- package/dist/indexer/name-lookup-policies/implicit-self.js.map +1 -0
- package/dist/indexer/name-lookup-policies/index.d.ts +3 -0
- package/dist/indexer/name-lookup-policies/index.d.ts.map +1 -0
- package/dist/indexer/name-lookup-policies/index.js +132 -0
- package/dist/indexer/name-lookup-policies/index.js.map +1 -0
- package/dist/indexer/name-lookup-policies/php.d.ts +3 -0
- package/dist/indexer/name-lookup-policies/php.d.ts.map +1 -0
- package/dist/indexer/name-lookup-policies/php.js +82 -0
- package/dist/indexer/name-lookup-policies/php.js.map +1 -0
- package/dist/indexer/name-resolution-types.d.ts +101 -0
- package/dist/indexer/name-resolution-types.d.ts.map +1 -0
- package/dist/indexer/name-resolution-types.js +2 -0
- package/dist/indexer/name-resolution-types.js.map +1 -0
- package/dist/indexer/name-resolution.d.ts +57 -0
- package/dist/indexer/name-resolution.d.ts.map +1 -0
- package/dist/indexer/name-resolution.js +204 -0
- package/dist/indexer/name-resolution.js.map +1 -0
- package/dist/indexer/navigation-cpp.d.ts +58 -0
- package/dist/indexer/navigation-cpp.d.ts.map +1 -0
- package/dist/indexer/navigation-cpp.js +935 -0
- package/dist/indexer/navigation-cpp.js.map +1 -0
- package/dist/indexer/navigation-goto.d.ts +115 -3
- package/dist/indexer/navigation-goto.d.ts.map +1 -1
- package/dist/indexer/navigation-goto.js +2469 -190
- package/dist/indexer/navigation-goto.js.map +1 -1
- package/dist/indexer/navigation-local.d.ts +21 -2
- package/dist/indexer/navigation-local.d.ts.map +1 -1
- package/dist/indexer/navigation-local.js +520 -63
- package/dist/indexer/navigation-local.js.map +1 -1
- package/dist/indexer/navigation-php.d.ts +66 -0
- package/dist/indexer/navigation-php.d.ts.map +1 -1
- package/dist/indexer/navigation-php.js +287 -4
- package/dist/indexer/navigation-php.js.map +1 -1
- package/dist/indexer/navigation-provenance.d.ts +1 -1
- package/dist/indexer/navigation-provenance.d.ts.map +1 -1
- package/dist/indexer/navigation-provenance.js +4 -13
- package/dist/indexer/navigation-provenance.js.map +1 -1
- package/dist/indexer/navigation-references.d.ts +73 -6
- package/dist/indexer/navigation-references.d.ts.map +1 -1
- package/dist/indexer/navigation-references.js +661 -67
- package/dist/indexer/navigation-references.js.map +1 -1
- package/dist/indexer/navigation-resolve.d.ts +46 -2
- package/dist/indexer/navigation-resolve.d.ts.map +1 -1
- package/dist/indexer/navigation-resolve.js +599 -193
- package/dist/indexer/navigation-resolve.js.map +1 -1
- package/dist/indexer/navigation.d.ts +29 -2
- package/dist/indexer/navigation.d.ts.map +1 -1
- package/dist/indexer/navigation.js +1092 -153
- package/dist/indexer/navigation.js.map +1 -1
- package/dist/indexer/parse-context.d.ts +2 -3
- package/dist/indexer/parse-context.d.ts.map +1 -1
- package/dist/indexer/parse-context.js +8 -21
- package/dist/indexer/parse-context.js.map +1 -1
- package/dist/indexer/php-namespace-symbols.d.ts +66 -0
- package/dist/indexer/php-namespace-symbols.d.ts.map +1 -0
- package/dist/indexer/php-namespace-symbols.js +342 -0
- package/dist/indexer/php-namespace-symbols.js.map +1 -0
- package/dist/indexer/reference-candidates.d.ts.map +1 -1
- package/dist/indexer/reference-candidates.js +13 -7
- package/dist/indexer/reference-candidates.js.map +1 -1
- package/dist/indexer/reference-context.d.ts +2 -0
- package/dist/indexer/reference-context.d.ts.map +1 -1
- package/dist/indexer/reference-context.js +4 -0
- package/dist/indexer/reference-context.js.map +1 -1
- package/dist/indexer/scope-nodes.d.ts +92 -13
- package/dist/indexer/scope-nodes.d.ts.map +1 -1
- package/dist/indexer/scope-nodes.js +212 -20
- package/dist/indexer/scope-nodes.js.map +1 -1
- package/dist/indexer/scope-types.d.ts +29 -1
- package/dist/indexer/scope-types.d.ts.map +1 -1
- package/dist/indexer/scope.d.ts +2 -3
- package/dist/indexer/scope.d.ts.map +1 -1
- package/dist/indexer/scope.js +968 -47
- package/dist/indexer/scope.js.map +1 -1
- package/dist/indexer/shared-owner-identity.d.ts +53 -0
- package/dist/indexer/shared-owner-identity.d.ts.map +1 -0
- package/dist/indexer/shared-owner-identity.js +460 -0
- package/dist/indexer/shared-owner-identity.js.map +1 -0
- package/dist/indexer/shared.d.ts +1 -1
- package/dist/indexer/shared.d.ts.map +1 -1
- package/dist/indexer/shared.js +1 -1
- package/dist/indexer/shared.js.map +1 -1
- package/dist/indexer/star-import-precedence.d.ts +113 -0
- package/dist/indexer/star-import-precedence.d.ts.map +1 -0
- package/dist/indexer/star-import-precedence.js +402 -0
- package/dist/indexer/star-import-precedence.js.map +1 -0
- package/dist/indexer/symbols.d.ts +3 -1
- package/dist/indexer/symbols.d.ts.map +1 -1
- package/dist/indexer/symbols.js +58 -18
- package/dist/indexer/symbols.js.map +1 -1
- package/dist/indexer/ts-callables.d.ts +42 -0
- package/dist/indexer/ts-callables.d.ts.map +1 -0
- package/dist/indexer/ts-callables.js +233 -0
- package/dist/indexer/ts-callables.js.map +1 -0
- package/dist/indexer/types.d.ts +41 -26
- package/dist/indexer/types.d.ts.map +1 -1
- package/dist/indexer/unused-exports.d.ts +13 -0
- package/dist/indexer/unused-exports.d.ts.map +1 -0
- package/dist/indexer/unused-exports.js +159 -0
- package/dist/indexer/unused-exports.js.map +1 -0
- package/dist/indexer/workspace-symbols.d.ts.map +1 -1
- package/dist/indexer/workspace-symbols.js +3 -2
- package/dist/indexer/workspace-symbols.js.map +1 -1
- package/dist/indexer.d.ts +3 -8
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js +1 -1
- package/dist/indexer.js.map +1 -1
- package/dist/languages/callable-arity.d.ts +223 -0
- package/dist/languages/callable-arity.d.ts.map +1 -0
- package/dist/languages/callable-arity.js +1199 -0
- package/dist/languages/callable-arity.js.map +1 -0
- package/dist/languages/definitions/c-family.d.ts.map +1 -1
- package/dist/languages/definitions/c-family.js +30 -1
- package/dist/languages/definitions/c-family.js.map +1 -1
- package/dist/languages/definitions/c.d.ts +4 -0
- package/dist/languages/definitions/c.d.ts.map +1 -1
- package/dist/languages/definitions/c.js +19 -0
- 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 +12 -0
- 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 +2 -8
- package/dist/languages/definitions/csharp.js.map +1 -1
- package/dist/languages/definitions/go.d.ts.map +1 -1
- package/dist/languages/definitions/go.js +3 -0
- package/dist/languages/definitions/go.js.map +1 -1
- package/dist/languages/definitions/javascript.d.ts.map +1 -1
- package/dist/languages/definitions/javascript.js +10 -1
- package/dist/languages/definitions/javascript.js.map +1 -1
- package/dist/languages/definitions/js-family.d.ts +1 -1
- package/dist/languages/definitions/js-family.d.ts.map +1 -1
- package/dist/languages/definitions/js-family.js +7 -1
- package/dist/languages/definitions/js-family.js.map +1 -1
- package/dist/languages/definitions/php.d.ts.map +1 -1
- package/dist/languages/definitions/php.js +5 -1
- package/dist/languages/definitions/php.js.map +1 -1
- package/dist/languages/definitions/typescript.d.ts.map +1 -1
- package/dist/languages/definitions/typescript.js +8 -1
- 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 +8 -0
- package/dist/languages/definitions/zig.js.map +1 -1
- package/dist/lifecycle/manifest.d.ts.map +1 -1
- package/dist/lifecycle/manifest.js +0 -1
- package/dist/lifecycle/manifest.js.map +1 -1
- package/dist/mcp/handlers.js +14 -7
- package/dist/mcp/handlers.js.map +1 -1
- package/dist/native/byte-index.d.ts +6 -0
- package/dist/native/byte-index.d.ts.map +1 -1
- package/dist/native/byte-index.js +11 -6
- package/dist/native/byte-index.js.map +1 -1
- package/dist/native/contracts.d.ts +2 -3
- package/dist/native/contracts.d.ts.map +1 -1
- package/dist/native/execution.d.ts +9 -9
- package/dist/native/execution.d.ts.map +1 -1
- package/dist/native/execution.js +37 -77
- package/dist/native/execution.js.map +1 -1
- package/dist/native/js-bridge.d.ts +2 -15
- package/dist/native/js-bridge.d.ts.map +1 -1
- package/dist/native/js-bridge.js +2 -15
- package/dist/native/js-bridge.js.map +1 -1
- package/dist/native/query-results.js +2 -2
- package/dist/native/query-results.js.map +1 -1
- package/dist/native/runtime.d.ts +12 -12
- package/dist/native/runtime.d.ts.map +1 -1
- package/dist/native/runtime.js +24 -69
- package/dist/native/runtime.js.map +1 -1
- package/dist/native/tree-sitter-native.d.ts +3 -3
- package/dist/native/tree-sitter-native.d.ts.map +1 -1
- package/dist/native/tree-sitter-native.js +2 -2
- package/dist/native/tree-sitter-native.js.map +1 -1
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +0 -4
- package/dist/presets.js.map +1 -1
- package/dist/review/candidates.d.ts.map +1 -1
- package/dist/review/candidates.js +1 -1
- package/dist/review/candidates.js.map +1 -1
- package/dist/review/deleted.d.ts +3 -3
- package/dist/review/deleted.d.ts.map +1 -1
- package/dist/review/deleted.js +82 -32
- package/dist/review/deleted.js.map +1 -1
- package/dist/review/report.d.ts +1 -0
- package/dist/review/report.d.ts.map +1 -1
- package/dist/review/report.js +1 -1
- package/dist/review/report.js.map +1 -1
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +3 -20
- package/dist/review.js.map +1 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +0 -5
- package/dist/session.js.map +1 -1
- package/dist/sql/navigation.d.ts.map +1 -1
- package/dist/sql/navigation.js +2 -1
- package/dist/sql/navigation.js.map +1 -1
- package/dist/sql/source-graph.d.ts.map +1 -1
- package/dist/sql/source-graph.js +2 -2
- package/dist/sql/source-graph.js.map +1 -1
- package/dist/sqlite/schema.d.ts +1 -1
- package/dist/sqlite/schema.d.ts.map +1 -1
- package/dist/sqlite/schema.js +8 -2
- package/dist/sqlite/schema.js.map +1 -1
- package/dist/sqlite/write.js +2 -2
- package/dist/sqlite/write.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/util/bloom-filter.d.ts +8 -1
- package/dist/util/bloom-filter.d.ts.map +1 -1
- package/dist/util/bloom-filter.js +15 -2
- package/dist/util/bloom-filter.js.map +1 -1
- package/dist/util/glob.d.ts +32 -0
- package/dist/util/glob.d.ts.map +1 -0
- package/dist/util/glob.js +137 -0
- package/dist/util/glob.js.map +1 -0
- package/dist/util/graph-edges.d.ts +19 -1
- package/dist/util/graph-edges.d.ts.map +1 -1
- package/dist/util/graph-edges.js +30 -4
- package/dist/util/graph-edges.js.map +1 -1
- package/dist/util/identifiers.d.ts +15 -0
- package/dist/util/identifiers.d.ts.map +1 -1
- package/dist/util/identifiers.js +35 -0
- package/dist/util/identifiers.js.map +1 -1
- package/dist/util/member-access-tables.d.ts +61 -4
- package/dist/util/member-access-tables.d.ts.map +1 -1
- package/dist/util/member-access-tables.js +139 -19
- package/dist/util/member-access-tables.js.map +1 -1
- package/dist/util/member-access.d.ts +17 -0
- package/dist/util/member-access.d.ts.map +1 -1
- package/dist/util/member-access.js +98 -3
- package/dist/util/member-access.js.map +1 -1
- package/dist/util/project-files.d.ts +2 -10
- package/dist/util/project-files.d.ts.map +1 -1
- package/dist/util/project-files.js +29 -51
- package/dist/util/project-files.js.map +1 -1
- package/dist/util/python-type-checking.d.ts +18 -0
- package/dist/util/python-type-checking.d.ts.map +1 -0
- package/dist/util/python-type-checking.js +160 -0
- package/dist/util/python-type-checking.js.map +1 -0
- package/dist/util/resolution/cargo-targets.d.ts +11 -0
- package/dist/util/resolution/cargo-targets.d.ts.map +1 -1
- package/dist/util/resolution/cargo-targets.js +174 -13
- package/dist/util/resolution/cargo-targets.js.map +1 -1
- package/dist/util/resolution/csharp.d.ts +33 -1
- package/dist/util/resolution/csharp.d.ts.map +1 -1
- package/dist/util/resolution/csharp.js +145 -30
- package/dist/util/resolution/csharp.js.map +1 -1
- package/dist/util/resolution/jvm.d.ts +7 -3
- package/dist/util/resolution/jvm.d.ts.map +1 -1
- package/dist/util/resolution/jvm.js +56 -38
- package/dist/util/resolution/jvm.js.map +1 -1
- package/dist/util/resolution/php.d.ts.map +1 -1
- package/dist/util/resolution/php.js +35 -8
- package/dist/util/resolution/php.js.map +1 -1
- package/dist/util/resolution/python.d.ts +9 -0
- package/dist/util/resolution/python.d.ts.map +1 -1
- package/dist/util/resolution/python.js +46 -0
- package/dist/util/resolution/python.js.map +1 -1
- package/dist/util/resolution/rust.d.ts +0 -1
- package/dist/util/resolution/rust.d.ts.map +1 -1
- package/dist/util/resolution/rust.js +95 -35
- package/dist/util/resolution/rust.js.map +1 -1
- package/dist/util/resolution/specifier-targets.d.ts +44 -0
- package/dist/util/resolution/specifier-targets.d.ts.map +1 -0
- package/dist/util/resolution/specifier-targets.js +152 -0
- package/dist/util/resolution/specifier-targets.js.map +1 -0
- package/dist/util/resolution-candidates.d.ts +5 -0
- package/dist/util/resolution-candidates.d.ts.map +1 -1
- package/dist/util/resolution-candidates.js +16 -3
- package/dist/util/resolution-candidates.js.map +1 -1
- package/dist/util/resolution.d.ts +2 -1
- package/dist/util/resolution.d.ts.map +1 -1
- package/dist/util/resolution.js +101 -15
- package/dist/util/resolution.js.map +1 -1
- package/dist/util/specifiers.d.ts +29 -1
- package/dist/util/specifiers.d.ts.map +1 -1
- package/dist/util/specifiers.js +56 -8
- package/dist/util/specifiers.js.map +1 -1
- package/dist/util/trivia.d.ts.map +1 -1
- package/dist/util/trivia.js +49 -30
- package/dist/util/trivia.js.map +1 -1
- package/dist/util/workspace.d.ts.map +1 -1
- package/dist/util/workspace.js +32 -4
- package/dist/util/workspace.js.map +1 -1
- package/docs/mcp.md +3 -2
- package/package.json +5 -7
- package/dist/impact/call-compatibility/providers/profiles.d.ts +0 -80
- package/dist/impact/call-compatibility/providers/profiles.d.ts.map +0 -1
- package/dist/impact/call-compatibility/providers/profiles.js +0 -164
- package/dist/impact/call-compatibility/providers/profiles.js.map +0 -1
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
+
import { findCommentEnd } from "../../impact/call-compatibility/text-scanner.js";
|
|
3
|
+
import { isGoExportedMemberName } from "../../indexer/declaration-visibility.js";
|
|
4
|
+
import { hasSeparateMemberScopes, inheritsMemberOverloads, selectMember, } from "../../indexer/member-selection.js";
|
|
2
5
|
import { SymbolKind } from "../../indexer/types.js";
|
|
6
|
+
import { supportForFileWithoutHeaderSample } from "../../languages.js";
|
|
7
|
+
import { isJsTsLanguage } from "../../languages/js-family.js";
|
|
3
8
|
import { sliceText } from "../../util/ast.js";
|
|
4
|
-
import { XID_IDENTIFIER_SOURCE } from "../../util/identifiers.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
9
|
+
import { foldPhpIdentifierCase, XID_IDENTIFIER_SOURCE } from "../../util/identifiers.js";
|
|
10
|
+
import { fileIdentityKey } from "../../util/paths.js";
|
|
11
|
+
import { keywordReceiverKind, ownReceiverMemberScope } from "../../util/member-access-tables.js";
|
|
12
|
+
import { getMemberAccessParts, getNavigationExpressionProperty, isMemberAccessNode, isMemberReferencePropertyIdentifier, isReceiverNameNode, receiverKeywordText, } from "../../util/member-access.js";
|
|
13
|
+
import { declarationMemberArity, findFirstNodeByType, isIdentifierType, PARAMETER_LIST_NODE_TYPES } from "./ast.js";
|
|
8
14
|
/** Languages whose grammar distinguishes static members from instance members. */
|
|
9
15
|
const STATIC_MEMBER_LANGUAGES = {
|
|
10
16
|
cpp: true,
|
|
@@ -12,15 +18,74 @@ const STATIC_MEMBER_LANGUAGES = {
|
|
|
12
18
|
java: true,
|
|
13
19
|
js: true,
|
|
14
20
|
php: true,
|
|
21
|
+
ruby: true,
|
|
15
22
|
swift: true,
|
|
16
23
|
ts: true,
|
|
17
24
|
tsx: true,
|
|
18
25
|
};
|
|
26
|
+
const MEMBER_OVERLOAD_LANGUAGE_IDS = {
|
|
27
|
+
cpp: true,
|
|
28
|
+
csharp: true,
|
|
29
|
+
java: true,
|
|
30
|
+
kotlin: true,
|
|
31
|
+
swift: true,
|
|
32
|
+
ts: true,
|
|
33
|
+
tsx: true,
|
|
34
|
+
};
|
|
35
|
+
/** Bare calls inside members can target a proven member even without an explicit receiver. */
|
|
36
|
+
const IMPLICIT_SELF_MEMBER_CALL_LANGUAGES = {
|
|
37
|
+
csharp: true,
|
|
38
|
+
swift: true,
|
|
39
|
+
};
|
|
40
|
+
/** Whether a bare, receiver-less call inside a member function may target `this`/an inherited member. */
|
|
41
|
+
export function supportsImplicitSelfMemberCalls(languageId) {
|
|
42
|
+
return !!IMPLICIT_SELF_MEMBER_CALL_LANGUAGES[languageId];
|
|
43
|
+
}
|
|
44
|
+
/** Whether member lookup uses call arity to select or reject same-name declarations. */
|
|
45
|
+
export function supportsReceiverMemberOverloads(languageId) {
|
|
46
|
+
return !!MEMBER_OVERLOAD_LANGUAGE_IDS[languageId];
|
|
47
|
+
}
|
|
19
48
|
/** Every language with a static-member distinction, guarded by the registry-consistency test. */
|
|
20
49
|
export const staticMemberLanguageIds = Object.keys(STATIC_MEMBER_LANGUAGES);
|
|
21
50
|
export function hasStaticMemberDistinction(languageId) {
|
|
22
51
|
return STATIC_MEMBER_LANGUAGES[languageId] !== undefined;
|
|
23
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Languages whose grammar gives members a static-equivalent scope without a `static` keyword:
|
|
55
|
+
* a Kotlin member of a `companion object` or a named `object` declaration is reachable as
|
|
56
|
+
* `Outer.member()`. Member lookup classifies those members "static" and every other member
|
|
57
|
+
* "instance", matching the keyword-`static` languages.
|
|
58
|
+
*/
|
|
59
|
+
const STATIC_EQUIVALENT_MEMBER_CONTAINERS = {
|
|
60
|
+
kotlin: { companion_object: true, object_declaration: true },
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Whether `node` is lexically declared inside its language's static-equivalent member
|
|
64
|
+
* container. The nearest enclosing member container decides: a nested type's members belong
|
|
65
|
+
* to that type, not to an outer `object`.
|
|
66
|
+
*/
|
|
67
|
+
export function declarationIsStaticEquivalent(languageId, node) {
|
|
68
|
+
const containers = STATIC_EQUIVALENT_MEMBER_CONTAINERS[languageId];
|
|
69
|
+
if (!containers)
|
|
70
|
+
return false;
|
|
71
|
+
let current = node.parent;
|
|
72
|
+
while (current) {
|
|
73
|
+
if (containers[current.type] === true)
|
|
74
|
+
return true;
|
|
75
|
+
if (MEMBER_CONTAINER_TYPES[current.type] === true)
|
|
76
|
+
return false;
|
|
77
|
+
current = current.parent;
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Whether member lookup for `languageId` distinguishes static-equivalent members from
|
|
83
|
+
* instance members. A bare type-name receiver restricts lookup to the static-equivalent
|
|
84
|
+
* scope exactly when this holds; otherwise every member must stay reachable.
|
|
85
|
+
*/
|
|
86
|
+
export function supportsStaticMemberScope(languageId) {
|
|
87
|
+
return (STATIC_MEMBER_LANGUAGES[languageId] !== undefined || STATIC_EQUIVALENT_MEMBER_CONTAINERS[languageId] !== undefined);
|
|
88
|
+
}
|
|
24
89
|
/**
|
|
25
90
|
* Call nodes that carry the receiver and the member name on the call node itself
|
|
26
91
|
* instead of exposing a member-access callee.
|
|
@@ -51,6 +116,25 @@ const MEMBER_CONTAINER_TYPES = {
|
|
|
51
116
|
struct_specifier: true,
|
|
52
117
|
trait_declaration: true,
|
|
53
118
|
trait_item: true,
|
|
119
|
+
type_alias_declaration: true,
|
|
120
|
+
// C/C++ unions declare members exactly like structs (tree-sitter-cpp captures
|
|
121
|
+
// union names and classifies them as classes).
|
|
122
|
+
union_specifier: true,
|
|
123
|
+
};
|
|
124
|
+
const CPP_MEMBER_CONTAINER_TYPES = {
|
|
125
|
+
class_specifier: true,
|
|
126
|
+
struct_specifier: true,
|
|
127
|
+
union_specifier: true,
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Container nodes whose declared members belong to the *enclosing* member container for
|
|
131
|
+
* direct-member lookup, rather than forming a separate nested type. Kotlin's unnamed
|
|
132
|
+
* `companion object { ... }` block is the language's static-member mechanism: `create()`
|
|
133
|
+
* declared inside one is a member of the enclosing class, reachable as `Outer.create()`,
|
|
134
|
+
* not a member of a distinct "Companion" type the indexer would need to name separately.
|
|
135
|
+
*/
|
|
136
|
+
export const TRANSPARENT_MEMBER_CONTAINER_TYPES = {
|
|
137
|
+
companion_object: true,
|
|
54
138
|
};
|
|
55
139
|
/** Nodes holding a call's argument list across the supported grammars. */
|
|
56
140
|
export const CALL_ARGUMENT_NODE_TYPES = {
|
|
@@ -66,6 +150,16 @@ const HIERARCHY_LABELS = {
|
|
|
66
150
|
mixin: true,
|
|
67
151
|
trait: true,
|
|
68
152
|
};
|
|
153
|
+
const UNPROVEN_HERITAGE_EXPRESSION_TYPES = new Set([
|
|
154
|
+
"binary_expression",
|
|
155
|
+
"call_expression",
|
|
156
|
+
"new_expression",
|
|
157
|
+
"subscript_expression",
|
|
158
|
+
"ternary_expression",
|
|
159
|
+
]);
|
|
160
|
+
export function isUnprovenHeritageExpression(node) {
|
|
161
|
+
return UNPROVEN_HERITAGE_EXPRESSION_TYPES.has(node.type);
|
|
162
|
+
}
|
|
69
163
|
/**
|
|
70
164
|
* Nodes that bind a value name across the supported grammars: locals, parameters,
|
|
71
165
|
* and assignment targets. A receiver naming one of these is a value, not a type.
|
|
@@ -75,6 +169,9 @@ const VALUE_BINDING_TYPES = {
|
|
|
75
169
|
assignment_expression: true,
|
|
76
170
|
assignment_statement: true,
|
|
77
171
|
class_parameter: true,
|
|
172
|
+
// C/C++ local variable statement (`Box b;`, `Box* p = raw;`); the declared type sits
|
|
173
|
+
// beside the declarator, unlike other grammars' dedicated `variable_declaration` node.
|
|
174
|
+
declaration: true,
|
|
78
175
|
formal_parameter: true,
|
|
79
176
|
init_declarator: true,
|
|
80
177
|
let_declaration: true,
|
|
@@ -90,21 +187,6 @@ const VALUE_BINDING_TYPES = {
|
|
|
90
187
|
variable_declaration: true,
|
|
91
188
|
variable_declarator: true,
|
|
92
189
|
};
|
|
93
|
-
/**
|
|
94
|
-
* Parameter lists whose identifier children are value bindings (Ruby has no wrapping param node).
|
|
95
|
-
* Union of the receiver-call and call-compatibility lists so Kotlin `function_value_parameters`
|
|
96
|
-
* and Ruby `block_parameters` are both recognized.
|
|
97
|
-
*/
|
|
98
|
-
export const PARAMETER_LIST_NODE_TYPES = {
|
|
99
|
-
block_parameters: true,
|
|
100
|
-
formal_parameters: true,
|
|
101
|
-
function_parameter_clause: true,
|
|
102
|
-
function_value_parameters: true,
|
|
103
|
-
lambda_parameters: true,
|
|
104
|
-
method_parameters: true,
|
|
105
|
-
parameter_list: true,
|
|
106
|
-
parameters: true,
|
|
107
|
-
};
|
|
108
190
|
/**
|
|
109
191
|
* Access nodes whose syntax is type-scoped (`::`), not dotted member access.
|
|
110
192
|
* A dotted identifier is never itself proof of a type.
|
|
@@ -180,6 +262,8 @@ const BINDING_DECLARATION_TYPES = new Set([
|
|
|
180
262
|
"property_declaration",
|
|
181
263
|
"local_variable_declaration",
|
|
182
264
|
"local_declaration_statement",
|
|
265
|
+
// C/C++ local variable statement, e.g. `Box b;`, `Box* p = raw;`, `Box w{5};`.
|
|
266
|
+
"declaration",
|
|
183
267
|
]);
|
|
184
268
|
const RUBY_CONSTANT_SOURCE = String.raw `(?=\p{Lu})${XID_IDENTIFIER_SOURCE}`;
|
|
185
269
|
/** Proven construction forms that name a receiver's type, keyed by language. */
|
|
@@ -193,14 +277,12 @@ const LANGUAGE_CONSTRUCTION_FORMS = {
|
|
|
193
277
|
php: { newExpression: true },
|
|
194
278
|
python: { capitalizedCall: true },
|
|
195
279
|
ruby: { rubyNew: true },
|
|
196
|
-
rust: { capitalizedCall: true, rustUnitStruct: true },
|
|
280
|
+
rust: { capitalizedCall: true, rustUnitStruct: true, compositeLiteral: true },
|
|
197
281
|
swift: { capitalizedCall: true },
|
|
198
282
|
ts: { newExpression: true },
|
|
199
283
|
tsx: { newExpression: true },
|
|
200
284
|
zig: { compositeLiteral: true },
|
|
201
285
|
};
|
|
202
|
-
/** Guards against a cyclic or pathological declared hierarchy. */
|
|
203
|
-
const MAX_SUPERTYPE_DEPTH = 16;
|
|
204
286
|
/**
|
|
205
287
|
* Resolves the receiver and member-name nodes of a call, or null when the call has no
|
|
206
288
|
* receiver or its shape is not a member access. `callee` is the call's resolved callee
|
|
@@ -237,12 +319,13 @@ export function receiverCallAccess(sup, callNode, callee) {
|
|
|
237
319
|
return { accessNode, receiver, property };
|
|
238
320
|
}
|
|
239
321
|
/**
|
|
240
|
-
* Identifier a binding node declares: a `name` field, a nested C/C++
|
|
241
|
-
* an assignment left-hand side, or the last identifier child (C++
|
|
242
|
-
* the name after the type).
|
|
322
|
+
* Identifier a binding node declares: a `name` or `pattern` field, a nested C/C++
|
|
323
|
+
* declarator, an assignment left-hand side, or the last identifier child (C++
|
|
324
|
+
* parameters hide the name after the type). Rust spells parameter and `let` names in
|
|
325
|
+
* the `pattern` field, where the last-identifier fallback would pick the declared type.
|
|
243
326
|
*/
|
|
244
327
|
function bindingIdentifier(node, sup) {
|
|
245
|
-
const named = node.childForFieldName("name");
|
|
328
|
+
const named = node.childForFieldName("name") ?? node.childForFieldName("pattern");
|
|
246
329
|
if (named && (isReceiverNameNode(sup, named.type) || named.type === "field_identifier")) {
|
|
247
330
|
return named;
|
|
248
331
|
}
|
|
@@ -323,6 +406,17 @@ function containsIndex(node, index) {
|
|
|
323
406
|
return node.startIndex <= index && node.endIndex >= index;
|
|
324
407
|
}
|
|
325
408
|
function constructorNameNode(node, sup) {
|
|
409
|
+
// A dedicated `type` field (C#'s `object_creation_expression`, C/C++'s `new_expression`) can
|
|
410
|
+
// wrap a qualified (`Outer.Inner`) or generic (`Box<int>`) shape the fallback scan below never
|
|
411
|
+
// matches; a language without that field (TS/PHP's `constructor` field, or none) falls through.
|
|
412
|
+
const typeField = node.childForFieldName("type");
|
|
413
|
+
if (typeField) {
|
|
414
|
+
if (isMemberAccessNode(sup, typeField))
|
|
415
|
+
return typeField;
|
|
416
|
+
const unwrapped = unwrapNamedType(typeField, sup);
|
|
417
|
+
if (unwrapped)
|
|
418
|
+
return unwrapped;
|
|
419
|
+
}
|
|
326
420
|
const constructor = node.childForFieldName("constructor") ?? node.child(0);
|
|
327
421
|
if (constructor && isReceiverNameNode(sup, constructor.type)) {
|
|
328
422
|
return constructor;
|
|
@@ -334,14 +428,85 @@ function constructorNameNode(node, sup) {
|
|
|
334
428
|
}
|
|
335
429
|
return null;
|
|
336
430
|
}
|
|
431
|
+
const PHP_OBJECT_CREATION_KEYWORDS = {
|
|
432
|
+
self: "self",
|
|
433
|
+
static: "static",
|
|
434
|
+
parent: "parent",
|
|
435
|
+
};
|
|
436
|
+
export function phpObjectCreationKeyword(node, source, sup) {
|
|
437
|
+
if (sup.id !== "php")
|
|
438
|
+
return null;
|
|
439
|
+
let creation = node;
|
|
440
|
+
while (creation && creation.type !== "object_creation_expression") {
|
|
441
|
+
if (creation.type === "method_declaration" ||
|
|
442
|
+
creation.type === "function_definition" ||
|
|
443
|
+
creation.type === "class_declaration") {
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
creation = creation.parent;
|
|
447
|
+
}
|
|
448
|
+
if (!creation)
|
|
449
|
+
return null;
|
|
450
|
+
const nameNode = constructorNameNode(creation, sup);
|
|
451
|
+
if (!nameNode)
|
|
452
|
+
return null;
|
|
453
|
+
const onName = node === creation || (node.startIndex >= nameNode.startIndex && node.endIndex <= nameNode.endIndex);
|
|
454
|
+
if (!onName)
|
|
455
|
+
return null;
|
|
456
|
+
const keyword = PHP_OBJECT_CREATION_KEYWORDS[foldPhpIdentifierCase(sliceText(nameNode, source))];
|
|
457
|
+
if (!keyword)
|
|
458
|
+
return null;
|
|
459
|
+
const container = nearestMemberContainer(creation);
|
|
460
|
+
const classNode = container?.type === "class_declaration" ? container : null;
|
|
461
|
+
return { keyword, nameNode, classNode };
|
|
462
|
+
}
|
|
463
|
+
/** Members-declaring symbol whose name node is this container's name, when that match is unique. */
|
|
464
|
+
export function memberContainerDef(mod, container) {
|
|
465
|
+
const nameNode = container.childForFieldName("name");
|
|
466
|
+
if (!nameNode)
|
|
467
|
+
return null;
|
|
468
|
+
const matches = mod.locals.filter((local) => declaresMembers(local) && local.range.start.index === nameNode.startIndex);
|
|
469
|
+
return matches.length === 1 ? (matches[0] ?? null) : null;
|
|
470
|
+
}
|
|
337
471
|
function rubyNewReceiverNameNode(node, source, sup) {
|
|
338
472
|
if (!new RegExp(String.raw `^(?:${RUBY_CONSTANT_SOURCE})\.new$`, "u").test(sliceText(node, source)))
|
|
339
473
|
return null;
|
|
340
474
|
return node.namedChildren.find((child) => isReceiverNameNode(sup, child.type) || child.type === "constant") ?? null;
|
|
341
475
|
}
|
|
476
|
+
const NULLISH_TYPE_TEXT = new Set(["undefined", "null", "void"]);
|
|
477
|
+
/**
|
|
478
|
+
* The `typeof import("spec")` type query a TypeScript annotation names, ignoring `| undefined` and
|
|
479
|
+
* `| null`: such a binding holds the module namespace of `spec`.
|
|
480
|
+
*/
|
|
481
|
+
export function typescriptImportTypeQuery(annotation) {
|
|
482
|
+
let current = annotation;
|
|
483
|
+
while (current?.type === "type_annotation")
|
|
484
|
+
current = current.namedChildren[0] ?? null;
|
|
485
|
+
if (current?.type === "union_type") {
|
|
486
|
+
const members = current.namedChildren.filter((member) => !NULLISH_TYPE_TEXT.has(member.text.trim()));
|
|
487
|
+
current = members.length === 1 ? members[0] : null;
|
|
488
|
+
}
|
|
489
|
+
if (current?.type !== "type_query")
|
|
490
|
+
return null;
|
|
491
|
+
const call = current.namedChildren[0];
|
|
492
|
+
return call?.type === "call_expression" && call.childForFieldName("function")?.type === "import" ? current : null;
|
|
493
|
+
}
|
|
494
|
+
/** The module specifier of a `typeof import("spec")` type query. */
|
|
495
|
+
export function importTypeQuerySpecifier(typeQuery) {
|
|
496
|
+
const argument = typeQuery.namedChildren[0]?.childForFieldName("arguments")?.namedChildren[0];
|
|
497
|
+
if (argument?.type !== "string")
|
|
498
|
+
return null;
|
|
499
|
+
return argument.namedChildren.find((child) => child.type === "string_fragment")?.text ?? null;
|
|
500
|
+
}
|
|
342
501
|
export function unwrapNamedType(node, sup) {
|
|
343
502
|
let current = node;
|
|
344
503
|
while (current) {
|
|
504
|
+
if (current.type === "union_type") {
|
|
505
|
+
// `Store | undefined` and `Store | null` still prove `Store` for a member call.
|
|
506
|
+
const members = current.namedChildren.filter((member) => !NULLISH_TYPE_TEXT.has(member.text.trim()));
|
|
507
|
+
current = members.length === 1 ? members[0] : null;
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
345
510
|
if (current.type === "type_annotation" ||
|
|
346
511
|
current.type === "named_type" ||
|
|
347
512
|
current.type === "user_type" ||
|
|
@@ -358,6 +523,16 @@ export function unwrapNamedType(node, sup) {
|
|
|
358
523
|
current = current.childForFieldName("type") ?? current.namedChildren[0] ?? null;
|
|
359
524
|
continue;
|
|
360
525
|
}
|
|
526
|
+
if (current.type === "qualified_name") {
|
|
527
|
+
// C#'s `Outer.Inner` names the nested type by its last segment. PHP also parses a
|
|
528
|
+
// namespaced name as `qualified_name`, but as one flat token with no `name` field, so an
|
|
529
|
+
// absent field leaves `current` as that whole node instead of nulling the result out.
|
|
530
|
+
const segment = current.childForFieldName("name");
|
|
531
|
+
if (!segment)
|
|
532
|
+
break;
|
|
533
|
+
current = segment;
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
361
536
|
break;
|
|
362
537
|
}
|
|
363
538
|
if (!current)
|
|
@@ -367,6 +542,34 @@ export function unwrapNamedType(node, sup) {
|
|
|
367
542
|
}
|
|
368
543
|
return null;
|
|
369
544
|
}
|
|
545
|
+
/**
|
|
546
|
+
* Kotlin extension-function receiver type, e.g. `Widget` in `fun Widget.describe(): String`.
|
|
547
|
+
* The receiver type is an unfielded `user_type` positioned before the function's own `name`;
|
|
548
|
+
* an ordinary function or class member declares no such node.
|
|
549
|
+
*/
|
|
550
|
+
export function kotlinExtensionReceiverTypeNode(node, sup) {
|
|
551
|
+
if (node.type !== "function_declaration")
|
|
552
|
+
return null;
|
|
553
|
+
const nameNode = node.childForFieldName("name");
|
|
554
|
+
if (!nameNode)
|
|
555
|
+
return null;
|
|
556
|
+
const receiverType = node.namedChildren.find((child) => child.startIndex < nameNode.startIndex && (child.type === "user_type" || child.type === "nullable_type"));
|
|
557
|
+
return receiverType ? unwrapNamedType(receiverType, sup) : null;
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Self-type name node of a Rust `impl` block: `Circle` in `impl Circle`, `impl Shape for
|
|
561
|
+
* Circle`, `impl<T> Box<T>`, or `impl Shape for &Circle`. The `type` field always names the
|
|
562
|
+
* self type (the `trait` field names the implemented trait), and `unwrapNamedType` strips
|
|
563
|
+
* generic and reference wrappers down to the base type identifier. Shared by member
|
|
564
|
+
* ownership in the detailed graph and receiver-member navigation so both attribute an
|
|
565
|
+
* impl method to the same owner.
|
|
566
|
+
*/
|
|
567
|
+
export function rustImplSelfTypeNode(implItem, sup) {
|
|
568
|
+
if (implItem.type !== "impl_item")
|
|
569
|
+
return null;
|
|
570
|
+
const typeNode = implItem.childForFieldName("type");
|
|
571
|
+
return typeNode ? unwrapNamedType(typeNode, sup) : null;
|
|
572
|
+
}
|
|
370
573
|
function capitalizedCallTypeName(expr, source, sup) {
|
|
371
574
|
if (expr.type !== "call" && expr.type !== "call_expression")
|
|
372
575
|
return null;
|
|
@@ -395,11 +598,21 @@ function compositeLiteralTypeName(expr, source, sup) {
|
|
|
395
598
|
return null;
|
|
396
599
|
current = operand;
|
|
397
600
|
}
|
|
398
|
-
|
|
601
|
+
// tree-sitter-go composite_literal, tree-sitter-zig struct_initializer, tree-sitter-rust
|
|
602
|
+
// struct_expression: `Type { field: value }` / `Type{ .field = value }`.
|
|
603
|
+
if (current.type !== "composite_literal" &&
|
|
604
|
+
current.type !== "struct_initializer" &&
|
|
605
|
+
current.type !== "struct_expression") {
|
|
399
606
|
return null;
|
|
607
|
+
}
|
|
400
608
|
const typeNode = current.childForFieldName("type") ??
|
|
401
|
-
current.namedChildren.find((child) => child.type === "type_identifier" ||
|
|
609
|
+
current.namedChildren.find((child) => child.type === "type_identifier" ||
|
|
610
|
+
child.type === "identifier" ||
|
|
611
|
+
child.type === sup.nodeTypes.memberExpression) ??
|
|
402
612
|
null;
|
|
613
|
+
// A qualified literal type (Zig `ns.Struct{...}`) has no dedicated `type` field and is not a
|
|
614
|
+
// simple named type either; `unwrapNamedType` rejects it, so the member-access node itself is
|
|
615
|
+
// kept so the caller can resolve it the same way as any other qualified expression.
|
|
403
616
|
return typeNode ? (unwrapNamedType(typeNode, sup) ?? typeNode) : null;
|
|
404
617
|
}
|
|
405
618
|
/**
|
|
@@ -455,16 +668,18 @@ function bindingValueExpression(node) {
|
|
|
455
668
|
]);
|
|
456
669
|
return node.namedChildren.find((child) => expressionTypes.has(child.type)) ?? null;
|
|
457
670
|
}
|
|
458
|
-
function declaredTypeNameNode(node, sup) {
|
|
671
|
+
export function declaredTypeNameNode(node, sup) {
|
|
459
672
|
const typeField = node.childForFieldName("type");
|
|
460
673
|
if (typeField)
|
|
461
|
-
return unwrapNamedType(typeField, sup);
|
|
674
|
+
return unwrapNamedType(typeField, sup) ?? typeField;
|
|
462
675
|
const typedChild = node.namedChildren.find((child) => child.type === "named_type" ||
|
|
463
676
|
child.type === "user_type" ||
|
|
464
677
|
child.type === "type_annotation" ||
|
|
465
678
|
child.type === "type");
|
|
466
679
|
if (typedChild)
|
|
467
|
-
return unwrapNamedType(typedChild, sup);
|
|
680
|
+
return unwrapNamedType(typedChild, sup) ?? typedChild;
|
|
681
|
+
if (node.type === "let_declaration")
|
|
682
|
+
return null;
|
|
468
683
|
const ids = node.namedChildren.filter((child) => isReceiverNameNode(sup, child.type) || child.type === "type_identifier" || child.type === "name");
|
|
469
684
|
if (ids.length >= 2)
|
|
470
685
|
return unwrapNamedType(ids[0], sup);
|
|
@@ -542,6 +757,13 @@ function bindingProof(node, receiverName, source, sup) {
|
|
|
542
757
|
return { status: "none" };
|
|
543
758
|
if (!bindingDeclaresReceiverName(node, receiverName, source, sup))
|
|
544
759
|
return { status: "none" };
|
|
760
|
+
const annotation = isJsTsLanguage(sup.id) ? node.childForFieldName("type") : null;
|
|
761
|
+
const annotated = annotation ? (unwrapNamedType(annotation, sup) ?? typescriptImportTypeQuery(annotation)) : null;
|
|
762
|
+
if (annotated)
|
|
763
|
+
return { status: "declared", node: annotated };
|
|
764
|
+
const declared = declaredTypeNameNode(node, sup);
|
|
765
|
+
if (declared)
|
|
766
|
+
return { status: "declared", node: declared };
|
|
545
767
|
const typeNode = constructionTypeFromBinding(node, receiverName, source, sup);
|
|
546
768
|
if (typeNode)
|
|
547
769
|
return { status: "type", node: typeNode };
|
|
@@ -551,17 +773,26 @@ function isSkippableBindingContainer(node, receiver) {
|
|
|
551
773
|
return BINDING_CONTAINER_TYPES.has(node.type) && !containsIndex(node, receiver.startIndex);
|
|
552
774
|
}
|
|
553
775
|
function findPriorConstructorInContainer(node, receiver, receiverName, source, sup) {
|
|
554
|
-
let
|
|
776
|
+
let typeEvidence = null;
|
|
555
777
|
let sawUnproven = false;
|
|
778
|
+
let declared = false;
|
|
556
779
|
const visit = (current) => {
|
|
557
780
|
if (current.startIndex >= receiver.startIndex)
|
|
558
781
|
return true;
|
|
559
782
|
if (current !== node && isSkippableBindingContainer(current, receiver))
|
|
560
783
|
return true;
|
|
561
784
|
const proof = bindingProof(current, receiverName, source, sup);
|
|
785
|
+
if (proof.status === "declared") {
|
|
786
|
+
typeEvidence = { typeNode: proof.node, origin: "declared-type" };
|
|
787
|
+
declared = isJsTsLanguage(sup.id);
|
|
788
|
+
return true;
|
|
789
|
+
}
|
|
790
|
+
// A later assignment to an annotated binding cannot change its declared type.
|
|
791
|
+
if (declared && proof.status !== "none")
|
|
792
|
+
return true;
|
|
562
793
|
if (proof.status === "unproven") {
|
|
563
|
-
if (
|
|
564
|
-
|
|
794
|
+
if (typeEvidence) {
|
|
795
|
+
typeEvidence = null;
|
|
565
796
|
return false;
|
|
566
797
|
}
|
|
567
798
|
sawUnproven = true;
|
|
@@ -569,14 +800,14 @@ function findPriorConstructorInContainer(node, receiver, receiverName, source, s
|
|
|
569
800
|
}
|
|
570
801
|
if (proof.status === "type") {
|
|
571
802
|
if (sawUnproven) {
|
|
572
|
-
|
|
803
|
+
typeEvidence = null;
|
|
573
804
|
return false;
|
|
574
805
|
}
|
|
575
|
-
if (
|
|
576
|
-
|
|
806
|
+
if (typeEvidence && sliceText(typeEvidence.typeNode, source) !== sliceText(proof.node, source)) {
|
|
807
|
+
typeEvidence = null;
|
|
577
808
|
return false;
|
|
578
809
|
}
|
|
579
|
-
|
|
810
|
+
typeEvidence = { typeNode: proof.node, origin: "constructor" };
|
|
580
811
|
return true;
|
|
581
812
|
}
|
|
582
813
|
for (const child of current.namedChildren) {
|
|
@@ -586,7 +817,7 @@ function findPriorConstructorInContainer(node, receiver, receiverName, source, s
|
|
|
586
817
|
return true;
|
|
587
818
|
};
|
|
588
819
|
visit(node);
|
|
589
|
-
return
|
|
820
|
+
return typeEvidence;
|
|
590
821
|
}
|
|
591
822
|
function bindingContainerDeclaresNameBefore(node, receiver, receiverName, source, sup) {
|
|
592
823
|
const visit = (current) => {
|
|
@@ -594,7 +825,10 @@ function bindingContainerDeclaresNameBefore(node, receiver, receiverName, source
|
|
|
594
825
|
return false;
|
|
595
826
|
if (current !== node && isSkippableBindingContainer(current, receiver))
|
|
596
827
|
return false;
|
|
597
|
-
|
|
828
|
+
// A JavaScript/TypeScript assignment updates an existing binding; it declares nothing.
|
|
829
|
+
const declaresNewBinding = !(isJsTsLanguage(sup.id) && current.type === "assignment_expression");
|
|
830
|
+
if (declaresNewBinding &&
|
|
831
|
+
BINDING_DECLARATION_TYPES.has(current.type) &&
|
|
598
832
|
bindingDeclaresReceiverName(current, receiverName, source, sup)) {
|
|
599
833
|
return true;
|
|
600
834
|
}
|
|
@@ -625,79 +859,402 @@ function findVisiblePriorConstructor(receiver, receiverName, source, sup) {
|
|
|
625
859
|
}
|
|
626
860
|
return findPriorConstructorInContainer(rootOf(receiver), receiver, receiverName, source, sup);
|
|
627
861
|
}
|
|
628
|
-
/**
|
|
629
|
-
|
|
630
|
-
* null when no constructor is proven for it. Shared with detailed symbol-graph call
|
|
631
|
-
* extraction so `goto` and resolved `calls` edges accept the same receiver forms.
|
|
632
|
-
*/
|
|
633
|
-
export function receiverConstructorExpression(obj, source, sup) {
|
|
862
|
+
/** Constructor or declared type visible at a receiver, without resolving its owner. */
|
|
863
|
+
function receiverTypeEvidence(obj, source, sup) {
|
|
634
864
|
const direct = constructionTypeName(obj, source, sup);
|
|
635
|
-
if (direct)
|
|
636
|
-
return direct;
|
|
637
865
|
if (!isReceiverNameNode(sup, obj.type))
|
|
638
|
-
return null;
|
|
866
|
+
return direct ? { typeNode: direct, origin: "constructor" } : null;
|
|
639
867
|
const receiverName = sliceText(obj, source);
|
|
868
|
+
if (direct && !bindsLocalValue(obj, receiverName, source, sup)) {
|
|
869
|
+
return { typeNode: direct, origin: "constructor" };
|
|
870
|
+
}
|
|
640
871
|
return findVisiblePriorConstructor(obj, receiverName, source, sup);
|
|
641
872
|
}
|
|
642
|
-
|
|
643
|
-
|
|
873
|
+
/** Syntax naming the type of a constructed or declared receiver. */
|
|
874
|
+
export function receiverConstructorExpression(obj, source, sup) {
|
|
875
|
+
return receiverTypeEvidence(obj, source, sup)?.typeNode ?? null;
|
|
876
|
+
}
|
|
877
|
+
/** Identifier segments in a C++ qualified name, excluding template arguments. */
|
|
878
|
+
export function cppQualifiedNameSegments(node, source) {
|
|
879
|
+
return cppQualifiedTextSegments(sliceText(node, source));
|
|
880
|
+
}
|
|
881
|
+
/** `::`-separated segments of a C++ qualified name, ignoring `::` inside template arguments and dropping them. */
|
|
882
|
+
export function cppQualifiedTextSegments(text) {
|
|
883
|
+
const segments = [];
|
|
884
|
+
let segmentStart = 0;
|
|
885
|
+
let templateDepth = 0;
|
|
886
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
887
|
+
const char = text[index];
|
|
888
|
+
if (char === "<") {
|
|
889
|
+
templateDepth += 1;
|
|
890
|
+
continue;
|
|
891
|
+
}
|
|
892
|
+
if (char === ">") {
|
|
893
|
+
templateDepth = Math.max(0, templateDepth - 1);
|
|
894
|
+
continue;
|
|
895
|
+
}
|
|
896
|
+
if (char !== ":" || text[index + 1] !== ":" || templateDepth !== 0)
|
|
897
|
+
continue;
|
|
898
|
+
const segment = text.slice(segmentStart, index).trim();
|
|
899
|
+
if (segment)
|
|
900
|
+
segments.push(segment.replace(/<.*$/u, "").trim());
|
|
901
|
+
segmentStart = index + 2;
|
|
902
|
+
index += 1;
|
|
903
|
+
}
|
|
904
|
+
const finalSegment = text.slice(segmentStart).trim();
|
|
905
|
+
if (finalSegment)
|
|
906
|
+
segments.push(finalSegment.replace(/<.*$/u, "").trim());
|
|
907
|
+
return segments.filter(Boolean);
|
|
908
|
+
}
|
|
909
|
+
/** Exact namespace/type path that qualifies a C++ out-of-line function definition. */
|
|
910
|
+
export function cppOutOfLineOwnerPath(node, source, sup) {
|
|
911
|
+
if (sup.id !== "cpp")
|
|
912
|
+
return null;
|
|
913
|
+
let current = node;
|
|
914
|
+
while (current) {
|
|
915
|
+
if (current.type === "function_definition") {
|
|
916
|
+
let declarator = current.childForFieldName("declarator");
|
|
917
|
+
while (declarator) {
|
|
918
|
+
if (declarator.type === "qualified_identifier") {
|
|
919
|
+
const path = cppQualifiedNameSegments(declarator, source);
|
|
920
|
+
path.pop();
|
|
921
|
+
if (!sliceText(declarator, source).trimStart().startsWith("::")) {
|
|
922
|
+
const namespaces = [];
|
|
923
|
+
let parent = current.parent;
|
|
924
|
+
while (parent) {
|
|
925
|
+
if (parent.type === "namespace_definition") {
|
|
926
|
+
const name = parent.childForFieldName("name");
|
|
927
|
+
if (name)
|
|
928
|
+
namespaces.push(cppQualifiedNameSegments(name, source));
|
|
929
|
+
}
|
|
930
|
+
parent = parent.parent;
|
|
931
|
+
}
|
|
932
|
+
for (const namespace of namespaces.reverse())
|
|
933
|
+
path.unshift(...namespace);
|
|
934
|
+
}
|
|
935
|
+
return path.length ? path : null;
|
|
936
|
+
}
|
|
937
|
+
const nested = declarator.childForFieldName("declarator") ?? declarator.namedChildren.at(-1);
|
|
938
|
+
if (!nested || nested.id === declarator.id)
|
|
939
|
+
break;
|
|
940
|
+
declarator = nested;
|
|
941
|
+
}
|
|
942
|
+
return null;
|
|
943
|
+
}
|
|
944
|
+
current = current.parent;
|
|
945
|
+
}
|
|
946
|
+
return null;
|
|
947
|
+
}
|
|
948
|
+
/** Unqualified member name from a C++ out-of-line function definition. */
|
|
949
|
+
export function cppOutOfLineMemberName(node, source, sup) {
|
|
950
|
+
if (sup.id !== "cpp")
|
|
951
|
+
return null;
|
|
952
|
+
let current = node;
|
|
953
|
+
while (current) {
|
|
954
|
+
if (current.type === "function_definition") {
|
|
955
|
+
const nameNode = cppFunctionDeclaratorName(current, sup);
|
|
956
|
+
return nameNode ? sliceText(nameNode, source) : null;
|
|
957
|
+
}
|
|
958
|
+
current = current.parent;
|
|
959
|
+
}
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
function sameSyntaxNode(left, right) {
|
|
963
|
+
if (!left)
|
|
964
|
+
return false;
|
|
965
|
+
if (left.id !== undefined && right.id !== undefined)
|
|
966
|
+
return left.id === right.id;
|
|
967
|
+
return left.type === right.type && left.startIndex === right.startIndex && left.endIndex === right.endIndex;
|
|
968
|
+
}
|
|
969
|
+
function cppFunctionDeclaratorName(node, sup) {
|
|
970
|
+
const functionDeclarator = node.type === "function_declarator" ? node : findFirstNodeByType(node, "function_declarator");
|
|
971
|
+
let current = functionDeclarator?.childForFieldName("declarator") ?? null;
|
|
972
|
+
while (current) {
|
|
973
|
+
if (isIdentifierType(sup, current.type) || current.type === "operator_name" || current.type === "destructor_name") {
|
|
974
|
+
return current;
|
|
975
|
+
}
|
|
976
|
+
let name = current.childForFieldName("name");
|
|
977
|
+
while (name?.childForFieldName("name"))
|
|
978
|
+
name = name.childForFieldName("name");
|
|
979
|
+
if (name &&
|
|
980
|
+
(isIdentifierType(sup, name.type) || name.type === "operator_name" || name.type === "destructor_name")) {
|
|
981
|
+
return name;
|
|
982
|
+
}
|
|
983
|
+
const nested = current.childForFieldName("declarator");
|
|
984
|
+
if (!nested || nested.id === current.id)
|
|
985
|
+
return null;
|
|
986
|
+
current = nested;
|
|
987
|
+
}
|
|
988
|
+
return null;
|
|
989
|
+
}
|
|
990
|
+
function cppMemberArityFromAncestor(node) {
|
|
991
|
+
let current = node;
|
|
992
|
+
while (current) {
|
|
993
|
+
const arity = declarationMemberArity(current, "cpp");
|
|
994
|
+
if (arity !== undefined)
|
|
995
|
+
return arity;
|
|
996
|
+
current = current.parent;
|
|
997
|
+
}
|
|
998
|
+
return undefined;
|
|
999
|
+
}
|
|
1000
|
+
function collectCppMemberDeclarations(node, ownerNode, localName, ownerSource, sup, expectedArity, out) {
|
|
1001
|
+
if ((node.type === "field_declaration" || node.type === "declaration") &&
|
|
1002
|
+
sameSyntaxNode(nearestMemberContainer(node), ownerNode)) {
|
|
1003
|
+
const nameNode = cppFunctionDeclaratorName(node, sup);
|
|
1004
|
+
if (nameNode &&
|
|
1005
|
+
sup.normalizeIdentifier(sliceText(nameNode, ownerSource)) === sup.normalizeIdentifier(localName) &&
|
|
1006
|
+
declarationMemberArity(node, sup.id) === expectedArity) {
|
|
1007
|
+
out.push({ node, nameNode });
|
|
1008
|
+
}
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
for (const child of node.namedChildren) {
|
|
1012
|
+
collectCppMemberDeclarations(child, ownerNode, localName, ownerSource, sup, expectedArity, out);
|
|
1013
|
+
}
|
|
644
1014
|
}
|
|
645
1015
|
/**
|
|
646
|
-
*
|
|
647
|
-
*
|
|
648
|
-
* Named-local constructor lookup is memoized per enclosing function and receiver text.
|
|
1016
|
+
* Finds the unique in-class declaration corresponding to a C++ out-of-line member
|
|
1017
|
+
* definition. Name and arity must both match so overloads do not collapse.
|
|
649
1018
|
*/
|
|
650
|
-
export function
|
|
651
|
-
|
|
652
|
-
const text = sliceText(receiver, source).trim();
|
|
653
|
-
if (!text)
|
|
1019
|
+
export function cppOutOfLineMemberDeclarationNode(definitionNameNode, localName, ownerNameNode, ownerSource, sup) {
|
|
1020
|
+
if (sup.id !== "cpp")
|
|
654
1021
|
return null;
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
1022
|
+
const ownerNode = nearestMemberContainer(ownerNameNode);
|
|
1023
|
+
if (!ownerNode)
|
|
1024
|
+
return null;
|
|
1025
|
+
const expectedArity = cppMemberArityFromAncestor(definitionNameNode);
|
|
1026
|
+
const declarations = [];
|
|
1027
|
+
collectCppMemberDeclarations(ownerNode, ownerNode, localName, ownerSource, sup, expectedArity, declarations);
|
|
1028
|
+
return declarations.length === 1 ? declarations[0] : null;
|
|
1029
|
+
}
|
|
1030
|
+
export function nodeDeclaresStatic(node, source) {
|
|
1031
|
+
if (node.type === "singleton_method") {
|
|
1032
|
+
const receiver = node.childForFieldName("object") ?? node.childForFieldName("receiver") ?? node.namedChildren[0];
|
|
1033
|
+
return !!receiver && sliceText(receiver, source).trim() === "self";
|
|
1034
|
+
}
|
|
1035
|
+
if (node.type === "static" || node.type === "static_modifier")
|
|
1036
|
+
return true;
|
|
1037
|
+
if (node.type === "storage_class_specifier" || node.type === "modifier" || node.type === "property_modifier") {
|
|
1038
|
+
return sliceText(node, source).trim() === "static";
|
|
1039
|
+
}
|
|
1040
|
+
if (node.type === "class") {
|
|
1041
|
+
const parentType = node.parent?.type;
|
|
1042
|
+
return (parentType === "function_declaration" ||
|
|
1043
|
+
parentType === "property_declaration" ||
|
|
1044
|
+
parentType === "subscript_declaration");
|
|
1045
|
+
}
|
|
1046
|
+
if (node.type === "modifiers") {
|
|
1047
|
+
for (let childIndex = 0;; childIndex += 1) {
|
|
1048
|
+
const child = node.child(childIndex);
|
|
1049
|
+
if (!child)
|
|
1050
|
+
break;
|
|
1051
|
+
if (nodeDeclaresStatic(child, source))
|
|
1052
|
+
return true;
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
return false;
|
|
1056
|
+
}
|
|
1057
|
+
export function declarationNodeIsStatic(node, source) {
|
|
1058
|
+
if (nodeDeclaresStatic(node, source))
|
|
1059
|
+
return true;
|
|
1060
|
+
for (let childIndex = 0;; childIndex += 1) {
|
|
1061
|
+
const child = node.child(childIndex);
|
|
1062
|
+
if (!child)
|
|
1063
|
+
return false;
|
|
1064
|
+
if (nodeDeclaresStatic(child, source))
|
|
1065
|
+
return true;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
export function nodeInStaticMemberContext(node, source) {
|
|
1069
|
+
const container = nearestMemberContainer(node);
|
|
1070
|
+
if (!container)
|
|
1071
|
+
return false;
|
|
1072
|
+
let current = node;
|
|
1073
|
+
while (current && current !== container) {
|
|
1074
|
+
if (declarationNodeIsStatic(current, source))
|
|
1075
|
+
return true;
|
|
1076
|
+
current = current.parent;
|
|
1077
|
+
}
|
|
1078
|
+
return false;
|
|
1079
|
+
}
|
|
1080
|
+
const JS_TS_DYNAMIC_THIS_FUNCTION_TYPES = {
|
|
1081
|
+
function: true,
|
|
1082
|
+
function_declaration: true,
|
|
1083
|
+
function_expression: true,
|
|
1084
|
+
generator_function: true,
|
|
1085
|
+
generator_function_declaration: true,
|
|
1086
|
+
method_definition: true,
|
|
1087
|
+
};
|
|
1088
|
+
/**
|
|
1089
|
+
* Ordinary JS/TS functions and object-literal methods own `this`/`super`; arrows preserve the
|
|
1090
|
+
* enclosing class member's receiver. Crossing one of those dynamic boundaries makes the class
|
|
1091
|
+
* receiver unproven.
|
|
1092
|
+
*/
|
|
1093
|
+
export function keywordReceiverCrossesDynamicBoundary(sup, node) {
|
|
1094
|
+
if (!isJsTsLanguage(sup.id))
|
|
1095
|
+
return false;
|
|
1096
|
+
const container = nearestMemberContainer(node);
|
|
1097
|
+
if (!container)
|
|
1098
|
+
return false;
|
|
1099
|
+
let current = node.parent;
|
|
1100
|
+
while (current && current !== container) {
|
|
1101
|
+
if (JS_TS_DYNAMIC_THIS_FUNCTION_TYPES[current.type]) {
|
|
1102
|
+
const directlyOwnedClassMethod = current.type === "method_definition" &&
|
|
1103
|
+
current.parent?.type === "class_body" &&
|
|
1104
|
+
current.parent.parent?.startIndex === container.startIndex;
|
|
1105
|
+
return !directlyOwnedClassMethod;
|
|
1106
|
+
}
|
|
1107
|
+
current = current.parent;
|
|
1108
|
+
}
|
|
1109
|
+
return false;
|
|
1110
|
+
}
|
|
1111
|
+
export function keywordReceiverMemberScope(sup, receiverName, node, source) {
|
|
1112
|
+
if (!hasStaticMemberDistinction(sup.id))
|
|
1113
|
+
return "any";
|
|
1114
|
+
if (nodeInStaticMemberContext(node, source))
|
|
1115
|
+
return "static";
|
|
1116
|
+
const kind = keywordReceiverKind(sup.id, receiverName);
|
|
1117
|
+
if (kind === "supertype")
|
|
1118
|
+
return "instance";
|
|
1119
|
+
return ownReceiverMemberScope(sup.id, receiverName) ?? "any";
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* The leftmost identifier of a C# chain of plain identifiers joined by `.` (`P` in `P.Inner.Mix`),
|
|
1123
|
+
* or `null` when `node` has a call, index, keyword, or type arguments. When that identifier binds
|
|
1124
|
+
* nothing, the chain is a namespace-qualified type name.
|
|
1125
|
+
*/
|
|
1126
|
+
export function csharpDottedNameRoot(node) {
|
|
1127
|
+
if (node.type === "identifier")
|
|
1128
|
+
return node;
|
|
1129
|
+
if (node.type !== "member_access_expression")
|
|
1130
|
+
return null;
|
|
1131
|
+
const object = node.childForFieldName("expression");
|
|
1132
|
+
if (!object || node.childForFieldName("name")?.type !== "identifier")
|
|
1133
|
+
return null;
|
|
1134
|
+
return csharpDottedNameRoot(object);
|
|
1135
|
+
}
|
|
1136
|
+
/** Classify a receiver from syntax and consumer-proven import bindings. */
|
|
1137
|
+
export function classifyReceiver(sup, receiver, source, proofCache, cacheScope, accessNode, hasLexicalBinding, classifyImport) {
|
|
1138
|
+
const text = receiverKeywordText(sup, receiver, source, hasLexicalBinding);
|
|
1139
|
+
if (!text)
|
|
1140
|
+
return { kind: "unknown", receiver };
|
|
1141
|
+
const keywordKind = keywordReceiverKind(sup.id, text);
|
|
1142
|
+
if (keywordKind) {
|
|
1143
|
+
if (keywordReceiverCrossesDynamicBoundary(sup, accessNode))
|
|
1144
|
+
return { kind: "unknown", receiver };
|
|
1145
|
+
const memberScope = keywordReceiverMemberScope(sup, text, accessNode, source);
|
|
1146
|
+
return keywordKind === "own" ? { kind: "own-type", memberScope } : { kind: "supertype", memberScope };
|
|
1147
|
+
}
|
|
659
1148
|
const receiverIsName = isReceiverNameNode(sup, receiver.type);
|
|
660
|
-
const
|
|
661
|
-
|
|
1149
|
+
const importProof = receiverIsName ? classifyImport?.(text, receiver) : null;
|
|
1150
|
+
if (importProof === "module-import")
|
|
1151
|
+
return { kind: "module-import", receiver };
|
|
1152
|
+
const cacheKey = proofCache ? cacheScope + "\u0000" + text : "";
|
|
1153
|
+
let proof = proofCache?.get(cacheKey);
|
|
662
1154
|
if (!proof) {
|
|
663
|
-
const
|
|
1155
|
+
const typeEvidence = receiverTypeEvidence(receiver, source, sup);
|
|
664
1156
|
proof = {
|
|
665
|
-
|
|
666
|
-
locallyBound: !
|
|
1157
|
+
typeEvidence,
|
|
1158
|
+
locallyBound: !typeEvidence && receiverIsName && bindsLocalValue(receiver, text, source, sup),
|
|
667
1159
|
};
|
|
668
|
-
proofCache
|
|
1160
|
+
proofCache?.set(cacheKey, proof);
|
|
669
1161
|
}
|
|
670
|
-
if (proof.
|
|
1162
|
+
if (proof.typeEvidence) {
|
|
1163
|
+
const { typeNode, origin } = proof.typeEvidence;
|
|
671
1164
|
return {
|
|
672
1165
|
kind: "named-type",
|
|
673
|
-
|
|
1166
|
+
proof: origin,
|
|
1167
|
+
typeName: sliceText(typeNode, source),
|
|
1168
|
+
typeNode,
|
|
674
1169
|
memberScope: hasStaticMemberDistinction(sup.id) ? "instance" : "any",
|
|
1170
|
+
constructed: origin === "constructor",
|
|
675
1171
|
};
|
|
676
1172
|
}
|
|
677
|
-
if (
|
|
678
|
-
return
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
//
|
|
684
|
-
// is the
|
|
685
|
-
// even when they name a parameter, so
|
|
1173
|
+
if (importProof === "static-type") {
|
|
1174
|
+
return { kind: "named-type", proof: "static-type", typeName: text, typeNode: receiver, memberScope: "static" };
|
|
1175
|
+
}
|
|
1176
|
+
if (!receiverIsName || proof.locallyBound)
|
|
1177
|
+
return { kind: "unknown", receiver };
|
|
1178
|
+
// Dotted `Cfg.load()` is not proof in languages where the identifier may be a
|
|
1179
|
+
// value. Type-scoped `::` is one named-type proof; C# `Box.Left()` is another
|
|
1180
|
+
// because a capitalized unbound name is the static type receiver. Ruby
|
|
1181
|
+
// capitalized names are `constant` tokens even when they name a parameter, so
|
|
1182
|
+
// `constant` is not itself type proof.
|
|
686
1183
|
const property = getMemberAccessParts(sup, accessNode).property;
|
|
687
1184
|
const between = property ? source.slice(receiver.endIndex, property.startIndex) : "";
|
|
688
1185
|
const typeScoped = TYPE_SCOPED_ACCESS_TYPES[accessNode.type] === true || between.includes("::");
|
|
689
|
-
if (receiver.type !== "type_identifier" && !typeScoped)
|
|
690
|
-
|
|
1186
|
+
if (receiver.type !== "type_identifier" && !typeScoped) {
|
|
1187
|
+
// A capitalized bare name is type proof where construction already types
|
|
1188
|
+
// `Box()` as a Box, and for static type-name receivers (`Box.Left()`).
|
|
1189
|
+
// The named type must still resolve to a members-declaring definition
|
|
1190
|
+
// before any call edge is recorded, so a name alone never invents a target.
|
|
1191
|
+
if (!capitalizedTypeReceiverName(sup, receiver, text))
|
|
1192
|
+
return { kind: "unknown", receiver };
|
|
1193
|
+
return {
|
|
1194
|
+
kind: "named-type",
|
|
1195
|
+
proof: "static-type",
|
|
1196
|
+
typeName: text,
|
|
1197
|
+
typeNode: receiver,
|
|
1198
|
+
memberScope: UNBOUND_INSTANCE_CALL_LANGUAGE_IDS[sup.id] ? "any" : "static",
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
691
1201
|
return {
|
|
692
1202
|
kind: "named-type",
|
|
1203
|
+
proof: "static-type",
|
|
693
1204
|
typeName: text,
|
|
1205
|
+
typeNode: receiver,
|
|
694
1206
|
memberScope: hasStaticMemberDistinction(sup.id) && typeScoped ? "static" : "any",
|
|
695
1207
|
};
|
|
696
1208
|
}
|
|
1209
|
+
/**
|
|
1210
|
+
* Languages whose runtime allows an instance member to be invoked through a type
|
|
1211
|
+
* name (`Box.instanceMethod(args)` is a real unbound call), so a type-named
|
|
1212
|
+
* receiver restricts nothing about static versus instance members.
|
|
1213
|
+
*/
|
|
1214
|
+
const UNBOUND_INSTANCE_CALL_LANGUAGE_IDS = {
|
|
1215
|
+
python: true,
|
|
1216
|
+
};
|
|
1217
|
+
/**
|
|
1218
|
+
* Languages whose dotted type-name receivers (`Box.Left()`) name the type itself.
|
|
1219
|
+
* Distinct from `capitalizedCall`, which also treats `Box()` as construction.
|
|
1220
|
+
*/
|
|
1221
|
+
const STATIC_TYPE_NAME_RECEIVER_LANGUAGE_IDS = {
|
|
1222
|
+
csharp: true,
|
|
1223
|
+
java: true,
|
|
1224
|
+
js: true,
|
|
1225
|
+
kotlin: true,
|
|
1226
|
+
ts: true,
|
|
1227
|
+
ruby: true,
|
|
1228
|
+
tsx: true,
|
|
1229
|
+
};
|
|
1230
|
+
/** Whether a receiver name is capitalized like a type in a capitalized-name language. */
|
|
1231
|
+
function capitalizedTypeReceiverName(sup, receiver, text) {
|
|
1232
|
+
if (LANGUAGE_CONSTRUCTION_FORMS[sup.id]?.capitalizedCall !== true &&
|
|
1233
|
+
!STATIC_TYPE_NAME_RECEIVER_LANGUAGE_IDS[sup.id]) {
|
|
1234
|
+
return false;
|
|
1235
|
+
}
|
|
1236
|
+
if (!isReceiverNameNode(sup, receiver.type))
|
|
1237
|
+
return false;
|
|
1238
|
+
const first = text[0];
|
|
1239
|
+
return !!first && first === first.toUpperCase() && first !== first.toLowerCase();
|
|
1240
|
+
}
|
|
697
1241
|
/** Whether a resolved definition can declare callable members. */
|
|
698
1242
|
export function declaresMembers(def) {
|
|
699
1243
|
return def.kind === SymbolKind.Class || def.kind === SymbolKind.Interface || def.kind === SymbolKind.TypeAlias;
|
|
700
1244
|
}
|
|
1245
|
+
/** Whether a C++ definition denotes a class, struct, or union that can own methods. */
|
|
1246
|
+
export function isCppMemberContainerDefinition(tree, def) {
|
|
1247
|
+
const position = {
|
|
1248
|
+
row: Math.max(0, def.range.start.line - 1),
|
|
1249
|
+
column: Math.max(0, def.range.start.column - 1),
|
|
1250
|
+
};
|
|
1251
|
+
const nameNode = tree.rootNode.descendantForPosition(position, position);
|
|
1252
|
+
const container = nearestMemberContainer(nameNode);
|
|
1253
|
+
if (!container || CPP_MEMBER_CONTAINER_TYPES[container.type] === undefined)
|
|
1254
|
+
return false;
|
|
1255
|
+
const containerName = container.childForFieldName("name");
|
|
1256
|
+
return containerName?.startPosition.row === position.row && containerName.startPosition.column === position.column;
|
|
1257
|
+
}
|
|
701
1258
|
/** Nearest enclosing declaration that lexically owns `node` as a member. */
|
|
702
1259
|
export function nearestMemberContainer(node) {
|
|
703
1260
|
let current = node.parent;
|
|
@@ -708,29 +1265,168 @@ export function nearestMemberContainer(node) {
|
|
|
708
1265
|
}
|
|
709
1266
|
return null;
|
|
710
1267
|
}
|
|
711
|
-
/** Positional argument count of a call,
|
|
712
|
-
export function callArgumentCount(callNode) {
|
|
713
|
-
|
|
714
|
-
|
|
1268
|
+
/** Positional argument count of a call, including Kotlin/Swift trailing lambdas. */
|
|
1269
|
+
export function callArgumentCount(callNode, source) {
|
|
1270
|
+
// Kotlin wraps `pick(1) { }` in an outer call node whose only other child is the
|
|
1271
|
+
// callee call; the trailing lambda belongs to the inner call's argument list.
|
|
1272
|
+
let scope = callNode;
|
|
1273
|
+
for (let wrapper = trailingLambdaWrapper(scope); wrapper; wrapper = trailingLambdaWrapper(scope)) {
|
|
1274
|
+
scope = wrapper;
|
|
1275
|
+
}
|
|
1276
|
+
let argumentNode = callNode.childForFieldName("arguments") ??
|
|
1277
|
+
callNode.childForFieldName("argument_list") ??
|
|
1278
|
+
(callNode.namedChildren ?? []).find((child) => CALL_ARGUMENT_NODE_TYPES[child.type]) ??
|
|
1279
|
+
null;
|
|
715
1280
|
if (argumentNode?.type === "call_suffix") {
|
|
716
1281
|
argumentNode = (argumentNode.namedChildren ?? []).find((child) => child.type === "value_arguments") ?? null;
|
|
717
1282
|
}
|
|
718
|
-
if (!argumentNode)
|
|
719
|
-
|
|
720
|
-
|
|
1283
|
+
if (!argumentNode) {
|
|
1284
|
+
// Swift allows a call suffix with only a trailing lambda (`pick { }`), and Kotlin
|
|
1285
|
+
// `pick { }` keeps the lambda directly on the call node: no argument list exists.
|
|
1286
|
+
const suffix = (callNode.namedChildren ?? []).find((child) => child.type === "call_suffix");
|
|
1287
|
+
return ((suffix ?? scope).namedChildren ?? []).filter((child) => TRAILING_LAMBDA_NODE_TYPES[child.type] && child.startIndex >= callNode.startIndex).length;
|
|
1288
|
+
}
|
|
1289
|
+
let count = (argumentNode.namedChildren ?? []).filter((argument) => argument.type !== "comment").length;
|
|
1290
|
+
const trailingEnd = argumentNode.parent?.type === "call_suffix" ? argumentNode.parent.endIndex : scope.endIndex;
|
|
1291
|
+
if (trailingEnd > argumentNode.endIndex && containsTrailingLambdaNode(scope, argumentNode.endIndex, trailingEnd)) {
|
|
1292
|
+
const trailing = countTrailingClosureArguments(source.slice(argumentNode.endIndex, trailingEnd));
|
|
1293
|
+
// A null scan means the trailing-closure count is unknown, so the whole call
|
|
1294
|
+
// arity is unknown rather than the parenthesized count alone.
|
|
1295
|
+
if (trailing === null)
|
|
1296
|
+
return null;
|
|
1297
|
+
count += trailing;
|
|
1298
|
+
}
|
|
1299
|
+
return count;
|
|
721
1300
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
1301
|
+
/** Trailing lambda nodes across the supported grammars. */
|
|
1302
|
+
const TRAILING_LAMBDA_NODE_TYPES = {
|
|
1303
|
+
annotated_lambda: true, // Kotlin wraps the lambda on the outer call node.
|
|
1304
|
+
lambda_literal: true, // Swift keeps trailing lambdas inside `call_suffix`.
|
|
1305
|
+
};
|
|
1306
|
+
/** Call nodes that can wrap a callee call plus a Kotlin trailing lambda. */
|
|
1307
|
+
const TRAILING_LAMBDA_WRAPPER_TYPES = {
|
|
1308
|
+
call: true,
|
|
1309
|
+
call_expression: true,
|
|
1310
|
+
};
|
|
1311
|
+
/**
|
|
1312
|
+
* The outer call node attaching a trailing lambda to `node`, or null. The wrapper
|
|
1313
|
+
* never carries its own argument list, which distinguishes it from a chained call.
|
|
1314
|
+
*/
|
|
1315
|
+
function trailingLambdaWrapper(node) {
|
|
1316
|
+
const parent = node.parent;
|
|
1317
|
+
if (!parent || !TRAILING_LAMBDA_WRAPPER_TYPES[parent.type])
|
|
725
1318
|
return null;
|
|
726
|
-
const
|
|
727
|
-
if (
|
|
1319
|
+
const children = parent.namedChildren ?? [];
|
|
1320
|
+
if (children.some((child) => CALL_ARGUMENT_NODE_TYPES[child.type]))
|
|
728
1321
|
return null;
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
1322
|
+
return children.some((child) => TRAILING_LAMBDA_NODE_TYPES[child.type]) ? parent : null;
|
|
1323
|
+
}
|
|
1324
|
+
/** Whether a trailing lambda node overlaps `[start, end)` anywhere under `node`. */
|
|
1325
|
+
function containsTrailingLambdaNode(node, start, end) {
|
|
1326
|
+
for (const child of node.namedChildren ?? []) {
|
|
1327
|
+
if (child.endIndex <= start || child.startIndex >= end)
|
|
1328
|
+
continue;
|
|
1329
|
+
if (TRAILING_LAMBDA_NODE_TYPES[child.type])
|
|
1330
|
+
return true;
|
|
1331
|
+
if (containsTrailingLambdaNode(child, start, end))
|
|
1332
|
+
return true;
|
|
1333
|
+
}
|
|
1334
|
+
return false;
|
|
1335
|
+
}
|
|
1336
|
+
/** End index after a Swift trailing-closure label and its colon, or null when absent. */
|
|
1337
|
+
function trailingClosureLabelEnd(text, startIndex) {
|
|
1338
|
+
if (text[startIndex] === "`") {
|
|
1339
|
+
const escapedEnd = text.indexOf("`", startIndex + 1);
|
|
1340
|
+
if (escapedEnd < 0 || text[escapedEnd + 1] !== ":")
|
|
1341
|
+
return null;
|
|
1342
|
+
return escapedEnd + 2;
|
|
1343
|
+
}
|
|
1344
|
+
const identifier = /^[_\p{ID_Start}][_\p{ID_Continue}]*/u.exec(text.slice(startIndex));
|
|
1345
|
+
if (!identifier)
|
|
732
1346
|
return null;
|
|
733
|
-
|
|
1347
|
+
const colonIndex = startIndex + identifier[0].length;
|
|
1348
|
+
return text[colonIndex] === ":" ? colonIndex + 1 : null;
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Counts the top-level `{ ... }` blocks in trailing call text, one per trailing
|
|
1352
|
+
* closure, or null when the text is not a well-formed trailing-closure run.
|
|
1353
|
+
* Shared with call-compatibility extraction so both paths count identically.
|
|
1354
|
+
*/
|
|
1355
|
+
export function countTrailingClosureArguments(text) {
|
|
1356
|
+
let startIndex = 0;
|
|
1357
|
+
let count = 0;
|
|
1358
|
+
while (startIndex < text.length) {
|
|
1359
|
+
while (/\s/.test(text[startIndex] ?? "")) {
|
|
1360
|
+
startIndex += 1;
|
|
1361
|
+
}
|
|
1362
|
+
if (startIndex === text.length) {
|
|
1363
|
+
return count;
|
|
1364
|
+
}
|
|
1365
|
+
if (text[startIndex] !== "{") {
|
|
1366
|
+
const labelEnd = trailingClosureLabelEnd(text, startIndex);
|
|
1367
|
+
if (labelEnd === null)
|
|
1368
|
+
return null;
|
|
1369
|
+
startIndex = labelEnd;
|
|
1370
|
+
while (/\s/.test(text[startIndex] ?? "")) {
|
|
1371
|
+
startIndex += 1;
|
|
1372
|
+
}
|
|
1373
|
+
if (text[startIndex] !== "{")
|
|
1374
|
+
return null;
|
|
1375
|
+
}
|
|
1376
|
+
let braceDepth = 0;
|
|
1377
|
+
let quote = null;
|
|
1378
|
+
let escaped = false;
|
|
1379
|
+
let closed = false;
|
|
1380
|
+
for (let index = startIndex; index < text.length; index += 1) {
|
|
1381
|
+
const char = text[index];
|
|
1382
|
+
if (quote) {
|
|
1383
|
+
if (escaped) {
|
|
1384
|
+
escaped = false;
|
|
1385
|
+
continue;
|
|
1386
|
+
}
|
|
1387
|
+
if (char === "\\") {
|
|
1388
|
+
escaped = true;
|
|
1389
|
+
continue;
|
|
1390
|
+
}
|
|
1391
|
+
if (char === quote) {
|
|
1392
|
+
quote = null;
|
|
1393
|
+
}
|
|
1394
|
+
continue;
|
|
1395
|
+
}
|
|
1396
|
+
const commentEnd = findCommentEnd(text, index);
|
|
1397
|
+
if (commentEnd !== null) {
|
|
1398
|
+
if (commentEnd < 0) {
|
|
1399
|
+
return null;
|
|
1400
|
+
}
|
|
1401
|
+
index = commentEnd - 1;
|
|
1402
|
+
continue;
|
|
1403
|
+
}
|
|
1404
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
1405
|
+
quote = char;
|
|
1406
|
+
continue;
|
|
1407
|
+
}
|
|
1408
|
+
if (char === "{") {
|
|
1409
|
+
braceDepth += 1;
|
|
1410
|
+
continue;
|
|
1411
|
+
}
|
|
1412
|
+
if (char === "}") {
|
|
1413
|
+
braceDepth -= 1;
|
|
1414
|
+
if (braceDepth < 0) {
|
|
1415
|
+
return null;
|
|
1416
|
+
}
|
|
1417
|
+
if (!braceDepth) {
|
|
1418
|
+
startIndex = index + 1;
|
|
1419
|
+
count += 1;
|
|
1420
|
+
closed = true;
|
|
1421
|
+
break;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
if (!closed) {
|
|
1426
|
+
return null;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
return count;
|
|
734
1430
|
}
|
|
735
1431
|
function loadSource(file, cache) {
|
|
736
1432
|
const cached = cache.get(file);
|
|
@@ -746,20 +1442,6 @@ function loadSource(file, cache) {
|
|
|
746
1442
|
return "";
|
|
747
1443
|
}
|
|
748
1444
|
}
|
|
749
|
-
function memberIdLooksStatic(memberId, sourceCache) {
|
|
750
|
-
const parsed = parseDefNodeId(memberId);
|
|
751
|
-
if (!parsed)
|
|
752
|
-
return false;
|
|
753
|
-
const source = loadSource(parsed.file, sourceCache);
|
|
754
|
-
if (!source)
|
|
755
|
-
return false;
|
|
756
|
-
const beforeBrace = source.lastIndexOf("{", parsed.index);
|
|
757
|
-
const beforeSemi = source.lastIndexOf(";", parsed.index);
|
|
758
|
-
const beforeClose = source.lastIndexOf("}", parsed.index);
|
|
759
|
-
const declStart = Math.max(beforeBrace, beforeSemi, beforeClose);
|
|
760
|
-
const prefix = source.slice(declStart + 1, parsed.index);
|
|
761
|
-
return /(?:^|[^\w$])static(?:$|[^\w$])/.test(prefix) || /(?:^|[^\w$])def\s+self\s*\./.test(prefix);
|
|
762
|
-
}
|
|
763
1445
|
function inferCallMemberScope(site, sourceCache) {
|
|
764
1446
|
const source = loadSource(site.file, sourceCache);
|
|
765
1447
|
if (!source)
|
|
@@ -774,22 +1456,108 @@ function inferCallMemberScope(site, sourceCache) {
|
|
|
774
1456
|
return "instance";
|
|
775
1457
|
if (/\)\s*\.\s*$/.test(before))
|
|
776
1458
|
return "instance";
|
|
777
|
-
//
|
|
778
|
-
// A lowercase dotted receiver is an instance value (`c.StaticMethod()`), not a type.
|
|
1459
|
+
// Older serialized candidates lack memberScope. Infer the common dotted-receiver cases.
|
|
779
1460
|
if (/(?:^|[^A-Za-z0-9_$])[a-z_][A-Za-z0-9_]*\s*\.\s*$/.test(before))
|
|
780
1461
|
return "instance";
|
|
781
1462
|
if (/(?:^|[^A-Za-z0-9_$])[A-Z][A-Za-z0-9_]*\s*\.\s*$/.test(before))
|
|
782
1463
|
return "static";
|
|
783
1464
|
return "any";
|
|
784
1465
|
}
|
|
1466
|
+
function callSiteKey(callerId, site) {
|
|
1467
|
+
const { start, end } = site.range;
|
|
1468
|
+
return `${callerId}\u0000${site.file}\u0000${start.line}:${start.column}:${start.index ?? ""}-${end.line}:${end.column}:${end.index ?? ""}`;
|
|
1469
|
+
}
|
|
1470
|
+
/** Prove overriding member pairs only for hierarchy receiver calls. */
|
|
1471
|
+
export async function inheritedReceiverMemberSignatures(graph, candidates, definitions, ownerAnchors, accessibleMembers, languageExtensions, sameParameterTypes) {
|
|
1472
|
+
const signatures = new Map();
|
|
1473
|
+
const membersByOwner = new Map();
|
|
1474
|
+
const ownerByMember = new Map();
|
|
1475
|
+
const parentsByOwner = new Map();
|
|
1476
|
+
for (const edge of graph.edges) {
|
|
1477
|
+
if (edge.label === "member_of") {
|
|
1478
|
+
ownerByMember.set(edge.from, edge.to);
|
|
1479
|
+
if (definitions.has(edge.from)) {
|
|
1480
|
+
const members = membersByOwner.get(edge.to) ?? [];
|
|
1481
|
+
members.push(edge.from);
|
|
1482
|
+
membersByOwner.set(edge.to, members);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
else if (edge.label && HIERARCHY_LABELS[edge.label]) {
|
|
1486
|
+
const parents = parentsByOwner.get(edge.from) ?? [];
|
|
1487
|
+
parents.push(edge.to);
|
|
1488
|
+
parentsByOwner.set(edge.from, parents);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
for (const [owner, accessible] of accessibleMembers) {
|
|
1492
|
+
const members = membersByOwner.get(owner) ?? [];
|
|
1493
|
+
for (const id of accessible)
|
|
1494
|
+
if (definitions.has(id) && !members.includes(id))
|
|
1495
|
+
members.push(id);
|
|
1496
|
+
membersByOwner.set(owner, members);
|
|
1497
|
+
}
|
|
1498
|
+
const checkedPairs = new Set();
|
|
1499
|
+
const checkedGroups = new Set();
|
|
1500
|
+
const separator = "\0";
|
|
1501
|
+
for (const candidate of candidates) {
|
|
1502
|
+
if (!inheritsMemberOverloads(supportForFileWithoutHeaderSample(candidate.site.file, languageExtensions)?.id ?? "")) {
|
|
1503
|
+
continue;
|
|
1504
|
+
}
|
|
1505
|
+
const rawOwner = candidate.ownerId ?? ownerByMember.get(candidate.callerId);
|
|
1506
|
+
if (!rawOwner)
|
|
1507
|
+
continue;
|
|
1508
|
+
const owner = ownerAnchors.get(rawOwner) ?? rawOwner;
|
|
1509
|
+
// Override pairs are a fact of the declarations, not of this call: an override that rejects
|
|
1510
|
+
// the argument count still hides the base declaration it overrides.
|
|
1511
|
+
const group = `${owner}\0${candidate.memberName}\0${candidate.viaSupertypes}`;
|
|
1512
|
+
if (checkedGroups.has(group))
|
|
1513
|
+
continue;
|
|
1514
|
+
checkedGroups.add(group);
|
|
1515
|
+
let level = candidate.viaSupertypes ? (parentsByOwner.get(owner) ?? []) : [owner];
|
|
1516
|
+
const seen = new Set([owner]);
|
|
1517
|
+
const shallower = [];
|
|
1518
|
+
for (let depth = 0; depth < 16 && level.length; depth += 1) {
|
|
1519
|
+
const current = [];
|
|
1520
|
+
const next = [];
|
|
1521
|
+
for (const id of level) {
|
|
1522
|
+
for (const memberId of membersByOwner.get(id) ?? []) {
|
|
1523
|
+
if (graph.nodes.get(memberId)?.name === candidate.memberName)
|
|
1524
|
+
current.push(memberId);
|
|
1525
|
+
}
|
|
1526
|
+
for (const parent of parentsByOwner.get(id) ?? []) {
|
|
1527
|
+
if (seen.has(parent))
|
|
1528
|
+
continue;
|
|
1529
|
+
seen.add(parent);
|
|
1530
|
+
next.push(parent);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
for (const derivedId of shallower) {
|
|
1534
|
+
const derived = definitions.get(derivedId);
|
|
1535
|
+
for (const inheritedId of current) {
|
|
1536
|
+
const pair = derivedId + separator + inheritedId;
|
|
1537
|
+
if (checkedPairs.has(pair))
|
|
1538
|
+
continue;
|
|
1539
|
+
checkedPairs.add(pair);
|
|
1540
|
+
if (!(await sameParameterTypes(derived, definitions.get(inheritedId))))
|
|
1541
|
+
continue;
|
|
1542
|
+
const inherited = signatures.get(derivedId) ?? new Set();
|
|
1543
|
+
inherited.add(inheritedId);
|
|
1544
|
+
signatures.set(derivedId, inherited);
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
shallower.push(...current);
|
|
1548
|
+
level = next;
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
return signatures;
|
|
1552
|
+
}
|
|
785
1553
|
/**
|
|
786
1554
|
* Records proven `calls` edges for deferred receiver invocations.
|
|
787
1555
|
* Ambiguous names at a level stop the walk.
|
|
788
1556
|
* `super`/`base`/`parent` follow class `extends` ancestors only.
|
|
789
1557
|
*/
|
|
790
|
-
export function emitReceiverCallEdges(graph, candidates, recordEdge) {
|
|
1558
|
+
export function emitReceiverCallEdges(graph, candidates, recordEdge, memberScopes = new Map(), nodeAliases = new Map(), memberArities = new Map(), ownerAnchors = new Map(), accessibleMembers = new Map(), fileHiddenMemberIds = new Set(), acceptsCallTarget, callableIdentities = new Map(), languageExtensions, overridingSignatures, isReceiverMemberVisible) {
|
|
791
1559
|
if (!candidates.length)
|
|
792
|
-
return;
|
|
1560
|
+
return [];
|
|
793
1561
|
const membersByOwner = new Map();
|
|
794
1562
|
const ownerByMember = new Map();
|
|
795
1563
|
const supertypesByOwner = new Map();
|
|
@@ -814,69 +1582,150 @@ export function emitReceiverCallEdges(graph, candidates, recordEdge) {
|
|
|
814
1582
|
if (label === "extends")
|
|
815
1583
|
pushUnique(classAncestorsByOwner, edge.from, edge.to);
|
|
816
1584
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
1585
|
+
// Receiver-local access does not change the nominal type's membership edges.
|
|
1586
|
+
for (const [ownerId, memberIds] of accessibleMembers) {
|
|
1587
|
+
for (const memberId of memberIds)
|
|
1588
|
+
pushUnique(membersByOwner, ownerId, memberId);
|
|
1589
|
+
}
|
|
1590
|
+
let activeCandidate;
|
|
1591
|
+
const facts = new Map();
|
|
1592
|
+
for (const [ownerId, ids] of membersByOwner) {
|
|
1593
|
+
for (const id of ids) {
|
|
1594
|
+
const canonicalId = canonicalMemberId(id, nodeAliases);
|
|
1595
|
+
const indexed = callableIdentities.get(id) ?? callableIdentities.get(canonicalId);
|
|
1596
|
+
const bounds = memberArities.get(id) ?? memberArities.get(canonicalId);
|
|
1597
|
+
facts.set(id, {
|
|
1598
|
+
key: indexed?.key ?? canonicalId,
|
|
1599
|
+
owner: indexed?.owner ?? ownerId,
|
|
1600
|
+
kind: indexed?.kind ?? "function",
|
|
1601
|
+
arity: bounds ? { minArgs: bounds.min, maxArgs: bounds.max } : null,
|
|
1602
|
+
...(indexed?.role ? { role: indexed.role } : {}),
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
const model = {
|
|
1607
|
+
ownerKey: (id) => id,
|
|
1608
|
+
members: (id) => membersByOwner.get(id) ?? [],
|
|
1609
|
+
supertypes: (id, classOnly) => {
|
|
1610
|
+
if (!classOnly)
|
|
1611
|
+
return supertypesByOwner.get(id) ?? [];
|
|
1612
|
+
return (classAncestorsByOwner.get(id) ?? []).filter((base) => graph.nodes.get(base)?.kind === "class");
|
|
1613
|
+
},
|
|
1614
|
+
name: (id) => graph.nodes.get(id)?.name ?? graph.nodes.get(canonicalMemberId(id, nodeAliases))?.name ?? "",
|
|
1615
|
+
key: (id) => facts.get(id)?.key ?? canonicalMemberId(id, nodeAliases),
|
|
1616
|
+
callable: (id) => facts.get(id),
|
|
1617
|
+
scope: (id) => memberScopes.get(id) ?? memberScopes.get(canonicalMemberId(id, nodeAliases)) ?? "any",
|
|
1618
|
+
visible: (id, useFile) => {
|
|
1619
|
+
const canonicalId = canonicalMemberId(id, nodeAliases);
|
|
1620
|
+
const node = graph.nodes.get(id) ?? graph.nodes.get(canonicalId);
|
|
1621
|
+
if (!node || (node.kind !== "function" && !node.callable))
|
|
1622
|
+
return false;
|
|
1623
|
+
if (isReceiverMemberVisible && !isReceiverMemberVisible(canonicalId, useFile))
|
|
1624
|
+
return false;
|
|
1625
|
+
if ((fileHiddenMemberIds.has(id) || fileHiddenMemberIds.has(canonicalId)) &&
|
|
1626
|
+
fileIdentityKey(node.file) !== fileIdentityKey(useFile))
|
|
1627
|
+
return false;
|
|
1628
|
+
return (!activeCandidate.goPackagePeerFiles ||
|
|
1629
|
+
isGoExportedMemberName("go", node.name) ||
|
|
1630
|
+
activeCandidate.goPackagePeerFiles.has(node.file));
|
|
1631
|
+
},
|
|
1632
|
+
sameSignature: (a, b) => overridingSignatures?.get(a)?.has(b) ?? false,
|
|
821
1633
|
};
|
|
1634
|
+
const callTargetsBySite = new Map();
|
|
1635
|
+
for (const edge of graph.edges) {
|
|
1636
|
+
if (edge.label !== "calls" || !edge.site)
|
|
1637
|
+
continue;
|
|
1638
|
+
const key = callSiteKey(edge.from, edge.site);
|
|
1639
|
+
const targets = callTargetsBySite.get(key);
|
|
1640
|
+
if (targets)
|
|
1641
|
+
targets.add(edge.to);
|
|
1642
|
+
else
|
|
1643
|
+
callTargetsBySite.set(key, new Set([edge.to]));
|
|
1644
|
+
}
|
|
1645
|
+
const rejectedCallSites = new Set();
|
|
822
1646
|
const sourceCache = new Map();
|
|
823
1647
|
for (const candidate of candidates) {
|
|
824
|
-
const
|
|
825
|
-
|
|
1648
|
+
const siteKey = callSiteKey(candidate.callerId, candidate.site);
|
|
1649
|
+
const existingTargets = callTargetsBySite.get(siteKey) ?? new Set();
|
|
1650
|
+
if (existingTargets.size > 1) {
|
|
1651
|
+
rejectedCallSites.add(siteKey);
|
|
826
1652
|
continue;
|
|
1653
|
+
}
|
|
1654
|
+
const rawOwner = candidate.ownerId ?? ownerByMember.get(candidate.callerId);
|
|
1655
|
+
if (!rawOwner)
|
|
1656
|
+
continue;
|
|
1657
|
+
// Shared-owner anchors redirect Swift extension and C# partial owners to the
|
|
1658
|
+
// coalesced type identity so lookup starts on the whole member set.
|
|
1659
|
+
const owner = ownerAnchors.get(rawOwner) ?? rawOwner;
|
|
827
1660
|
const memberScope = candidate.memberScope ?? inferCallMemberScope(candidate.site, sourceCache);
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
1661
|
+
const languageId = supportForFileWithoutHeaderSample(candidate.site.file, languageExtensions)?.id ?? "";
|
|
1662
|
+
activeCandidate = candidate;
|
|
1663
|
+
const lookup = selectMember([owner], model, {
|
|
1664
|
+
name: candidate.memberName,
|
|
1665
|
+
argumentCount: candidate.argumentCount,
|
|
1666
|
+
scope: memberScope,
|
|
1667
|
+
useFile: candidate.site.file,
|
|
1668
|
+
phpCaseInsensitive: !!candidate.caseInsensitiveMemberName,
|
|
1669
|
+
separateMemberScopes: hasSeparateMemberScopes(languageId),
|
|
1670
|
+
startAtAncestor: candidate.viaSupertypes,
|
|
1671
|
+
inheritOverloads: inheritsMemberOverloads(languageId),
|
|
1672
|
+
});
|
|
1673
|
+
let receiverDisposition = lookup.status === "unique" ? "resolved" : lookup.status;
|
|
1674
|
+
if (lookup.status === "unique") {
|
|
1675
|
+
const memberId = canonicalMemberId(lookup.member, nodeAliases);
|
|
1676
|
+
if (acceptsCallTarget && !acceptsCallTarget(memberId, candidate)) {
|
|
1677
|
+
receiverDisposition = "ambiguous";
|
|
1678
|
+
if (existingTargets.size)
|
|
1679
|
+
rejectedCallSites.add(siteKey);
|
|
835
1680
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
if (
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
1681
|
+
else {
|
|
1682
|
+
receiverDisposition = "resolved";
|
|
1683
|
+
const combinedTargets = new Set(existingTargets);
|
|
1684
|
+
combinedTargets.add(memberId);
|
|
1685
|
+
if (combinedTargets.size === 1) {
|
|
1686
|
+
if (!existingTargets.size && recordEdge(candidate.callerId, memberId, "calls", candidate.site)) {
|
|
1687
|
+
existingTargets.add(memberId);
|
|
1688
|
+
callTargetsBySite.set(siteKey, existingTargets);
|
|
1689
|
+
}
|
|
845
1690
|
}
|
|
1691
|
+
else
|
|
1692
|
+
rejectedCallSites.add(siteKey);
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
else if (lookup.status === "ambiguous" && existingTargets.size) {
|
|
1696
|
+
rejectedCallSites.add(siteKey);
|
|
1697
|
+
}
|
|
1698
|
+
if (receiverDisposition === "none") {
|
|
1699
|
+
if (candidate.fallbackTargetId && !existingTargets.size) {
|
|
1700
|
+
recordEdge(candidate.callerId, candidate.fallbackTargetId, "calls", candidate.site);
|
|
1701
|
+
}
|
|
1702
|
+
else if (existingTargets.size) {
|
|
1703
|
+
rejectedCallSites.add(siteKey);
|
|
846
1704
|
}
|
|
847
|
-
level = next;
|
|
848
1705
|
}
|
|
849
1706
|
}
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
*/
|
|
857
|
-
function provenMemberTarget(graph, membersByOwner, owners, candidate, memberScope, sourceCache) {
|
|
858
|
-
const matches = new Set();
|
|
859
|
-
for (const ownerId of owners) {
|
|
860
|
-
for (const memberId of membersByOwner.get(ownerId) ?? []) {
|
|
861
|
-
const node = graph.nodes.get(memberId);
|
|
862
|
-
if (!node || node.kind !== "function" || node.name !== candidate.memberName)
|
|
863
|
-
continue;
|
|
864
|
-
if (memberScope === "static" && !memberIdLooksStatic(memberId, sourceCache))
|
|
865
|
-
continue;
|
|
866
|
-
if (memberScope === "instance" && memberIdLooksStatic(memberId, sourceCache))
|
|
1707
|
+
const removed = [];
|
|
1708
|
+
if (rejectedCallSites.size) {
|
|
1709
|
+
let writeIndex = 0;
|
|
1710
|
+
for (const edge of graph.edges) {
|
|
1711
|
+
if (edge.label === "calls" && edge.site && rejectedCallSites.has(callSiteKey(edge.from, edge.site))) {
|
|
1712
|
+
removed.push(edge);
|
|
867
1713
|
continue;
|
|
868
|
-
|
|
1714
|
+
}
|
|
1715
|
+
graph.edges[writeIndex] = edge;
|
|
1716
|
+
writeIndex += 1;
|
|
869
1717
|
}
|
|
1718
|
+
graph.edges.length = writeIndex;
|
|
870
1719
|
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
return
|
|
1720
|
+
return removed;
|
|
1721
|
+
}
|
|
1722
|
+
function canonicalMemberId(id, aliases) {
|
|
1723
|
+
let current = id;
|
|
1724
|
+
const seen = new Set();
|
|
1725
|
+
while (aliases.has(current) && !seen.has(current)) {
|
|
1726
|
+
seen.add(current);
|
|
1727
|
+
current = aliases.get(current);
|
|
1728
|
+
}
|
|
1729
|
+
return current;
|
|
881
1730
|
}
|
|
882
1731
|
//# sourceMappingURL=receiver-calls.js.map
|