@lzehrung/codegraph 2.1.0 → 2.1.2
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 +27 -29
- package/codegraph-skill/codegraph/SKILL.md +27 -26
- package/dist/agent/artifact.d.ts.map +1 -1
- package/dist/agent/artifact.js +105 -14
- package/dist/agent/artifact.js.map +1 -1
- package/dist/agent/candidateTests.d.ts +12 -0
- package/dist/agent/candidateTests.d.ts.map +1 -0
- package/dist/agent/candidateTests.js +17 -0
- package/dist/agent/candidateTests.js.map +1 -0
- package/dist/agent/explain.d.ts +3 -0
- package/dist/agent/explain.d.ts.map +1 -1
- package/dist/agent/explain.js +8 -0
- package/dist/agent/explain.js.map +1 -1
- package/dist/agent/explore.d.ts.map +1 -1
- package/dist/agent/explore.js +11 -6
- package/dist/agent/explore.js.map +1 -1
- package/dist/agent/fileView.d.ts.map +1 -1
- package/dist/agent/fileView.js +113 -120
- package/dist/agent/fileView.js.map +1 -1
- package/dist/agent/orient.d.ts.map +1 -1
- package/dist/agent/orient.js +7 -4
- package/dist/agent/orient.js.map +1 -1
- package/dist/agent/packet.d.ts.map +1 -1
- package/dist/agent/packet.js +5 -12
- package/dist/agent/packet.js.map +1 -1
- package/dist/agent/query-index/candidates.d.ts +13 -2
- package/dist/agent/query-index/candidates.d.ts.map +1 -1
- package/dist/agent/query-index/candidates.js +28 -39
- package/dist/agent/query-index/candidates.js.map +1 -1
- package/dist/agent/query-index/content.d.ts +1 -1
- package/dist/agent/query-index/content.js +4 -4
- package/dist/agent/query-index/content.js.map +1 -1
- package/dist/agent/query-index/schema.d.ts.map +1 -1
- package/dist/agent/query-index/schema.js.map +1 -1
- package/dist/agent/query-index/sessionStore.d.ts.map +1 -1
- package/dist/agent/query-index/sessionStore.js +42 -26
- package/dist/agent/query-index/sessionStore.js.map +1 -1
- package/dist/agent/query-index/store.d.ts +10 -4
- package/dist/agent/query-index/store.d.ts.map +1 -1
- package/dist/agent/query-index/store.js +115 -10
- package/dist/agent/query-index/store.js.map +1 -1
- package/dist/agent/query-index/update.d.ts.map +1 -1
- package/dist/agent/query-index/update.js +24 -9
- package/dist/agent/query-index/update.js.map +1 -1
- package/dist/agent/refactorPlan.d.ts.map +1 -1
- package/dist/agent/refactorPlan.js +6 -14
- package/dist/agent/refactorPlan.js.map +1 -1
- package/dist/agent/renamePreview.d.ts +2 -5
- package/dist/agent/renamePreview.d.ts.map +1 -1
- package/dist/agent/renamePreview.js +133 -80
- package/dist/agent/renamePreview.js.map +1 -1
- package/dist/agent/search.d.ts +3 -1
- package/dist/agent/search.d.ts.map +1 -1
- package/dist/agent/search.js +103 -35
- package/dist/agent/search.js.map +1 -1
- package/dist/agent/semanticSymbols.d.ts.map +1 -1
- package/dist/agent/semanticSymbols.js +2 -1
- package/dist/agent/semanticSymbols.js.map +1 -1
- package/dist/agent/session.d.ts +4 -0
- package/dist/agent/session.d.ts.map +1 -1
- package/dist/agent/session.js +20 -7
- package/dist/agent/session.js.map +1 -1
- package/dist/agent-tools.d.ts +1 -1
- package/dist/agent-tools.d.ts.map +1 -1
- package/dist/agent-tools.js +12 -21
- package/dist/agent-tools.js.map +1 -1
- package/dist/bin/cli.js +29242 -25373
- package/dist/bin/queryIndexWorker.js +131 -42
- package/dist/bin/rawQueryWorker.js +270 -0
- package/dist/chunking/chunkFile.d.ts +5 -0
- package/dist/chunking/chunkFile.d.ts.map +1 -1
- package/dist/chunking/chunkFile.js +14 -15
- package/dist/chunking/chunkFile.js.map +1 -1
- package/dist/cli/affected.d.ts.map +1 -1
- package/dist/cli/affected.js +17 -10
- package/dist/cli/affected.js.map +1 -1
- package/dist/cli/callHierarchy.d.ts.map +1 -1
- package/dist/cli/callHierarchy.js +9 -2
- package/dist/cli/callHierarchy.js.map +1 -1
- package/dist/cli/commandTable.d.ts.map +1 -1
- package/dist/cli/commandTable.js +16 -4
- package/dist/cli/commandTable.js.map +1 -1
- package/dist/cli/doctor.d.ts +7 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +166 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/graph.d.ts +2 -1
- package/dist/cli/graph.d.ts.map +1 -1
- package/dist/cli/graph.js +60 -16
- package/dist/cli/graph.js.map +1 -1
- package/dist/cli/graphDelta.d.ts +2 -1
- package/dist/cli/graphDelta.d.ts.map +1 -1
- package/dist/cli/graphDelta.js +5 -0
- package/dist/cli/graphDelta.js.map +1 -1
- package/dist/cli/grep.d.ts +1 -1
- package/dist/cli/grep.d.ts.map +1 -1
- package/dist/cli/grep.js +14 -4
- package/dist/cli/grep.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 +17 -8
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/impact.d.ts +2 -1
- package/dist/cli/impact.d.ts.map +1 -1
- package/dist/cli/impact.js +5 -0
- package/dist/cli/impact.js.map +1 -1
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +3 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/indexPolicy.d.ts.map +1 -1
- package/dist/cli/indexPolicy.js.map +1 -1
- package/dist/cli/inspect.d.ts +2 -1
- package/dist/cli/inspect.d.ts.map +1 -1
- package/dist/cli/inspect.js +25 -13
- package/dist/cli/inspect.js.map +1 -1
- package/dist/cli/install.js +1 -1
- package/dist/cli/install.js.map +1 -1
- package/dist/cli/invocationContext.d.ts.map +1 -1
- package/dist/cli/invocationContext.js +3 -0
- package/dist/cli/invocationContext.js.map +1 -1
- package/dist/cli/links.d.ts +2 -0
- package/dist/cli/links.d.ts.map +1 -1
- package/dist/cli/links.js +1 -1
- package/dist/cli/links.js.map +1 -1
- package/dist/cli/navigation.d.ts +41 -1
- package/dist/cli/navigation.d.ts.map +1 -1
- package/dist/cli/navigation.js +4 -1
- package/dist/cli/navigation.js.map +1 -1
- package/dist/cli/options.d.ts.map +1 -1
- package/dist/cli/options.js +32 -11
- package/dist/cli/options.js.map +1 -1
- package/dist/cli/renamePreview.d.ts.map +1 -1
- package/dist/cli/renamePreview.js +7 -1
- package/dist/cli/renamePreview.js.map +1 -1
- package/dist/cli/review.d.ts +2 -1
- package/dist/cli/review.d.ts.map +1 -1
- package/dist/cli/review.js +5 -0
- package/dist/cli/review.js.map +1 -1
- package/dist/cli/rootPolicy.d.ts.map +1 -1
- package/dist/cli/rootPolicy.js +36 -3
- package/dist/cli/rootPolicy.js.map +1 -1
- package/dist/cli/skill.js +2 -2
- package/dist/cli/skill.js.map +1 -1
- package/dist/cli/sql.js +1 -1
- package/dist/cli/symbols.d.ts.map +1 -1
- package/dist/cli/symbols.js +4 -2
- package/dist/cli/symbols.js.map +1 -1
- package/dist/cli/viewer.d.ts.map +1 -1
- package/dist/cli/viewer.js +46 -34
- package/dist/cli/viewer.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +36 -16
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +35 -3
- package/dist/config.js.map +1 -1
- package/dist/documentLinks/check.d.ts +2 -1
- package/dist/documentLinks/check.d.ts.map +1 -1
- package/dist/documentLinks/check.js +22 -11
- package/dist/documentLinks/check.js.map +1 -1
- package/dist/duplicate-token-normalization.d.ts.map +1 -1
- package/dist/duplicate-token-normalization.js +10 -2
- package/dist/duplicate-token-normalization.js.map +1 -1
- package/dist/duplicates/scoring.d.ts +0 -10
- package/dist/duplicates/scoring.d.ts.map +1 -1
- package/dist/duplicates/scoring.js +9 -9
- package/dist/duplicates/scoring.js.map +1 -1
- package/dist/duplicates/types.d.ts +2 -0
- package/dist/duplicates/types.d.ts.map +1 -1
- package/dist/duplicates/unitCache.d.ts +15 -9
- package/dist/duplicates/unitCache.d.ts.map +1 -1
- package/dist/duplicates/unitCache.js +184 -33
- package/dist/duplicates/unitCache.js.map +1 -1
- package/dist/duplicates/units.d.ts +6 -15
- package/dist/duplicates/units.d.ts.map +1 -1
- package/dist/duplicates/units.js +42 -20
- package/dist/duplicates/units.js.map +1 -1
- package/dist/duplicates.d.ts.map +1 -1
- package/dist/duplicates.js +59 -0
- package/dist/duplicates.js.map +1 -1
- package/dist/frameworks/angularjs.d.ts.map +1 -1
- package/dist/frameworks/angularjs.js +18 -12
- package/dist/frameworks/angularjs.js.map +1 -1
- package/dist/graph-builder.d.ts.map +1 -1
- package/dist/graph-builder.js +12 -9
- package/dist/graph-builder.js.map +1 -1
- package/dist/graph-edge-collector.d.ts +1 -0
- package/dist/graph-edge-collector.d.ts.map +1 -1
- package/dist/graph-edge-collector.js +1 -1
- package/dist/graph-edge-collector.js.map +1 -1
- package/dist/graphs/grep.d.ts.map +1 -1
- package/dist/graphs/grep.js +7 -2
- package/dist/graphs/grep.js.map +1 -1
- package/dist/graphs/specifiers.d.ts.map +1 -1
- package/dist/graphs/specifiers.js +8 -2
- package/dist/graphs/specifiers.js.map +1 -1
- package/dist/graphs/symbol-graph-detailed.d.ts +10 -1
- package/dist/graphs/symbol-graph-detailed.d.ts.map +1 -1
- package/dist/graphs/symbol-graph-detailed.js +21 -5
- package/dist/graphs/symbol-graph-detailed.js.map +1 -1
- package/dist/impact/analyzer.d.ts.map +1 -1
- package/dist/impact/analyzer.js +19 -2
- package/dist/impact/analyzer.js.map +1 -1
- package/dist/impact/budgets.d.ts.map +1 -1
- package/dist/impact/budgets.js +5 -3
- package/dist/impact/budgets.js.map +1 -1
- package/dist/impact/call-compatibility/textScanner.d.ts +23 -0
- package/dist/impact/call-compatibility/textScanner.d.ts.map +1 -0
- package/dist/impact/call-compatibility/textScanner.js +615 -0
- package/dist/impact/call-compatibility/textScanner.js.map +1 -0
- package/dist/impact/callCompatibility.d.ts +8 -1
- package/dist/impact/callCompatibility.d.ts.map +1 -1
- package/dist/impact/callCompatibility.js +64 -587
- package/dist/impact/callCompatibility.js.map +1 -1
- package/dist/impact/context.d.ts.map +1 -1
- package/dist/impact/context.js +4 -1
- package/dist/impact/context.js.map +1 -1
- package/dist/impact/direct.d.ts +1 -1
- package/dist/impact/direct.d.ts.map +1 -1
- package/dist/impact/direct.js +7 -6
- package/dist/impact/direct.js.map +1 -1
- package/dist/impact/index.d.ts +6 -0
- package/dist/impact/index.d.ts.map +1 -1
- package/dist/impact/index.js +0 -8
- package/dist/impact/index.js.map +1 -1
- package/dist/impact/map.js +2 -2
- package/dist/impact/map.js.map +1 -1
- package/dist/impact/memberResolutionCoverage.d.ts.map +1 -1
- package/dist/impact/memberResolutionCoverage.js +5 -1
- package/dist/impact/memberResolutionCoverage.js.map +1 -1
- package/dist/impact/parse.d.ts.map +1 -1
- package/dist/impact/parse.js +108 -37
- package/dist/impact/parse.js.map +1 -1
- package/dist/impact/referenceCache.js +1 -1
- package/dist/impact/referenceCache.js.map +1 -1
- package/dist/impact/report-suggestions.d.ts.map +1 -1
- package/dist/impact/report-suggestions.js +347 -72
- package/dist/impact/report-suggestions.js.map +1 -1
- package/dist/impact/report.d.ts.map +1 -1
- package/dist/impact/report.js +13 -2
- package/dist/impact/report.js.map +1 -1
- package/dist/impact/reportCompact.d.ts.map +1 -1
- package/dist/impact/reportCompact.js +8 -0
- package/dist/impact/reportCompact.js.map +1 -1
- package/dist/impact/reportFull.d.ts.map +1 -1
- package/dist/impact/reportFull.js +1 -0
- package/dist/impact/reportFull.js.map +1 -1
- package/dist/impact/reportParts.d.ts +9 -0
- package/dist/impact/reportParts.d.ts.map +1 -1
- package/dist/impact/severity.d.ts +3 -2
- package/dist/impact/severity.d.ts.map +1 -1
- package/dist/impact/severity.js +16 -5
- package/dist/impact/severity.js.map +1 -1
- package/dist/impact/streaming.d.ts +32 -2
- package/dist/impact/streaming.d.ts.map +1 -1
- package/dist/impact/streaming.js +62 -3
- package/dist/impact/streaming.js.map +1 -1
- package/dist/impact/suggestions.d.ts.map +1 -1
- package/dist/impact/suggestions.js +1 -1
- package/dist/impact/suggestions.js.map +1 -1
- package/dist/impact/transitive.d.ts.map +1 -1
- package/dist/impact/transitive.js +13 -5
- package/dist/impact/transitive.js.map +1 -1
- package/dist/impact/types.d.ts +21 -20
- package/dist/impact/types.d.ts.map +1 -1
- package/dist/impact/types.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/build-cache/location.d.ts +19 -0
- package/dist/indexer/build-cache/location.d.ts.map +1 -0
- package/dist/indexer/build-cache/location.js +132 -0
- package/dist/indexer/build-cache/location.js.map +1 -0
- package/dist/indexer/build-cache/manifest.d.ts +14 -6
- package/dist/indexer/build-cache/manifest.d.ts.map +1 -1
- package/dist/indexer/build-cache/manifest.js +194 -30
- package/dist/indexer/build-cache/manifest.js.map +1 -1
- package/dist/indexer/build-cache/module-cache.d.ts +24 -2
- package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
- package/dist/indexer/build-cache/module-cache.js +98 -32
- package/dist/indexer/build-cache/module-cache.js.map +1 -1
- package/dist/indexer/build-cache/options.d.ts +3 -1
- package/dist/indexer/build-cache/options.d.ts.map +1 -1
- package/dist/indexer/build-cache/options.js +10 -2
- package/dist/indexer/build-cache/options.js.map +1 -1
- package/dist/indexer/build-cache/project-snapshot.d.ts +33 -13
- package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
- package/dist/indexer/build-cache/project-snapshot.js +472 -91
- package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
- package/dist/indexer/build-cache/reports.d.ts.map +1 -1
- package/dist/indexer/build-cache/reports.js +10 -1
- package/dist/indexer/build-cache/reports.js.map +1 -1
- package/dist/indexer/build-cache/resolver-environment.d.ts +9 -0
- package/dist/indexer/build-cache/resolver-environment.d.ts.map +1 -0
- package/dist/indexer/build-cache/resolver-environment.js +160 -0
- package/dist/indexer/build-cache/resolver-environment.js.map +1 -0
- package/dist/indexer/build-cache.d.ts +4 -3
- package/dist/indexer/build-cache.d.ts.map +1 -1
- package/dist/indexer/build-cache.js +4 -3
- 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 +268 -96
- package/dist/indexer/build-index.js.map +1 -1
- package/dist/indexer/build-manifest.d.ts +1 -0
- package/dist/indexer/build-manifest.d.ts.map +1 -1
- package/dist/indexer/build-manifest.js +15 -5
- package/dist/indexer/build-manifest.js.map +1 -1
- package/dist/indexer/build-workers.d.ts +1 -1
- package/dist/indexer/build-workers.d.ts.map +1 -1
- package/dist/indexer/build-workers.js +57 -42
- 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.map +1 -1
- package/dist/indexer/finalize.d.ts.map +1 -1
- package/dist/indexer/finalize.js +7 -4
- package/dist/indexer/finalize.js.map +1 -1
- package/dist/indexer/import-types.d.ts +8 -0
- package/dist/indexer/import-types.d.ts.map +1 -1
- package/dist/indexer/imports/jsTextImports.d.ts.map +1 -1
- package/dist/indexer/imports/jsTextImports.js +14 -6
- package/dist/indexer/imports/jsTextImports.js.map +1 -1
- package/dist/indexer/imports/languageSpecific.d.ts.map +1 -1
- package/dist/indexer/imports/languageSpecific.js +10 -5
- package/dist/indexer/imports/languageSpecific.js.map +1 -1
- package/dist/indexer/imports/nativeCaptures.d.ts.map +1 -1
- package/dist/indexer/imports/nativeCaptures.js +4 -1
- package/dist/indexer/imports/nativeCaptures.js.map +1 -1
- package/dist/indexer/imports/python.d.ts.map +1 -1
- package/dist/indexer/imports/python.js +19 -9
- package/dist/indexer/imports/python.js.map +1 -1
- package/dist/indexer/incremental-plan.d.ts +2 -1
- package/dist/indexer/incremental-plan.d.ts.map +1 -1
- package/dist/indexer/incremental-plan.js +7 -4
- package/dist/indexer/incremental-plan.js.map +1 -1
- package/dist/indexer/load-current-index.d.ts.map +1 -1
- package/dist/indexer/load-current-index.js.map +1 -1
- package/dist/indexer/locals-and-exports.d.ts.map +1 -1
- package/dist/indexer/locals-and-exports.js +77 -22
- package/dist/indexer/locals-and-exports.js.map +1 -1
- package/dist/indexer/navigation-goto.d.ts.map +1 -1
- package/dist/indexer/navigation-goto.js +26 -16
- package/dist/indexer/navigation-goto.js.map +1 -1
- package/dist/indexer/navigation-local.d.ts.map +1 -1
- package/dist/indexer/navigation-local.js +7 -4
- package/dist/indexer/navigation-local.js.map +1 -1
- package/dist/indexer/navigation-references.d.ts +1 -1
- package/dist/indexer/navigation-references.d.ts.map +1 -1
- package/dist/indexer/navigation-references.js +34 -17
- package/dist/indexer/navigation-references.js.map +1 -1
- package/dist/indexer/navigation-resolve.d.ts.map +1 -1
- package/dist/indexer/navigation-resolve.js +116 -53
- package/dist/indexer/navigation-resolve.js.map +1 -1
- package/dist/indexer/navigation.d.ts +2 -1
- package/dist/indexer/navigation.d.ts.map +1 -1
- package/dist/indexer/navigation.js +34 -20
- package/dist/indexer/navigation.js.map +1 -1
- package/dist/indexer/parse-context.d.ts +2 -2
- package/dist/indexer/parse-context.d.ts.map +1 -1
- package/dist/indexer/parse-context.js +25 -4
- package/dist/indexer/parse-context.js.map +1 -1
- package/dist/indexer/reference-context.d.ts +2 -2
- package/dist/indexer/reference-context.d.ts.map +1 -1
- package/dist/indexer/reference-context.js +4 -2
- package/dist/indexer/reference-context.js.map +1 -1
- package/dist/indexer/scope-types.d.ts +3 -0
- package/dist/indexer/scope-types.d.ts.map +1 -1
- package/dist/indexer/scope.js +37 -38
- package/dist/indexer/scope.js.map +1 -1
- package/dist/indexer/shared.d.ts.map +1 -1
- package/dist/indexer/shared.js +3 -1
- package/dist/indexer/shared.js.map +1 -1
- package/dist/indexer/type-hierarchy.d.ts.map +1 -1
- package/dist/indexer/type-hierarchy.js +12 -8
- package/dist/indexer/type-hierarchy.js.map +1 -1
- package/dist/indexer/types.d.ts +27 -1
- package/dist/indexer/types.d.ts.map +1 -1
- package/dist/indexer/workspace-symbols.d.ts.map +1 -1
- package/dist/indexer/workspace-symbols.js +5 -3
- package/dist/indexer/workspace-symbols.js.map +1 -1
- package/dist/installer/locks.d.ts +10 -0
- package/dist/installer/locks.d.ts.map +1 -0
- package/dist/installer/locks.js +232 -0
- package/dist/installer/locks.js.map +1 -0
- package/dist/installer/registry.d.ts.map +1 -1
- package/dist/installer/registry.js +75 -235
- package/dist/installer/registry.js.map +1 -1
- package/dist/languages/definitions/csharp.d.ts.map +1 -1
- package/dist/languages/definitions/csharp.js +8 -0
- 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 +3 -0
- package/dist/languages/definitions/java.js.map +1 -1
- package/dist/languages/definitions/python.d.ts.map +1 -1
- package/dist/languages/definitions/python.js +2 -0
- package/dist/languages/definitions/python.js.map +1 -1
- package/dist/languages/definitions/rust.d.ts.map +1 -1
- package/dist/languages/definitions/rust.js +2 -0
- package/dist/languages/definitions/rust.js.map +1 -1
- package/dist/languages/importStatementParsers.d.ts +2 -0
- package/dist/languages/importStatementParsers.d.ts.map +1 -1
- package/dist/languages/importStatementParsers.js +24 -10
- package/dist/languages/importStatementParsers.js.map +1 -1
- package/dist/mcp/http.d.ts +3 -1
- package/dist/mcp/http.d.ts.map +1 -1
- package/dist/mcp/http.js +69 -20
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/server.d.ts +58 -16
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +447 -140
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts +51 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +129 -3
- package/dist/mcp/tools.js.map +1 -1
- package/dist/native/byteIndex.d.ts +26 -0
- package/dist/native/byteIndex.d.ts.map +1 -0
- package/dist/native/byteIndex.js +70 -0
- package/dist/native/byteIndex.js.map +1 -0
- package/dist/native/projectedTree.d.ts +3 -2
- package/dist/native/projectedTree.d.ts.map +1 -1
- package/dist/native/projectedTree.js +6 -50
- package/dist/native/projectedTree.js.map +1 -1
- package/dist/native/queryResults.d.ts +7 -1
- package/dist/native/queryResults.d.ts.map +1 -1
- package/dist/native/queryResults.js +13 -5
- package/dist/native/queryResults.js.map +1 -1
- package/dist/review/candidates.d.ts.map +1 -1
- package/dist/review/candidates.js +4 -1
- package/dist/review/candidates.js.map +1 -1
- package/dist/review/changes.d.ts +2 -0
- package/dist/review/changes.d.ts.map +1 -1
- package/dist/review/changes.js +10 -0
- package/dist/review/changes.js.map +1 -1
- package/dist/review/deleted.d.ts.map +1 -1
- package/dist/review/deleted.js +20 -2
- package/dist/review/deleted.js.map +1 -1
- package/dist/review/summaries.d.ts +5 -0
- package/dist/review/summaries.d.ts.map +1 -1
- package/dist/review/summaries.js +32 -21
- package/dist/review/summaries.js.map +1 -1
- package/dist/review/types.d.ts +3 -1
- package/dist/review/types.d.ts.map +1 -1
- package/dist/review/types.js +8 -1
- package/dist/review/types.js.map +1 -1
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +14 -5
- package/dist/review.js.map +1 -1
- package/dist/session.d.ts +20 -4
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +76 -16
- package/dist/session.js.map +1 -1
- package/dist/sql/types.d.ts.map +1 -1
- package/dist/sqlite/query.d.ts +29 -0
- package/dist/sqlite/query.d.ts.map +1 -1
- package/dist/sqlite/query.js +98 -11
- package/dist/sqlite/query.js.map +1 -1
- package/dist/sqlite/rawQueryWorker.d.ts +22 -0
- package/dist/sqlite/rawQueryWorker.d.ts.map +1 -0
- package/dist/sqlite/rawQueryWorker.js +31 -0
- package/dist/sqlite/rawQueryWorker.js.map +1 -0
- package/dist/sqlite/rawQueryWorkerPool.d.ts +66 -0
- package/dist/sqlite/rawQueryWorkerPool.d.ts.map +1 -0
- package/dist/sqlite/rawQueryWorkerPool.js +142 -0
- package/dist/sqlite/rawQueryWorkerPool.js.map +1 -0
- package/dist/sqlite/schema.d.ts +2 -1
- package/dist/sqlite/schema.d.ts.map +1 -1
- package/dist/sqlite/schema.js +15 -1
- package/dist/sqlite/schema.js.map +1 -1
- package/dist/sqlite/write.d.ts.map +1 -1
- package/dist/sqlite/write.js +15 -0
- package/dist/sqlite/write.js.map +1 -1
- package/dist/sqlite-driver.d.ts +11 -0
- package/dist/sqlite-driver.d.ts.map +1 -1
- package/dist/sqlite-driver.js +28 -2
- package/dist/sqlite-driver.js.map +1 -1
- package/dist/sqlite.d.ts +1 -1
- package/dist/sqlite.d.ts.map +1 -1
- package/dist/sqlite.js +1 -1
- package/dist/sqlite.js.map +1 -1
- package/dist/util/bloomFilter.d.ts +3 -2
- package/dist/util/bloomFilter.d.ts.map +1 -1
- package/dist/util/bloomFilter.js +8 -8
- package/dist/util/bloomFilter.js.map +1 -1
- package/dist/util/concurrency.d.ts +1 -0
- package/dist/util/concurrency.d.ts.map +1 -1
- package/dist/util/concurrency.js +9 -2
- package/dist/util/concurrency.js.map +1 -1
- package/dist/util/confinedFile.d.ts +42 -2
- package/dist/util/confinedFile.d.ts.map +1 -1
- package/dist/util/confinedFile.js +114 -3
- package/dist/util/confinedFile.js.map +1 -1
- package/dist/util/errors.d.ts +2 -0
- package/dist/util/errors.d.ts.map +1 -1
- package/dist/util/errors.js +18 -0
- package/dist/util/errors.js.map +1 -1
- package/dist/util/git.d.ts +2 -0
- package/dist/util/git.d.ts.map +1 -1
- package/dist/util/git.js +174 -26
- package/dist/util/git.js.map +1 -1
- package/dist/util/identifiers.d.ts +75 -0
- package/dist/util/identifiers.d.ts.map +1 -0
- package/dist/util/identifiers.js +82 -0
- package/dist/util/identifiers.js.map +1 -0
- package/dist/util/paths.d.ts.map +1 -1
- package/dist/util/paths.js +45 -9
- package/dist/util/paths.js.map +1 -1
- package/dist/util/projectFiles.d.ts.map +1 -1
- package/dist/util/projectFiles.js +43 -14
- package/dist/util/projectFiles.js.map +1 -1
- package/dist/util/resolution/jvm.d.ts.map +1 -1
- package/dist/util/resolution/jvm.js +20 -9
- 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 +6 -5
- package/dist/util/resolution/php.js.map +1 -1
- package/dist/util/resolution/tsconfig.d.ts.map +1 -1
- package/dist/util/resolution/tsconfig.js +26 -12
- package/dist/util/resolution/tsconfig.js.map +1 -1
- package/dist/util/rustTestModules.d.ts.map +1 -1
- package/dist/util/rustTestModules.js +4 -2
- package/dist/util/rustTestModules.js.map +1 -1
- package/dist/util/specifiers.d.ts.map +1 -1
- package/dist/util/specifiers.js +10 -3
- package/dist/util/specifiers.js.map +1 -1
- package/dist/util/sqliteSchema.d.ts.map +1 -1
- package/dist/util/sqliteSchema.js +10 -1
- package/dist/util/sqliteSchema.js.map +1 -1
- package/dist/worker/nativeExtractWorker.d.ts +4 -2
- package/dist/worker/nativeExtractWorker.d.ts.map +1 -1
- package/dist/worker/nativeExtractWorker.js +12 -11
- package/dist/worker/nativeExtractWorker.js.map +1 -1
- package/docs/mcp.md +35 -14
- package/package.json +3 -3
|
@@ -6,29 +6,35 @@ import { buildGraphAdjacency } from "../../graphs/adjacency.js";
|
|
|
6
6
|
import { buildReferenceCandidateIndex } from "../reference-candidates.js";
|
|
7
7
|
import { BloomFilter, BloomFilterCache } from "../../util/bloomFilter.js";
|
|
8
8
|
import { summarizeAnalysis } from "../../analysisSummary.js";
|
|
9
|
-
import { fileIdentityKey, isFilePathWithinRoot, normalizePath } from "../../util/paths.js";
|
|
9
|
+
import { assertFilePathWithinRoot, fileIdentityKey, isFilePathWithinRoot, normalizePath } from "../../util/paths.js";
|
|
10
10
|
import { getNativeRuntimeFingerprint } from "../../native/treeSitterNative.js";
|
|
11
|
+
import { logWithLevel } from "../../logging.js";
|
|
11
12
|
import { SymbolKind } from "../types.js";
|
|
12
13
|
import { buildSymbolGraph, } from "../../graphs/symbol-graph.js";
|
|
13
14
|
import { getImplementationFingerprint, normalizeGraphOptions } from "./options.js";
|
|
14
|
-
import {
|
|
15
|
+
import { cacheAbsolutePath, cacheRelativePath, transformPersistedExportFromModule, } from "./module-cache.js";
|
|
16
|
+
import { cacheRoot } from "./location.js";
|
|
15
17
|
const SNAPSHOT_SYMBOL_KINDS = new Set(Object.values(SymbolKind));
|
|
16
|
-
const PROJECT_SNAPSHOT_VERSION =
|
|
18
|
+
const PROJECT_SNAPSHOT_VERSION = 9;
|
|
19
|
+
export const BLOOM_FILTER_SNAPSHOT_VERSION = 4;
|
|
20
|
+
export const BLOOM_FILTER_SNAPSHOT_FILENAME = "bloom-filters.json";
|
|
17
21
|
const BLOOM_FILTER_MIN_SIZE = 1_000;
|
|
18
22
|
const BLOOM_FILTER_MAX_SIZE = 1_000_000;
|
|
19
23
|
const BLOOM_FILTER_MIN_HASH_COUNT = 1;
|
|
20
24
|
const BLOOM_FILTER_MAX_HASH_COUNT = 10;
|
|
21
|
-
const DETAILED_SYMBOL_GRAPH_SNAPSHOT_VERSION =
|
|
25
|
+
const DETAILED_SYMBOL_GRAPH_SNAPSHOT_VERSION = 3;
|
|
22
26
|
const DETAILED_SYMBOL_GRAPH_SNAPSHOT_FILENAME = "detailed-symbol-graph.json";
|
|
23
27
|
const SNAPSHOT_TEMP_RETENTION_MS = 24 * 60 * 60 * 1_000;
|
|
24
28
|
const SNAPSHOT_TEMP_SUFFIX = ".tmp";
|
|
25
29
|
const MAX_SNAPSHOT_CACHE_ENTRIES = 32;
|
|
26
30
|
const parsedSnapshotCache = new Map();
|
|
31
|
+
const transformedSnapshotCache = new Map();
|
|
32
|
+
const transformedSnapshotModulesCache = new Map();
|
|
27
33
|
const detailedSymbolGraphCache = new Map();
|
|
28
|
-
export function projectSnapshotFilesSignature(entries) {
|
|
34
|
+
export function projectSnapshotFilesSignature(entries, projectRoot) {
|
|
29
35
|
const hash = createHash("sha256");
|
|
30
36
|
for (const [file, entry] of [...entries.entries()].sort(([left], [right]) => compareSnapshotPath(left, right))) {
|
|
31
|
-
hash.update(file);
|
|
37
|
+
hash.update(projectRoot ? cacheRelativePath(projectRoot, file) : file);
|
|
32
38
|
hash.update("\0");
|
|
33
39
|
hash.update(entry.sig);
|
|
34
40
|
hash.update("\0");
|
|
@@ -55,8 +61,115 @@ export function createProjectSnapshotIdentity(filesSignature, opts) {
|
|
|
55
61
|
function serializedProjectRoot(projectRoot) {
|
|
56
62
|
return normalizePath(path.resolve(projectRoot));
|
|
57
63
|
}
|
|
58
|
-
function
|
|
59
|
-
|
|
64
|
+
function transformPath(root, value, toRelative) {
|
|
65
|
+
if (toRelative) {
|
|
66
|
+
return path.isAbsolute(value) ? cacheRelativePath(root, value) : value;
|
|
67
|
+
}
|
|
68
|
+
return assertFilePathWithinRoot(root, cacheAbsolutePath(root, value), "Persisted cache path");
|
|
69
|
+
}
|
|
70
|
+
function transformHandle(root, value, toRelative) {
|
|
71
|
+
const separator = value.indexOf("::");
|
|
72
|
+
if (separator < 0)
|
|
73
|
+
return transformPath(root, value, toRelative);
|
|
74
|
+
const file = value.slice(0, separator);
|
|
75
|
+
return `${transformPath(root, file, toRelative)}${value.slice(separator)}`;
|
|
76
|
+
}
|
|
77
|
+
function transformModule(root, module, toRelative) {
|
|
78
|
+
const copy = structuredClone(module);
|
|
79
|
+
const file = (value) => transformPath(root, value, toRelative);
|
|
80
|
+
copy.file = file(copy.file);
|
|
81
|
+
for (const local of copy.locals)
|
|
82
|
+
local.file = file(local.file);
|
|
83
|
+
for (const entry of copy.exports) {
|
|
84
|
+
if (entry.type === "local") {
|
|
85
|
+
entry.target.file = file(entry.target.file);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
transformPersistedExportFromModule(root, entry, toRelative);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
for (const binding of copy.imports) {
|
|
92
|
+
if (typeof binding.resolved === "string")
|
|
93
|
+
binding.resolved = file(binding.resolved);
|
|
94
|
+
}
|
|
95
|
+
return copy;
|
|
96
|
+
}
|
|
97
|
+
function transformSnapshotPaths(payload, root, toRelative) {
|
|
98
|
+
const copy = structuredClone(payload);
|
|
99
|
+
copy.graph.nodes = copy.graph.nodes.map((node) => transformPath(root, node, toRelative));
|
|
100
|
+
copy.graph.edges = copy.graph.edges.map((edge) => ({
|
|
101
|
+
...edge,
|
|
102
|
+
from: transformPath(root, edge.from, toRelative),
|
|
103
|
+
to: edge.to.type === "file" ? { ...edge.to, path: transformPath(root, edge.to.path, toRelative) } : edge.to,
|
|
104
|
+
}));
|
|
105
|
+
copy.modules = copy.modules.map((module) => transformModule(root, module, toRelative));
|
|
106
|
+
if (copy.projectFiles) {
|
|
107
|
+
copy.projectFiles = copy.projectFiles.map((file) => ({
|
|
108
|
+
...file,
|
|
109
|
+
path: transformPath(root, file.path, toRelative),
|
|
110
|
+
projectRoot: transformPath(root, file.projectRoot, toRelative),
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
if (copy.bloomFilters) {
|
|
114
|
+
const bloomFilters = {};
|
|
115
|
+
for (const [file, filter] of Object.entries(copy.bloomFilters)) {
|
|
116
|
+
bloomFilters[transformPath(root, file, toRelative)] = filter;
|
|
117
|
+
}
|
|
118
|
+
copy.bloomFilters = bloomFilters;
|
|
119
|
+
}
|
|
120
|
+
const fileSignatures = {};
|
|
121
|
+
for (const [file, signature] of Object.entries(copy.fileSignatures ?? {})) {
|
|
122
|
+
fileSignatures[transformPath(root, file, toRelative)] = signature;
|
|
123
|
+
}
|
|
124
|
+
copy.fileSignatures = fileSignatures;
|
|
125
|
+
return copy;
|
|
126
|
+
}
|
|
127
|
+
function migrateProjectSnapshotPayload(value, currentRoot) {
|
|
128
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
129
|
+
return value;
|
|
130
|
+
const payload = value;
|
|
131
|
+
if ((payload.version !== 4 && payload.version !== 5) || typeof payload.projectRoot !== "string")
|
|
132
|
+
return value;
|
|
133
|
+
const relative = transformSnapshotPaths(value, payload.projectRoot, true);
|
|
134
|
+
const migrated = transformSnapshotPaths(relative, currentRoot, false);
|
|
135
|
+
migrated.version = PROJECT_SNAPSHOT_VERSION;
|
|
136
|
+
migrated.projectRoot = serializedProjectRoot(currentRoot);
|
|
137
|
+
return migrated;
|
|
138
|
+
}
|
|
139
|
+
function transformDetailedGraph(graph, root, toRelative) {
|
|
140
|
+
return {
|
|
141
|
+
nodes: graph.nodes.map((node) => {
|
|
142
|
+
const file = transformPath(root, node.file, toRelative);
|
|
143
|
+
return { ...node, file, id: transformHandle(root, node.id, toRelative) };
|
|
144
|
+
}),
|
|
145
|
+
edges: graph.edges.map((edge) => ({
|
|
146
|
+
...edge,
|
|
147
|
+
from: transformHandle(root, edge.from, toRelative),
|
|
148
|
+
to: transformHandle(root, edge.to, toRelative),
|
|
149
|
+
...(edge.site
|
|
150
|
+
? {
|
|
151
|
+
site: {
|
|
152
|
+
...edge.site,
|
|
153
|
+
file: transformPath(root, edge.site.file, toRelative),
|
|
154
|
+
},
|
|
155
|
+
}
|
|
156
|
+
: {}),
|
|
157
|
+
})),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function migrateDetailedSymbolGraphPayload(value, currentRoot) {
|
|
161
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
162
|
+
return value;
|
|
163
|
+
const payload = value;
|
|
164
|
+
if (payload.version !== 2 || typeof payload.projectRoot !== "string" || !payload.graph)
|
|
165
|
+
return value;
|
|
166
|
+
const relativeGraph = transformDetailedGraph(payload.graph, payload.projectRoot, true);
|
|
167
|
+
return {
|
|
168
|
+
...payload,
|
|
169
|
+
version: DETAILED_SYMBOL_GRAPH_SNAPSHOT_VERSION,
|
|
170
|
+
projectRoot: serializedProjectRoot(currentRoot),
|
|
171
|
+
graph: transformDetailedGraph(relativeGraph, currentRoot, false),
|
|
172
|
+
};
|
|
60
173
|
}
|
|
61
174
|
function compareSnapshotPath(left, right) {
|
|
62
175
|
if (left < right)
|
|
@@ -153,17 +266,30 @@ function materializeDetailedSymbolGraph(payload) {
|
|
|
153
266
|
function decodeSnapshotPayload(compressed) {
|
|
154
267
|
return JSON.parse(brotliDecompressSync(compressed).toString("utf8"));
|
|
155
268
|
}
|
|
269
|
+
function recordSnapshotCorruption(report, artifact, reason, logLevel) {
|
|
270
|
+
if (report) {
|
|
271
|
+
report.manifest ??= { used: true, reused: false };
|
|
272
|
+
report.manifest.corruptions ??= [];
|
|
273
|
+
if (!report.manifest.corruptions.some((entry) => entry.artifact === artifact)) {
|
|
274
|
+
report.manifest.corruptions.push({ artifact, reason });
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
logWithLevel(logLevel, "warn", `Warning: Corrupt cache artifact ${artifact}: ${reason}`);
|
|
278
|
+
}
|
|
279
|
+
function isMissingArtifactError(error) {
|
|
280
|
+
return !!error && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
281
|
+
}
|
|
156
282
|
async function readParsedSnapshot(snapshotPath) {
|
|
157
283
|
const before = await snapshotFileIdentity(snapshotPath);
|
|
158
284
|
const cached = parsedSnapshotCache.get(snapshotPath);
|
|
159
285
|
if (cached && sameSnapshotFileIdentity(cached.identity, before)) {
|
|
160
286
|
setBoundedSnapshotCache(parsedSnapshotCache, snapshotPath, cached);
|
|
161
|
-
return { identity: cached.identity, payload:
|
|
287
|
+
return { identity: cached.identity, payload: cached.payload };
|
|
162
288
|
}
|
|
163
289
|
const compressed = Buffer.from(await fsp.readFile(snapshotPath));
|
|
164
290
|
const payload = decodeSnapshotPayload(compressed);
|
|
165
291
|
const after = await snapshotFileIdentity(snapshotPath);
|
|
166
|
-
const entry = { identity: before, compressed };
|
|
292
|
+
const entry = { identity: before, compressed, payload };
|
|
167
293
|
if (sameSnapshotFileIdentity(before, after)) {
|
|
168
294
|
setBoundedSnapshotCache(parsedSnapshotCache, snapshotPath, entry);
|
|
169
295
|
}
|
|
@@ -172,6 +298,55 @@ async function readParsedSnapshot(snapshotPath) {
|
|
|
172
298
|
}
|
|
173
299
|
return { identity: before, payload };
|
|
174
300
|
}
|
|
301
|
+
function transformCachedProjectSnapshot(snapshotPath, identity, rawPayload, projectRoot) {
|
|
302
|
+
const cached = transformedSnapshotCache.get(snapshotPath);
|
|
303
|
+
if (cached && cached.root === projectRoot && sameSnapshotFileIdentity(cached.identity, identity)) {
|
|
304
|
+
setBoundedSnapshotCache(transformedSnapshotCache, snapshotPath, cached);
|
|
305
|
+
return structuredClone(cached.payload);
|
|
306
|
+
}
|
|
307
|
+
const migratedPayload = migrateProjectSnapshotPayload(rawPayload, projectRoot);
|
|
308
|
+
const payload = migratedPayload && typeof migratedPayload === "object" && !Array.isArray(migratedPayload)
|
|
309
|
+
? transformSnapshotPaths(migratedPayload, projectRoot, false)
|
|
310
|
+
: migratedPayload;
|
|
311
|
+
setBoundedSnapshotCache(transformedSnapshotCache, snapshotPath, { identity, root: projectRoot, payload });
|
|
312
|
+
return structuredClone(payload);
|
|
313
|
+
}
|
|
314
|
+
function transformCachedProjectSnapshotModules(snapshotPath, identity, rawPayload, projectRoot) {
|
|
315
|
+
const cached = transformedSnapshotModulesCache.get(snapshotPath);
|
|
316
|
+
if (cached && cached.root === projectRoot && sameSnapshotFileIdentity(cached.identity, identity)) {
|
|
317
|
+
setBoundedSnapshotCache(transformedSnapshotModulesCache, snapshotPath, cached);
|
|
318
|
+
return structuredClone(cached.payload);
|
|
319
|
+
}
|
|
320
|
+
const migratedPayload = migrateProjectSnapshotPayload(rawPayload, projectRoot);
|
|
321
|
+
if (!migratedPayload || typeof migratedPayload !== "object" || Array.isArray(migratedPayload)) {
|
|
322
|
+
return migratedPayload;
|
|
323
|
+
}
|
|
324
|
+
const payload = migratedPayload;
|
|
325
|
+
if (!Array.isArray(payload.modules) || !payload.fileSignatures || typeof payload.fileSignatures !== "object") {
|
|
326
|
+
return migratedPayload;
|
|
327
|
+
}
|
|
328
|
+
const modules = structuredClone(payload.modules).map((module) => transformModule(projectRoot, module, false));
|
|
329
|
+
const fileSignatures = {};
|
|
330
|
+
for (const [file, signature] of Object.entries(payload.fileSignatures)) {
|
|
331
|
+
fileSignatures[transformPath(projectRoot, file, false)] = signature;
|
|
332
|
+
}
|
|
333
|
+
const transformed = {
|
|
334
|
+
version: payload.version ?? PROJECT_SNAPSHOT_VERSION,
|
|
335
|
+
filesSignature: payload.filesSignature ?? "",
|
|
336
|
+
projectRoot: serializedProjectRoot(projectRoot),
|
|
337
|
+
...(payload.nativeMode !== undefined ? { nativeMode: payload.nativeMode } : {}),
|
|
338
|
+
nativeRuntimeFingerprint: payload.nativeRuntimeFingerprint ?? "",
|
|
339
|
+
implementationFingerprint: payload.implementationFingerprint ?? "",
|
|
340
|
+
modules,
|
|
341
|
+
fileSignatures,
|
|
342
|
+
};
|
|
343
|
+
setBoundedSnapshotCache(transformedSnapshotModulesCache, snapshotPath, {
|
|
344
|
+
identity,
|
|
345
|
+
root: projectRoot,
|
|
346
|
+
payload: transformed,
|
|
347
|
+
});
|
|
348
|
+
return structuredClone(transformed);
|
|
349
|
+
}
|
|
175
350
|
function projectIndexManifestEntries(entries) {
|
|
176
351
|
return new Map(Array.from(entries, ([file, entry]) => [
|
|
177
352
|
file,
|
|
@@ -181,24 +356,22 @@ function projectIndexManifestEntries(entries) {
|
|
|
181
356
|
},
|
|
182
357
|
]));
|
|
183
358
|
}
|
|
184
|
-
export async function tryLoadProjectIndexSnapshot(projectRoot, opts, manifestEntries) {
|
|
185
|
-
const filesSignature = projectSnapshotFilesSignature(manifestEntries);
|
|
359
|
+
export async function tryLoadProjectIndexSnapshot(projectRoot, opts, manifestEntries, report) {
|
|
360
|
+
const filesSignature = projectSnapshotFilesSignature(manifestEntries, projectRoot);
|
|
186
361
|
if ((opts?.cache ?? "off") !== "disk")
|
|
187
362
|
return null;
|
|
188
363
|
try {
|
|
189
|
-
const
|
|
364
|
+
const parsedSnapshot = await readParsedSnapshot(projectSnapshotPath(projectRoot, opts));
|
|
365
|
+
const payload = transformCachedProjectSnapshot(projectSnapshotPath(projectRoot, opts), parsedSnapshot.identity, parsedSnapshot.payload, projectRoot);
|
|
190
366
|
const nativeRuntimeFingerprint = getNativeRuntimeFingerprint(opts?.native);
|
|
191
367
|
const implementationFingerprint = getImplementationFingerprint();
|
|
192
|
-
if (!isProjectIndexSnapshotPayload(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
rawPayload.implementationFingerprint !== implementationFingerprint) {
|
|
368
|
+
if (!isProjectIndexSnapshotPayload(payload) ||
|
|
369
|
+
payload.filesSignature !== filesSignature ||
|
|
370
|
+
payload.nativeMode !== normalizedSnapshotNativeMode(opts?.native) ||
|
|
371
|
+
payload.nativeRuntimeFingerprint !== nativeRuntimeFingerprint ||
|
|
372
|
+
payload.implementationFingerprint !== implementationFingerprint) {
|
|
198
373
|
return null;
|
|
199
374
|
}
|
|
200
|
-
// Payload is freshly JSON.parsed from memoized compressed bytes (no deep clone).
|
|
201
|
-
const payload = rawPayload;
|
|
202
375
|
const graph = {
|
|
203
376
|
nodes: new Set(payload.graph.nodes),
|
|
204
377
|
edges: payload.graph.edges,
|
|
@@ -211,11 +384,12 @@ export async function tryLoadProjectIndexSnapshot(projectRoot, opts, manifestEnt
|
|
|
211
384
|
modules,
|
|
212
385
|
byFile: modules,
|
|
213
386
|
projectRoot: serializedProjectRoot(projectRoot),
|
|
387
|
+
...(payload.languageExtensions ? { languageExtensions: payload.languageExtensions } : {}),
|
|
214
388
|
...(payload.nativeMode ? { nativeMode: payload.nativeMode } : {}),
|
|
215
389
|
exportCache: new Map(),
|
|
216
390
|
scopeCache: new Map(),
|
|
217
391
|
...(shouldHydrateBloomFilters && payload.bloomFilters
|
|
218
|
-
? { bloomFilters: deserializeBloomFilterCache(payload.bloomFilters) }
|
|
392
|
+
? { bloomFilters: deserializeBloomFilterCache(payload.bloomFilters, projectRoot) }
|
|
219
393
|
: {}),
|
|
220
394
|
...(payload.projectFiles ? { projectFiles: payload.projectFiles } : {}),
|
|
221
395
|
referenceCandidates: buildReferenceCandidateIndex(modules),
|
|
@@ -231,56 +405,157 @@ export async function tryLoadProjectIndexSnapshot(projectRoot, opts, manifestEnt
|
|
|
231
405
|
...(payload.analysisReport ? { analysisReport: payload.analysisReport } : {}),
|
|
232
406
|
};
|
|
233
407
|
}
|
|
234
|
-
catch {
|
|
408
|
+
catch (error) {
|
|
409
|
+
if (!isMissingArtifactError(error)) {
|
|
410
|
+
recordSnapshotCorruption(report, projectSnapshotPath(projectRoot, opts), String(error), opts?.logLevel);
|
|
411
|
+
}
|
|
235
412
|
return null;
|
|
236
413
|
}
|
|
237
414
|
}
|
|
238
415
|
/**
|
|
239
|
-
* Load only
|
|
240
|
-
* the
|
|
241
|
-
* Bloom filters are a pure function of a file's text, so a filter persisted for a given file
|
|
242
|
-
* is safe to reuse after its snapshot's root and implementation fingerprints are validated.
|
|
243
|
-
* Only the bloom section is then read, so a corrupt payload is rejected without walking
|
|
244
|
-
* `graph.edges` / `modules`. Returns `null` when disk caching is off, `useBloomFilters` is
|
|
245
|
-
* disabled, or no valid snapshot with bloom data exists.
|
|
416
|
+
* Load only modules and signatures from the last-written project snapshot. Path transforms avoid
|
|
417
|
+
* cloning the graph and project metadata, while each returned module remains caller-owned.
|
|
246
418
|
*/
|
|
247
|
-
export async function
|
|
419
|
+
export async function tryLoadProjectSnapshotModules(projectRoot, opts, fileSignatures, report) {
|
|
420
|
+
if ((opts?.cache ?? "off") !== "disk")
|
|
421
|
+
return null;
|
|
422
|
+
try {
|
|
423
|
+
const parsedSnapshot = await readParsedSnapshot(projectSnapshotPath(projectRoot, opts));
|
|
424
|
+
const payload = transformCachedProjectSnapshotModules(projectSnapshotPath(projectRoot, opts), parsedSnapshot.identity, parsedSnapshot.payload, projectRoot);
|
|
425
|
+
const nativeRuntimeFingerprint = getNativeRuntimeFingerprint(opts?.native);
|
|
426
|
+
const implementationFingerprint = getImplementationFingerprint();
|
|
427
|
+
if (!isProjectSnapshotModulesPayload(payload) ||
|
|
428
|
+
payload.nativeMode !== normalizedSnapshotNativeMode(opts?.native) ||
|
|
429
|
+
payload.nativeRuntimeFingerprint !== nativeRuntimeFingerprint ||
|
|
430
|
+
payload.implementationFingerprint !== implementationFingerprint) {
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
const normalizedFileSignatures = new Map(Object.entries(payload.fileSignatures).map(([file, signature]) => [fileIdentityKey(file), signature]));
|
|
434
|
+
const normalizedCurrentSignatures = new Map(Array.from(fileSignatures, ([file, signature]) => [fileIdentityKey(file), signature]));
|
|
435
|
+
const modules = new Map();
|
|
436
|
+
for (const mod of payload.modules) {
|
|
437
|
+
const moduleKey = fileIdentityKey(mod.file);
|
|
438
|
+
const signature = normalizedCurrentSignatures.get(moduleKey);
|
|
439
|
+
const snapshotSignature = normalizedFileSignatures.get(moduleKey);
|
|
440
|
+
if (!signature || !snapshotSignature || !snapshotSignatureMatches(snapshotSignature, signature))
|
|
441
|
+
continue;
|
|
442
|
+
modules.set(moduleKey, mod);
|
|
443
|
+
}
|
|
444
|
+
return modules;
|
|
445
|
+
}
|
|
446
|
+
catch (error) {
|
|
447
|
+
if (!isMissingArtifactError(error)) {
|
|
448
|
+
recordSnapshotCorruption(report, projectSnapshotPath(projectRoot, opts), String(error), opts?.logLevel);
|
|
449
|
+
}
|
|
450
|
+
return null;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
export async function tryLoadPersistedBloomFilters(projectRoot, opts, report) {
|
|
248
454
|
if ((opts?.cache ?? "off") !== "disk" || (opts?.useBloomFilters ?? true) === false)
|
|
249
455
|
return null;
|
|
456
|
+
try {
|
|
457
|
+
const sidecarPath = bloomFilterSnapshotPath(projectRoot, opts);
|
|
458
|
+
const sidecarParsed = (await readParsedSnapshot(sidecarPath)).payload;
|
|
459
|
+
const sidecarBloom = persistedBloomFiltersFromSidecar(sidecarParsed, projectRoot);
|
|
460
|
+
if (sidecarBloom) {
|
|
461
|
+
return createPersistedBloomFilters(sidecarBloom.bloomFilters, sidecarBloom.fileSignatures, projectRoot);
|
|
462
|
+
}
|
|
463
|
+
recordSnapshotCorruption(report, sidecarPath, "invalid bloom filter payload", opts?.logLevel);
|
|
464
|
+
}
|
|
465
|
+
catch (error) {
|
|
466
|
+
const isMissing = error && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
467
|
+
if (!isMissing) {
|
|
468
|
+
recordSnapshotCorruption(report, bloomFilterSnapshotPath(projectRoot, opts), String(error), opts?.logLevel);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
250
471
|
try {
|
|
251
472
|
const payload = (await readParsedSnapshot(projectSnapshotPath(projectRoot, opts))).payload;
|
|
252
473
|
const bloomFilters = persistedBloomFiltersFromSnapshot(payload, projectRoot);
|
|
253
474
|
if (!bloomFilters)
|
|
254
475
|
return null;
|
|
255
|
-
return
|
|
476
|
+
return createPersistedBloomFilters(bloomFilters.bloomFilters, bloomFilters.fileSignatures, projectRoot);
|
|
256
477
|
}
|
|
257
|
-
catch {
|
|
478
|
+
catch (error) {
|
|
479
|
+
const isMissing = error && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
480
|
+
if (!isMissing) {
|
|
481
|
+
recordSnapshotCorruption(report, projectSnapshotPath(projectRoot, opts), String(error), opts?.logLevel);
|
|
482
|
+
}
|
|
258
483
|
return null;
|
|
259
484
|
}
|
|
260
485
|
}
|
|
261
|
-
|
|
262
|
-
function persistedBloomFiltersFromSnapshot(value, projectRoot) {
|
|
486
|
+
function persistedBloomFiltersFromSidecar(value, projectRoot) {
|
|
263
487
|
if (!value || typeof value !== "object")
|
|
264
488
|
return null;
|
|
265
489
|
const payload = value;
|
|
490
|
+
if (payload.version !== BLOOM_FILTER_SNAPSHOT_VERSION ||
|
|
491
|
+
typeof payload.projectRoot !== "string" ||
|
|
492
|
+
payload.implementationFingerprint !== getImplementationFingerprint() ||
|
|
493
|
+
typeof payload.projectSnapshotIdentity !== "string" ||
|
|
494
|
+
!/^[a-f0-9]{64}$/.test(payload.projectSnapshotIdentity)) {
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
497
|
+
const bloomFilters = payload.bloomFilters;
|
|
498
|
+
const fileSignatures = payload.fileSignatures;
|
|
499
|
+
if (!isSerializedBloomFilterRecord(bloomFilters) || !isSnapshotFileSignatureRecord(fileSignatures)) {
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
return { bloomFilters, fileSignatures };
|
|
503
|
+
}
|
|
504
|
+
/** Light validation for bloom hydration: snapshot version, root identity, and bloom section only. */
|
|
505
|
+
function persistedBloomFiltersFromSnapshot(value, projectRoot) {
|
|
506
|
+
const migrated = migrateProjectSnapshotPayload(value, projectRoot);
|
|
507
|
+
if (!migrated || typeof migrated !== "object")
|
|
508
|
+
return null;
|
|
509
|
+
const payload = migrated;
|
|
266
510
|
if (payload.version !== PROJECT_SNAPSHOT_VERSION ||
|
|
267
511
|
typeof payload.projectRoot !== "string" ||
|
|
268
|
-
!projectRootMatches(projectRoot, payload.projectRoot) ||
|
|
269
512
|
payload.implementationFingerprint !== getImplementationFingerprint()) {
|
|
270
513
|
return null;
|
|
271
514
|
}
|
|
272
|
-
|
|
515
|
+
const bloomFilters = payload.bloomFilters;
|
|
516
|
+
const fileSignatures = payload.fileSignatures;
|
|
517
|
+
if (!isSerializedBloomFilterRecord(bloomFilters) || !isSnapshotFileSignatureRecord(fileSignatures)) {
|
|
273
518
|
return null;
|
|
274
|
-
|
|
519
|
+
}
|
|
520
|
+
return { bloomFilters, fileSignatures };
|
|
521
|
+
}
|
|
522
|
+
function createPersistedBloomFilters(bloomFilters, fileSignatures, projectRoot) {
|
|
523
|
+
const filters = deserializeBloomFilterCache(bloomFilters, projectRoot);
|
|
524
|
+
const signatures = new Map(Object.entries(fileSignatures).map(([file, signature]) => [
|
|
525
|
+
fileIdentityKey(cacheAbsolutePath(projectRoot, file)),
|
|
526
|
+
signature,
|
|
527
|
+
]));
|
|
528
|
+
return {
|
|
529
|
+
get: (file, signature) => {
|
|
530
|
+
const persistedSignature = signatures.get(fileIdentityKey(file));
|
|
531
|
+
if (!persistedSignature || !snapshotSignatureMatches(persistedSignature, signature))
|
|
532
|
+
return undefined;
|
|
533
|
+
return filters.get(file);
|
|
534
|
+
},
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
function snapshotSignatureMatches(snapshotSignature, currentSignature) {
|
|
538
|
+
const matchingGitSignature = !!snapshotSignature.gitSig && !!currentSignature.gitSig && snapshotSignature.gitSig === currentSignature.gitSig;
|
|
539
|
+
if (matchingGitSignature)
|
|
540
|
+
return true;
|
|
541
|
+
// `cacheSig` is git- or content-hash-derived (forced whenever caching is enabled without a git
|
|
542
|
+
// signature; see `fileSignature()`), so when both sides have it, it is a strictly stronger and
|
|
543
|
+
// authoritative identity check than the cheap `mtime:size` `sig`. Comparing bare `sig` alone
|
|
544
|
+
// would wrongly treat a same-size edit whose mtime got restored as unchanged.
|
|
545
|
+
if (snapshotSignature.cacheSig !== undefined && currentSignature.cacheSig !== undefined) {
|
|
546
|
+
return snapshotSignature.cacheSig === currentSignature.cacheSig;
|
|
547
|
+
}
|
|
548
|
+
return snapshotSignature.sig === currentSignature.sig;
|
|
275
549
|
}
|
|
276
550
|
export async function writeProjectIndexSnapshot(projectRoot, opts, index, filesSignature) {
|
|
277
551
|
const projectSnapshotIdentity = createProjectSnapshotIdentity(filesSignature, opts);
|
|
552
|
+
const fileSignatures = serializeSnapshotFileSignatures(index.manifestEntries, projectRoot);
|
|
278
553
|
const serializedBloomFilters = index.bloomFilters
|
|
279
|
-
? serializeBloomFilterCache(index.bloomFilters, Array.from(index.byFile.values(), (module) => module.file))
|
|
554
|
+
? serializeBloomFilterCache(index.bloomFilters, Array.from(index.byFile.values(), (module) => module.file), projectRoot)
|
|
280
555
|
: undefined;
|
|
281
556
|
const snapshotAnalysisReport = analysisReportFromBuildReport(index.buildReport);
|
|
282
557
|
const snapshotAnalysis = index.buildReport ? summarizeAnalysis({ index, report: index.buildReport }) : index.analysis;
|
|
283
|
-
const payload = {
|
|
558
|
+
const payload = transformSnapshotPaths({
|
|
284
559
|
version: PROJECT_SNAPSHOT_VERSION,
|
|
285
560
|
filesSignature,
|
|
286
561
|
projectRoot: serializedProjectRoot(projectRoot),
|
|
@@ -291,6 +566,8 @@ export async function writeProjectIndexSnapshot(projectRoot, opts, index, filesS
|
|
|
291
566
|
edges: index.graph.edges,
|
|
292
567
|
},
|
|
293
568
|
modules: [...index.byFile.values()],
|
|
569
|
+
fileSignatures,
|
|
570
|
+
...(index.languageExtensions ? { languageExtensions: index.languageExtensions } : {}),
|
|
294
571
|
...(normalizedSnapshotNativeMode(index.nativeMode)
|
|
295
572
|
? { nativeMode: normalizedSnapshotNativeMode(index.nativeMode) }
|
|
296
573
|
: {}),
|
|
@@ -298,7 +575,7 @@ export async function writeProjectIndexSnapshot(projectRoot, opts, index, filesS
|
|
|
298
575
|
...(serializedBloomFilters ? { bloomFilters: serializedBloomFilters } : {}),
|
|
299
576
|
...(snapshotAnalysis ? { analysis: snapshotAnalysis } : {}),
|
|
300
577
|
...(snapshotAnalysisReport ? { analysisReport: snapshotAnalysisReport } : {}),
|
|
301
|
-
};
|
|
578
|
+
}, projectRoot, true);
|
|
302
579
|
try {
|
|
303
580
|
const snapshotPath = projectSnapshotPath(projectRoot, opts);
|
|
304
581
|
const compressed = brotliCompressSync(JSON.stringify(payload), {
|
|
@@ -306,8 +583,36 @@ export async function writeProjectIndexSnapshot(projectRoot, opts, index, filesS
|
|
|
306
583
|
});
|
|
307
584
|
await writeSnapshotAtomically(snapshotPath, compressed);
|
|
308
585
|
const identity = await snapshotFileIdentity(snapshotPath);
|
|
309
|
-
|
|
586
|
+
transformedSnapshotCache.delete(snapshotPath);
|
|
587
|
+
transformedSnapshotModulesCache.delete(snapshotPath);
|
|
588
|
+
setBoundedSnapshotCache(parsedSnapshotCache, snapshotPath, { identity, compressed, payload });
|
|
310
589
|
index.projectSnapshotIdentity = projectSnapshotIdentity;
|
|
590
|
+
if (serializedBloomFilters) {
|
|
591
|
+
try {
|
|
592
|
+
const bloomPayload = {
|
|
593
|
+
version: BLOOM_FILTER_SNAPSHOT_VERSION,
|
|
594
|
+
projectRoot: serializedProjectRoot(projectRoot),
|
|
595
|
+
implementationFingerprint: getImplementationFingerprint(),
|
|
596
|
+
projectSnapshotIdentity,
|
|
597
|
+
fileSignatures,
|
|
598
|
+
bloomFilters: serializedBloomFilters,
|
|
599
|
+
};
|
|
600
|
+
const bloomPath = bloomFilterSnapshotPath(projectRoot, opts);
|
|
601
|
+
const bloomCompressed = brotliCompressSync(JSON.stringify(bloomPayload), {
|
|
602
|
+
params: { [zlibConstants.BROTLI_PARAM_QUALITY]: 4 },
|
|
603
|
+
});
|
|
604
|
+
await writeSnapshotAtomically(bloomPath, bloomCompressed);
|
|
605
|
+
const bloomIdentity = await snapshotFileIdentity(bloomPath);
|
|
606
|
+
setBoundedSnapshotCache(parsedSnapshotCache, bloomPath, {
|
|
607
|
+
identity: bloomIdentity,
|
|
608
|
+
compressed: bloomCompressed,
|
|
609
|
+
payload: bloomPayload,
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
catch {
|
|
613
|
+
// Bloom sidecar write failure must not fail indexing
|
|
614
|
+
}
|
|
615
|
+
}
|
|
311
616
|
}
|
|
312
617
|
catch {
|
|
313
618
|
delete index.projectSnapshotIdentity;
|
|
@@ -317,44 +622,13 @@ export async function writeProjectIndexSnapshot(projectRoot, opts, index, filesS
|
|
|
317
622
|
function projectSnapshotPath(projectRoot, opts) {
|
|
318
623
|
return path.join(cacheRoot(projectRoot, opts), "project-index-snapshot.json");
|
|
319
624
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
const observedIdentity = await snapshotFileIdentity(snapshotPath);
|
|
326
|
-
const cached = detailedSymbolGraphCache.get(snapshotPath);
|
|
327
|
-
if (cached &&
|
|
328
|
-
cached.projectSnapshotIdentity === index.projectSnapshotIdentity &&
|
|
329
|
-
sameSnapshotFileIdentity(cached.identity, observedIdentity)) {
|
|
330
|
-
setBoundedSnapshotCache(detailedSymbolGraphCache, snapshotPath, cached);
|
|
331
|
-
return materializeDetailedSymbolGraph(cached.graph);
|
|
332
|
-
}
|
|
333
|
-
const parsed = await readParsedSnapshot(snapshotPath);
|
|
334
|
-
const payload = parsed.payload;
|
|
335
|
-
if (!isDetailedSymbolGraphSnapshotPayload(payload) ||
|
|
336
|
-
!projectRootMatches(projectRoot, payload.projectRoot) ||
|
|
337
|
-
payload.implementationFingerprint !== getImplementationFingerprint() ||
|
|
338
|
-
payload.projectSnapshotIdentity !== index.projectSnapshotIdentity) {
|
|
339
|
-
return null;
|
|
340
|
-
}
|
|
341
|
-
const graph = materializeDetailedSymbolGraph(payload.graph);
|
|
342
|
-
if (!(await isDetailedSymbolGraphCompatibleWithProject(projectRoot, index, graph))) {
|
|
343
|
-
return null;
|
|
344
|
-
}
|
|
345
|
-
const identity = await snapshotFileIdentity(snapshotPath);
|
|
346
|
-
if (!sameSnapshotFileIdentity(parsed.identity, identity))
|
|
347
|
-
return null;
|
|
348
|
-
setBoundedSnapshotCache(detailedSymbolGraphCache, snapshotPath, {
|
|
349
|
-
identity,
|
|
350
|
-
projectSnapshotIdentity: index.projectSnapshotIdentity,
|
|
351
|
-
graph: payload.graph,
|
|
352
|
-
});
|
|
353
|
-
return graph;
|
|
354
|
-
}
|
|
355
|
-
catch {
|
|
356
|
-
return null;
|
|
625
|
+
function bloomFilterSnapshotPath(projectRoot, opts) {
|
|
626
|
+
const root = path.resolve(cacheRoot(projectRoot, opts));
|
|
627
|
+
const snapshotPath = path.resolve(root, BLOOM_FILTER_SNAPSHOT_FILENAME);
|
|
628
|
+
if (!isFilePathWithinRoot(root, snapshotPath)) {
|
|
629
|
+
throw new Error(`Bloom filter snapshot escaped cache root: ${snapshotPath}`);
|
|
357
630
|
}
|
|
631
|
+
return snapshotPath;
|
|
358
632
|
}
|
|
359
633
|
export async function writeDetailedSymbolGraphSnapshot(projectRoot, opts, index, graph) {
|
|
360
634
|
if ((opts?.cache ?? "off") !== "disk" || !index.projectSnapshotIdentity)
|
|
@@ -365,26 +639,29 @@ export async function writeDetailedSymbolGraphSnapshot(projectRoot, opts, index,
|
|
|
365
639
|
implementationFingerprint: getImplementationFingerprint(),
|
|
366
640
|
graphHash: detailedSymbolGraphContentHash(index.projectSnapshotIdentity, graph),
|
|
367
641
|
projectSnapshotIdentity: index.projectSnapshotIdentity,
|
|
368
|
-
graph: {
|
|
642
|
+
graph: transformDetailedGraph({
|
|
369
643
|
nodes: [...graph.nodes.values()],
|
|
370
644
|
edges: graph.edges,
|
|
371
|
-
},
|
|
645
|
+
}, projectRoot, true),
|
|
372
646
|
};
|
|
373
647
|
try {
|
|
374
648
|
const snapshotPath = detailedSymbolGraphSnapshotPath(projectRoot, opts);
|
|
375
649
|
parsedSnapshotCache.delete(snapshotPath);
|
|
650
|
+
transformedSnapshotModulesCache.delete(snapshotPath);
|
|
376
651
|
detailedSymbolGraphCache.delete(snapshotPath);
|
|
377
652
|
const compressed = brotliCompressSync(JSON.stringify(payload), {
|
|
378
653
|
params: { [zlibConstants.BROTLI_PARAM_QUALITY]: 4 },
|
|
379
654
|
});
|
|
380
655
|
await writeSnapshotAtomically(snapshotPath, compressed);
|
|
381
656
|
const identity = await snapshotFileIdentity(snapshotPath);
|
|
382
|
-
|
|
383
|
-
setBoundedSnapshotCache(parsedSnapshotCache, snapshotPath, { identity, compressed });
|
|
657
|
+
setBoundedSnapshotCache(parsedSnapshotCache, snapshotPath, { identity, compressed, payload });
|
|
384
658
|
setBoundedSnapshotCache(detailedSymbolGraphCache, snapshotPath, {
|
|
385
659
|
identity,
|
|
386
660
|
projectSnapshotIdentity: index.projectSnapshotIdentity,
|
|
387
|
-
graph:
|
|
661
|
+
graph: {
|
|
662
|
+
nodes: [...graph.nodes.values()],
|
|
663
|
+
edges: graph.edges,
|
|
664
|
+
},
|
|
388
665
|
});
|
|
389
666
|
}
|
|
390
667
|
catch {
|
|
@@ -399,6 +676,57 @@ function detailedSymbolGraphSnapshotPath(projectRoot, opts) {
|
|
|
399
676
|
}
|
|
400
677
|
return snapshotPath;
|
|
401
678
|
}
|
|
679
|
+
export async function tryLoadDetailedSymbolGraphSnapshot(projectRoot, opts, index, report) {
|
|
680
|
+
if ((opts?.cache ?? "off") !== "disk" || !index.projectSnapshotIdentity)
|
|
681
|
+
return null;
|
|
682
|
+
const snapshotPath = detailedSymbolGraphSnapshotPath(projectRoot, opts);
|
|
683
|
+
try {
|
|
684
|
+
const observedIdentity = await snapshotFileIdentity(snapshotPath);
|
|
685
|
+
const cached = detailedSymbolGraphCache.get(snapshotPath);
|
|
686
|
+
if (cached &&
|
|
687
|
+
cached.projectSnapshotIdentity === index.projectSnapshotIdentity &&
|
|
688
|
+
sameSnapshotFileIdentity(cached.identity, observedIdentity)) {
|
|
689
|
+
setBoundedSnapshotCache(detailedSymbolGraphCache, snapshotPath, cached);
|
|
690
|
+
return materializeDetailedSymbolGraph(cached.graph);
|
|
691
|
+
}
|
|
692
|
+
const parsed = await readParsedSnapshot(snapshotPath);
|
|
693
|
+
const migratedPayload = migrateDetailedSymbolGraphPayload(parsed.payload, projectRoot);
|
|
694
|
+
const payload = migratedPayload && typeof migratedPayload === "object" && !Array.isArray(migratedPayload)
|
|
695
|
+
? {
|
|
696
|
+
...migratedPayload,
|
|
697
|
+
graph: transformDetailedGraph(migratedPayload.graph, projectRoot, false),
|
|
698
|
+
}
|
|
699
|
+
: migratedPayload;
|
|
700
|
+
if (!isDetailedSymbolGraphSnapshotPayload(payload) ||
|
|
701
|
+
payload.implementationFingerprint !== getImplementationFingerprint() ||
|
|
702
|
+
payload.projectSnapshotIdentity !== index.projectSnapshotIdentity) {
|
|
703
|
+
recordSnapshotCorruption(report, snapshotPath, "invalid detailed symbol graph payload", opts?.logLevel);
|
|
704
|
+
return null;
|
|
705
|
+
}
|
|
706
|
+
const graph = materializeDetailedSymbolGraph(payload.graph);
|
|
707
|
+
if (!(await isDetailedSymbolGraphCompatibleWithProject(projectRoot, index, graph))) {
|
|
708
|
+
recordSnapshotCorruption(report, snapshotPath, "detailed symbol graph does not match project", opts?.logLevel);
|
|
709
|
+
return null;
|
|
710
|
+
}
|
|
711
|
+
const identity = await snapshotFileIdentity(snapshotPath);
|
|
712
|
+
if (!sameSnapshotFileIdentity(parsed.identity, identity)) {
|
|
713
|
+
recordSnapshotCorruption(report, snapshotPath, "detailed symbol graph changed while reading", opts?.logLevel);
|
|
714
|
+
return null;
|
|
715
|
+
}
|
|
716
|
+
setBoundedSnapshotCache(detailedSymbolGraphCache, snapshotPath, {
|
|
717
|
+
identity,
|
|
718
|
+
projectSnapshotIdentity: index.projectSnapshotIdentity,
|
|
719
|
+
graph: payload.graph,
|
|
720
|
+
});
|
|
721
|
+
return graph;
|
|
722
|
+
}
|
|
723
|
+
catch (error) {
|
|
724
|
+
if (!isMissingArtifactError(error)) {
|
|
725
|
+
recordSnapshotCorruption(report, snapshotPath, String(error), opts?.logLevel);
|
|
726
|
+
}
|
|
727
|
+
return null;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
402
730
|
function detailedSymbolGraphContentHash(projectSnapshotIdentity, graph) {
|
|
403
731
|
const hash = createHash("sha256");
|
|
404
732
|
hash.update(projectSnapshotIdentity);
|
|
@@ -642,6 +970,21 @@ function isProjectFileType(value) {
|
|
|
642
970
|
function isProjectFileRole(value) {
|
|
643
971
|
return value === "manifest" || value === "lockfile" || value === "config" || value === "solution" || value === "ide";
|
|
644
972
|
}
|
|
973
|
+
function isProjectSnapshotModulesPayload(value) {
|
|
974
|
+
if (!value || typeof value !== "object")
|
|
975
|
+
return false;
|
|
976
|
+
const payload = value;
|
|
977
|
+
return (payload.version === PROJECT_SNAPSHOT_VERSION &&
|
|
978
|
+
typeof payload.filesSignature === "string" &&
|
|
979
|
+
typeof payload.projectRoot === "string" &&
|
|
980
|
+
typeof payload.nativeRuntimeFingerprint === "string" &&
|
|
981
|
+
typeof payload.implementationFingerprint === "string" &&
|
|
982
|
+
/^[a-f0-9]{64}$/.test(payload.implementationFingerprint) &&
|
|
983
|
+
Array.isArray(payload.modules) &&
|
|
984
|
+
payload.modules.every(isModuleIndex) &&
|
|
985
|
+
isSnapshotFileSignatureRecord(payload.fileSignatures) &&
|
|
986
|
+
(payload.nativeMode === undefined || isSnapshotNativeMode(payload.nativeMode)));
|
|
987
|
+
}
|
|
645
988
|
function isProjectIndexSnapshotPayload(value) {
|
|
646
989
|
if (!value || typeof value !== "object")
|
|
647
990
|
return false;
|
|
@@ -659,7 +1002,9 @@ function isProjectIndexSnapshotPayload(value) {
|
|
|
659
1002
|
payload.graph.edges.every(isGraphEdge) &&
|
|
660
1003
|
Array.isArray(payload.modules) &&
|
|
661
1004
|
payload.modules.every(isModuleIndex) &&
|
|
1005
|
+
isSnapshotFileSignatureRecord(payload.fileSignatures) &&
|
|
662
1006
|
(payload.nativeMode === undefined || isSnapshotNativeMode(payload.nativeMode)) &&
|
|
1007
|
+
(payload.languageExtensions === undefined || isLanguageExtensionMap(payload.languageExtensions)) &&
|
|
663
1008
|
(payload.bloomFilters === undefined || isSerializedBloomFilterRecord(payload.bloomFilters)) &&
|
|
664
1009
|
(payload.analysis === undefined || isAnalysisSummary(payload.analysis)) &&
|
|
665
1010
|
(payload.analysisReport === undefined || isSnapshotAnalysisReport(payload.analysisReport)) &&
|
|
@@ -746,14 +1091,14 @@ function isAnalysisSummary(value) {
|
|
|
746
1091
|
typeof summary.nativeFilesFellBack === "number" &&
|
|
747
1092
|
typeof summary.label === "string");
|
|
748
1093
|
}
|
|
749
|
-
function serializeBloomFilterCache(cache, files) {
|
|
1094
|
+
function serializeBloomFilterCache(cache, files, projectRoot) {
|
|
750
1095
|
const serialized = {};
|
|
751
1096
|
for (const file of files) {
|
|
752
1097
|
const filter = cache.get(file);
|
|
753
1098
|
if (!filter)
|
|
754
1099
|
continue;
|
|
755
1100
|
const metadata = filter.getMetadata();
|
|
756
|
-
serialized[file] = {
|
|
1101
|
+
serialized[cacheRelativePath(projectRoot, file)] = {
|
|
757
1102
|
size: metadata.size,
|
|
758
1103
|
hashCount: metadata.hashCount,
|
|
759
1104
|
bitsBase64: filter.toBuffer().toString("base64"),
|
|
@@ -761,10 +1106,35 @@ function serializeBloomFilterCache(cache, files) {
|
|
|
761
1106
|
}
|
|
762
1107
|
return Object.keys(serialized).length ? serialized : undefined;
|
|
763
1108
|
}
|
|
764
|
-
function
|
|
1109
|
+
function serializeSnapshotFileSignatures(entries, projectRoot) {
|
|
1110
|
+
const serialized = {};
|
|
1111
|
+
for (const [file, entry] of entries ?? []) {
|
|
1112
|
+
serialized[cacheRelativePath(projectRoot, file)] = {
|
|
1113
|
+
sig: entry.sig,
|
|
1114
|
+
...(entry.gitSig ? { gitSig: entry.gitSig } : {}),
|
|
1115
|
+
...(entry.cacheSig ? { cacheSig: entry.cacheSig } : {}),
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
return serialized;
|
|
1119
|
+
}
|
|
1120
|
+
function isSnapshotFileSignatureRecord(value) {
|
|
1121
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
1122
|
+
return false;
|
|
1123
|
+
return Object.values(value).every(isSnapshotFileSignature);
|
|
1124
|
+
}
|
|
1125
|
+
function isSnapshotFileSignature(value) {
|
|
1126
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
1127
|
+
return false;
|
|
1128
|
+
const signature = value;
|
|
1129
|
+
return (typeof signature.sig === "string" &&
|
|
1130
|
+
(signature.gitSig === undefined || typeof signature.gitSig === "string") &&
|
|
1131
|
+
(signature.cacheSig === undefined || typeof signature.cacheSig === "string"));
|
|
1132
|
+
}
|
|
1133
|
+
function deserializeBloomFilterCache(serialized, projectRoot) {
|
|
765
1134
|
const cache = new BloomFilterCache();
|
|
766
1135
|
for (const [file, filter] of Object.entries(serialized)) {
|
|
767
|
-
|
|
1136
|
+
const absoluteFile = assertFilePathWithinRoot(projectRoot, cacheAbsolutePath(projectRoot, file), "Persisted cache path");
|
|
1137
|
+
cache.set(absoluteFile, BloomFilter.fromBuffer(Buffer.from(filter.bitsBase64, "base64"), filter.size, filter.hashCount));
|
|
768
1138
|
}
|
|
769
1139
|
return cache;
|
|
770
1140
|
}
|
|
@@ -773,6 +1143,11 @@ function isSerializedBloomFilterRecord(value) {
|
|
|
773
1143
|
return false;
|
|
774
1144
|
return Object.values(value).every(isSerializedBloomFilter);
|
|
775
1145
|
}
|
|
1146
|
+
function isLanguageExtensionMap(value) {
|
|
1147
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
1148
|
+
return false;
|
|
1149
|
+
return Object.values(value).every((entry) => typeof entry === "string");
|
|
1150
|
+
}
|
|
776
1151
|
function isSerializedBloomFilter(value) {
|
|
777
1152
|
if (!value || typeof value !== "object")
|
|
778
1153
|
return false;
|
|
@@ -788,9 +1163,15 @@ function isSerializedBloomFilter(value) {
|
|
|
788
1163
|
typeof filter.bitsBase64 !== "string") {
|
|
789
1164
|
return false;
|
|
790
1165
|
}
|
|
791
|
-
const
|
|
792
|
-
|
|
793
|
-
|
|
1166
|
+
const expectedBytes = Math.ceil(filter.size / 8);
|
|
1167
|
+
let decoded;
|
|
1168
|
+
try {
|
|
1169
|
+
decoded = Buffer.from(filter.bitsBase64, "base64");
|
|
1170
|
+
}
|
|
1171
|
+
catch {
|
|
1172
|
+
return false;
|
|
1173
|
+
}
|
|
1174
|
+
return decoded.length === expectedBytes && decoded.toString("base64") === filter.bitsBase64;
|
|
794
1175
|
}
|
|
795
1176
|
function isModuleIndex(value) {
|
|
796
1177
|
if (!value || typeof value !== "object")
|