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,719 @@
|
|
|
1
|
+
import { CallSiteFactAccumulator as FactAccumulator, finalizeChain } from './call-site-harvest.js';
|
|
2
|
+
/** Node types that own a nested CFG — their subtrees are opaque to harvesting. */
|
|
3
|
+
const NESTED_FUNCTION_TYPES = new Set([
|
|
4
|
+
'function_declaration',
|
|
5
|
+
'anonymous_function',
|
|
6
|
+
'lambda_literal',
|
|
7
|
+
]);
|
|
8
|
+
const COMMENT_TYPES = new Set(['line_comment', 'multiline_comment', 'shebang_line']);
|
|
9
|
+
export class KotlinHarvester {
|
|
10
|
+
fnNode;
|
|
11
|
+
bindings = [];
|
|
12
|
+
/** Single function-scope name → binding index (v1: no block scope). */
|
|
13
|
+
table = new Map();
|
|
14
|
+
synthetic = new Map();
|
|
15
|
+
fnId;
|
|
16
|
+
/** >0 while walking a conditionally-evaluated subexpression — defs become may-defs. */
|
|
17
|
+
conditionalDepth = 0;
|
|
18
|
+
/**
|
|
19
|
+
* `call_expression` node id → binding indices its single-target result is
|
|
20
|
+
* assigned to (`val x = f()` / `x = g()` ⇒ `[x]`). Populated just before the
|
|
21
|
+
* value walk reaches the call (see {@link registerResultDefs}) and consumed by
|
|
22
|
+
* {@link visitCall}. Mirrors the Go / Python / Dart harvesters' `resultDefTargets`.
|
|
23
|
+
*/
|
|
24
|
+
resultDefTargets = new Map();
|
|
25
|
+
constructor(fnNode) {
|
|
26
|
+
this.fnNode = fnNode;
|
|
27
|
+
this.fnId = fnNode.id;
|
|
28
|
+
this.declareParams(fnNode);
|
|
29
|
+
const body = this.bodyOf(fnNode);
|
|
30
|
+
if (body)
|
|
31
|
+
this.prescan(body);
|
|
32
|
+
}
|
|
33
|
+
/** The completed binding table — pass to `CfgBuilder.finish`. */
|
|
34
|
+
bindingTable() {
|
|
35
|
+
return this.bindings;
|
|
36
|
+
}
|
|
37
|
+
/** The function/lambda body subtree to pre-scan (`statements` or `function_body`). */
|
|
38
|
+
bodyOf(fnNode) {
|
|
39
|
+
if (fnNode.type === 'lambda_literal') {
|
|
40
|
+
return fnNode.namedChildren.find((c) => c.type === 'statements');
|
|
41
|
+
}
|
|
42
|
+
return fnNode.namedChildren.find((c) => c.type === 'function_body');
|
|
43
|
+
}
|
|
44
|
+
// ── phase 1: declaration pre-scan ────────────────────────────────────────
|
|
45
|
+
declare(nameNode, kind) {
|
|
46
|
+
const name = nameNode.text;
|
|
47
|
+
if (!name || name === '_' || this.table.has(name))
|
|
48
|
+
return;
|
|
49
|
+
this.table.set(name, this.bindings.length);
|
|
50
|
+
this.bindings.push({
|
|
51
|
+
name,
|
|
52
|
+
declLine: nameNode.startPosition.row + 1,
|
|
53
|
+
declColumn: nameNode.startPosition.column,
|
|
54
|
+
kind,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** Declare every parameter binder of a fn / anonymous fn / lambda. */
|
|
58
|
+
declareParams(fnNode) {
|
|
59
|
+
const params = fnNode.namedChildren.find((c) => c.type === 'function_value_parameters');
|
|
60
|
+
if (params) {
|
|
61
|
+
for (const p of params.namedChildren) {
|
|
62
|
+
if (p.type !== 'parameter')
|
|
63
|
+
continue;
|
|
64
|
+
const name = p.namedChildren.find((c) => c.type === 'simple_identifier');
|
|
65
|
+
if (name)
|
|
66
|
+
this.declare(name, 'param');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Lambda params: `lambda_parameters` → `variable_declaration`(s).
|
|
70
|
+
const lambdaParams = fnNode.namedChildren.find((c) => c.type === 'lambda_parameters');
|
|
71
|
+
if (lambdaParams) {
|
|
72
|
+
for (const vd of lambdaParams.namedChildren) {
|
|
73
|
+
if (vd.type === 'variable_declaration')
|
|
74
|
+
this.declareVariableDeclaration(vd, 'param');
|
|
75
|
+
else if (vd.type === 'multi_variable_declaration') {
|
|
76
|
+
for (const inner of vd.namedChildren) {
|
|
77
|
+
if (inner.type === 'variable_declaration')
|
|
78
|
+
this.declareVariableDeclaration(inner, 'param');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** Declare the `simple_identifier` of a `variable_declaration`. */
|
|
85
|
+
declareVariableDeclaration(vd, kind) {
|
|
86
|
+
const id = vd.namedChildren.find((c) => c.type === 'simple_identifier') ?? vd;
|
|
87
|
+
if (id.type === 'simple_identifier')
|
|
88
|
+
this.declare(id, kind);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Pre-scan the function body once, declaring every bound name. Recurses into
|
|
92
|
+
* compound expressions but NOT into nested function/lambda bodies (opaque).
|
|
93
|
+
*/
|
|
94
|
+
prescan(node) {
|
|
95
|
+
const t = node.type;
|
|
96
|
+
if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId)
|
|
97
|
+
return;
|
|
98
|
+
switch (t) {
|
|
99
|
+
case 'property_declaration':
|
|
100
|
+
this.declarePropertyPattern(node, 'let');
|
|
101
|
+
break;
|
|
102
|
+
case 'for_statement':
|
|
103
|
+
this.declareForPattern(node);
|
|
104
|
+
break;
|
|
105
|
+
case 'catch_block':
|
|
106
|
+
this.declareCatchParam(node);
|
|
107
|
+
break;
|
|
108
|
+
case 'when_subject':
|
|
109
|
+
this.declareWhenSubject(node);
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
115
|
+
const c = node.namedChild(i);
|
|
116
|
+
if (c)
|
|
117
|
+
this.prescan(c);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** Declare every binder of a `property_declaration`'s pattern (single or multi). */
|
|
121
|
+
declarePropertyPattern(node, kind) {
|
|
122
|
+
const single = node.namedChildren.find((c) => c.type === 'variable_declaration');
|
|
123
|
+
if (single) {
|
|
124
|
+
this.declareVariableDeclaration(single, kind);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const multi = node.namedChildren.find((c) => c.type === 'multi_variable_declaration');
|
|
128
|
+
if (multi) {
|
|
129
|
+
for (const vd of multi.namedChildren) {
|
|
130
|
+
if (vd.type === 'variable_declaration')
|
|
131
|
+
this.declareVariableDeclaration(vd, kind);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** Declare a `for` loop variable (`variable_declaration` / `multi_variable_declaration`). */
|
|
136
|
+
declareForPattern(node) {
|
|
137
|
+
const single = node.namedChildren.find((c) => c.type === 'variable_declaration');
|
|
138
|
+
if (single) {
|
|
139
|
+
this.declareVariableDeclaration(single, 'let');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const multi = node.namedChildren.find((c) => c.type === 'multi_variable_declaration');
|
|
143
|
+
if (multi) {
|
|
144
|
+
for (const vd of multi.namedChildren) {
|
|
145
|
+
if (vd.type === 'variable_declaration')
|
|
146
|
+
this.declareVariableDeclaration(vd, 'let');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Declare a `catch (e: T)` error name. */
|
|
151
|
+
declareCatchParam(node) {
|
|
152
|
+
const id = node.namedChildren.find((c) => c.type === 'simple_identifier');
|
|
153
|
+
if (id)
|
|
154
|
+
this.declare(id, 'catch');
|
|
155
|
+
}
|
|
156
|
+
/** Declare a `when (val r = e)` subject binding. */
|
|
157
|
+
declareWhenSubject(node) {
|
|
158
|
+
const vd = node.namedChildren.find((c) => c.type === 'variable_declaration');
|
|
159
|
+
if (vd)
|
|
160
|
+
this.declareVariableDeclaration(vd, 'let');
|
|
161
|
+
}
|
|
162
|
+
// ── phase 2: per-statement fact extraction ───────────────────────────────
|
|
163
|
+
/** Def/use facts for one statement (or construct-header expression) node. */
|
|
164
|
+
facts(node) {
|
|
165
|
+
const acc = new FactAccumulator(node.startPosition.row + 1);
|
|
166
|
+
this.walkValue(node, acc);
|
|
167
|
+
return acc.finish();
|
|
168
|
+
}
|
|
169
|
+
/** Facts for an expression whose WHOLE evaluation is conditional (case tests). */
|
|
170
|
+
factsConditional(node) {
|
|
171
|
+
const acc = new FactAccumulator(node.startPosition.row + 1);
|
|
172
|
+
this.conditional(() => this.walkValue(node, acc));
|
|
173
|
+
return acc.finish();
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Facts for a `for ( PAT in COLLECTION )` head: the loop pattern's leaves are
|
|
177
|
+
* defs, the iterated collection a use.
|
|
178
|
+
*/
|
|
179
|
+
forHeadFacts(stmt) {
|
|
180
|
+
const acc = new FactAccumulator(stmt.startPosition.row + 1);
|
|
181
|
+
const collection = this.forCollection(stmt);
|
|
182
|
+
if (collection)
|
|
183
|
+
this.walkValue(collection, acc);
|
|
184
|
+
this.defForPattern(stmt, acc);
|
|
185
|
+
return acc.finish();
|
|
186
|
+
}
|
|
187
|
+
/** Facts for a `when` subject: a `val r = e` binds `r` (def); the expr's uses. */
|
|
188
|
+
whenSubjectFacts(subject) {
|
|
189
|
+
const acc = new FactAccumulator(subject.startPosition.row + 1);
|
|
190
|
+
const vd = subject.namedChildren.find((c) => c.type === 'variable_declaration');
|
|
191
|
+
// Walk the subject's value expression(s) for uses; bind the `val` name.
|
|
192
|
+
for (const c of subject.namedChildren) {
|
|
193
|
+
if (c.type === 'variable_declaration')
|
|
194
|
+
continue;
|
|
195
|
+
this.walkValue(c, acc);
|
|
196
|
+
}
|
|
197
|
+
if (vd)
|
|
198
|
+
this.defVariableDeclaration(vd, acc);
|
|
199
|
+
return acc.finish();
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Def-ONLY facts for a value-position binding carrier (`val x = <branch>`,
|
|
203
|
+
* #2205): just the bound name's def, attached to the continuation block the
|
|
204
|
+
* branch arms rejoin. The branch subject + arm-value USES are already harvested
|
|
205
|
+
* onto the branch's own blocks (visitWhen / visitIf), so this must not re-walk
|
|
206
|
+
* them — only the `variable_declaration` leaves are defs here.
|
|
207
|
+
*/
|
|
208
|
+
bindingDefFacts(stmt) {
|
|
209
|
+
const acc = new FactAccumulator(stmt.startPosition.row + 1);
|
|
210
|
+
this.defForPattern(stmt, acc);
|
|
211
|
+
return acc.defCount() ? acc.finish() : undefined;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Def-ONLY facts for a value-position assignment carrier (`x = when (k) {…}`,
|
|
215
|
+
* #2205): just the LHS target, attached to the continuation block the branch
|
|
216
|
+
* arms rejoin. The branch subject + arm-value USES are already harvested onto
|
|
217
|
+
* the branch's own blocks, so this must NOT re-walk the RHS — only a plain `=`
|
|
218
|
+
* to a simple-identifier lvalue defines (a member / index target is not a
|
|
219
|
+
* scalar def; a compound `+=` is not a value-branch carrier).
|
|
220
|
+
*/
|
|
221
|
+
assignmentDefFacts(node) {
|
|
222
|
+
if (this.assignmentOperator(node) !== '=')
|
|
223
|
+
return undefined;
|
|
224
|
+
const acc = new FactAccumulator(node.startPosition.row + 1);
|
|
225
|
+
const lvalue = node.namedChildren.find((c) => c.type === 'directly_assignable_expression');
|
|
226
|
+
if (lvalue) {
|
|
227
|
+
const lv = this.unwrapAssignable(lvalue);
|
|
228
|
+
if (lv.type === 'simple_identifier')
|
|
229
|
+
this.def(lv, acc);
|
|
230
|
+
}
|
|
231
|
+
return acc.defCount() ? acc.finish() : undefined;
|
|
232
|
+
}
|
|
233
|
+
/** ENTRY-block facts for the parameters (defs only). */
|
|
234
|
+
paramFacts() {
|
|
235
|
+
const acc = new FactAccumulator(this.fnNode.startPosition.row + 1);
|
|
236
|
+
const params = this.fnNode.namedChildren.find((c) => c.type === 'function_value_parameters');
|
|
237
|
+
if (params) {
|
|
238
|
+
for (const p of params.namedChildren) {
|
|
239
|
+
if (p.type !== 'parameter')
|
|
240
|
+
continue;
|
|
241
|
+
const name = p.namedChildren.find((c) => c.type === 'simple_identifier');
|
|
242
|
+
if (name)
|
|
243
|
+
this.def(name, acc);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const lambdaParams = this.fnNode.namedChildren.find((c) => c.type === 'lambda_parameters');
|
|
247
|
+
if (lambdaParams) {
|
|
248
|
+
for (const vd of lambdaParams.namedChildren) {
|
|
249
|
+
if (vd.type === 'variable_declaration')
|
|
250
|
+
this.defVariableDeclaration(vd, acc);
|
|
251
|
+
else if (vd.type === 'multi_variable_declaration') {
|
|
252
|
+
for (const inner of vd.namedChildren) {
|
|
253
|
+
if (inner.type === 'variable_declaration')
|
|
254
|
+
this.defVariableDeclaration(inner, acc);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return acc.defCount() ? acc.finish() : undefined;
|
|
260
|
+
}
|
|
261
|
+
/** Def fact for a `catch (e: T)` error name — prepend to the handler entry block. */
|
|
262
|
+
catchParamFacts(catchBlock) {
|
|
263
|
+
const id = catchBlock.namedChildren.find((c) => c.type === 'simple_identifier');
|
|
264
|
+
if (!id)
|
|
265
|
+
return undefined;
|
|
266
|
+
const acc = new FactAccumulator(catchBlock.startPosition.row + 1);
|
|
267
|
+
this.def(id, acc);
|
|
268
|
+
return acc.defCount() ? acc.finish() : undefined;
|
|
269
|
+
}
|
|
270
|
+
resolve(nameNode) {
|
|
271
|
+
const name = nameNode.text;
|
|
272
|
+
const idx = this.table.get(name);
|
|
273
|
+
if (idx !== undefined)
|
|
274
|
+
return idx;
|
|
275
|
+
let syn = this.synthetic.get(name);
|
|
276
|
+
if (syn === undefined) {
|
|
277
|
+
syn = this.bindings.length;
|
|
278
|
+
this.synthetic.set(name, syn);
|
|
279
|
+
this.bindings.push({ name, declLine: 0, declColumn: 0, kind: 'module', synthetic: true });
|
|
280
|
+
}
|
|
281
|
+
return syn;
|
|
282
|
+
}
|
|
283
|
+
def(nameNode, acc) {
|
|
284
|
+
if (nameNode.text === '_')
|
|
285
|
+
return; // blank target defines nothing
|
|
286
|
+
if (this.conditionalDepth > 0)
|
|
287
|
+
acc.addMayDef(this.resolve(nameNode));
|
|
288
|
+
else
|
|
289
|
+
acc.addDef(this.resolve(nameNode));
|
|
290
|
+
}
|
|
291
|
+
use(nameNode, acc) {
|
|
292
|
+
if (nameNode.text === '_')
|
|
293
|
+
return;
|
|
294
|
+
acc.addUse(this.resolve(nameNode));
|
|
295
|
+
}
|
|
296
|
+
/** Run `fn` with defs demoted to may-defs (conditionally-evaluated context). */
|
|
297
|
+
conditional(fn) {
|
|
298
|
+
this.conditionalDepth++;
|
|
299
|
+
try {
|
|
300
|
+
fn();
|
|
301
|
+
}
|
|
302
|
+
finally {
|
|
303
|
+
this.conditionalDepth--;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/** Def the `simple_identifier` of a `variable_declaration`. */
|
|
307
|
+
defVariableDeclaration(vd, acc) {
|
|
308
|
+
const id = vd.namedChildren.find((c) => c.type === 'simple_identifier');
|
|
309
|
+
if (id)
|
|
310
|
+
this.def(id, acc);
|
|
311
|
+
}
|
|
312
|
+
/** Def every binder of a `for` loop pattern. */
|
|
313
|
+
defForPattern(stmt, acc) {
|
|
314
|
+
const single = stmt.namedChildren.find((c) => c.type === 'variable_declaration');
|
|
315
|
+
if (single) {
|
|
316
|
+
this.defVariableDeclaration(single, acc);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
const multi = stmt.namedChildren.find((c) => c.type === 'multi_variable_declaration');
|
|
320
|
+
if (multi) {
|
|
321
|
+
for (const vd of multi.namedChildren) {
|
|
322
|
+
if (vd.type === 'variable_declaration')
|
|
323
|
+
this.defVariableDeclaration(vd, acc);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/** The iterated collection of a `for_statement` — the named child after `in`. */
|
|
328
|
+
forCollection(stmt) {
|
|
329
|
+
let sawIn = false;
|
|
330
|
+
for (let i = 0; i < stmt.childCount; i++) {
|
|
331
|
+
const c = stmt.child(i);
|
|
332
|
+
if (!c)
|
|
333
|
+
continue;
|
|
334
|
+
if (c.type === 'in') {
|
|
335
|
+
sawIn = true;
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
if (c.type === ')')
|
|
339
|
+
return undefined;
|
|
340
|
+
if (sawIn && c.isNamed && !COMMENT_TYPES.has(c.type))
|
|
341
|
+
return c;
|
|
342
|
+
}
|
|
343
|
+
return undefined;
|
|
344
|
+
}
|
|
345
|
+
/** Value-position walk: collect uses; route def positions to the pattern handler. */
|
|
346
|
+
walkValue(node, acc) {
|
|
347
|
+
const t = node.type;
|
|
348
|
+
if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId)
|
|
349
|
+
return; // opaque
|
|
350
|
+
switch (t) {
|
|
351
|
+
case 'simple_identifier':
|
|
352
|
+
this.use(node, acc);
|
|
353
|
+
return;
|
|
354
|
+
case 'property_declaration': {
|
|
355
|
+
// Walk the value for uses, then def each pattern binder.
|
|
356
|
+
const binder = node.namedChildren.find((c) => c.type === 'variable_declaration' || c.type === 'multi_variable_declaration');
|
|
357
|
+
const value = this.propertyValue(node);
|
|
358
|
+
// Register result-defs BEFORE the value walk so the call site (reached
|
|
359
|
+
// during the walk) carries them — single `variable_declaration` binder
|
|
360
|
+
// only (`val x = f()`); a `multi_variable_declaration` destructuring
|
|
361
|
+
// (`val (a, b) = p`) attaches nothing.
|
|
362
|
+
if (value && binder?.type === 'variable_declaration') {
|
|
363
|
+
const id = binder.namedChildren.find((c) => c.type === 'simple_identifier');
|
|
364
|
+
if (id)
|
|
365
|
+
this.registerResultDefs(value, [id]);
|
|
366
|
+
}
|
|
367
|
+
if (value)
|
|
368
|
+
this.walkValue(value, acc);
|
|
369
|
+
if (binder?.type === 'variable_declaration')
|
|
370
|
+
this.defVariableDeclaration(binder, acc);
|
|
371
|
+
else if (binder?.type === 'multi_variable_declaration') {
|
|
372
|
+
for (const vd of binder.namedChildren) {
|
|
373
|
+
if (vd.type === 'variable_declaration')
|
|
374
|
+
this.defVariableDeclaration(vd, acc);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
case 'assignment': {
|
|
380
|
+
const lvalue = node.namedChildren.find((c) => c.type === 'directly_assignable_expression');
|
|
381
|
+
const op = this.assignmentOperator(node);
|
|
382
|
+
const value = this.assignmentValue(node);
|
|
383
|
+
const scalar = lvalue ? this.unwrapAssignable(lvalue) : undefined;
|
|
384
|
+
// Plain `x = f(a)` attaches `resultDefs: [x]` (a compound `x += f(a)`
|
|
385
|
+
// does not — the prior value flows in too; a member/index lvalue is not
|
|
386
|
+
// a scalar def).
|
|
387
|
+
if (value && op === '=' && scalar?.type === 'simple_identifier') {
|
|
388
|
+
this.registerResultDefs(value, [scalar]);
|
|
389
|
+
}
|
|
390
|
+
if (value)
|
|
391
|
+
this.walkValue(value, acc);
|
|
392
|
+
if (lvalue) {
|
|
393
|
+
const lv = scalar ?? this.unwrapAssignable(lvalue);
|
|
394
|
+
if (lv.type === 'simple_identifier') {
|
|
395
|
+
this.def(lv, acc);
|
|
396
|
+
if (op !== '=')
|
|
397
|
+
this.use(lv, acc); // compound assign reads too
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
// `this.x = …`, `a[i] = …` — root is a use only (not a scalar def).
|
|
401
|
+
this.walkValue(lv, acc);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
case 'postfix_expression':
|
|
407
|
+
case 'prefix_expression': {
|
|
408
|
+
// `x++` / `--x` — def AND use the operand when it is a plain identifier
|
|
409
|
+
// and the operator is an increment/decrement. Other pre/postfix forms
|
|
410
|
+
// (`-x`, `!x`, `x!!`, `x?`) are pure reads → walk the operand as a use.
|
|
411
|
+
const operand = node.namedChild(0);
|
|
412
|
+
if (operand?.type === 'simple_identifier' && this.isIncDec(node)) {
|
|
413
|
+
this.def(operand, acc);
|
|
414
|
+
this.use(operand, acc);
|
|
415
|
+
}
|
|
416
|
+
else if (operand) {
|
|
417
|
+
this.walkValue(operand, acc);
|
|
418
|
+
}
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
case 'call_expression':
|
|
422
|
+
// #2227 follow-up: explicit case (previously default-descended) — same
|
|
423
|
+
// uses, plus a taint-site record. Kotlin has no `new` (constructor calls
|
|
424
|
+
// are plain `call_expression`s). Defs/uses stay byte-identical.
|
|
425
|
+
this.visitCall(node, acc);
|
|
426
|
+
return;
|
|
427
|
+
case 'navigation_expression': {
|
|
428
|
+
// `a.b` / `a?.b` — value read of the chain root only; the suffix name is
|
|
429
|
+
// not a scalar binding. Records the chain-root use (identical to the old
|
|
430
|
+
// descent) plus at most ONE member-read site (the innermost access),
|
|
431
|
+
// mirroring the Go / Python harvesters' value-position `walkChain`.
|
|
432
|
+
this.walkChain(node, acc, false);
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
case 'conjunction_expression':
|
|
436
|
+
case 'disjunction_expression': {
|
|
437
|
+
// `a && b` / `a || b` — the right operand is conditionally evaluated.
|
|
438
|
+
const operands = node.namedChildren.filter((c) => !COMMENT_TYPES.has(c.type));
|
|
439
|
+
if (operands.length > 0)
|
|
440
|
+
this.walkValue(operands[0], acc);
|
|
441
|
+
for (let i = 1; i < operands.length; i++) {
|
|
442
|
+
const rhs = operands[i];
|
|
443
|
+
this.conditional(() => this.walkValue(rhs, acc));
|
|
444
|
+
}
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
case 'elvis_expression': {
|
|
448
|
+
// `a ?: b` — the right operand only evaluates when the left is null.
|
|
449
|
+
const operands = node.namedChildren.filter((c) => !COMMENT_TYPES.has(c.type));
|
|
450
|
+
if (operands.length > 0)
|
|
451
|
+
this.walkValue(operands[0], acc);
|
|
452
|
+
for (let i = 1; i < operands.length; i++) {
|
|
453
|
+
const rhs = operands[i];
|
|
454
|
+
this.conditional(() => this.walkValue(rhs, acc));
|
|
455
|
+
}
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
case 'when_subject':
|
|
459
|
+
case 'user_type':
|
|
460
|
+
case 'type_identifier':
|
|
461
|
+
case 'binding_pattern_kind':
|
|
462
|
+
// Binding keyword / type position — no scalar value uses.
|
|
463
|
+
return;
|
|
464
|
+
default:
|
|
465
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
466
|
+
const c = node.namedChild(i);
|
|
467
|
+
if (c)
|
|
468
|
+
this.walkValue(c, acc);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
/** True iff `node` carries a `++` / `--` operator token (`x++` / `--x`). */
|
|
473
|
+
isIncDec(node) {
|
|
474
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
475
|
+
const c = node.child(i);
|
|
476
|
+
if (c && !c.isNamed && (c.text === '++' || c.text === '--'))
|
|
477
|
+
return true;
|
|
478
|
+
}
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
/** The `= value` expression of a `property_declaration` (the child after `=`). */
|
|
482
|
+
propertyValue(node) {
|
|
483
|
+
let sawEq = false;
|
|
484
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
485
|
+
const c = node.child(i);
|
|
486
|
+
if (!c)
|
|
487
|
+
continue;
|
|
488
|
+
if (c.type === '=') {
|
|
489
|
+
sawEq = true;
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
if (sawEq && c.isNamed && !COMMENT_TYPES.has(c.type))
|
|
493
|
+
return c;
|
|
494
|
+
}
|
|
495
|
+
return undefined;
|
|
496
|
+
}
|
|
497
|
+
/** The assignment operator text (`=` / `+=` / …) of an `assignment`. */
|
|
498
|
+
assignmentOperator(node) {
|
|
499
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
500
|
+
const c = node.child(i);
|
|
501
|
+
if (c && !c.isNamed && /^[+\-*/%]?=$/.test(c.type))
|
|
502
|
+
return c.type;
|
|
503
|
+
}
|
|
504
|
+
return '=';
|
|
505
|
+
}
|
|
506
|
+
/** The right-hand value of an `assignment` (the named child after the operator). */
|
|
507
|
+
assignmentValue(node) {
|
|
508
|
+
let sawOp = false;
|
|
509
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
510
|
+
const c = node.child(i);
|
|
511
|
+
if (!c)
|
|
512
|
+
continue;
|
|
513
|
+
if (!c.isNamed && /^[+\-*/%]?=$/.test(c.type)) {
|
|
514
|
+
sawOp = true;
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
if (sawOp && c.isNamed && !COMMENT_TYPES.has(c.type))
|
|
518
|
+
return c;
|
|
519
|
+
}
|
|
520
|
+
return undefined;
|
|
521
|
+
}
|
|
522
|
+
/** Strip a `directly_assignable_expression` wrapper around an lvalue. */
|
|
523
|
+
unwrapAssignable(node) {
|
|
524
|
+
let n = node;
|
|
525
|
+
let hops = 4;
|
|
526
|
+
while (n.type === 'directly_assignable_expression' && hops-- > 0) {
|
|
527
|
+
const inner = n.namedChild(0);
|
|
528
|
+
if (!inner)
|
|
529
|
+
break;
|
|
530
|
+
n = inner;
|
|
531
|
+
}
|
|
532
|
+
return n;
|
|
533
|
+
}
|
|
534
|
+
// ── taint-site harvest (#2227 follow-up) ─────────────────────────────────
|
|
535
|
+
/** Strip `parenthesized_expression` wrappers around a value (`(f())`). */
|
|
536
|
+
unwrapValue(node) {
|
|
537
|
+
let n = node;
|
|
538
|
+
let hops = 8;
|
|
539
|
+
while (n.type === 'parenthesized_expression' && hops-- > 0) {
|
|
540
|
+
const inner = n.namedChild(0);
|
|
541
|
+
if (!inner)
|
|
542
|
+
break;
|
|
543
|
+
n = inner;
|
|
544
|
+
}
|
|
545
|
+
return n;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* When `value`'s root (after stripping parens) is a `call_expression`, remember
|
|
549
|
+
* that call site should carry `resultDefs` — the binding indices of `targets`
|
|
550
|
+
* (def-position identifiers). Consumed by {@link visitCall} once the value walk
|
|
551
|
+
* reaches the node. Single-target only (the caller restricts to a plain
|
|
552
|
+
* identifier binder); the blank target (`_`) binds nothing and is skipped.
|
|
553
|
+
*/
|
|
554
|
+
registerResultDefs(value, targets) {
|
|
555
|
+
const root = this.unwrapValue(value);
|
|
556
|
+
if (root.type !== 'call_expression')
|
|
557
|
+
return;
|
|
558
|
+
const defs = [];
|
|
559
|
+
for (const target of targets) {
|
|
560
|
+
if (target.type !== 'simple_identifier' || target.text === '_')
|
|
561
|
+
continue;
|
|
562
|
+
defs.push(this.resolve(target));
|
|
563
|
+
}
|
|
564
|
+
if (defs.length > 0)
|
|
565
|
+
this.resultDefTargets.set(root.id, defs);
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* The callee node of a `call_expression` — the first named child that is NOT
|
|
569
|
+
* the trailing `call_suffix` (a bare `simple_identifier` for a free call, or a
|
|
570
|
+
* `navigation_expression` for a member/chained call).
|
|
571
|
+
*/
|
|
572
|
+
calleeOf(call) {
|
|
573
|
+
for (let i = 0; i < call.namedChildCount; i++) {
|
|
574
|
+
const c = call.namedChild(i);
|
|
575
|
+
if (c && c.type !== 'call_suffix' && !COMMENT_TYPES.has(c.type))
|
|
576
|
+
return c;
|
|
577
|
+
}
|
|
578
|
+
return undefined;
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Explicit `call_expression` handler. Records a call site (callee path,
|
|
582
|
+
* receiver, per-arg occurrence entries, result defs, spread marker) while
|
|
583
|
+
* reproducing EXACTLY the uses the old default descent recorded (callee chain
|
|
584
|
+
* root + arguments). Kotlin has no `new` — every site is `kind: 'call'`.
|
|
585
|
+
*/
|
|
586
|
+
visitCall(node, acc) {
|
|
587
|
+
const calleeNode = this.calleeOf(node);
|
|
588
|
+
// `node` IS the `call_expression` — the SAME node the scope query anchors
|
|
589
|
+
// `@reference.call.free/.member` on (its `atRange`), so the resolved-id join
|
|
590
|
+
// lands by exact position (see file header ANCHOR ALIGNMENT).
|
|
591
|
+
const siteIdx = acc.openCallSite('call', [
|
|
592
|
+
node.startPosition.row + 1,
|
|
593
|
+
node.startPosition.column,
|
|
594
|
+
]);
|
|
595
|
+
acc.pushFrame(siteIdx);
|
|
596
|
+
if (calleeNode) {
|
|
597
|
+
const callee = this.unwrapValue(calleeNode);
|
|
598
|
+
if (callee.type === 'simple_identifier') {
|
|
599
|
+
// A bare free call — the callee NAME is a statement-level use but NOT a
|
|
600
|
+
// value occurrence in any enclosing argument.
|
|
601
|
+
if (callee.text !== '_')
|
|
602
|
+
acc.addUseWithoutOccurrence(this.resolve(callee));
|
|
603
|
+
acc.setSiteCallee(siteIdx, callee.text);
|
|
604
|
+
}
|
|
605
|
+
else if (callee.type === 'navigation_expression') {
|
|
606
|
+
// skipFinalRead: the final `.name` IS the callee, carried by the path.
|
|
607
|
+
const chain = this.walkChain(callee, acc, true);
|
|
608
|
+
if (chain.path !== undefined)
|
|
609
|
+
acc.setSiteCallee(siteIdx, chain.path);
|
|
610
|
+
if (chain.rootIdx !== undefined)
|
|
611
|
+
acc.setSiteReceiver(siteIdx, chain.rootIdx);
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
// Call-rooted chains (`f().g()`), indexing (`m[k]()`), parenthesized
|
|
615
|
+
// callables — the walk still records uses and nested sites; the callee
|
|
616
|
+
// path is not statically known.
|
|
617
|
+
this.walkValue(callee, acc);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
const resultDefs = this.resultDefTargets.get(node.id);
|
|
621
|
+
if (resultDefs !== undefined)
|
|
622
|
+
acc.setSiteResultDefs(siteIdx, resultDefs);
|
|
623
|
+
const suffix = node.namedChildren.find((c) => c.type === 'call_suffix');
|
|
624
|
+
if (suffix)
|
|
625
|
+
this.walkArguments(suffix, siteIdx, acc);
|
|
626
|
+
acc.popFrame();
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Walk a `call_suffix`'s `value_arguments`, tagging each positional / named /
|
|
630
|
+
* spread argument's occurrence position. A trailing `annotated_lambda` is a
|
|
631
|
+
* nested function body — opaque (its `lambda_literal` is excluded by
|
|
632
|
+
* {@link NESTED_FUNCTION_TYPES}), so it is not an argument occurrence here.
|
|
633
|
+
*/
|
|
634
|
+
walkArguments(suffix, siteIdx, acc) {
|
|
635
|
+
const args = suffix.namedChildren.find((c) => c.type === 'value_arguments');
|
|
636
|
+
if (!args)
|
|
637
|
+
return;
|
|
638
|
+
let pos = 0;
|
|
639
|
+
for (let i = 0; i < args.namedChildCount; i++) {
|
|
640
|
+
const arg = args.namedChild(i);
|
|
641
|
+
if (!arg || arg.type !== 'value_argument')
|
|
642
|
+
continue;
|
|
643
|
+
acc.setFrameArg(pos);
|
|
644
|
+
const value = this.argumentValue(arg);
|
|
645
|
+
if (value?.type === 'spread_expression') {
|
|
646
|
+
// `f(*xs)` — a spread. Mark the first spread position so the matcher
|
|
647
|
+
// degrades soundly; the inner value still walks for occurrences.
|
|
648
|
+
acc.setSiteSpread(siteIdx, pos);
|
|
649
|
+
const inner = value.namedChild(0);
|
|
650
|
+
if (inner)
|
|
651
|
+
this.walkValue(inner, acc);
|
|
652
|
+
}
|
|
653
|
+
else if (value) {
|
|
654
|
+
this.walkValue(value, acc);
|
|
655
|
+
}
|
|
656
|
+
pos++;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* The value expression of a `value_argument` — for a named argument
|
|
661
|
+
* (`name = value`) the leading `simple_identifier` name is dropped (it is a
|
|
662
|
+
* parameter name, not a use), and only the value after `=` is returned; a
|
|
663
|
+
* positional argument's value is its sole non-comment named child.
|
|
664
|
+
*/
|
|
665
|
+
argumentValue(arg) {
|
|
666
|
+
// A named arg carries an anon `=` token; the value is the named child after
|
|
667
|
+
// it (skipping the leading `simple_identifier` name).
|
|
668
|
+
let sawEq = false;
|
|
669
|
+
for (let i = 0; i < arg.childCount; i++) {
|
|
670
|
+
const c = arg.child(i);
|
|
671
|
+
if (!c)
|
|
672
|
+
continue;
|
|
673
|
+
if (!c.isNamed && c.type === '=') {
|
|
674
|
+
sawEq = true;
|
|
675
|
+
continue;
|
|
676
|
+
}
|
|
677
|
+
if (sawEq && c.isNamed && !COMMENT_TYPES.has(c.type))
|
|
678
|
+
return c;
|
|
679
|
+
}
|
|
680
|
+
// Positional arg — the first non-comment named child.
|
|
681
|
+
for (let i = 0; i < arg.namedChildCount; i++) {
|
|
682
|
+
const c = arg.namedChild(i);
|
|
683
|
+
if (c && c.type !== 'annotation' && !COMMENT_TYPES.has(c.type))
|
|
684
|
+
return c;
|
|
685
|
+
}
|
|
686
|
+
return undefined;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* `navigation_expression` chain walk shared by value position and callee
|
|
690
|
+
* position. Records the chain-root identifier as a use (identical to the old
|
|
691
|
+
* default descent) plus at most ONE member-read site — the INNERMOST access —
|
|
692
|
+
* when the root is an identifier; `skipFinalRead` suppresses it when that
|
|
693
|
+
* access is the callee (carried by the dotted path instead). Mirrors the Go /
|
|
694
|
+
* Python harvesters' `walkChain`.
|
|
695
|
+
*/
|
|
696
|
+
walkChain(node, acc, skipFinalRead) {
|
|
697
|
+
const accesses = [];
|
|
698
|
+
let cur = this.unwrapValue(node);
|
|
699
|
+
for (;;) {
|
|
700
|
+
if (cur.type === 'navigation_expression') {
|
|
701
|
+
const suffix = cur.namedChildren.find((c) => c.type === 'navigation_suffix');
|
|
702
|
+
const name = suffix?.namedChildren.find((c) => c.type === 'simple_identifier');
|
|
703
|
+
accesses.unshift(name?.text ?? '');
|
|
704
|
+
const operand = cur.namedChild(0);
|
|
705
|
+
if (!operand)
|
|
706
|
+
break;
|
|
707
|
+
cur = this.unwrapValue(operand);
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
break;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
// The shared terminal: root-use record + innermost member-read + path-join.
|
|
714
|
+
return finalizeChain(acc, cur, accesses, skipFinalRead, (t) => t === 'simple_identifier', {
|
|
715
|
+
resolve: (n) => this.resolve(n),
|
|
716
|
+
walkRoot: (n) => this.walkValue(n, acc),
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
}
|