@lzehrung/codegraph 3.0.1 → 3.1.1
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 +17 -17
- package/codegraph-skill/codegraph/SKILL.md +6 -2
- package/dist/agent/artifact.d.ts.map +1 -1
- package/dist/agent/artifact.js +4 -9
- package/dist/agent/artifact.js.map +1 -1
- package/dist/agent/call-hierarchy.d.ts +4 -2
- package/dist/agent/call-hierarchy.d.ts.map +1 -1
- package/dist/agent/call-hierarchy.js +20 -29
- package/dist/agent/call-hierarchy.js.map +1 -1
- package/dist/agent/explain.d.ts.map +1 -1
- package/dist/agent/explain.js +24 -18
- package/dist/agent/explain.js.map +1 -1
- package/dist/agent/explore.d.ts.map +1 -1
- package/dist/agent/explore.js +2 -11
- package/dist/agent/explore.js.map +1 -1
- package/dist/agent/file-view.d.ts.map +1 -1
- package/dist/agent/file-view.js +4 -12
- package/dist/agent/file-view.js.map +1 -1
- package/dist/agent/normalize.d.ts +0 -3
- package/dist/agent/normalize.d.ts.map +1 -1
- package/dist/agent/normalize.js +1 -7
- package/dist/agent/normalize.js.map +1 -1
- package/dist/agent/orient.d.ts.map +1 -1
- package/dist/agent/orient.js +2 -6
- package/dist/agent/orient.js.map +1 -1
- package/dist/agent/packet.d.ts.map +1 -1
- package/dist/agent/packet.js +2 -5
- package/dist/agent/packet.js.map +1 -1
- package/dist/agent/query-index/content.d.ts.map +1 -1
- package/dist/agent/query-index/content.js +2 -6
- package/dist/agent/query-index/content.js.map +1 -1
- package/dist/agent/query-index/update.d.ts.map +1 -1
- package/dist/agent/query-index/update.js +8 -45
- package/dist/agent/query-index/update.js.map +1 -1
- package/dist/agent/query-index/worker-pool.d.ts.map +1 -1
- package/dist/agent/query-index/worker-pool.js +2 -1
- package/dist/agent/query-index/worker-pool.js.map +1 -1
- package/dist/agent/refactor-plan.d.ts +2 -2
- package/dist/agent/refactor-plan.d.ts.map +1 -1
- package/dist/agent/refactor-plan.js +11 -57
- 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 +166 -23
- package/dist/agent/rename-preview.js.map +1 -1
- package/dist/agent/search.d.ts +13 -0
- package/dist/agent/search.d.ts.map +1 -1
- package/dist/agent/search.js +17 -26
- package/dist/agent/search.js.map +1 -1
- package/dist/agent/semantic-symbols.d.ts +1 -1
- package/dist/agent/semantic-symbols.d.ts.map +1 -1
- package/dist/agent/semantic-symbols.js +2 -5
- package/dist/agent/semantic-symbols.js.map +1 -1
- package/dist/agent/semantic.d.ts +5 -0
- package/dist/agent/semantic.d.ts.map +1 -1
- package/dist/agent/semantic.js +12 -1
- package/dist/agent/semantic.js.map +1 -1
- package/dist/agent/session.d.ts +9 -0
- package/dist/agent/session.d.ts.map +1 -1
- package/dist/agent/session.js +59 -41
- package/dist/agent/session.js.map +1 -1
- package/dist/agent/type-hierarchy.d.ts +4 -2
- package/dist/agent/type-hierarchy.d.ts.map +1 -1
- package/dist/agent/type-hierarchy.js +19 -31
- package/dist/agent/type-hierarchy.js.map +1 -1
- package/dist/agent/workspace-symbols.d.ts +1 -1
- package/dist/agent/workspace-symbols.d.ts.map +1 -1
- package/dist/agent/workspace-symbols.js +7 -15
- package/dist/agent/workspace-symbols.js.map +1 -1
- package/dist/analysis-summary.d.ts +1 -4
- package/dist/analysis-summary.d.ts.map +1 -1
- package/dist/analysis-summary.js +58 -19
- package/dist/analysis-summary.js.map +1 -1
- package/dist/bin/cli.js +41060 -27641
- package/dist/bin/query-index-worker.js +268 -241
- package/dist/bootstrap/tree-sitter-languages.d.ts +2 -0
- package/dist/bootstrap/tree-sitter-languages.d.ts.map +1 -1
- package/dist/bootstrap/tree-sitter-languages.js +6 -19
- package/dist/bootstrap/tree-sitter-languages.js.map +1 -1
- package/dist/chunking/chunk-matches.d.ts.map +1 -1
- package/dist/chunking/chunk-matches.js +6 -42
- package/dist/chunking/chunk-matches.js.map +1 -1
- package/dist/chunking/chunk-split.d.ts +7 -0
- package/dist/chunking/chunk-split.d.ts.map +1 -1
- package/dist/chunking/chunk-split.js +3 -3
- package/dist/chunking/chunk-split.js.map +1 -1
- package/dist/chunking/chunk-text-file.js +2 -30
- package/dist/chunking/chunk-text-file.js.map +1 -1
- package/dist/cli/affected.d.ts.map +1 -1
- package/dist/cli/affected.js +1 -9
- package/dist/cli/affected.js.map +1 -1
- package/dist/cli/call-hierarchy.js +3 -6
- package/dist/cli/call-hierarchy.js.map +1 -1
- package/dist/cli/chunk.d.ts.map +1 -1
- package/dist/cli/chunk.js +4 -11
- package/dist/cli/chunk.js.map +1 -1
- package/dist/cli/command-table.d.ts.map +1 -1
- package/dist/cli/command-table.js +7 -0
- package/dist/cli/command-table.js.map +1 -1
- package/dist/cli/context.d.ts +1 -0
- package/dist/cli/context.d.ts.map +1 -1
- package/dist/cli/context.js +1 -1
- package/dist/cli/context.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +1 -11
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/duplicates.d.ts +5 -0
- package/dist/cli/duplicates.d.ts.map +1 -1
- package/dist/cli/duplicates.js +15 -2
- package/dist/cli/duplicates.js.map +1 -1
- package/dist/cli/graph.d.ts +4 -12
- package/dist/cli/graph.d.ts.map +1 -1
- package/dist/cli/graph.js +17 -8
- package/dist/cli/graph.js.map +1 -1
- package/dist/cli/help.d.ts +4 -4
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +17 -9
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/index.d.ts +2 -12
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/links.d.ts.map +1 -1
- package/dist/cli/links.js +4 -10
- package/dist/cli/links.js.map +1 -1
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +5 -0
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/module-locals.d.ts +8 -0
- package/dist/cli/module-locals.d.ts.map +1 -0
- package/dist/cli/module-locals.js +9 -0
- package/dist/cli/module-locals.js.map +1 -0
- package/dist/cli/navigation.d.ts +2 -0
- package/dist/cli/navigation.d.ts.map +1 -1
- package/dist/cli/navigation.js +3 -5
- package/dist/cli/navigation.js.map +1 -1
- package/dist/cli/options.d.ts.map +1 -1
- package/dist/cli/options.js +6 -1
- package/dist/cli/options.js.map +1 -1
- package/dist/cli/pretty.d.ts +1 -0
- package/dist/cli/pretty.d.ts.map +1 -1
- package/dist/cli/pretty.js +6 -8
- package/dist/cli/pretty.js.map +1 -1
- package/dist/cli/progress.d.ts.map +1 -1
- package/dist/cli/progress.js +42 -16
- package/dist/cli/progress.js.map +1 -1
- package/dist/cli/refactor-plan.js +2 -5
- package/dist/cli/refactor-plan.js.map +1 -1
- package/dist/cli/rename-preview.js +2 -5
- package/dist/cli/rename-preview.js.map +1 -1
- package/dist/cli/review.d.ts +6 -16
- package/dist/cli/review.d.ts.map +1 -1
- package/dist/cli/review.js +2 -0
- package/dist/cli/review.js.map +1 -1
- package/dist/cli/server.d.ts.map +1 -1
- package/dist/cli/server.js +9 -10
- package/dist/cli/server.js.map +1 -1
- package/dist/cli/type-hierarchy.js +8 -8
- package/dist/cli/type-hierarchy.js.map +1 -1
- package/dist/cli/viewer.js +1 -1
- package/dist/cli/viewer.js.map +1 -1
- package/dist/document-links/asciidoc.d.ts.map +1 -1
- package/dist/document-links/asciidoc.js +4 -16
- package/dist/document-links/asciidoc.js.map +1 -1
- package/dist/document-links/check.d.ts.map +1 -1
- package/dist/document-links/check.js +1 -3
- package/dist/document-links/check.js.map +1 -1
- package/dist/document-links/html.d.ts.map +1 -1
- package/dist/document-links/html.js +6 -44
- package/dist/document-links/html.js.map +1 -1
- package/dist/document-links/markdown.d.ts.map +1 -1
- package/dist/document-links/markdown.js +4 -13
- package/dist/document-links/markdown.js.map +1 -1
- package/dist/document-links/rst.d.ts.map +1 -1
- package/dist/document-links/rst.js +7 -31
- package/dist/document-links/rst.js.map +1 -1
- package/dist/document-links/sfc.d.ts.map +1 -1
- package/dist/document-links/sfc.js +2 -5
- package/dist/document-links/sfc.js.map +1 -1
- package/dist/document-links/shared.d.ts +2 -0
- package/dist/document-links/shared.d.ts.map +1 -1
- package/dist/document-links/shared.js +13 -0
- package/dist/document-links/shared.js.map +1 -1
- package/dist/drift/artifact.d.ts.map +1 -1
- package/dist/drift/artifact.js +4 -27
- package/dist/drift/artifact.js.map +1 -1
- package/dist/drift/git.d.ts.map +1 -1
- package/dist/drift/git.js +10 -2
- package/dist/drift/git.js.map +1 -1
- package/dist/drift/graph-edges.d.ts +4 -0
- package/dist/drift/graph-edges.d.ts.map +1 -0
- package/dist/drift/graph-edges.js +15 -0
- package/dist/drift/graph-edges.js.map +1 -0
- package/dist/drift/snapshot.d.ts.map +1 -1
- package/dist/drift/snapshot.js +2 -17
- package/dist/drift/snapshot.js.map +1 -1
- package/dist/duplicates/candidates.d.ts +61 -0
- package/dist/duplicates/candidates.d.ts.map +1 -0
- package/dist/duplicates/candidates.js +873 -0
- package/dist/duplicates/candidates.js.map +1 -0
- package/dist/duplicates/progress.d.ts +17 -0
- package/dist/duplicates/progress.d.ts.map +1 -0
- package/dist/duplicates/progress.js +57 -0
- package/dist/duplicates/progress.js.map +1 -0
- package/dist/duplicates/scoring.d.ts +9 -40
- package/dist/duplicates/scoring.d.ts.map +1 -1
- package/dist/duplicates/scoring.js +34 -414
- package/dist/duplicates/scoring.js.map +1 -1
- package/dist/duplicates/types.d.ts +30 -1
- package/dist/duplicates/types.d.ts.map +1 -1
- package/dist/duplicates/unit-cache.d.ts +11 -1
- package/dist/duplicates/unit-cache.d.ts.map +1 -1
- package/dist/duplicates/unit-cache.js +20 -2
- package/dist/duplicates/unit-cache.js.map +1 -1
- package/dist/duplicates/units.d.ts +4 -2
- package/dist/duplicates/units.d.ts.map +1 -1
- package/dist/duplicates/units.js +47 -25
- package/dist/duplicates/units.js.map +1 -1
- package/dist/duplicates.d.ts +1 -0
- package/dist/duplicates.d.ts.map +1 -1
- package/dist/duplicates.js +116 -62
- package/dist/duplicates.js.map +1 -1
- package/dist/graph-builder.d.ts +1 -1
- package/dist/graph-builder.d.ts.map +1 -1
- package/dist/graph-builder.js +3 -2
- package/dist/graph-builder.js.map +1 -1
- package/dist/graph-edge-collector.d.ts +3 -1
- package/dist/graph-edge-collector.d.ts.map +1 -1
- package/dist/graph-edge-collector.js +38 -6
- package/dist/graph-edge-collector.js.map +1 -1
- package/dist/graphs/angularjs.d.ts.map +1 -1
- package/dist/graphs/angularjs.js +2 -9
- package/dist/graphs/angularjs.js.map +1 -1
- package/dist/graphs/edge-resolution.d.ts +4 -0
- package/dist/graphs/edge-resolution.d.ts.map +1 -1
- package/dist/graphs/edge-resolution.js +2 -0
- package/dist/graphs/edge-resolution.js.map +1 -1
- package/dist/graphs/external/manifests.d.ts.map +1 -1
- package/dist/graphs/external/manifests.js +1 -6
- package/dist/graphs/external/manifests.js.map +1 -1
- package/dist/graphs/specifiers.d.ts.map +1 -1
- package/dist/graphs/specifiers.js +47 -26
- package/dist/graphs/specifiers.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts +2 -0
- package/dist/graphs/symbol-graph-detailed/edge-passes.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/edge-passes.js +9 -3
- package/dist/graphs/symbol-graph-detailed/edge-passes.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts +3 -3
- package/dist/graphs/symbol-graph-detailed/receiver-calls.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed/receiver-calls.js +2 -26
- 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 +38 -1
- package/dist/graphs/symbol-graph-detailed.js.map +1 -1
- package/dist/impact/analyzer.d.ts.map +1 -1
- package/dist/impact/analyzer.js +23 -17
- package/dist/impact/analyzer.js.map +1 -1
- package/dist/impact/budgets.d.ts.map +1 -1
- package/dist/impact/budgets.js +3 -9
- package/dist/impact/budgets.js.map +1 -1
- package/dist/impact/call-compatibility.d.ts.map +1 -1
- package/dist/impact/call-compatibility.js +3 -12
- package/dist/impact/call-compatibility.js.map +1 -1
- package/dist/impact/context.d.ts +6 -0
- package/dist/impact/context.d.ts.map +1 -1
- package/dist/impact/context.js +2 -2
- package/dist/impact/context.js.map +1 -1
- package/dist/impact/direct.d.ts.map +1 -1
- package/dist/impact/direct.js +2 -6
- package/dist/impact/direct.js.map +1 -1
- package/dist/impact/map.d.ts +3 -1
- package/dist/impact/map.d.ts.map +1 -1
- package/dist/impact/map.js +12 -5
- package/dist/impact/map.js.map +1 -1
- package/dist/impact/providers/base.js +1 -1
- package/dist/impact/providers/base.js.map +1 -1
- package/dist/impact/reference-cache.d.ts.map +1 -1
- package/dist/impact/reference-cache.js +1 -24
- package/dist/impact/reference-cache.js.map +1 -1
- package/dist/impact/report-shared.d.ts +2 -1
- package/dist/impact/report-shared.d.ts.map +1 -1
- package/dist/impact/report-shared.js +10 -0
- package/dist/impact/report-shared.js.map +1 -1
- package/dist/impact/report-suggestions.d.ts.map +1 -1
- package/dist/impact/report-suggestions.js +2 -8
- package/dist/impact/report-suggestions.js.map +1 -1
- package/dist/impact/report.d.ts.map +1 -1
- package/dist/impact/report.js +2 -8
- package/dist/impact/report.js.map +1 -1
- package/dist/impact/streaming.d.ts.map +1 -1
- package/dist/impact/streaming.js +3 -8
- package/dist/impact/streaming.js.map +1 -1
- package/dist/indexer/build-cache/manifest.d.ts.map +1 -1
- package/dist/indexer/build-cache/manifest.js +10 -108
- package/dist/indexer/build-cache/manifest.js.map +1 -1
- package/dist/indexer/build-cache/module-cache.d.ts +6 -1
- package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
- package/dist/indexer/build-cache/module-cache.js +25 -2
- package/dist/indexer/build-cache/module-cache.js.map +1 -1
- package/dist/indexer/build-cache/options.d.ts +38 -1
- package/dist/indexer/build-cache/options.d.ts.map +1 -1
- package/dist/indexer/build-cache/options.js +38 -1
- package/dist/indexer/build-cache/options.js.map +1 -1
- package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
- package/dist/indexer/build-cache/project-snapshot.js +48 -99
- package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
- package/dist/indexer/build-cache/reports.d.ts +1 -0
- package/dist/indexer/build-cache/reports.d.ts.map +1 -1
- package/dist/indexer/build-cache/reports.js +10 -0
- package/dist/indexer/build-cache/reports.js.map +1 -1
- package/dist/indexer/build-index.d.ts +2 -0
- package/dist/indexer/build-index.d.ts.map +1 -1
- package/dist/indexer/build-index.js +187 -57
- package/dist/indexer/build-index.js.map +1 -1
- package/dist/indexer/build-workers.d.ts +7 -1
- package/dist/indexer/build-workers.d.ts.map +1 -1
- package/dist/indexer/build-workers.js +12 -0
- package/dist/indexer/build-workers.js.map +1 -1
- package/dist/indexer/call-hierarchy.d.ts.map +1 -1
- package/dist/indexer/call-hierarchy.js +5 -17
- package/dist/indexer/call-hierarchy.js.map +1 -1
- package/dist/indexer/compilation-units.d.ts +32 -20
- package/dist/indexer/compilation-units.d.ts.map +1 -1
- package/dist/indexer/compilation-units.js +139 -145
- package/dist/indexer/compilation-units.js.map +1 -1
- package/dist/indexer/cpp-callables.d.ts.map +1 -1
- package/dist/indexer/cpp-callables.js +2 -7
- package/dist/indexer/cpp-callables.js.map +1 -1
- package/dist/indexer/import-types.d.ts +5 -0
- package/dist/indexer/import-types.d.ts.map +1 -1
- package/dist/indexer/import-types.js.map +1 -1
- package/dist/indexer/imports/binding-ranges.d.ts +5 -12
- package/dist/indexer/imports/binding-ranges.d.ts.map +1 -1
- package/dist/indexer/imports/binding-ranges.js +13 -19
- package/dist/indexer/imports/binding-ranges.js.map +1 -1
- package/dist/indexer/imports/context.d.ts +6 -0
- package/dist/indexer/imports/context.d.ts.map +1 -1
- package/dist/indexer/imports/import-binding-tables.d.ts +28 -13
- package/dist/indexer/imports/import-binding-tables.d.ts.map +1 -1
- package/dist/indexer/imports/import-binding-tables.js +179 -178
- package/dist/indexer/imports/import-binding-tables.js.map +1 -1
- package/dist/indexer/imports/js-text-imports.d.ts +0 -1
- package/dist/indexer/imports/js-text-imports.d.ts.map +1 -1
- package/dist/indexer/imports/js-text-imports.js +0 -176
- package/dist/indexer/imports/js-text-imports.js.map +1 -1
- package/dist/indexer/imports/language-specific.d.ts.map +1 -1
- package/dist/indexer/imports/language-specific.js +4 -8
- package/dist/indexer/imports/language-specific.js.map +1 -1
- package/dist/indexer/imports/python.d.ts +0 -1
- package/dist/indexer/imports/python.d.ts.map +1 -1
- package/dist/indexer/imports/python.js +1 -29
- package/dist/indexer/imports/python.js.map +1 -1
- package/dist/indexer/imports/text-import-extractors.d.ts +2 -9
- package/dist/indexer/imports/text-import-extractors.d.ts.map +1 -1
- package/dist/indexer/imports/text-import-extractors.js +0 -284
- package/dist/indexer/imports/text-import-extractors.js.map +1 -1
- package/dist/indexer/imports.d.ts +15 -0
- package/dist/indexer/imports.d.ts.map +1 -1
- package/dist/indexer/imports.js +82 -44
- package/dist/indexer/imports.js.map +1 -1
- package/dist/indexer/incremental-plan.d.ts +0 -1
- package/dist/indexer/incremental-plan.d.ts.map +1 -1
- package/dist/indexer/incremental-plan.js +6 -12
- package/dist/indexer/incremental-plan.js.map +1 -1
- package/dist/indexer/name-lookup-policies/implicit-self.d.ts.map +1 -1
- package/dist/indexer/name-lookup-policies/implicit-self.js +25 -4
- package/dist/indexer/name-lookup-policies/implicit-self.js.map +1 -1
- package/dist/indexer/name-resolution-types.d.ts +5 -0
- package/dist/indexer/name-resolution-types.d.ts.map +1 -1
- package/dist/indexer/name-resolution.d.ts.map +1 -1
- package/dist/indexer/name-resolution.js +2 -0
- package/dist/indexer/name-resolution.js.map +1 -1
- package/dist/indexer/navigation-cpp.d.ts.map +1 -1
- package/dist/indexer/navigation-cpp.js +3 -5
- package/dist/indexer/navigation-cpp.js.map +1 -1
- package/dist/indexer/navigation-goto.d.ts +49 -3
- package/dist/indexer/navigation-goto.d.ts.map +1 -1
- package/dist/indexer/navigation-goto.js +500 -106
- package/dist/indexer/navigation-goto.js.map +1 -1
- package/dist/indexer/navigation-local.d.ts +7 -0
- package/dist/indexer/navigation-local.d.ts.map +1 -1
- package/dist/indexer/navigation-local.js +22 -2
- package/dist/indexer/navigation-local.js.map +1 -1
- package/dist/indexer/navigation-php.d.ts +0 -1
- package/dist/indexer/navigation-php.d.ts.map +1 -1
- package/dist/indexer/navigation-php.js +1 -7
- package/dist/indexer/navigation-php.js.map +1 -1
- package/dist/indexer/navigation-references.d.ts +1 -0
- package/dist/indexer/navigation-references.d.ts.map +1 -1
- package/dist/indexer/navigation-references.js +134 -23
- package/dist/indexer/navigation-references.js.map +1 -1
- package/dist/indexer/navigation-resolve.d.ts +22 -0
- package/dist/indexer/navigation-resolve.d.ts.map +1 -1
- package/dist/indexer/navigation-resolve.js +73 -8
- package/dist/indexer/navigation-resolve.js.map +1 -1
- package/dist/indexer/navigation.d.ts +4 -1
- package/dist/indexer/navigation.d.ts.map +1 -1
- package/dist/indexer/navigation.js +398 -95
- package/dist/indexer/navigation.js.map +1 -1
- package/dist/indexer/python-property-decorator.d.ts +11 -0
- package/dist/indexer/python-property-decorator.d.ts.map +1 -0
- package/dist/indexer/python-property-decorator.js +30 -0
- package/dist/indexer/python-property-decorator.js.map +1 -0
- package/dist/indexer/shared-owner-identity.d.ts +3 -1
- package/dist/indexer/shared-owner-identity.d.ts.map +1 -1
- package/dist/indexer/shared-owner-identity.js +40 -12
- package/dist/indexer/shared-owner-identity.js.map +1 -1
- package/dist/indexer/shared.d.ts +10 -0
- package/dist/indexer/shared.d.ts.map +1 -1
- package/dist/indexer/shared.js +8 -0
- package/dist/indexer/shared.js.map +1 -1
- package/dist/indexer/star-import-precedence.d.ts +5 -1
- package/dist/indexer/star-import-precedence.d.ts.map +1 -1
- package/dist/indexer/star-import-precedence.js +12 -19
- package/dist/indexer/star-import-precedence.js.map +1 -1
- package/dist/indexer/type-hierarchy.d.ts.map +1 -1
- package/dist/indexer/type-hierarchy.js +8 -9
- package/dist/indexer/type-hierarchy.js.map +1 -1
- package/dist/indexer/types.d.ts +49 -1
- package/dist/indexer/types.d.ts.map +1 -1
- package/dist/indexer/types.js.map +1 -1
- package/dist/indexer/workspace-symbols.d.ts.map +1 -1
- package/dist/indexer/workspace-symbols.js +3 -13
- package/dist/indexer/workspace-symbols.js.map +1 -1
- package/dist/installer/locks.d.ts +1 -0
- package/dist/installer/locks.d.ts.map +1 -1
- package/dist/installer/locks.js +4 -8
- package/dist/installer/locks.js.map +1 -1
- package/dist/installer/registry.d.ts.map +1 -1
- package/dist/installer/registry.js +9 -15
- package/dist/installer/registry.js.map +1 -1
- package/dist/languages/callable-arity.d.ts.map +1 -1
- package/dist/languages/callable-arity.js +1 -38
- package/dist/languages/callable-arity.js.map +1 -1
- package/dist/languages/definitions/csharp.d.ts.map +1 -1
- package/dist/languages/definitions/csharp.js +5 -13
- package/dist/languages/definitions/csharp.js.map +1 -1
- package/dist/languages/definitions/java.d.ts.map +1 -1
- package/dist/languages/definitions/java.js +4 -13
- package/dist/languages/definitions/java.js.map +1 -1
- package/dist/languages/definitions/kotlin.d.ts.map +1 -1
- package/dist/languages/definitions/kotlin.js +4 -8
- package/dist/languages/definitions/kotlin.js.map +1 -1
- package/dist/languages/definitions/python.d.ts.map +1 -1
- package/dist/languages/definitions/python.js +5 -3
- package/dist/languages/definitions/python.js.map +1 -1
- package/dist/languages/import-statement-parsers.d.ts +0 -30
- package/dist/languages/import-statement-parsers.d.ts.map +1 -1
- package/dist/languages/import-statement-parsers.js +1 -81
- package/dist/languages/import-statement-parsers.js.map +1 -1
- package/dist/languages/sfc.d.ts.map +1 -1
- package/dist/languages/sfc.js +8 -43
- package/dist/languages/sfc.js.map +1 -1
- package/dist/lifecycle/manifest.d.ts.map +1 -1
- package/dist/lifecycle/manifest.js +11 -29
- package/dist/lifecycle/manifest.js.map +1 -1
- package/dist/mcp/cancellation.d.ts +6 -0
- package/dist/mcp/cancellation.d.ts.map +1 -0
- package/dist/mcp/cancellation.js +11 -0
- package/dist/mcp/cancellation.js.map +1 -0
- package/dist/mcp/handlers.d.ts +54 -3
- package/dist/mcp/handlers.d.ts.map +1 -1
- package/dist/mcp/handlers.js +186 -42
- package/dist/mcp/handlers.js.map +1 -1
- package/dist/mcp/http-transport.d.ts.map +1 -1
- package/dist/mcp/http-transport.js +9 -2
- package/dist/mcp/http-transport.js.map +1 -1
- package/dist/mcp/index-readiness.d.ts +114 -0
- package/dist/mcp/index-readiness.d.ts.map +1 -0
- package/dist/mcp/index-readiness.js +264 -0
- package/dist/mcp/index-readiness.js.map +1 -0
- package/dist/mcp/project-watcher.d.ts +125 -0
- package/dist/mcp/project-watcher.d.ts.map +1 -0
- package/dist/mcp/project-watcher.js +643 -0
- package/dist/mcp/project-watcher.js.map +1 -0
- package/dist/mcp/protocol.d.ts.map +1 -1
- package/dist/mcp/protocol.js +23 -10
- package/dist/mcp/protocol.js.map +1 -1
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +11 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/stale-install.d.ts +13 -0
- package/dist/mcp/stale-install.d.ts.map +1 -0
- package/dist/mcp/stale-install.js +30 -0
- package/dist/mcp/stale-install.js.map +1 -0
- package/dist/native/byte-index.d.ts +1 -0
- package/dist/native/byte-index.d.ts.map +1 -1
- package/dist/native/byte-index.js +1 -1
- package/dist/native/byte-index.js.map +1 -1
- package/dist/native/contracts.d.ts +1 -0
- package/dist/native/contracts.d.ts.map +1 -1
- package/dist/native/native-backend-report.d.ts +2 -1
- package/dist/native/native-backend-report.d.ts.map +1 -1
- package/dist/native/native-backend-report.js +23 -0
- package/dist/native/native-backend-report.js.map +1 -1
- package/dist/native/tree-shape.d.ts +5 -7
- package/dist/native/tree-shape.d.ts.map +1 -1
- package/dist/native/tree-shape.js +11 -10
- package/dist/native/tree-shape.js.map +1 -1
- package/dist/presentation/bounds.d.ts +2 -0
- package/dist/presentation/bounds.d.ts.map +1 -1
- package/dist/presentation/bounds.js +8 -0
- package/dist/presentation/bounds.js.map +1 -1
- package/dist/review/candidates.d.ts.map +1 -1
- package/dist/review/candidates.js +4 -25
- package/dist/review/candidates.js.map +1 -1
- package/dist/review/deleted.js +1 -1
- package/dist/review/deleted.js.map +1 -1
- package/dist/review/report.d.ts.map +1 -1
- package/dist/review/report.js +4 -2
- package/dist/review/report.js.map +1 -1
- package/dist/review/summaries.d.ts.map +1 -1
- package/dist/review/summaries.js +14 -35
- package/dist/review/summaries.js.map +1 -1
- package/dist/review.d.ts +6 -0
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +5 -6
- package/dist/review.js.map +1 -1
- package/dist/scss/navigation.d.ts +13 -0
- package/dist/scss/navigation.d.ts.map +1 -0
- package/dist/scss/navigation.js +150 -0
- package/dist/scss/navigation.js.map +1 -0
- package/dist/scss/resolution.d.ts +190 -0
- package/dist/scss/resolution.d.ts.map +1 -0
- package/dist/scss/resolution.js +1802 -0
- package/dist/scss/resolution.js.map +1 -0
- package/dist/scss/syntax.d.ts +181 -0
- package/dist/scss/syntax.d.ts.map +1 -0
- package/dist/scss/syntax.js +1436 -0
- package/dist/scss/syntax.js.map +1 -0
- package/dist/sql/classify-sql-file.d.ts +7 -0
- package/dist/sql/classify-sql-file.d.ts.map +1 -1
- package/dist/sql/classify-sql-file.js +9 -0
- package/dist/sql/classify-sql-file.js.map +1 -1
- package/dist/sql/extract-facts.d.ts.map +1 -1
- package/dist/sql/extract-facts.js +517 -77
- package/dist/sql/extract-facts.js.map +1 -1
- package/dist/sql/lex.d.ts +100 -1
- package/dist/sql/lex.d.ts.map +1 -1
- package/dist/sql/lex.js +473 -11
- package/dist/sql/lex.js.map +1 -1
- package/dist/sql/lookup.d.ts +17 -0
- package/dist/sql/lookup.d.ts.map +1 -1
- package/dist/sql/lookup.js +21 -0
- package/dist/sql/lookup.js.map +1 -1
- package/dist/sql/navigation.d.ts +28 -1
- package/dist/sql/navigation.d.ts.map +1 -1
- package/dist/sql/navigation.js +474 -84
- package/dist/sql/navigation.js.map +1 -1
- package/dist/sql/object-mentions.d.ts +24 -0
- package/dist/sql/object-mentions.d.ts.map +1 -0
- package/dist/sql/object-mentions.js +233 -0
- package/dist/sql/object-mentions.js.map +1 -0
- package/dist/sql/review.d.ts +3 -0
- package/dist/sql/review.d.ts.map +1 -1
- package/dist/sql/review.js +15 -14
- package/dist/sql/review.js.map +1 -1
- package/dist/sql/routine-mentions.d.ts +61 -0
- package/dist/sql/routine-mentions.d.ts.map +1 -0
- package/dist/sql/routine-mentions.js +868 -0
- package/dist/sql/routine-mentions.js.map +1 -0
- package/dist/sql/source-graph.d.ts +18 -3
- package/dist/sql/source-graph.d.ts.map +1 -1
- package/dist/sql/source-graph.js +109 -32
- package/dist/sql/source-graph.js.map +1 -1
- package/dist/sqlite/raw-query-worker-pool.d.ts.map +1 -1
- package/dist/sqlite/raw-query-worker-pool.js +2 -0
- package/dist/sqlite/raw-query-worker-pool.js.map +1 -1
- package/dist/sqlite/types.d.ts +6 -5
- package/dist/sqlite/types.d.ts.map +1 -1
- package/dist/sqlite/write.d.ts.map +1 -1
- package/dist/sqlite/write.js.map +1 -1
- package/dist/sqlite-driver.d.ts +0 -1
- package/dist/sqlite-driver.d.ts.map +1 -1
- package/dist/sqlite-driver.js +0 -11
- package/dist/sqlite-driver.js.map +1 -1
- package/dist/terraform/navigation.d.ts.map +1 -1
- package/dist/terraform/navigation.js +1 -3
- package/dist/terraform/navigation.js.map +1 -1
- package/dist/terraform/syntax.d.ts.map +1 -1
- package/dist/terraform/syntax.js +1 -4
- package/dist/terraform/syntax.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/util/ast.d.ts +5 -0
- package/dist/util/ast.d.ts.map +1 -1
- package/dist/util/ast.js +10 -0
- package/dist/util/ast.js.map +1 -1
- package/dist/util/atomic-file.d.ts +22 -0
- package/dist/util/atomic-file.d.ts.map +1 -0
- package/dist/util/atomic-file.js +106 -0
- package/dist/util/atomic-file.js.map +1 -0
- package/dist/util/collections.d.ts +5 -0
- package/dist/util/collections.d.ts.map +1 -1
- package/dist/util/collections.js +26 -0
- package/dist/util/collections.js.map +1 -1
- package/dist/util/concurrency.d.ts +8 -0
- package/dist/util/concurrency.d.ts.map +1 -1
- package/dist/util/concurrency.js +16 -0
- package/dist/util/concurrency.js.map +1 -1
- package/dist/util/confined-file.d.ts.map +1 -1
- package/dist/util/confined-file.js +1 -3
- package/dist/util/confined-file.js.map +1 -1
- package/dist/util/csharp-tree.d.ts +65 -0
- package/dist/util/csharp-tree.d.ts.map +1 -0
- package/dist/util/csharp-tree.js +266 -0
- package/dist/util/csharp-tree.js.map +1 -0
- package/dist/util/errors.d.ts +1 -0
- package/dist/util/errors.d.ts.map +1 -1
- package/dist/util/errors.js +3 -0
- package/dist/util/errors.js.map +1 -1
- package/dist/util/graph-edges.d.ts +2 -0
- package/dist/util/graph-edges.d.ts.map +1 -1
- package/dist/util/graph-edges.js +11 -0
- package/dist/util/graph-edges.js.map +1 -1
- package/dist/util/guards.d.ts +1 -0
- package/dist/util/guards.d.ts.map +1 -1
- package/dist/util/guards.js +6 -0
- package/dist/util/guards.js.map +1 -1
- package/dist/util/identifiers.d.ts +0 -24
- package/dist/util/identifiers.d.ts.map +1 -1
- package/dist/util/identifiers.js +0 -24
- package/dist/util/identifiers.js.map +1 -1
- package/dist/util/jvm-tree.d.ts +58 -0
- package/dist/util/jvm-tree.d.ts.map +1 -0
- package/dist/util/jvm-tree.js +153 -0
- package/dist/util/jvm-tree.js.map +1 -0
- package/dist/util/package-exports.d.ts +0 -22
- package/dist/util/package-exports.d.ts.map +1 -1
- package/dist/util/package-exports.js +25 -5
- package/dist/util/package-exports.js.map +1 -1
- package/dist/util/paths.d.ts +1 -0
- package/dist/util/paths.d.ts.map +1 -1
- package/dist/util/paths.js +10 -4
- package/dist/util/paths.js.map +1 -1
- package/dist/util/resolution/csharp.d.ts +20 -8
- package/dist/util/resolution/csharp.d.ts.map +1 -1
- package/dist/util/resolution/csharp.js +126 -127
- package/dist/util/resolution/csharp.js.map +1 -1
- package/dist/util/resolution/files.d.ts +6 -0
- package/dist/util/resolution/files.d.ts.map +1 -1
- package/dist/util/resolution/files.js +74 -21
- package/dist/util/resolution/files.js.map +1 -1
- package/dist/util/resolution/jvm.d.ts +21 -1
- package/dist/util/resolution/jvm.d.ts.map +1 -1
- package/dist/util/resolution/jvm.js +168 -100
- package/dist/util/resolution/jvm.js.map +1 -1
- package/dist/util/resolution/project-symbols.d.ts +1 -1
- package/dist/util/resolution/project-symbols.d.ts.map +1 -1
- package/dist/util/resolution/project-symbols.js.map +1 -1
- package/dist/util/resolution/specifier-targets.d.ts +4 -0
- package/dist/util/resolution/specifier-targets.d.ts.map +1 -1
- package/dist/util/resolution/specifier-targets.js +11 -3
- package/dist/util/resolution/specifier-targets.js.map +1 -1
- package/dist/util/resolution.d.ts.map +1 -1
- package/dist/util/resolution.js +21 -7
- package/dist/util/resolution.js.map +1 -1
- package/dist/util/syntax-tree.d.ts +16 -0
- package/dist/util/syntax-tree.d.ts.map +1 -0
- package/dist/util/syntax-tree.js +34 -0
- package/dist/util/syntax-tree.js.map +1 -0
- package/dist/util/text-scanning.d.ts +6 -0
- package/dist/util/text-scanning.d.ts.map +1 -0
- package/dist/util/text-scanning.js +35 -0
- package/dist/util/text-scanning.js.map +1 -0
- package/dist/util/trivia-tables.d.ts +13 -8
- package/dist/util/trivia-tables.d.ts.map +1 -1
- package/dist/util/trivia-tables.js +13 -72
- package/dist/util/trivia-tables.js.map +1 -1
- package/dist/util/trivia.d.ts +10 -3
- package/dist/util/trivia.d.ts.map +1 -1
- package/dist/util/trivia.js +209 -79
- package/dist/util/trivia.js.map +1 -1
- package/dist/util/windows-process-drain.d.ts.map +1 -1
- package/dist/util/windows-process-drain.js.map +1 -1
- package/dist/util/worker-threads.d.ts +16 -0
- package/dist/util/worker-threads.d.ts.map +1 -1
- package/dist/util/worker-threads.js +118 -0
- package/dist/util/worker-threads.js.map +1 -1
- package/dist/worker/native-worker-pool.d.ts.map +1 -1
- package/dist/worker/native-worker-pool.js +2 -1
- package/dist/worker/native-worker-pool.js.map +1 -1
- package/docs/mcp.md +82 -8
- package/package.json +7 -7
package/dist/sql/navigation.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import fsp from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
2
|
import { createNavigationProvenance, okGoToResult } from "../indexer/navigation-provenance.js";
|
|
4
3
|
import { buildIndexedCandidateCoverage } from "../indexer/navigation-references.js";
|
|
4
|
+
import { SymbolKind } from "../indexer/types.js";
|
|
5
5
|
import { fileIdentityKey, normalizePath } from "../util/paths.js";
|
|
6
|
+
import { isSqlFilePath } from "./classify-sql-file.js";
|
|
6
7
|
import { extractSqlFactsFromSource } from "./extract-facts.js";
|
|
7
|
-
import {
|
|
8
|
-
import { maskSqlStringsAndComments, normalizeSqlObjectName, SQL_IDENTIFIER_PART_PATTERN, splitTopLevelCommaSeparated, sqlObjectBaseNameLookupKey, sqlObjectLookupKey,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
8
|
+
import { addSqlDefinition, createSqlDefinitionIndex, sqlRoutineNameCandidates, } from "./lookup.js";
|
|
9
|
+
import { maskSqlQuotedIdentifiers, maskSqlStringsAndComments, normalizeSqlObjectName, SQL_IDENTIFIER_PART_PATTERN, splitTopLevelCommaSeparated, sqlObjectBaseNameLookupKey, sqlObjectLookupKey, sqlQueryScopes, sqlSourceClauses, } from "./lex.js";
|
|
10
|
+
import { sqlDefinedNameSpan, sqlObjectMentionCovers, sqlRelationReadSpans, sqlSpanCovers, sqlSyntacticObjectSpans, } from "./object-mentions.js";
|
|
11
|
+
import { findSqlRoutineMentions, findSqlRoutineSources, sqlRoutineDefinitionNamespace, sqlStatementDropsRoutine, } from "./routine-mentions.js";
|
|
12
12
|
function rangeForToken(line, column, length) {
|
|
13
13
|
return {
|
|
14
14
|
start: { line, column },
|
|
@@ -18,7 +18,7 @@ function rangeForToken(line, column, length) {
|
|
|
18
18
|
function sqlFiles(index) {
|
|
19
19
|
return Array.from(index.byFile.values())
|
|
20
20
|
.map((module) => normalizePath(module.file))
|
|
21
|
-
.filter(
|
|
21
|
+
.filter((file) => isSqlFilePath(file, index.languageExtensions))
|
|
22
22
|
.sort((left, right) => left.localeCompare(right));
|
|
23
23
|
}
|
|
24
24
|
function getSqlNavigationCache(index) {
|
|
@@ -28,23 +28,23 @@ function getSqlNavigationCache(index) {
|
|
|
28
28
|
};
|
|
29
29
|
return index.sqlNavigation;
|
|
30
30
|
}
|
|
31
|
+
/** Table, view, and index definitions. Routines resolve through `getSqlRoutineLookups`. */
|
|
31
32
|
function getSqlDefinitionLookup(index) {
|
|
32
33
|
const cache = getSqlNavigationCache(index);
|
|
33
34
|
if (cache.definitionLookup)
|
|
34
35
|
return cache.definitionLookup;
|
|
35
|
-
const
|
|
36
|
-
const basename = new Map();
|
|
36
|
+
const lookup = createSqlDefinitionIndex();
|
|
37
37
|
for (const file of sqlFiles(index)) {
|
|
38
38
|
const module = index.byFile.get(fileIdentityKey(file));
|
|
39
39
|
if (!module)
|
|
40
40
|
continue;
|
|
41
41
|
for (const local of module.locals) {
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
if (local.kind !== SymbolKind.Routine)
|
|
43
|
+
addSqlDefinition(lookup, local.localName, local);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
cache.definitionLookup =
|
|
47
|
-
return
|
|
46
|
+
cache.definitionLookup = lookup;
|
|
47
|
+
return lookup;
|
|
48
48
|
}
|
|
49
49
|
function sqlDefinitionsFromLookup(lookup, objectName) {
|
|
50
50
|
const normalizedName = sqlObjectLookupKey(objectName);
|
|
@@ -75,6 +75,7 @@ function sqlDefinitionMatches(lookup, objectName) {
|
|
|
75
75
|
const SQL_IDENTIFIER = SQL_IDENTIFIER_PART_PATTERN;
|
|
76
76
|
const SQL_DOTTED_TOKEN = String.raw `${SQL_IDENTIFIER}(?:\s*\.\s*${SQL_IDENTIFIER})*`;
|
|
77
77
|
const SQL_DOTTED_TOKEN_RE = new RegExp(SQL_DOTTED_TOKEN, "g");
|
|
78
|
+
const SQL_IDENTIFIER_PART_RE = new RegExp(SQL_IDENTIFIER, "g");
|
|
78
79
|
const SQL_SOURCE_KEYWORDS = new Set([
|
|
79
80
|
"as",
|
|
80
81
|
"on",
|
|
@@ -93,9 +94,8 @@ const SQL_SOURCE_KEYWORDS = new Set([
|
|
|
93
94
|
"returning",
|
|
94
95
|
]);
|
|
95
96
|
const SQL_SOURCE_MODIFIERS = new Set(["only", "lateral"]);
|
|
96
|
-
const SQL_SOURCE_BOUNDARY_RE = /\b(?:where|group\s+by|order\s+by|having|limit|offset|returning|union|intersect|except|on|inner\s+join|left\s+join|right\s+join|full\s+join|cross\s+join|join)\b/i;
|
|
97
97
|
function wordAtPosition(source, line, column) {
|
|
98
|
-
const lineText = maskSqlStringsAndComments(source).split(/\r?\n/)[line - 1];
|
|
98
|
+
const lineText = maskSqlStringsAndComments(source, { escapeStrings: true }).split(/\r?\n/)[line - 1];
|
|
99
99
|
if (!lineText)
|
|
100
100
|
return null;
|
|
101
101
|
const zeroBasedColumn = Math.max(0, column - 1);
|
|
@@ -113,14 +113,20 @@ function sqlObjectNameParts(name) {
|
|
|
113
113
|
.map((part) => part.trim())
|
|
114
114
|
.filter(Boolean);
|
|
115
115
|
}
|
|
116
|
+
const slicesByFacts = new WeakMap();
|
|
117
|
+
/** The statements of one file's facts in source order. A file's facts are fixed, so the result is cached. */
|
|
116
118
|
function sqlStatementSlices(facts) {
|
|
119
|
+
const cached = slicesByFacts.get(facts);
|
|
120
|
+
if (cached)
|
|
121
|
+
return cached;
|
|
117
122
|
const slices = [];
|
|
118
123
|
const seen = new Set();
|
|
119
124
|
for (const fact of facts) {
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
// One statement yields several facts. Its start offset tells it apart from an identical statement
|
|
126
|
+
// on the same line, which its lines and text cannot.
|
|
127
|
+
if (seen.has(fact.startIndex))
|
|
122
128
|
continue;
|
|
123
|
-
seen.add(
|
|
129
|
+
seen.add(fact.startIndex);
|
|
124
130
|
slices.push({
|
|
125
131
|
text: fact.statementText,
|
|
126
132
|
startLine: fact.startLine,
|
|
@@ -128,15 +134,13 @@ function sqlStatementSlices(facts) {
|
|
|
128
134
|
endLine: fact.endLine,
|
|
129
135
|
});
|
|
130
136
|
}
|
|
131
|
-
|
|
137
|
+
slices.sort((left, right) => left.startLine - right.startLine || left.endLine - right.endLine);
|
|
138
|
+
slicesByFacts.set(facts, slices);
|
|
139
|
+
return slices;
|
|
132
140
|
}
|
|
133
141
|
function sqlStatementAtLine(facts, line) {
|
|
134
142
|
return (sqlStatementSlices(facts).find((statement) => line >= statement.startLine && line <= statement.endLine) ?? null);
|
|
135
143
|
}
|
|
136
|
-
function sourceClauseEndIndex(text, start) {
|
|
137
|
-
const boundary = text.slice(start).search(SQL_SOURCE_BOUNDARY_RE);
|
|
138
|
-
return boundary < 0 ? text.length : start + boundary;
|
|
139
|
-
}
|
|
140
144
|
function cteNamesForStatement(text) {
|
|
141
145
|
const cteNames = new Set();
|
|
142
146
|
const cteRe = new RegExp(String.raw `(?:\bwith\s+(?:recursive\s+)?|,\s*)(${SQL_IDENTIFIER})(?:\s*\([^)]*\))?\s+as\s*\(`, "gi");
|
|
@@ -150,12 +154,14 @@ function cteNamesForStatement(text) {
|
|
|
150
154
|
return cteNames;
|
|
151
155
|
}
|
|
152
156
|
function parseSqlSourceEntry(entry) {
|
|
157
|
+
const leading = entry.length - entry.trimStart().length;
|
|
153
158
|
const trimmed = entry.trim();
|
|
154
159
|
if (!trimmed || trimmed.startsWith("("))
|
|
155
160
|
return null;
|
|
156
161
|
const tokenRe = new RegExp(SQL_DOTTED_TOKEN, "gy");
|
|
157
162
|
let cursor = 0;
|
|
158
163
|
let objectName = null;
|
|
164
|
+
let objectOffset = -1;
|
|
159
165
|
while (cursor < trimmed.length) {
|
|
160
166
|
tokenRe.lastIndex = cursor;
|
|
161
167
|
const match = tokenRe.exec(trimmed);
|
|
@@ -167,12 +173,13 @@ function parseSqlSourceEntry(entry) {
|
|
|
167
173
|
cursor = match.index + match[0].length;
|
|
168
174
|
if (!SQL_SOURCE_MODIFIERS.has(normalized.toLowerCase())) {
|
|
169
175
|
objectName = normalized;
|
|
176
|
+
objectOffset = leading + match.index;
|
|
170
177
|
break;
|
|
171
178
|
}
|
|
172
179
|
while (cursor < trimmed.length && /\s/.test(trimmed[cursor] ?? ""))
|
|
173
180
|
cursor += 1;
|
|
174
181
|
}
|
|
175
|
-
if (!objectName)
|
|
182
|
+
if (!objectName || objectOffset < 0)
|
|
176
183
|
return null;
|
|
177
184
|
let rest = trimmed.slice(cursor).trimStart();
|
|
178
185
|
if (rest.startsWith("."))
|
|
@@ -182,31 +189,9 @@ function parseSqlSourceEntry(entry) {
|
|
|
182
189
|
const aliasMatch = new RegExp(String.raw `^(${SQL_IDENTIFIER})`, "i").exec(rest);
|
|
183
190
|
const aliasName = normalizeSqlObjectName(aliasMatch?.[1]) ?? null;
|
|
184
191
|
if (!aliasName || SQL_SOURCE_KEYWORDS.has(aliasName.toLowerCase())) {
|
|
185
|
-
return { objectName, aliasName: null };
|
|
186
|
-
}
|
|
187
|
-
return { objectName, aliasName };
|
|
188
|
-
}
|
|
189
|
-
function sqlAliasMapForStatement(statementText) {
|
|
190
|
-
const aliases = new Map();
|
|
191
|
-
const cteNames = cteNamesForStatement(statementText);
|
|
192
|
-
const clauseRe = /\b(?:from|using|join|inner\s+join|left\s+join|right\s+join|full\s+join|cross\s+join)\s+/gi;
|
|
193
|
-
for (const match of statementText.matchAll(clauseRe)) {
|
|
194
|
-
if (sqlParenDepthAt(statementText, match.index ?? 0) > 0)
|
|
195
|
-
continue;
|
|
196
|
-
const start = (match.index ?? 0) + match[0].length;
|
|
197
|
-
const clause = statementText.slice(start, sourceClauseEndIndex(statementText, start));
|
|
198
|
-
for (const part of splitTopLevelCommaSeparated(clause)) {
|
|
199
|
-
const parsed = parseSqlSourceEntry(part);
|
|
200
|
-
if (!parsed?.aliasName)
|
|
201
|
-
continue;
|
|
202
|
-
const objectKey = sqlObjectLookupKey(parsed.objectName);
|
|
203
|
-
const objectBaseKey = sqlObjectBaseNameLookupKey(parsed.objectName);
|
|
204
|
-
if (cteNames.has(objectKey) || cteNames.has(objectBaseKey))
|
|
205
|
-
continue;
|
|
206
|
-
aliases.set(sqlObjectLookupKey(parsed.aliasName), parsed.objectName);
|
|
207
|
-
}
|
|
192
|
+
return { objectName, aliasName: null, objectOffset };
|
|
208
193
|
}
|
|
209
|
-
return
|
|
194
|
+
return { objectName, aliasName, objectOffset };
|
|
210
195
|
}
|
|
211
196
|
function unambiguousSqlPrefixDefinitionName(lookup, objectName) {
|
|
212
197
|
const matches = sqlDefinitionMatches(lookup, objectName);
|
|
@@ -218,23 +203,116 @@ function unambiguousSqlPrefixDefinitionName(lookup, objectName) {
|
|
|
218
203
|
return matches.basename[0]?.localName ?? null;
|
|
219
204
|
return null;
|
|
220
205
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
206
|
+
/** Resolve a qualifier against the nearest query's relation aliases and indexed routine sources. */
|
|
207
|
+
function sqlSourceBindings(lookups, statementText) {
|
|
208
|
+
const masked = maskSqlStringsAndComments(statementText, { escapeStrings: true });
|
|
209
|
+
const scan = maskSqlQuotedIdentifiers(masked);
|
|
210
|
+
const scopes = sqlQueryScopes(scan);
|
|
211
|
+
const bindings = new Map();
|
|
212
|
+
const addBinding = (offset, key, binding) => {
|
|
213
|
+
const scope = scopes.at(offset);
|
|
214
|
+
let inScope = bindings.get(scope);
|
|
215
|
+
if (!inScope) {
|
|
216
|
+
inScope = new Map();
|
|
217
|
+
bindings.set(scope, inScope);
|
|
218
|
+
}
|
|
219
|
+
const previous = inScope.get(key);
|
|
220
|
+
if (!previous) {
|
|
221
|
+
inScope.set(key, binding);
|
|
222
|
+
}
|
|
223
|
+
else if (previous.kind !== binding.kind ||
|
|
224
|
+
(previous.kind === "relation" && binding.kind === "relation" && previous.objectName !== binding.objectName)) {
|
|
225
|
+
inScope.set(key, { kind: "ambiguous" });
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
const cteNames = cteNamesForStatement(masked);
|
|
229
|
+
const routineSources = lookups.namespaceByDefinition.size
|
|
230
|
+
? findSqlRoutineSources(statementText).filter(({ mention }) => routineCandidates(lookups, mention).length > 0)
|
|
231
|
+
: [];
|
|
232
|
+
for (const source of sqlSourceClauses(scan)) {
|
|
233
|
+
const clause = masked.slice(source.end, source.clauseEnd);
|
|
234
|
+
let nextPartStart = source.end;
|
|
235
|
+
for (const part of splitTopLevelCommaSeparated(clause)) {
|
|
236
|
+
const partStart = masked.indexOf(part, nextPartStart);
|
|
237
|
+
if (partStart < 0)
|
|
238
|
+
continue;
|
|
239
|
+
const partEnd = partStart + part.length;
|
|
240
|
+
nextPartStart = partEnd + 1;
|
|
241
|
+
const parsed = parseSqlSourceEntry(part);
|
|
242
|
+
if (!parsed)
|
|
243
|
+
continue;
|
|
244
|
+
// A routine source owns only its own source item. A later call that merely falls inside this
|
|
245
|
+
// slice, such as the next statement of a procedure body, must not drop the relation binding.
|
|
246
|
+
if (routineSources.some(({ mention }) => mention.start === partStart + parsed.objectOffset))
|
|
247
|
+
continue;
|
|
248
|
+
const objectKey = sqlObjectLookupKey(parsed.objectName);
|
|
249
|
+
const objectBaseKey = sqlObjectBaseNameLookupKey(parsed.objectName);
|
|
250
|
+
if (cteNames.has(objectKey) || cteNames.has(objectBaseKey))
|
|
251
|
+
continue;
|
|
252
|
+
const relation = { kind: "relation", objectName: parsed.objectName };
|
|
253
|
+
if (parsed.aliasName) {
|
|
254
|
+
addBinding(source.start, sqlObjectLookupKey(parsed.aliasName), relation);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
addBinding(source.start, objectKey, relation);
|
|
258
|
+
if (objectBaseKey !== objectKey)
|
|
259
|
+
addBinding(source.start, objectBaseKey, relation);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
for (const { mention, alias } of routineSources) {
|
|
264
|
+
if (alias) {
|
|
265
|
+
addBinding(mention.start, sqlObjectLookupKey(alias), { kind: "routine" });
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
addBinding(mention.start, sqlObjectLookupKey(mention.name), { kind: "routine" });
|
|
269
|
+
addBinding(mention.start, sqlObjectBaseNameLookupKey(mention.name), { kind: "routine" });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
at(offset, parts) {
|
|
274
|
+
for (let scope = scopes.at(offset);; scope = scopes.parent.get(scope) ?? 0) {
|
|
275
|
+
const inScope = bindings.get(scope);
|
|
276
|
+
let binding = inScope?.get(sqlObjectLookupKey(parts[0] ?? ""));
|
|
277
|
+
for (let count = 2; count < parts.length; count += 1) {
|
|
278
|
+
const candidate = inScope?.get(sqlObjectLookupKey(parts.slice(0, count).join(".")));
|
|
279
|
+
if (candidate && binding && candidate !== binding)
|
|
280
|
+
return { kind: "ambiguous" };
|
|
281
|
+
binding ??= candidate;
|
|
282
|
+
}
|
|
283
|
+
if (binding)
|
|
284
|
+
return binding;
|
|
285
|
+
if (!scope)
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
return null;
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
function resolveQualifiedSqlName(lookup, routineLookups, name, statementText, offset) {
|
|
224
293
|
const parts = sqlObjectNameParts(name);
|
|
225
294
|
if (parts.length < 2)
|
|
226
295
|
return name;
|
|
227
296
|
const firstPart = parts[0];
|
|
228
297
|
if (!firstPart)
|
|
229
298
|
return null;
|
|
230
|
-
if (statementText) {
|
|
231
|
-
const maskedStatementText = maskSqlStringsAndComments(statementText);
|
|
299
|
+
if (statementText && offset !== undefined) {
|
|
300
|
+
const maskedStatementText = maskSqlStringsAndComments(statementText, { escapeStrings: true });
|
|
232
301
|
if (cteNamesForStatement(maskedStatementText).has(sqlObjectLookupKey(firstPart)))
|
|
233
302
|
return null;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
return
|
|
303
|
+
if (sqlObjectMentionCovers(statementText, offset)) {
|
|
304
|
+
const direct = sqlDefinitionMatches(lookup, name);
|
|
305
|
+
return direct.exact.length || direct.basename.length === 1 ? name : null;
|
|
306
|
+
}
|
|
307
|
+
const binding = sqlSourceBindings(routineLookups, statementText).at(offset, parts);
|
|
308
|
+
if (binding) {
|
|
309
|
+
if (binding.kind !== "relation")
|
|
310
|
+
return null;
|
|
311
|
+
return sqlDefinitionsFromLookup(lookup, binding.objectName).length ? binding.objectName : null;
|
|
312
|
+
}
|
|
237
313
|
}
|
|
314
|
+
if (sqlDefinitionsFromLookup(lookup, name).length)
|
|
315
|
+
return name;
|
|
238
316
|
for (let partCount = parts.length - 1; partCount >= 1; partCount -= 1) {
|
|
239
317
|
const candidate = parts.slice(0, partCount).join(".");
|
|
240
318
|
const resolvedName = unambiguousSqlPrefixDefinitionName(lookup, candidate);
|
|
@@ -261,7 +339,15 @@ function sqlNameResolvesToDefinition(lookup, name, definition) {
|
|
|
261
339
|
return matches.exact.includes(definition);
|
|
262
340
|
return matches.basename.length === 1 && matches.basename[0] === definition;
|
|
263
341
|
}
|
|
264
|
-
|
|
342
|
+
/**
|
|
343
|
+
* Where the last `partCount` parts of a dotted name begin. Rename edits the definition's own name and
|
|
344
|
+
* keeps the qualifier in front of it: a rename of `f` edits the `f` in `public.f`.
|
|
345
|
+
*/
|
|
346
|
+
function trailingPartsOffset(dottedName, partCount) {
|
|
347
|
+
const parts = [...dottedName.matchAll(SQL_IDENTIFIER_PART_RE)];
|
|
348
|
+
return parts[parts.length - partCount]?.index ?? 0;
|
|
349
|
+
}
|
|
350
|
+
function factReferenceRanges(fact, objectName, claimedStarts, keepParts = 0) {
|
|
265
351
|
const statement = {
|
|
266
352
|
text: fact.statementText,
|
|
267
353
|
startLine: fact.startLine,
|
|
@@ -270,22 +356,35 @@ function factReferenceRanges(fact, objectName) {
|
|
|
270
356
|
};
|
|
271
357
|
const objectKey = sqlObjectLookupKey(objectName);
|
|
272
358
|
const ranges = [];
|
|
273
|
-
const
|
|
359
|
+
const sourceSpans = fact.kind === "reads_from" || fact.kind === "joins" ? sqlRelationReadSpans(statement.text) : null;
|
|
360
|
+
const maskedStatementText = maskSqlStringsAndComments(statement.text, { escapeStrings: true });
|
|
274
361
|
for (const match of maskedStatementText.matchAll(SQL_DOTTED_TOKEN_RE)) {
|
|
275
362
|
const token = normalizeSqlObjectName(match[0]);
|
|
276
363
|
if (!token || sqlObjectLookupKey(token) !== objectKey)
|
|
277
364
|
continue;
|
|
278
365
|
const offset = match.index ?? 0;
|
|
279
|
-
|
|
366
|
+
if (claimedStarts?.has(offset))
|
|
367
|
+
continue;
|
|
368
|
+
if (sourceSpans &&
|
|
369
|
+
!sourceSpans.some((span) => span.start === offset && sqlObjectLookupKey(span.name) === objectKey))
|
|
370
|
+
continue;
|
|
371
|
+
const nameOffset = keepParts ? trailingPartsOffset(match[0], keepParts) : 0;
|
|
372
|
+
ranges.push(rangeForToken(statementLineForOffset(statement, offset + nameOffset), statementColumnForOffset(statement, offset + nameOffset), match[0].length - nameOffset));
|
|
280
373
|
}
|
|
281
374
|
return ranges;
|
|
282
375
|
}
|
|
283
|
-
function qualifiedReferenceRanges(lookup, statement, definition) {
|
|
376
|
+
function qualifiedReferenceRanges(lookup, routineLookups, statement, definition, claimedStarts, keepParts = 0) {
|
|
284
377
|
const ranges = [];
|
|
285
|
-
|
|
286
|
-
const
|
|
378
|
+
let ambiguous = false;
|
|
379
|
+
const maskedStatementText = maskSqlStringsAndComments(statement.text, { escapeStrings: true });
|
|
380
|
+
const bindings = sqlSourceBindings(routineLookups, statement.text);
|
|
287
381
|
const cteNames = cteNamesForStatement(maskedStatementText);
|
|
382
|
+
// One scan for the statement. A fresh scan for every qualified name is quadratic.
|
|
383
|
+
const objectSpans = sqlSyntacticObjectSpans(statement.text);
|
|
288
384
|
for (const match of maskedStatementText.matchAll(SQL_DOTTED_TOKEN_RE)) {
|
|
385
|
+
const offset = match.index ?? 0;
|
|
386
|
+
if (claimedStarts?.has(offset))
|
|
387
|
+
continue;
|
|
289
388
|
const token = normalizeSqlObjectName(match[0]);
|
|
290
389
|
if (!token)
|
|
291
390
|
continue;
|
|
@@ -297,19 +396,38 @@ function qualifiedReferenceRanges(lookup, statement, definition) {
|
|
|
297
396
|
continue;
|
|
298
397
|
if (cteNames.has(sqlObjectLookupKey(firstPart)))
|
|
299
398
|
continue;
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
399
|
+
if (sqlSpanCovers(objectSpans, offset)) {
|
|
400
|
+
const direct = sqlDefinitionMatches(lookup, token);
|
|
401
|
+
if (!direct.exact.length && direct.basename.length > 1 && direct.basename.includes(definition))
|
|
402
|
+
ambiguous = true;
|
|
403
|
+
if (sqlNameResolvesToDefinition(lookup, token, definition)) {
|
|
404
|
+
const nameOffset = keepParts ? trailingPartsOffset(match[0], keepParts) : 0;
|
|
405
|
+
ranges.push(rangeForToken(statementLineForOffset(statement, offset + nameOffset), statementColumnForOffset(statement, offset + nameOffset), match[0].length - nameOffset));
|
|
406
|
+
}
|
|
407
|
+
continue;
|
|
306
408
|
}
|
|
307
|
-
|
|
409
|
+
const binding = bindings.at(offset, parts);
|
|
410
|
+
if (binding?.kind === "ambiguous") {
|
|
411
|
+
ambiguous = true;
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
if (binding?.kind === "routine")
|
|
415
|
+
continue;
|
|
416
|
+
let matches = false;
|
|
417
|
+
if (binding) {
|
|
418
|
+
matches = sqlNameResolvesToDefinition(lookup, binding.objectName, definition);
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
for (let partCount = parts.length - 1; partCount >= 1 && !matches; partCount -= 1) {
|
|
422
|
+
const candidate = parts.slice(0, partCount).join(".");
|
|
423
|
+
matches = sqlNameResolvesToDefinition(lookup, candidate, definition);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
if (!matches)
|
|
308
427
|
continue;
|
|
309
|
-
const offset = match.index ?? 0;
|
|
310
428
|
ranges.push(rangeForToken(statementLineForOffset(statement, offset), statementColumnForOffset(statement, offset), match[0].length));
|
|
311
429
|
}
|
|
312
|
-
return ranges;
|
|
430
|
+
return { ranges, ambiguous };
|
|
313
431
|
}
|
|
314
432
|
async function sourceForFile(filePath, index) {
|
|
315
433
|
const cache = getSqlNavigationCache(index);
|
|
@@ -332,17 +450,185 @@ async function sqlFactsForFile(index, filePath) {
|
|
|
332
450
|
cache.factsByFile.set(key, facts);
|
|
333
451
|
return facts;
|
|
334
452
|
}
|
|
453
|
+
const routineLookupsByIndex = new WeakMap();
|
|
454
|
+
const mentionsByFacts = new WeakMap();
|
|
455
|
+
function siteKey(file, line, column) {
|
|
456
|
+
return `${fileIdentityKey(file)}:${line}:${column}`;
|
|
457
|
+
}
|
|
458
|
+
/** The name space of each routine one file defines, by the position where its statement starts. */
|
|
459
|
+
async function routineNamespacesByStart(index, file) {
|
|
460
|
+
const namespaces = new Map();
|
|
461
|
+
for (const fact of await sqlFactsForFile(index, file)) {
|
|
462
|
+
if (fact.kind !== "defines_routine")
|
|
463
|
+
continue;
|
|
464
|
+
namespaces.set(`${fact.startLine}:${fact.startColumn}`, sqlRoutineDefinitionNamespace(fact.statementText));
|
|
465
|
+
}
|
|
466
|
+
return namespaces;
|
|
467
|
+
}
|
|
468
|
+
async function buildSqlRoutineLookups(index) {
|
|
469
|
+
const lookups = {
|
|
470
|
+
callable: createSqlDefinitionIndex(),
|
|
471
|
+
trigger: createSqlDefinitionIndex(),
|
|
472
|
+
namespaceByDefinition: new Map(),
|
|
473
|
+
definitionByStart: new Map(),
|
|
474
|
+
};
|
|
475
|
+
for (const file of sqlFiles(index)) {
|
|
476
|
+
const locals = index.byFile.get(fileIdentityKey(file))?.locals ?? [];
|
|
477
|
+
const routines = locals.filter((local) => local.kind === SymbolKind.Routine);
|
|
478
|
+
if (!routines.length)
|
|
479
|
+
continue;
|
|
480
|
+
const namespaces = await routineNamespacesByStart(index, file);
|
|
481
|
+
for (const routine of routines) {
|
|
482
|
+
const { line, column } = routine.range.start;
|
|
483
|
+
const namespace = namespaces.get(`${line}:${column}`) ?? "callable";
|
|
484
|
+
addSqlDefinition(lookups[namespace], routine.localName, routine);
|
|
485
|
+
lookups.namespaceByDefinition.set(routine, namespace);
|
|
486
|
+
lookups.definitionByStart.set(siteKey(file, line, column), routine);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return lookups;
|
|
490
|
+
}
|
|
491
|
+
function getSqlRoutineLookups(index) {
|
|
492
|
+
const cached = routineLookupsByIndex.get(index);
|
|
493
|
+
if (cached)
|
|
494
|
+
return cached;
|
|
495
|
+
const lookups = buildSqlRoutineLookups(index);
|
|
496
|
+
routineLookupsByIndex.set(index, lookups);
|
|
497
|
+
// A failed build must not stay cached; the next lookup tries again.
|
|
498
|
+
lookups.catch(() => routineLookupsByIndex.delete(index));
|
|
499
|
+
return lookups;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* The mentions in each statement that name a routine. A keyword mention always does. A bare `name(`
|
|
503
|
+
* does only when an indexed routine has that name, because `INSERT INTO users (id)` has the same shape.
|
|
504
|
+
*/
|
|
505
|
+
function statementMentions(lookups, facts) {
|
|
506
|
+
const cached = mentionsByFacts.get(facts);
|
|
507
|
+
if (cached)
|
|
508
|
+
return cached;
|
|
509
|
+
const statements = [];
|
|
510
|
+
for (const statement of sqlStatementSlices(facts)) {
|
|
511
|
+
const mentions = findSqlRoutineMentions(statement.text).filter((mention) => !mention.speculative || routineCandidates(lookups, mention).length);
|
|
512
|
+
if (mentions.length)
|
|
513
|
+
statements.push({ statement, mentions });
|
|
514
|
+
}
|
|
515
|
+
mentionsByFacts.set(facts, statements);
|
|
516
|
+
return statements;
|
|
517
|
+
}
|
|
518
|
+
function routineCandidates(lookups, mention) {
|
|
519
|
+
return sqlRoutineNameCandidates(lookups[mention.namespace], mention.name, (definition) => definition.localName)
|
|
520
|
+
.candidates;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Start offsets of the tokens in each statement that name a routine, by statement start. A table or
|
|
524
|
+
* view reference skips these tokens: a name in a routine position is not a relation.
|
|
525
|
+
*/
|
|
526
|
+
function claimedMentionStarts(lookups, facts) {
|
|
527
|
+
const claimed = new Map();
|
|
528
|
+
for (const { statement, mentions } of statementMentions(lookups, facts)) {
|
|
529
|
+
claimed.set(`${statement.startLine}:${statement.startColumn}`, new Set(mentions.map((mention) => mention.start)));
|
|
530
|
+
}
|
|
531
|
+
return claimed;
|
|
532
|
+
}
|
|
533
|
+
function mentionRange(statement, mention, keepParts = 0) {
|
|
534
|
+
const start = mention.start + (keepParts ? trailingPartsOffset(statement.text.slice(mention.start, mention.end), keepParts) : 0);
|
|
535
|
+
return {
|
|
536
|
+
start: {
|
|
537
|
+
line: statementLineForOffset(statement, start),
|
|
538
|
+
column: statementColumnForOffset(statement, start),
|
|
539
|
+
},
|
|
540
|
+
end: {
|
|
541
|
+
line: statementLineForOffset(statement, mention.end),
|
|
542
|
+
column: statementColumnForOffset(statement, mention.end),
|
|
543
|
+
},
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
function statementOffsetAtPosition(statement, line, column) {
|
|
547
|
+
if (line < statement.startLine || line > statement.endLine)
|
|
548
|
+
return undefined;
|
|
549
|
+
let lineStart = 0;
|
|
550
|
+
for (let current = statement.startLine; current < line; current += 1) {
|
|
551
|
+
const newline = statement.text.indexOf("\n", lineStart);
|
|
552
|
+
if (newline < 0)
|
|
553
|
+
return undefined;
|
|
554
|
+
lineStart = newline + 1;
|
|
555
|
+
}
|
|
556
|
+
return lineStart + column - (line === statement.startLine ? statement.startColumn : 1);
|
|
557
|
+
}
|
|
558
|
+
function goToRoutineMention(index, lookups, file, facts, position) {
|
|
559
|
+
for (const statement of sqlStatementSlices(facts)) {
|
|
560
|
+
const offset = statementOffsetAtPosition(statement, position.line, position.column);
|
|
561
|
+
// Several statements can share one line, so only the statement that holds the position counts.
|
|
562
|
+
if (offset === undefined || offset < 0 || offset >= statement.text.length)
|
|
563
|
+
continue;
|
|
564
|
+
const mention = findSqlRoutineMentions(statement.text).find((entry) => offset >= entry.start && offset < entry.end);
|
|
565
|
+
if (!mention)
|
|
566
|
+
return null;
|
|
567
|
+
if (mention.kind === "definition") {
|
|
568
|
+
const definition = lookups.definitionByStart.get(siteKey(file, statement.startLine, statement.startColumn));
|
|
569
|
+
return definition ? okGoToResult(index, definition, { resolution: "exact", confidence: "high" }) : null;
|
|
570
|
+
}
|
|
571
|
+
const candidates = routineCandidates(lookups, mention);
|
|
572
|
+
const [only] = candidates;
|
|
573
|
+
if (only && candidates.length === 1)
|
|
574
|
+
return okGoToResult(index, only, { resolution: "exact", confidence: "high" });
|
|
575
|
+
if (candidates.length)
|
|
576
|
+
return { status: "not_found", reason: "Several SQL routines share this name" };
|
|
577
|
+
// A bare `name(` can name a table or an index; a keyword such as `CALL` or `DROP FUNCTION` names a routine.
|
|
578
|
+
return mention.speculative ? null : { status: "not_found", reason: "No matching SQL routine definition" };
|
|
579
|
+
}
|
|
580
|
+
return null;
|
|
581
|
+
}
|
|
582
|
+
function routineMentionIsProven(lookups, statementText, offset) {
|
|
583
|
+
const mention = findSqlRoutineMentions(statementText).find((entry) => offset >= entry.start && offset < entry.end);
|
|
584
|
+
if (!mention)
|
|
585
|
+
return false;
|
|
586
|
+
// A bare `name(` is a routine only when an indexed routine has that name. Otherwise it may be a table.
|
|
587
|
+
if (!mention.speculative)
|
|
588
|
+
return true;
|
|
589
|
+
return routineCandidates(lookups, mention).length > 0;
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* True when the position names an object or a routine by SQL syntax: a `FROM`/`JOIN`/`CALL`/`ON`
|
|
593
|
+
* target, not a column that happens to share a table's name. The name that a `CREATE` statement
|
|
594
|
+
* defines is no mention: it names the definition itself.
|
|
595
|
+
*/
|
|
596
|
+
export async function sqlPositionIsProvenObjectOrRoutineMention(index, req) {
|
|
597
|
+
if (!isSqlFilePath(req.file, index.languageExtensions))
|
|
598
|
+
return false;
|
|
599
|
+
const facts = await sqlFactsForFile(index, req.file);
|
|
600
|
+
const routineLookups = await getSqlRoutineLookups(index);
|
|
601
|
+
for (const statement of sqlStatementSlices(facts)) {
|
|
602
|
+
const offset = statementOffsetAtPosition(statement, req.line, req.column);
|
|
603
|
+
if (offset === undefined || offset < 0 || offset >= statement.text.length)
|
|
604
|
+
continue;
|
|
605
|
+
const defined = sqlDefinedNameSpan(statement.text);
|
|
606
|
+
if (defined && offset >= defined.start && offset < defined.end)
|
|
607
|
+
return false;
|
|
608
|
+
if (routineMentionIsProven(routineLookups, statement.text, offset))
|
|
609
|
+
return true;
|
|
610
|
+
return sqlObjectMentionCovers(statement.text, offset);
|
|
611
|
+
}
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
335
614
|
export async function goToSqlDefinition(index, req) {
|
|
336
|
-
if (!
|
|
615
|
+
if (!isSqlFilePath(req.file, index.languageExtensions))
|
|
337
616
|
return null;
|
|
338
617
|
const source = await sourceForFile(req.file, index);
|
|
339
|
-
const name = wordAtPosition(source, req.line, req.column);
|
|
340
|
-
if (!name)
|
|
341
|
-
return { status: "not_found", reason: "No SQL object at position" };
|
|
342
618
|
const lookup = getSqlDefinitionLookup(index);
|
|
619
|
+
const routineLookups = await getSqlRoutineLookups(index);
|
|
343
620
|
const facts = await sqlFactsForFile(index, req.file);
|
|
621
|
+
// `DROP FUNCTION f`, `CALL f`, and the like name a routine even when the project defines none, so they
|
|
622
|
+
// never fall through to a table of the same name.
|
|
623
|
+
const routineResult = goToRoutineMention(index, routineLookups, req.file, facts, req);
|
|
624
|
+
if (routineResult)
|
|
625
|
+
return routineResult;
|
|
344
626
|
const statement = sqlStatementAtLine(facts, req.line);
|
|
345
|
-
const
|
|
627
|
+
const name = wordAtPosition(source, req.line, req.column);
|
|
628
|
+
if (!name)
|
|
629
|
+
return { status: "not_found", reason: "No SQL object at position" };
|
|
630
|
+
const offset = statement ? statementOffsetAtPosition(statement, req.line, req.column) : undefined;
|
|
631
|
+
const resolvedName = resolveQualifiedSqlName(lookup, routineLookups, name, statement?.text ?? null, offset);
|
|
346
632
|
if (!resolvedName)
|
|
347
633
|
return { status: "not_found", reason: "No matching SQL object definition" };
|
|
348
634
|
const definitions = sqlDefinitionsFromLookup(lookup, resolvedName);
|
|
@@ -354,24 +640,65 @@ export async function goToSqlDefinition(index, req) {
|
|
|
354
640
|
confidence: "high",
|
|
355
641
|
});
|
|
356
642
|
}
|
|
357
|
-
|
|
358
|
-
|
|
643
|
+
/**
|
|
644
|
+
* The site of the name `definition` declares, as in `users` in `CREATE TABLE users`. A definition spans
|
|
645
|
+
* its whole statement, so its range does not say where its name is.
|
|
646
|
+
*/
|
|
647
|
+
async function declarationSiteKey(index, definition) {
|
|
648
|
+
const { line, column } = definition.range.start;
|
|
649
|
+
const facts = await sqlFactsForFile(index, definition.file);
|
|
650
|
+
const statement = sqlStatementSlices(facts).find((slice) => slice.startLine === line && slice.startColumn === column);
|
|
651
|
+
const name = statement ? sqlDefinedNameSpan(statement.text) : null;
|
|
652
|
+
if (!statement || !name)
|
|
653
|
+
return null;
|
|
654
|
+
const nameLine = statementLineForOffset(statement, name.start);
|
|
655
|
+
return siteKey(definition.file, nameLine, statementColumnForOffset(statement, name.start));
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* The indexed definition declared at the site `definition` names. Impact analysis passes a copy of a
|
|
659
|
+
* definition, and a lookup by object identity cannot match a copy.
|
|
660
|
+
*/
|
|
661
|
+
function indexedSqlDefinition(index, definition) {
|
|
662
|
+
const { line, column } = definition.range.start;
|
|
663
|
+
const locals = index.byFile.get(fileIdentityKey(definition.file))?.locals ?? [];
|
|
664
|
+
return (locals.find((local) => local.range.start.line === line &&
|
|
665
|
+
local.range.start.column === column &&
|
|
666
|
+
local.kind === definition.kind &&
|
|
667
|
+
local.localName === definition.localName) ?? null);
|
|
668
|
+
}
|
|
669
|
+
export async function findSqlReferences(index, requested, options) {
|
|
670
|
+
if (!isSqlFilePath(requested.file, index.languageExtensions))
|
|
359
671
|
return null;
|
|
672
|
+
const definition = indexedSqlDefinition(index, requested);
|
|
673
|
+
// Without the indexed definition no lookup can match, and an empty list would claim a complete scan.
|
|
674
|
+
if (!definition)
|
|
675
|
+
return { status: "not_found", reason: "SQL definition is not in the index" };
|
|
360
676
|
const references = [];
|
|
361
677
|
const seen = new Set();
|
|
362
678
|
const lookup = getSqlDefinitionLookup(index);
|
|
679
|
+
const routineLookups = await getSqlRoutineLookups(index);
|
|
680
|
+
const routineNamespace = routineLookups.namespaceByDefinition.get(definition);
|
|
681
|
+
const hasRoutines = !!routineLookups.namespaceByDefinition.size;
|
|
363
682
|
const candidateFiles = sqlFiles(index);
|
|
364
683
|
const scannedFiles = [];
|
|
684
|
+
// Files with a mention that several routine definitions could own, so no one definition owns it.
|
|
685
|
+
const ambiguousFiles = [];
|
|
365
686
|
const includeDefinition = options?.includeDefinition ?? true;
|
|
687
|
+
const keepParts = options?.renameRanges ? sqlObjectNameParts(definition.localName).length : 0;
|
|
366
688
|
const maxReferences = typeof options?.maxReferences === "number" && options.maxReferences > 0 ? options.maxReferences : undefined;
|
|
367
689
|
const collectionLimit = maxReferences === undefined ? undefined : maxReferences + 1;
|
|
368
|
-
const definitionKey =
|
|
690
|
+
const definitionKey = siteKey(definition.file, definition.range.start.line, definition.range.start.column);
|
|
691
|
+
// A usage lookup leaves out the declaration. A routine's declaration is a mention, skipped below.
|
|
692
|
+
// A relation's is not, so find the site of its name here.
|
|
693
|
+
let declarationKey = null;
|
|
694
|
+
if (!includeDefinition && !routineNamespace)
|
|
695
|
+
declarationKey = await declarationSiteKey(index, definition);
|
|
369
696
|
const hasReachedCollectionLimit = () => collectionLimit !== undefined && references.length >= collectionLimit;
|
|
370
697
|
const addReference = (file, range) => {
|
|
371
698
|
if (hasReachedCollectionLimit())
|
|
372
699
|
return;
|
|
373
|
-
const key =
|
|
374
|
-
if (
|
|
700
|
+
const key = siteKey(file, range.start.line, range.start.column);
|
|
701
|
+
if (key === declarationKey)
|
|
375
702
|
return;
|
|
376
703
|
if (seen.has(key))
|
|
377
704
|
return;
|
|
@@ -383,13 +710,44 @@ export async function findSqlReferences(index, definition, options) {
|
|
|
383
710
|
break;
|
|
384
711
|
scannedFiles.push(file);
|
|
385
712
|
const facts = await sqlFactsForFile(index, file);
|
|
713
|
+
if (routineNamespace) {
|
|
714
|
+
for (const { statement, mentions } of statementMentions(routineLookups, facts)) {
|
|
715
|
+
for (const mention of mentions) {
|
|
716
|
+
if (hasReachedCollectionLimit())
|
|
717
|
+
break;
|
|
718
|
+
if (mention.namespace !== routineNamespace)
|
|
719
|
+
continue;
|
|
720
|
+
if (mention.kind === "definition") {
|
|
721
|
+
// A definition always names itself, even when several definitions share the name. Only a
|
|
722
|
+
// lookup that includes the declaration reports it.
|
|
723
|
+
const namesDefinition = siteKey(file, statement.startLine, statement.startColumn) === definitionKey;
|
|
724
|
+
if (includeDefinition && namesDefinition)
|
|
725
|
+
addReference(file, mentionRange(statement, mention, keepParts));
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
const candidates = routineCandidates(routineLookups, mention);
|
|
729
|
+
if (!candidates.includes(definition))
|
|
730
|
+
continue;
|
|
731
|
+
if (candidates.length === 1)
|
|
732
|
+
addReference(file, mentionRange(statement, mention, keepParts));
|
|
733
|
+
else if (!ambiguousFiles.includes(file))
|
|
734
|
+
ambiguousFiles.push(file);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
continue;
|
|
738
|
+
}
|
|
739
|
+
const claimedStarts = hasRoutines ? claimedMentionStarts(routineLookups, facts) : undefined;
|
|
386
740
|
for (const fact of facts) {
|
|
387
741
|
if (hasReachedCollectionLimit())
|
|
388
742
|
break;
|
|
743
|
+
// The name in `DROP FUNCTION name` is a routine mention, never a table of the same name.
|
|
744
|
+
if (fact.kind === "drops_object" && sqlStatementDropsRoutine(fact.statementText))
|
|
745
|
+
continue;
|
|
746
|
+
const claimed = claimedStarts?.get(`${fact.startLine}:${fact.startColumn}`);
|
|
389
747
|
for (const name of [fact.objectName, fact.relatedObjectName]) {
|
|
390
748
|
if (!name || !sqlNameResolvesToDefinition(lookup, name, definition))
|
|
391
749
|
continue;
|
|
392
|
-
for (const range of factReferenceRanges(fact, name)) {
|
|
750
|
+
for (const range of factReferenceRanges(fact, name, claimed, keepParts)) {
|
|
393
751
|
addReference(file, range);
|
|
394
752
|
}
|
|
395
753
|
}
|
|
@@ -399,9 +757,14 @@ export async function findSqlReferences(index, definition, options) {
|
|
|
399
757
|
for (const statement of sqlStatementSlices(facts)) {
|
|
400
758
|
if (hasReachedCollectionLimit())
|
|
401
759
|
break;
|
|
402
|
-
|
|
760
|
+
if (sqlStatementDropsRoutine(statement.text))
|
|
761
|
+
continue;
|
|
762
|
+
const claimed = claimedStarts?.get(`${statement.startLine}:${statement.startColumn}`);
|
|
763
|
+
const { ranges, ambiguous } = qualifiedReferenceRanges(lookup, routineLookups, statement, definition, claimed, keepParts);
|
|
764
|
+
for (const range of ranges)
|
|
403
765
|
addReference(file, range);
|
|
404
|
-
|
|
766
|
+
if (ambiguous && !ambiguousFiles.includes(file))
|
|
767
|
+
ambiguousFiles.push(file);
|
|
405
768
|
}
|
|
406
769
|
}
|
|
407
770
|
references.sort((left, right) => {
|
|
@@ -426,7 +789,34 @@ export async function findSqlReferences(index, definition, options) {
|
|
|
426
789
|
candidateFiles,
|
|
427
790
|
scannedFiles,
|
|
428
791
|
truncated,
|
|
792
|
+
strategyUnavailableFiles: ambiguousFiles,
|
|
429
793
|
}),
|
|
430
794
|
};
|
|
431
795
|
}
|
|
796
|
+
/**
|
|
797
|
+
* What each changed SQL symbol is called in graph edges: a table, view, or index by its name, a
|
|
798
|
+
* routine by its name and name space. The index stores no name space, and an index restored from a
|
|
799
|
+
* cache never read the statement, so the name space comes from the facts of the changed file.
|
|
800
|
+
*/
|
|
801
|
+
export async function sqlChangedSymbolTargets(index, symbols) {
|
|
802
|
+
const targets = new Map();
|
|
803
|
+
const namespacesByFile = new Map();
|
|
804
|
+
for (const symbol of symbols) {
|
|
805
|
+
if (symbol.kind === SymbolKind.Table || symbol.kind === SymbolKind.View || symbol.kind === SymbolKind.Index) {
|
|
806
|
+
targets.set(symbol, { name: symbol.name, namespace: "relation" });
|
|
807
|
+
continue;
|
|
808
|
+
}
|
|
809
|
+
if (symbol.kind !== SymbolKind.Routine)
|
|
810
|
+
continue;
|
|
811
|
+
const fileKey = fileIdentityKey(symbol.file);
|
|
812
|
+
let namespaces = namespacesByFile.get(fileKey);
|
|
813
|
+
if (!namespaces) {
|
|
814
|
+
namespaces = await routineNamespacesByStart(index, symbol.file);
|
|
815
|
+
namespacesByFile.set(fileKey, namespaces);
|
|
816
|
+
}
|
|
817
|
+
const { line, column } = symbol.range.start;
|
|
818
|
+
targets.set(symbol, { name: symbol.name, namespace: namespaces.get(`${line}:${column}`) ?? "callable" });
|
|
819
|
+
}
|
|
820
|
+
return targets;
|
|
821
|
+
}
|
|
432
822
|
//# sourceMappingURL=navigation.js.map
|