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
|
@@ -97,6 +97,32 @@ export function normalizeExtractedRoutePath(routePath, prefix) {
|
|
|
97
97
|
function escapeRegex(s) {
|
|
98
98
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
99
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Canonicalize a route's HTTP verb for persistence on the Route node.
|
|
102
|
+
* Returns an upper-cased standard method, or `undefined` when the value
|
|
103
|
+
* is not a real HTTP verb. Laravel `Route::resource` / `apiResource`
|
|
104
|
+
* surface `httpMethod` values like `resource` / `apiResource` (they
|
|
105
|
+
* expand to several verbs at runtime), so they must not be stored as a
|
|
106
|
+
* method — leaving them `undefined` keeps the column clean and lets the
|
|
107
|
+
* contract extractor fall back to its source-scan path for those routes.
|
|
108
|
+
*/
|
|
109
|
+
const VALID_HTTP_METHODS = new Set([
|
|
110
|
+
'GET',
|
|
111
|
+
'POST',
|
|
112
|
+
'PUT',
|
|
113
|
+
'PATCH',
|
|
114
|
+
'DELETE',
|
|
115
|
+
'HEAD',
|
|
116
|
+
'OPTIONS',
|
|
117
|
+
'TRACE',
|
|
118
|
+
'CONNECT',
|
|
119
|
+
]);
|
|
120
|
+
export function normalizeRouteMethod(raw) {
|
|
121
|
+
if (typeof raw !== 'string')
|
|
122
|
+
return undefined;
|
|
123
|
+
const verb = raw.trim().toUpperCase();
|
|
124
|
+
return VALID_HTTP_METHODS.has(verb) ? verb : undefined;
|
|
125
|
+
}
|
|
100
126
|
export const routesPhase = {
|
|
101
127
|
name: 'routes',
|
|
102
128
|
deps: ['parse'],
|
|
@@ -166,6 +192,7 @@ export const routesPhase = {
|
|
|
166
192
|
addRoute(routeUrl, {
|
|
167
193
|
filePath: route.filePath,
|
|
168
194
|
source: 'framework-route',
|
|
195
|
+
method: normalizeRouteMethod(route.httpMethod),
|
|
169
196
|
});
|
|
170
197
|
if (route.routeName && !namedRouteRegistry.has(route.routeName)) {
|
|
171
198
|
namedRouteRegistry.set(route.routeName, routeUrl);
|
|
@@ -176,6 +203,7 @@ export const routesPhase = {
|
|
|
176
203
|
addRoute(url, {
|
|
177
204
|
filePath: dr.filePath,
|
|
178
205
|
source: `decorator-${dr.decoratorName}`,
|
|
206
|
+
method: normalizeRouteMethod(dr.httpMethod),
|
|
179
207
|
});
|
|
180
208
|
}
|
|
181
209
|
let handlerContents;
|
|
@@ -183,7 +211,7 @@ export const routesPhase = {
|
|
|
183
211
|
const handlerPaths = [...routeRegistry.values()].map((e) => e.filePath);
|
|
184
212
|
handlerContents = await readFileContents(ctx.repoPath, handlerPaths);
|
|
185
213
|
for (const [routeURL, entry] of routeRegistry) {
|
|
186
|
-
const { filePath: handlerPath, source: routeSource } = entry;
|
|
214
|
+
const { filePath: handlerPath, source: routeSource, method: routeMethod } = entry;
|
|
187
215
|
const content = handlerContents.get(handlerPath);
|
|
188
216
|
const { responseKeys, errorKeys } = content
|
|
189
217
|
? handlerPath.endsWith('.php')
|
|
@@ -199,6 +227,7 @@ export const routesPhase = {
|
|
|
199
227
|
properties: {
|
|
200
228
|
name: routeURL,
|
|
201
229
|
filePath: handlerPath,
|
|
230
|
+
...(routeMethod ? { method: routeMethod } : {}),
|
|
202
231
|
...(responseKeys ? { responseKeys } : {}),
|
|
203
232
|
...(errorKeys ? { errorKeys } : {}),
|
|
204
233
|
...(middleware && middleware.length > 0 ? { middleware } : {}),
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase: taintSummaries (#2084 M4 U3/U5)
|
|
3
|
+
*
|
|
4
|
+
* The interprocedural taint fixpoint. Runs AFTER scope-resolution (where the
|
|
5
|
+
* complete, resolved `CALLS` graph lives in `ctx.graph` and the per-function
|
|
6
|
+
* summaries were harvested in-phase) and composes those summaries to find
|
|
7
|
+
* source→sink flows that cross function and file boundaries.
|
|
8
|
+
*
|
|
9
|
+
* Opt-in: registered with `enabledWhen: (o) => o.pdg === true` (the first real
|
|
10
|
+
* pdg-gated phase). A default `analyze` run never includes it, so the graph is
|
|
11
|
+
* byte-identical. No always-on phase depends on it (a filtered-out dep would
|
|
12
|
+
* throw in `getPhaseOutput`).
|
|
13
|
+
*
|
|
14
|
+
* @deps scopeResolution, pruneLocalSymbols
|
|
15
|
+
* @reads graph (CALLS edges, Function/Method nodes), scopeResolution output
|
|
16
|
+
* (functionSummaries)
|
|
17
|
+
* @writes graph (TAINT_PATH edges)
|
|
18
|
+
*/
|
|
19
|
+
import type { PipelinePhase } from './types.js';
|
|
20
|
+
export interface TaintSummariesOutput {
|
|
21
|
+
/** Function summaries fed to the fixpoint. */
|
|
22
|
+
summaries: number;
|
|
23
|
+
/** Cross-function findings (pre-cap). */
|
|
24
|
+
findings: number;
|
|
25
|
+
/** TAINT_PATH edges persisted. */
|
|
26
|
+
edgesEmitted: number;
|
|
27
|
+
/** Call sites whose callee did not resolve to a summary edge (diagnostics). */
|
|
28
|
+
unmatchedCallSites: number;
|
|
29
|
+
}
|
|
30
|
+
export declare const taintSummariesPhase: PipelinePhase<TaintSummariesOutput>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase: taintSummaries (#2084 M4 U3/U5)
|
|
3
|
+
*
|
|
4
|
+
* The interprocedural taint fixpoint. Runs AFTER scope-resolution (where the
|
|
5
|
+
* complete, resolved `CALLS` graph lives in `ctx.graph` and the per-function
|
|
6
|
+
* summaries were harvested in-phase) and composes those summaries to find
|
|
7
|
+
* source→sink flows that cross function and file boundaries.
|
|
8
|
+
*
|
|
9
|
+
* Opt-in: registered with `enabledWhen: (o) => o.pdg === true` (the first real
|
|
10
|
+
* pdg-gated phase). A default `analyze` run never includes it, so the graph is
|
|
11
|
+
* byte-identical. No always-on phase depends on it (a filtered-out dep would
|
|
12
|
+
* throw in `getPhaseOutput`).
|
|
13
|
+
*
|
|
14
|
+
* @deps scopeResolution, pruneLocalSymbols
|
|
15
|
+
* @reads graph (CALLS edges, Function/Method nodes), scopeResolution output
|
|
16
|
+
* (functionSummaries)
|
|
17
|
+
* @writes graph (TAINT_PATH edges)
|
|
18
|
+
*/
|
|
19
|
+
import { getPhaseOutput } from './types.js';
|
|
20
|
+
import { solveInterprocTaint, DEFAULT_MAX_INTERPROC_HOPS, DEFAULT_PDG_MAX_INTERPROC_FINDINGS, } from '../taint/interproc-solver.js';
|
|
21
|
+
import { emitInterprocTaint, DEFAULT_PDG_MAX_INTERPROC_EDGES } from '../taint/interproc-emit.js';
|
|
22
|
+
import { logger } from '../../logger.js';
|
|
23
|
+
const EMPTY = {
|
|
24
|
+
summaries: 0,
|
|
25
|
+
findings: 0,
|
|
26
|
+
edgesEmitted: 0,
|
|
27
|
+
unmatchedCallSites: 0,
|
|
28
|
+
};
|
|
29
|
+
export const taintSummariesPhase = {
|
|
30
|
+
name: 'taintSummaries',
|
|
31
|
+
deps: ['scopeResolution', 'pruneLocalSymbols'],
|
|
32
|
+
async execute(ctx, deps) {
|
|
33
|
+
const scope = getPhaseOutput(deps, 'scopeResolution');
|
|
34
|
+
const summaries = scope.functionSummaries;
|
|
35
|
+
if (summaries.length === 0)
|
|
36
|
+
return EMPTY;
|
|
37
|
+
// Index summaries by function node id.
|
|
38
|
+
const summaryMap = new Map(summaries.map((s) => [s.fnId, s]));
|
|
39
|
+
// Build the call-edge adjacency from resolved CALLS edges. The join to a
|
|
40
|
+
// summary's call-arg edge is by CALLEE NAME (base-independent — see the
|
|
41
|
+
// solver doc); recover it from the callee node's `name` property.
|
|
42
|
+
const callEdges = [];
|
|
43
|
+
for (const rel of ctx.graph.iterRelationshipsByType('CALLS')) {
|
|
44
|
+
const callee = ctx.graph.getNode(rel.targetId);
|
|
45
|
+
const calleeName = callee && typeof callee.properties.name === 'string' ? callee.properties.name : undefined;
|
|
46
|
+
if (calleeName === undefined)
|
|
47
|
+
continue;
|
|
48
|
+
callEdges.push({ callerId: rel.sourceId, calleeId: rel.targetId, calleeName });
|
|
49
|
+
}
|
|
50
|
+
// Arm the per-run caps (#2084 review P1-3) — every other pdg layer bounds
|
|
51
|
+
// its output via RepoMeta.pdg; without this the fixpoint state + TAINT_PATH
|
|
52
|
+
// edges grow unbounded on a fan-in-heavy repo (OOM). `0` ⇒ unlimited
|
|
53
|
+
// (preserved like the other pdg caps). The solver/emit already implement
|
|
54
|
+
// deterministic truncate-and-warn — this just hands them the budgets.
|
|
55
|
+
const maxFindings = ctx.options?.pdgMaxInterprocFindings ?? DEFAULT_PDG_MAX_INTERPROC_FINDINGS;
|
|
56
|
+
const maxHops = ctx.options?.pdgMaxInterprocHops ?? DEFAULT_MAX_INTERPROC_HOPS;
|
|
57
|
+
const maxEdges = ctx.options?.pdgMaxInterprocEdges ?? DEFAULT_PDG_MAX_INTERPROC_EDGES;
|
|
58
|
+
const solved = solveInterprocTaint(summaryMap, callEdges, { maxFindings, maxHops });
|
|
59
|
+
const emit = emitInterprocTaint(ctx.graph, solved.findings, { maxEdges }, (m) => logger.warn(m));
|
|
60
|
+
// Surface drops UNCONDITIONALLY (R4 — never silently truncate the layer).
|
|
61
|
+
if (solved.droppedFindings > 0 || emit.edgesDropped > 0) {
|
|
62
|
+
logger.warn(`[taint-interproc] capped: ${solved.droppedFindings} finding(s) dropped by the ` +
|
|
63
|
+
`per-run findings cap (${maxFindings}), ${emit.edgesDropped} edge(s) by the edge cap ` +
|
|
64
|
+
`(${maxEdges}) — raise pdgMaxInterprocFindings/pdgMaxInterprocEdges if intentional`);
|
|
65
|
+
}
|
|
66
|
+
if (solved.findings.length > 0 || emit.edgesEmitted > 0) {
|
|
67
|
+
logger.debug(`[taint-interproc] ${summaries.length} summaries, ${callEdges.length} CALLS edges → ` +
|
|
68
|
+
`${solved.findings.length} cross-function finding(s), ${emit.edgesEmitted} TAINT_PATH edge(s)` +
|
|
69
|
+
(emit.hopsTruncated > 0 ? `, ${emit.hopsTruncated} with truncated paths` : '') +
|
|
70
|
+
(solved.unmatchedCallSites > 0
|
|
71
|
+
? `, ${solved.unmatchedCallSites} unmatched call site(s)`
|
|
72
|
+
: ''));
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
summaries: summaries.length,
|
|
76
|
+
findings: solved.findings.length,
|
|
77
|
+
edgesEmitted: emit.edgesEmitted,
|
|
78
|
+
unmatchedCallSites: solved.unmatchedCallSites,
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
};
|
|
@@ -25,6 +25,98 @@ export interface PipelineOptions {
|
|
|
25
25
|
* to retain those nodes under `skipGraphPhases`.
|
|
26
26
|
*/
|
|
27
27
|
skipGraphPhases?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Build the control-flow-graph / PDG substrate (#2081 M1, opt-in via `--pdg`).
|
|
30
|
+
* Off by default: workers skip all CFG work and emit no `cfgSideChannel`, and
|
|
31
|
+
* scope-resolution emits no BasicBlock nodes or CFG edges — so the default
|
|
32
|
+
* graph is byte-identical to a pre-#2081 run. Folded into the parse-cache key
|
|
33
|
+
* so a pdg-off warm cache is not reused on a `--pdg` run.
|
|
34
|
+
*/
|
|
35
|
+
pdg?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Per-function source-line cap for worker-side CFG construction.
|
|
38
|
+
* `undefined` ⇒ the worker applies `DEFAULT_PDG_MAX_FUNCTION_LINES`; `0` ⇒ no
|
|
39
|
+
* cap (unlimited). Bounds the cost of a pathological mega-function; over-cap
|
|
40
|
+
* functions are skipped (no CFG emitted for them). No CLI flag in M1 —
|
|
41
|
+
* programmatic / server analyze-worker path only.
|
|
42
|
+
*/
|
|
43
|
+
pdgMaxFunctionLines?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Per-function CFG edge cap for the scope-resolution emit step.
|
|
46
|
+
* `undefined` ⇒ `DEFAULT_MAX_CFG_EDGES_PER_FUNCTION`; `0` ⇒ no cap (unlimited).
|
|
47
|
+
* Over-cap functions stop at the cap and log a structured drop warning (no
|
|
48
|
+
* silent truncation). No CLI flag in M1 — programmatic / server path only.
|
|
49
|
+
*/
|
|
50
|
+
pdgMaxEdgesPerFunction?: number;
|
|
51
|
+
/**
|
|
52
|
+
* Per-function REACHING_DEF edge cap for the scope-resolution emit step
|
|
53
|
+
* (#2082 M2). `undefined` ⇒ `DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION`
|
|
54
|
+
* (4000); `0` ⇒ no cap (unlimited). Emit-time-only — NOT folded into the
|
|
55
|
+
* parse-cache chunk key (the worker never sees it); recorded in
|
|
56
|
+
* `RepoMeta.pdg` so a cap change forces a full writeback. No CLI flag —
|
|
57
|
+
* programmatic / server path only, like the M1 caps.
|
|
58
|
+
*/
|
|
59
|
+
pdgMaxReachingDefEdgesPerFunction?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Per-function CDG (control-dependence) edge cap for the scope-resolution
|
|
62
|
+
* emit step (#2085 M5). `undefined` ⇒ `DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION`
|
|
63
|
+
* (5000); `0` ⇒ no cap (unlimited). Emit-time-only — NOT folded into the
|
|
64
|
+
* parse-cache chunk key; recorded resolved in `RepoMeta.pdg` so introducing
|
|
65
|
+
* CDG (an absent stamp key) forces a full writeback for pre-CDG `--pdg`
|
|
66
|
+
* indexes. No CLI flag — programmatic / server path only.
|
|
67
|
+
*/
|
|
68
|
+
pdgMaxCdgEdgesPerFunction?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Per-function taint findings cap for the scope-resolution taint pass
|
|
71
|
+
* (#2083 M3). `undefined` ⇒ `DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION`
|
|
72
|
+
* (200); `0` ⇒ no cap (unlimited). Emit-time-only — NOT folded into the
|
|
73
|
+
* parse-cache chunk key; recorded resolved in `RepoMeta.pdg` so a cap
|
|
74
|
+
* change forces a full writeback. No CLI flag or rc key (KTD8) —
|
|
75
|
+
* programmatic / server path only, like the other pdg caps.
|
|
76
|
+
*/
|
|
77
|
+
pdgMaxTaintFindingsPerFunction?: number;
|
|
78
|
+
/**
|
|
79
|
+
* Per-finding taint hop cap (#2083 M3, KTD6 — bounds the persisted
|
|
80
|
+
* hop-encoded `reason`). `undefined` ⇒ `DEFAULT_PDG_MAX_TAINT_HOPS` (32);
|
|
81
|
+
* `0` ⇒ no cap (unlimited). Same emit-time-only / RepoMeta-stamped /
|
|
82
|
+
* no-CLI-flag discipline as `pdgMaxTaintFindingsPerFunction`.
|
|
83
|
+
*/
|
|
84
|
+
pdgMaxTaintHops?: number;
|
|
85
|
+
/**
|
|
86
|
+
* Per-run cross-function findings cap (#2084 M4 review P1-3). `undefined` ⇒
|
|
87
|
+
* `DEFAULT_PDG_MAX_INTERPROC_FINDINGS` (2000); `0` ⇒ no cap. Consumed by the
|
|
88
|
+
* `taintSummaries` phase; RepoMeta-stamped, no CLI flag (KTD8) — same
|
|
89
|
+
* discipline as the per-function taint caps.
|
|
90
|
+
*/
|
|
91
|
+
pdgMaxInterprocFindings?: number;
|
|
92
|
+
/** Per-finding cross-function hop cap (#2084 review P1-3). `undefined` ⇒
|
|
93
|
+
* `DEFAULT_MAX_INTERPROC_HOPS` (32); `0` ⇒ no cap. */
|
|
94
|
+
pdgMaxInterprocHops?: number;
|
|
95
|
+
/** Per-run `TAINT_PATH` edge cap (#2084 review P1-3). `undefined` ⇒
|
|
96
|
+
* `DEFAULT_PDG_MAX_INTERPROC_EDGES` (1000); `0` ⇒ no cap. */
|
|
97
|
+
pdgMaxInterprocEdges?: number;
|
|
98
|
+
/** Per-run `CALL_SUMMARY` edge cap (PDG FU-C, U-C3). `undefined` ⇒
|
|
99
|
+
* `DEFAULT_PDG_MAX_CALL_SUMMARY_EDGES` (0 = unlimited); `0` ⇒ no cap.
|
|
100
|
+
* Programmatic only, no CLI flag (KTD8) — same discipline as the other
|
|
101
|
+
* pdg caps. */
|
|
102
|
+
pdgMaxCallSummaryEdges?: number;
|
|
103
|
+
/**
|
|
104
|
+
* Streaming/chunked PDG graph emit (#2202). When true, the BasicBlock +
|
|
105
|
+
* intra-file PDG-edge layer (CFG / REACHING_DEF / CDG / POST_DOMINATE /
|
|
106
|
+
* TAINTED / SANITIZES) is streamed to CSV-on-disk during the scope-resolution
|
|
107
|
+
* emit loop instead of being materialized in the in-memory graph, bounding
|
|
108
|
+
* peak RSS to O(chunk) rather than O(graph) at full-kernel scale. Already
|
|
109
|
+
* gated by the caller to full-rebuild runs only (the incremental writeback
|
|
110
|
+
* reads BasicBlocks back from the in-memory graph). Memory-only — produces a
|
|
111
|
+
* byte-identical persisted graph and is NOT part of `RepoMeta.pdg`, so
|
|
112
|
+
* toggling it never trips `pdgModeMismatch`. Default/false ⇒ today's
|
|
113
|
+
* whole-graph emit.
|
|
114
|
+
*/
|
|
115
|
+
streamPdgEmit?: boolean;
|
|
116
|
+
/** Streamed PDG-emit write buffer (rows) when `streamPdgEmit` is on (#2202).
|
|
117
|
+
* `undefined` ⇒ `DEFAULT_PDG_EMIT_CHUNK_ROWS`. Memory-only; does not affect
|
|
118
|
+
* emitted bytes. */
|
|
119
|
+
pdgEmitChunkSize?: number;
|
|
28
120
|
/**
|
|
29
121
|
* Request parsing with the worker pool disabled. The sequential parser was
|
|
30
122
|
* removed — the worker pool is the sole parse path — so setting this now
|
|
@@ -33,16 +125,6 @@ export interface PipelineOptions {
|
|
|
33
125
|
* silently-different result.
|
|
34
126
|
*/
|
|
35
127
|
skipWorkers?: boolean;
|
|
36
|
-
/**
|
|
37
|
-
* @internal Test-only override for the worker script URL the pool
|
|
38
|
-
* spawns. When unset, parse-impl resolves `parse-worker.js` from the
|
|
39
|
-
* adjacent `workers/` directory (or the compiled `dist/` fallback
|
|
40
|
-
* under vitest). Integration tests use this to inject a custom
|
|
41
|
-
* worker script that deterministically triggers worker-pool
|
|
42
|
-
* resilience paths (e.g., crash-on-poison-file). Do not use from production
|
|
43
|
-
* call sites.
|
|
44
|
-
*/
|
|
45
|
-
workerUrlForTest?: URL;
|
|
46
128
|
/**
|
|
47
129
|
* Incremental-indexing parse cache. When provided:
|
|
48
130
|
* - The parse phase looks up each chunk's content hash in
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* See ARCHITECTURE.md for the full phase dependency diagram.
|
|
16
16
|
*/
|
|
17
17
|
import { createKnowledgeGraph } from '../graph/graph.js';
|
|
18
|
-
import { runPipeline, getPhaseOutput, scanPhase, structurePhase, markdownPhase, cobolPhase, parsePhase, routesPhase, toolsPhase, ormPhase, crossFilePhase, scopeResolutionPhase, pruneLocalSymbolsPhase, mroPhase, communitiesPhase, processesPhase, PhaseRegistry, } from './pipeline-phases/index.js';
|
|
18
|
+
import { runPipeline, getPhaseOutput, scanPhase, structurePhase, markdownPhase, cobolPhase, parsePhase, routesPhase, toolsPhase, ormPhase, crossFilePhase, scopeResolutionPhase, pruneLocalSymbolsPhase, taintSummariesPhase, callSummariesPhase, mroPhase, communitiesPhase, processesPhase, PhaseRegistry, } from './pipeline-phases/index.js';
|
|
19
19
|
// ── Phase registry ─────────────────────────────────────────────────────────
|
|
20
20
|
/**
|
|
21
21
|
* All pipeline phases with their dependency relationships.
|
|
@@ -49,6 +49,11 @@ export function buildPhaseList(options) {
|
|
|
49
49
|
.register(crossFilePhase)
|
|
50
50
|
.register(scopeResolutionPhase)
|
|
51
51
|
.register(pruneLocalSymbolsPhase)
|
|
52
|
+
// M4 (#2084): interprocedural taint fixpoint — the first real opt-in
|
|
53
|
+
// pdg-gated phase. Off ⇒ absent ⇒ byte-identical graph. No always-on
|
|
54
|
+
// phase depends on it (a filtered-out dep would throw in getPhaseOutput).
|
|
55
|
+
.register(taintSummariesPhase, { enabledWhen: (o) => o.pdg === true })
|
|
56
|
+
.register(callSummariesPhase, { enabledWhen: (o) => o.pdg === true })
|
|
52
57
|
.register(mroPhase, { enabledWhen: (o) => !o.skipGraphPhases })
|
|
53
58
|
.register(communitiesPhase, { enabledWhen: (o) => !o.skipGraphPhases })
|
|
54
59
|
.register(processesPhase, { enabledWhen: (o) => !o.skipGraphPhases })
|
|
@@ -72,7 +77,10 @@ export const runPipelineFromRepo = async (repoPath, onProgress, options) => {
|
|
|
72
77
|
const { totalFiles, usedWorkerPool } = getPhaseOutput(results, 'parse');
|
|
73
78
|
let communityResult;
|
|
74
79
|
let processResult;
|
|
75
|
-
const
|
|
80
|
+
const scopeResolutionOutput = getPhaseOutput(results, 'scopeResolution');
|
|
81
|
+
const resolutionOutcomes = scopeResolutionOutput.resolutionOutcomes;
|
|
82
|
+
// Streamed PDG-emit manifest (#2202): present only when streaming was on.
|
|
83
|
+
const pdgEmitManifest = scopeResolutionOutput.pdgEmitManifest;
|
|
76
84
|
if (!options?.skipGraphPhases) {
|
|
77
85
|
communityResult = getPhaseOutput(results, 'communities').communityResult;
|
|
78
86
|
processResult = getPhaseOutput(results, 'processes').processResult;
|
|
@@ -97,5 +105,6 @@ export const runPipelineFromRepo = async (repoPath, onProgress, options) => {
|
|
|
97
105
|
processResult,
|
|
98
106
|
resolutionOutcomes,
|
|
99
107
|
usedWorkerPool,
|
|
108
|
+
pdgEmitManifest,
|
|
100
109
|
};
|
|
101
110
|
};
|
|
@@ -399,6 +399,7 @@ function buildDefFromDeclarationMatch(match, anchor, filePath) {
|
|
|
399
399
|
const returnType = match['@declaration.return-type']?.text;
|
|
400
400
|
const templateConstraints = parseJsonCapture(match['@declaration.template-constraints']);
|
|
401
401
|
const isExplicit = parseBooleanCapture(match['@declaration.is-explicit']);
|
|
402
|
+
const isDeleted = parseBooleanCapture(match['@declaration.is-deleted']);
|
|
402
403
|
return {
|
|
403
404
|
nodeId: makeDefId(filePath, anchor.range, type, nameCap.text),
|
|
404
405
|
filePath,
|
|
@@ -413,6 +414,7 @@ function buildDefFromDeclarationMatch(match, anchor, filePath) {
|
|
|
413
414
|
...(templateArguments !== undefined ? { templateArguments } : {}),
|
|
414
415
|
...(templateConstraints !== undefined ? { templateConstraints } : {}),
|
|
415
416
|
...(isExplicit === true ? { isExplicit: true } : {}),
|
|
417
|
+
...(isDeleted === true ? { isDeleted: true } : {}),
|
|
416
418
|
};
|
|
417
419
|
}
|
|
418
420
|
/** Parse an opaque JSON payload synthesized by per-language captures
|
|
@@ -475,12 +477,19 @@ function parseJsonParameterTypeClassesCapture(cap) {
|
|
|
475
477
|
if (typeof o.pointerDepth !== 'number' || !Number.isFinite(o.pointerDepth)) {
|
|
476
478
|
return undefined;
|
|
477
479
|
}
|
|
478
|
-
|
|
480
|
+
const shape = {
|
|
479
481
|
base: o.base,
|
|
480
482
|
cv: o.cv,
|
|
481
483
|
indirection: o.indirection,
|
|
482
484
|
pointerDepth: o.pointerDepth,
|
|
483
|
-
}
|
|
485
|
+
};
|
|
486
|
+
if (Array.isArray(o.templateArguments)) {
|
|
487
|
+
if (!o.templateArguments.every((x) => typeof x === 'string')) {
|
|
488
|
+
return undefined;
|
|
489
|
+
}
|
|
490
|
+
shape.templateArguments = [...o.templateArguments];
|
|
491
|
+
}
|
|
492
|
+
out.push(shape);
|
|
484
493
|
}
|
|
485
494
|
return out;
|
|
486
495
|
}
|
|
@@ -922,6 +931,7 @@ const KNOWN_SUB_TAGS = new Set([
|
|
|
922
931
|
'@declaration.return-type',
|
|
923
932
|
'@declaration.template-constraints',
|
|
924
933
|
'@declaration.is-explicit',
|
|
934
|
+
'@declaration.is-deleted',
|
|
925
935
|
]);
|
|
926
936
|
/**
|
|
927
937
|
* Return the anchor capture for a match — the one whose name begins with
|
|
@@ -618,6 +618,15 @@ export interface ScopeResolver {
|
|
|
618
618
|
* `cppConversionRank`; other languages define their own if needed.
|
|
619
619
|
*/
|
|
620
620
|
readonly conversionRankFn?: ConversionRankFn;
|
|
621
|
+
/**
|
|
622
|
+
* Optional per-language argument-type prefixes for conversion-only
|
|
623
|
+
* argument sentinels. When ranking cannot find any viable candidate
|
|
624
|
+
* for a multi-overload set containing one of these sentinels, shared
|
|
625
|
+
* narrowing suppresses the ambiguous set instead of falling back to
|
|
626
|
+
* arity-only candidates. Languages without such sentinels leave this
|
|
627
|
+
* undefined.
|
|
628
|
+
*/
|
|
629
|
+
readonly conversionOnlyArgTypePrefixes?: readonly string[];
|
|
621
630
|
/**
|
|
622
631
|
* Optional predicate to identify definitions with file-local linkage
|
|
623
632
|
* (e.g. C `static` functions). When provided, `pickUniqueGlobalCallable`
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolved-callee-id capture sink (#2227 follow-up plan U2).
|
|
3
|
+
*
|
|
4
|
+
* During Phase-4 scope-resolution CALLS-edge emission, each resolved call
|
|
5
|
+
* site's `(callSiteLine, callSiteCol) → resolvedCalleeId` mapping is
|
|
6
|
+
* accumulated here — across ALL THREE CALLS emit paths
|
|
7
|
+
* (`emitReceiverBoundCalls` via `tryEmitEdge`/`tryEmitEdgeWithExplicitTargetId`,
|
|
8
|
+
* and the inline `graph.addRelationship` in `emitFreeCallFallback` and
|
|
9
|
+
* `emitReferencesViaLookup`), each BEFORE its dedup (KTD6/R8). A later unit
|
|
10
|
+
* (U3) joins this map to CFG `BasicBlock`s by exact call-site position and
|
|
11
|
+
* emits a `BasicBlock.calleeIds` set.
|
|
12
|
+
*
|
|
13
|
+
* KEY ALIGNMENT (plan KTD7 — load-bearing): the key is the call/new
|
|
14
|
+
* expression node's start position — `line` 1-based (`startPosition.row + 1`),
|
|
15
|
+
* `col` 0-based (`startPosition.column`). This MUST equal the U1
|
|
16
|
+
* `SiteRecord.at` so the U3 position join lands. The CALLS resolution exposes
|
|
17
|
+
* the same node's range via `site.atRange` (`atRange: anchor.range`,
|
|
18
|
+
* scope-extractor.ts:1030), whose `startLine`/`startCol` are built by
|
|
19
|
+
* `nodeToCapture` as `row + 1` / `column` (1-based line, 0-based col — see the
|
|
20
|
+
* `Range` doc in gitnexus-shared). So a capture keyed on
|
|
21
|
+
* `(atRange.startLine, atRange.startCol)` is byte-equal to U1's `at` — no
|
|
22
|
+
* normalization needed.
|
|
23
|
+
*
|
|
24
|
+
* Gating (R4): the concrete sink is created in `run.ts` only when
|
|
25
|
+
* `input.pdg === true`; otherwise `undefined` is threaded through, so off-mode
|
|
26
|
+
* does zero work and emits byte-identical output.
|
|
27
|
+
*
|
|
28
|
+
* Multi-target dispatch (R2/KTD8): one site → multiple emit calls → the `Set`
|
|
29
|
+
* accumulates every resolved target. Capture is per-emit-call, so the
|
|
30
|
+
* candidate set is complete and a real target is never dropped.
|
|
31
|
+
*/
|
|
32
|
+
/** Encoded position key: `${line}:${col}` (1-based line, 0-based col). */
|
|
33
|
+
export type CalleeIdPosKey = string;
|
|
34
|
+
/** Build the position key from a call-site anchor. Single source of truth so
|
|
35
|
+
* producer (this sink) and consumer (U3's CFG join) encode positions
|
|
36
|
+
* identically. */
|
|
37
|
+
export declare function calleeIdPosKey(line: number, col: number): CalleeIdPosKey;
|
|
38
|
+
/**
|
|
39
|
+
* Write-side contract handed to the three CALLS emitters. Each resolved CALLS
|
|
40
|
+
* edge feeds one `add` BEFORE its dedup, keyed on the call-site anchor.
|
|
41
|
+
*/
|
|
42
|
+
export interface CalleeIdSink {
|
|
43
|
+
/**
|
|
44
|
+
* Record that the call site at `(line, col)` in `filePath` resolved to
|
|
45
|
+
* `calleeId`. Idempotent per `(filePath, line, col, calleeId)` — the
|
|
46
|
+
* underlying value is a `Set`, so repeat targets collapse.
|
|
47
|
+
*/
|
|
48
|
+
add(filePath: string, line: number, col: number, calleeId: string): void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Read-side accessor consumed by U3's CFG-emit join. Returns the per-file
|
|
52
|
+
* `posKey → Set<calleeId>` map (or `undefined` when the file produced no
|
|
53
|
+
* captures). Kept separate from the write interface so the emitters only see
|
|
54
|
+
* the narrow `add` surface.
|
|
55
|
+
*/
|
|
56
|
+
export interface CalleeIdMapView {
|
|
57
|
+
/** Per-file position→ids map, or `undefined` if nothing was captured for it. */
|
|
58
|
+
get(filePath: string): ReadonlyMap<CalleeIdPosKey, ReadonlySet<string>> | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Release a file's captured map once its CFG emit has consumed it (R6). The
|
|
61
|
+
* three CALLS passes fully precede the CFG-emit loop and each file is read
|
|
62
|
+
* exactly once, so releasing after consumption bounds the accumulator to one
|
|
63
|
+
* file's call sites instead of holding the whole repo's for the full phase.
|
|
64
|
+
*/
|
|
65
|
+
delete(filePath: string): void;
|
|
66
|
+
}
|
|
67
|
+
/** The concrete accumulator: a write sink that also exposes the read view. */
|
|
68
|
+
export interface CalleeIdAccumulator extends CalleeIdSink, CalleeIdMapView {
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create the concrete nested-`Map` accumulator. Call ONLY when
|
|
72
|
+
* `input.pdg === true` (else thread `undefined` for byte-identity / zero
|
|
73
|
+
* overhead — R4).
|
|
74
|
+
*/
|
|
75
|
+
export declare function createCalleeIdAccumulator(): CalleeIdAccumulator;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolved-callee-id capture sink (#2227 follow-up plan U2).
|
|
3
|
+
*
|
|
4
|
+
* During Phase-4 scope-resolution CALLS-edge emission, each resolved call
|
|
5
|
+
* site's `(callSiteLine, callSiteCol) → resolvedCalleeId` mapping is
|
|
6
|
+
* accumulated here — across ALL THREE CALLS emit paths
|
|
7
|
+
* (`emitReceiverBoundCalls` via `tryEmitEdge`/`tryEmitEdgeWithExplicitTargetId`,
|
|
8
|
+
* and the inline `graph.addRelationship` in `emitFreeCallFallback` and
|
|
9
|
+
* `emitReferencesViaLookup`), each BEFORE its dedup (KTD6/R8). A later unit
|
|
10
|
+
* (U3) joins this map to CFG `BasicBlock`s by exact call-site position and
|
|
11
|
+
* emits a `BasicBlock.calleeIds` set.
|
|
12
|
+
*
|
|
13
|
+
* KEY ALIGNMENT (plan KTD7 — load-bearing): the key is the call/new
|
|
14
|
+
* expression node's start position — `line` 1-based (`startPosition.row + 1`),
|
|
15
|
+
* `col` 0-based (`startPosition.column`). This MUST equal the U1
|
|
16
|
+
* `SiteRecord.at` so the U3 position join lands. The CALLS resolution exposes
|
|
17
|
+
* the same node's range via `site.atRange` (`atRange: anchor.range`,
|
|
18
|
+
* scope-extractor.ts:1030), whose `startLine`/`startCol` are built by
|
|
19
|
+
* `nodeToCapture` as `row + 1` / `column` (1-based line, 0-based col — see the
|
|
20
|
+
* `Range` doc in gitnexus-shared). So a capture keyed on
|
|
21
|
+
* `(atRange.startLine, atRange.startCol)` is byte-equal to U1's `at` — no
|
|
22
|
+
* normalization needed.
|
|
23
|
+
*
|
|
24
|
+
* Gating (R4): the concrete sink is created in `run.ts` only when
|
|
25
|
+
* `input.pdg === true`; otherwise `undefined` is threaded through, so off-mode
|
|
26
|
+
* does zero work and emits byte-identical output.
|
|
27
|
+
*
|
|
28
|
+
* Multi-target dispatch (R2/KTD8): one site → multiple emit calls → the `Set`
|
|
29
|
+
* accumulates every resolved target. Capture is per-emit-call, so the
|
|
30
|
+
* candidate set is complete and a real target is never dropped.
|
|
31
|
+
*/
|
|
32
|
+
/** Build the position key from a call-site anchor. Single source of truth so
|
|
33
|
+
* producer (this sink) and consumer (U3's CFG join) encode positions
|
|
34
|
+
* identically. */
|
|
35
|
+
export function calleeIdPosKey(line, col) {
|
|
36
|
+
return `${line}:${col}`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create the concrete nested-`Map` accumulator. Call ONLY when
|
|
40
|
+
* `input.pdg === true` (else thread `undefined` for byte-identity / zero
|
|
41
|
+
* overhead — R4).
|
|
42
|
+
*/
|
|
43
|
+
export function createCalleeIdAccumulator() {
|
|
44
|
+
const byFile = new Map();
|
|
45
|
+
return {
|
|
46
|
+
add(filePath, line, col, calleeId) {
|
|
47
|
+
let byPos = byFile.get(filePath);
|
|
48
|
+
if (byPos === undefined) {
|
|
49
|
+
byPos = new Map();
|
|
50
|
+
byFile.set(filePath, byPos);
|
|
51
|
+
}
|
|
52
|
+
const key = calleeIdPosKey(line, col);
|
|
53
|
+
let ids = byPos.get(key);
|
|
54
|
+
if (ids === undefined) {
|
|
55
|
+
ids = new Set();
|
|
56
|
+
byPos.set(key, ids);
|
|
57
|
+
}
|
|
58
|
+
ids.add(calleeId);
|
|
59
|
+
},
|
|
60
|
+
get(filePath) {
|
|
61
|
+
return byFile.get(filePath);
|
|
62
|
+
},
|
|
63
|
+
delete(filePath) {
|
|
64
|
+
byFile.delete(filePath);
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -18,6 +18,16 @@ import type { Reference, ScopeId, SymbolDefinition } from '../../../../_shared/i
|
|
|
18
18
|
import type { KnowledgeGraph } from '../../../graph/types.js';
|
|
19
19
|
import type { ScopeResolutionIndexes } from '../../model/scope-resolution-indexes.js';
|
|
20
20
|
import type { GraphNodeLookup } from '../graph-bridge/node-lookup.js';
|
|
21
|
+
import type { CalleeIdSink } from './callee-id-sink.js';
|
|
22
|
+
/**
|
|
23
|
+
* Optional resolved-callee-id capture context (#2227 follow-up U2). Threaded
|
|
24
|
+
* in only under `--pdg` (else `undefined` → zero overhead, byte-identity R4).
|
|
25
|
+
* `filePath` is NOT on the `site` param, so it rides here alongside the sink.
|
|
26
|
+
*/
|
|
27
|
+
export interface CalleeIdCaptureCtx {
|
|
28
|
+
readonly sink: CalleeIdSink;
|
|
29
|
+
readonly filePath: string;
|
|
30
|
+
}
|
|
21
31
|
/**
|
|
22
32
|
* Map a `Reference.kind` to a graph edge type. `import-use` is dropped
|
|
23
33
|
* (no edge type today — provenance lives on the IMPORTS edge emitted
|
|
@@ -40,7 +50,7 @@ export declare function tryEmitEdge(graph: KnowledgeGraph, scopes: ScopeResoluti
|
|
|
40
50
|
startCol: number;
|
|
41
51
|
};
|
|
42
52
|
readonly kind: string;
|
|
43
|
-
}, targetDef: SymbolDefinition, reason: string, seen: Set<string>, confidence?: number, collapseByCallerTarget?: boolean): boolean;
|
|
53
|
+
}, targetDef: SymbolDefinition, reason: string, seen: Set<string>, confidence?: number, collapseByCallerTarget?: boolean, calleeCapture?: CalleeIdCaptureCtx): boolean;
|
|
44
54
|
/**
|
|
45
55
|
* Variant of `tryEmitEdge` that takes a pre-resolved target graph id
|
|
46
56
|
* instead of resolving it from a `SymbolDefinition`. Used by the
|
|
@@ -61,4 +71,4 @@ export declare function tryEmitEdgeWithExplicitTargetId(graph: KnowledgeGraph, s
|
|
|
61
71
|
startCol: number;
|
|
62
72
|
};
|
|
63
73
|
readonly kind: string;
|
|
64
|
-
}, targetGraphId: string, reason: string, seen: Set<string>, confidence?: number, collapseByCallerTarget?: boolean): boolean;
|
|
74
|
+
}, targetGraphId: string, reason: string, seen: Set<string>, confidence?: number, collapseByCallerTarget?: boolean, calleeCapture?: CalleeIdCaptureCtx): boolean;
|
|
@@ -51,7 +51,7 @@ export function mapReferenceKindToEdgeType(kind) {
|
|
|
51
51
|
* multiple language-specific post-passes can share it and never
|
|
52
52
|
* double-emit a resolution one of them already produced.
|
|
53
53
|
*/
|
|
54
|
-
export function tryEmitEdge(graph, scopes, nodeLookup, site, targetDef, reason, seen, confidence = 0.85, collapseByCallerTarget = false) {
|
|
54
|
+
export function tryEmitEdge(graph, scopes, nodeLookup, site, targetDef, reason, seen, confidence = 0.85, collapseByCallerTarget = false, calleeCapture) {
|
|
55
55
|
// Inheritance edges are emitted directly by `preEmitInheritanceEdges` (which
|
|
56
56
|
// owns the enclosing-class caller and the EXTENDS-vs-IMPLEMENTS type), so this
|
|
57
57
|
// generic bridge derives caller + edge type purely from the site.
|
|
@@ -64,6 +64,13 @@ export function tryEmitEdge(graph, scopes, nodeLookup, site, targetDef, reason,
|
|
|
64
64
|
return false;
|
|
65
65
|
if (edgeType === undefined)
|
|
66
66
|
return false;
|
|
67
|
+
// Resolved-callee-id capture (#2227 U2/KTD6/R8): record this CALLS site's
|
|
68
|
+
// resolved target BEFORE the dedup `seen` check, so collapsed same-target
|
|
69
|
+
// multi-line calls are still captured per site. Keyed on `site.atRange`
|
|
70
|
+
// (1-based line / 0-based col — byte-equal to U1's SiteRecord.at).
|
|
71
|
+
if (calleeCapture !== undefined && edgeType === 'CALLS') {
|
|
72
|
+
calleeCapture.sink.add(calleeCapture.filePath, site.atRange.startLine, site.atRange.startCol, targetGraphId);
|
|
73
|
+
}
|
|
67
74
|
// CALLS edges may collapse to `(caller, target)` granularity when
|
|
68
75
|
// the provider opts in (C# matches legacy DAG behavior this way).
|
|
69
76
|
// Write/read ACCESSES keep per-site dedup so multiple writes to the
|
|
@@ -98,13 +105,18 @@ export function tryEmitEdge(graph, scopes, nodeLookup, site, targetDef, reason,
|
|
|
98
105
|
* All other invariants of `tryEmitEdge` apply: dedup key shape, collapse
|
|
99
106
|
* flag honoring, edge-type mapping, caller-id resolution.
|
|
100
107
|
*/
|
|
101
|
-
export function tryEmitEdgeWithExplicitTargetId(graph, scopes, nodeLookup, site, targetGraphId, reason, seen, confidence = 0.85, collapseByCallerTarget = false) {
|
|
108
|
+
export function tryEmitEdgeWithExplicitTargetId(graph, scopes, nodeLookup, site, targetGraphId, reason, seen, confidence = 0.85, collapseByCallerTarget = false, calleeCapture) {
|
|
102
109
|
const callerGraphId = resolveCallerGraphId(site.inScope, scopes, nodeLookup, site.atRange);
|
|
103
110
|
const edgeType = mapReferenceKindToEdgeType(site.kind);
|
|
104
111
|
if (callerGraphId === undefined)
|
|
105
112
|
return false;
|
|
106
113
|
if (edgeType === undefined)
|
|
107
114
|
return false;
|
|
115
|
+
// Resolved-callee-id capture (#2227 U2/KTD6/R8) — before dedup, see
|
|
116
|
+
// `tryEmitEdge`. The explicit target id IS the resolved callee id.
|
|
117
|
+
if (calleeCapture !== undefined && edgeType === 'CALLS') {
|
|
118
|
+
calleeCapture.sink.add(calleeCapture.filePath, site.atRange.startLine, site.atRange.startCol, targetGraphId);
|
|
119
|
+
}
|
|
108
120
|
const useCollapsed = collapseByCallerTarget && edgeType === 'CALLS';
|
|
109
121
|
const dedupKey = useCollapsed
|
|
110
122
|
? `${edgeType}:${callerGraphId}->${targetGraphId}`
|
|
@@ -21,6 +21,7 @@ import type { Reference, ScopeId } from '../../../../_shared/index.js';
|
|
|
21
21
|
import type { KnowledgeGraph } from '../../../graph/types.js';
|
|
22
22
|
import type { ScopeResolutionIndexes } from '../../model/scope-resolution-indexes.js';
|
|
23
23
|
import type { GraphNodeLookup } from '../graph-bridge/node-lookup.js';
|
|
24
|
+
import type { CalleeIdSink } from '../graph-bridge/callee-id-sink.js';
|
|
24
25
|
/**
|
|
25
26
|
* Optional opaque skip key — providers may pre-emit edges (e.g. via
|
|
26
27
|
* receiver-bound post-passes) and want this loop to skip references at
|
|
@@ -31,7 +32,11 @@ import type { GraphNodeLookup } from '../graph-bridge/node-lookup.js';
|
|
|
31
32
|
type ReferenceSiteSkipSet = ReadonlySet<string>;
|
|
32
33
|
export declare function emitReferencesViaLookup(graph: KnowledgeGraph, scopes: ScopeResolutionIndexes, referenceIndex: {
|
|
33
34
|
readonly bySourceScope: ReadonlyMap<ScopeId, readonly Reference[]>;
|
|
34
|
-
}, nodeLookup: GraphNodeLookup, skipSites?: ReferenceSiteSkipSet
|
|
35
|
+
}, nodeLookup: GraphNodeLookup, skipSites?: ReferenceSiteSkipSet,
|
|
36
|
+
/** Resolved-callee-id capture sink (#2227 U2). Threaded in only under
|
|
37
|
+
* `--pdg`; `undefined` ⇒ zero overhead, byte-identity (R4). Captured at the
|
|
38
|
+
* CALLS emit below BEFORE this loop's `seen` dedup (KTD6/R8). */
|
|
39
|
+
calleeIdSink?: CalleeIdSink): {
|
|
35
40
|
emitted: number;
|
|
36
41
|
skipped: number;
|
|
37
42
|
};
|