gitnexus 1.6.8-rc.9 → 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 +11 -0
- package/dist/core/ingestion/languages/c-cpp.js +6 -1
- 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 +3 -0
- 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 +23 -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/parse-worker.d.ts +13 -0
- package/dist/core/ingestion/workers/parse-worker.js +76 -17
- package/dist/core/ingestion/workers/worker-pool.d.ts +9 -40
- package/dist/core/ingestion/workers/worker-pool.js +15 -2
- 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.d.ts +17 -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 +41 -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
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
import { CallSiteFactAccumulator } from './call-site-harvest.js';
|
|
2
|
+
import { ScopeTreeHarvester } from './scope-tree-harvest.js';
|
|
3
|
+
/** Node types that own a nested CFG — their subtrees are opaque to harvesting. */
|
|
4
|
+
const NESTED_FUNCTION_TYPES = new Set(['lambda_expression', 'function_definition']);
|
|
5
|
+
/**
|
|
6
|
+
* Nodes that open a lexical scope for block-local declarations. A `compound_
|
|
7
|
+
* statement` is one scope; the for-loops open a scope for their loop variable.
|
|
8
|
+
*/
|
|
9
|
+
const SCOPE_TYPES = new Set([
|
|
10
|
+
'compound_statement',
|
|
11
|
+
'for_statement',
|
|
12
|
+
'for_range_loop',
|
|
13
|
+
'catch_clause',
|
|
14
|
+
]);
|
|
15
|
+
/** Type-position subtrees — identifiers inside them are not value uses. */
|
|
16
|
+
const TYPE_CONTEXT_TYPES = new Set([
|
|
17
|
+
'type_descriptor',
|
|
18
|
+
'template_argument_list',
|
|
19
|
+
'template_type',
|
|
20
|
+
'sized_type_specifier',
|
|
21
|
+
'primitive_type',
|
|
22
|
+
]);
|
|
23
|
+
export class CCppHarvester extends ScopeTreeHarvester {
|
|
24
|
+
constructor(fnNode) {
|
|
25
|
+
super(fnNode);
|
|
26
|
+
this.declareParams(fnNode);
|
|
27
|
+
const body = this.bodyOf(fnNode);
|
|
28
|
+
if (body)
|
|
29
|
+
this.prescan(body, this.openScope(body));
|
|
30
|
+
}
|
|
31
|
+
/** The function/lambda body block (`compound_statement`). */
|
|
32
|
+
bodyOf(fnNode) {
|
|
33
|
+
const body = fnNode.childForFieldName('body');
|
|
34
|
+
if (body)
|
|
35
|
+
return body;
|
|
36
|
+
return fnNode.namedChildren.find((c) => c.type === 'compound_statement');
|
|
37
|
+
}
|
|
38
|
+
// ── phase 1: declaration pre-scan ────────────────────────────────────────
|
|
39
|
+
/** The bare identifier a declarator chain ultimately names (or undefined). */
|
|
40
|
+
declaratorName(node) {
|
|
41
|
+
let cur = node;
|
|
42
|
+
let hops = 12;
|
|
43
|
+
while (cur && hops-- > 0) {
|
|
44
|
+
if (cur.type === 'identifier' || cur.type === 'field_identifier')
|
|
45
|
+
return cur;
|
|
46
|
+
// Unwrap pointer/reference/array/init/parenthesized declarator layers.
|
|
47
|
+
const next = cur.childForFieldName('declarator') ??
|
|
48
|
+
cur.namedChildren.find((c) => c.type === 'identifier' ||
|
|
49
|
+
c.type === 'field_identifier' ||
|
|
50
|
+
c.type === 'pointer_declarator' ||
|
|
51
|
+
c.type === 'reference_declarator' ||
|
|
52
|
+
c.type === 'array_declarator' ||
|
|
53
|
+
c.type === 'parenthesized_declarator' ||
|
|
54
|
+
c.type === 'init_declarator');
|
|
55
|
+
if (!next || next.id === cur.id)
|
|
56
|
+
break;
|
|
57
|
+
cur = next;
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
declareParams(fnNode) {
|
|
62
|
+
// function_definition: declarator → function_declarator → parameter_list.
|
|
63
|
+
// A C++ lambda routes through abstract_function_declarator.
|
|
64
|
+
const declarator = fnNode.childForFieldName('declarator');
|
|
65
|
+
const fnDeclarator = this.findFunctionDeclarator(declarator);
|
|
66
|
+
const params = fnDeclarator?.childForFieldName('parameters');
|
|
67
|
+
if (!params)
|
|
68
|
+
return;
|
|
69
|
+
for (let i = 0; i < params.namedChildCount; i++) {
|
|
70
|
+
const p = params.namedChild(i);
|
|
71
|
+
if (p?.type !== 'parameter_declaration')
|
|
72
|
+
continue;
|
|
73
|
+
const name = this.declaratorName(p.childForFieldName('declarator') ?? null);
|
|
74
|
+
if (name)
|
|
75
|
+
this.declare(name, 'param', this.root);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
findFunctionDeclarator(node) {
|
|
79
|
+
let cur = node;
|
|
80
|
+
let hops = 10;
|
|
81
|
+
while (cur && hops-- > 0) {
|
|
82
|
+
if (cur.type === 'function_declarator' || cur.type === 'abstract_function_declarator') {
|
|
83
|
+
return cur;
|
|
84
|
+
}
|
|
85
|
+
cur = cur.childForFieldName('declarator') ?? null;
|
|
86
|
+
}
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
prescan(node, scope) {
|
|
90
|
+
this.nearestScopeCache.set(node.id, scope);
|
|
91
|
+
const t = node.type;
|
|
92
|
+
if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId) {
|
|
93
|
+
// A nested function/lambda body is opaque — do not descend.
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
let childScope = scope;
|
|
97
|
+
if (SCOPE_TYPES.has(t))
|
|
98
|
+
childScope = this.openScope(node);
|
|
99
|
+
switch (t) {
|
|
100
|
+
case 'declaration':
|
|
101
|
+
this.declareDeclarators(node, childScope);
|
|
102
|
+
break;
|
|
103
|
+
case 'for_range_loop': {
|
|
104
|
+
// `for (int x : xs)` — the declarator binds in the loop scope.
|
|
105
|
+
const decl = node.childForFieldName('declarator');
|
|
106
|
+
const name = this.declaratorName(decl ?? null);
|
|
107
|
+
if (name)
|
|
108
|
+
this.declare(name, 'var', childScope);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
case 'catch_clause': {
|
|
112
|
+
const params = node.childForFieldName('parameters');
|
|
113
|
+
if (params) {
|
|
114
|
+
for (let i = 0; i < params.namedChildCount; i++) {
|
|
115
|
+
const p = params.namedChild(i);
|
|
116
|
+
if (p?.type !== 'parameter_declaration')
|
|
117
|
+
continue;
|
|
118
|
+
const name = this.declaratorName(p.childForFieldName('declarator') ?? null);
|
|
119
|
+
if (name)
|
|
120
|
+
this.declare(name, 'catch', childScope);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
default:
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
129
|
+
const c = node.namedChild(i);
|
|
130
|
+
if (c)
|
|
131
|
+
this.prescan(c, childScope);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The `structured_binding_declarator` a declarator binds (C++17 `auto [a,b]`,
|
|
136
|
+
* or `auto& [a,b]` whose binding sits under a `reference_declarator`), or
|
|
137
|
+
* undefined. C has no structured bindings, so this is inert for C.
|
|
138
|
+
*/
|
|
139
|
+
structuredBinding(declarator) {
|
|
140
|
+
let cur = declarator ?? undefined;
|
|
141
|
+
let hops = 4;
|
|
142
|
+
while (cur && hops-- > 0) {
|
|
143
|
+
if (cur.type === 'structured_binding_declarator')
|
|
144
|
+
return cur;
|
|
145
|
+
if (cur.type !== 'reference_declarator' && cur.type !== 'pointer_declarator')
|
|
146
|
+
break;
|
|
147
|
+
cur = cur.namedChildren.find((c) => c.type === 'structured_binding_declarator' ||
|
|
148
|
+
c.type === 'reference_declarator' ||
|
|
149
|
+
c.type === 'pointer_declarator');
|
|
150
|
+
}
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
/** The identifier leaves a `structured_binding_declarator` binds (`[a, b]`). */
|
|
154
|
+
structuredBindingNames(sbd) {
|
|
155
|
+
return sbd.namedChildren.filter((c) => c.type === 'identifier');
|
|
156
|
+
}
|
|
157
|
+
declareDeclarators(declNode, scope) {
|
|
158
|
+
for (let i = 0; i < declNode.namedChildCount; i++) {
|
|
159
|
+
const d = declNode.namedChild(i);
|
|
160
|
+
if (!d)
|
|
161
|
+
continue;
|
|
162
|
+
if (d.type === 'init_declarator') {
|
|
163
|
+
const declarator = d.childForFieldName('declarator');
|
|
164
|
+
const sbd = this.structuredBinding(declarator);
|
|
165
|
+
if (sbd) {
|
|
166
|
+
// `auto [a, b] = e;` — every identifier binds a scalar local.
|
|
167
|
+
for (const id of this.structuredBindingNames(sbd))
|
|
168
|
+
this.declare(id, 'var', scope);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const name = this.declaratorName(declarator ?? null);
|
|
172
|
+
if (name)
|
|
173
|
+
this.declare(name, 'var', scope);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else if (d.type === 'identifier' ||
|
|
177
|
+
d.type === 'pointer_declarator' ||
|
|
178
|
+
d.type === 'array_declarator' ||
|
|
179
|
+
d.type === 'reference_declarator') {
|
|
180
|
+
// Uninitialized local (`int x;`) — declare the BINDING (so a later
|
|
181
|
+
// assignment resolves to a real, non-synthetic binding) but the
|
|
182
|
+
// declaration itself produces no def (handled in phase 2).
|
|
183
|
+
const name = this.declaratorName(d);
|
|
184
|
+
if (name)
|
|
185
|
+
this.declare(name, 'var', scope);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// ── phase 2: per-statement fact extraction ───────────────────────────────
|
|
190
|
+
/** Def/use facts for one statement (or construct-header expression) node. */
|
|
191
|
+
facts(node) {
|
|
192
|
+
const acc = new FactAccumulator(node.startPosition.row + 1);
|
|
193
|
+
this.walkValue(node, acc);
|
|
194
|
+
return acc.finish();
|
|
195
|
+
}
|
|
196
|
+
/** Facts for an expression whose WHOLE evaluation is conditional (case tests). */
|
|
197
|
+
factsConditional(node) {
|
|
198
|
+
const acc = new FactAccumulator(node.startPosition.row + 1);
|
|
199
|
+
this.conditional(() => this.walkValue(node, acc));
|
|
200
|
+
return acc.finish();
|
|
201
|
+
}
|
|
202
|
+
/** Facts for a `for (decl : right)` range head: decl binds, right is used. */
|
|
203
|
+
forRangeHeadFacts(stmt) {
|
|
204
|
+
const acc = new FactAccumulator(stmt.startPosition.row + 1);
|
|
205
|
+
const decl = stmt.childForFieldName('declarator');
|
|
206
|
+
const right = stmt.childForFieldName('right');
|
|
207
|
+
const name = this.declaratorName(decl ?? null);
|
|
208
|
+
if (name)
|
|
209
|
+
this.def(name, acc);
|
|
210
|
+
if (right)
|
|
211
|
+
this.walkValue(right, acc);
|
|
212
|
+
return acc.finish();
|
|
213
|
+
}
|
|
214
|
+
/** ENTRY-block facts for the function's parameters (defs only). */
|
|
215
|
+
paramFacts() {
|
|
216
|
+
const declarator = this.fnNode.childForFieldName('declarator');
|
|
217
|
+
const fnDeclarator = this.findFunctionDeclarator(declarator);
|
|
218
|
+
const params = fnDeclarator?.childForFieldName('parameters');
|
|
219
|
+
if (!params)
|
|
220
|
+
return undefined;
|
|
221
|
+
const acc = new FactAccumulator(this.fnNode.startPosition.row + 1);
|
|
222
|
+
for (let i = 0; i < params.namedChildCount; i++) {
|
|
223
|
+
const p = params.namedChild(i);
|
|
224
|
+
if (p?.type !== 'parameter_declaration')
|
|
225
|
+
continue;
|
|
226
|
+
const name = this.declaratorName(p.childForFieldName('declarator') ?? null);
|
|
227
|
+
if (name)
|
|
228
|
+
this.def(name, acc);
|
|
229
|
+
}
|
|
230
|
+
return acc.defCount() ? acc.finish() : undefined;
|
|
231
|
+
}
|
|
232
|
+
/** Def fact for a `catch (T& e)` parameter — prepend to the handler entry block. */
|
|
233
|
+
catchParamFacts(catchClause) {
|
|
234
|
+
const params = catchClause.childForFieldName('parameters');
|
|
235
|
+
if (!params)
|
|
236
|
+
return undefined;
|
|
237
|
+
const acc = new FactAccumulator(catchClause.startPosition.row + 1);
|
|
238
|
+
for (let i = 0; i < params.namedChildCount; i++) {
|
|
239
|
+
const p = params.namedChild(i);
|
|
240
|
+
if (p?.type !== 'parameter_declaration')
|
|
241
|
+
continue;
|
|
242
|
+
const name = this.declaratorName(p.childForFieldName('declarator') ?? null);
|
|
243
|
+
if (name)
|
|
244
|
+
this.def(name, acc);
|
|
245
|
+
}
|
|
246
|
+
return acc.defCount() ? acc.finish() : undefined;
|
|
247
|
+
}
|
|
248
|
+
/** Strip parenthesized wrappers around an lvalue (`(x) = 1`). */
|
|
249
|
+
unwrapLvalue(node) {
|
|
250
|
+
let n = node;
|
|
251
|
+
let hops = 8;
|
|
252
|
+
while (n.type === 'parenthesized_expression' && hops-- > 0) {
|
|
253
|
+
const inner = n.namedChild(0);
|
|
254
|
+
if (!inner)
|
|
255
|
+
break;
|
|
256
|
+
n = inner;
|
|
257
|
+
}
|
|
258
|
+
return n;
|
|
259
|
+
}
|
|
260
|
+
/** Value-position walk: collect uses; route def positions to the lvalue handler. */
|
|
261
|
+
walkValue(node, acc) {
|
|
262
|
+
const t = node.type;
|
|
263
|
+
if (TYPE_CONTEXT_TYPES.has(t))
|
|
264
|
+
return;
|
|
265
|
+
if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId) {
|
|
266
|
+
// Opaque nested function / lambda — captured reads/writes are invisible.
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
switch (t) {
|
|
270
|
+
case 'identifier':
|
|
271
|
+
case 'field_identifier':
|
|
272
|
+
this.use(node, acc);
|
|
273
|
+
return;
|
|
274
|
+
case 'declaration':
|
|
275
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
276
|
+
const d = node.namedChild(i);
|
|
277
|
+
if (d?.type !== 'init_declarator')
|
|
278
|
+
continue;
|
|
279
|
+
const declarator = d.childForFieldName('declarator');
|
|
280
|
+
const value = d.childForFieldName('value');
|
|
281
|
+
const sbd = this.structuredBinding(declarator);
|
|
282
|
+
if (sbd && value) {
|
|
283
|
+
// `auto [a, b] = e;` — each identifier is a scalar def; the result
|
|
284
|
+
// of `e` flows into all of them (resultDefs covers the whole list).
|
|
285
|
+
const snap = acc.defSnapshot();
|
|
286
|
+
for (const id of this.structuredBindingNames(sbd))
|
|
287
|
+
this.def(id, acc);
|
|
288
|
+
this.registerResultDefs(value, acc.defsSince(snap));
|
|
289
|
+
this.walkValue(value, acc);
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
const name = declarator ? this.declaratorName(declarator) : undefined;
|
|
293
|
+
// Only an INITIALIZED declarator writes (`int x = e;`). A bare
|
|
294
|
+
// `int x;` is not a def (it writes nothing at runtime), matching the
|
|
295
|
+
// TS bare-`var` rule. Pointer/array/member declarators are not scalar
|
|
296
|
+
// defs either — their inner identifiers stay uses.
|
|
297
|
+
if (name && value && declarator?.type === 'identifier') {
|
|
298
|
+
const snap = acc.defSnapshot();
|
|
299
|
+
this.def(name, acc);
|
|
300
|
+
this.registerResultDefs(value, acc.defsSince(snap));
|
|
301
|
+
}
|
|
302
|
+
else if (declarator && declarator.type !== 'identifier') {
|
|
303
|
+
this.walkValue(declarator, acc);
|
|
304
|
+
}
|
|
305
|
+
if (value)
|
|
306
|
+
this.walkValue(value, acc);
|
|
307
|
+
}
|
|
308
|
+
return;
|
|
309
|
+
case 'assignment_expression': {
|
|
310
|
+
const left = node.childForFieldName('left');
|
|
311
|
+
const right = node.childForFieldName('right');
|
|
312
|
+
const op = node.childForFieldName('operator')?.text ?? '=';
|
|
313
|
+
if (left) {
|
|
314
|
+
const lv = this.unwrapLvalue(left);
|
|
315
|
+
if (lv.type === 'identifier') {
|
|
316
|
+
const snap = acc.defSnapshot();
|
|
317
|
+
this.def(lv, acc);
|
|
318
|
+
if (op !== '=')
|
|
319
|
+
this.use(lv, acc); // compound assign reads too
|
|
320
|
+
// A plain `x = f(a)` attaches `resultDefs: [x]` to f's site; a
|
|
321
|
+
// compound `x += f(a)` does not (the prior value flows in too).
|
|
322
|
+
if (op === '=' && right)
|
|
323
|
+
this.registerResultDefs(right, acc.defsSince(snap));
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
this.walkValue(lv, acc); // member/pointer/subscript target — uses only
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (right)
|
|
330
|
+
this.walkValue(right, acc);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
case 'update_expression': {
|
|
334
|
+
const rawArg = node.childForFieldName('argument');
|
|
335
|
+
const arg = rawArg ? this.unwrapLvalue(rawArg) : null;
|
|
336
|
+
if (arg?.type === 'identifier') {
|
|
337
|
+
this.def(arg, acc);
|
|
338
|
+
this.use(arg, acc);
|
|
339
|
+
}
|
|
340
|
+
else if (arg) {
|
|
341
|
+
this.walkValue(arg, acc);
|
|
342
|
+
}
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
case 'binary_expression': {
|
|
346
|
+
const left = node.childForFieldName('left');
|
|
347
|
+
const right = node.childForFieldName('right');
|
|
348
|
+
const op = node.childForFieldName('operator')?.text ?? '';
|
|
349
|
+
if (left)
|
|
350
|
+
this.walkValue(left, acc);
|
|
351
|
+
if (right) {
|
|
352
|
+
if (op === '&&' || op === '||')
|
|
353
|
+
this.conditional(() => this.walkValue(right, acc));
|
|
354
|
+
else
|
|
355
|
+
this.walkValue(right, acc);
|
|
356
|
+
}
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
case 'conditional_expression': {
|
|
360
|
+
const cond = node.childForFieldName('condition');
|
|
361
|
+
const cons = node.childForFieldName('consequence');
|
|
362
|
+
const alt = node.childForFieldName('alternative');
|
|
363
|
+
if (cond)
|
|
364
|
+
this.walkValue(cond, acc);
|
|
365
|
+
if (cons)
|
|
366
|
+
this.conditional(() => this.walkValue(cons, acc));
|
|
367
|
+
if (alt)
|
|
368
|
+
this.conditional(() => this.walkValue(alt, acc));
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
case 'call_expression':
|
|
372
|
+
// #2195 U6: explicit case (previously default-descended) — same uses,
|
|
373
|
+
// plus a taint-site record. Defs/uses stay byte-identical.
|
|
374
|
+
this.visitCall(node, acc, 'call');
|
|
375
|
+
return;
|
|
376
|
+
case 'new_expression':
|
|
377
|
+
// C++ `new Foo(x)` — constructor call site (`type` field is the callee).
|
|
378
|
+
this.visitCall(node, acc, 'new');
|
|
379
|
+
return;
|
|
380
|
+
case 'field_expression': {
|
|
381
|
+
// `a.b` / `a->b` — value read of the chain root only; the field name is
|
|
382
|
+
// not a scalar binding. Mirrors the TS member-read use semantics, plus a
|
|
383
|
+
// member-read site for the innermost identifier-rooted access.
|
|
384
|
+
this.walkChain(node, acc, false);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
default:
|
|
388
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
389
|
+
const c = node.namedChild(i);
|
|
390
|
+
if (c && !TYPE_CONTEXT_TYPES.has(c.type))
|
|
391
|
+
this.walkValue(c, acc);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// ── taint-site harvest (#2195 U6) ────────────────────────────────────────
|
|
396
|
+
/**
|
|
397
|
+
* When `value`'s root (after stripping parens) is a call/new node, remember
|
|
398
|
+
* that its site should carry `resultDefs: defs` — consumed by
|
|
399
|
+
* {@link visitCall} once the value walk reaches the node.
|
|
400
|
+
*/
|
|
401
|
+
registerResultDefs(value, defs) {
|
|
402
|
+
if (defs.length === 0)
|
|
403
|
+
return;
|
|
404
|
+
const root = this.unwrapLvalue(value);
|
|
405
|
+
if (root.type === 'call_expression' || root.type === 'new_expression') {
|
|
406
|
+
this.resultDefTargets.set(root.id, [...defs]);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Explicit call/new handler: records a call site (callee path, receiver,
|
|
411
|
+
* per-arg occurrence entries, result defs) while reproducing EXACTLY the uses
|
|
412
|
+
* the old default descent recorded — callee chain root + arguments. `new`
|
|
413
|
+
* sites read the `type` field as the callee; `call` sites the `function`
|
|
414
|
+
* field.
|
|
415
|
+
*/
|
|
416
|
+
visitCall(node, acc, kind) {
|
|
417
|
+
const calleeNode = node.childForFieldName(kind === 'new' ? 'type' : 'function');
|
|
418
|
+
const argsNode = node.childForFieldName('arguments');
|
|
419
|
+
// `node` IS the call/new expression — the SAME node the scope-extractor
|
|
420
|
+
// anchors `@reference.call.*` (its `atRange`) on (KTD7).
|
|
421
|
+
const siteIdx = acc.openCallSite(kind, [node.startPosition.row + 1, node.startPosition.column]);
|
|
422
|
+
acc.pushFrame(siteIdx);
|
|
423
|
+
let calleePath;
|
|
424
|
+
if (calleeNode) {
|
|
425
|
+
const callee = this.unwrapLvalue(calleeNode);
|
|
426
|
+
if (callee.type === 'identifier' || callee.type === 'type_identifier') {
|
|
427
|
+
// The callee NAME is a statement-level use but NOT a value occurrence in
|
|
428
|
+
// any enclosing argument (`exec(escape(x))` must not put `escape` into
|
|
429
|
+
// exec's arg 0). A `new Foo(...)` type identifier is a type, not a
|
|
430
|
+
// scalar binding — record neither a use nor an occurrence for it.
|
|
431
|
+
if (callee.type === 'identifier')
|
|
432
|
+
acc.addUseWithoutOccurrence(this.resolve(callee));
|
|
433
|
+
calleePath = callee.text;
|
|
434
|
+
}
|
|
435
|
+
else if (callee.type === 'field_expression') {
|
|
436
|
+
// skipFinalRead: the final access IS the callee, carried by the dotted
|
|
437
|
+
// path — recording it as a member read would double-count.
|
|
438
|
+
const chain = this.walkChain(callee, acc, true);
|
|
439
|
+
calleePath = chain.path;
|
|
440
|
+
if (chain.rootIdx !== undefined)
|
|
441
|
+
acc.setSiteReceiver(siteIdx, chain.rootIdx);
|
|
442
|
+
}
|
|
443
|
+
else if (callee.type === 'qualified_identifier') {
|
|
444
|
+
// `ns::g(...)` — a static dotted path, no scalar receiver binding.
|
|
445
|
+
calleePath = this.qualifiedPath(callee);
|
|
446
|
+
this.walkValue(callee, acc);
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
// Call-rooted chains, function-pointer expressions — the walk still
|
|
450
|
+
// records uses and nested sites.
|
|
451
|
+
this.walkValue(callee, acc);
|
|
452
|
+
}
|
|
453
|
+
if (calleePath !== undefined)
|
|
454
|
+
acc.setSiteCallee(siteIdx, calleePath);
|
|
455
|
+
}
|
|
456
|
+
const resultDefs = this.resultDefTargets.get(node.id);
|
|
457
|
+
if (resultDefs !== undefined)
|
|
458
|
+
acc.setSiteResultDefs(siteIdx, resultDefs);
|
|
459
|
+
if (argsNode) {
|
|
460
|
+
let pos = 0;
|
|
461
|
+
for (let i = 0; i < argsNode.namedChildCount; i++) {
|
|
462
|
+
const arg = argsNode.namedChild(i);
|
|
463
|
+
if (!arg || arg.type === 'comment')
|
|
464
|
+
continue;
|
|
465
|
+
acc.setFrameArg(pos);
|
|
466
|
+
this.walkValue(arg, acc);
|
|
467
|
+
pos++;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
acc.popFrame();
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Member chain walk shared by value position and callee position. Use-
|
|
474
|
+
* recording is identical to the old default descent (chain-root identifier
|
|
475
|
+
* once). Member-read sites: at most ONE per chain — the INNERMOST access —
|
|
476
|
+
* and only when the chain root is an identifier; `skipFinalRead` suppresses it
|
|
477
|
+
* when that access is the callee (carried by the dotted path instead).
|
|
478
|
+
*/
|
|
479
|
+
walkChain(node, acc, skipFinalRead) {
|
|
480
|
+
// Collect field accesses outer→inner (unshift), then resolve the root.
|
|
481
|
+
const accesses = [];
|
|
482
|
+
let cur = this.unwrapLvalue(node);
|
|
483
|
+
for (;;) {
|
|
484
|
+
if (cur.type === 'field_expression') {
|
|
485
|
+
const field = cur.childForFieldName('field');
|
|
486
|
+
accesses.unshift(field?.text ?? '');
|
|
487
|
+
const obj = cur.childForFieldName('argument');
|
|
488
|
+
if (!obj)
|
|
489
|
+
break;
|
|
490
|
+
cur = this.unwrapLvalue(obj);
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
let rootIdx;
|
|
497
|
+
let rootSegment;
|
|
498
|
+
if (cur.type === 'identifier' || cur.type === 'field_identifier') {
|
|
499
|
+
rootIdx = this.resolve(cur);
|
|
500
|
+
acc.addUse(rootIdx);
|
|
501
|
+
rootSegment = cur.text;
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
this.walkValue(cur, acc); // call-rooted etc. — uses + nested sites
|
|
505
|
+
}
|
|
506
|
+
const innermost = accesses[0];
|
|
507
|
+
if (rootIdx !== undefined && innermost && !(skipFinalRead && accesses.length === 1)) {
|
|
508
|
+
acc.addMemberRead(rootIdx, innermost);
|
|
509
|
+
}
|
|
510
|
+
const path = rootSegment !== undefined && accesses.every((a) => a !== '')
|
|
511
|
+
? [rootSegment, ...accesses].join('.')
|
|
512
|
+
: undefined;
|
|
513
|
+
return { path, rootIdx };
|
|
514
|
+
}
|
|
515
|
+
/** Dotted path of a `ns::a::b` qualified_identifier (`::` folded to `.`). */
|
|
516
|
+
qualifiedPath(node) {
|
|
517
|
+
const segs = [];
|
|
518
|
+
let cur = node;
|
|
519
|
+
let hops = 16;
|
|
520
|
+
while (cur && hops-- > 0) {
|
|
521
|
+
if (cur.type === 'qualified_identifier') {
|
|
522
|
+
const scope = cur.childForFieldName('scope');
|
|
523
|
+
const name = cur.childForFieldName('name');
|
|
524
|
+
if (scope)
|
|
525
|
+
segs.push(scope.text);
|
|
526
|
+
cur = name ?? null;
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
segs.push(cur.text);
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return segs.length ? segs.join('.') : undefined;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Ordered, deduplicating def/use + call-site collector for one statement record.
|
|
538
|
+
* The shared {@link CallSiteFactAccumulator} carries the def/use machinery the
|
|
539
|
+
* old local class had, plus the taint-site harvest (#2195 U6).
|
|
540
|
+
*/
|
|
541
|
+
const FactAccumulator = CallSiteFactAccumulator;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C / C++ CfgVisitor (#2195 U2, plan KTD1).
|
|
3
|
+
*
|
|
4
|
+
* Walks a C or C++ function's tree-sitter AST and drives the language-agnostic
|
|
5
|
+
* {@link CfgBuilder} to produce a serializable {@link FunctionCfg}, plus a
|
|
6
|
+
* def/use harvest ({@link CCppHarvester}) for the reaching-defs / CDG solvers.
|
|
7
|
+
*
|
|
8
|
+
* SHARED CORE, TWO FACTORIES. A grammar-introspection probe (mandatory pre-step,
|
|
9
|
+
* KTD1) confirmed every control-flow node type and field this visitor uses is
|
|
10
|
+
* IDENTICAL between tree-sitter-c and tree-sitter-cpp — `if_statement`,
|
|
11
|
+
* `for_statement`, `while_statement`, `do_statement`, `switch_statement` /
|
|
12
|
+
* `case_statement`, `return`/`break`/`continue`/`goto_statement` /
|
|
13
|
+
* `labeled_statement`, `compound_statement`, and the `condition`/`consequence`/
|
|
14
|
+
* `alternative`/`initializer`/`update`/`body`/`label`/`value` fields. So the C
|
|
15
|
+
* walk ({@link CCfgWalk}) is grammar-shared, and C++ EXTENDS it ({@link
|
|
16
|
+
* CppCfgWalk}) with exception flow (`try_statement` / `catch_clause` /
|
|
17
|
+
* `throw_statement`) and `for_range_loop` — node types that simply never occur
|
|
18
|
+
* in a C parse, so there is no `if (lang === …)` branching (AGENTS.md
|
|
19
|
+
* no-language-naming rule). The two factories differ only in which walk class
|
|
20
|
+
* and function-node set they install.
|
|
21
|
+
*
|
|
22
|
+
* Edge-kind contract (matches the TS visitor — RD/CDG consume these):
|
|
23
|
+
* - if/else → `cond-true` / `cond-false`
|
|
24
|
+
* - loops (for / while / do-while / for-range) → `cond-true` / `loop-back` /
|
|
25
|
+
* `cond-false`
|
|
26
|
+
* - switch → `switch-case` / `fallthrough` (C-style: a case body that does not
|
|
27
|
+
* `break` falls into the next case)
|
|
28
|
+
* - try/catch (C++) → `throw` (every protected-region block → the handler)
|
|
29
|
+
* - return / throw / break / continue → the matching terminator kind
|
|
30
|
+
* - straight-line → `seq`
|
|
31
|
+
*
|
|
32
|
+
* Classic hazards, handled explicitly:
|
|
33
|
+
* - loops allocate a dedicated loop-exit block so `break` has a target before
|
|
34
|
+
* the loop's successor is known; `continue` targets the header/increment.
|
|
35
|
+
* - `for (;;) {}` / `while (1) {}` still emit the structural `header → loopExit`
|
|
36
|
+
* `cond-false` escape edge so EXIT stays reverse-reachable from every block —
|
|
37
|
+
* the post-dominator / CDG pass is unsound otherwise (it silently emits zero
|
|
38
|
+
* CDG for the function).
|
|
39
|
+
* - C `goto`/`labeled_statement`: labels resolve within the function (forward
|
|
40
|
+
* AND backward); an unresolved `goto` (label not in this function) routes to
|
|
41
|
+
* EXIT and logs via the builder warn path, preserving single-exit.
|
|
42
|
+
* - C++ `try`/`catch`: conservative exceptional flow — EVERY block in the
|
|
43
|
+
* protected region edges to the handler (an exception may fire mid-block),
|
|
44
|
+
* matching the TS `visitTry` over-approximation. A `throw` with no enclosing
|
|
45
|
+
* try routes to EXIT.
|
|
46
|
+
*
|
|
47
|
+
* Known limitations:
|
|
48
|
+
* - C++ RAII: a destructor runs implicitly at scope exit, but tree-sitter does
|
|
49
|
+
* NOT represent that call in the AST. This visitor therefore does NOT model
|
|
50
|
+
* destructor-at-scope-exit control/data flow — it is a documented gap, not
|
|
51
|
+
* faked. (C++ has no `finally`; `try`/`catch` is the only modeled exception
|
|
52
|
+
* construct, so the TS finalizer-frame machinery is unused here.)
|
|
53
|
+
* - A `goto` whose label is undefined in the function keeps the conservative
|
|
54
|
+
* route-to-EXIT fallback (single-exit preserved; the continuation path is
|
|
55
|
+
* approximate). `setjmp`/`longjmp` non-local control is not modeled.
|
|
56
|
+
* - Computed `goto` (`goto *ptr;`, a GNU extension) has no static label target
|
|
57
|
+
* and routes to EXIT like an unresolved label.
|
|
58
|
+
* - Def/use harvest scope: see `c-cpp-harvest.ts` — member/pointer/array writes
|
|
59
|
+
* are not scalar defs; C++ lambda bodies are opaque in both directions.
|
|
60
|
+
*
|
|
61
|
+
* Returns `undefined` (never throws) for an AST shape it cannot model, so a
|
|
62
|
+
* malformed function never drops the whole file's CFG group (R4).
|
|
63
|
+
*/
|
|
64
|
+
import type { SyntaxNode } from '../../utils/ast-helpers.js';
|
|
65
|
+
import type { CfgVisitor } from '../types.js';
|
|
66
|
+
/** C function node — only `function_definition` owns a CFG-bearing body. */
|
|
67
|
+
declare const C_FUNCTION_TYPES: Set<string>;
|
|
68
|
+
/** C++ adds the lambda as a CFG-bearing function. */
|
|
69
|
+
declare const CPP_FUNCTION_TYPES: Set<string>;
|
|
70
|
+
/** The C CFG visitor. */
|
|
71
|
+
export declare function createCCfgVisitor(): CfgVisitor<SyntaxNode>;
|
|
72
|
+
/** The C++ CFG visitor (C core + exceptions + range-for + lambdas). */
|
|
73
|
+
export declare function createCppCfgVisitor(): CfgVisitor<SyntaxNode>;
|
|
74
|
+
export { C_FUNCTION_TYPES, CPP_FUNCTION_TYPES };
|