gitnexus 1.6.8-rc.8 → 1.6.8
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 +3 -3
- package/dist/_shared/graph/types.d.ts +31 -1
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +11 -1
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +6 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/scope-resolution/parsed-file.d.ts +21 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/symbol-definition.d.ts +6 -0
- package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +31 -1
- package/dist/cli/ai-context.js +18 -16
- package/dist/cli/analyze-config.js +11 -0
- package/dist/cli/analyze.d.ts +14 -0
- package/dist/cli/analyze.js +98 -0
- package/dist/cli/embedding-dims.d.ts +33 -0
- package/dist/cli/embedding-dims.js +39 -0
- package/dist/cli/eval-server.d.ts +8 -0
- package/dist/cli/eval-server.js +242 -2
- package/dist/cli/help-i18n.js +19 -0
- package/dist/cli/i18n/en.d.ts +15 -1
- package/dist/cli/i18n/en.js +15 -1
- package/dist/cli/i18n/resources.d.ts +29 -1
- package/dist/cli/i18n/zh-CN.d.ts +14 -0
- package/dist/cli/i18n/zh-CN.js +15 -1
- package/dist/cli/index.js +89 -1
- package/dist/cli/mcp.d.ts +6 -1
- package/dist/cli/mcp.js +26 -1
- package/dist/cli/optional-grammars.d.ts +6 -8
- package/dist/cli/optional-grammars.js +8 -11
- package/dist/cli/setup.d.ts +3 -1
- package/dist/cli/setup.js +67 -17
- package/dist/cli/skill-gen.js +2 -1
- package/dist/cli/tool.d.ts +19 -1
- package/dist/cli/tool.js +96 -3
- package/dist/core/embeddings/hf-env.d.ts +0 -66
- package/dist/core/embeddings/http-client.d.ts +7 -0
- package/dist/core/embeddings/http-client.js +5 -3
- package/dist/core/embeddings/server-mapping.d.ts +1 -1
- package/dist/core/embeddings/server-mapping.js +7 -3
- package/dist/core/graph/import-cycles.d.ts +10 -0
- package/dist/core/graph/import-cycles.js +103 -0
- package/dist/core/group/cross-impact.d.ts +2 -1
- package/dist/core/group/cross-impact.js +5 -1
- package/dist/core/group/extractors/grpc-patterns/proto.js +10 -6
- package/dist/core/group/extractors/http-patterns/kotlin.js +7 -7
- package/dist/core/group/extractors/http-route-extractor.d.ts +24 -0
- package/dist/core/group/extractors/http-route-extractor.js +22 -4
- package/dist/core/group/extractors/include-extractor.js +22 -13
- package/dist/core/group/sync.d.ts +27 -1
- package/dist/core/group/sync.js +0 -0
- package/dist/core/incremental/subgraph-extract.js +18 -1
- package/dist/core/ingestion/cfg/cfg-builder.d.ts +114 -0
- package/dist/core/ingestion/cfg/cfg-builder.js +196 -0
- package/dist/core/ingestion/cfg/collect.d.ts +51 -0
- package/dist/core/ingestion/cfg/collect.js +77 -0
- package/dist/core/ingestion/cfg/control-dependence.d.ts +58 -0
- package/dist/core/ingestion/cfg/control-dependence.js +182 -0
- package/dist/core/ingestion/cfg/control-flow-context.d.ts +106 -0
- package/dist/core/ingestion/cfg/control-flow-context.js +124 -0
- package/dist/core/ingestion/cfg/emit.d.ts +293 -0
- package/dist/core/ingestion/cfg/emit.js +646 -0
- package/dist/core/ingestion/cfg/post-dominators.d.ts +79 -0
- package/dist/core/ingestion/cfg/post-dominators.js +176 -0
- package/dist/core/ingestion/cfg/reaching-def-reason-codec.d.ts +106 -0
- package/dist/core/ingestion/cfg/reaching-def-reason-codec.js +133 -0
- package/dist/core/ingestion/cfg/reaching-defs-graph.d.ts +18 -0
- package/dist/core/ingestion/cfg/reaching-defs-graph.js +312 -0
- package/dist/core/ingestion/cfg/reaching-defs.d.ts +162 -0
- package/dist/core/ingestion/cfg/reaching-defs.js +785 -0
- package/dist/core/ingestion/cfg/synthetic-escape.d.ts +124 -0
- package/dist/core/ingestion/cfg/synthetic-escape.js +300 -0
- package/dist/core/ingestion/cfg/traversal-result.d.ts +20 -0
- package/dist/core/ingestion/cfg/traversal-result.js +2 -0
- package/dist/core/ingestion/cfg/types.d.ts +274 -0
- package/dist/core/ingestion/cfg/types.js +13 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.d.ts +111 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.js +541 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp.d.ts +74 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp.js +584 -0
- package/dist/core/ingestion/cfg/visitors/call-site-harvest.d.ts +195 -0
- package/dist/core/ingestion/cfg/visitors/call-site-harvest.js +350 -0
- package/dist/core/ingestion/cfg/visitors/csharp-harvest.d.ts +124 -0
- package/dist/core/ingestion/cfg/visitors/csharp-harvest.js +589 -0
- package/dist/core/ingestion/cfg/visitors/csharp.d.ts +87 -0
- package/dist/core/ingestion/cfg/visitors/csharp.js +867 -0
- package/dist/core/ingestion/cfg/visitors/dart-harvest.d.ts +278 -0
- package/dist/core/ingestion/cfg/visitors/dart-harvest.js +870 -0
- package/dist/core/ingestion/cfg/visitors/dart.d.ts +119 -0
- package/dist/core/ingestion/cfg/visitors/dart.js +836 -0
- package/dist/core/ingestion/cfg/visitors/go-harvest.d.ts +160 -0
- package/dist/core/ingestion/cfg/visitors/go-harvest.js +621 -0
- package/dist/core/ingestion/cfg/visitors/go.d.ts +108 -0
- package/dist/core/ingestion/cfg/visitors/go.js +638 -0
- package/dist/core/ingestion/cfg/visitors/java-harvest.d.ts +108 -0
- package/dist/core/ingestion/cfg/visitors/java-harvest.js +513 -0
- package/dist/core/ingestion/cfg/visitors/java.d.ts +101 -0
- package/dist/core/ingestion/cfg/visitors/java.js +812 -0
- package/dist/core/ingestion/cfg/visitors/kotlin-harvest.d.ts +253 -0
- package/dist/core/ingestion/cfg/visitors/kotlin-harvest.js +719 -0
- package/dist/core/ingestion/cfg/visitors/kotlin.d.ts +121 -0
- package/dist/core/ingestion/cfg/visitors/kotlin.js +809 -0
- package/dist/core/ingestion/cfg/visitors/php-harvest.d.ts +172 -0
- package/dist/core/ingestion/cfg/visitors/php-harvest.js +626 -0
- package/dist/core/ingestion/cfg/visitors/php.d.ts +96 -0
- package/dist/core/ingestion/cfg/visitors/php.js +721 -0
- package/dist/core/ingestion/cfg/visitors/python-harvest.d.ts +212 -0
- package/dist/core/ingestion/cfg/visitors/python-harvest.js +739 -0
- package/dist/core/ingestion/cfg/visitors/python.d.ts +103 -0
- package/dist/core/ingestion/cfg/visitors/python.js +558 -0
- package/dist/core/ingestion/cfg/visitors/ruby-harvest.d.ts +223 -0
- package/dist/core/ingestion/cfg/visitors/ruby-harvest.js +587 -0
- package/dist/core/ingestion/cfg/visitors/ruby.d.ts +112 -0
- package/dist/core/ingestion/cfg/visitors/ruby.js +756 -0
- package/dist/core/ingestion/cfg/visitors/rust-harvest.d.ts +324 -0
- package/dist/core/ingestion/cfg/visitors/rust-harvest.js +873 -0
- package/dist/core/ingestion/cfg/visitors/rust.d.ts +95 -0
- package/dist/core/ingestion/cfg/visitors/rust.js +558 -0
- package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.d.ts +87 -0
- package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.js +116 -0
- package/dist/core/ingestion/cfg/visitors/swift-harvest.d.ts +255 -0
- package/dist/core/ingestion/cfg/visitors/swift-harvest.js +679 -0
- package/dist/core/ingestion/cfg/visitors/swift.d.ts +116 -0
- package/dist/core/ingestion/cfg/visitors/swift.js +787 -0
- package/dist/core/ingestion/cfg/visitors/typescript-harvest.d.ts +149 -0
- package/dist/core/ingestion/cfg/visitors/typescript-harvest.js +1056 -0
- package/dist/core/ingestion/cfg/visitors/typescript.d.ts +66 -0
- package/dist/core/ingestion/cfg/visitors/typescript.js +583 -0
- package/dist/core/ingestion/import-resolvers/utils.js +2 -0
- package/dist/core/ingestion/language-provider.d.ts +23 -2
- package/dist/core/ingestion/languages/c-cpp.js +17 -5
- package/dist/core/ingestion/languages/cobol.js +4 -0
- package/dist/core/ingestion/languages/cpp/arity-metadata.js +41 -2
- package/dist/core/ingestion/languages/cpp/captures.js +50 -1
- package/dist/core/ingestion/languages/cpp/conversion-rank.d.ts +2 -0
- package/dist/core/ingestion/languages/cpp/conversion-rank.js +89 -0
- package/dist/core/ingestion/languages/cpp/header-scan.d.ts +1 -1
- package/dist/core/ingestion/languages/cpp/header-scan.js +2 -2
- package/dist/core/ingestion/languages/cpp/inline-namespaces.js +7 -2
- package/dist/core/ingestion/languages/cpp/member-lookup.js +2 -1
- package/dist/core/ingestion/languages/cpp/query.js +23 -0
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +2 -1
- package/dist/core/ingestion/languages/csharp.js +2 -0
- package/dist/core/ingestion/languages/dart.js +2 -0
- package/dist/core/ingestion/languages/go.js +2 -0
- package/dist/core/ingestion/languages/java.js +3 -0
- package/dist/core/ingestion/languages/kotlin/query.js +3 -2
- package/dist/core/ingestion/languages/kotlin.js +8 -1
- package/dist/core/ingestion/languages/php.js +2 -0
- package/dist/core/ingestion/languages/python.js +2 -0
- package/dist/core/ingestion/languages/ruby.js +2 -0
- package/dist/core/ingestion/languages/rust.js +2 -0
- package/dist/core/ingestion/languages/swift.js +2 -0
- package/dist/core/ingestion/languages/typescript.js +5 -0
- package/dist/core/ingestion/languages/vue.js +6 -0
- package/dist/core/ingestion/method-extractors/configs/c-cpp.js +6 -13
- package/dist/core/ingestion/method-extractors/generic.js +1 -0
- package/dist/core/ingestion/method-types.d.ts +2 -0
- package/dist/core/ingestion/model/symbol-table.d.ts +1 -0
- package/dist/core/ingestion/model/symbol-table.js +1 -0
- package/dist/core/ingestion/mro-processor.js +109 -0
- package/dist/core/ingestion/parsing-processor.js +44 -0
- package/dist/core/ingestion/pipeline-phases/call-summaries.d.ts +26 -0
- package/dist/core/ingestion/pipeline-phases/call-summaries.js +46 -0
- package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
- package/dist/core/ingestion/pipeline-phases/index.js +2 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +0 -21
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +18 -1
- package/dist/core/ingestion/pipeline-phases/routes.d.ts +10 -0
- package/dist/core/ingestion/pipeline-phases/routes.js +30 -1
- package/dist/core/ingestion/pipeline-phases/taint-summaries.d.ts +30 -0
- package/dist/core/ingestion/pipeline-phases/taint-summaries.js +81 -0
- package/dist/core/ingestion/pipeline.d.ts +92 -10
- package/dist/core/ingestion/pipeline.js +11 -2
- package/dist/core/ingestion/scope-extractor.js +12 -2
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +9 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.d.ts +75 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +67 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +12 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +14 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +6 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +13 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +9 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +28 -2
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +4 -0
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +9 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +6 -1
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +174 -40
- package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +24 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +276 -190
- package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +43 -3
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +75 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +349 -1
- package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
- package/dist/core/ingestion/taint/call-summary-codec.d.ts +75 -0
- package/dist/core/ingestion/taint/call-summary-codec.js +128 -0
- package/dist/core/ingestion/taint/call-summary-emit.d.ts +43 -0
- package/dist/core/ingestion/taint/call-summary-emit.js +70 -0
- package/dist/core/ingestion/taint/call-summary-harvest.d.ts +77 -0
- package/dist/core/ingestion/taint/call-summary-harvest.js +179 -0
- package/dist/core/ingestion/taint/call-summary-model.d.ts +47 -0
- package/dist/core/ingestion/taint/call-summary-model.js +25 -0
- package/dist/core/ingestion/taint/emit.d.ts +125 -0
- package/dist/core/ingestion/taint/emit.js +208 -0
- package/dist/core/ingestion/taint/interproc-emit.d.ts +50 -0
- package/dist/core/ingestion/taint/interproc-emit.js +88 -0
- package/dist/core/ingestion/taint/interproc-solver.d.ts +110 -0
- package/dist/core/ingestion/taint/interproc-solver.js +312 -0
- package/dist/core/ingestion/taint/match.d.ts +153 -0
- package/dist/core/ingestion/taint/match.js +278 -0
- package/dist/core/ingestion/taint/path-codec.d.ts +134 -0
- package/dist/core/ingestion/taint/path-codec.js +190 -0
- package/dist/core/ingestion/taint/propagate.d.ts +216 -0
- package/dist/core/ingestion/taint/propagate.js +659 -0
- package/dist/core/ingestion/taint/site-safety.d.ts +29 -0
- package/dist/core/ingestion/taint/site-safety.js +98 -0
- package/dist/core/ingestion/taint/source-sink-config.d.ts +107 -23
- package/dist/core/ingestion/taint/source-sink-config.js +35 -12
- package/dist/core/ingestion/taint/source-sink-registry.d.ts +6 -4
- package/dist/core/ingestion/taint/source-sink-registry.js +6 -4
- package/dist/core/ingestion/taint/summary-harvest-driver.d.ts +80 -0
- package/dist/core/ingestion/taint/summary-harvest-driver.js +179 -0
- package/dist/core/ingestion/taint/summary-harvest.d.ts +89 -0
- package/dist/core/ingestion/taint/summary-harvest.js +537 -0
- package/dist/core/ingestion/taint/summary-model.d.ts +200 -0
- package/dist/core/ingestion/taint/summary-model.js +86 -0
- package/dist/core/ingestion/taint/typescript-model.d.ts +38 -0
- package/dist/core/ingestion/taint/typescript-model.js +102 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +21 -0
- package/dist/core/ingestion/utils/env.d.ts +7 -0
- package/dist/core/ingestion/utils/env.js +12 -0
- package/dist/core/ingestion/utils/method-props.js +1 -0
- package/dist/core/ingestion/workers/clone-safety.d.ts +109 -0
- package/dist/core/ingestion/workers/clone-safety.js +465 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +23 -0
- package/dist/core/ingestion/workers/parse-worker.js +81 -53
- package/dist/core/ingestion/workers/post-result.d.ts +22 -0
- package/dist/core/ingestion/workers/post-result.js +87 -0
- package/dist/core/ingestion/workers/result-merge.d.ts +20 -0
- package/dist/core/ingestion/workers/result-merge.js +43 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +15 -40
- package/dist/core/ingestion/workers/worker-pool.js +43 -16
- package/dist/core/lbug/csv-generator.d.ts +51 -3
- package/dist/core/lbug/csv-generator.js +369 -255
- package/dist/core/lbug/lbug-adapter.d.ts +58 -18
- package/dist/core/lbug/lbug-adapter.js +346 -84
- package/dist/core/lbug/lbug-config.d.ts +19 -0
- package/dist/core/lbug/lbug-config.js +29 -0
- package/dist/core/lbug/pdg-emit-sink.d.ts +127 -0
- package/dist/core/lbug/pdg-emit-sink.js +358 -0
- package/dist/core/lbug/pool-adapter.d.ts +35 -0
- package/dist/core/lbug/pool-adapter.js +90 -1
- package/dist/core/lbug/rel-pair-routing.d.ts +54 -0
- package/dist/core/lbug/rel-pair-routing.js +140 -0
- package/dist/core/lbug/schema.d.ts +2 -2
- package/dist/core/lbug/schema.js +3 -0
- package/dist/core/logger.d.ts +0 -5
- package/dist/core/run-analyze.d.ts +96 -0
- package/dist/core/run-analyze.js +207 -3
- package/dist/core/tree-sitter/parser-loader.js +5 -4
- package/dist/core/tree-sitter/safe-parse.d.ts +0 -5
- package/dist/core/tree-sitter/vendored-grammars.d.ts +39 -0
- package/dist/core/tree-sitter/vendored-grammars.js +57 -0
- package/dist/core/wiki/generator.js +3 -1
- package/dist/core/wiki/graph-queries.d.ts +6 -0
- package/dist/core/wiki/graph-queries.js +9 -1
- package/dist/mcp/http-transport.d.ts +134 -0
- package/dist/mcp/http-transport.js +503 -0
- package/dist/mcp/local/local-backend.d.ts +110 -24
- package/dist/mcp/local/local-backend.js +1225 -19
- package/dist/mcp/local/pdg-impact.d.ts +384 -0
- package/dist/mcp/local/pdg-impact.js +1972 -0
- package/dist/mcp/resources.js +13 -1
- package/dist/mcp/tools.d.ts +12 -0
- package/dist/mcp/tools.js +214 -7
- package/dist/server/analyze-launch.d.ts +29 -0
- package/dist/server/analyze-launch.js +137 -0
- package/dist/server/analyze-upload.d.ts +33 -0
- package/dist/server/analyze-upload.js +123 -0
- package/dist/server/analyze-worker-ipc.d.ts +58 -0
- package/dist/server/analyze-worker-ipc.js +16 -0
- package/dist/server/analyze-worker.d.ts +17 -1
- package/dist/server/analyze-worker.js +7 -1
- package/dist/server/api.d.ts +17 -0
- package/dist/server/api.js +132 -168
- package/dist/server/git-clone.d.ts +43 -2
- package/dist/server/git-clone.js +211 -16
- package/dist/server/mcp-http.d.ts +5 -6
- package/dist/server/mcp-http.js +9 -82
- package/dist/server/middleware.d.ts +40 -0
- package/dist/server/middleware.js +92 -0
- package/dist/server/private-ip.d.ts +1 -0
- package/dist/server/private-ip.js +15 -0
- package/dist/server/upload-ingest.d.ts +56 -0
- package/dist/server/upload-ingest.js +276 -0
- package/dist/server/upload-paths.d.ts +37 -0
- package/dist/server/upload-paths.js +57 -0
- package/dist/server/upload-sweep.d.ts +20 -0
- package/dist/server/upload-sweep.js +57 -0
- package/dist/storage/git.js +5 -8
- package/dist/storage/parse-cache.d.ts +22 -1
- package/dist/storage/parse-cache.js +44 -10
- package/dist/storage/repo-manager.d.ts +121 -10
- package/dist/storage/repo-manager.js +43 -5
- package/dist/types/pipeline.d.ts +9 -0
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +110 -10
- package/hooks/claude/gitnexus-hook.cjs +110 -13
- package/hooks/claude/hook-db-lock-probe.cjs +513 -26
- package/package.json +8 -2
- package/scripts/assert-publish-grammar-coverage.cjs +31 -0
- package/scripts/build-tree-sitter-grammars.cjs +16 -10
- package/scripts/cross-platform-tests.ts +1 -0
- package/skills/gitnexus-debugging.md +16 -4
- package/skills/gitnexus-exploring.md +3 -3
- package/skills/gitnexus-guide.md +33 -0
- package/skills/gitnexus-pdg-query.md +89 -0
- package/skills/gitnexus-refactoring.md +1 -1
- package/skills/gitnexus-taint-analysis.md +178 -0
- package/vendor/tree-sitter-c/package.json +1 -1
- package/vendor/tree-sitter-dart/package.json +1 -1
- package/vendor/tree-sitter-kotlin/package.json +1 -1
- package/vendor/tree-sitter-proto/package.json +1 -1
- package/vendor/tree-sitter-swift/package.json +1 -1
- package/web/assets/{agent-CKPMqImC.js → agent-D3Xd7zZE.js} +123 -123
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-ChH9xW-N.js +36 -0
- package/web/assets/{blockDiagram-7IZFK4PR-B4niSLvR.js → blockDiagram-7IZFK4PR-BkWhpzWB.js} +1 -1
- package/web/assets/{c4Diagram-Y2BXMSZH-DIzEXalR.js → c4Diagram-Y2BXMSZH-DtBvpzWD.js} +1 -1
- package/web/assets/{chunk-3SSMPTDK-BzGeeheI.js → chunk-3SSMPTDK-B4_etUhr.js} +2 -2
- package/web/assets/{chunk-5IMINLNL-CnTLsXIV.js → chunk-5IMINLNL-DOdTeQri.js} +1 -1
- package/web/assets/{chunk-5VCL7Z4A-w1BCx98Z.js → chunk-5VCL7Z4A-CQ-2dYWj.js} +1 -1
- package/web/assets/chunk-6764PJDD-DpIS7hxD.js +1 -0
- package/web/assets/{chunk-67TQ5CYL-CChC2cAv.js → chunk-67TQ5CYL-4sNPJU1q.js} +3 -3
- package/web/assets/{chunk-7W6UQGC5-CgFyfZ6k.js → chunk-7W6UQGC5-KyEG0HQg.js} +1 -1
- package/web/assets/{chunk-AZZRMDJM-5E9ARdDQ.js → chunk-AZZRMDJM-y-xJBuMz.js} +1 -1
- package/web/assets/{chunk-INKRHTLW-ELpfuk9h.js → chunk-INKRHTLW-Nu4ri9P-.js} +1 -1
- package/web/assets/{chunk-JQRUD6KW-Dcq_Qnyy.js → chunk-JQRUD6KW-Dbva2Z17.js} +1 -1
- package/web/assets/{chunk-KGFNY3KK-W-VR57xb.js → chunk-KGFNY3KK-JGMJvKCK.js} +1 -1
- package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +161 -0
- package/web/assets/{chunk-KNLZD3CH-BuZBOcso.js → chunk-KNLZD3CH-BGlP6X9R.js} +1 -1
- package/web/assets/{chunk-KRXBNO2N-DH2NPM7I.js → chunk-KRXBNO2N-BW5o0KUN.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-Dfmux4m1.js → chunk-LCXTWHL2-zoomRtWX.js} +1 -1
- package/web/assets/{chunk-LII3EMHJ-3X33tCpU.js → chunk-LII3EMHJ-D-jm-dLa.js} +1 -1
- package/web/assets/{chunk-QA3QBVWF-D5Ha3GgB.js → chunk-QA3QBVWF-BgRW3SXd.js} +1 -1
- package/web/assets/{chunk-RG4AUYOV-CAkzcoRj.js → chunk-RG4AUYOV-DD0B2N2B.js} +1 -1
- package/web/assets/{chunk-T2UQINTJ-kGYG7ppP.js → chunk-T2UQINTJ-DSBqkzH7.js} +1 -1
- package/web/assets/chunk-T5OCTHI4-DdZvN-9i.js +1 -0
- package/web/assets/{chunk-UY5QBCOK-Du-c56gs.js → chunk-UY5QBCOK-DyF0vyGd.js} +1 -1
- package/web/assets/{chunk-W44A43WB-lrCpuupA.js → chunk-W44A43WB-JqMLIpR0.js} +1 -1
- package/web/assets/{chunk-ZXARS5L4-CSZRiyOf.js → chunk-ZXARS5L4-CxN8oiwI.js} +1 -1
- package/web/assets/classDiagram-KGZ6W3CR-DJm9BgF-.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-DJm9BgF-.js +1 -0
- package/web/assets/{context-builder-_HS0v2ma.js → context-builder-BHiFUA8O.js} +10 -2
- package/web/assets/{cose-bilkent-UX7MHV2Q-BHv2bbtl.js → cose-bilkent-UX7MHV2Q-D71wNYRJ.js} +1 -1
- package/web/assets/dagre-ND4H6XIP-BIkxmhcu.js +4 -0
- package/web/assets/diagram-3NCE3AQN-BTa6iH0T.js +43 -0
- package/web/assets/diagram-GF46GFSD-DZDV0vBj.js +24 -0
- package/web/assets/{diagram-HNR7UZ2L-fUWreZzx.js → diagram-HNR7UZ2L-DFCfd5LI.js} +2 -2
- package/web/assets/diagram-QXG6HAR7-BzM--Jj0.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-DFFwz0k4.js +10 -0
- package/web/assets/{erDiagram-L5TCEMPS-QN2eEP1e.js → erDiagram-L5TCEMPS-CfHMJJqo.js} +1 -1
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +1 -0
- package/web/assets/{flowDiagram-H6V6AXG4-CXbXImlN.js → flowDiagram-H6V6AXG4-Be805QiJ.js} +3 -3
- package/web/assets/{ganttDiagram-JCBTUEKG-BHQssTz6.js → ganttDiagram-JCBTUEKG-D3iL2Aet.js} +1 -1
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +106 -0
- package/web/assets/index-BvYev1UJ.js +635 -0
- package/web/assets/index-_lgn7hs5.css +2 -0
- package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-Y7BKSoke.js +2 -0
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-6LKOvBfp.js → ishikawaDiagram-BNXS4ZKH-CT4SHFuI.js} +1 -1
- package/web/assets/{journeyDiagram-M6C3CM3L-DNPYCpvq.js → journeyDiagram-M6C3CM3L-CvArszLo.js} +1 -1
- package/web/assets/{kanban-definition-75IXJCU3-DgDi9oJT.js → kanban-definition-75IXJCU3-C6yDxr7N.js} +3 -3
- package/web/assets/{katex-K3KEBU37-CrVLz8l7.js → katex-K3KEBU37-CTc5BslQ.js} +1 -1
- package/web/assets/{mindmap-definition-2TDM6QVE-CwR5sBB-.js → mindmap-definition-2TDM6QVE-BOc2WEne.js} +1 -1
- package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +1 -0
- package/web/assets/{pieDiagram-CU6KROY3-By8g6f6B.js → pieDiagram-CU6KROY3-Cvc0f_Pd.js} +1 -1
- package/web/assets/{quadrantDiagram-VICAPDV7-bAm6Hi_5.js → quadrantDiagram-VICAPDV7-yXSZ2lLz.js} +1 -1
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +1 -0
- package/web/assets/{requirementDiagram-JXO7QTGE-7oDcJ1_J.js → requirementDiagram-JXO7QTGE-BRcZvHs4.js} +1 -1
- package/web/assets/{sankeyDiagram-URQDO5SZ-LFJz53u5.js → sankeyDiagram-URQDO5SZ-1qEjlFIB.js} +1 -1
- package/web/assets/{sequenceDiagram-VS2MUI6T-FySeKCUy.js → sequenceDiagram-VS2MUI6T-PcSCuvrB.js} +3 -3
- package/web/assets/stateDiagram-7D4R322I-D6qYSV1E.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-Bg-ImOSX.js +1 -0
- package/web/assets/{timeline-definition-O6YCAMPW-Ds2CnVZK.js → timeline-definition-O6YCAMPW-QWkh01xw.js} +1 -1
- package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +1 -0
- package/web/assets/{vennDiagram-MWXL3ELB-DUIEwXWp.js → vennDiagram-MWXL3ELB-ak4DfwuM.js} +3 -3
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +1 -0
- package/web/assets/{wardleyDiagram-CUQ6CDDI-DEiFPQih.js → wardleyDiagram-CUQ6CDDI-CTzR4Loq.js} +1 -1
- package/web/assets/{xychartDiagram-N2JHSOCM-BUbayhST.js → xychartDiagram-N2JHSOCM-DA1BEaQz.js} +1 -1
- package/web/index.html +13 -15
- package/scripts/materialize-vendor-grammars.cjs +0 -97
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-BETj2x4g.js +0 -1
- package/web/assets/architectureDiagram-UL44E2DR-D1EXI0zA.js +0 -36
- package/web/assets/chunk-2T2R6R2M-n6s9JZqv.js +0 -4
- package/web/assets/chunk-2UTLFMKG-CMBB1TMN.js +0 -1
- package/web/assets/chunk-4R4BOZG6-mKhL59ul.js +0 -159
- package/web/assets/chunk-6764PJDD-ChwMM2z4.js +0 -1
- package/web/assets/chunk-7J6CGLKN-DT-b53FT.js +0 -10
- package/web/assets/chunk-C62D2QBJ-CDAWj26E.js +0 -1
- package/web/assets/chunk-CEXFNPSA-D68Tk6ls.js +0 -1
- package/web/assets/chunk-CilyBKbf.js +0 -1
- package/web/assets/chunk-J5EP6P6S-DxWW0yvu.js +0 -1
- package/web/assets/chunk-KGYTTC2M-C6PHeuay.js +0 -1
- package/web/assets/chunk-RERM46MO-DQNbXtfw.js +0 -1
- package/web/assets/chunk-RKZBBQEN-BmTPLSyv.js +0 -1
- package/web/assets/chunk-RLI5ZMPA-DExu2DOK.js +0 -1
- package/web/assets/chunk-T5OCTHI4--9wWpVws.js +0 -1
- package/web/assets/chunk-UP6H54XL-DsKdC6jC.js +0 -1
- package/web/assets/chunk-UXSXWOXI-DR81EqLr.js +0 -1
- package/web/assets/classDiagram-KGZ6W3CR-Bv93af_b.js +0 -1
- package/web/assets/classDiagram-v2-72OJOZXJ-CLfEqHUa.js +0 -1
- package/web/assets/dagre-ND4H6XIP-DsIr9MOv.js +0 -4
- package/web/assets/diagram-3NCE3AQN-BqAtKUpW.js +0 -43
- package/web/assets/diagram-GF46GFSD-CaBG6n6o.js +0 -24
- package/web/assets/diagram-QXG6HAR7-CZ-O3rcV.js +0 -24
- package/web/assets/diagram-WEQXMOUZ-P4lSL4GH.js +0 -10
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-B3myHUst.js +0 -1
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DF3rtf4A.js +0 -1
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CCwVLT__.js +0 -106
- package/web/assets/index-BKWA-m7o.css +0 -2
- package/web/assets/index-CG6q8eTs.js +0 -626
- package/web/assets/info-J43DQDTF-KCYPFFUO-R4XV_akJ.js +0 -1
- package/web/assets/infoDiagram-3YFTVSEB-DmLICZx1.js +0 -2
- package/web/assets/packet-YPE3B663-LP52Z2RK-CgQPdNZa.js +0 -1
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BzWOwc_c.js +0 -1
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-B7KG0FN7.js +0 -1
- package/web/assets/stateDiagram-7D4R322I-CB2nABwH.js +0 -1
- package/web/assets/stateDiagram-v2-36443NZ5-COBGd2RL.js +0 -1
- package/web/assets/treeView-BLDUP644-QA4HXRO3-CRSxEwLO.js +0 -1
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-a0PfKoVn.js +0 -1
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-BKQ6e5mC.js +0 -1
- /package/web/assets/{chunk-AQ6EADP3-CCFje6lL.js → chunk-AQ6EADP3-CZhslHi-.js} +0 -0
|
@@ -27,6 +27,9 @@ import type { KnowledgeGraph } from '../../../graph/types.js';
|
|
|
27
27
|
import type { MutableSemanticModel } from '../../model/semantic-model.js';
|
|
28
28
|
import { type ResolveStats } from '../../resolve-references.js';
|
|
29
29
|
import { buildGraphNodeLookup } from '../graph-bridge/node-lookup.js';
|
|
30
|
+
import { type FunctionNodeIndex } from '../../taint/summary-harvest-driver.js';
|
|
31
|
+
import type { FunctionSummary } from '../../taint/summary-model.js';
|
|
32
|
+
import type { CallSummary } from '../../taint/call-summary-model.js';
|
|
30
33
|
import type { ScopeResolver } from '../contract/scope-resolver.js';
|
|
31
34
|
import type { ResolutionOutcome, ResolutionOutcomeRecorder } from '../resolution-outcome.js';
|
|
32
35
|
export type ScopeResolutionSubPhase = 'extracting' | 'analyzing types' | 'resolving references' | 'linking symbols';
|
|
@@ -58,6 +61,54 @@ interface RunScopeResolutionInput {
|
|
|
58
61
|
readonly treeCache?: {
|
|
59
62
|
get(filePath: string): unknown;
|
|
60
63
|
};
|
|
64
|
+
/**
|
|
65
|
+
* CFG/PDG opt-in (#2081 M1). When true, emit BasicBlock nodes + CFG edges
|
|
66
|
+
* from each ParsedFile's worker-built `cfgSideChannel` during Phase-4 graph
|
|
67
|
+
* emission (while the disk store is still live). Default/false ⇒ no CFG
|
|
68
|
+
* nodes or edges and a byte-identical graph.
|
|
69
|
+
*/
|
|
70
|
+
readonly pdg?: boolean;
|
|
71
|
+
/** Per-function CFG edge cap. `undefined` ⇒ {@link DEFAULT_MAX_CFG_EDGES_PER_FUNCTION};
|
|
72
|
+
* `0` ⇒ no cap (unlimited). */
|
|
73
|
+
readonly pdgMaxEdgesPerFunction?: number;
|
|
74
|
+
/** Per-function REACHING_DEF edge cap (#2082 M2). `undefined` ⇒
|
|
75
|
+
* {@link DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION}; `0` ⇒ no cap. */
|
|
76
|
+
readonly pdgMaxReachingDefEdgesPerFunction?: number;
|
|
77
|
+
/** Per-function CDG (control-dependence) edge cap (#2085 M5). `undefined` ⇒
|
|
78
|
+
* {@link DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION}; `0` ⇒ no cap. */
|
|
79
|
+
readonly pdgMaxCdgEdgesPerFunction?: number;
|
|
80
|
+
/** Per-function taint findings cap (#2083 M3, consumed by the U4 taint
|
|
81
|
+
* emit step in the pdg window). `undefined` ⇒
|
|
82
|
+
* `DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION` (200); `0` ⇒ no cap. */
|
|
83
|
+
readonly pdgMaxTaintFindingsPerFunction?: number;
|
|
84
|
+
/** Per-finding taint hop cap (#2083 M3 KTD6 — bounds the hop-encoded
|
|
85
|
+
* `reason`; consumed by the U4 taint emit step). `undefined` ⇒
|
|
86
|
+
* `DEFAULT_PDG_MAX_TAINT_HOPS` (32); `0` ⇒ no cap. */
|
|
87
|
+
readonly pdgMaxTaintHops?: number;
|
|
88
|
+
/**
|
|
89
|
+
* Streaming PDG-emit sink (#2202). When present (streaming on, full rebuild),
|
|
90
|
+
* the `--pdg` emit routes BasicBlock nodes + intra-file PDG edges to THIS
|
|
91
|
+
* graph-shaped target instead of the in-memory `graph`, so the bulky PDG
|
|
92
|
+
* layer never accumulates in memory (peak RSS O(chunk)). Typed as a plain
|
|
93
|
+
* `KnowledgeGraph` so this module stays decoupled from the persistence layer;
|
|
94
|
+
* the caller (the scope-resolution phase) owns its lifecycle and finalizes it
|
|
95
|
+
* after the last language. Absent ⇒ the emit writes to `graph` as before
|
|
96
|
+
* (byte-identical default).
|
|
97
|
+
*/
|
|
98
|
+
readonly pdgEmitSink?: KnowledgeGraph;
|
|
99
|
+
/**
|
|
100
|
+
* Cross-pass per-file dedup set for streaming PDG emit (#2202). Shared across
|
|
101
|
+
* every language pass (owned by the scope-resolution phase). A file imported
|
|
102
|
+
* by more than one language (e.g. a `.ts` module pulled into the Vue context
|
|
103
|
+
* pass) is PDG-emitted in each pass over the same `cfgSideChannel`, producing
|
|
104
|
+
* identical ids; the in-memory graph dedups that by id, but the streaming sink
|
|
105
|
+
* is dedup-free (to stay O(write buffer), not O(total ids)). So when present
|
|
106
|
+
* (streaming on), the emit loop skips a file whose PDG already streamed and
|
|
107
|
+
* records the rest — keeping the streamed set byte-identical to the
|
|
108
|
+
* Map-deduped whole-graph emit, for any language-pass order. Absent ⇒ no skip
|
|
109
|
+
* (the graph Map dedups), so the default path is unchanged.
|
|
110
|
+
*/
|
|
111
|
+
readonly pdgEmittedFiles?: Set<string>;
|
|
61
112
|
/**
|
|
62
113
|
* Optional graph-node lookup built ONCE by the caller and shared across
|
|
63
114
|
* every language pass. `buildGraphNodeLookup` scans the whole graph and is
|
|
@@ -70,6 +121,14 @@ interface RunScopeResolutionInput {
|
|
|
70
121
|
* base is safe.
|
|
71
122
|
*/
|
|
72
123
|
readonly prebuiltNodeLookup?: ReturnType<typeof buildGraphNodeLookup>;
|
|
124
|
+
/**
|
|
125
|
+
* Functionish-node index built ONCE by the caller and shared across every
|
|
126
|
+
* language pass (#2084 review P2-6). Like `prebuiltNodeLookup`,
|
|
127
|
+
* `buildFunctionNodeIndex` is a whole-graph scan and is language-agnostic, so
|
|
128
|
+
* rebuilding it per language wastes a full scan each time. When omitted
|
|
129
|
+
* (tests / isolated calls) it is built locally for the pdg-enabled language.
|
|
130
|
+
*/
|
|
131
|
+
readonly prebuiltFunctionNodeIndex?: FunctionNodeIndex;
|
|
73
132
|
/**
|
|
74
133
|
* Opaque per-language import-resolution config (e.g. tsconfig path
|
|
75
134
|
* aliases for TypeScript). Loaded once by the caller via
|
|
@@ -127,6 +186,22 @@ interface RunScopeResolutionStats {
|
|
|
127
186
|
readonly referenceEdgesEmitted: number;
|
|
128
187
|
readonly referenceSkipped: number;
|
|
129
188
|
readonly resolutionOutcomes: readonly ResolutionOutcome[];
|
|
189
|
+
/**
|
|
190
|
+
* Per-function taint summaries harvested in the pdg window (#2084 M4 U1).
|
|
191
|
+
* Empty unless `input.pdg === true` and the language has a registered taint
|
|
192
|
+
* model. Keyed by resolved `Function`/`Method` node id; the cross-function
|
|
193
|
+
* fixpoint phase composes them over the complete `CALLS` graph.
|
|
194
|
+
*/
|
|
195
|
+
readonly functionSummaries: readonly FunctionSummary[];
|
|
196
|
+
/**
|
|
197
|
+
* Per-function RETURN-VALUE ASCENT summaries harvested in the pdg window
|
|
198
|
+
* (PDG FU-C, U-C2). Empty unless `input.pdg === true`. Keyed by resolved
|
|
199
|
+
* `Function`/`Method`/`Constructor` node id; the whole-program CALL_SUMMARY
|
|
200
|
+
* emit phase materialises one self-loop edge per entry once the call graph is
|
|
201
|
+
* known. Unlike {@link functionSummaries} this needs NO taint model — it is
|
|
202
|
+
* pure data-dependence — so it is harvested for every `--pdg` language.
|
|
203
|
+
*/
|
|
204
|
+
readonly callSummaries: readonly CallSummary[];
|
|
130
205
|
}
|
|
131
206
|
export declare function runScopeResolution(input: RunScopeResolutionInput, provider: ScopeResolver): RunScopeResolutionStats;
|
|
132
207
|
export {};
|
|
@@ -30,12 +30,20 @@ import { extractParsedFile } from '../../scope-extractor-bridge.js';
|
|
|
30
30
|
import { finalizeScopeModel } from '../../finalize-orchestrator.js';
|
|
31
31
|
import { resolveReferenceSites } from '../../resolve-references.js';
|
|
32
32
|
import { buildGraphNodeLookup } from '../graph-bridge/node-lookup.js';
|
|
33
|
+
import { emitFileCfgs, emitFileReachingDefs, emitFileCdg, isEmitSafeCfg, DEFAULT_MAX_CFG_EDGES_PER_FUNCTION, DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION, DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION, DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION, REACHING_DEF_FACTS_PER_EDGE_CAP, } from '../../cfg/emit.js';
|
|
34
|
+
import { createMemoizedReachingDefs } from '../../cfg/reaching-defs.js';
|
|
35
|
+
import { emitFileTaint, DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION, DEFAULT_PDG_MAX_TAINT_HOPS, } from '../../taint/emit.js';
|
|
36
|
+
import { registerBuiltinTaintModels } from '../../taint/typescript-model.js';
|
|
37
|
+
import { getSourceSinkConfig } from '../../taint/source-sink-registry.js';
|
|
38
|
+
import { buildFunctionNodeIndex, harvestFileSummaries, } from '../../taint/summary-harvest-driver.js';
|
|
39
|
+
import { harvestFileCallSummaries } from '../../taint/summary-harvest-driver.js';
|
|
33
40
|
import { resolveDefGraphId } from '../graph-bridge/ids.js';
|
|
34
41
|
import { buildPopulatedMethodDispatch } from '../graph-bridge/method-dispatch.js';
|
|
35
42
|
import { propagateImportedReturnTypes } from '../passes/imported-return-types.js';
|
|
36
43
|
import { emitReceiverBoundCalls } from '../passes/receiver-bound-calls.js';
|
|
37
44
|
import { emitFreeCallFallback } from '../passes/free-call-fallback.js';
|
|
38
45
|
import { emitReferencesViaLookup } from '../graph-bridge/references-to-edges.js';
|
|
46
|
+
import { createCalleeIdAccumulator, } from '../graph-bridge/callee-id-sink.js';
|
|
39
47
|
import { emitImportEdges } from '../graph-bridge/imports-to-edges.js';
|
|
40
48
|
import { findEnclosingClassDef, resolveInheritanceBaseInScope } from '../scope/walkers.js';
|
|
41
49
|
import { buildWorkspaceResolutionIndex } from '../workspace-index.js';
|
|
@@ -286,6 +294,8 @@ export function runScopeResolution(input, provider) {
|
|
|
286
294
|
referenceEdgesEmitted: 0,
|
|
287
295
|
referenceSkipped: 0,
|
|
288
296
|
resolutionOutcomes,
|
|
297
|
+
functionSummaries: [],
|
|
298
|
+
callSummaries: [],
|
|
289
299
|
};
|
|
290
300
|
}
|
|
291
301
|
const tExtract = PROF ? process.hrtime.bigint() : 0n;
|
|
@@ -427,8 +437,15 @@ export function runScopeResolution(input, provider) {
|
|
|
427
437
|
// ── Phase 4: emit graph edges (LOAD-BEARING ORDER — see I1) ────────────
|
|
428
438
|
input.onProgress?.('linking symbols', files.length, files.length);
|
|
429
439
|
const handledSites = new Set(preEmittedInheritanceSites);
|
|
440
|
+
// Resolved-callee-id capture accumulator (#2227 U2). Created ONLY under
|
|
441
|
+
// `--pdg` — `undefined` otherwise so the three emitters do zero work and emit
|
|
442
|
+
// byte-identical output (R4). Populated below at all three CALLS emit paths
|
|
443
|
+
// (each before its dedup, KTD6/R8); consumed by the CFG-emit join (U3) at
|
|
444
|
+
// `emitFileCfgs` below to produce `BasicBlock.calleeIds`.
|
|
445
|
+
const calleeIdAccumulator = input.pdg === true ? createCalleeIdAccumulator() : undefined;
|
|
430
446
|
const receiverExtras = emitReceiverBoundCalls(graph, indexes, emitParsedFiles, postHeritageNodeLookup, handledSites, provider, workspaceIndex, readonlyModel, {
|
|
431
447
|
recordResolutionOutcome,
|
|
448
|
+
calleeIdSink: calleeIdAccumulator,
|
|
432
449
|
});
|
|
433
450
|
const unresolvedReceiverExtras = provider.emitUnresolvedReceiverEdges !== undefined
|
|
434
451
|
? provider.emitUnresolvedReceiverEdges(graph, indexes, emitParsedFiles, postHeritageNodeLookup, handledSites, readonlyModel)
|
|
@@ -440,10 +457,12 @@ export function runScopeResolution(input, provider) {
|
|
|
440
457
|
isCallableVisibleFromCaller: provider.isCallableVisibleFromCaller,
|
|
441
458
|
resolveAdlCandidates: provider.resolveAdlCandidates,
|
|
442
459
|
conversionRankFn: provider.conversionRankFn,
|
|
460
|
+
conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
|
|
443
461
|
constraintCompatibility: provider.constraintCompatibility,
|
|
444
462
|
recordResolutionOutcome,
|
|
463
|
+
calleeIdSink: calleeIdAccumulator,
|
|
445
464
|
});
|
|
446
|
-
const { emitted, skipped } = emitReferencesViaLookup(graph, indexes, referenceIndex, postHeritageNodeLookup, handledSites);
|
|
465
|
+
const { emitted, skipped } = emitReferencesViaLookup(graph, indexes, referenceIndex, postHeritageNodeLookup, handledSites, calleeIdAccumulator);
|
|
447
466
|
const importsEmitted = emitImportEdges(graph, indexes.imports, indexes.scopeTree, provider.importEdgeReason);
|
|
448
467
|
// Language-specific supplementary edges (e.g. Vue template-derived
|
|
449
468
|
// BINDS_EVENT_HANDLER / EMITS_EVENT / CALLS / ACCESSES edges).
|
|
@@ -454,6 +473,330 @@ export function runScopeResolution(input, provider) {
|
|
|
454
473
|
resolutionConfig,
|
|
455
474
|
});
|
|
456
475
|
}
|
|
476
|
+
// ── CFG/PDG emission (#2081 M1, opt-in via `--pdg`) ──────────────────────
|
|
477
|
+
// Emit BasicBlock nodes + CFG edges from each ParsedFile's worker-built
|
|
478
|
+
// `cfgSideChannel`, HERE — the last point inside scope-resolution where the
|
|
479
|
+
// ParsedFiles are still loaded (`emitParsedFiles` carries the channel; the
|
|
480
|
+
// disk store is cleared right after this orchestrator returns, see phase.ts).
|
|
481
|
+
// A post-`mro` phase would read empty data (KTD1). Off by default ⇒ zero
|
|
482
|
+
// BasicBlock/CFG nodes/edges and a byte-identical graph.
|
|
483
|
+
// Accumulated M2 reaching-defs time (solve + dedup + REACHING_DEF emit),
|
|
484
|
+
// reported as the PROF `pdg=` segment. It is a SUBSET of `emit=` — the M1
|
|
485
|
+
// CFG emit and the M2 solve interleave per file, so a separate checkpoint
|
|
486
|
+
// pair can't bracket them; without this accumulator the M2 cost would
|
|
487
|
+
// silently disappear into `emit=` and field regressions would be invisible.
|
|
488
|
+
let pdgMs = 0;
|
|
489
|
+
// M4 (#2084 U1): per-function taint summaries harvested in the pdg window,
|
|
490
|
+
// returned on the stats for the cross-function fixpoint phase. Function-scoped
|
|
491
|
+
// so the return (below the pdg block) can read it; empty on non-pdg runs.
|
|
492
|
+
const harvestedSummaries = [];
|
|
493
|
+
let summaryUnresolved = 0;
|
|
494
|
+
// FU-C (U-C2): per-function RETURN-VALUE ASCENT summaries harvested in the
|
|
495
|
+
// pdg window for the whole-program CALL_SUMMARY emit phase. Function-scoped
|
|
496
|
+
// (read by the return below the pdg block); empty on non-pdg runs.
|
|
497
|
+
const harvestedCallSummaries = [];
|
|
498
|
+
let callSummaryUnresolved = 0;
|
|
499
|
+
// M3 (#2083 U4): accumulated taint time (match + taint-side solve +
|
|
500
|
+
// propagate + TAINTED/SANITIZES emit), a sibling of `pdgMs` for the same
|
|
501
|
+
// reason — it interleaves per file inside `emit=`, so only an accumulator
|
|
502
|
+
// can bracket it. Printed as the PROF `taint=` segment.
|
|
503
|
+
let taintMs = 0;
|
|
504
|
+
if (input.pdg === true) {
|
|
505
|
+
// Streaming target (#2202): when a sink is provided, BasicBlock nodes +
|
|
506
|
+
// intra-file PDG edges are routed to CSV-on-disk through it instead of
|
|
507
|
+
// accumulating in `graph`. The function-node index below is still built
|
|
508
|
+
// from the real `graph` (Function/Method nodes live there, never the sink).
|
|
509
|
+
const pdgTarget = input.pdgEmitSink ?? graph;
|
|
510
|
+
let cfgBlocks = 0;
|
|
511
|
+
let cfgEdges = 0;
|
|
512
|
+
let cfgDroppedEdges = 0;
|
|
513
|
+
let rdEdges = 0;
|
|
514
|
+
let rdDropped = 0;
|
|
515
|
+
let rdFacts = 0;
|
|
516
|
+
let rdTruncated = 0;
|
|
517
|
+
let cdgEdges = 0;
|
|
518
|
+
let cdgDropped = 0;
|
|
519
|
+
let cdgSkippedUnsound = 0;
|
|
520
|
+
// ── M3 taint setup (#2083 U4) ────────────────────────────────────────
|
|
521
|
+
// Explicit model-registration seam (idempotent, cheap) — the registry
|
|
522
|
+
// stays empty on non-pdg runs, preserving default-run parity. The
|
|
523
|
+
// registry is keyed by `SupportedLanguages` enum VALUES ('typescript' /
|
|
524
|
+
// 'javascript'), and `ScopeResolver.language` IS a `SupportedLanguages`
|
|
525
|
+
// member registered under those same constants — the join is direct
|
|
526
|
+
// equality, no mapping table. A language without a registered spec
|
|
527
|
+
// (python, go, …) skips taint entirely: no work, no warn spam (KTD8).
|
|
528
|
+
registerBuiltinTaintModels();
|
|
529
|
+
const taintSpec = getSourceSinkConfig(provider.language);
|
|
530
|
+
// Taint-side solver fact cap: the SAME derivation emitFileReachingDefs
|
|
531
|
+
// uses for the RD projection (edge cap × headroom factor, 0 ⇒ unlimited),
|
|
532
|
+
// so taint coverage and RD coverage truncate together — a function is
|
|
533
|
+
// never a taint coverage gap while its RD projection computed, and the
|
|
534
|
+
// RD layer's per-function truncation warn already names it.
|
|
535
|
+
const rdEdgeCap = input.pdgMaxReachingDefEdgesPerFunction ?? DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION;
|
|
536
|
+
const taintLimits = {
|
|
537
|
+
maxFindingsPerFunction: input.pdgMaxTaintFindingsPerFunction ?? DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION,
|
|
538
|
+
maxHops: input.pdgMaxTaintHops ?? DEFAULT_PDG_MAX_TAINT_HOPS,
|
|
539
|
+
maxFacts: rdEdgeCap > 0 ? rdEdgeCap * REACHING_DEF_FACTS_PER_EDGE_CAP : 0,
|
|
540
|
+
};
|
|
541
|
+
// Cross-file aggregate of EVERY TaintEmitResult counter (the M2 emit
|
|
542
|
+
// result shipped with two fields dropped on the floor — R4 forbids that
|
|
543
|
+
// here; gaps/drops feed the unconditional warn below, volume feeds the
|
|
544
|
+
// per-language debug line).
|
|
545
|
+
const taintTotals = {
|
|
546
|
+
analyzed: 0,
|
|
547
|
+
noMatch: 0,
|
|
548
|
+
unsafeSites: 0,
|
|
549
|
+
gapTruncated: 0,
|
|
550
|
+
gapOverflow: 0,
|
|
551
|
+
gapNoFacts: 0,
|
|
552
|
+
findings: 0,
|
|
553
|
+
kills: 0,
|
|
554
|
+
dropped: 0,
|
|
555
|
+
hopsTruncated: 0,
|
|
556
|
+
gapExamples: [],
|
|
557
|
+
dropExamples: [],
|
|
558
|
+
};
|
|
559
|
+
// M4 (#2084 U1): per-function summary harvest. The functionish-node index
|
|
560
|
+
// is built ONCE (whole-graph scan) and reused across every file; summaries
|
|
561
|
+
// accumulate here and ride out on the stats for the cross-function fixpoint
|
|
562
|
+
// phase. Only built when the language has a registered taint model.
|
|
563
|
+
// Built whenever pdg is on (NOT gated on taintSpec): the FU-C call-summary
|
|
564
|
+
// harvest needs it for EVERY language (it is pure data-dependence, no taint
|
|
565
|
+
// model), and the taint summary harvest reuses it when taintSpec is present.
|
|
566
|
+
const fnNodeIndex = input.prebuiltFunctionNodeIndex ?? buildFunctionNodeIndex(graph);
|
|
567
|
+
for (const pf of emitParsedFiles) {
|
|
568
|
+
const cfgs = pf.cfgSideChannel;
|
|
569
|
+
// Defensive: cfgSideChannel is opaque (`unknown`) and crosses the cache /
|
|
570
|
+
// durable store. A stale or wrong-shape value (e.g. a pre-SCHEMA_BUMP
|
|
571
|
+
// shard that slipped the version gate) must skip emission, not throw a
|
|
572
|
+
// TypeError mid-graph-build and abort scope-resolution for the language.
|
|
573
|
+
if (!Array.isArray(cfgs) || cfgs.length === 0)
|
|
574
|
+
continue;
|
|
575
|
+
// Cross-pass per-file dedup (#2202): when streaming, a file whose PDG
|
|
576
|
+
// already streamed in a prior language pass (e.g. a `.ts` module pulled
|
|
577
|
+
// into the Vue context pass) would re-emit identical ids from the same
|
|
578
|
+
// cfgSideChannel — the dedup-free streaming sink would double the rows.
|
|
579
|
+
// Skip it here; the in-memory-graph path needs no skip (its Map dedups).
|
|
580
|
+
if (input.pdgEmittedFiles !== undefined) {
|
|
581
|
+
if (input.pdgEmittedFiles.has(pf.filePath))
|
|
582
|
+
continue;
|
|
583
|
+
input.pdgEmittedFiles.add(pf.filePath);
|
|
584
|
+
}
|
|
585
|
+
try {
|
|
586
|
+
// Per-element emit-safety filter (mirrors the parsedfile-store
|
|
587
|
+
// reviver's POLICY: valid elements in a mixed array still emit; junk
|
|
588
|
+
// is warned and skipped). isEmitSafeCfg lives in cfg/emit.ts next to
|
|
589
|
+
// the id templating it defends — see its doc for why anchor-field and
|
|
590
|
+
// endpoint-membership checks are load-bearing. Runs INSIDE the try so
|
|
591
|
+
// even a predicate-time throw (e.g. a hostile getter) is isolated.
|
|
592
|
+
const wellFormed = cfgs.filter(isEmitSafeCfg);
|
|
593
|
+
if (wellFormed.length < cfgs.length) {
|
|
594
|
+
logger.warn(`[cfg] ${pf.filePath}: skipped ${cfgs.length - wellFormed.length} malformed ` +
|
|
595
|
+
`cfgSideChannel element(s) (bad shape, missing id-anchor fields, or edge ` +
|
|
596
|
+
`endpoints matching no block) — CFG for those functions omitted`);
|
|
597
|
+
}
|
|
598
|
+
if (wellFormed.length === 0)
|
|
599
|
+
continue;
|
|
600
|
+
// U3 hook (#2227): the resolved-callee-id map for this file is
|
|
601
|
+
// `calleeIdAccumulator?.get(pf.filePath)` — joined here by exact
|
|
602
|
+
// call-site position to emit `BasicBlock.calleeIds`. Captured above at
|
|
603
|
+
// the three CALLS emit paths (U2); wired into `emitFileCfgs` by U3.
|
|
604
|
+
const emitted = emitFileCfgs(pdgTarget, wellFormed, input.pdgMaxEdgesPerFunction ?? DEFAULT_MAX_CFG_EDGES_PER_FUNCTION,
|
|
605
|
+
// Log cap-overflow drops UNCONDITIONALLY (not via input.onWarn, which is
|
|
606
|
+
// gated behind the semantic-model validator and silent in production) so
|
|
607
|
+
// the per-function edge cap never truncates the CFG silently (R6/KTD6).
|
|
608
|
+
(message) => logger.warn(message),
|
|
609
|
+
// U3 (#2227): the resolved-callee-id map for this file (captured at the
|
|
610
|
+
// three CALLS emit paths in U2), joined by exact call-site position to
|
|
611
|
+
// emit `BasicBlock.calleeIds`. `undefined` when pdg is off (the
|
|
612
|
+
// accumulator is only created under `input.pdg === true`).
|
|
613
|
+
calleeIdAccumulator?.get(pf.filePath));
|
|
614
|
+
cfgBlocks += emitted.blocks;
|
|
615
|
+
cfgEdges += emitted.edges;
|
|
616
|
+
cfgDroppedEdges += emitted.droppedEdges;
|
|
617
|
+
// R6 (#2227 tri-review-2): release this file's captured id map now that
|
|
618
|
+
// emitFileCfgs has consumed it — the CALLS passes fully precede this loop
|
|
619
|
+
// and each file is read exactly once, so this bounds the accumulator to one
|
|
620
|
+
// file's call sites instead of holding the whole repo's for the phase.
|
|
621
|
+
calleeIdAccumulator?.delete(pf.filePath);
|
|
622
|
+
// M2 (#2082 U4): reaching definitions over the same validated CFGs.
|
|
623
|
+
// In-memory facts are computed per function and dropped after the
|
|
624
|
+
// bounded (defBlock, useBlock, binding) projection is persisted —
|
|
625
|
+
// M3 recomputes via the same pure solver in-phase (KTD8). Timing is
|
|
626
|
+
// PROF-gated like every other checkpoint here (zero cost when off).
|
|
627
|
+
// U12: one memoized RD solver per file, shared by the RD-emit + call-
|
|
628
|
+
// summary + taint + summary passes, so the per-function fixpoint runs once
|
|
629
|
+
// per (limits) bucket instead of 3–4× (#2227 tri-review). File-scoped: it
|
|
630
|
+
// is re-created each iteration, so its per-function facts drop with the file.
|
|
631
|
+
const rdSolve = createMemoizedReachingDefs();
|
|
632
|
+
const t0 = PROF ? performance.now() : 0;
|
|
633
|
+
const rd = emitFileReachingDefs(pdgTarget, wellFormed, input.pdgMaxReachingDefEdgesPerFunction ??
|
|
634
|
+
DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION, (message) => logger.warn(message), // unconditional — R7, both layers
|
|
635
|
+
rdSolve);
|
|
636
|
+
if (PROF)
|
|
637
|
+
pdgMs += performance.now() - t0;
|
|
638
|
+
rdEdges += rd.edges;
|
|
639
|
+
rdDropped += rd.droppedEdges;
|
|
640
|
+
rdFacts += rd.facts;
|
|
641
|
+
rdTruncated += rd.truncatedFunctions;
|
|
642
|
+
// M5 (#2085 U5): control dependence over the SAME validated CFGs.
|
|
643
|
+
// Independent of taint — runs for every `--pdg` language (post-dom +
|
|
644
|
+
// Ferrante are language-agnostic, no source/sink model needed). Pure
|
|
645
|
+
// compute; the bounded (controller, dependent, label) projection is
|
|
646
|
+
// persisted and its time folds into the `pdg=` PROF segment next to RD.
|
|
647
|
+
const tCdg = PROF ? performance.now() : 0;
|
|
648
|
+
const cdg = emitFileCdg(pdgTarget, wellFormed, input.pdgMaxCdgEdgesPerFunction ?? DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION, (message) => logger.warn(message));
|
|
649
|
+
if (PROF)
|
|
650
|
+
pdgMs += performance.now() - tCdg;
|
|
651
|
+
cdgEdges += cdg.edges;
|
|
652
|
+
cdgDropped += cdg.droppedEdges;
|
|
653
|
+
cdgSkippedUnsound += cdg.skippedUnsoundFunctions;
|
|
654
|
+
// FU-C (U-C2): RETURN-VALUE ASCENT summaries over the SAME validated
|
|
655
|
+
// CFGs, inside the SAME per-file try. Independent of taint — runs for
|
|
656
|
+
// EVERY `--pdg` language (pure data-dependence, no source/sink model).
|
|
657
|
+
// Reuses the same RD fact cap the RD/taint solves use (coverage parity).
|
|
658
|
+
const callHarvest = harvestFileCallSummaries(fnNodeIndex, wellFormed, taintLimits.maxFacts && taintLimits.maxFacts > 0
|
|
659
|
+
? taintLimits.maxFacts
|
|
660
|
+
: DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION, rdSolve);
|
|
661
|
+
harvestedCallSummaries.push(...callHarvest.summaries);
|
|
662
|
+
callSummaryUnresolved += callHarvest.unresolved;
|
|
663
|
+
// M3 (#2083 U4): taint over the SAME validated CFGs, inside the SAME
|
|
664
|
+
// per-file try (a taint throw costs this file's taint layer only —
|
|
665
|
+
// its CFG/REACHING_DEF edges above are already in the graph). Skipped
|
|
666
|
+
// entirely when the language has no registered model.
|
|
667
|
+
if (taintSpec !== undefined) {
|
|
668
|
+
const t1 = PROF ? performance.now() : 0;
|
|
669
|
+
const taint = emitFileTaint(pdgTarget, wellFormed, pf.parsedImports, taintSpec, taintLimits, (message) => logger.warn(message), // unconditional — R4/R6
|
|
670
|
+
rdSolve);
|
|
671
|
+
if (PROF)
|
|
672
|
+
taintMs += performance.now() - t1;
|
|
673
|
+
taintTotals.analyzed += taint.functionsAnalyzed;
|
|
674
|
+
taintTotals.noMatch += taint.functionsSkippedNoMatch;
|
|
675
|
+
taintTotals.unsafeSites += taint.functionsSkippedUnsafeSites;
|
|
676
|
+
taintTotals.gapTruncated += taint.functionsCoverageGap.truncated;
|
|
677
|
+
taintTotals.gapOverflow += taint.functionsCoverageGap.overflow;
|
|
678
|
+
taintTotals.gapNoFacts += taint.functionsCoverageGap['no-facts'];
|
|
679
|
+
taintTotals.findings += taint.findingsEmitted;
|
|
680
|
+
taintTotals.kills += taint.killsEmitted;
|
|
681
|
+
taintTotals.dropped += taint.findingsDropped;
|
|
682
|
+
taintTotals.hopsTruncated += taint.hopsTruncatedFindings;
|
|
683
|
+
for (const ex of taint.coverageGapExamples) {
|
|
684
|
+
if (taintTotals.gapExamples.length < 5)
|
|
685
|
+
taintTotals.gapExamples.push(ex);
|
|
686
|
+
}
|
|
687
|
+
for (const ex of taint.droppedExamples) {
|
|
688
|
+
if (taintTotals.dropExamples.length < 5)
|
|
689
|
+
taintTotals.dropExamples.push(ex);
|
|
690
|
+
}
|
|
691
|
+
// M4 (#2084 U1): harvest per-function summaries over the SAME
|
|
692
|
+
// emit-safe CFGs, inside the SAME per-file try. Pure aside from the
|
|
693
|
+
// read-only node-index lookup; the cross-function fixpoint phase
|
|
694
|
+
// consumes `harvestedSummaries` once the whole call graph is built.
|
|
695
|
+
if (fnNodeIndex !== undefined) {
|
|
696
|
+
const harvest = harvestFileSummaries(fnNodeIndex, wellFormed, pf.parsedImports, taintSpec,
|
|
697
|
+
// Same fact cap the taint-side RD solve uses (coverage parity).
|
|
698
|
+
taintLimits.maxFacts && taintLimits.maxFacts > 0
|
|
699
|
+
? taintLimits.maxFacts
|
|
700
|
+
: DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION, rdSolve);
|
|
701
|
+
harvestedSummaries.push(...harvest.summaries);
|
|
702
|
+
summaryUnresolved += harvest.unresolved;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
catch (err) {
|
|
707
|
+
// Last-resort isolation, mirroring the worker-side per-file try/catch:
|
|
708
|
+
// a shape the predicate misses must cost this one file's CFG, not
|
|
709
|
+
// abort the language's whole scope-resolution pass mid-graph-build.
|
|
710
|
+
// NOTE a mid-emit throw can leave this file's already-inserted
|
|
711
|
+
// BasicBlock nodes in the graph (addNode is not transactional) —
|
|
712
|
+
// orphaned but inert; the predicate keeps every JSON-representable
|
|
713
|
+
// bad shape from reaching this path at all.
|
|
714
|
+
logger.warn(`[cfg] ${pf.filePath}: CFG emission failed (${err instanceof Error ? err.message : String(err)}) — ` +
|
|
715
|
+
`this file's CFG is partial or absent`);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
if (cfgBlocks > 0) {
|
|
719
|
+
logger.debug(`[scope-resolution] CFG emit (lang=${provider.language}): ` +
|
|
720
|
+
`${cfgBlocks} BasicBlock nodes, ${cfgEdges} CFG edges` +
|
|
721
|
+
(cfgDroppedEdges > 0 ? `, ${cfgDroppedEdges} edges dropped (per-function cap)` : '') +
|
|
722
|
+
`; ${rdEdges} REACHING_DEF edges (${rdFacts} facts)` +
|
|
723
|
+
(rdDropped > 0 ? `, ${rdDropped} REACHING_DEF edges dropped (per-function cap)` : '') +
|
|
724
|
+
(rdTruncated > 0 ? `, ${rdTruncated} function(s) hit the fact limit` : '') +
|
|
725
|
+
`; ${cdgEdges} CDG edges` +
|
|
726
|
+
(cdgDropped > 0 ? `, ${cdgDropped} CDG edges dropped (per-function cap)` : '') +
|
|
727
|
+
(cdgSkippedUnsound > 0
|
|
728
|
+
? `, ${cdgSkippedUnsound} function(s) CDG-skipped (EXIT not reachable from all blocks)`
|
|
729
|
+
: '') +
|
|
730
|
+
// M3 volume telemetry — only for languages with a registered model.
|
|
731
|
+
(taintSpec !== undefined
|
|
732
|
+
? `; taint: ${taintTotals.findings} TAINTED, ${taintTotals.kills} SANITIZES ` +
|
|
733
|
+
`(${taintTotals.analyzed} function(s) analyzed, ` +
|
|
734
|
+
`${taintTotals.noMatch} skipped: no source/sink match` +
|
|
735
|
+
(taintTotals.hopsTruncated > 0
|
|
736
|
+
? `, ${taintTotals.hopsTruncated} finding(s) with truncated hop paths`
|
|
737
|
+
: '') +
|
|
738
|
+
`)`
|
|
739
|
+
: ''));
|
|
740
|
+
}
|
|
741
|
+
// R8 (#2195): CDG soundness skips surface UNCONDITIONALLY (parity with the
|
|
742
|
+
// taint/RD gap warns) — not buried in the logger.debug stats line above. A
|
|
743
|
+
// function whose EXIT is not reverse-reachable from every block gets NO
|
|
744
|
+
// control dependence (an unmodeled non-terminating / multi-terminal CFG
|
|
745
|
+
// shape the synthetic-escape pass could not bridge). Withholding CDG
|
|
746
|
+
// silently would let a language's control dependence erode unnoticed; CFG
|
|
747
|
+
// and REACHING_DEF do not depend on post-dominance and are unaffected.
|
|
748
|
+
if (cdgSkippedUnsound > 0) {
|
|
749
|
+
logger.warn(`[cfg] lang=${provider.language}: ${cdgSkippedUnsound} function(s) had control ` +
|
|
750
|
+
`dependence skipped (EXIT not reverse-reachable from all blocks); ` +
|
|
751
|
+
`CFG and REACHING_DEF are unaffected`);
|
|
752
|
+
}
|
|
753
|
+
// R4: taint coverage gaps and cap drops surface UNCONDITIONALLY (never
|
|
754
|
+
// logger.debug, never input.onWarn) at the per-language aggregate, with
|
|
755
|
+
// counts and up to 5 example functions. Per-function warns above cover
|
|
756
|
+
// the rare/actionable cases (unsafe sites, cap drops); solver-status gaps
|
|
757
|
+
// were already per-function-warned by the RD layer (same solver, same
|
|
758
|
+
// fact cap), so this aggregate is their single taint-side surface.
|
|
759
|
+
if (taintSpec !== undefined) {
|
|
760
|
+
const gapCount = taintTotals.unsafeSites +
|
|
761
|
+
taintTotals.gapTruncated +
|
|
762
|
+
taintTotals.gapOverflow +
|
|
763
|
+
taintTotals.gapNoFacts;
|
|
764
|
+
if (gapCount > 0 || taintTotals.dropped > 0) {
|
|
765
|
+
const parts = [];
|
|
766
|
+
if (gapCount > 0) {
|
|
767
|
+
parts.push(`${gapCount} function(s) skipped for taint ` +
|
|
768
|
+
`(${taintTotals.gapTruncated} fact-limit, ${taintTotals.gapOverflow} overflow, ` +
|
|
769
|
+
`${taintTotals.gapNoFacts} no-facts, ${taintTotals.unsafeSites} malformed sites)` +
|
|
770
|
+
(taintTotals.gapExamples.length > 0
|
|
771
|
+
? ` — e.g. ${taintTotals.gapExamples.join(', ')}`
|
|
772
|
+
: ''));
|
|
773
|
+
}
|
|
774
|
+
if (taintTotals.dropped > 0) {
|
|
775
|
+
parts.push(`${taintTotals.dropped} finding(s) dropped by the per-function cap` +
|
|
776
|
+
(taintTotals.dropExamples.length > 0
|
|
777
|
+
? ` — e.g. ${taintTotals.dropExamples.join(', ')}`
|
|
778
|
+
: ''));
|
|
779
|
+
}
|
|
780
|
+
logger.warn(`[taint] lang=${provider.language}: ${parts.join('; ')}`);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
// M4 (#2084 U1): summary harvest volume + anchor-resolution diagnostics.
|
|
784
|
+
if (harvestedSummaries.length > 0 || summaryUnresolved > 0) {
|
|
785
|
+
logger.debug(`[taint-summary] lang=${provider.language}: ${harvestedSummaries.length} function ` +
|
|
786
|
+
`summary/summaries harvested` +
|
|
787
|
+
(summaryUnresolved > 0
|
|
788
|
+
? `, ${summaryUnresolved} CFG anchor(s) unresolved (same-line collision or missing node)`
|
|
789
|
+
: ''));
|
|
790
|
+
}
|
|
791
|
+
// FU-C (U-C2): call-summary harvest volume + anchor-resolution diagnostics.
|
|
792
|
+
if (harvestedCallSummaries.length > 0 || callSummaryUnresolved > 0) {
|
|
793
|
+
logger.debug(`[call-summary] lang=${provider.language}: ${harvestedCallSummaries.length} function ` +
|
|
794
|
+
`return-ascent summary/summaries harvested` +
|
|
795
|
+
(callSummaryUnresolved > 0
|
|
796
|
+
? `, ${callSummaryUnresolved} CFG anchor(s) unresolved (same-line collision or missing node)`
|
|
797
|
+
: ''));
|
|
798
|
+
}
|
|
799
|
+
}
|
|
457
800
|
if (PROF) {
|
|
458
801
|
const tEnd = process.hrtime.bigint();
|
|
459
802
|
const ns = (a, b) => Number(b - a) / 1_000_000;
|
|
@@ -462,6 +805,9 @@ export function runScopeResolution(input, provider) {
|
|
|
462
805
|
` propagate=${ns(tFinalize, tPropagate).toFixed(0)}ms` +
|
|
463
806
|
` resolve=${ns(tPropagate, tResolve).toFixed(0)}ms` +
|
|
464
807
|
` emit=${ns(tResolve, tEnd).toFixed(0)}ms` +
|
|
808
|
+
// pdg ⊆ emit: the M2 reaching-defs share of the emit bucket (#2082 U4).
|
|
809
|
+
// taint ⊆ emit likewise: the M3 match+solve+propagate+emit share (#2083 U4).
|
|
810
|
+
(input.pdg === true ? ` pdg=${pdgMs.toFixed(0)}ms taint=${taintMs.toFixed(0)}ms` : '') +
|
|
465
811
|
` total=${ns(tStart, tEnd).toFixed(0)}ms` +
|
|
466
812
|
` (${parsedFiles.length} files)`);
|
|
467
813
|
}
|
|
@@ -474,5 +820,7 @@ export function runScopeResolution(input, provider) {
|
|
|
474
820
|
referenceEdgesEmitted: emitted + receiverExtras + unresolvedReceiverExtras + freeCallExtras,
|
|
475
821
|
referenceSkipped: skipped,
|
|
476
822
|
resolutionOutcomes,
|
|
823
|
+
functionSummaries: harvestedSummaries,
|
|
824
|
+
callSummaries: harvestedCallSummaries,
|
|
477
825
|
};
|
|
478
826
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Range } from '../../../_shared/index.js';
|
|
2
|
-
export type ResolutionSuppressionReason = 'adl-ordinary-lookup-blocked' | 'conversion-rank-tied' | 'inline-ns-ambiguous' | 'member-lookup-ambiguous' | 'overload-ambiguous' | 'overload-ambiguous-normalization';
|
|
2
|
+
export type ResolutionSuppressionReason = 'adl-ordinary-lookup-blocked' | 'conversion-rank-tied' | 'inline-ns-ambiguous' | 'member-lookup-ambiguous' | 'selected-callable-deleted' | 'overload-ambiguous' | 'overload-ambiguous-normalization';
|
|
3
3
|
export type ResolutionOutcome = {
|
|
4
4
|
readonly kind: 'resolved';
|
|
5
5
|
readonly targetId: string;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Call-summary reason codec (PDG FU-C, U-C2) — the ONE shared encoder/decoder
|
|
3
|
+
* for the bitset carried on persisted `CALL_SUMMARY` edges.
|
|
4
|
+
*
|
|
5
|
+
* A `CALL_SUMMARY` edge is a self-loop on a Function/Method/Constructor node
|
|
6
|
+
* recording that callee's RETURN-VALUE ASCENT: for each formal-parameter index,
|
|
7
|
+
* whether that parameter flows to the function's return value. The producer
|
|
8
|
+
* (the whole-program emit phase) writes this; a later consumer phase reads it to
|
|
9
|
+
* ascend a callee's return effect into the caller continuation. Two hand-rolled
|
|
10
|
+
* copies of a wire format drift — both sides MUST import from here (the same
|
|
11
|
+
* discipline `path-codec.ts` documents).
|
|
12
|
+
*
|
|
13
|
+
* ## Wire format (version `1`)
|
|
14
|
+
*
|
|
15
|
+
* ```
|
|
16
|
+
* 1|r:<hexbitset>[|<reserved-segment>…]
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* - One-character version prefix ({@link CALL_SUMMARY_CODEC_VERSION}), then `|`,
|
|
20
|
+
* then a `r:` (return) segment whose payload is the param→return bitset as a
|
|
21
|
+
* lowercase hex string (LSB = formal index 0). Bit `i` set ⇒ formal parameter
|
|
22
|
+
* `i` flows to the return value. An empty/zero bitset is the absence of any
|
|
23
|
+
* return-flow (a sound EMPTY summary — never a false claim).
|
|
24
|
+
* - FORWARD COMPATIBILITY: the format reserves space for future facts via
|
|
25
|
+
* additional trailing `|<tag>:<payload>` segments (planned: `o:` out-params,
|
|
26
|
+
* `e:` exception ascent — both deferred: out-params need an alias model,
|
|
27
|
+
* exception ascent needs try/catch CDG). The decoder accepts and ignores any
|
|
28
|
+
* trailing segment whose tag it does not understand, so a future writer's
|
|
29
|
+
* output stays decodable by today's reader (and vice-versa: today's reader
|
|
30
|
+
* only requires the `r:` segment). Reserved tags MUST stay disjoint from `r`.
|
|
31
|
+
*
|
|
32
|
+
* ## Delimiter / round-trip discipline (mirrors path-codec KTD6)
|
|
33
|
+
*
|
|
34
|
+
* Every structural character (`|`, `:`, the version digit, hex digits `[0-9a-f]`)
|
|
35
|
+
* is printable ASCII, so the encoding survives `escapeCSVField ∘ sanitizeUTF8`
|
|
36
|
+
* (csv-generator.ts) byte-exact (pinned by the round-trip test). The hex payload
|
|
37
|
+
* is a non-negative integer rendered via BigInt, so the codec handles functions
|
|
38
|
+
* with arbitrarily many formal parameters without overflow.
|
|
39
|
+
*
|
|
40
|
+
* The decoder NEVER throws — anything malformed yields a typed failure, exactly
|
|
41
|
+
* like `decodeTaintPath`. A decode failure on the consumer side means "no usable
|
|
42
|
+
* ascent fact", which is the sound default (never claim a false return-flow).
|
|
43
|
+
*/
|
|
44
|
+
/** One-character format version prefix. Bump on any wire-format change. */
|
|
45
|
+
export declare const CALL_SUMMARY_CODEC_VERSION = "1";
|
|
46
|
+
/** A decoded call summary's facts. Forward-compatible: future facts add fields. */
|
|
47
|
+
export interface DecodedCallSummary {
|
|
48
|
+
readonly ok: true;
|
|
49
|
+
readonly version: string;
|
|
50
|
+
/**
|
|
51
|
+
* Sorted, de-duplicated formal-parameter indices that flow to the return
|
|
52
|
+
* value (ascending). Empty ⇒ no return-flow recorded (sound EMPTY summary).
|
|
53
|
+
*/
|
|
54
|
+
readonly returnFlowParams: readonly number[];
|
|
55
|
+
}
|
|
56
|
+
/** Typed parse failure — the decoder never throws. */
|
|
57
|
+
export interface CallSummaryDecodeFailure {
|
|
58
|
+
readonly ok: false;
|
|
59
|
+
readonly error: string;
|
|
60
|
+
}
|
|
61
|
+
export type CallSummaryDecodeResult = DecodedCallSummary | CallSummaryDecodeFailure;
|
|
62
|
+
/**
|
|
63
|
+
* Encode the param→return ascent into the versioned `reason` wire string.
|
|
64
|
+
* Deterministic; never throws. `returnFlowParams` is the set of formal indices
|
|
65
|
+
* that flow to the return value (order/duplication irrelevant — the bitset
|
|
66
|
+
* canonicalises). An empty set encodes as `r:0` (an explicit empty summary).
|
|
67
|
+
*/
|
|
68
|
+
export declare function encodeCallSummary(returnFlowParams: Iterable<number>): string;
|
|
69
|
+
/**
|
|
70
|
+
* Decode a `CALL_SUMMARY` reason wire string into its ascent facts. Returns a
|
|
71
|
+
* typed failure for anything that is not a well-formed version-`1` summary —
|
|
72
|
+
* never throws. Unknown trailing segments (future facts) are accepted and
|
|
73
|
+
* ignored (forward compatibility).
|
|
74
|
+
*/
|
|
75
|
+
export declare function decodeCallSummary(reason: unknown): CallSummaryDecodeResult;
|