gitnexus 1.6.9 → 1.6.10-aptos.0
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 +211 -53
- package/dist/_shared/graph/types.d.ts +67 -3
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/index.d.ts +1 -0
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.d.ts +3 -1
- package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.js +4 -3
- package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +2 -0
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/languages.d.ts +2 -0
- package/dist/_shared/languages.d.ts.map +1 -1
- package/dist/_shared/languages.js +2 -0
- package/dist/_shared/languages.js.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +2 -2
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +8 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/pipeline.d.ts +1 -1
- package/dist/_shared/pipeline.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/callable-flow-site.d.ts +110 -0
- package/dist/_shared/scope-resolution/callable-flow-site.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/callable-flow-site.js +11 -0
- package/dist/_shared/scope-resolution/callable-flow-site.js.map +1 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.d.ts +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.js +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.js +1 -0
- package/dist/_shared/scope-resolution/language-classification.js.map +1 -1
- package/dist/_shared/scope-resolution/parsed-file.d.ts +7 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts +9 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/types.d.ts +20 -3
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +1 -1
- package/dist/cli/ai-context.js +25 -44
- package/dist/cli/analyze.d.ts +5 -2
- package/dist/cli/analyze.js +197 -11
- package/dist/cli/clean.js +17 -3
- package/dist/cli/cli-message.d.ts +1 -1
- package/dist/cli/doctor.d.ts +18 -0
- package/dist/cli/doctor.js +96 -5
- package/dist/cli/editor-targets.d.ts +17 -2
- package/dist/cli/editor-targets.js +44 -0
- package/dist/cli/embeddings.d.ts +12 -0
- package/dist/cli/embeddings.js +49 -0
- package/dist/cli/eval-server.d.ts +23 -1
- package/dist/cli/eval-server.js +126 -8
- package/dist/cli/help-i18n.js +6 -0
- package/dist/cli/i18n/en.d.ts +18 -8
- package/dist/cli/i18n/en.js +18 -8
- package/dist/cli/i18n/resources.d.ts +28 -8
- package/dist/cli/i18n/zh-CN.d.ts +10 -0
- package/dist/cli/i18n/zh-CN.js +18 -8
- package/dist/cli/index.js +21 -7
- package/dist/cli/lazy-action.d.ts +7 -0
- package/dist/cli/lazy-action.js +27 -0
- package/dist/cli/mcp.js +6 -3
- package/dist/cli/move-availability.d.ts +5 -0
- package/dist/cli/move-availability.js +11 -0
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.js +230 -32
- package/dist/cli/skill-gen.js +38 -18
- package/dist/cli/standard-skills.d.ts +76 -0
- package/dist/cli/standard-skills.js +45 -0
- package/dist/cli/status.d.ts +4 -1
- package/dist/cli/status.js +57 -4
- package/dist/cli/tool.js +11 -0
- package/dist/cli/uninstall.js +77 -18
- package/dist/cli/wiki.d.ts +1 -0
- package/dist/cli/wiki.js +7 -1
- package/dist/config/ignore-service.d.ts +2 -0
- package/dist/config/ignore-service.js +27 -0
- package/dist/core/analysis-features.d.ts +21 -0
- package/dist/core/analysis-features.js +59 -0
- package/dist/core/analyzer-identity.d.ts +74 -0
- package/dist/core/analyzer-identity.js +1820 -0
- package/dist/core/augmentation/engine.js +13 -8
- package/dist/core/embeddings/embedder.d.ts +3 -2
- package/dist/core/embeddings/embedder.js +24 -7
- package/dist/core/embeddings/embedding-identity.d.ts +11 -0
- package/dist/core/embeddings/embedding-identity.js +24 -0
- package/dist/core/embeddings/embedding-pipeline.d.ts +36 -1
- package/dist/core/embeddings/embedding-pipeline.js +100 -9
- package/dist/core/embeddings/http-client.d.ts +33 -3
- package/dist/core/embeddings/http-client.js +237 -25
- package/dist/core/embeddings/node-module-compat.d.ts +25 -0
- package/dist/core/embeddings/node-module-compat.js +25 -0
- package/dist/core/embeddings/onnxruntime-common-resolver.js +8 -5
- package/dist/core/embeddings/onnxruntime-node-resolver.js +33 -7
- package/dist/core/embeddings/runtime-install.d.ts +119 -0
- package/dist/core/embeddings/runtime-install.js +372 -0
- package/dist/core/embeddings/runtime-support.d.ts +48 -17
- package/dist/core/embeddings/runtime-support.js +96 -0
- package/dist/core/git-staleness.js +1 -1
- package/dist/core/group/bridge-db.js +2 -0
- package/dist/core/group/extractors/http-patterns/python.js +246 -108
- package/dist/core/group/extractors/manifest-extractor.js +4 -0
- package/dist/core/incremental/escalation-gate.d.ts +38 -0
- package/dist/core/incremental/escalation-gate.js +48 -0
- package/dist/core/incremental/shadow-candidates.d.ts +3 -3
- package/dist/core/incremental/shadow-candidates.js +3 -3
- package/dist/core/incremental/subgraph-extract.d.ts +2 -2
- package/dist/core/incremental/subgraph-extract.js +2 -2
- package/dist/core/index-freshness.d.ts +5 -0
- package/dist/core/index-freshness.js +13 -0
- package/dist/core/ingestion/class-extractors/configs/jvm.js +29 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.js +1 -1
- package/dist/core/ingestion/cobol/jcl-processor.js +9 -8
- package/dist/core/ingestion/cobol-processor.js +27 -26
- package/dist/core/ingestion/community-processor.d.ts +51 -1
- package/dist/core/ingestion/community-processor.js +323 -64
- package/dist/core/ingestion/emit-references.js +7 -2
- package/dist/core/ingestion/filesystem-walker.js +4 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +3 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.js +7 -0
- package/dist/core/ingestion/frameworks/spring/bean-candidates.d.ts +30 -0
- package/dist/core/ingestion/frameworks/spring/bean-candidates.js +182 -0
- package/dist/core/ingestion/frameworks/spring/bean-catalog.d.ts +12 -0
- package/dist/core/ingestion/frameworks/spring/bean-catalog.js +26 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.d.ts +24 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.js +115 -0
- package/dist/core/ingestion/languages/c/captures.js +56 -0
- package/dist/core/ingestion/languages/c/query.js +17 -0
- package/dist/core/ingestion/languages/c/scope-resolver.js +6 -0
- package/dist/core/ingestion/languages/cobol/captures.js +93 -0
- package/dist/core/ingestion/languages/cobol/scope-resolver.js +7 -0
- package/dist/core/ingestion/languages/cpp/captures.js +365 -75
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +14 -0
- package/dist/core/ingestion/languages/csharp/captures.js +25 -0
- package/dist/core/ingestion/languages/dart/captures.js +90 -2
- package/dist/core/ingestion/languages/dart/extension-type-preprocess.d.ts +7 -0
- package/dist/core/ingestion/languages/dart/extension-type-preprocess.js +30 -0
- package/dist/core/ingestion/languages/dart.js +2 -0
- package/dist/core/ingestion/languages/go/captures.js +34 -0
- package/dist/core/ingestion/languages/index.d.ts +1 -0
- package/dist/core/ingestion/languages/index.js +2 -0
- package/dist/core/ingestion/languages/java/analysis-features.d.ts +3 -0
- package/dist/core/ingestion/languages/java/analysis-features.js +13 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +22 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.js +58 -0
- package/dist/core/ingestion/languages/java/captures.d.ts +4 -3
- package/dist/core/ingestion/languages/java/captures.js +193 -17
- package/dist/core/ingestion/languages/java/package-facts.d.ts +5 -0
- package/dist/core/ingestion/languages/java/package-facts.js +9 -0
- package/dist/core/ingestion/languages/java/package-siblings.d.ts +3 -16
- package/dist/core/ingestion/languages/java/package-siblings.js +8 -147
- package/dist/core/ingestion/languages/java/query.js +23 -0
- package/dist/core/ingestion/languages/java/scope-resolver.js +23 -0
- package/dist/core/ingestion/languages/java/spring-bean-metadata.d.ts +2 -0
- package/dist/core/ingestion/languages/java/spring-bean-metadata.js +8 -0
- package/dist/core/ingestion/languages/java/spring-config-bindings.d.ts +23 -0
- package/dist/core/ingestion/languages/java/spring-config-bindings.js +215 -0
- package/dist/core/ingestion/languages/java.js +3 -0
- package/dist/core/ingestion/languages/javascript/captures.js +16 -0
- package/dist/core/ingestion/languages/javascript/query.js +21 -0
- package/dist/core/ingestion/languages/jvm/package-facts.d.ts +35 -0
- package/dist/core/ingestion/languages/jvm/package-facts.js +40 -0
- package/dist/core/ingestion/languages/jvm/package-siblings.d.ts +14 -0
- package/dist/core/ingestion/languages/jvm/package-siblings.js +129 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +17 -3
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +42 -8
- package/dist/core/ingestion/languages/kotlin/captures.js +59 -0
- package/dist/core/ingestion/languages/kotlin/package-facts.d.ts +5 -0
- package/dist/core/ingestion/languages/kotlin/package-facts.js +9 -0
- package/dist/core/ingestion/languages/kotlin/package-siblings.d.ts +4 -0
- package/dist/core/ingestion/languages/kotlin/package-siblings.js +8 -0
- package/dist/core/ingestion/languages/kotlin/query.js +19 -0
- package/dist/core/ingestion/languages/kotlin/scope-resolver.js +9 -1
- package/dist/core/ingestion/languages/kotlin/spring-bean-metadata.d.ts +2 -0
- package/dist/core/ingestion/languages/kotlin/spring-bean-metadata.js +8 -0
- package/dist/core/ingestion/languages/kotlin.js +5 -6
- package/dist/core/ingestion/languages/move.d.ts +1 -0
- package/dist/core/ingestion/languages/move.js +27 -0
- package/dist/core/ingestion/languages/php/captures.js +40 -0
- package/dist/core/ingestion/languages/php/import-decomposer.js +12 -0
- package/dist/core/ingestion/languages/php/import-target.d.ts +2 -1
- package/dist/core/ingestion/languages/php/import-target.js +110 -2
- package/dist/core/ingestion/languages/php/interpret.js +10 -0
- package/dist/core/ingestion/languages/php/scope-resolver.js +1 -1
- package/dist/core/ingestion/languages/python/captures.d.ts +3 -4
- package/dist/core/ingestion/languages/python/captures.js +24 -5
- package/dist/core/ingestion/languages/python/interpret.js +4 -0
- package/dist/core/ingestion/languages/python/receiver-binding.d.ts +15 -2
- package/dist/core/ingestion/languages/python/receiver-binding.js +96 -2
- package/dist/core/ingestion/languages/python/simple-hooks.d.ts +5 -5
- package/dist/core/ingestion/languages/python/simple-hooks.js +15 -5
- package/dist/core/ingestion/languages/ruby/captures.js +42 -0
- package/dist/core/ingestion/languages/rust/captures.js +13 -0
- package/dist/core/ingestion/languages/rust/interpret.js +18 -0
- package/dist/core/ingestion/languages/rust/query.js +9 -0
- package/dist/core/ingestion/languages/rust/range-binding.js +6 -2
- package/dist/core/ingestion/languages/swift/captures.js +12 -0
- package/dist/core/ingestion/languages/typescript/captures.js +21 -0
- package/dist/core/ingestion/languages/typescript/nuxt-auto-imports.js +2 -1
- package/dist/core/ingestion/languages/typescript/query.js +37 -0
- package/dist/core/ingestion/markdown-processor.js +3 -2
- package/dist/core/ingestion/model/registration-table.js +1 -0
- package/dist/core/ingestion/parsing-processor.d.ts +3 -1
- package/dist/core/ingestion/parsing-processor.js +36 -1
- 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.js +56 -2
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +0 -2
- package/dist/core/ingestion/pipeline-phases/parse.js +12 -3
- package/dist/core/ingestion/pipeline-phases/processes.d.ts +8 -0
- package/dist/core/ingestion/pipeline-phases/processes.js +11 -1
- package/dist/core/ingestion/pipeline-phases/spring-config.d.ts +37 -0
- package/dist/core/ingestion/pipeline-phases/spring-config.js +433 -0
- package/dist/core/ingestion/pipeline-phases/standalone-ingest.d.ts +10 -0
- package/dist/core/ingestion/pipeline-phases/standalone-ingest.js +6 -0
- package/dist/core/ingestion/pipeline.d.ts +4 -2
- package/dist/core/ingestion/pipeline.js +5 -2
- package/dist/core/ingestion/resolve-references.js +12 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +83 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.js +131 -0
- package/dist/core/ingestion/route-extractors/python-const-resolver.d.ts +75 -0
- package/dist/core/ingestion/route-extractors/python-const-resolver.js +299 -0
- package/dist/core/ingestion/scope-extractor.js +306 -43
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +71 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.d.ts +7 -7
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +8 -7
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +3 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +6 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +1 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +4 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +7 -2
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +47 -0
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +1138 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +16 -4
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +97 -1
- package/dist/core/ingestion/scope-resolution/passes/property-dispatch.d.ts +60 -0
- package/dist/core/ingestion/scope-resolution/passes/property-dispatch.js +111 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +4 -3
- package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +5 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +25 -38
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +6 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +147 -35
- package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
- package/dist/core/ingestion/scope-resolution/scope/walkers.js +73 -44
- package/dist/core/ingestion/taint/typescript-model.js +34 -2
- package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
- package/dist/core/ingestion/tree-sitter-queries.js +23 -2
- package/dist/core/ingestion/type-extractors/jvm.js +17 -2
- package/dist/core/ingestion/utils/ast-helpers.d.ts +1 -0
- package/dist/core/ingestion/utils/ast-helpers.js +153 -2
- package/dist/core/ingestion/utils/callable-flow-captures.d.ts +94 -0
- package/dist/core/ingestion/utils/callable-flow-captures.js +878 -0
- package/dist/core/ingestion/utils/line-base.d.ts +20 -0
- package/dist/core/ingestion/utils/line-base.js +20 -0
- package/dist/core/ingestion/utils/symbol-labels.d.ts +21 -0
- package/dist/core/ingestion/utils/symbol-labels.js +45 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +34 -0
- package/dist/core/ingestion/workers/parse-worker.js +40 -5
- package/dist/core/ingestion/workers/result-merge.js +4 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +28 -0
- package/dist/core/ingestion/workers/worker-pool.js +128 -28
- package/dist/core/lbug/csv-generator.d.ts +15 -0
- package/dist/core/lbug/csv-generator.js +124 -27
- package/dist/core/lbug/cypher-escape.d.ts +20 -0
- package/dist/core/lbug/cypher-escape.js +20 -0
- package/dist/core/lbug/extension-load-error.d.ts +67 -0
- package/dist/core/lbug/extension-load-error.js +326 -0
- package/dist/core/lbug/extension-loader.d.ts +17 -2
- package/dist/core/lbug/extension-loader.js +38 -13
- package/dist/core/lbug/lbug-adapter.d.ts +203 -2
- package/dist/core/lbug/lbug-adapter.js +527 -86
- package/dist/core/lbug/lbug-config.d.ts +56 -2
- package/dist/core/lbug/lbug-config.js +267 -7
- package/dist/core/lbug/move-columns.d.ts +7 -0
- package/dist/core/lbug/move-columns.js +86 -0
- package/dist/core/lbug/native-check.d.ts +40 -0
- package/dist/core/lbug/native-check.js +90 -0
- package/dist/core/lbug/node-table-layout.d.ts +29 -0
- package/dist/core/lbug/node-table-layout.js +119 -0
- package/dist/core/lbug/pool-adapter.d.ts +23 -1
- package/dist/core/lbug/pool-adapter.js +115 -8
- package/dist/core/lbug/schema.d.ts +4 -3
- package/dist/core/lbug/schema.js +16 -16
- package/dist/core/lbug/sidecar-recovery.d.ts +172 -0
- package/dist/core/lbug/sidecar-recovery.js +418 -16
- package/dist/core/lbug/wal-checkpoint-driver.js +3 -0
- package/dist/core/move/artifact-download.d.ts +19 -0
- package/dist/core/move/artifact-download.js +179 -0
- package/dist/core/move/compiler-facts.d.ts +120 -0
- package/dist/core/move/compiler-facts.js +9 -0
- package/dist/core/move/consistency.d.ts +28 -0
- package/dist/core/move/consistency.js +98 -0
- package/dist/core/move/constants.d.ts +98 -0
- package/dist/core/move/constants.js +136 -0
- package/dist/core/move/discovery.d.ts +10 -0
- package/dist/core/move/discovery.js +22 -0
- package/dist/core/move/entry-points.d.ts +14 -0
- package/dist/core/move/entry-points.js +40 -0
- package/dist/core/move/facts-mapper.d.ts +75 -0
- package/dist/core/move/facts-mapper.js +534 -0
- package/dist/core/move/install-lock.d.ts +14 -0
- package/dist/core/move/install-lock.js +102 -0
- package/dist/core/move/install.d.ts +39 -0
- package/dist/core/move/install.js +391 -0
- package/dist/core/move/mcp-client.d.ts +115 -0
- package/dist/core/move/mcp-client.js +436 -0
- package/dist/core/move/move-ingest.d.ts +49 -0
- package/dist/core/move/move-ingest.js +320 -0
- package/dist/core/move/provision.d.ts +19 -0
- package/dist/core/move/provision.js +91 -0
- package/dist/core/move/release.d.ts +6 -0
- package/dist/core/move/release.js +10 -0
- package/dist/core/move/symbol-id.d.ts +35 -0
- package/dist/core/move/symbol-id.js +65 -0
- package/dist/core/move/type-parser.d.ts +11 -0
- package/dist/core/move/type-parser.js +38 -0
- package/dist/core/platform/capabilities.d.ts +0 -1
- package/dist/core/platform/capabilities.js +39 -8
- package/dist/core/run-analyze.d.ts +3 -3
- package/dist/core/run-analyze.js +1001 -184
- package/dist/core/search/fts-indexes.d.ts +31 -0
- package/dist/core/search/fts-indexes.js +73 -0
- package/dist/core/search/fts-schema.js +2 -0
- package/dist/core/tree-sitter/safe-parse.d.ts +8 -3
- package/dist/core/tree-sitter/safe-parse.js +21 -7
- package/dist/core/wiki/graph-queries.js +6 -5
- package/dist/core/wiki/llm-client.d.ts +8 -2
- package/dist/core/wiki/llm-client.js +41 -5
- package/dist/mcp/core/embedder.js +16 -2
- package/dist/mcp/http-transport.d.ts +5 -0
- package/dist/mcp/http-transport.js +19 -5
- package/dist/mcp/local/bean-metadata.d.ts +2 -0
- package/dist/mcp/local/bean-metadata.js +25 -0
- package/dist/mcp/local/line-display.d.ts +22 -0
- package/dist/mcp/local/line-display.js +3 -0
- package/dist/mcp/local/local-backend.d.ts +19 -1
- package/dist/mcp/local/local-backend.js +402 -155
- package/dist/mcp/local/pdg-impact.d.ts +5 -3
- package/dist/mcp/local/pdg-impact.js +5 -2
- package/dist/mcp/output-budget.d.ts +5 -0
- package/dist/mcp/output-budget.js +52 -0
- package/dist/mcp/read-only-policy.d.ts +12 -0
- package/dist/mcp/read-only-policy.js +102 -0
- package/dist/mcp/repository-policy.d.ts +34 -0
- package/dist/mcp/repository-policy.js +328 -0
- package/dist/mcp/resources.js +32 -5
- package/dist/mcp/server.d.ts +5 -2
- package/dist/mcp/server.js +29 -9
- package/dist/mcp/tools.d.ts +0 -8
- package/dist/mcp/tools.js +102 -5
- package/dist/server/analyze-job.d.ts +3 -0
- package/dist/server/analyze-job.js +17 -0
- package/dist/server/analyze-launch.d.ts +6 -0
- package/dist/server/analyze-launch.js +82 -6
- package/dist/server/analyze-worker-core.d.ts +2 -1
- package/dist/server/analyze-worker-core.js +5 -2
- package/dist/server/analyze-worker.js +29 -6
- package/dist/server/api.d.ts +30 -0
- package/dist/server/api.js +120 -34
- package/dist/server/mcp-http.d.ts +1 -1
- package/dist/server/mcp-http.js +4 -2
- package/dist/server/upload-ingest.js +2 -1
- package/dist/server/validation.js +2 -1
- package/dist/storage/git.d.ts +31 -0
- package/dist/storage/git.js +111 -1
- package/dist/storage/parse-cache.js +7 -1
- package/dist/storage/parsedfile-store.d.ts +8 -0
- package/dist/storage/parsedfile-store.js +165 -1
- package/dist/storage/repo-manager.d.ts +194 -2
- package/dist/storage/repo-manager.js +56 -1
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +50 -3
- package/hooks/claude/gitnexus-hook.cjs +59 -9
- package/hooks/claude/pre-tool-use.sh +0 -0
- package/hooks/claude/session-start.sh +0 -0
- package/package.json +21 -15
- package/scripts/cross-platform-tests.ts +56 -0
- package/scripts/ensure-fts.ts +43 -0
- package/scripts/install-duckdb-extension.mjs +85 -24
- package/scripts/run-cross-platform.ts +61 -6
- package/scripts/shard-arg.ts +30 -0
- package/scripts/sync-plugin-manifests.mjs +192 -0
- package/skills/gitnexus-lfg/README.md +55 -0
- package/skills/gitnexus-lfg/SKILL.md +86 -0
- package/skills/gitnexus-plan/README.md +142 -0
- package/skills/gitnexus-plan/SKILL.md +348 -0
- package/skills/gitnexus-plan/references/context-ledger.md +137 -0
- package/skills/gitnexus-plan/references/context-pack.md +126 -0
- package/skills/gitnexus-plan/references/evidence-provenance.md +272 -0
- package/skills/gitnexus-plan/references/pdg-slice.md +109 -0
- package/skills/gitnexus-plan/references/plan-template.md +201 -0
- package/skills/gitnexus-plan/scripts/evidence-provenance.mjs +2084 -0
- package/skills/gitnexus-review/SKILL.md +273 -0
- package/skills/gitnexus-review/ci-personas/ci-adversarial-lens.md +42 -0
- package/skills/gitnexus-review/ci-personas/ci-blast-radius-lens.md +39 -0
- package/skills/gitnexus-review/ci-personas/ci-correctness-lens.md +37 -0
- package/skills/gitnexus-review/ci-personas/ci-coverage-lens.md +40 -0
- package/skills/gitnexus-review/ci-personas/ci-critic-lens.md +42 -0
- package/skills/gitnexus-review/ci-personas/ci-security-lens.md +39 -0
- package/skills/gitnexus-work/README.md +71 -0
- package/skills/gitnexus-work/SKILL.md +269 -0
- package/skills/gitnexus-work/references/evidence-provenance.md +272 -0
- package/skills/gitnexus-work/scripts/evidence-provenance.mjs +2084 -0
- package/web/assets/ProcessFlowModal-B_bfBySy.js +22 -0
- package/web/assets/__vite-browser-external-bMKyYQkO.js +1 -0
- package/web/assets/agent-Bqxn-abU.js +626 -0
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-BVWFvYz2.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-CmG3uPWf.js +36 -0
- package/web/assets/{blockDiagram-7IZFK4PR-BkWhpzWB.js → blockDiagram-7IZFK4PR-DBefcjof.js} +7 -7
- package/web/assets/{c4Diagram-Y2BXMSZH-DtBvpzWD.js → c4Diagram-Y2BXMSZH-EjWnjEJl.js} +6 -6
- package/web/assets/chunk-2T2R6R2M-Bb6Sy3_j.js +4 -0
- package/web/assets/chunk-2UTLFMKG-CXlhF3Pt.js +1 -0
- package/web/assets/chunk-3SSMPTDK-rPsRM1x0.js +321 -0
- package/web/assets/chunk-4R4BOZG6-Be_F0JoX.js +159 -0
- package/web/assets/{chunk-6764PJDD-DpIS7hxD.js → chunk-6764PJDD-C7xxk063.js} +1 -1
- package/web/assets/chunk-67TQ5CYL-CA7OhIEf.js +124 -0
- package/web/assets/chunk-7FYTHRHK-CsmYIswB.js +32 -0
- package/web/assets/chunk-7J6CGLKN-BlKwgXKs.js +10 -0
- package/web/assets/chunk-7W6UQGC5-pyKGssV3.js +1 -0
- package/web/assets/chunk-C62D2QBJ-3gdL8EKc.js +1 -0
- package/web/assets/chunk-CEXFNPSA-CjwtMDkc.js +1 -0
- package/web/assets/{chunk-INKRHTLW-Nu4ri9P-.js → chunk-INKRHTLW-Ckl3_KkO.js} +13 -13
- package/web/assets/chunk-J5EP6P6S-L19oz55R.js +1 -0
- package/web/assets/{chunk-KGFNY3KK-JGMJvKCK.js → chunk-KGFNY3KK-BZeP-55u.js} +17 -17
- package/web/assets/chunk-KGYTTC2M-zm6n242I.js +1 -0
- package/web/assets/{chunk-KRXBNO2N-BW5o0KUN.js → chunk-KRXBNO2N-C-UNuKKf.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-CfLLCywY.js → chunk-LCXTWHL2-C162wE5z.js} +5 -5
- package/web/assets/chunk-LII3EMHJ-BL6lKJ_P.js +1 -0
- package/web/assets/chunk-LRIF4GLE-n59lhprL.js +1 -0
- package/web/assets/chunk-QA3QBVWF-DVXPOIxe.js +2 -0
- package/web/assets/chunk-RERM46MO-B5dAdWpP.js +1 -0
- package/web/assets/chunk-RG4AUYOV-ZNgyLFq6.js +206 -0
- package/web/assets/chunk-RKZBBQEN-MyIQbGgD.js +1 -0
- package/web/assets/chunk-RLI5ZMPA-CkXZ0y0U.js +1 -0
- package/web/assets/chunk-T2UQINTJ-BEyXhZWe.js +1 -0
- package/web/assets/chunk-UP6H54XL-BG-n7qDp.js +1 -0
- package/web/assets/chunk-UXSXWOXI-CW1_r5cS.js +1 -0
- package/web/assets/chunk-UY5QBCOK-ByqTVLvh.js +1 -0
- package/web/assets/chunk-VU6ZFW4Y-BLeasdkU.js +2 -0
- package/web/assets/{chunk-W44A43WB-JqMLIpR0.js → chunk-W44A43WB-BN8EQc_u.js} +1 -1
- package/web/assets/chunk-ZXARS5L4-C3v-4Fsw.js +1 -0
- package/web/assets/classDiagram-KGZ6W3CR-olpO3fMe.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-olpO3fMe.js +1 -0
- package/web/assets/cose-bilkent-UX7MHV2Q-BmnZ7Mvj.js +1 -0
- package/web/assets/dagre-ND4H6XIP-CY4iIF7v.js +4 -0
- package/web/assets/diagram-3NCE3AQN-CO6QpzEE.js +43 -0
- package/web/assets/diagram-GF46GFSD-B2atbzmU.js +24 -0
- package/web/assets/diagram-HNR7UZ2L-DVRltWbL.js +3 -0
- package/web/assets/diagram-QXG6HAR7-DR6AHD2h.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-DkpoMwTL.js +10 -0
- package/web/assets/erDiagram-L5TCEMPS-n8g_90bc.js +85 -0
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-CgFBM7e-.js +1 -0
- package/web/assets/flowDiagram-H6V6AXG4-SGMDiCkB.js +162 -0
- package/web/assets/ganttDiagram-JCBTUEKG-Cb3UBqRS.js +292 -0
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DCJv7SII.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-Bs9CR7tq.js +106 -0
- package/web/assets/index-CX_fADmQ.css +2 -0
- package/web/assets/index-D1Z3dGGz.js +575 -0
- package/web/assets/info-J43DQDTF-KCYPFFUO-BfNy-9Nd.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-T368on4D.js +2 -0
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-DfYpxnE5.js → ishikawaDiagram-BNXS4ZKH-XpjJRU9h.js} +6 -6
- package/web/assets/journeyDiagram-M6C3CM3L-C6wjooas.js +139 -0
- package/web/assets/kanban-definition-75IXJCU3-5_UVY79g.js +89 -0
- package/web/assets/{katex-K3KEBU37-CTc5BslQ.js → katex-K3KEBU37-qRQBy-EZ.js} +2 -2
- package/web/assets/{mindmap-definition-2TDM6QVE-DypvbOMQ.js → mindmap-definition-2TDM6QVE-8xDLzk2e.js} +29 -29
- package/web/assets/node-Ct_zna8U.js +8 -0
- package/web/assets/packet-YPE3B663-LP52Z2RK-D4qkeG9k.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-B_yMKyQa.js +1 -0
- package/web/assets/pieDiagram-CU6KROY3-Bv4LpAbr.js +30 -0
- package/web/assets/preload-helper-Czpn1I53.js +1 -0
- package/web/assets/{quadrantDiagram-VICAPDV7-yXSZ2lLz.js → quadrantDiagram-VICAPDV7-DR54jOeR.js} +6 -6
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DeD6yN_0.js +1 -0
- package/web/assets/requirementDiagram-JXO7QTGE-PEkg7sKC.js +84 -0
- package/web/assets/rolldown-runtime-QTnfLwEv.js +1 -0
- package/web/assets/sankeyDiagram-URQDO5SZ-DDWEtjcs.js +40 -0
- package/web/assets/sdk-CzHHH8tD.js +37 -0
- package/web/assets/sequenceDiagram-VS2MUI6T-Bv-uwANx.js +162 -0
- package/web/assets/src-JV30wyV8.js +1 -0
- package/web/assets/stateDiagram-7D4R322I-DVNjmkEq.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-CyN4Fh7_.js +1 -0
- package/web/assets/timeline-definition-O6YCAMPW-Qmsuo7qS.js +120 -0
- package/web/assets/treeView-BLDUP644-QA4HXRO3-CDuSYnd4.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-imazucyJ.js +1 -0
- package/web/assets/vennDiagram-MWXL3ELB-BD1iK1SX.js +34 -0
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-DqrT9tB8.js +1 -0
- package/web/assets/wardleyDiagram-CUQ6CDDI-D6TzLVob.js +78 -0
- package/web/assets/{xychartDiagram-N2JHSOCM-BOLm0eNm.js → xychartDiagram-N2JHSOCM-CoZ_Tits.js} +6 -6
- package/web/index.html +18 -10
- package/skills/gitnexus-pr-review.md +0 -163
- package/web/assets/agent-Dli_x7bU.js +0 -660
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +0 -1
- package/web/assets/architectureDiagram-UL44E2DR-dEkqUZN9.js +0 -36
- package/web/assets/chunk-3SSMPTDK-B4_etUhr.js +0 -321
- package/web/assets/chunk-67TQ5CYL-4sNPJU1q.js +0 -124
- package/web/assets/chunk-7W6UQGC5-KyEG0HQg.js +0 -1
- package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +0 -161
- package/web/assets/chunk-LII3EMHJ-D-jm-dLa.js +0 -1
- package/web/assets/chunk-QA3QBVWF-BgRW3SXd.js +0 -2
- package/web/assets/chunk-RG4AUYOV-CqWzWsV3.js +0 -206
- package/web/assets/chunk-T2UQINTJ-DSBqkzH7.js +0 -1
- package/web/assets/chunk-UY5QBCOK-DyF0vyGd.js +0 -1
- package/web/assets/chunk-ZXARS5L4-CxN8oiwI.js +0 -1
- package/web/assets/classDiagram-KGZ6W3CR-CMne4tG9.js +0 -1
- package/web/assets/classDiagram-v2-72OJOZXJ-CMne4tG9.js +0 -1
- package/web/assets/cose-bilkent-UX7MHV2Q-D71wNYRJ.js +0 -1
- package/web/assets/dagre-ND4H6XIP-Co5rRx9X.js +0 -4
- package/web/assets/diagram-3NCE3AQN-DBp4O00j.js +0 -43
- package/web/assets/diagram-GF46GFSD-6N_8yS0i.js +0 -24
- package/web/assets/diagram-HNR7UZ2L-DFCfd5LI.js +0 -3
- package/web/assets/diagram-QXG6HAR7-Di093rFg.js +0 -24
- package/web/assets/diagram-WEQXMOUZ-DZWi4SUN.js +0 -10
- package/web/assets/erDiagram-L5TCEMPS-8X1y6R4Y.js +0 -85
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +0 -1
- package/web/assets/flowDiagram-H6V6AXG4-CMpY8Ufn.js +0 -162
- package/web/assets/ganttDiagram-JCBTUEKG-D3iL2Aet.js +0 -292
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +0 -1
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +0 -106
- package/web/assets/index-KctnI3Vq.js +0 -635
- package/web/assets/index-_lgn7hs5.css +0 -2
- package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +0 -1
- package/web/assets/infoDiagram-3YFTVSEB-BaLMZkUg.js +0 -2
- package/web/assets/journeyDiagram-M6C3CM3L-CvArszLo.js +0 -139
- package/web/assets/kanban-definition-75IXJCU3-CpfVLLf9.js +0 -89
- package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +0 -1
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +0 -1
- package/web/assets/pieDiagram-CU6KROY3-s27EFWgP.js +0 -30
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +0 -1
- package/web/assets/requirementDiagram-JXO7QTGE-CWhqInuf.js +0 -84
- package/web/assets/sankeyDiagram-URQDO5SZ-1qEjlFIB.js +0 -40
- package/web/assets/sequenceDiagram-VS2MUI6T-RyTlZ5cR.js +0 -162
- package/web/assets/stateDiagram-7D4R322I-DTjVfX4A.js +0 -1
- package/web/assets/stateDiagram-v2-36443NZ5-xY9_k9_Q.js +0 -1
- package/web/assets/timeline-definition-O6YCAMPW-DrrqLYAf.js +0 -120
- package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +0 -1
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +0 -1
- package/web/assets/vennDiagram-MWXL3ELB-B0RkWAim.js +0 -34
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +0 -1
- package/web/assets/wardleyDiagram-CUQ6CDDI-boUxiQ5F.js +0 -78
|
@@ -0,0 +1,878 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configurable AST-to-`@callable-flow.*` capture synthesis.
|
|
3
|
+
*
|
|
4
|
+
* The traversal is language-neutral: providers supply their grammar's node
|
|
5
|
+
* vocabulary and the small semantic callbacks (true-reference bindings,
|
|
6
|
+
* callable signatures, protocol invocation names). The central extractor
|
|
7
|
+
* never sees a parser node and shared ingestion code never branches on a
|
|
8
|
+
* language name.
|
|
9
|
+
*/
|
|
10
|
+
import { nodeToCapture, syntheticCapture } from './ast-helpers.js';
|
|
11
|
+
/**
|
|
12
|
+
* Emit normalized flow captures in deterministic source order.
|
|
13
|
+
*
|
|
14
|
+
* One explicit DFS supplies all phases below. Query-backed emitters may still
|
|
15
|
+
* perform their existing query walk; this helper never reparses and remains
|
|
16
|
+
* linear in AST size (the scope-capture benchmark guards the scaling ratio).
|
|
17
|
+
*/
|
|
18
|
+
export function synthesizeCallableFlowCaptures(root, options) {
|
|
19
|
+
const nodes = collectNodes(root);
|
|
20
|
+
const functions = collectFunctions(nodes, options);
|
|
21
|
+
const knownCallableNames = new Set(functions.map((fn) => fn.name));
|
|
22
|
+
const assignments = collectAssignments(nodes, options);
|
|
23
|
+
const valueBindings = buildValueBindingIndex(nodes, assignments, functions, options);
|
|
24
|
+
const out = [];
|
|
25
|
+
for (const assignment of assignments) {
|
|
26
|
+
emitAssignmentFact(assignment, knownCallableNames, valueBindings, options, out);
|
|
27
|
+
}
|
|
28
|
+
for (const fn of functions)
|
|
29
|
+
emitFormalFacts(fn, options, out);
|
|
30
|
+
for (const node of nodes) {
|
|
31
|
+
if (options.callNodeTypes.has(node.type) &&
|
|
32
|
+
(options.isCallNode === undefined || options.isCallNode(node))) {
|
|
33
|
+
emitCallFacts(node, knownCallableNames, valueBindings, options, out);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
out.sort((a, b) => compareCaptures(firstCapture(a), firstCapture(b)));
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
function collectNodes(root) {
|
|
40
|
+
const out = [];
|
|
41
|
+
const stack = [root];
|
|
42
|
+
while (stack.length > 0) {
|
|
43
|
+
const node = stack.pop();
|
|
44
|
+
out.push(node);
|
|
45
|
+
const children = node.namedChildren;
|
|
46
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
47
|
+
const child = children[i];
|
|
48
|
+
if (child !== null)
|
|
49
|
+
stack.push(child);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
function collectFunctions(nodes, options) {
|
|
55
|
+
const out = [];
|
|
56
|
+
for (const node of nodes) {
|
|
57
|
+
if (!options.functionNodeTypes.has(node.type))
|
|
58
|
+
continue;
|
|
59
|
+
const name = options.functionName?.(node) ?? defaultFunctionName(node, options);
|
|
60
|
+
if (name === undefined || name.length === 0)
|
|
61
|
+
continue;
|
|
62
|
+
out.push({ node, name, parameters: functionParameters(node, options) });
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
function defaultFunctionName(node, options) {
|
|
67
|
+
const direct = node.childForFieldName('name');
|
|
68
|
+
if (direct !== null) {
|
|
69
|
+
const id = terminalIdentifier(direct, options);
|
|
70
|
+
if (id !== undefined)
|
|
71
|
+
return id.text;
|
|
72
|
+
}
|
|
73
|
+
const declarator = node.childForFieldName('declarator');
|
|
74
|
+
if (declarator !== null) {
|
|
75
|
+
const id = bindingIdentifier(declarator, options);
|
|
76
|
+
if (id !== undefined)
|
|
77
|
+
return id.text;
|
|
78
|
+
}
|
|
79
|
+
const parent = node.parent;
|
|
80
|
+
if (parent !== null && options.bindingNodeTypes.has(parent.type)) {
|
|
81
|
+
const destination = assignmentParts(parent, options)[0]?.destination;
|
|
82
|
+
if (destination !== undefined)
|
|
83
|
+
return bindingIdentifier(destination, options)?.text;
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
function functionParameters(node, options) {
|
|
88
|
+
const providerParameters = options.extractFunctionParameters?.(node);
|
|
89
|
+
if (providerParameters !== undefined)
|
|
90
|
+
return providerParameters;
|
|
91
|
+
const explicit = node.childForFieldName('parameters') ??
|
|
92
|
+
node.childForFieldName('parameter') ??
|
|
93
|
+
findFirstDescendantOfTypes(node, options.parameterListNodeTypes);
|
|
94
|
+
if (explicit === null)
|
|
95
|
+
return [];
|
|
96
|
+
const direct = explicit.namedChildren.filter((child) => child !== null &&
|
|
97
|
+
(options.parameterNodeTypes.has(child.type) ||
|
|
98
|
+
(options.parameterListNodeTypes.has(explicit.type) &&
|
|
99
|
+
bindingIdentifier(child, options) !== undefined)));
|
|
100
|
+
return direct;
|
|
101
|
+
}
|
|
102
|
+
function collectAssignments(nodes, options) {
|
|
103
|
+
const out = [];
|
|
104
|
+
const seen = new Set();
|
|
105
|
+
for (const node of nodes) {
|
|
106
|
+
if (!options.bindingNodeTypes.has(node.type) && !options.assignmentNodeTypes.has(node.type)) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (seen.has(node.id))
|
|
110
|
+
continue;
|
|
111
|
+
const parts = assignmentParts(node, options);
|
|
112
|
+
if (parts.length === 0)
|
|
113
|
+
continue;
|
|
114
|
+
seen.add(node.id);
|
|
115
|
+
out.push(...parts);
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
function buildValueBindingIndex(nodes, assignments, functions, options) {
|
|
120
|
+
const assignmentRegionIdsByName = new Map();
|
|
121
|
+
const formalByOwner = new Map();
|
|
122
|
+
const signatureByNameAndRegion = new Map();
|
|
123
|
+
const add = (index, owner, name) => {
|
|
124
|
+
let names = index.get(owner);
|
|
125
|
+
if (names === undefined) {
|
|
126
|
+
names = new Set();
|
|
127
|
+
index.set(owner, names);
|
|
128
|
+
}
|
|
129
|
+
names.add(name);
|
|
130
|
+
};
|
|
131
|
+
for (const assignment of assignments) {
|
|
132
|
+
const destinationNames = new Set();
|
|
133
|
+
const destination = operandSyntax(assignment.destination, options, true);
|
|
134
|
+
if (destination !== undefined)
|
|
135
|
+
destinationNames.add(destination.name);
|
|
136
|
+
// Member-path destinations (`o->run = handler`) store into the MEMBER's
|
|
137
|
+
// name-cell — the seed fact is keyed on `run`, so the store must be
|
|
138
|
+
// visible under that name too or the member-call invoke gate never sees
|
|
139
|
+
// it (#2522 review, M3 ops-vtable pattern).
|
|
140
|
+
const terminal = terminalIdentifier(assignment.destination, options);
|
|
141
|
+
if (terminal !== undefined)
|
|
142
|
+
destinationNames.add(terminal.text);
|
|
143
|
+
for (const name of destinationNames) {
|
|
144
|
+
const region = nearestLexicalRegion(assignment.container, options);
|
|
145
|
+
let regionIds = assignmentRegionIdsByName.get(name);
|
|
146
|
+
if (regionIds === undefined) {
|
|
147
|
+
regionIds = new Set();
|
|
148
|
+
assignmentRegionIdsByName.set(name, regionIds);
|
|
149
|
+
}
|
|
150
|
+
regionIds.add(region.id);
|
|
151
|
+
if (options.functionScopedValueBindings === true) {
|
|
152
|
+
const functionOwner = nearestFunctionOwner(assignment.container, options);
|
|
153
|
+
if (functionOwner !== undefined)
|
|
154
|
+
regionIds.add(functionOwner.id);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
for (const fn of functions) {
|
|
159
|
+
for (const parameter of fn.parameters) {
|
|
160
|
+
const binding = bindingIdentifier(parameter, options);
|
|
161
|
+
if (binding !== undefined)
|
|
162
|
+
add(formalByOwner, fn.node.id, binding.text);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
for (const node of nodes) {
|
|
166
|
+
if (options.callableSignatureDeclarationNodeTypes?.has(node.type) !== true)
|
|
167
|
+
continue;
|
|
168
|
+
const binding = bindingIdentifier(node, options);
|
|
169
|
+
const signature = options.expectedSignature?.(node, node);
|
|
170
|
+
if (binding === undefined || signature === undefined)
|
|
171
|
+
continue;
|
|
172
|
+
// Only callable-typed VARIABLE declarations (`void (*fp)(int);`) create
|
|
173
|
+
// value cells — a plain function/method prototype (`void f(int);`)
|
|
174
|
+
// declares a callee, not a value. A variable declarator interposes a
|
|
175
|
+
// pointer/parenthesized declarator between the declaration and its
|
|
176
|
+
// identifier; a prototype's identifier hangs directly off the function
|
|
177
|
+
// declarator. Indexing prototypes here turned every call to a declared
|
|
178
|
+
// function into an indirect invoke — and, with
|
|
179
|
+
// `emitCanonicalInvokeReference`, minted a free-call reference that
|
|
180
|
+
// bypassed the precise passes' two-phase/ambiguity suppression
|
|
181
|
+
// (#2522 CI: eight cpp resolver tests gained a phantom edge).
|
|
182
|
+
if (!bindingInterposesValueDeclarator(node, binding))
|
|
183
|
+
continue;
|
|
184
|
+
const region = nearestLexicalRegion(node, options);
|
|
185
|
+
let byRegion = signatureByNameAndRegion.get(binding.text);
|
|
186
|
+
if (byRegion === undefined) {
|
|
187
|
+
byRegion = new Map();
|
|
188
|
+
signatureByNameAndRegion.set(binding.text, byRegion);
|
|
189
|
+
}
|
|
190
|
+
byRegion.set(region.id, signature);
|
|
191
|
+
if (options.functionScopedValueBindings === true) {
|
|
192
|
+
const functionOwner = nearestFunctionOwner(node, options);
|
|
193
|
+
if (functionOwner !== undefined)
|
|
194
|
+
byRegion.set(functionOwner.id, signature);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return { assignmentRegionIdsByName, formalByOwner, signatureByNameAndRegion };
|
|
198
|
+
}
|
|
199
|
+
/** True when a pointer/parenthesized declarator sits between the declaration
|
|
200
|
+
* and its binding identifier — the shape of a callable-typed variable, never
|
|
201
|
+
* of a plain prototype. Only C/C++ supply signature-declaration node types,
|
|
202
|
+
* so the type-name sniff stays scoped to those grammars. */
|
|
203
|
+
function bindingInterposesValueDeclarator(declaration, binding) {
|
|
204
|
+
let node = binding.parent;
|
|
205
|
+
while (node !== null && node.id !== declaration.id) {
|
|
206
|
+
if (node.type.includes('pointer') || node.type.includes('parenthesized'))
|
|
207
|
+
return true;
|
|
208
|
+
node = node.parent;
|
|
209
|
+
}
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
function nearestFunctionOwner(input, options) {
|
|
213
|
+
const providerOwner = options.lexicalFunctionOwner?.(input);
|
|
214
|
+
if (providerOwner !== undefined)
|
|
215
|
+
return providerOwner;
|
|
216
|
+
let node = input;
|
|
217
|
+
while (node !== null) {
|
|
218
|
+
if (options.functionNodeTypes.has(node.type))
|
|
219
|
+
return node;
|
|
220
|
+
node = node.parent;
|
|
221
|
+
}
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
function nearestLexicalRegion(input, options) {
|
|
225
|
+
const providerOwner = options.lexicalFunctionOwner?.(input);
|
|
226
|
+
let node = input.parent;
|
|
227
|
+
let outermost = input;
|
|
228
|
+
while (node !== null) {
|
|
229
|
+
outermost = node;
|
|
230
|
+
if (providerOwner !== undefined && node.id === providerOwner.id)
|
|
231
|
+
return node;
|
|
232
|
+
if (options.functionNodeTypes.has(node.type) || isLexicalRegionNode(node))
|
|
233
|
+
return node;
|
|
234
|
+
node = node.parent;
|
|
235
|
+
}
|
|
236
|
+
return providerOwner ?? outermost;
|
|
237
|
+
}
|
|
238
|
+
function isLexicalRegionNode(node) {
|
|
239
|
+
return /(?:^|_)(?:block|body|compound_statement|source_file|program|module|script)(?:$|_)/.test(node.type);
|
|
240
|
+
}
|
|
241
|
+
function isVisibleValueBinding(input, name, bindings, options) {
|
|
242
|
+
const assignmentRegionIds = bindings.assignmentRegionIdsByName.get(name);
|
|
243
|
+
const providerOwner = options.lexicalFunctionOwner?.(input);
|
|
244
|
+
if (providerOwner !== undefined &&
|
|
245
|
+
(assignmentRegionIds?.has(providerOwner.id) === true ||
|
|
246
|
+
bindings.formalByOwner.get(providerOwner.id)?.has(name) === true)) {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
let node = input;
|
|
250
|
+
while (node !== null) {
|
|
251
|
+
if (assignmentRegionIds?.has(node.id) === true)
|
|
252
|
+
return true;
|
|
253
|
+
if (options.functionNodeTypes.has(node.type) &&
|
|
254
|
+
bindings.formalByOwner.get(node.id)?.has(name) === true) {
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
node = node.parent;
|
|
258
|
+
}
|
|
259
|
+
if (bindings.formalByOwner.get(undefined)?.has(name) === true)
|
|
260
|
+
return true;
|
|
261
|
+
// A declared callable-typed binding (file-scope `void (*fp)(int);`) is a
|
|
262
|
+
// value binding wherever its declaration is visible — its assignments may
|
|
263
|
+
// live in OTHER functions (the init/register callback pattern), so
|
|
264
|
+
// assignment regions alone under-approximate visibility and the cross-
|
|
265
|
+
// function call emitted no invoke fact at all (#2522 review, H1).
|
|
266
|
+
return visibleCallableSignature(input, name, bindings, options) !== undefined;
|
|
267
|
+
}
|
|
268
|
+
function visibleCallableSignature(input, name, bindings, options) {
|
|
269
|
+
const byRegion = bindings.signatureByNameAndRegion.get(name);
|
|
270
|
+
if (byRegion === undefined)
|
|
271
|
+
return undefined;
|
|
272
|
+
const providerOwner = options.lexicalFunctionOwner?.(input);
|
|
273
|
+
if (providerOwner !== undefined) {
|
|
274
|
+
const signature = byRegion.get(providerOwner.id);
|
|
275
|
+
if (signature !== undefined)
|
|
276
|
+
return signature;
|
|
277
|
+
}
|
|
278
|
+
let node = input;
|
|
279
|
+
while (node !== null) {
|
|
280
|
+
const signature = byRegion.get(node.id);
|
|
281
|
+
if (signature !== undefined)
|
|
282
|
+
return signature;
|
|
283
|
+
node = node.parent;
|
|
284
|
+
}
|
|
285
|
+
return undefined;
|
|
286
|
+
}
|
|
287
|
+
function assignmentParts(node, options) {
|
|
288
|
+
const providerParts = options.extractAssignment?.(node);
|
|
289
|
+
if (providerParts !== undefined) {
|
|
290
|
+
const pairs = Array.isArray(providerParts) ? providerParts : [providerParts];
|
|
291
|
+
return pairs.map((pair) => ({ container: node, ...pair }));
|
|
292
|
+
}
|
|
293
|
+
const destination = node.childForFieldName('left') ??
|
|
294
|
+
node.childForFieldName('name') ??
|
|
295
|
+
node.childForFieldName('pattern') ??
|
|
296
|
+
node.childForFieldName('declarator') ??
|
|
297
|
+
node.childForFieldName('target'); // Swift assignment
|
|
298
|
+
const source = node.childForFieldName('right') ??
|
|
299
|
+
node.childForFieldName('value') ??
|
|
300
|
+
node.childForFieldName('initializer') ??
|
|
301
|
+
node.childForFieldName('default_value') ??
|
|
302
|
+
node.childForFieldName('result'); // Swift assignment
|
|
303
|
+
// Declaration wrappers often contain the real initialized declarator one
|
|
304
|
+
// level below (for example a declarator list).
|
|
305
|
+
if (destination === null || source === null) {
|
|
306
|
+
for (const child of node.namedChildren) {
|
|
307
|
+
if (child === null || child.id === node.id)
|
|
308
|
+
continue;
|
|
309
|
+
if (!options.bindingNodeTypes.has(child.type))
|
|
310
|
+
continue;
|
|
311
|
+
const nested = assignmentParts(child, options);
|
|
312
|
+
if (nested.length > 0)
|
|
313
|
+
return nested;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (destination === null || source === null)
|
|
317
|
+
return [];
|
|
318
|
+
return [{ container: node, destination, source }];
|
|
319
|
+
}
|
|
320
|
+
function emitAssignmentFact(assignment, knownCallableNames, valueBindings, options, out) {
|
|
321
|
+
const destination = operandSyntax(assignment.destination, options, options.bindingNodeTypes.has(assignment.container.type));
|
|
322
|
+
const source = operandSyntax(assignment.source, options);
|
|
323
|
+
if (destination === undefined || source === undefined)
|
|
324
|
+
return;
|
|
325
|
+
const signature = options.expectedSignature?.(assignment.container, assignment.destination) ??
|
|
326
|
+
visibleCallableSignature(assignment.container, destination.name, valueBindings, options);
|
|
327
|
+
const sourceIsValueBinding = isVisibleValueBinding(assignment.source, source.name, valueBindings, options);
|
|
328
|
+
if (options.bareNamesAreCalls === true &&
|
|
329
|
+
source.directDesignator &&
|
|
330
|
+
!source.callableReference &&
|
|
331
|
+
!source.anonymousCallable &&
|
|
332
|
+
!sourceIsValueBinding) {
|
|
333
|
+
// The RHS is the produced value of a call, not a reference to the callee.
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const sourceIsKnownCallable = source.callableReference ||
|
|
337
|
+
source.anonymousCallable ||
|
|
338
|
+
(source.directDesignator &&
|
|
339
|
+
!sourceIsValueBinding &&
|
|
340
|
+
(knownCallableNames.has(source.name) ||
|
|
341
|
+
source.qualifiedName !== undefined ||
|
|
342
|
+
signature !== undefined));
|
|
343
|
+
const flowSource = sourceIsKnownCallable ? asCallableDesignator(source) : source;
|
|
344
|
+
// A call/constructor/composite result is not the function designator that
|
|
345
|
+
// appears inside it. This guard must precede the store path: otherwise
|
|
346
|
+
// `*slot = factory()` stores `factory` itself into `slot`.
|
|
347
|
+
if (!source.directDesignator &&
|
|
348
|
+
!sourceIsKnownCallable &&
|
|
349
|
+
source.indirection === 0 &&
|
|
350
|
+
!source.addressOf) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
if (destination.indirection > 0) {
|
|
354
|
+
out.push(binaryFact('store', assignment.container, 'pointer', destination, 'source', flowSource));
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (source.addressOf && !sourceIsKnownCallable) {
|
|
358
|
+
// An address of a value binding creates an abstract-cell edge. Addresses
|
|
359
|
+
// of named callables are seeds instead (function designator semantics).
|
|
360
|
+
if (sourceIsValueBinding) {
|
|
361
|
+
out.push(binaryFact('address', assignment.container, 'destination', destination, 'source', source));
|
|
362
|
+
}
|
|
363
|
+
else if (source.directDesignator) {
|
|
364
|
+
// A declaration imported from another file is only visible after scope
|
|
365
|
+
// finalization. Preserve both interpretations here: the address relation
|
|
366
|
+
// supports pointer-to-pointer cells, while the copy lets the solver's
|
|
367
|
+
// exact lexical/import lookup recognize `auto fp = &importedTarget`.
|
|
368
|
+
out.push(binaryFact('address', assignment.container, 'destination', destination, 'source', source));
|
|
369
|
+
out.push(binaryFact('copy', assignment.container, 'destination', destination, 'source', source));
|
|
370
|
+
}
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (source.indirection > 0 && !sourceIsKnownCallable) {
|
|
374
|
+
out.push(binaryFact('load', assignment.container, 'destination', destination, 'pointer', source));
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (sourceIsKnownCallable) {
|
|
378
|
+
const match = {
|
|
379
|
+
'@callable-flow.seed': nodeToCapture('@callable-flow.seed', assignment.container),
|
|
380
|
+
'@callable-flow.destination': operandCapture('@callable-flow.destination', destination),
|
|
381
|
+
'@callable-flow.target': operandCapture('@callable-flow.target', flowSource),
|
|
382
|
+
'@callable-flow.target-name': syntheticCapture('@callable-flow.target-name', flowSource.node, flowSource.anonymousCallable ? destination.name : flowSource.name),
|
|
383
|
+
};
|
|
384
|
+
if (flowSource.qualifiedName !== undefined) {
|
|
385
|
+
match['@callable-flow.target-qualified-name'] = syntheticCapture('@callable-flow.target-qualified-name', flowSource.node, options.normalizeQualifiedName?.(flowSource.qualifiedName) ?? flowSource.qualifiedName);
|
|
386
|
+
}
|
|
387
|
+
addSignatureCaptures(match, assignment.container, signature);
|
|
388
|
+
out.push(match);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
const kind = options.isTrueReferenceBinding?.(assignment.container, assignment.destination)
|
|
392
|
+
? 'alias'
|
|
393
|
+
: 'copy';
|
|
394
|
+
out.push(binaryFact(kind, assignment.container, 'destination', destination, 'source', flowSource));
|
|
395
|
+
}
|
|
396
|
+
function emitFormalFacts(fn, options, out) {
|
|
397
|
+
for (let index = 0; index < fn.parameters.length; index++) {
|
|
398
|
+
const parameter = fn.parameters[index];
|
|
399
|
+
const binding = bindingIdentifier(parameter, options);
|
|
400
|
+
if (binding === undefined)
|
|
401
|
+
continue;
|
|
402
|
+
const mode = options.parameterPassingMode?.(parameter) ?? 'value';
|
|
403
|
+
const match = {
|
|
404
|
+
'@callable-flow.formal': nodeToCapture('@callable-flow.formal', fn.node),
|
|
405
|
+
'@callable-flow.owner': syntheticCapture('@callable-flow.owner', fn.node, fn.name),
|
|
406
|
+
'@callable-flow.binding': syntheticCapture('@callable-flow.binding', binding, binding.text),
|
|
407
|
+
'@callable-flow.parameter-index': syntheticCapture('@callable-flow.parameter-index', binding, String(index)),
|
|
408
|
+
'@callable-flow.passing-mode': syntheticCapture('@callable-flow.passing-mode', parameter, mode),
|
|
409
|
+
};
|
|
410
|
+
addSignatureCaptures(match, parameter, options.expectedSignature?.(parameter, parameter));
|
|
411
|
+
out.push(match);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
function emitCallFacts(call, knownCallableNames, valueBindings, options, out) {
|
|
415
|
+
const calleeNode = options.extractCallCallee?.(call) ??
|
|
416
|
+
call.childForFieldName('function') ??
|
|
417
|
+
call.childForFieldName('callee') ??
|
|
418
|
+
call.childForFieldName('name') ??
|
|
419
|
+
call.childForFieldName('method') ??
|
|
420
|
+
call.firstNamedChild;
|
|
421
|
+
if (calleeNode === null)
|
|
422
|
+
return;
|
|
423
|
+
const callSite = options.callSiteNode?.(call) ?? call;
|
|
424
|
+
const args = callArguments(call, options);
|
|
425
|
+
const member = directCallMemberParts(call, options) ?? memberParts(calleeNode, options);
|
|
426
|
+
const callee = operandSyntax(calleeNode, options);
|
|
427
|
+
const calleeIsValueBinding = callee !== undefined && isVisibleValueBinding(call, callee.name, valueBindings, options);
|
|
428
|
+
const directCalleeName = member === undefined &&
|
|
429
|
+
callee !== undefined &&
|
|
430
|
+
callee.indirection === 0 &&
|
|
431
|
+
!calleeIsValueBinding
|
|
432
|
+
? callee.name
|
|
433
|
+
: undefined;
|
|
434
|
+
for (let index = 0; index < args.length; index++) {
|
|
435
|
+
const rawSource = operandSyntax(args[index], options);
|
|
436
|
+
if (rawSource === undefined)
|
|
437
|
+
continue;
|
|
438
|
+
// A call/constructor/composite result is a produced value, not a reference
|
|
439
|
+
// to the terminal identifier inside the expression.
|
|
440
|
+
if (!rawSource.directDesignator && rawSource.indirection === 0 && !rawSource.addressOf) {
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
const sourceIsValueBinding = isVisibleValueBinding(args[index], rawSource.name, valueBindings, options);
|
|
444
|
+
if (options.bareNamesAreCalls === true &&
|
|
445
|
+
rawSource.directDesignator &&
|
|
446
|
+
!rawSource.callableReference &&
|
|
447
|
+
!rawSource.anonymousCallable &&
|
|
448
|
+
!sourceIsValueBinding) {
|
|
449
|
+
// Bare argument name = a call's produced value in this language.
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
const sourceIsKnownCallable = rawSource.callableReference ||
|
|
453
|
+
rawSource.anonymousCallable ||
|
|
454
|
+
(rawSource.directDesignator &&
|
|
455
|
+
!sourceIsValueBinding &&
|
|
456
|
+
(knownCallableNames.has(rawSource.name) || rawSource.qualifiedName !== undefined));
|
|
457
|
+
// Keep unresolved direct identifiers (not arbitrary expressions): imports
|
|
458
|
+
// and cross-file callable bindings are only known after registry finalize.
|
|
459
|
+
// The solver requires an exact callable lexical binding before propagating,
|
|
460
|
+
// so ordinary value arguments remain inert.
|
|
461
|
+
if (!sourceIsValueBinding &&
|
|
462
|
+
!sourceIsKnownCallable &&
|
|
463
|
+
!rawSource.directDesignator &&
|
|
464
|
+
!rawSource.addressOf) {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
const source = sourceIsKnownCallable ? asCallableDesignator(rawSource) : rawSource;
|
|
468
|
+
out.push({
|
|
469
|
+
'@callable-flow.argument': nodeToCapture('@callable-flow.argument', callSite),
|
|
470
|
+
'@callable-flow.source': operandCapture('@callable-flow.source', source),
|
|
471
|
+
...operandMetadataCaptures('source', source),
|
|
472
|
+
...(source.indirection > 0
|
|
473
|
+
? {
|
|
474
|
+
'@callable-flow.source-indirection': syntheticCapture('@callable-flow.source-indirection', source.node, String(source.indirection)),
|
|
475
|
+
}
|
|
476
|
+
: {}),
|
|
477
|
+
...(source.addressOf
|
|
478
|
+
? {
|
|
479
|
+
'@callable-flow.source-address': syntheticCapture('@callable-flow.source-address', source.node, 'true'),
|
|
480
|
+
}
|
|
481
|
+
: {}),
|
|
482
|
+
'@callable-flow.parameter-index': syntheticCapture('@callable-flow.parameter-index', args[index], String(index)),
|
|
483
|
+
...(directCalleeName !== undefined
|
|
484
|
+
? {
|
|
485
|
+
'@callable-flow.direct-callee-name': syntheticCapture('@callable-flow.direct-callee-name', callee.node, directCalleeName),
|
|
486
|
+
}
|
|
487
|
+
: {}),
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
if (member !== undefined) {
|
|
491
|
+
if (member.operator !== undefined &&
|
|
492
|
+
options.memberPointerOperators?.has(member.operator) === true) {
|
|
493
|
+
emitInvoke(callSite, member.member, 'member-pointer', args.length, out, options, member.receiver);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
if (options.callableProtocolMethods?.has(member.member.name) === true) {
|
|
497
|
+
emitInvoke(callSite, member.receiver, 'callable-object', args.length, out, options);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
// Field-stored callables (`o->run = handler; o->run(1)` — the C ops-vtable
|
|
501
|
+
// pattern): when a visible assignment wrote this member's name-cell, the
|
|
502
|
+
// member call is an indirect invoke through that cell (#2522 review, M3).
|
|
503
|
+
// Gated on the store so plain accessor calls (`map.get(x)`) stay inert;
|
|
504
|
+
// name-keyed field collapse matches the solver's store/load model.
|
|
505
|
+
// ponytail: same-region joins only — cross-function vtable installs need
|
|
506
|
+
// a field-sensitive cell model.
|
|
507
|
+
if (isVisibleValueBinding(call, member.member.name, valueBindings, options)) {
|
|
508
|
+
emitInvoke(callSite, member.member, 'indirect', args.length, out, options, member.receiver);
|
|
509
|
+
}
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (callee === undefined)
|
|
513
|
+
return;
|
|
514
|
+
if (callee.indirection > 0 || calleeIsValueBinding) {
|
|
515
|
+
const invokeCallee = !calleeIsValueBinding && knownCallableNames.has(callee.name)
|
|
516
|
+
? asCallableDesignator(callee)
|
|
517
|
+
: callee;
|
|
518
|
+
emitInvoke(callSite, invokeCallee, 'indirect', args.length, out, options);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
function emitInvoke(call, callee, invocationKind, arity, out, options, receiver) {
|
|
522
|
+
out.push({
|
|
523
|
+
'@callable-flow.invoke': nodeToCapture('@callable-flow.invoke', call),
|
|
524
|
+
'@callable-flow.callee': operandCapture('@callable-flow.callee', callee),
|
|
525
|
+
...operandMetadataCaptures('callee', callee),
|
|
526
|
+
...(callee.indirection > 0
|
|
527
|
+
? {
|
|
528
|
+
'@callable-flow.callee-indirection': syntheticCapture('@callable-flow.callee-indirection', callee.node, String(callee.indirection)),
|
|
529
|
+
}
|
|
530
|
+
: {}),
|
|
531
|
+
...(receiver !== undefined
|
|
532
|
+
? {
|
|
533
|
+
'@callable-flow.receiver': operandCapture('@callable-flow.receiver', receiver),
|
|
534
|
+
...operandMetadataCaptures('receiver', receiver),
|
|
535
|
+
}
|
|
536
|
+
: {}),
|
|
537
|
+
'@callable-flow.invocation-kind': syntheticCapture('@callable-flow.invocation-kind', call, invocationKind),
|
|
538
|
+
'@callable-flow.arity': syntheticCapture('@callable-flow.arity', call, String(arity)),
|
|
539
|
+
});
|
|
540
|
+
if (invocationKind === 'member-pointer' && receiver !== undefined) {
|
|
541
|
+
// Parenthesized member-pointer callees are not matched by the ordinary
|
|
542
|
+
// member-call query shape.
|
|
543
|
+
// Supply the same canonical callsite contract so the shared resolver can
|
|
544
|
+
// exact-join this fact instead of trusting an unanchored/stale side fact.
|
|
545
|
+
out.push({
|
|
546
|
+
'@reference.call.member': nodeToCapture('@reference.call.member', call),
|
|
547
|
+
'@reference.receiver': operandCapture('@reference.receiver', receiver),
|
|
548
|
+
'@reference.name': operandCapture('@reference.name', callee),
|
|
549
|
+
'@reference.arity': syntheticCapture('@reference.arity', call, String(arity)),
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
else if (options.emitCanonicalInvokeReference === true) {
|
|
553
|
+
out.push({
|
|
554
|
+
'@reference.call.free': nodeToCapture('@reference.call.free', call),
|
|
555
|
+
'@reference.name': operandCapture('@reference.name', callee),
|
|
556
|
+
'@reference.arity': syntheticCapture('@reference.arity', call, String(arity)),
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
function callArguments(call, options) {
|
|
561
|
+
const list = call.childForFieldName('arguments') ??
|
|
562
|
+
call.childForFieldName('argument') ??
|
|
563
|
+
call.namedChildren.find((child) => child !== null && options.parameterListNodeTypes.has(child.type)) ??
|
|
564
|
+
findFirstDescendantOfTypes(call, options.parameterListNodeTypes) ??
|
|
565
|
+
null;
|
|
566
|
+
if (list === null)
|
|
567
|
+
return [];
|
|
568
|
+
if (options.parameterListNodeTypes.has(list.type)) {
|
|
569
|
+
return list.namedChildren.filter((child) => child !== null && child.type !== 'comment');
|
|
570
|
+
}
|
|
571
|
+
return [list];
|
|
572
|
+
}
|
|
573
|
+
function directCallMemberParts(call, options) {
|
|
574
|
+
const receiverNode = call.childForFieldName('object') ?? call.childForFieldName('receiver');
|
|
575
|
+
const memberNode = call.childForFieldName('method') ?? call.childForFieldName('name');
|
|
576
|
+
if (receiverNode === null || memberNode === null)
|
|
577
|
+
return undefined;
|
|
578
|
+
const receiver = operandSyntax(receiverNode, options);
|
|
579
|
+
const member = operandSyntax(memberNode, options);
|
|
580
|
+
return receiver === undefined || member === undefined ? undefined : { receiver, member };
|
|
581
|
+
}
|
|
582
|
+
function memberParts(input, options) {
|
|
583
|
+
const providerParts = options.memberPointerParts?.(input);
|
|
584
|
+
if (providerParts !== undefined) {
|
|
585
|
+
const receiver = operandSyntax(providerParts.receiver, options);
|
|
586
|
+
const member = operandSyntax(providerParts.member, options);
|
|
587
|
+
if (receiver !== undefined && member !== undefined) {
|
|
588
|
+
return { receiver, member, operator: providerParts.operator };
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
let node = input;
|
|
592
|
+
for (let guard = 0; guard < 8; guard++) {
|
|
593
|
+
const wrapped = wrappedExpression(node);
|
|
594
|
+
if (wrapped === null)
|
|
595
|
+
break;
|
|
596
|
+
node = wrapped;
|
|
597
|
+
}
|
|
598
|
+
const receiverNode = node.childForFieldName('object') ??
|
|
599
|
+
node.childForFieldName('argument') ??
|
|
600
|
+
node.childForFieldName('receiver');
|
|
601
|
+
const memberNode = node.childForFieldName('property') ??
|
|
602
|
+
node.childForFieldName('field') ??
|
|
603
|
+
node.childForFieldName('method');
|
|
604
|
+
if (receiverNode === null || memberNode === null)
|
|
605
|
+
return undefined;
|
|
606
|
+
const receiver = operandSyntax(receiverNode, options);
|
|
607
|
+
const member = operandSyntax(memberNode, options);
|
|
608
|
+
if (receiver === undefined || member === undefined)
|
|
609
|
+
return undefined;
|
|
610
|
+
const operator = node.children.find((child) => options.memberPointerOperators?.has(child.type) === true ||
|
|
611
|
+
options.memberPointerOperators?.has(child.text) === true);
|
|
612
|
+
return { receiver, member, ...(operator !== undefined ? { operator: operator.text } : {}) };
|
|
613
|
+
}
|
|
614
|
+
function operandSyntax(input, options, declarationBinding = false) {
|
|
615
|
+
if (declarationBinding) {
|
|
616
|
+
const binding = bindingIdentifier(input, options);
|
|
617
|
+
if (binding === undefined)
|
|
618
|
+
return undefined;
|
|
619
|
+
return {
|
|
620
|
+
name: binding.text,
|
|
621
|
+
node: binding,
|
|
622
|
+
indirection: 0,
|
|
623
|
+
addressOf: false,
|
|
624
|
+
directDesignator: false,
|
|
625
|
+
callableReference: false,
|
|
626
|
+
anonymousCallable: false,
|
|
627
|
+
expressionKind: 'binding',
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
const providerReference = options.extractCallableReference?.(input);
|
|
631
|
+
if (providerReference !== undefined) {
|
|
632
|
+
return {
|
|
633
|
+
name: providerReference.name,
|
|
634
|
+
node: providerReference.anchor,
|
|
635
|
+
indirection: 0,
|
|
636
|
+
addressOf: false,
|
|
637
|
+
...(providerReference.qualifiedName !== undefined
|
|
638
|
+
? { qualifiedName: providerReference.qualifiedName }
|
|
639
|
+
: {}),
|
|
640
|
+
directDesignator: true,
|
|
641
|
+
callableReference: true,
|
|
642
|
+
anonymousCallable: false,
|
|
643
|
+
expressionKind: providerReference.qualifiedName === undefined ? 'callable-designator' : 'bound-member',
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
let node = input;
|
|
647
|
+
let indirection = 0;
|
|
648
|
+
let addressOf = false;
|
|
649
|
+
for (let guard = 0; guard < 16; guard++) {
|
|
650
|
+
if (options.functionNodeTypes.has(node.type)) {
|
|
651
|
+
return {
|
|
652
|
+
name: '<anonymous>',
|
|
653
|
+
node,
|
|
654
|
+
indirection,
|
|
655
|
+
addressOf,
|
|
656
|
+
directDesignator: true,
|
|
657
|
+
callableReference: true,
|
|
658
|
+
anonymousCallable: true,
|
|
659
|
+
expressionKind: 'anonymous-callable',
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
const operator = unaryOperator(node);
|
|
663
|
+
if (operator === '&')
|
|
664
|
+
addressOf = true;
|
|
665
|
+
if (operator === '*')
|
|
666
|
+
indirection++;
|
|
667
|
+
const wrapped = wrappedExpression(node);
|
|
668
|
+
if (wrapped === null)
|
|
669
|
+
break;
|
|
670
|
+
node = wrapped;
|
|
671
|
+
}
|
|
672
|
+
const id = terminalIdentifier(node, options);
|
|
673
|
+
if (id === undefined)
|
|
674
|
+
return undefined;
|
|
675
|
+
const isQualified = id.id !== node.id && hasMultipleIdentifierLeaves(node, options);
|
|
676
|
+
const singleNameText = node.text.trim().replace(/^[\$@]+/, '');
|
|
677
|
+
const valueProducingExpression = /call|invocation|creation|new_expression|composite_literal/.test(node.type);
|
|
678
|
+
return {
|
|
679
|
+
name: id.text,
|
|
680
|
+
node: id,
|
|
681
|
+
indirection,
|
|
682
|
+
addressOf,
|
|
683
|
+
...(isQualified ? { qualifiedName: node.text } : {}),
|
|
684
|
+
directDesignator: options.identifierNodeTypes.has(node.type) ||
|
|
685
|
+
(!isQualified && singleNameText === id.text) ||
|
|
686
|
+
(isQualified && !valueProducingExpression && !/[([{]/.test(node.text)),
|
|
687
|
+
callableReference: options.callableReferenceNodeTypes?.has(node.type) === true,
|
|
688
|
+
anonymousCallable: false,
|
|
689
|
+
expressionKind: isQualified
|
|
690
|
+
? 'bound-member'
|
|
691
|
+
: options.callableReferenceNodeTypes?.has(node.type) === true
|
|
692
|
+
? 'callable-designator'
|
|
693
|
+
: 'binding',
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
function asCallableDesignator(operand) {
|
|
697
|
+
if (operand.expressionKind !== 'binding')
|
|
698
|
+
return operand;
|
|
699
|
+
return { ...operand, expressionKind: 'callable-designator' };
|
|
700
|
+
}
|
|
701
|
+
function wrappedExpression(node) {
|
|
702
|
+
const field = node.childForFieldName('argument') ??
|
|
703
|
+
node.childForFieldName('expression') ??
|
|
704
|
+
node.childForFieldName('value');
|
|
705
|
+
if (field !== null && field.id !== node.id && node.namedChildCount === 1)
|
|
706
|
+
return field;
|
|
707
|
+
if (node.type.includes('parenthesized') ||
|
|
708
|
+
node.type.includes('reference_expression') ||
|
|
709
|
+
node.type.includes('pointer_expression') ||
|
|
710
|
+
node.type.includes('unary_expression') ||
|
|
711
|
+
node.type.includes('cast_expression')) {
|
|
712
|
+
return node.namedChild(node.namedChildCount - 1);
|
|
713
|
+
}
|
|
714
|
+
return null;
|
|
715
|
+
}
|
|
716
|
+
function unaryOperator(node) {
|
|
717
|
+
for (const child of node.children) {
|
|
718
|
+
if (child.text === '&' || child.text === '*')
|
|
719
|
+
return child.text;
|
|
720
|
+
}
|
|
721
|
+
const trimmed = node.text.trimStart();
|
|
722
|
+
if (trimmed.startsWith('&'))
|
|
723
|
+
return '&';
|
|
724
|
+
if (trimmed.startsWith('*'))
|
|
725
|
+
return '*';
|
|
726
|
+
return undefined;
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* For a subscript/index expression, the identifier of interest is always in
|
|
730
|
+
* the container operand, never the index: `tbl[i] = h` must bind the cell
|
|
731
|
+
* `tbl` (index-insensitive, Andersen-style), not the index variable `i` —
|
|
732
|
+
* seeding `i` both pollutes a same-named formal and misses the later
|
|
733
|
+
* `tbl[i]()` join (#2522 review). Field names cover the grammars that field
|
|
734
|
+
* their subscript nodes; others keep the generic traversal.
|
|
735
|
+
*/
|
|
736
|
+
function subscriptBase(node) {
|
|
737
|
+
if (node.childForFieldName('index') === null)
|
|
738
|
+
return null;
|
|
739
|
+
return (node.childForFieldName('argument') ?? // C/C++ subscript_expression
|
|
740
|
+
node.childForFieldName('object') ?? // JS/TS subscript_expression
|
|
741
|
+
node.childForFieldName('value') ?? // Python subscript
|
|
742
|
+
node.childForFieldName('operand') ?? // Go index_expression
|
|
743
|
+
node.childForFieldName('array') // Java array_access
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
function bindingIdentifier(node, options) {
|
|
747
|
+
if (options.identifierNodeTypes.has(node.type))
|
|
748
|
+
return node;
|
|
749
|
+
const base = subscriptBase(node);
|
|
750
|
+
if (base !== null)
|
|
751
|
+
return bindingIdentifier(base, options);
|
|
752
|
+
for (const fieldName of ['name', 'declarator', 'pattern', 'left']) {
|
|
753
|
+
const field = node.childForFieldName(fieldName);
|
|
754
|
+
if (field === null || field.id === node.id)
|
|
755
|
+
continue;
|
|
756
|
+
const found = bindingIdentifier(field, options);
|
|
757
|
+
if (found !== undefined)
|
|
758
|
+
return found;
|
|
759
|
+
}
|
|
760
|
+
for (const child of node.namedChildren) {
|
|
761
|
+
if (child === null)
|
|
762
|
+
continue;
|
|
763
|
+
const found = bindingIdentifier(child, options);
|
|
764
|
+
if (found !== undefined)
|
|
765
|
+
return found;
|
|
766
|
+
}
|
|
767
|
+
return undefined;
|
|
768
|
+
}
|
|
769
|
+
function terminalIdentifier(node, options) {
|
|
770
|
+
if (options.identifierNodeTypes.has(node.type))
|
|
771
|
+
return node;
|
|
772
|
+
const base = subscriptBase(node);
|
|
773
|
+
if (base !== null)
|
|
774
|
+
return terminalIdentifier(base, options);
|
|
775
|
+
for (const fieldName of ['name', 'property', 'field', 'method', 'declarator']) {
|
|
776
|
+
const field = node.childForFieldName(fieldName);
|
|
777
|
+
if (field === null || field.id === node.id)
|
|
778
|
+
continue;
|
|
779
|
+
const found = terminalIdentifier(field, options);
|
|
780
|
+
if (found !== undefined)
|
|
781
|
+
return found;
|
|
782
|
+
}
|
|
783
|
+
for (let i = node.namedChildCount - 1; i >= 0; i--) {
|
|
784
|
+
const child = node.namedChild(i);
|
|
785
|
+
if (child === null)
|
|
786
|
+
continue;
|
|
787
|
+
const found = terminalIdentifier(child, options);
|
|
788
|
+
if (found !== undefined)
|
|
789
|
+
return found;
|
|
790
|
+
}
|
|
791
|
+
return undefined;
|
|
792
|
+
}
|
|
793
|
+
function hasMultipleIdentifierLeaves(node, options) {
|
|
794
|
+
let count = 0;
|
|
795
|
+
const stack = [node];
|
|
796
|
+
while (stack.length > 0) {
|
|
797
|
+
const current = stack.pop();
|
|
798
|
+
if (options.identifierNodeTypes.has(current.type)) {
|
|
799
|
+
if (++count > 1)
|
|
800
|
+
return true;
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
for (const child of current.namedChildren)
|
|
804
|
+
if (child !== null)
|
|
805
|
+
stack.push(child);
|
|
806
|
+
}
|
|
807
|
+
return false;
|
|
808
|
+
}
|
|
809
|
+
function findFirstDescendantOfTypes(root, types) {
|
|
810
|
+
const stack = [...root.namedChildren].filter((child) => child !== null);
|
|
811
|
+
while (stack.length > 0) {
|
|
812
|
+
const node = stack.shift();
|
|
813
|
+
if (types.has(node.type))
|
|
814
|
+
return node;
|
|
815
|
+
for (const child of node.namedChildren)
|
|
816
|
+
if (child !== null)
|
|
817
|
+
stack.push(child);
|
|
818
|
+
}
|
|
819
|
+
return null;
|
|
820
|
+
}
|
|
821
|
+
function binaryFact(kind, anchor, leftRole, left, rightRole, right) {
|
|
822
|
+
return {
|
|
823
|
+
[`@callable-flow.${kind}`]: nodeToCapture(`@callable-flow.${kind}`, anchor),
|
|
824
|
+
[`@callable-flow.${leftRole}`]: operandCapture(`@callable-flow.${leftRole}`, left),
|
|
825
|
+
...operandMetadataCaptures(leftRole, left),
|
|
826
|
+
...(left.indirection > 0
|
|
827
|
+
? {
|
|
828
|
+
[`@callable-flow.${leftRole}-indirection`]: syntheticCapture(`@callable-flow.${leftRole}-indirection`, left.node, String(left.indirection)),
|
|
829
|
+
}
|
|
830
|
+
: {}),
|
|
831
|
+
[`@callable-flow.${rightRole}`]: operandCapture(`@callable-flow.${rightRole}`, right),
|
|
832
|
+
...operandMetadataCaptures(rightRole, right),
|
|
833
|
+
...(right.indirection > 0
|
|
834
|
+
? {
|
|
835
|
+
[`@callable-flow.${rightRole}-indirection`]: syntheticCapture(`@callable-flow.${rightRole}-indirection`, right.node, String(right.indirection)),
|
|
836
|
+
}
|
|
837
|
+
: {}),
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
function operandCapture(name, operand) {
|
|
841
|
+
return syntheticCapture(name, operand.node, operand.name);
|
|
842
|
+
}
|
|
843
|
+
function operandMetadataCaptures(role, operand) {
|
|
844
|
+
return {
|
|
845
|
+
[`@callable-flow.${role}-kind`]: syntheticCapture(`@callable-flow.${role}-kind`, operand.node, operand.expressionKind),
|
|
846
|
+
...(operand.qualifiedName !== undefined
|
|
847
|
+
? {
|
|
848
|
+
[`@callable-flow.${role}-qualified-name`]: syntheticCapture(`@callable-flow.${role}-qualified-name`, operand.node, operand.qualifiedName),
|
|
849
|
+
}
|
|
850
|
+
: {}),
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function addSignatureCaptures(match, anchor, signature) {
|
|
854
|
+
if (signature?.parameterCount !== undefined) {
|
|
855
|
+
match['@callable-flow.expected-arity'] = syntheticCapture('@callable-flow.expected-arity', anchor, String(signature.parameterCount));
|
|
856
|
+
}
|
|
857
|
+
if (signature?.parameterTypes !== undefined) {
|
|
858
|
+
match['@callable-flow.expected-types'] = syntheticCapture('@callable-flow.expected-types', anchor, JSON.stringify(signature.parameterTypes));
|
|
859
|
+
}
|
|
860
|
+
if (signature?.parameterTypeClasses !== undefined) {
|
|
861
|
+
match['@callable-flow.expected-type-classes'] = syntheticCapture('@callable-flow.expected-type-classes', anchor, JSON.stringify(signature.parameterTypeClasses));
|
|
862
|
+
}
|
|
863
|
+
if (signature?.isConst !== undefined) {
|
|
864
|
+
match['@callable-flow.expected-const'] = syntheticCapture('@callable-flow.expected-const', anchor, String(signature.isConst));
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
function firstCapture(match) {
|
|
868
|
+
return Object.values(match)[0];
|
|
869
|
+
}
|
|
870
|
+
function compareCaptures(a, b) {
|
|
871
|
+
if (a === undefined)
|
|
872
|
+
return b === undefined ? 0 : 1;
|
|
873
|
+
if (b === undefined)
|
|
874
|
+
return -1;
|
|
875
|
+
return (a.range.startLine - b.range.startLine ||
|
|
876
|
+
a.range.startCol - b.range.startCol ||
|
|
877
|
+
a.name.localeCompare(b.name));
|
|
878
|
+
}
|