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
|
@@ -0,0 +1,589 @@
|
|
|
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([
|
|
5
|
+
'lambda_expression',
|
|
6
|
+
'anonymous_method_expression',
|
|
7
|
+
'local_function_statement',
|
|
8
|
+
'method_declaration',
|
|
9
|
+
'constructor_declaration',
|
|
10
|
+
]);
|
|
11
|
+
/**
|
|
12
|
+
* Nodes that open a lexical scope for block-local declarations. A `block` is one
|
|
13
|
+
* scope; the loop constructs open a scope for their loop variable; a
|
|
14
|
+
* `catch_clause` scopes its exception name; a `using_statement` scopes its
|
|
15
|
+
* resource declaration; a `switch_section` scopes its pattern bindings.
|
|
16
|
+
*/
|
|
17
|
+
const SCOPE_TYPES = new Set([
|
|
18
|
+
'block',
|
|
19
|
+
'for_statement',
|
|
20
|
+
'foreach_statement',
|
|
21
|
+
'while_statement',
|
|
22
|
+
'using_statement',
|
|
23
|
+
'catch_clause',
|
|
24
|
+
'switch_section',
|
|
25
|
+
'switch_expression_arm',
|
|
26
|
+
]);
|
|
27
|
+
export class CsharpHarvester extends ScopeTreeHarvester {
|
|
28
|
+
constructor(fnNode) {
|
|
29
|
+
super(fnNode);
|
|
30
|
+
this.declareParams(fnNode);
|
|
31
|
+
const body = this.bodyOf(fnNode);
|
|
32
|
+
if (body)
|
|
33
|
+
this.prescan(body, this.openScope(body));
|
|
34
|
+
}
|
|
35
|
+
/** The function/lambda body node (a `block` or an expression for `=> expr`). */
|
|
36
|
+
bodyOf(fnNode) {
|
|
37
|
+
const body = fnNode.childForFieldName('body');
|
|
38
|
+
if (body)
|
|
39
|
+
return body;
|
|
40
|
+
// Anonymous method / local function: the body is the first `block` child.
|
|
41
|
+
return fnNode.namedChildren.find((c) => c.type === 'block');
|
|
42
|
+
}
|
|
43
|
+
// ── phase 1: declaration pre-scan ────────────────────────────────────────
|
|
44
|
+
declareParams(fnNode) {
|
|
45
|
+
const params = fnNode.childForFieldName('parameters') ??
|
|
46
|
+
fnNode.namedChildren.find((c) => c.type === 'parameter_list' || c.type === 'implicit_parameter');
|
|
47
|
+
if (!params)
|
|
48
|
+
return;
|
|
49
|
+
if (params.type === 'implicit_parameter') {
|
|
50
|
+
// Single un-parenthesized lambda parameter: `x => …`.
|
|
51
|
+
this.declare(params, 'param', this.root);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
for (let i = 0; i < params.namedChildCount; i++) {
|
|
55
|
+
const p = params.namedChild(i);
|
|
56
|
+
if (p?.type !== 'parameter')
|
|
57
|
+
continue;
|
|
58
|
+
const name = p.childForFieldName('name');
|
|
59
|
+
if (name)
|
|
60
|
+
this.declare(name, 'param', this.root);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
prescan(node, scope) {
|
|
64
|
+
this.nearestScopeCache.set(node.id, scope);
|
|
65
|
+
const t = node.type;
|
|
66
|
+
if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId) {
|
|
67
|
+
// A nested function / lambda body is opaque — do not descend.
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
let childScope = scope;
|
|
71
|
+
if (SCOPE_TYPES.has(t))
|
|
72
|
+
childScope = this.openScope(node);
|
|
73
|
+
switch (t) {
|
|
74
|
+
case 'local_declaration_statement': {
|
|
75
|
+
const decl = node.namedChildren.find((c) => c.type === 'variable_declaration');
|
|
76
|
+
if (decl)
|
|
77
|
+
this.declareVariableDeclaration(decl, childScope);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
case 'foreach_statement': {
|
|
81
|
+
// `foreach (var x in xs)` — the `left` is the loop var (identifier or a
|
|
82
|
+
// `tuple_pattern` of identifiers); binds in the loop scope.
|
|
83
|
+
const left = node.childForFieldName('left');
|
|
84
|
+
if (left)
|
|
85
|
+
this.declareForeachTarget(left, childScope);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case 'using_statement': {
|
|
89
|
+
// `using (var f = Open())` — declaration form binds the resource.
|
|
90
|
+
const decl = node.namedChildren.find((c) => c.type === 'variable_declaration');
|
|
91
|
+
if (decl)
|
|
92
|
+
this.declareVariableDeclaration(decl, childScope);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case 'catch_clause': {
|
|
96
|
+
const declNode = node.namedChildren.find((c) => c.type === 'catch_declaration');
|
|
97
|
+
const name = declNode?.childForFieldName('name');
|
|
98
|
+
if (name)
|
|
99
|
+
this.declare(name, 'catch', childScope);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
case 'declaration_pattern': {
|
|
103
|
+
// `o is string s` / `case int n:` — `s`/`n` is a fresh binding.
|
|
104
|
+
const name = node.childForFieldName('name');
|
|
105
|
+
if (name)
|
|
106
|
+
this.declare(name, 'var', childScope);
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
case 'declaration_expression': {
|
|
110
|
+
// `f(out var n)` / `f(out int n)` — `n` is a fresh out-binding written
|
|
111
|
+
// by the callee; declare it so its def + later uses resolve to a real
|
|
112
|
+
// local rather than a synthetic module binding.
|
|
113
|
+
const name = node.childForFieldName('name');
|
|
114
|
+
if (name)
|
|
115
|
+
this.declare(name, 'var', childScope);
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
default:
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
122
|
+
const c = node.namedChild(i);
|
|
123
|
+
if (c)
|
|
124
|
+
this.prescan(c, childScope);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/** Declare every `variable_declarator` name in a `variable_declaration`. */
|
|
128
|
+
declareVariableDeclaration(declNode, scope) {
|
|
129
|
+
for (let i = 0; i < declNode.namedChildCount; i++) {
|
|
130
|
+
const d = declNode.namedChild(i);
|
|
131
|
+
if (d?.type !== 'variable_declarator')
|
|
132
|
+
continue;
|
|
133
|
+
const name = d.childForFieldName('name');
|
|
134
|
+
if (name) {
|
|
135
|
+
this.declare(name, 'var', scope);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
// Deconstruction declaration `var (a, b) = …;` — the declarator's name
|
|
139
|
+
// slot is a `tuple_pattern`; declare each identifier under it (reusing
|
|
140
|
+
// the foreach tuple-target logic).
|
|
141
|
+
const tuple = d.namedChildren.find((c) => c.type === 'tuple_pattern');
|
|
142
|
+
if (tuple)
|
|
143
|
+
this.declareForeachTarget(tuple, scope);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/** Declare a `foreach` target — an identifier or a `tuple_pattern`. */
|
|
148
|
+
declareForeachTarget(left, scope) {
|
|
149
|
+
if (left.type === 'identifier') {
|
|
150
|
+
this.declare(left, 'var', scope);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// `var (k, v)` deconstruction — declare each identifier under the pattern.
|
|
154
|
+
for (let i = 0; i < left.namedChildCount; i++) {
|
|
155
|
+
const c = left.namedChild(i);
|
|
156
|
+
if (c?.type === 'identifier')
|
|
157
|
+
this.declare(c, 'var', scope);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// ── phase 2: per-statement fact extraction ───────────────────────────────
|
|
161
|
+
/** Def/use facts for one statement (or construct-header expression) node. */
|
|
162
|
+
facts(node) {
|
|
163
|
+
const acc = new FactAccumulator(node.startPosition.row + 1);
|
|
164
|
+
this.walkValue(node, acc);
|
|
165
|
+
return acc.finish();
|
|
166
|
+
}
|
|
167
|
+
/** Facts for an expression whose WHOLE evaluation is conditional (case tests). */
|
|
168
|
+
factsConditional(node) {
|
|
169
|
+
const acc = new FactAccumulator(node.startPosition.row + 1);
|
|
170
|
+
this.conditional(() => this.walkValue(node, acc));
|
|
171
|
+
return acc.finish();
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Def-ONLY facts for a value-position binding carrier (`var x = k switch {…}`,
|
|
175
|
+
* #2207): just the declared name(s)' def, attached to the continuation block the
|
|
176
|
+
* switch arms rejoin. The discriminant + arm-value USES are already harvested
|
|
177
|
+
* onto the branch's own blocks ({@link facts} on each arm), so this must NOT
|
|
178
|
+
* re-walk the initializer — only each `variable_declarator`'s name is a def here.
|
|
179
|
+
*/
|
|
180
|
+
bindingDefFacts(stmt) {
|
|
181
|
+
const acc = new FactAccumulator(stmt.startPosition.row + 1);
|
|
182
|
+
const decl = stmt.namedChildren.find((c) => c.type === 'variable_declaration');
|
|
183
|
+
if (decl) {
|
|
184
|
+
for (let i = 0; i < decl.namedChildCount; i++) {
|
|
185
|
+
const d = decl.namedChild(i);
|
|
186
|
+
if (d?.type !== 'variable_declarator')
|
|
187
|
+
continue;
|
|
188
|
+
const name = d.childForFieldName('name');
|
|
189
|
+
if (name)
|
|
190
|
+
this.def(name, acc);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return acc.defCount() ? acc.finish() : undefined;
|
|
194
|
+
}
|
|
195
|
+
/** Facts for a `foreach (decl in right)` head: decl binds, right is used. */
|
|
196
|
+
forEachHeadFacts(stmt) {
|
|
197
|
+
const acc = new FactAccumulator(stmt.startPosition.row + 1);
|
|
198
|
+
const left = stmt.childForFieldName('left');
|
|
199
|
+
const right = stmt.childForFieldName('right');
|
|
200
|
+
if (left)
|
|
201
|
+
this.defForeachTarget(left, acc);
|
|
202
|
+
if (right)
|
|
203
|
+
this.walkValue(right, acc);
|
|
204
|
+
return acc.finish();
|
|
205
|
+
}
|
|
206
|
+
/** ENTRY-block facts for the function's parameters (defs only). */
|
|
207
|
+
paramFacts() {
|
|
208
|
+
const params = this.fnNode.childForFieldName('parameters') ??
|
|
209
|
+
this.fnNode.namedChildren.find((c) => c.type === 'parameter_list' || c.type === 'implicit_parameter');
|
|
210
|
+
if (!params)
|
|
211
|
+
return undefined;
|
|
212
|
+
const acc = new FactAccumulator(this.fnNode.startPosition.row + 1);
|
|
213
|
+
if (params.type === 'implicit_parameter') {
|
|
214
|
+
this.def(params, acc);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
for (let i = 0; i < params.namedChildCount; i++) {
|
|
218
|
+
const p = params.namedChild(i);
|
|
219
|
+
if (p?.type !== 'parameter')
|
|
220
|
+
continue;
|
|
221
|
+
const name = p.childForFieldName('name');
|
|
222
|
+
if (name)
|
|
223
|
+
this.def(name, acc);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return acc.defCount() ? acc.finish() : undefined;
|
|
227
|
+
}
|
|
228
|
+
/** Def fact for a `catch (T e)` declaration — prepend to the handler entry block. */
|
|
229
|
+
catchParamFacts(catchClause) {
|
|
230
|
+
const declNode = catchClause.namedChildren.find((c) => c.type === 'catch_declaration');
|
|
231
|
+
const name = declNode?.childForFieldName('name');
|
|
232
|
+
if (!name)
|
|
233
|
+
return undefined;
|
|
234
|
+
const acc = new FactAccumulator(catchClause.startPosition.row + 1);
|
|
235
|
+
this.def(name, acc);
|
|
236
|
+
return acc.defCount() ? acc.finish() : undefined;
|
|
237
|
+
}
|
|
238
|
+
/** Strip parenthesized wrappers around an lvalue (`(x) = 1`). */
|
|
239
|
+
unwrapLvalue(node) {
|
|
240
|
+
let n = node;
|
|
241
|
+
let hops = 8;
|
|
242
|
+
while (n.type === 'parenthesized_expression' && hops-- > 0) {
|
|
243
|
+
const inner = n.namedChild(0);
|
|
244
|
+
if (!inner)
|
|
245
|
+
break;
|
|
246
|
+
n = inner;
|
|
247
|
+
}
|
|
248
|
+
return n;
|
|
249
|
+
}
|
|
250
|
+
/** Def a `foreach` target (identifier or tuple) in a header fact accumulator. */
|
|
251
|
+
defForeachTarget(left, acc) {
|
|
252
|
+
if (left.type === 'identifier') {
|
|
253
|
+
this.def(left, acc);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
for (let i = 0; i < left.namedChildCount; i++) {
|
|
257
|
+
const c = left.namedChild(i);
|
|
258
|
+
if (c?.type === 'identifier')
|
|
259
|
+
this.def(c, acc);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/** Value-position walk: collect uses; route def positions to the lvalue handler. */
|
|
263
|
+
walkValue(node, acc) {
|
|
264
|
+
const t = node.type;
|
|
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
|
+
this.use(node, acc);
|
|
272
|
+
return;
|
|
273
|
+
case 'local_declaration_statement':
|
|
274
|
+
case 'variable_declaration': {
|
|
275
|
+
const decl = t === 'variable_declaration' ? node : node.namedChild(0);
|
|
276
|
+
if (decl && decl.type === 'variable_declaration') {
|
|
277
|
+
for (let i = 0; i < decl.namedChildCount; i++) {
|
|
278
|
+
const d = decl.namedChild(i);
|
|
279
|
+
if (d?.type !== 'variable_declarator')
|
|
280
|
+
continue;
|
|
281
|
+
const name = d.childForFieldName('name');
|
|
282
|
+
if (!name) {
|
|
283
|
+
// Deconstruction declaration `var (a, b) = e;` — def each
|
|
284
|
+
// identifier in the `tuple_pattern`; the initializer is the
|
|
285
|
+
// declarator's non-pattern child.
|
|
286
|
+
const tuple = d.namedChildren.find((c) => c.type === 'tuple_pattern');
|
|
287
|
+
const tupleInit = d.namedChildren.find((c) => c.type !== 'tuple_pattern');
|
|
288
|
+
if (tuple) {
|
|
289
|
+
const snap = acc.defSnapshot();
|
|
290
|
+
this.defTupleTargets(tuple, acc);
|
|
291
|
+
if (tupleInit)
|
|
292
|
+
this.registerResultDefs(tupleInit, acc.defsSince(snap));
|
|
293
|
+
}
|
|
294
|
+
if (tupleInit)
|
|
295
|
+
this.walkValue(tupleInit, acc);
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
// The initializer (if any) is the LAST named child after `name`.
|
|
299
|
+
const init = this.declaratorInit(d);
|
|
300
|
+
if (name && init) {
|
|
301
|
+
const snap = acc.defSnapshot();
|
|
302
|
+
this.def(name, acc);
|
|
303
|
+
this.registerResultDefs(init, acc.defsSince(snap));
|
|
304
|
+
}
|
|
305
|
+
if (init)
|
|
306
|
+
this.walkValue(init, acc);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
case 'declaration_expression': {
|
|
312
|
+
// `out var n` / `out int n` — the callee writes `n` (a must-def: C#
|
|
313
|
+
// requires an out parameter to be assigned before the method returns).
|
|
314
|
+
const name = node.childForFieldName('name');
|
|
315
|
+
if (name)
|
|
316
|
+
this.def(name, acc);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
case 'assignment_expression': {
|
|
320
|
+
const left = node.childForFieldName('left');
|
|
321
|
+
const right = node.childForFieldName('right');
|
|
322
|
+
const op = node.childForFieldName('operator')?.text ?? '=';
|
|
323
|
+
if (left) {
|
|
324
|
+
const lv = this.unwrapLvalue(left);
|
|
325
|
+
if (lv.type === 'identifier') {
|
|
326
|
+
const snap = acc.defSnapshot();
|
|
327
|
+
this.def(lv, acc);
|
|
328
|
+
if (op !== '=')
|
|
329
|
+
this.use(lv, acc); // compound assign reads too
|
|
330
|
+
if (op === '=' && right)
|
|
331
|
+
this.registerResultDefs(right, acc.defsSince(snap));
|
|
332
|
+
}
|
|
333
|
+
else if (lv.type === 'tuple_expression') {
|
|
334
|
+
this.defTupleTargets(lv, acc); // `(a, b) = …` deconstruction
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
this.walkValue(lv, acc); // member/element target — uses only
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (right)
|
|
341
|
+
this.walkValue(right, acc);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
case 'postfix_unary_expression':
|
|
345
|
+
case 'prefix_unary_expression': {
|
|
346
|
+
const arg = node.namedChild(0);
|
|
347
|
+
const lv = arg ? this.unwrapLvalue(arg) : null;
|
|
348
|
+
// Only `++`/`--` write; `!x`/`-x`/`~x` are pure reads. The operator is an
|
|
349
|
+
// anonymous child; treat as a def+use only when the operand is an
|
|
350
|
+
// identifier AND the op text is an increment/decrement.
|
|
351
|
+
if (lv?.type === 'identifier' && this.isIncDec(node)) {
|
|
352
|
+
this.def(lv, acc);
|
|
353
|
+
this.use(lv, acc);
|
|
354
|
+
}
|
|
355
|
+
else if (arg) {
|
|
356
|
+
this.walkValue(arg, acc);
|
|
357
|
+
}
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
case 'binary_expression': {
|
|
361
|
+
const left = node.childForFieldName('left');
|
|
362
|
+
const right = node.childForFieldName('right');
|
|
363
|
+
const op = node.childForFieldName('operator')?.text ?? '';
|
|
364
|
+
if (left)
|
|
365
|
+
this.walkValue(left, acc);
|
|
366
|
+
if (right) {
|
|
367
|
+
if (op === '&&' || op === '||' || op === '??') {
|
|
368
|
+
this.conditional(() => this.walkValue(right, acc));
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
this.walkValue(right, acc);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
case 'conditional_expression': {
|
|
377
|
+
const cond = node.childForFieldName('condition');
|
|
378
|
+
const cons = node.childForFieldName('consequence');
|
|
379
|
+
const alt = node.childForFieldName('alternative');
|
|
380
|
+
if (cond)
|
|
381
|
+
this.walkValue(cond, acc);
|
|
382
|
+
if (cons)
|
|
383
|
+
this.conditional(() => this.walkValue(cons, acc));
|
|
384
|
+
if (alt)
|
|
385
|
+
this.conditional(() => this.walkValue(alt, acc));
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
case 'invocation_expression':
|
|
389
|
+
// #2195 U6: explicit case (previously default-descended) — same uses,
|
|
390
|
+
// plus a taint-site record. Defs/uses stay byte-identical.
|
|
391
|
+
this.visitCall(node, acc, 'call');
|
|
392
|
+
return;
|
|
393
|
+
case 'object_creation_expression':
|
|
394
|
+
// `new Foo(x)` — constructor call site (`type` field is the callee).
|
|
395
|
+
this.visitCall(node, acc, 'new');
|
|
396
|
+
return;
|
|
397
|
+
case 'member_access_expression': {
|
|
398
|
+
// `a.B` — value read of the chain root only; the member name is not a
|
|
399
|
+
// scalar binding. Mirrors the TS member-read use semantics, plus a
|
|
400
|
+
// member-read site for the innermost identifier-rooted access.
|
|
401
|
+
this.walkChain(node, acc, false);
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
default:
|
|
405
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
406
|
+
const c = node.namedChild(i);
|
|
407
|
+
if (c)
|
|
408
|
+
this.walkValue(c, acc);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
// ── taint-site harvest (#2195 U6) ────────────────────────────────────────
|
|
413
|
+
/**
|
|
414
|
+
* When `value`'s root (after stripping parens) is an invocation/creation
|
|
415
|
+
* node, remember that its site should carry `resultDefs: defs` — consumed by
|
|
416
|
+
* {@link visitCall} once the value walk reaches the node.
|
|
417
|
+
*/
|
|
418
|
+
registerResultDefs(value, defs) {
|
|
419
|
+
if (defs.length === 0)
|
|
420
|
+
return;
|
|
421
|
+
const root = this.unwrapLvalue(value);
|
|
422
|
+
if (root.type === 'invocation_expression' || root.type === 'object_creation_expression') {
|
|
423
|
+
this.resultDefTargets.set(root.id, [...defs]);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Explicit invocation / object-creation handler: records a call site (callee
|
|
428
|
+
* path, receiver, per-arg occurrence entries, result defs) while reproducing
|
|
429
|
+
* EXACTLY the uses the old default descent recorded. C# wraps each argument in
|
|
430
|
+
* an `argument` node; `new Foo(...)` reads the `type` field as the callee.
|
|
431
|
+
*/
|
|
432
|
+
visitCall(node, acc, kind) {
|
|
433
|
+
const calleeNode = node.childForFieldName(kind === 'new' ? 'type' : 'function');
|
|
434
|
+
const argsNode = node.childForFieldName('arguments');
|
|
435
|
+
// `node` IS the call/object-creation expression — the SAME node the
|
|
436
|
+
// scope-extractor anchors `@reference.call.*` (its `atRange`) on (KTD7).
|
|
437
|
+
const siteIdx = acc.openCallSite(kind, [node.startPosition.row + 1, node.startPosition.column]);
|
|
438
|
+
acc.pushFrame(siteIdx);
|
|
439
|
+
let calleePath;
|
|
440
|
+
if (calleeNode) {
|
|
441
|
+
const callee = this.unwrapLvalue(calleeNode);
|
|
442
|
+
if (callee.type === 'identifier') {
|
|
443
|
+
// For a `new Foo(...)`, the `type` is a type name, not a scalar
|
|
444
|
+
// binding — record neither a use nor an occurrence for it; for a bare
|
|
445
|
+
// call the callee name is a statement-level use but not an occurrence.
|
|
446
|
+
if (kind === 'call')
|
|
447
|
+
acc.addUseWithoutOccurrence(this.resolve(callee));
|
|
448
|
+
calleePath = callee.text;
|
|
449
|
+
}
|
|
450
|
+
else if (callee.type === 'member_access_expression') {
|
|
451
|
+
// skipFinalRead: the final access IS the callee, carried by the path.
|
|
452
|
+
// A static dotted path (`System.Console.WriteLine(...)`) parses as a
|
|
453
|
+
// member_access_expression chain too, so this one branch covers both
|
|
454
|
+
// instance and static dotted callees.
|
|
455
|
+
const chain = this.walkChain(callee, acc, true);
|
|
456
|
+
calleePath = chain.path;
|
|
457
|
+
if (chain.rootIdx !== undefined)
|
|
458
|
+
acc.setSiteReceiver(siteIdx, chain.rootIdx);
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
this.walkValue(callee, acc);
|
|
462
|
+
}
|
|
463
|
+
if (calleePath !== undefined)
|
|
464
|
+
acc.setSiteCallee(siteIdx, calleePath);
|
|
465
|
+
}
|
|
466
|
+
const resultDefs = this.resultDefTargets.get(node.id);
|
|
467
|
+
if (resultDefs !== undefined)
|
|
468
|
+
acc.setSiteResultDefs(siteIdx, resultDefs);
|
|
469
|
+
if (argsNode) {
|
|
470
|
+
let pos = 0;
|
|
471
|
+
for (let i = 0; i < argsNode.namedChildCount; i++) {
|
|
472
|
+
const arg = argsNode.namedChild(i);
|
|
473
|
+
// C# wraps each value in an `argument` node; the value is the inner
|
|
474
|
+
// expression (a named argument `name: x` exposes the label through the
|
|
475
|
+
// `name` field — skip it so `x` is what flows).
|
|
476
|
+
if (!arg || arg.type === 'comment')
|
|
477
|
+
continue;
|
|
478
|
+
acc.setFrameArg(pos);
|
|
479
|
+
const value = arg.type === 'argument' ? this.argumentValue(arg) : arg;
|
|
480
|
+
if (value)
|
|
481
|
+
this.walkValue(value, acc);
|
|
482
|
+
pos++;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
acc.popFrame();
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* The value expression inside an `argument` node. A named argument
|
|
489
|
+
* (`name: x`) carries the label on the `name` field and the value as a
|
|
490
|
+
* sibling; a positional argument is just the value. Returns the last named
|
|
491
|
+
* child that is not the `name`-field label (and skips `ref`/`out`/`in`
|
|
492
|
+
* modifier keywords, which are anonymous tokens, not named children).
|
|
493
|
+
*/
|
|
494
|
+
argumentValue(arg) {
|
|
495
|
+
const label = arg.childForFieldName('name');
|
|
496
|
+
for (let i = arg.namedChildCount - 1; i >= 0; i--) {
|
|
497
|
+
const c = arg.namedChild(i);
|
|
498
|
+
if (c && c.id !== label?.id)
|
|
499
|
+
return c;
|
|
500
|
+
}
|
|
501
|
+
return undefined;
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Member chain walk shared by value position and callee position. Records the
|
|
505
|
+
* chain-root identifier as a use (identical to the old default descent), plus
|
|
506
|
+
* at most ONE member-read site — the INNERMOST access — when the root is an
|
|
507
|
+
* identifier; `skipFinalRead` suppresses it when that access is the callee.
|
|
508
|
+
*/
|
|
509
|
+
walkChain(node, acc, skipFinalRead) {
|
|
510
|
+
const accesses = [];
|
|
511
|
+
let cur = this.unwrapLvalue(node);
|
|
512
|
+
for (;;) {
|
|
513
|
+
if (cur.type === 'member_access_expression') {
|
|
514
|
+
const name = cur.childForFieldName('name');
|
|
515
|
+
accesses.unshift(name?.text ?? '');
|
|
516
|
+
const expr = cur.childForFieldName('expression');
|
|
517
|
+
if (!expr)
|
|
518
|
+
break;
|
|
519
|
+
cur = this.unwrapLvalue(expr);
|
|
520
|
+
}
|
|
521
|
+
else {
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
let rootIdx;
|
|
526
|
+
let rootSegment;
|
|
527
|
+
if (cur.type === 'identifier') {
|
|
528
|
+
rootIdx = this.resolve(cur);
|
|
529
|
+
acc.addUse(rootIdx);
|
|
530
|
+
rootSegment = cur.text;
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
this.walkValue(cur, acc);
|
|
534
|
+
}
|
|
535
|
+
const innermost = accesses[0];
|
|
536
|
+
if (rootIdx !== undefined && innermost && !(skipFinalRead && accesses.length === 1)) {
|
|
537
|
+
acc.addMemberRead(rootIdx, innermost);
|
|
538
|
+
}
|
|
539
|
+
const path = rootSegment !== undefined && accesses.every((a) => a !== '')
|
|
540
|
+
? [rootSegment, ...accesses].join('.')
|
|
541
|
+
: undefined;
|
|
542
|
+
return { path, rootIdx };
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* The initializer value of a `variable_declarator` — the named child after
|
|
546
|
+
* `name`. NOTE: deliberately duplicated in `csharp.ts` (the visitor is a
|
|
547
|
+
* standalone class with no shared base — repo convention). The two copies must
|
|
548
|
+
* stay in sync; there is no C#-specific shared module to host it, and the only
|
|
549
|
+
* module both files share is the generic `utils/ast-helpers` (types only).
|
|
550
|
+
*/
|
|
551
|
+
declaratorInit(declarator) {
|
|
552
|
+
const name = declarator.childForFieldName('name');
|
|
553
|
+
for (let i = 0; i < declarator.namedChildCount; i++) {
|
|
554
|
+
const c = declarator.namedChild(i);
|
|
555
|
+
if (c && c.id !== name?.id)
|
|
556
|
+
return c;
|
|
557
|
+
}
|
|
558
|
+
return undefined;
|
|
559
|
+
}
|
|
560
|
+
/** Whether a unary expression is `++`/`--` (the only writing unary ops). */
|
|
561
|
+
isIncDec(node) {
|
|
562
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
563
|
+
const c = node.child(i);
|
|
564
|
+
if (c && !c.isNamed && (c.text === '++' || c.text === '--'))
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
/** Def each identifier in a `(a, b) = …` tuple deconstruction target. */
|
|
570
|
+
defTupleTargets(tuple, acc) {
|
|
571
|
+
for (let i = 0; i < tuple.namedChildCount; i++) {
|
|
572
|
+
const c = tuple.namedChild(i);
|
|
573
|
+
if (!c)
|
|
574
|
+
continue;
|
|
575
|
+
// tuple_expression wraps each element in an `argument`.
|
|
576
|
+
const inner = c.type === 'argument' ? c.namedChild(0) : c;
|
|
577
|
+
if (inner?.type === 'identifier')
|
|
578
|
+
this.def(inner, acc);
|
|
579
|
+
else if (inner)
|
|
580
|
+
this.walkValue(inner, acc);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Ordered, deduplicating def/use + call-site collector for one statement record.
|
|
586
|
+
* The shared {@link CallSiteFactAccumulator} carries the def/use machinery the
|
|
587
|
+
* old local class had, plus the taint-site harvest (#2195 U6).
|
|
588
|
+
*/
|
|
589
|
+
const FactAccumulator = CallSiteFactAccumulator;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C# CfgVisitor (#2195 U3, plan KTD2).
|
|
3
|
+
*
|
|
4
|
+
* Walks a 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 CsharpHarvester}) for the reaching-defs / CDG solvers.
|
|
7
|
+
* Structured like the TS visitor — a `visit_<node_type>` dispatch over the
|
|
8
|
+
* statement taxonomy, driving a per-function {@link ControlFlowContext} — because
|
|
9
|
+
* C# shares TS's `finally` semantics (try/finally AND `using`/`lock`-as-finally),
|
|
10
|
+
* which the finalizer-frame machinery in `control-flow-context.ts` models.
|
|
11
|
+
*
|
|
12
|
+
* Every node type and field literal below was grammar-validated against
|
|
13
|
+
* tree-sitter-c-sharp via the introspection probe before use (mandatory pre-step,
|
|
14
|
+
* KTD5). Known C# surprises pre-empted: records are `record_declaration` (NOT
|
|
15
|
+
* `record_struct_declaration`); there is no `else_clause` wrapper (an
|
|
16
|
+
* `if_statement`'s `alternative` is the else body / nested `if` directly); switch
|
|
17
|
+
* cases live in `switch_section`s under a `switch_body`; `variable_declarator`
|
|
18
|
+
* exposes only a `name` field (the initializer is a positional child);
|
|
19
|
+
* `finally_clause` / `lock_statement` / `catch_filter_clause` expose no field for
|
|
20
|
+
* their body/condition (positional children).
|
|
21
|
+
*
|
|
22
|
+
* Function nodes: `method_declaration`, `local_function_statement`,
|
|
23
|
+
* `constructor_declaration`, `lambda_expression`, `anonymous_method_expression`,
|
|
24
|
+
* and expression-bodied members (`body` is an `arrow_expression_clause`).
|
|
25
|
+
*
|
|
26
|
+
* Edge-kind contract (matches the TS visitor — RD/CDG consume these):
|
|
27
|
+
* - if/else → `cond-true` / `cond-false`
|
|
28
|
+
* - loops (for / foreach / while / do-while) → `cond-true` / `loop-back` /
|
|
29
|
+
* `cond-false`
|
|
30
|
+
* - switch (`switch_statement`) → `switch-case` / `fallthrough`; a
|
|
31
|
+
* `switch_expression` arm dispatches as `switch-case` (each arm a guarded
|
|
32
|
+
* branch, no fallthrough)
|
|
33
|
+
* - try/catch → `throw` (every protected-region block → the handler); a jump
|
|
34
|
+
* crossing a `finally` → `finally-return` / `finally-break` / `finally-continue`
|
|
35
|
+
* - `using` / `lock` → modeled like try/finally: the dispose (`using`) runs on
|
|
36
|
+
* BOTH normal and exception exit (deterministic), so a `return`/`break`/
|
|
37
|
+
* `continue` crossing it gets the `finally-*` completion edge too. `lock`'s
|
|
38
|
+
* monitor-release is likewise a deterministic finalizer.
|
|
39
|
+
* - return / throw / break / continue → the matching terminator kind
|
|
40
|
+
* - straight-line → `seq`
|
|
41
|
+
*
|
|
42
|
+
* Classic hazards, handled explicitly (mirrors the TS visitor):
|
|
43
|
+
* - loops allocate a dedicated loop-exit block so `break` has a target before
|
|
44
|
+
* the loop's successor is known; `continue` targets the header/increment.
|
|
45
|
+
* - `for (;;) {}` / `while (true) {}` still emit the structural `header →
|
|
46
|
+
* loopExit` `cond-false` escape edge so EXIT stays reverse-reachable from
|
|
47
|
+
* every block — the post-dominator / CDG pass silently emits zero CDG for the
|
|
48
|
+
* function otherwise.
|
|
49
|
+
* - labeled `goto`: labels resolve within the function (forward AND backward);
|
|
50
|
+
* an unresolved `goto` (incl. `goto case`/`goto default`, which target a
|
|
51
|
+
* switch arm this CFG does not label) routes to EXIT and logs, preserving
|
|
52
|
+
* single-exit.
|
|
53
|
+
* - try/catch: conservative exceptional flow — EVERY block in the protected
|
|
54
|
+
* region edges to the handler (an exception may fire mid-block), matching the
|
|
55
|
+
* TS `visitTry` over-approximation.
|
|
56
|
+
*
|
|
57
|
+
* Known limitations:
|
|
58
|
+
* - `yield return` / `yield break`: C# iterator methods compile to a hidden
|
|
59
|
+
* state machine; tree-sitter shows only the surface `yield_statement`. This
|
|
60
|
+
* visitor models `yield break` as a terminator → EXIT (`return`) and
|
|
61
|
+
* `yield return e` as a block whose value continues to the next statement
|
|
62
|
+
* (the producer resumes after the consumer pulls). The real suspend/resume
|
|
63
|
+
* state-machine control flow is NOT modeled — documented gap, not faked.
|
|
64
|
+
* - `goto case L;` / `goto default;` have no statically-labeled CFG target
|
|
65
|
+
* (switch arms are not labeled blocks here) and route to EXIT like an
|
|
66
|
+
* unresolved label.
|
|
67
|
+
* - Async/await suspension points are modeled as straight-line (the awaited
|
|
68
|
+
* continuation is not a separate flow), consistent with the TS visitor.
|
|
69
|
+
* - A value-position `switch_expression` (`k switch {…}`) with ≥2 arms IS modeled
|
|
70
|
+
* as a `switch-case` dispatch in three carriers (#2207): a single-declarator
|
|
71
|
+
* `var x = k switch {…}` (arms rejoin at a binding continuation), `return k
|
|
72
|
+
* switch {…}`, and an `=> k switch {…}` expression body (each arm returns).
|
|
73
|
+
* A value switch in any OTHER position — an assignment RHS (`x = k switch …`),
|
|
74
|
+
* a call argument, or a multi-declarator decl — stays INLINE (one block).
|
|
75
|
+
* - Def/use harvest scope: see `csharp-harvest.ts` — member/element writes are
|
|
76
|
+
* not scalar defs; nested-function bodies are opaque in both directions.
|
|
77
|
+
*
|
|
78
|
+
* Returns `undefined` (never throws) for an AST shape it cannot model, so a
|
|
79
|
+
* malformed function never drops the whole file's CFG group (R4).
|
|
80
|
+
*/
|
|
81
|
+
import type { SyntaxNode } from '../../utils/ast-helpers.js';
|
|
82
|
+
import type { CfgVisitor } from '../types.js';
|
|
83
|
+
/** C# node types that own a CFG-bearing function body. */
|
|
84
|
+
declare const CSHARP_FUNCTION_TYPES: Set<string>;
|
|
85
|
+
/** The C# CFG visitor. */
|
|
86
|
+
export declare function createCsharpCfgVisitor(): CfgVisitor<SyntaxNode>;
|
|
87
|
+
export { CSHARP_FUNCTION_TYPES };
|