@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,16 +1,60 @@
|
|
|
1
|
+
import path from "node:path";
|
|
1
2
|
import { supportForFileWithoutHeaderSample } from "../languages.js";
|
|
2
|
-
import { fileIdentityKey } from "../util/paths.js";
|
|
3
|
+
import { fileIdentityKey, normalizePath } from "../util/paths.js";
|
|
3
4
|
import { sliceText, toRange } from "../util/ast.js";
|
|
5
|
+
import { getMemberAccessParts, isMemberAccessNode, isReceiverNameNode } from "../util/member-access.js";
|
|
6
|
+
import { classifyReceiver, declaresMembers, receiverConstructorExpression, } from "../graphs/symbol-graph-detailed/receiver-calls.js";
|
|
7
|
+
import { provenClassifiedReceiverOmitsMember } from "./navigation-goto.js";
|
|
4
8
|
import { ensureParsedContext } from "./parse-context.js";
|
|
5
|
-
import { sameDef } from "./reference-context.js";
|
|
6
|
-
import { readPhpNamespaceFromRange } from "./navigation-php.js";
|
|
9
|
+
import { definitionIdentityKey, sameDef } from "./reference-context.js";
|
|
10
|
+
import { canonicalPhpReferenceNames, comparePhpReferenceNames, getPhpQualifiedReference, inferPhpQualifiedReferenceImportType, isInsidePhpUseDeclaration, isPhpQualifiedReferenceNode, phpLastIdentifierSegment, readPhpNamespaceFromRange, selectFirstExistingPhpCanonicalName, } from "./navigation-php.js";
|
|
11
|
+
import { isKeywordReceiver, memberSyntaxNamesFreeFunction } from "../util/member-access-tables.js";
|
|
12
|
+
import { getCompilationUnitPeers, getPackageDeclarationName } from "./compilation-units.js";
|
|
13
|
+
import { isJvmPackageSymbolVisible } from "./declaration-visibility.js";
|
|
14
|
+
import { findClosestScopeBinding, getOrBuildScopeIndex } from "./navigation-local.js";
|
|
15
|
+
import { scopeNodesFor } from "./scope-nodes.js";
|
|
7
16
|
import { candidateFilesImportingTarget } from "./reference-candidates.js";
|
|
8
|
-
import {
|
|
9
|
-
import { resolveExport, resolveImported } from "./navigation-resolve.js";
|
|
10
|
-
import {
|
|
17
|
+
import { bindingKindToSymbolKind } from "./declarations.js";
|
|
18
|
+
import { javaKotlinFunctionOverloadIncludes, javaStaticNamedImportIncludes, resolveExport, resolveImported, } from "./navigation-resolve.js";
|
|
19
|
+
import { isAmbiguousResolutionReason } from "./ambiguous-resolution.js";
|
|
20
|
+
import { ensurePhpNamespaceSymbolIndex, phpNamespaceSymbolIndexFor, phpReferenceRoleMatchesKind, } from "./php-namespace-symbols.js";
|
|
21
|
+
import { SymbolKind, } from "./types.js";
|
|
22
|
+
import { ECMASCRIPT_IDENTIFIER_SOURCE, foldPhpIdentifierCase } from "../util/identifiers.js";
|
|
23
|
+
import { JAVA_UNICODE_ESCAPE_BLOOM_TOKEN } from "../util/bloom-filter.js";
|
|
11
24
|
const EXPORT_FROM_PATTERN = new RegExp(String.raw `\bexport\s+(?:type\s+)?\{([^}]*)\}\s*from\s*(["'])([^"']+)\2`, "gu");
|
|
12
25
|
const NAMESPACE_EXPORT_PATTERN = new RegExp(String.raw `\bexport\s*\*\s*as\s*(${ECMASCRIPT_IDENTIFIER_SOURCE})\s*from\s*(["'])([^"']+)\2`, "gu");
|
|
13
26
|
const EXPORT_FROM_SPECIFIER_PATTERN = new RegExp(String.raw `^(${ECMASCRIPT_IDENTIFIER_SOURCE})`, "u");
|
|
27
|
+
const importClosureCache = new WeakMap();
|
|
28
|
+
/** File keys reachable from `file` through resolved imports and includes, including `file`. */
|
|
29
|
+
function importClosure(index, file) {
|
|
30
|
+
let byFile = importClosureCache.get(index);
|
|
31
|
+
if (!byFile) {
|
|
32
|
+
byFile = new Map();
|
|
33
|
+
importClosureCache.set(index, byFile);
|
|
34
|
+
}
|
|
35
|
+
const startKey = fileIdentityKey(file);
|
|
36
|
+
const cached = byFile.get(startKey);
|
|
37
|
+
if (cached)
|
|
38
|
+
return cached;
|
|
39
|
+
const reached = new Set([startKey]);
|
|
40
|
+
const startModule = index.byFile.get(startKey);
|
|
41
|
+
const pending = startModule ? [startModule] : [];
|
|
42
|
+
while (pending.length) {
|
|
43
|
+
for (const imp of pending.pop().imports) {
|
|
44
|
+
if (typeof imp.resolved !== "string")
|
|
45
|
+
continue;
|
|
46
|
+
const key = fileIdentityKey(imp.resolved);
|
|
47
|
+
if (reached.has(key))
|
|
48
|
+
continue;
|
|
49
|
+
reached.add(key);
|
|
50
|
+
const moduleEntry = index.byFile.get(key);
|
|
51
|
+
if (moduleEntry)
|
|
52
|
+
pending.push(moduleEntry);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
byFile.set(startKey, reached);
|
|
56
|
+
return reached;
|
|
57
|
+
}
|
|
14
58
|
export function exportFromIdentifier(index, fileId, range, parsed) {
|
|
15
59
|
if (!parsed.sup.supportsExportFromReferences)
|
|
16
60
|
return null;
|
|
@@ -67,40 +111,198 @@ export function exportFromIdentifier(index, fileId, range, parsed) {
|
|
|
67
111
|
return null;
|
|
68
112
|
}
|
|
69
113
|
export function getCachedScope(index, fileId, moduleIndex, parsedCtx) {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
114
|
+
const keepOccurrence = (binding, occurrence) => {
|
|
115
|
+
if (exportFromIdentifier(index, fileId, occurrence, parsedCtx)?.isExportFrom)
|
|
116
|
+
return false;
|
|
117
|
+
if (parsedCtx.sup.id !== "php" || !binding.def || occurrence.start.index === binding.def.start.index)
|
|
118
|
+
return true;
|
|
119
|
+
const kind = bindingKindToSymbolKind(binding.kind);
|
|
120
|
+
if (kind === SymbolKind.Variable)
|
|
121
|
+
return true;
|
|
122
|
+
const start = occurrence.start.index;
|
|
123
|
+
if (start === undefined)
|
|
124
|
+
return true;
|
|
125
|
+
const node = parsedCtx.tree.rootNode.descendantForIndex(start, start);
|
|
126
|
+
return phpReferenceRoleMatchesKind(node, kind);
|
|
127
|
+
};
|
|
128
|
+
// One builder for the shared scope cache: it reuses the module's indexed callables.
|
|
129
|
+
const scopeIndex = getOrBuildScopeIndex(index, fileId, parsedCtx.source, parsedCtx.sup, moduleIndex, parsedCtx.tree);
|
|
81
130
|
for (const binding of scopeIndex.all) {
|
|
82
|
-
binding.occurrences = binding.occurrences.filter((occurrence) =>
|
|
131
|
+
binding.occurrences = binding.occurrences.filter((occurrence) => keepOccurrence(binding, occurrence));
|
|
83
132
|
}
|
|
84
|
-
index.scopeCache.set(fileKey, scopeIndex);
|
|
85
133
|
return scopeIndex;
|
|
86
134
|
}
|
|
87
|
-
|
|
135
|
+
/**
|
|
136
|
+
* The authoritative PHP spellings of a definition: `Namespace\Name`, or the bare `Name` for a
|
|
137
|
+
* global-namespace declaration. These are the names a reference must resolve to, so they keep
|
|
138
|
+
* the declaration's own case. A global-namespace declaration is still addressable by its bare
|
|
139
|
+
* name and by the fully-qualified `\Name` spelling, so the global-name scan must run for it;
|
|
140
|
+
* returning `[]` here left a global PHP symbol on the importer-narrowed path, which never scans
|
|
141
|
+
* a consumer that has no `use` statement.
|
|
142
|
+
*/
|
|
143
|
+
async function readPhpDefinitionNames(index, definitionFile, def) {
|
|
88
144
|
try {
|
|
89
145
|
const definitionParsed = await ensureParsedContext(definitionFile, index.parsed?.get(fileIdentityKey(definitionFile)), index.languageExtensions);
|
|
90
146
|
if (definitionParsed.sup.id !== "php") {
|
|
91
147
|
return [];
|
|
92
148
|
}
|
|
93
149
|
const phpNamespace = readPhpNamespaceFromRange(definitionParsed.tree, definitionParsed.source, def.range);
|
|
94
|
-
|
|
95
|
-
return [];
|
|
96
|
-
const qualifiedName = `${phpNamespace}\\${def.localName}`;
|
|
97
|
-
return [qualifiedName, `\\${qualifiedName}`];
|
|
150
|
+
return [phpNamespace ? `${phpNamespace}\\${def.localName}` : def.localName];
|
|
98
151
|
}
|
|
99
152
|
catch {
|
|
100
153
|
return [];
|
|
101
154
|
}
|
|
102
155
|
}
|
|
103
|
-
async function
|
|
156
|
+
export async function buildPhpQualifiedNames(index, definitionFile, def) {
|
|
157
|
+
// Keep one canonical spelling. Case-variant consumers are admitted during the single AST
|
|
158
|
+
// walk by comparePhpReferenceNames; extra folded probes would multiply whole-file scans.
|
|
159
|
+
return readPhpDefinitionNames(index, definitionFile, def);
|
|
160
|
+
}
|
|
161
|
+
const phpCanonicalNamesCache = new WeakMap();
|
|
162
|
+
const phpNameEquivalenceGaps = new WeakMap();
|
|
163
|
+
async function phpCanonicalDefinitionNames(index, def) {
|
|
164
|
+
let perIndex = phpCanonicalNamesCache.get(index);
|
|
165
|
+
if (!perIndex) {
|
|
166
|
+
perIndex = new Map();
|
|
167
|
+
phpCanonicalNamesCache.set(index, perIndex);
|
|
168
|
+
}
|
|
169
|
+
const key = definitionIdentityKey(def);
|
|
170
|
+
const cached = perIndex.get(key);
|
|
171
|
+
if (cached)
|
|
172
|
+
return cached;
|
|
173
|
+
const indexed = phpNamespaceSymbolIndexFor(index)?.canonicalByDefinition.get(key);
|
|
174
|
+
if (indexed) {
|
|
175
|
+
perIndex.set(key, [indexed]);
|
|
176
|
+
return [indexed];
|
|
177
|
+
}
|
|
178
|
+
const canonicalNames = (await readPhpDefinitionNames(index, def.file, def)).map((name) => name.replace(/^\\+/, ""));
|
|
179
|
+
perIndex.set(key, canonicalNames);
|
|
180
|
+
return canonicalNames;
|
|
181
|
+
}
|
|
182
|
+
function markPhpNameEquivalenceGap(index, def) {
|
|
183
|
+
let gaps = phpNameEquivalenceGaps.get(index);
|
|
184
|
+
if (!gaps) {
|
|
185
|
+
gaps = new Set();
|
|
186
|
+
phpNameEquivalenceGaps.set(index, gaps);
|
|
187
|
+
}
|
|
188
|
+
gaps.add(definitionIdentityKey(def));
|
|
189
|
+
}
|
|
190
|
+
const PHP_OWN_RECEIVER_KEYWORDS = new Set(["$this", "self", "static"]);
|
|
191
|
+
const PHP_TYPE_CONTAINER_TYPES = new Set([
|
|
192
|
+
"class_declaration",
|
|
193
|
+
"interface_declaration",
|
|
194
|
+
"trait_declaration",
|
|
195
|
+
"enum_declaration",
|
|
196
|
+
]);
|
|
197
|
+
async function phpOwnerInfo(index, def) {
|
|
198
|
+
const module = index.byFile.get(fileIdentityKey(def.file));
|
|
199
|
+
if (!module)
|
|
200
|
+
return null;
|
|
201
|
+
const parsed = await ensureParsedContext(def.file, index.parsed?.get(fileIdentityKey(def.file)), index.languageExtensions);
|
|
202
|
+
const start = def.range.start;
|
|
203
|
+
const position = { row: Math.max(0, start.line - 1), column: Math.max(0, start.column - 1) };
|
|
204
|
+
let current = parsed.tree.rootNode.descendantForPosition(position, position);
|
|
205
|
+
while (current) {
|
|
206
|
+
if (PHP_TYPE_CONTAINER_TYPES.has(current.type)) {
|
|
207
|
+
const nameNode = current.childForFieldName("name");
|
|
208
|
+
const className = nameNode ? sliceText(nameNode, parsed.source) : null;
|
|
209
|
+
if (!className)
|
|
210
|
+
return null;
|
|
211
|
+
const owner = module.locals.find((local) => local.localName === className &&
|
|
212
|
+
local.range.start.index === nameNode?.startIndex &&
|
|
213
|
+
(local.kind === SymbolKind.Class ||
|
|
214
|
+
local.kind === SymbolKind.Interface ||
|
|
215
|
+
local.kind === SymbolKind.TypeAlias)) ?? null;
|
|
216
|
+
if (!owner)
|
|
217
|
+
return null;
|
|
218
|
+
return { owner, containerStart: current.startIndex, containerEnd: current.endIndex };
|
|
219
|
+
}
|
|
220
|
+
current = current.parent;
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
function phpMemberAccessProperty(node, parsed) {
|
|
225
|
+
const parent = node.parent;
|
|
226
|
+
if (!parent || !isMemberAccessNode(parsed.sup, parent))
|
|
227
|
+
return null;
|
|
228
|
+
const parts = getMemberAccessParts(parsed.sup, parent);
|
|
229
|
+
if (!parts.property || !parts.object)
|
|
230
|
+
return null;
|
|
231
|
+
const isProperty = parts.property === node ||
|
|
232
|
+
(parts.property.id !== undefined && parts.property.id === node.id) ||
|
|
233
|
+
(parts.property.startIndex === node.startIndex && parts.property.endIndex === node.endIndex);
|
|
234
|
+
if (!isProperty)
|
|
235
|
+
return null;
|
|
236
|
+
if (parts.object.startIndex === parts.property.startIndex)
|
|
237
|
+
return null;
|
|
238
|
+
return { object: parts.object, property: parts.property, parent };
|
|
239
|
+
}
|
|
240
|
+
async function phpCaseInsensitiveReceiverMemberMatch(index, fileId, node, parsed, expectedDef) {
|
|
241
|
+
const access = phpMemberAccessProperty(node, parsed);
|
|
242
|
+
if (!access)
|
|
243
|
+
return "skip";
|
|
244
|
+
const propertyText = sliceText(access.property, parsed.source);
|
|
245
|
+
const comparison = comparePhpReferenceNames(propertyText, expectedDef.localName, {
|
|
246
|
+
symbolKind: expectedDef.kind,
|
|
247
|
+
});
|
|
248
|
+
if (comparison !== "equivalent")
|
|
249
|
+
return "skip";
|
|
250
|
+
const exactSpelling = propertyText === expectedDef.localName;
|
|
251
|
+
const ownerInfo = await phpOwnerInfo(index, expectedDef);
|
|
252
|
+
if (!ownerInfo)
|
|
253
|
+
return exactSpelling ? "skip" : "unverified";
|
|
254
|
+
const owner = ownerInfo.owner;
|
|
255
|
+
const receiverName = sliceText(access.object, parsed.source);
|
|
256
|
+
if (PHP_OWN_RECEIVER_KEYWORDS.has(receiverName)) {
|
|
257
|
+
if (fileIdentityKey(fileId) === fileIdentityKey(expectedDef.file) &&
|
|
258
|
+
node.startIndex >= ownerInfo.containerStart &&
|
|
259
|
+
node.startIndex <= ownerInfo.containerEnd) {
|
|
260
|
+
return "matched";
|
|
261
|
+
}
|
|
262
|
+
return exactSpelling ? "skip" : "unverified";
|
|
263
|
+
}
|
|
264
|
+
if (isKeywordReceiver(parsed.sup.id, receiverName)) {
|
|
265
|
+
return exactSpelling ? "skip" : "unverified";
|
|
266
|
+
}
|
|
267
|
+
const constructor = receiverConstructorExpression(access.object, parsed.source, parsed.sup);
|
|
268
|
+
const typeNode = constructor ?? (access.parent.type === "scoped_call_expression" ? access.object : null);
|
|
269
|
+
if (!typeNode)
|
|
270
|
+
return exactSpelling ? "skip" : "unverified";
|
|
271
|
+
const ownerNames = await phpCanonicalDefinitionNames(index, owner);
|
|
272
|
+
const imports = index.byFile.get(fileIdentityKey(fileId))?.imports;
|
|
273
|
+
const typeNames = canonicalPhpReferenceNames(sliceText(typeNode, parsed.source), parsed.source, parsed.tree, typeNode, {
|
|
274
|
+
...(imports ? { imports } : {}),
|
|
275
|
+
role: "class",
|
|
276
|
+
});
|
|
277
|
+
const matchesOwner = typeNames.some((typeName) => ownerNames.some((ownerName) => comparePhpReferenceNames(typeName, ownerName, { symbolKind: SymbolKind.Class }) === "equivalent"));
|
|
278
|
+
if (matchesOwner)
|
|
279
|
+
return "matched";
|
|
280
|
+
return "skip";
|
|
281
|
+
}
|
|
282
|
+
function matchesPhpFallbackDefinition(node, parsed, expectedDef) {
|
|
283
|
+
if (expectedDef.isMember)
|
|
284
|
+
return false;
|
|
285
|
+
const parent = node.parent;
|
|
286
|
+
if (parent && isMemberAccessNode(parsed.sup, parent)) {
|
|
287
|
+
const property = getMemberAccessParts(parsed.sup, parent).property;
|
|
288
|
+
if (property &&
|
|
289
|
+
(property === node ||
|
|
290
|
+
(property.id !== undefined && property.id === node.id) ||
|
|
291
|
+
(property.startIndex === node.startIndex && property.endIndex === node.endIndex))) {
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const referenceKind = inferPhpQualifiedReferenceImportType(node);
|
|
296
|
+
if (expectedDef.kind === SymbolKind.Function)
|
|
297
|
+
return referenceKind === "function";
|
|
298
|
+
if (expectedDef.kind === SymbolKind.Class ||
|
|
299
|
+
expectedDef.kind === SymbolKind.Interface ||
|
|
300
|
+
expectedDef.kind === SymbolKind.TypeAlias) {
|
|
301
|
+
return referenceKind === "class";
|
|
302
|
+
}
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
async function collectNamedNodeReferences(index, fileId, symbolName, symbolKind) {
|
|
104
306
|
try {
|
|
105
307
|
const parsedEntry = index.parsed?.get(fileIdentityKey(fileId));
|
|
106
308
|
const parsed = await ensureParsedContext(fileId, parsedEntry, index.languageExtensions);
|
|
@@ -112,15 +314,39 @@ async function collectNamedNodeReferences(index, fileId, symbolName) {
|
|
|
112
314
|
"field_identifier",
|
|
113
315
|
]);
|
|
114
316
|
const canonicalSymbolName = parsed.sup.normalizeIdentifier(symbolName);
|
|
115
|
-
const
|
|
317
|
+
const isPhp = parsed.sup.id === "php";
|
|
318
|
+
const matched = [];
|
|
319
|
+
let nameEquivalenceUnavailable = false;
|
|
116
320
|
const moduleIndex = index.byFile.get(fileIdentityKey(fileId));
|
|
117
321
|
const importDeclarationKeys = importBindingDeclarationRangeKeys(moduleIndex);
|
|
322
|
+
const row = scopeNodesFor(parsed.sup.id);
|
|
118
323
|
const walk = (node) => {
|
|
119
|
-
if (identifierTypes.has(node.type)
|
|
120
|
-
parsed.sup.normalizeIdentifier(sliceText(node, parsed.source))
|
|
121
|
-
|
|
122
|
-
if (!
|
|
123
|
-
|
|
324
|
+
if (identifierTypes.has(node.type)) {
|
|
325
|
+
const text = parsed.sup.normalizeIdentifier(sliceText(node, parsed.source));
|
|
326
|
+
let isMatch;
|
|
327
|
+
if (!isPhp) {
|
|
328
|
+
isMatch = text === canonicalSymbolName;
|
|
329
|
+
}
|
|
330
|
+
else if ((node.type === "name" || node.type === "namespace_name") &&
|
|
331
|
+
(isPhpQualifiedReferenceNode(node.parent) ||
|
|
332
|
+
(node.parent && identifierTypes.has(node.parent.type) && row.childSkipNameTypes?.has(node.type)))) {
|
|
333
|
+
isMatch = false;
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
const comparisonText = node.type === "qualified_name" || node.type === "relative_name" ? phpLastIdentifierSegment(text) : text;
|
|
337
|
+
const comparison = comparePhpReferenceNames(comparisonText, phpLastIdentifierSegment(canonicalSymbolName), {
|
|
338
|
+
caseSensitiveForm: node.type === "variable_name" || node.type === "constant",
|
|
339
|
+
...(symbolKind ? { symbolKind } : {}),
|
|
340
|
+
});
|
|
341
|
+
if (comparison === "unverified")
|
|
342
|
+
nameEquivalenceUnavailable = true;
|
|
343
|
+
isMatch = comparison === "equivalent";
|
|
344
|
+
}
|
|
345
|
+
if (isMatch) {
|
|
346
|
+
const range = toRange(node);
|
|
347
|
+
if (!importDeclarationKeys.has(rangeIdentityKey(range)) && !(isPhp && isInsidePhpUseDeclaration(node))) {
|
|
348
|
+
matched.push({ range, node });
|
|
349
|
+
}
|
|
124
350
|
}
|
|
125
351
|
}
|
|
126
352
|
for (const child of node.namedChildren) {
|
|
@@ -128,31 +354,149 @@ async function collectNamedNodeReferences(index, fileId, symbolName) {
|
|
|
128
354
|
}
|
|
129
355
|
};
|
|
130
356
|
walk(parsed.tree.rootNode);
|
|
131
|
-
return {
|
|
357
|
+
return { matched, parsed, nameEquivalenceUnavailable };
|
|
132
358
|
}
|
|
133
359
|
catch {
|
|
134
360
|
return null;
|
|
135
361
|
}
|
|
136
362
|
}
|
|
137
|
-
|
|
138
|
-
|
|
363
|
+
/** True when `range` is the property of a member-access expression, not a bare call. */
|
|
364
|
+
export function isMemberAccessPropertyRange(parsed, range) {
|
|
365
|
+
const startIndex = range.start.index;
|
|
366
|
+
const node = startIndex !== undefined
|
|
367
|
+
? parsed.tree.rootNode.descendantForIndex(startIndex, range.end.index ?? startIndex)
|
|
368
|
+
: parsed.tree.rootNode.descendantForPosition({ row: range.start.line - 1, column: range.start.column - 1 }, { row: range.start.line - 1, column: range.start.column - 1 });
|
|
369
|
+
const parent = node.parent;
|
|
370
|
+
if (!parent || !isMemberAccessNode(parsed.sup, parent))
|
|
371
|
+
return false;
|
|
372
|
+
const property = getMemberAccessParts(parsed.sup, parent).property;
|
|
373
|
+
return !!property && node.startIndex >= property.startIndex && node.endIndex <= property.endIndex;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* A member call on a local, parameter, field, or `this`/`self` cannot name a free function
|
|
377
|
+
* in a language whose member syntax never calls one. A missing receiver, or a module or
|
|
378
|
+
* namespace binding (`util.helper()`, `mod.thing()`), stays unproven.
|
|
379
|
+
*/
|
|
380
|
+
function freeFunctionMemberSiteIsProvenNonReference(index, fileId, parsed, objectNode, expectedDef) {
|
|
381
|
+
if (expectedDef.isMember || expectedDef.kind !== SymbolKind.Function)
|
|
382
|
+
return false;
|
|
383
|
+
if (memberSyntaxNamesFreeFunction(parsed.sup.id))
|
|
384
|
+
return false;
|
|
385
|
+
const receiverText = sliceText(objectNode, parsed.source).trim();
|
|
386
|
+
if (isKeywordReceiver(parsed.sup.id, receiverText))
|
|
387
|
+
return true;
|
|
388
|
+
if (!isReceiverNameNode(parsed.sup, objectNode.type))
|
|
389
|
+
return false;
|
|
390
|
+
const mod = index.byFile.get(fileIdentityKey(fileId));
|
|
391
|
+
if (!mod)
|
|
392
|
+
return false;
|
|
393
|
+
const binding = findClosestScopeBinding(getCachedScope(index, fileId, mod, parsed), receiverText, objectNode, parsed.sup);
|
|
394
|
+
return binding?.kind === "local" || binding?.kind === "param";
|
|
395
|
+
}
|
|
396
|
+
async function receiverProofUnavailable(index, fileId, parsed, range, resolveDefinition, expectedDef) {
|
|
397
|
+
const position = {
|
|
398
|
+
row: range.start.line - 1,
|
|
399
|
+
column: range.start.column - 1,
|
|
400
|
+
};
|
|
401
|
+
const nameNode = parsed.tree.rootNode.descendantForPosition(position, position);
|
|
402
|
+
let current = nameNode.parent;
|
|
403
|
+
while (current) {
|
|
404
|
+
if (isMemberAccessNode(parsed.sup, current)) {
|
|
405
|
+
const { object, property } = getMemberAccessParts(parsed.sup, current);
|
|
406
|
+
if (!object || !property || property.startIndex !== range.start.index)
|
|
407
|
+
return false;
|
|
408
|
+
const receiver = classifyReceiver(parsed.sup, object, parsed.source, new Map(), current.startIndex, current, (callee) => {
|
|
409
|
+
const mod = index.byFile.get(fileIdentityKey(fileId));
|
|
410
|
+
if (!mod)
|
|
411
|
+
return true;
|
|
412
|
+
const scope = getCachedScope(index, fileId, mod, parsed);
|
|
413
|
+
return !!findClosestScopeBinding(scope, sliceText(callee, parsed.source), callee, parsed.sup);
|
|
414
|
+
});
|
|
415
|
+
// A recognized shape is not proof. Exclude it only when the type is a resolved
|
|
416
|
+
// member-declaring definition, every supertype resolves, and none declare this member.
|
|
417
|
+
let unavailable;
|
|
418
|
+
if (receiver) {
|
|
419
|
+
const omits = await provenClassifiedReceiverOmitsMember(index, fileId, parsed, current, object, sliceText(property, parsed.source));
|
|
420
|
+
unavailable = !omits;
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
const receiverRange = toRange(object);
|
|
424
|
+
const resolvedReceiver = await resolveDefinition({
|
|
425
|
+
file: fileId,
|
|
426
|
+
line: receiverRange.start.line,
|
|
427
|
+
column: receiverRange.start.column,
|
|
428
|
+
}, parsed);
|
|
429
|
+
unavailable = !(resolvedReceiver.status === "ok" &&
|
|
430
|
+
resolvedReceiver.definition &&
|
|
431
|
+
declaresMembers(resolvedReceiver.definition));
|
|
432
|
+
}
|
|
433
|
+
if (!unavailable)
|
|
434
|
+
return false;
|
|
435
|
+
return !freeFunctionMemberSiteIsProvenNonReference(index, fileId, parsed, object, expectedDef);
|
|
436
|
+
}
|
|
437
|
+
current = current.parent;
|
|
438
|
+
}
|
|
439
|
+
return false;
|
|
440
|
+
}
|
|
441
|
+
export async function collectVerifiedNamedNodeReferences(index, fileId, symbolName, expectedDef, resolveDefinition, maxVerified, includeReference, onReceiverProofUnavailable, equivalentDefinitions = []) {
|
|
442
|
+
const collected = await collectNamedNodeReferences(index, fileId, symbolName, expectedDef.kind);
|
|
139
443
|
if (!collected)
|
|
140
444
|
return [];
|
|
141
|
-
const {
|
|
445
|
+
const { matched, parsed, nameEquivalenceUnavailable } = collected;
|
|
446
|
+
if (nameEquivalenceUnavailable)
|
|
447
|
+
markPhpNameEquivalenceGap(index, expectedDef);
|
|
448
|
+
const phpCanonicalNames = parsed.sup.id === "php" ? await phpCanonicalDefinitionNames(index, expectedDef) : undefined;
|
|
449
|
+
const phpExistingFunctionNames = phpCanonicalNames && expectedDef.kind === SymbolKind.Function
|
|
450
|
+
? (await ensurePhpNamespaceSymbolIndex(index)).functionNames
|
|
451
|
+
: undefined;
|
|
142
452
|
const verified = [];
|
|
453
|
+
const matchesExpectedDefinition = (definition) => sameDef(definition, expectedDef, index.languageExtensions) ||
|
|
454
|
+
equivalentDefinitions.some((equivalent) => sameDef(definition, equivalent, index.languageExtensions));
|
|
455
|
+
const candidateFileKey = fileIdentityKey(fileId);
|
|
456
|
+
const equivalentDefinitionsInFile = equivalentDefinitions.filter((equivalent) => fileIdentityKey(equivalent.file) === candidateFileKey);
|
|
457
|
+
const isEquivalentDeclarationRange = (range) => equivalentDefinitionsInFile.some((equivalent) => {
|
|
458
|
+
const startMatches = range.start.index !== undefined && equivalent.range.start.index !== undefined
|
|
459
|
+
? range.start.index === equivalent.range.start.index
|
|
460
|
+
: range.start.line === equivalent.range.start.line && range.start.column === equivalent.range.start.column;
|
|
461
|
+
const endMatches = range.end.index !== undefined && equivalent.range.end.index !== undefined
|
|
462
|
+
? range.end.index === equivalent.range.end.index
|
|
463
|
+
: range.end.line === equivalent.range.end.line && range.end.column === equivalent.range.end.column;
|
|
464
|
+
return startMatches && endMatches;
|
|
465
|
+
});
|
|
143
466
|
const pushVerified = (reference) => {
|
|
144
467
|
if (!includeReference || includeReference(reference))
|
|
145
468
|
verified.push(reference);
|
|
146
469
|
};
|
|
147
|
-
|
|
470
|
+
let definitionVisible;
|
|
471
|
+
const definitionVisibleHere = () => {
|
|
472
|
+
if (definitionVisible === undefined) {
|
|
473
|
+
const closure = importClosure(index, fileId);
|
|
474
|
+
definitionVisible = [expectedDef, ...equivalentDefinitions].some((definition) => closure.has(fileIdentityKey(definition.file)));
|
|
475
|
+
}
|
|
476
|
+
return definitionVisible;
|
|
477
|
+
};
|
|
478
|
+
for (const { range, node } of matched) {
|
|
148
479
|
if (maxVerified !== undefined && maxVerified > 0 && verified.length >= maxVerified) {
|
|
149
480
|
break;
|
|
150
481
|
}
|
|
482
|
+
if (isEquivalentDeclarationRange(range)) {
|
|
483
|
+
pushVerified({ range });
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
if (parsed.sup.id === "c" && expectedDef.kind === SymbolKind.Function) {
|
|
487
|
+
let enclosing = node.parent;
|
|
488
|
+
while (enclosing && enclosing.type !== "field_declaration" && enclosing.type !== "translation_unit") {
|
|
489
|
+
enclosing = enclosing.parent;
|
|
490
|
+
}
|
|
491
|
+
// A C struct function-pointer field is not a declaration or use of a free function.
|
|
492
|
+
if (enclosing?.type === "field_declaration")
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
151
495
|
const exportFrom = exportFromIdentifier(index, fileId, range, parsed);
|
|
152
496
|
if (exportFrom?.entry) {
|
|
153
497
|
const reexported = resolveExport(index, exportFrom.entry.fromModule, exportFrom.entry.sourceSpecifier);
|
|
154
498
|
if (reexported?.kind === "resolved") {
|
|
155
|
-
if (
|
|
499
|
+
if (matchesExpectedDefinition(reexported.def)) {
|
|
156
500
|
pushVerified({ range, via: { reexport: true } });
|
|
157
501
|
}
|
|
158
502
|
continue;
|
|
@@ -163,14 +507,71 @@ export async function collectVerifiedNamedNodeReferences(index, fileId, symbolNa
|
|
|
163
507
|
line: range.start.line,
|
|
164
508
|
column: range.start.column,
|
|
165
509
|
}, parsed);
|
|
166
|
-
if (resolved.status
|
|
510
|
+
if (resolved.status === "ok" && resolved.definition) {
|
|
511
|
+
if (matchesExpectedDefinition(resolved.definition)) {
|
|
512
|
+
pushVerified({
|
|
513
|
+
range,
|
|
514
|
+
...(exportFrom?.isExportFrom ? { via: { reexport: true } } : {}),
|
|
515
|
+
...(resolved.provenance ? { provenance: resolved.provenance } : {}),
|
|
516
|
+
});
|
|
517
|
+
}
|
|
167
518
|
continue;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
519
|
+
}
|
|
520
|
+
let recoveredByLanguageFallback = false;
|
|
521
|
+
if (parsed.sup.id === "php" && expectedDef.isMember) {
|
|
522
|
+
const memberMatch = await phpCaseInsensitiveReceiverMemberMatch(index, fileId, node, parsed, expectedDef);
|
|
523
|
+
if (memberMatch === "matched") {
|
|
524
|
+
pushVerified({ range, ...(exportFrom?.isExportFrom ? { via: { reexport: true } } : {}) });
|
|
525
|
+
recoveredByLanguageFallback = true;
|
|
526
|
+
}
|
|
527
|
+
else if (memberMatch === "unverified") {
|
|
528
|
+
markPhpNameEquivalenceGap(index, expectedDef);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
else if (phpCanonicalNames && matchesPhpFallbackDefinition(node, parsed, expectedDef)) {
|
|
532
|
+
// PHP names are case-insensitive, but a namespace spelling alone cannot prove a member or
|
|
533
|
+
// distinguish a class reference from a function call. Restrict the fallback to syntax whose
|
|
534
|
+
// role matches the namespace-level definition.
|
|
535
|
+
const rawText = getPhpQualifiedReference(node, parsed.source) ?? sliceText(node, parsed.source);
|
|
536
|
+
const imports = index.byFile.get(fileIdentityKey(fileId))?.imports;
|
|
537
|
+
const role = inferPhpQualifiedReferenceImportType(node);
|
|
538
|
+
const candidates = canonicalPhpReferenceNames(rawText, parsed.source, parsed.tree, node, {
|
|
539
|
+
...(imports ? { imports } : {}),
|
|
540
|
+
...(role ? { role } : {}),
|
|
173
541
|
});
|
|
542
|
+
const existingNames = phpExistingFunctionNames ?? phpCanonicalNames;
|
|
543
|
+
const selectedCandidate = selectFirstExistingPhpCanonicalName(candidates, existingNames, expectedDef.kind);
|
|
544
|
+
let matchedCanonical;
|
|
545
|
+
if (selectedCandidate) {
|
|
546
|
+
matchedCanonical = phpCanonicalNames.find((canonicalName) => comparePhpReferenceNames(selectedCandidate, canonicalName, { symbolKind: expectedDef.kind }) ===
|
|
547
|
+
"equivalent");
|
|
548
|
+
}
|
|
549
|
+
if (matchedCanonical) {
|
|
550
|
+
// A qualified path proves the namespace, but a bare case-variant `name` could also be a
|
|
551
|
+
// same-named constant, so the equivalence is unproven for that form and coverage says so
|
|
552
|
+
// instead of silently returning a short list.
|
|
553
|
+
if (!isPhpQualifiedReferenceNode(node)) {
|
|
554
|
+
const lastSegment = matchedCanonical.split("\\").pop() ?? matchedCanonical;
|
|
555
|
+
const bareText = sliceText(node, parsed.source).trim();
|
|
556
|
+
if (bareText !== lastSegment && foldPhpIdentifierCase(bareText) === foldPhpIdentifierCase(lastSegment)) {
|
|
557
|
+
markPhpNameEquivalenceGap(index, expectedDef);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
pushVerified({ range, ...(exportFrom?.isExportFrom ? { via: { reexport: true } } : {}) });
|
|
561
|
+
recoveredByLanguageFallback = true;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
// A same-name node that direct resolution and every language-specific fallback both failed
|
|
565
|
+
// to place is not provably unrelated: report the file so coverage cannot silently claim
|
|
566
|
+
// `complete` while this occurrence's status stays unknown. An ambiguous result (star
|
|
567
|
+
// imports, C++ overloads, or using targets) is the same kind of gap when this definition
|
|
568
|
+
// (or an equivalent declaration) is visible from this file: one of the candidates may be
|
|
569
|
+
// it. A name with no binding at all is proven unrelated by scope and stays out.
|
|
570
|
+
if (!recoveredByLanguageFallback && onReceiverProofUnavailable) {
|
|
571
|
+
if ((isAmbiguousResolutionReason(resolved.reason) && definitionVisibleHere()) ||
|
|
572
|
+
(await receiverProofUnavailable(index, fileId, parsed, range, resolveDefinition, expectedDef))) {
|
|
573
|
+
onReceiverProofUnavailable(fileId);
|
|
574
|
+
}
|
|
174
575
|
}
|
|
175
576
|
}
|
|
176
577
|
return verified;
|
|
@@ -210,31 +611,81 @@ export function hasExpandedNamedImport(moduleIndex, targetFile, symbolName) {
|
|
|
210
611
|
fileIdentityKey(candidate.resolved) === targetKey);
|
|
211
612
|
}
|
|
212
613
|
const referenceCandidateCache = new WeakMap();
|
|
614
|
+
/** A package import may expose a child only along its exact dotted module path. */
|
|
615
|
+
export function pythonParentPackageNamespacePaths(moduleIndex, definitionFile) {
|
|
616
|
+
const file = normalizePath(definitionFile);
|
|
617
|
+
const basename = path.posix.basename(file);
|
|
618
|
+
if (!file.endsWith(".py") && !file.endsWith(".pyi"))
|
|
619
|
+
return [];
|
|
620
|
+
const moduleStem = basename === "__init__.py" || basename === "__init__.pyi"
|
|
621
|
+
? path.posix.dirname(file)
|
|
622
|
+
: file.slice(0, -path.posix.extname(file).length);
|
|
623
|
+
const paths = [];
|
|
624
|
+
for (const imp of moduleIndex.imports) {
|
|
625
|
+
if (imp.kind !== "namespace" || imp.mechanism !== "python" || typeof imp.resolved !== "string")
|
|
626
|
+
continue;
|
|
627
|
+
const target = normalizePath(imp.resolved);
|
|
628
|
+
const targetName = path.posix.basename(target);
|
|
629
|
+
const initializer = targetName === "__init__.py" || targetName === "__init__.pyi";
|
|
630
|
+
if (!initializer && (target.endsWith(".py") || target.endsWith(".pyi")))
|
|
631
|
+
continue;
|
|
632
|
+
const packageDirectory = initializer ? path.posix.dirname(target) : target;
|
|
633
|
+
const child = path.posix.relative(packageDirectory, moduleStem);
|
|
634
|
+
if (!child || child.startsWith("..") || path.posix.isAbsolute(child))
|
|
635
|
+
continue;
|
|
636
|
+
const boundName = imp.from.includes(".") && !imp.explicitAlias ? imp.from : imp.localNS;
|
|
637
|
+
paths.push({ namespace: boundName + "." + child.replaceAll("/", "."), importBinding: imp });
|
|
638
|
+
}
|
|
639
|
+
return paths;
|
|
640
|
+
}
|
|
213
641
|
function referenceCandidateCacheKey(index, def, exportedNames) {
|
|
214
642
|
const normalizeIdentifier = supportForFileWithoutHeaderSample(def.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
|
|
215
643
|
const sortedNames = exportedNames.map(normalizeIdentifier).sort();
|
|
216
644
|
return `${fileIdentityKey(def.file)}::${def.range.start.index ?? 0}::canonical::${sortedNames.join("\0")}`;
|
|
217
645
|
}
|
|
218
|
-
function importCanReferenceDefinition(index, imp, def, exportedNames) {
|
|
646
|
+
function importCanReferenceDefinition(index, imp, def, exportedNames, languageId) {
|
|
219
647
|
const targetFile = typeof imp.resolved === "string" ? imp.resolved : undefined;
|
|
220
648
|
if (!targetFile)
|
|
221
649
|
return false;
|
|
650
|
+
let cNamespace;
|
|
651
|
+
if (languageId === "c")
|
|
652
|
+
cNamespace = def.cTag ? "tag" : "ordinary";
|
|
653
|
+
const exportOptions = cNamespace ? { cNamespace } : undefined;
|
|
654
|
+
if (cNamespace && imp.kind === "named" && (imp.cNamespace ?? "ordinary") !== cNamespace)
|
|
655
|
+
return false;
|
|
222
656
|
const resolvesToDefinition = (exportedName) => {
|
|
223
|
-
const hit = resolveExport(index, targetFile, exportedName);
|
|
657
|
+
const hit = resolveExport(index, targetFile, exportedName, exportOptions);
|
|
224
658
|
if (hit?.kind === "resolved") {
|
|
225
659
|
return sameDef(hit.def, def, index.languageExtensions);
|
|
226
660
|
}
|
|
661
|
+
if (javaKotlinFunctionOverloadIncludes(index, targetFile, exportedName, def))
|
|
662
|
+
return true;
|
|
663
|
+
if (cppCanonicalStructuralExport(index, targetFile, exportedName, def, languageId)) {
|
|
664
|
+
return true;
|
|
665
|
+
}
|
|
227
666
|
return imp.kind === "namespace" && fileIdentityKey(targetFile) === fileIdentityKey(def.file);
|
|
228
667
|
};
|
|
229
668
|
if (imp.kind === "named") {
|
|
230
|
-
|
|
669
|
+
if (imp.jvmStaticWildcardName)
|
|
670
|
+
return javaStaticNamedImportIncludes(index, imp, def);
|
|
671
|
+
if (resolvesToDefinition(imp.imported))
|
|
672
|
+
return true;
|
|
673
|
+
// A python `from pkg import name` binds `name` from the package's own namespace; when the
|
|
674
|
+
// package has no such export, Python's own import system falls back to treating `name` as
|
|
675
|
+
// an implicit submodule attribute instead (the same fallback `resolveImported` applies at
|
|
676
|
+
// consumption time). Reusing that fallback here keeps candidate-file discovery in agreement
|
|
677
|
+
// with the goto/reference-collection consumers that already resolve through it.
|
|
678
|
+
if (languageId !== "python")
|
|
679
|
+
return false;
|
|
680
|
+
const result = resolveImported(index, imp, imp.imported, exportOptions);
|
|
681
|
+
return !!result && "namespace" in result && fileIdentityKey(result.namespace) === fileIdentityKey(def.file);
|
|
231
682
|
}
|
|
232
683
|
if (imp.kind === "default") {
|
|
233
684
|
return resolvesToDefinition("default");
|
|
234
685
|
}
|
|
235
686
|
if (imp.kind === "star") {
|
|
236
687
|
return exportedNames.some((exportedName) => {
|
|
237
|
-
const result = resolveImported(index, imp, exportedName);
|
|
688
|
+
const result = resolveImported(index, imp, exportedName, exportOptions);
|
|
238
689
|
return !!result && !("namespace" in result) && sameDef(result, def, index.languageExtensions);
|
|
239
690
|
});
|
|
240
691
|
}
|
|
@@ -259,10 +710,16 @@ function moduleExportProbeNames(index, moduleIndex, exportedNames, visited = new
|
|
|
259
710
|
}
|
|
260
711
|
return [...names];
|
|
261
712
|
}
|
|
262
|
-
function filesExportingDefinition(index, def, exportedNames) {
|
|
713
|
+
function filesExportingDefinition(index, def, exportedNames, languageId) {
|
|
263
714
|
const files = new Map([[fileIdentityKey(def.file), def.file]]);
|
|
715
|
+
const namespaceLinks = [];
|
|
264
716
|
for (const moduleIndex of index.byFile.values()) {
|
|
265
717
|
const fileId = moduleIndex.file;
|
|
718
|
+
for (const entry of moduleIndex.exports) {
|
|
719
|
+
if (entry.type === "namespaceReexport") {
|
|
720
|
+
namespaceLinks.push({ sourceFile: fileId, exportedAs: entry.exportedAs, targetFile: entry.fromModule });
|
|
721
|
+
}
|
|
722
|
+
}
|
|
266
723
|
if (fileIdentityKey(fileId) === fileIdentityKey(def.file) || !moduleIndex.exports.length)
|
|
267
724
|
continue;
|
|
268
725
|
for (const exportedName of moduleExportProbeNames(index, moduleIndex, exportedNames)) {
|
|
@@ -271,6 +728,10 @@ function filesExportingDefinition(index, def, exportedNames) {
|
|
|
271
728
|
files.set(fileIdentityKey(fileId), fileId);
|
|
272
729
|
break;
|
|
273
730
|
}
|
|
731
|
+
if (cppCanonicalStructuralExport(index, fileId, exportedName, def, languageId)) {
|
|
732
|
+
files.set(fileIdentityKey(fileId), fileId);
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
274
735
|
}
|
|
275
736
|
if (moduleIndex.exports.some((entry) => entry.type === "reexport" &&
|
|
276
737
|
exportedNames.includes(entry.sourceSpecifier) &&
|
|
@@ -278,15 +739,31 @@ function filesExportingDefinition(index, def, exportedNames) {
|
|
|
278
739
|
files.set(fileIdentityKey(fileId), fileId);
|
|
279
740
|
}
|
|
280
741
|
}
|
|
742
|
+
// A namespace re-export can expose an inner symbol through a member chain even
|
|
743
|
+
// though it does not export that symbol under its own name. Include consumers
|
|
744
|
+
// only when the visible namespace alias really targets the exporting module.
|
|
745
|
+
let grew = true;
|
|
746
|
+
while (grew) {
|
|
747
|
+
grew = false;
|
|
748
|
+
for (const link of namespaceLinks) {
|
|
749
|
+
const sourceKey = fileIdentityKey(link.sourceFile);
|
|
750
|
+
if (files.has(sourceKey) || !files.has(fileIdentityKey(link.targetFile)))
|
|
751
|
+
continue;
|
|
752
|
+
const visible = resolveExport(index, link.sourceFile, link.exportedAs, { allowLocalFallback: false });
|
|
753
|
+
if (visible?.kind !== "namespace" || fileIdentityKey(visible.file) !== fileIdentityKey(link.targetFile)) {
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
files.set(sourceKey, link.sourceFile);
|
|
757
|
+
grew = true;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
281
760
|
return [...files.values()];
|
|
282
761
|
}
|
|
283
|
-
function getIndexedReferenceCandidateFiles(index, def, exportedNames) {
|
|
284
|
-
if (def.file.toLowerCase().endsWith(".php"))
|
|
285
|
-
return undefined;
|
|
762
|
+
function getIndexedReferenceCandidateFiles(index, def, exportedNames, languageId) {
|
|
286
763
|
if (!index.referenceCandidates)
|
|
287
764
|
return undefined;
|
|
288
765
|
const files = new Map();
|
|
289
|
-
for (const exportingFile of filesExportingDefinition(index, def, exportedNames)) {
|
|
766
|
+
for (const exportingFile of filesExportingDefinition(index, def, exportedNames, languageId)) {
|
|
290
767
|
for (const importingFile of candidateFilesImportingTarget(index.referenceCandidates, exportingFile) ?? []) {
|
|
291
768
|
files.set(fileIdentityKey(importingFile), importingFile);
|
|
292
769
|
}
|
|
@@ -295,30 +772,49 @@ function getIndexedReferenceCandidateFiles(index, def, exportedNames) {
|
|
|
295
772
|
const fileId = moduleIndex.file;
|
|
296
773
|
if (fileIdentityKey(fileId) === fileIdentityKey(def.file) || files.has(fileIdentityKey(fileId)))
|
|
297
774
|
continue;
|
|
298
|
-
if (moduleIndex.imports.some((imp) => (imp.kind === "star" || imp.kind === "namespace") &&
|
|
299
|
-
importCanReferenceDefinition(index, imp, def, exportedNames))) {
|
|
775
|
+
if (moduleIndex.imports.some((imp) => (imp.kind === "star" || imp.kind === "namespace" || (imp.kind === "named" && imp.mechanism === "python")) &&
|
|
776
|
+
importCanReferenceDefinition(index, imp, def, exportedNames, languageId))) {
|
|
300
777
|
files.set(fileIdentityKey(fileId), fileId);
|
|
301
778
|
}
|
|
302
779
|
}
|
|
303
780
|
return [...files.values()].sort((left, right) => left.localeCompare(right));
|
|
304
781
|
}
|
|
305
|
-
export function getCachedReferenceCandidateFiles(index, def, exportedNames, hasGlobalNameReferences) {
|
|
782
|
+
export function getCachedReferenceCandidateFiles(index, def, exportedNames, hasGlobalNameReferences, languageId) {
|
|
306
783
|
if (hasGlobalNameReferences) {
|
|
307
|
-
|
|
784
|
+
// Callers only set this for a PHP definition (`buildPhpQualifiedNames` returns names for no
|
|
785
|
+
// other language), and PHP's global-namespace fallback can be referenced from any PHP file
|
|
786
|
+
// without an import, so the import-graph narrowing below cannot apply. Every other language
|
|
787
|
+
// is still a sound, source-free rejection: a PHP symbol can never be referenced from a file
|
|
788
|
+
// whose own language a different parser owns.
|
|
789
|
+
return Array.from(index.byFile.values(), (module) => module.file)
|
|
790
|
+
.filter((file) => supportForFileWithoutHeaderSample(file, index.languageExtensions)?.id === "php")
|
|
791
|
+
.sort((left, right) => left.localeCompare(right));
|
|
308
792
|
}
|
|
309
793
|
let cache = referenceCandidateCache.get(index);
|
|
310
794
|
if (!cache) {
|
|
311
795
|
cache = new Map();
|
|
312
796
|
referenceCandidateCache.set(index, cache);
|
|
313
797
|
}
|
|
314
|
-
const key = referenceCandidateCacheKey(index, def, exportedNames)
|
|
798
|
+
const key = `${languageId}:${referenceCandidateCacheKey(index, def, exportedNames)}`;
|
|
315
799
|
const cached = cache.get(key);
|
|
316
800
|
if (cached)
|
|
317
801
|
return cached;
|
|
318
802
|
const candidates = new Map();
|
|
319
|
-
|
|
803
|
+
if (def.isMember)
|
|
804
|
+
candidates.set(fileIdentityKey(def.file), def.file);
|
|
805
|
+
// Files sharing the definition's compilation unit can name it without any import edge (Go and
|
|
806
|
+
// JVM packages, C# namespaces, Swift modules), so they bypass the import filter below. C#
|
|
807
|
+
// also includes same-directory files that can reach the type only through a qualified name,
|
|
808
|
+
// so dotted and `global::` uses are candidates even when the consumer declares unrelated
|
|
809
|
+
// namespaces. Bare-name resolution still uses the related-namespace peer set.
|
|
810
|
+
for (const unitPeer of getCompilationUnitPeers(index, def.file, languageId === "csharp" ? { csharpQualifiedName: true } : undefined).files) {
|
|
811
|
+
if (fileIdentityKey(unitPeer) !== fileIdentityKey(def.file)) {
|
|
812
|
+
candidates.set(fileIdentityKey(unitPeer), unitPeer);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
const candidateFileEntries = getIndexedReferenceCandidateFiles(index, def, exportedNames, languageId) ??
|
|
320
816
|
Array.from(index.byFile.values(), (module) => module.file);
|
|
321
|
-
const exportingFileIds = filesExportingDefinition(index, def, exportedNames);
|
|
817
|
+
const exportingFileIds = filesExportingDefinition(index, def, exportedNames, languageId);
|
|
322
818
|
const exportingFiles = new Set(exportingFileIds.map((file) => fileIdentityKey(file)));
|
|
323
819
|
for (const fileId of exportingFileIds) {
|
|
324
820
|
if (fileIdentityKey(fileId) !== fileIdentityKey(def.file)) {
|
|
@@ -335,16 +831,94 @@ export function getCachedReferenceCandidateFiles(index, def, exportedNames, hasG
|
|
|
335
831
|
if (typeof imp.resolved !== "string")
|
|
336
832
|
return false;
|
|
337
833
|
return (exportingFiles.has(fileIdentityKey(imp.resolved)) ||
|
|
338
|
-
importCanReferenceDefinition(index, imp, def, exportedNames));
|
|
834
|
+
importCanReferenceDefinition(index, imp, def, exportedNames, languageId));
|
|
339
835
|
})) {
|
|
340
836
|
candidates.set(fileIdentityKey(fileId), fileId);
|
|
341
837
|
}
|
|
342
838
|
}
|
|
839
|
+
// A fully package-qualified use needs no import, even from another compilation unit.
|
|
840
|
+
// Probe both its package root and member name; Java Unicode escapes can hide either spelling.
|
|
841
|
+
if (languageId === "java" || languageId === "kotlin") {
|
|
842
|
+
const packageName = getPackageDeclarationName(index, def.file, languageId);
|
|
843
|
+
const rootName = packageName?.split(".")[0];
|
|
844
|
+
if (rootName) {
|
|
845
|
+
const exported = def.isMember ||
|
|
846
|
+
index.byFile
|
|
847
|
+
.get(fileIdentityKey(def.file))
|
|
848
|
+
?.exports.some((entry) => entry.type === "local" && sameDef(entry.target, def, index.languageExtensions));
|
|
849
|
+
if (exported) {
|
|
850
|
+
for (const moduleIndex of index.byFile.values()) {
|
|
851
|
+
const support = supportForFileWithoutHeaderSample(moduleIndex.file, index.languageExtensions);
|
|
852
|
+
if (support?.id !== "java" && support?.id !== "kotlin")
|
|
853
|
+
continue;
|
|
854
|
+
const samePackage = getPackageDeclarationName(index, moduleIndex.file, support.id) === packageName;
|
|
855
|
+
if (!isJvmPackageSymbolVisible(def, languageId, support.id, samePackage))
|
|
856
|
+
continue;
|
|
857
|
+
const fileKey = fileIdentityKey(moduleIndex.file);
|
|
858
|
+
if (candidates.has(fileKey))
|
|
859
|
+
continue;
|
|
860
|
+
const filter = index.bloomFilters?.get(fileKey);
|
|
861
|
+
const rootProbe = support.normalizeIdentifier(rootName);
|
|
862
|
+
const nameProbe = support.normalizeIdentifier(def.localName);
|
|
863
|
+
if (!filter ||
|
|
864
|
+
(filter.mightContain(rootProbe) && filter.mightContain(nameProbe)) ||
|
|
865
|
+
(support.id === "java" && filter.mightContain(JAVA_UNICODE_ESCAPE_BLOOM_TOKEN))) {
|
|
866
|
+
candidates.set(fileKey, moduleIndex.file);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
// A plain package import does not prove its child's attribute, but a same-name use
|
|
873
|
+
// through that package must be checked before coverage can claim completeness.
|
|
874
|
+
if (languageId === "python" && !def.isMember) {
|
|
875
|
+
for (const moduleIndex of index.byFile.values()) {
|
|
876
|
+
if (pythonParentPackageNamespacePaths(moduleIndex, def.file).length) {
|
|
877
|
+
candidates.set(fileIdentityKey(moduleIndex.file), moduleIndex.file);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
343
881
|
const sorted = [...candidates.values()].sort((left, right) => left.localeCompare(right));
|
|
344
882
|
cache.set(key, sorted);
|
|
345
883
|
return sorted;
|
|
346
884
|
}
|
|
347
|
-
|
|
885
|
+
/**
|
|
886
|
+
* The single precedence table for reference-coverage reasons, shared by the direct
|
|
887
|
+
* indexed-candidate builder and the bounded reference lookup cache. Existing reasons keep
|
|
888
|
+
* their established relative order so current expectations stay stable; the two strategy
|
|
889
|
+
* reasons sit after the file-level reasons they refine and before `truncated`, because a
|
|
890
|
+
* skipped collection strategy is a correctness gap while `truncated` only reflects the
|
|
891
|
+
* caller's own requested bound.
|
|
892
|
+
*/
|
|
893
|
+
export const REFERENCE_COVERAGE_REASON_ORDER = [
|
|
894
|
+
"parser_degraded",
|
|
895
|
+
"unresolved_import",
|
|
896
|
+
"strategy_unavailable",
|
|
897
|
+
"name_equivalence_unavailable",
|
|
898
|
+
"truncated",
|
|
899
|
+
];
|
|
900
|
+
export function describeReferenceStrategies(args) {
|
|
901
|
+
const applicable = [];
|
|
902
|
+
const executed = [];
|
|
903
|
+
if (args.sameFileOccurrence?.applicable) {
|
|
904
|
+
applicable.push("same_file_occurrence");
|
|
905
|
+
if (args.sameFileOccurrence.executed)
|
|
906
|
+
executed.push("same_file_occurrence");
|
|
907
|
+
}
|
|
908
|
+
if (args.implicitUnitPeers?.applicable) {
|
|
909
|
+
applicable.push("implicit_unit_peers");
|
|
910
|
+
if (args.implicitUnitPeers.executed)
|
|
911
|
+
executed.push("implicit_unit_peers");
|
|
912
|
+
}
|
|
913
|
+
if (args.languageId === "php") {
|
|
914
|
+
// Every PHP definition is addressable by its global or namespace-qualified spelling, so
|
|
915
|
+
// the qualified-name scan is required; the receiver scan is not the PHP strategy.
|
|
916
|
+
applicable.push("php_qualified_name");
|
|
917
|
+
if (args.phpQualifiedNames.length)
|
|
918
|
+
executed.push("php_qualified_name");
|
|
919
|
+
}
|
|
920
|
+
return { applicable, executed };
|
|
921
|
+
}
|
|
348
922
|
export function rangeIdentityKey(range) {
|
|
349
923
|
return `${range.start.line}:${range.start.column}:${range.start.index ?? ""}:${range.end.line}:${range.end.column}:${range.end.index ?? ""}`;
|
|
350
924
|
}
|
|
@@ -379,7 +953,7 @@ export function importBindingReferenceSites(imp) {
|
|
|
379
953
|
sites.push({ range: localRange, importBinding: "local" });
|
|
380
954
|
}
|
|
381
955
|
}
|
|
382
|
-
else if (imp.kind === "default") {
|
|
956
|
+
else if (imp.kind === "default" || imp.kind === "namespace") {
|
|
383
957
|
const { localRange } = bindingTokenRanges(imp);
|
|
384
958
|
if (localRange) {
|
|
385
959
|
sites.push({ range: localRange, importBinding: "local" });
|
|
@@ -443,7 +1017,13 @@ function structurallyExportsDefinition(index, moduleFile, exportedName, def, def
|
|
|
443
1017
|
}
|
|
444
1018
|
return false;
|
|
445
1019
|
}
|
|
446
|
-
|
|
1020
|
+
/** Recover C++ overload candidates through real exports, never the unresolved-import name shortcut. */
|
|
1021
|
+
export function cppCanonicalStructuralExport(index, targetFile, exportedName, def, languageId) {
|
|
1022
|
+
if (languageId !== "cpp")
|
|
1023
|
+
return false;
|
|
1024
|
+
return structurallyExportsDefinition(index, targetFile, exportedName, def, []);
|
|
1025
|
+
}
|
|
1026
|
+
function isUnresolvedIndexedImport(index, imp, def, exportedNames, languageId) {
|
|
447
1027
|
if (typeof imp.resolved !== "string")
|
|
448
1028
|
return false;
|
|
449
1029
|
let importedName;
|
|
@@ -455,7 +1035,7 @@ function isUnresolvedIndexedImport(index, imp, def, exportedNames) {
|
|
|
455
1035
|
return false;
|
|
456
1036
|
if (!structurallyExportsDefinition(index, imp.resolved, importedName, def, exportedNames))
|
|
457
1037
|
return false;
|
|
458
|
-
return !importCanReferenceDefinition(index, imp, def, exportedNames);
|
|
1038
|
+
return !importCanReferenceDefinition(index, imp, def, exportedNames, languageId);
|
|
459
1039
|
}
|
|
460
1040
|
function parserDegradedCandidateFiles(index, scannedFiles) {
|
|
461
1041
|
const report = index.buildReport?.backend?.parser;
|
|
@@ -484,7 +1064,7 @@ function parserDegradedCandidateFiles(index, scannedFiles) {
|
|
|
484
1064
|
return { files: affected, hasUnlistedCandidate };
|
|
485
1065
|
}
|
|
486
1066
|
export function buildIndexedCandidateCoverage(args) {
|
|
487
|
-
const { index, def, exportedNames, candidateFiles, scannedFiles, truncated } = args;
|
|
1067
|
+
const { index, def, languageId, exportedNames, candidateFiles, scannedFiles, truncated, strategies, strategyUnavailableFiles = [], } = args;
|
|
488
1068
|
const reasons = [];
|
|
489
1069
|
const affectedFiles = [];
|
|
490
1070
|
const affectedSeen = new Set();
|
|
@@ -506,7 +1086,7 @@ export function buildIndexedCandidateCoverage(args) {
|
|
|
506
1086
|
const moduleIndex = index.byFile.get(fileIdentityKey(fileId));
|
|
507
1087
|
if (!moduleIndex)
|
|
508
1088
|
continue;
|
|
509
|
-
if (moduleIndex.imports.some((imp) => isUnresolvedIndexedImport(index, imp, def, exportedNames))) {
|
|
1089
|
+
if (moduleIndex.imports.some((imp) => isUnresolvedIndexedImport(index, imp, def, exportedNames, languageId))) {
|
|
510
1090
|
unresolvedFiles.push(fileId);
|
|
511
1091
|
}
|
|
512
1092
|
}
|
|
@@ -515,6 +1095,20 @@ export function buildIndexedCandidateCoverage(args) {
|
|
|
515
1095
|
for (const file of unresolvedFiles)
|
|
516
1096
|
addAffected(file);
|
|
517
1097
|
}
|
|
1098
|
+
if (strategyUnavailableFiles.length) {
|
|
1099
|
+
reasons.push("strategy_unavailable");
|
|
1100
|
+
for (const file of strategyUnavailableFiles)
|
|
1101
|
+
addAffected(file);
|
|
1102
|
+
}
|
|
1103
|
+
if (strategies) {
|
|
1104
|
+
const executed = new Set(strategies.executed);
|
|
1105
|
+
if (strategies.applicable.some((strategy) => !executed.has(strategy))) {
|
|
1106
|
+
reasons.push("strategy_unavailable");
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
if (phpNameEquivalenceGaps.get(index)?.has(definitionIdentityKey(def))) {
|
|
1110
|
+
reasons.push("name_equivalence_unavailable");
|
|
1111
|
+
}
|
|
518
1112
|
if (truncated)
|
|
519
1113
|
reasons.push("truncated");
|
|
520
1114
|
if (!reasons.length) {
|
|
@@ -523,7 +1117,7 @@ export function buildIndexedCandidateCoverage(args) {
|
|
|
523
1117
|
return {
|
|
524
1118
|
scope: "indexed_candidates",
|
|
525
1119
|
state: "partial",
|
|
526
|
-
reasons:
|
|
1120
|
+
reasons: REFERENCE_COVERAGE_REASON_ORDER.filter((reason) => reasons.includes(reason)),
|
|
527
1121
|
...(affectedFiles.length ? { affectedFiles } : {}),
|
|
528
1122
|
};
|
|
529
1123
|
}
|