trail-code 0.0.0-stage → 0.28.0-semantic.3
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/LICENSE +21 -0
- package/README.md +567 -2
- package/dist/ai/crux.d.ts +88 -0
- package/dist/ai/crux.d.ts.map +1 -0
- package/dist/ai/crux.js +219 -0
- package/dist/ai/crux.js.map +1 -0
- package/dist/ai/failure.d.ts +60 -0
- package/dist/ai/failure.d.ts.map +1 -0
- package/dist/ai/failure.js +86 -0
- package/dist/ai/failure.js.map +1 -0
- package/dist/ai/llm/anthropic.d.ts +37 -0
- package/dist/ai/llm/anthropic.d.ts.map +1 -0
- package/dist/ai/llm/anthropic.js +144 -0
- package/dist/ai/llm/anthropic.js.map +1 -0
- package/dist/ai/llm/factory.d.ts +28 -0
- package/dist/ai/llm/factory.d.ts.map +1 -0
- package/dist/ai/llm/factory.js +36 -0
- package/dist/ai/llm/factory.js.map +1 -0
- package/dist/ai/llm/litellm.d.ts +34 -0
- package/dist/ai/llm/litellm.d.ts.map +1 -0
- package/dist/ai/llm/litellm.js +45 -0
- package/dist/ai/llm/litellm.js.map +1 -0
- package/dist/ai/llm/openai.d.ts +145 -0
- package/dist/ai/llm/openai.d.ts.map +1 -0
- package/dist/ai/llm/openai.js +629 -0
- package/dist/ai/llm/openai.js.map +1 -0
- package/dist/ai/llm/orcarouter.d.ts +34 -0
- package/dist/ai/llm/orcarouter.d.ts.map +1 -0
- package/dist/ai/llm/orcarouter.js +45 -0
- package/dist/ai/llm/orcarouter.js.map +1 -0
- package/dist/ai/llm/recover-tool.d.ts +21 -0
- package/dist/ai/llm/recover-tool.d.ts.map +1 -0
- package/dist/ai/llm/recover-tool.js +109 -0
- package/dist/ai/llm/recover-tool.js.map +1 -0
- package/dist/ai/llm/types.d.ts +122 -0
- package/dist/ai/llm/types.d.ts.map +1 -0
- package/dist/ai/llm/types.js +33 -0
- package/dist/ai/llm/types.js.map +1 -0
- package/dist/ai/providers.d.ts +59 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +54 -0
- package/dist/ai/providers.js.map +1 -0
- package/dist/ai/summarize.d.ts +25 -0
- package/dist/ai/summarize.d.ts.map +1 -0
- package/dist/ai/summarize.js +34 -0
- package/dist/ai/summarize.js.map +1 -0
- package/dist/ai/synthesize.d.ts +40 -0
- package/dist/ai/synthesize.d.ts.map +1 -0
- package/dist/ai/synthesize.js +230 -0
- package/dist/ai/synthesize.js.map +1 -0
- package/dist/ask/ask.d.ts +199 -0
- package/dist/ask/ask.d.ts.map +1 -0
- package/dist/ask/ask.js +1291 -0
- package/dist/ask/ask.js.map +1 -0
- package/dist/ask/file-rank.d.ts +72 -0
- package/dist/ask/file-rank.d.ts.map +1 -0
- package/dist/ask/file-rank.js +160 -0
- package/dist/ask/file-rank.js.map +1 -0
- package/dist/ask/file-selection.d.ts +22 -0
- package/dist/ask/file-selection.d.ts.map +1 -0
- package/dist/ask/file-selection.js +66 -0
- package/dist/ask/file-selection.js.map +1 -0
- package/dist/ask/fuse.d.ts +195 -0
- package/dist/ask/fuse.d.ts.map +1 -0
- package/dist/ask/fuse.js +344 -0
- package/dist/ask/fuse.js.map +1 -0
- package/dist/ask/graphrank.d.ts +61 -0
- package/dist/ask/graphrank.d.ts.map +1 -0
- package/dist/ask/graphrank.js +130 -0
- package/dist/ask/graphrank.js.map +1 -0
- package/dist/ask/index-file.d.ts +44 -0
- package/dist/ask/index-file.d.ts.map +1 -0
- package/dist/ask/index-file.js +128 -0
- package/dist/ask/index-file.js.map +1 -0
- package/dist/ask/semantic.d.ts +42 -0
- package/dist/ask/semantic.d.ts.map +1 -0
- package/dist/ask/semantic.js +293 -0
- package/dist/ask/semantic.js.map +1 -0
- package/dist/bin/graft.d.ts +3 -0
- package/dist/bin/graft.d.ts.map +1 -0
- package/dist/bin/graft.js +14 -0
- package/dist/bin/graft.js.map +1 -0
- package/dist/bin/trail.d.ts +3 -0
- package/dist/bin/trail.d.ts.map +1 -0
- package/dist/bin/trail.js +13 -0
- package/dist/bin/trail.js.map +1 -0
- package/dist/blast/blast-cli.d.ts +35 -0
- package/dist/blast/blast-cli.d.ts.map +1 -0
- package/dist/blast/blast-cli.js +155 -0
- package/dist/blast/blast-cli.js.map +1 -0
- package/dist/blast/blast.d.ts +128 -0
- package/dist/blast/blast.d.ts.map +1 -0
- package/dist/blast/blast.js +383 -0
- package/dist/blast/blast.js.map +1 -0
- package/dist/blast/diff.d.ts +53 -0
- package/dist/blast/diff.d.ts.map +1 -0
- package/dist/blast/diff.js +193 -0
- package/dist/blast/diff.js.map +1 -0
- package/dist/blast/evidence.d.ts +51 -0
- package/dist/blast/evidence.d.ts.map +1 -0
- package/dist/blast/evidence.js +162 -0
- package/dist/blast/evidence.js.map +1 -0
- package/dist/blast/modules.d.ts +33 -0
- package/dist/blast/modules.d.ts.map +1 -0
- package/dist/blast/modules.js +83 -0
- package/dist/blast/modules.js.map +1 -0
- package/dist/blast/name.d.ts +74 -0
- package/dist/blast/name.d.ts.map +1 -0
- package/dist/blast/name.js +269 -0
- package/dist/blast/name.js.map +1 -0
- package/dist/blast/owners.d.ts +85 -0
- package/dist/blast/owners.d.ts.map +1 -0
- package/dist/blast/owners.js +272 -0
- package/dist/blast/owners.js.map +1 -0
- package/dist/blast/render.d.ts +46 -0
- package/dist/blast/render.d.ts.map +1 -0
- package/dist/blast/render.js +422 -0
- package/dist/blast/render.js.map +1 -0
- package/dist/blast/viz.d.ts +37 -0
- package/dist/blast/viz.d.ts.map +1 -0
- package/dist/blast/viz.js +180 -0
- package/dist/blast/viz.js.map +1 -0
- package/dist/brand.d.ts +111 -0
- package/dist/brand.d.ts.map +1 -0
- package/dist/brand.js +282 -0
- package/dist/brand.js.map +1 -0
- package/dist/claude/build-progress.d.ts +30 -0
- package/dist/claude/build-progress.d.ts.map +1 -0
- package/dist/claude/build-progress.js +81 -0
- package/dist/claude/build-progress.js.map +1 -0
- package/dist/claude/hermes-skill-template.d.ts +16 -0
- package/dist/claude/hermes-skill-template.d.ts.map +1 -0
- package/dist/claude/hermes-skill-template.js +154 -0
- package/dist/claude/hermes-skill-template.js.map +1 -0
- package/dist/claude/init.d.ts +65 -0
- package/dist/claude/init.d.ts.map +1 -0
- package/dist/claude/init.js +258 -0
- package/dist/claude/init.js.map +1 -0
- package/dist/claude/paths.d.ts +9 -0
- package/dist/claude/paths.d.ts.map +1 -0
- package/dist/claude/paths.js +22 -0
- package/dist/claude/paths.js.map +1 -0
- package/dist/claude/session-metrics.d.ts +73 -0
- package/dist/claude/session-metrics.d.ts.map +1 -0
- package/dist/claude/session-metrics.js +209 -0
- package/dist/claude/session-metrics.js.map +1 -0
- package/dist/claude/settings-merge.d.ts +76 -0
- package/dist/claude/settings-merge.d.ts.map +1 -0
- package/dist/claude/settings-merge.js +283 -0
- package/dist/claude/settings-merge.js.map +1 -0
- package/dist/claude/skill-template.d.ts +13 -0
- package/dist/claude/skill-template.d.ts.map +1 -0
- package/dist/claude/skill-template.js +290 -0
- package/dist/claude/skill-template.js.map +1 -0
- package/dist/claude/state.d.ts +85 -0
- package/dist/claude/state.d.ts.map +1 -0
- package/dist/claude/state.js +88 -0
- package/dist/claude/state.js.map +1 -0
- package/dist/claude/stats.d.ts +5 -0
- package/dist/claude/stats.d.ts.map +1 -0
- package/dist/claude/stats.js +24 -0
- package/dist/claude/stats.js.map +1 -0
- package/dist/cli-epilogue.d.ts +12 -0
- package/dist/cli-epilogue.d.ts.map +1 -0
- package/dist/cli-epilogue.js +72 -0
- package/dist/cli-epilogue.js.map +1 -0
- package/dist/cli-meta.d.ts +82 -0
- package/dist/cli-meta.d.ts.map +1 -0
- package/dist/cli-meta.js +238 -0
- package/dist/cli-meta.js.map +1 -0
- package/dist/cli-picker.d.ts +139 -0
- package/dist/cli-picker.d.ts.map +1 -0
- package/dist/cli-picker.js +439 -0
- package/dist/cli-picker.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1638 -0
- package/dist/cli.js.map +1 -0
- package/dist/context/batches.d.ts +29 -0
- package/dist/context/batches.d.ts.map +1 -0
- package/dist/context/batches.js +130 -0
- package/dist/context/batches.js.map +1 -0
- package/dist/context/build.d.ts +57 -0
- package/dist/context/build.d.ts.map +1 -0
- package/dist/context/build.js +396 -0
- package/dist/context/build.js.map +1 -0
- package/dist/context/check.d.ts +42 -0
- package/dist/context/check.d.ts.map +1 -0
- package/dist/context/check.js +162 -0
- package/dist/context/check.js.map +1 -0
- package/dist/context/map-dir.d.ts +13 -0
- package/dist/context/map-dir.d.ts.map +1 -0
- package/dist/context/map-dir.js +81 -0
- package/dist/context/map-dir.js.map +1 -0
- package/dist/context/node-file.d.ts +109 -0
- package/dist/context/node-file.d.ts.map +1 -0
- package/dist/context/node-file.js +390 -0
- package/dist/context/node-file.js.map +1 -0
- package/dist/context/price.d.ts +49 -0
- package/dist/context/price.d.ts.map +1 -0
- package/dist/context/price.js +83 -0
- package/dist/context/price.js.map +1 -0
- package/dist/context/savings.d.ts +67 -0
- package/dist/context/savings.d.ts.map +1 -0
- package/dist/context/savings.js +125 -0
- package/dist/context/savings.js.map +1 -0
- package/dist/engine.d.ts +85 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +122 -0
- package/dist/engine.js.map +1 -0
- package/dist/graph/bindings.d.ts +64 -0
- package/dist/graph/bindings.d.ts.map +1 -0
- package/dist/graph/bindings.js +713 -0
- package/dist/graph/bindings.js.map +1 -0
- package/dist/graph/build-run.d.ts +25 -0
- package/dist/graph/build-run.d.ts.map +1 -0
- package/dist/graph/build-run.js +121 -0
- package/dist/graph/build-run.js.map +1 -0
- package/dist/graph/build.d.ts +88 -0
- package/dist/graph/build.d.ts.map +1 -0
- package/dist/graph/build.js +386 -0
- package/dist/graph/build.js.map +1 -0
- package/dist/graph/cards.d.ts +46 -0
- package/dist/graph/cards.d.ts.map +1 -0
- package/dist/graph/cards.js +280 -0
- package/dist/graph/cards.js.map +1 -0
- package/dist/graph/check.d.ts +25 -0
- package/dist/graph/check.d.ts.map +1 -0
- package/dist/graph/check.js +192 -0
- package/dist/graph/check.js.map +1 -0
- package/dist/graph/container.d.ts +63 -0
- package/dist/graph/container.d.ts.map +1 -0
- package/dist/graph/container.js +191 -0
- package/dist/graph/container.js.map +1 -0
- package/dist/graph/depth-parser.d.ts +61 -0
- package/dist/graph/depth-parser.d.ts.map +1 -0
- package/dist/graph/depth-parser.js +153 -0
- package/dist/graph/depth-parser.js.map +1 -0
- package/dist/graph/enrich.d.ts +62 -0
- package/dist/graph/enrich.d.ts.map +1 -0
- package/dist/graph/enrich.js +258 -0
- package/dist/graph/enrich.js.map +1 -0
- package/dist/graph/extract-cache.d.ts +101 -0
- package/dist/graph/extract-cache.d.ts.map +1 -0
- package/dist/graph/extract-cache.js +199 -0
- package/dist/graph/extract-cache.js.map +1 -0
- package/dist/graph/extract.d.ts +85 -0
- package/dist/graph/extract.d.ts.map +1 -0
- package/dist/graph/extract.js +2377 -0
- package/dist/graph/extract.js.map +1 -0
- package/dist/graph/fingerprint.d.ts +76 -0
- package/dist/graph/fingerprint.d.ts.map +1 -0
- package/dist/graph/fingerprint.js +160 -0
- package/dist/graph/fingerprint.js.map +1 -0
- package/dist/graph/generic.d.ts +74 -0
- package/dist/graph/generic.d.ts.map +1 -0
- package/dist/graph/generic.js +773 -0
- package/dist/graph/generic.js.map +1 -0
- package/dist/graph/invariants.d.ts +33 -0
- package/dist/graph/invariants.d.ts.map +1 -0
- package/dist/graph/invariants.js +52 -0
- package/dist/graph/invariants.js.map +1 -0
- package/dist/graph/load.d.ts +29 -0
- package/dist/graph/load.d.ts.map +1 -0
- package/dist/graph/load.js +97 -0
- package/dist/graph/load.js.map +1 -0
- package/dist/graph/lsp/client.d.ts +61 -0
- package/dist/graph/lsp/client.d.ts.map +1 -0
- package/dist/graph/lsp/client.js +217 -0
- package/dist/graph/lsp/client.js.map +1 -0
- package/dist/graph/lsp/enrich.d.ts +11 -0
- package/dist/graph/lsp/enrich.d.ts.map +1 -0
- package/dist/graph/lsp/enrich.js +163 -0
- package/dist/graph/lsp/enrich.js.map +1 -0
- package/dist/graph/lsp/registry.d.ts +22 -0
- package/dist/graph/lsp/registry.d.ts.map +1 -0
- package/dist/graph/lsp/registry.js +71 -0
- package/dist/graph/lsp/registry.js.map +1 -0
- package/dist/graph/map.d.ts +107 -0
- package/dist/graph/map.d.ts.map +1 -0
- package/dist/graph/map.js +239 -0
- package/dist/graph/map.js.map +1 -0
- package/dist/graph/markdown.d.ts +22 -0
- package/dist/graph/markdown.d.ts.map +1 -0
- package/dist/graph/markdown.js +143 -0
- package/dist/graph/markdown.js.map +1 -0
- package/dist/graph/native.d.ts +46 -0
- package/dist/graph/native.d.ts.map +1 -0
- package/dist/graph/native.js +169 -0
- package/dist/graph/native.js.map +1 -0
- package/dist/graph/queries/c.scm +13 -0
- package/dist/graph/queries/c_sharp.scm +19 -0
- package/dist/graph/queries/clojure.scm +58 -0
- package/dist/graph/queries/cpp.scm +23 -0
- package/dist/graph/queries/dart.scm +42 -0
- package/dist/graph/queries/elixir.scm +54 -0
- package/dist/graph/queries/gleam.scm +51 -0
- package/dist/graph/queries/java.scm +20 -0
- package/dist/graph/queries/kotlin.scm +43 -0
- package/dist/graph/queries/lua.scm +36 -0
- package/dist/graph/queries/nix.scm +32 -0
- package/dist/graph/queries/php.scm +40 -0
- package/dist/graph/queries/ruby.scm +65 -0
- package/dist/graph/queries/rust.scm +41 -0
- package/dist/graph/queries/scala.scm +66 -0
- package/dist/graph/queries/solidity.scm +43 -0
- package/dist/graph/queries/swift.scm +51 -0
- package/dist/graph/refresh.d.ts +106 -0
- package/dist/graph/refresh.d.ts.map +1 -0
- package/dist/graph/refresh.js +430 -0
- package/dist/graph/refresh.js.map +1 -0
- package/dist/graph/relations.d.ts +14 -0
- package/dist/graph/relations.d.ts.map +1 -0
- package/dist/graph/relations.js +8 -0
- package/dist/graph/relations.js.map +1 -0
- package/dist/graph/resolve.d.ts +17 -0
- package/dist/graph/resolve.d.ts.map +1 -0
- package/dist/graph/resolve.js +716 -0
- package/dist/graph/resolve.js.map +1 -0
- package/dist/graph/root.d.ts +11 -0
- package/dist/graph/root.d.ts.map +1 -0
- package/dist/graph/root.js +40 -0
- package/dist/graph/root.js.map +1 -0
- package/dist/graph/scopes.d.ts +40 -0
- package/dist/graph/scopes.d.ts.map +1 -0
- package/dist/graph/scopes.js +383 -0
- package/dist/graph/scopes.js.map +1 -0
- package/dist/graph/seed.d.ts +38 -0
- package/dist/graph/seed.d.ts.map +1 -0
- package/dist/graph/seed.js +229 -0
- package/dist/graph/seed.js.map +1 -0
- package/dist/graph/source-files.d.ts +46 -0
- package/dist/graph/source-files.d.ts.map +1 -0
- package/dist/graph/source-files.js +118 -0
- package/dist/graph/source-files.js.map +1 -0
- package/dist/graph/traverse-cli.d.ts +55 -0
- package/dist/graph/traverse-cli.d.ts.map +1 -0
- package/dist/graph/traverse-cli.js +189 -0
- package/dist/graph/traverse-cli.js.map +1 -0
- package/dist/graph/traverse.d.ts +112 -0
- package/dist/graph/traverse.d.ts.map +1 -0
- package/dist/graph/traverse.js +192 -0
- package/dist/graph/traverse.js.map +1 -0
- package/dist/graph/types.d.ts +78 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +14 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/graph/wasm-runtime.d.ts +19 -0
- package/dist/graph/wasm-runtime.d.ts.map +1 -0
- package/dist/graph/wasm-runtime.js +38 -0
- package/dist/graph/wasm-runtime.js.map +1 -0
- package/dist/graph/workspace-cli.d.ts +56 -0
- package/dist/graph/workspace-cli.d.ts.map +1 -0
- package/dist/graph/workspace-cli.js +111 -0
- package/dist/graph/workspace-cli.js.map +1 -0
- package/dist/graph/workspace.d.ts +172 -0
- package/dist/graph/workspace.d.ts.map +1 -0
- package/dist/graph/workspace.js +714 -0
- package/dist/graph/workspace.js.map +1 -0
- package/dist/graph/write.d.ts +13 -0
- package/dist/graph/write.d.ts.map +1 -0
- package/dist/graph/write.js +86 -0
- package/dist/graph/write.js.map +1 -0
- package/dist/hosts/antigravity.d.ts +14 -0
- package/dist/hosts/antigravity.d.ts.map +1 -0
- package/dist/hosts/antigravity.js +59 -0
- package/dist/hosts/antigravity.js.map +1 -0
- package/dist/hosts/auto.d.ts +37 -0
- package/dist/hosts/auto.d.ts.map +1 -0
- package/dist/hosts/auto.js +141 -0
- package/dist/hosts/auto.js.map +1 -0
- package/dist/hosts/claude-global.d.ts +72 -0
- package/dist/hosts/claude-global.d.ts.map +1 -0
- package/dist/hosts/claude-global.js +230 -0
- package/dist/hosts/claude-global.js.map +1 -0
- package/dist/hosts/config-write.d.ts +36 -0
- package/dist/hosts/config-write.d.ts.map +1 -0
- package/dist/hosts/config-write.js +64 -0
- package/dist/hosts/config-write.js.map +1 -0
- package/dist/hosts/init.d.ts +28 -0
- package/dist/hosts/init.d.ts.map +1 -0
- package/dist/hosts/init.js +89 -0
- package/dist/hosts/init.js.map +1 -0
- package/dist/hosts/instructions.d.ts +14 -0
- package/dist/hosts/instructions.d.ts.map +1 -0
- package/dist/hosts/instructions.js +95 -0
- package/dist/hosts/instructions.js.map +1 -0
- package/dist/hosts/mcp-config.d.ts +78 -0
- package/dist/hosts/mcp-config.d.ts.map +1 -0
- package/dist/hosts/mcp-config.js +251 -0
- package/dist/hosts/mcp-config.js.map +1 -0
- package/dist/hosts/plan.d.ts +32 -0
- package/dist/hosts/plan.d.ts.map +1 -0
- package/dist/hosts/plan.js +73 -0
- package/dist/hosts/plan.js.map +1 -0
- package/dist/hosts/registry.d.ts +41 -0
- package/dist/hosts/registry.d.ts.map +1 -0
- package/dist/hosts/registry.js +164 -0
- package/dist/hosts/registry.js.map +1 -0
- package/dist/hosts/retract.d.ts +47 -0
- package/dist/hosts/retract.d.ts.map +1 -0
- package/dist/hosts/retract.js +520 -0
- package/dist/hosts/retract.js.map +1 -0
- package/dist/hosts/sections.d.ts +47 -0
- package/dist/hosts/sections.d.ts.map +1 -0
- package/dist/hosts/sections.js +127 -0
- package/dist/hosts/sections.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest/fs.d.ts +79 -0
- package/dist/ingest/fs.d.ts.map +1 -0
- package/dist/ingest/fs.js +306 -0
- package/dist/ingest/fs.js.map +1 -0
- package/dist/init-guard.d.ts +16 -0
- package/dist/init-guard.d.ts.map +1 -0
- package/dist/init-guard.js +27 -0
- package/dist/init-guard.js.map +1 -0
- package/dist/mcp/instructions.d.ts +5 -0
- package/dist/mcp/instructions.d.ts.map +1 -0
- package/dist/mcp/instructions.js +64 -0
- package/dist/mcp/instructions.js.map +1 -0
- package/dist/mcp/kept-listing.d.ts +27 -0
- package/dist/mcp/kept-listing.d.ts.map +1 -0
- package/dist/mcp/kept-listing.js +63 -0
- package/dist/mcp/kept-listing.js.map +1 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +147 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tool-names.d.ts +27 -0
- package/dist/mcp/tool-names.d.ts.map +1 -0
- package/dist/mcp/tool-names.js +47 -0
- package/dist/mcp/tool-names.js.map +1 -0
- package/dist/mcp/tools.d.ts +22 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +440 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/node-version.d.ts +15 -0
- package/dist/node-version.d.ts.map +1 -0
- package/dist/node-version.js +23 -0
- package/dist/node-version.js.map +1 -0
- package/dist/search/grep-cli.d.ts +35 -0
- package/dist/search/grep-cli.d.ts.map +1 -0
- package/dist/search/grep-cli.js +115 -0
- package/dist/search/grep-cli.js.map +1 -0
- package/dist/search/grep.d.ts +60 -0
- package/dist/search/grep.d.ts.map +1 -0
- package/dist/search/grep.js +143 -0
- package/dist/search/grep.js.map +1 -0
- package/dist/search/ignored-code.d.ts +9 -0
- package/dist/search/ignored-code.d.ts.map +1 -0
- package/dist/search/ignored-code.js +73 -0
- package/dist/search/ignored-code.js.map +1 -0
- package/dist/search/user-regexp.d.ts +26 -0
- package/dist/search/user-regexp.d.ts.map +1 -0
- package/dist/search/user-regexp.js +150 -0
- package/dist/search/user-regexp.js.map +1 -0
- package/dist/telemetry/contract.d.ts +117 -0
- package/dist/telemetry/contract.d.ts.map +1 -0
- package/dist/telemetry/contract.js +341 -0
- package/dist/telemetry/contract.js.map +1 -0
- package/dist/telemetry/flush.d.ts +21 -0
- package/dist/telemetry/flush.d.ts.map +1 -0
- package/dist/telemetry/flush.js +85 -0
- package/dist/telemetry/flush.js.map +1 -0
- package/dist/telemetry/gate.d.ts +30 -0
- package/dist/telemetry/gate.d.ts.map +1 -0
- package/dist/telemetry/gate.js +81 -0
- package/dist/telemetry/gate.js.map +1 -0
- package/dist/telemetry/identity.d.ts +40 -0
- package/dist/telemetry/identity.d.ts.map +1 -0
- package/dist/telemetry/identity.js +80 -0
- package/dist/telemetry/identity.js.map +1 -0
- package/dist/telemetry/index.d.ts +18 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +16 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/key.d.ts +21 -0
- package/dist/telemetry/key.d.ts.map +1 -0
- package/dist/telemetry/key.js +49 -0
- package/dist/telemetry/key.js.map +1 -0
- package/dist/telemetry/notice.d.ts +19 -0
- package/dist/telemetry/notice.d.ts.map +1 -0
- package/dist/telemetry/notice.js +93 -0
- package/dist/telemetry/notice.js.map +1 -0
- package/dist/telemetry/queue.d.ts +35 -0
- package/dist/telemetry/queue.d.ts.map +1 -0
- package/dist/telemetry/queue.js +162 -0
- package/dist/telemetry/queue.js.map +1 -0
- package/dist/telemetry/send.d.ts +19 -0
- package/dist/telemetry/send.d.ts.map +1 -0
- package/dist/telemetry/send.js +84 -0
- package/dist/telemetry/send.js.map +1 -0
- package/dist/telemetry/sessions.d.ts +25 -0
- package/dist/telemetry/sessions.d.ts.map +1 -0
- package/dist/telemetry/sessions.js +104 -0
- package/dist/telemetry/sessions.js.map +1 -0
- package/dist/telemetry/track.d.ts +62 -0
- package/dist/telemetry/track.d.ts.map +1 -0
- package/dist/telemetry/track.js +143 -0
- package/dist/telemetry/track.js.map +1 -0
- package/dist/upkeep-run.d.ts +22 -0
- package/dist/upkeep-run.d.ts.map +1 -0
- package/dist/upkeep-run.js +85 -0
- package/dist/upkeep-run.js.map +1 -0
- package/dist/upkeep.d.ts +127 -0
- package/dist/upkeep.d.ts.map +1 -0
- package/dist/upkeep.js +252 -0
- package/dist/upkeep.js.map +1 -0
- package/dist/util/actions-folder.d.ts +2 -0
- package/dist/util/actions-folder.d.ts.map +1 -0
- package/dist/util/actions-folder.js +9 -0
- package/dist/util/actions-folder.js.map +1 -0
- package/dist/util/browser.d.ts +3 -0
- package/dist/util/browser.d.ts.map +1 -0
- package/dist/util/browser.js +14 -0
- package/dist/util/browser.js.map +1 -0
- package/dist/util/child-process.d.ts +15 -0
- package/dist/util/child-process.d.ts.map +1 -0
- package/dist/util/child-process.js +15 -0
- package/dist/util/child-process.js.map +1 -0
- package/dist/util/front-matter.d.ts +46 -0
- package/dist/util/front-matter.d.ts.map +1 -0
- package/dist/util/front-matter.js +113 -0
- package/dist/util/front-matter.js.map +1 -0
- package/dist/util/id.d.ts +7 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +14 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/paths.d.ts +29 -0
- package/dist/util/paths.d.ts.map +1 -0
- package/dist/util/paths.js +71 -0
- package/dist/util/paths.js.map +1 -0
- package/dist/util/private-file.d.ts +14 -0
- package/dist/util/private-file.d.ts.map +1 -0
- package/dist/util/private-file.js +82 -0
- package/dist/util/private-file.js.map +1 -0
- package/dist/util/source.d.ts +4 -0
- package/dist/util/source.d.ts.map +1 -0
- package/dist/util/source.js +12 -0
- package/dist/util/source.js.map +1 -0
- package/dist/util/spinner.d.ts +15 -0
- package/dist/util/spinner.d.ts.map +1 -0
- package/dist/util/spinner.js +52 -0
- package/dist/util/spinner.js.map +1 -0
- package/dist/util/state.d.ts +120 -0
- package/dist/util/state.d.ts.map +1 -0
- package/dist/util/state.js +264 -0
- package/dist/util/state.js.map +1 -0
- package/dist/vendor/grammars/tree-sitter-go.LICENSE +21 -0
- package/dist/vendor/grammars/tree-sitter-go.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-java.LICENSE +21 -0
- package/dist/vendor/grammars/tree-sitter-java.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-kotlin.LICENSE +9 -0
- package/dist/vendor/grammars/tree-sitter-kotlin.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-php.LICENSE +22 -0
- package/dist/vendor/grammars/tree-sitter-php.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-python.LICENSE +21 -0
- package/dist/vendor/grammars/tree-sitter-python.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-r.LICENSE +9 -0
- package/dist/vendor/grammars/tree-sitter-r.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-swift.LICENSE +21 -0
- package/dist/vendor/grammars/tree-sitter-swift.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-typescript.LICENSE +21 -0
- package/dist/vendor/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/viewer/app.js +2 -0
- package/dist/viewer/index.html +49 -0
- package/dist/viewer/style.css +154 -0
- package/dist/viz/assemble.d.ts +83 -0
- package/dist/viz/assemble.d.ts.map +1 -0
- package/dist/viz/assemble.js +101 -0
- package/dist/viz/assemble.js.map +1 -0
- package/dist/viz/export.d.ts +39 -0
- package/dist/viz/export.d.ts.map +1 -0
- package/dist/viz/export.js +98 -0
- package/dist/viz/export.js.map +1 -0
- package/dist/viz/serve.d.ts +13 -0
- package/dist/viz/serve.d.ts.map +1 -0
- package/dist/viz/serve.js +130 -0
- package/dist/viz/serve.js.map +1 -0
- package/package.json +115 -4
- package/scripts/build-grammar-wasm.mjs +112 -0
- package/scripts/build-viewer.mjs +44 -0
- package/scripts/graph-quality.mjs +117 -0
- package/scripts/pack-trail.mjs +53 -0
- package/scripts/postinstall.mjs +65 -0
- package/scripts/run-tests.mjs +72 -0
- package/scripts/stamp-telemetry-key.mjs +56 -0
- package/scripts/tally-audit.mjs +140 -0
- package/scripts/vendor-grammars.mjs +53 -0
|
@@ -0,0 +1,713 @@
|
|
|
1
|
+
/** Variable/field → bare type name, keyed by scope. Scope keys mirror
|
|
2
|
+
* extract.ts's own scope stack (`scope.join(".")`, `""` at module level) so a
|
|
3
|
+
* lookup from extract.ts's walk finds exactly what was bound in the same
|
|
4
|
+
* lexical position. */
|
|
5
|
+
export class FileBindings {
|
|
6
|
+
map = new Map();
|
|
7
|
+
set(scopePath, name, type) {
|
|
8
|
+
this.map.set(`${scopePath}|${name}`, type);
|
|
9
|
+
}
|
|
10
|
+
/** Innermost-first: for scope ["a","b"] name "x", tries `a.b|x`, `a|x`, `|x`. */
|
|
11
|
+
lookup(scope, name) {
|
|
12
|
+
for (let i = scope.length; i >= 0; i--) {
|
|
13
|
+
const hit = this.map.get(`${scope.slice(0, i).join(".")}|${name}`);
|
|
14
|
+
if (hit)
|
|
15
|
+
return hit;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const FN_VALUE_TYPES = new Set(["arrow_function", "function", "function_expression", "generator_function"]);
|
|
21
|
+
/** Definition-node types that push a new scope segment, mirroring extract.ts's
|
|
22
|
+
* `describe()` closely enough to keep the two scope stacks in lockstep — but
|
|
23
|
+
* duplicated here (not imported) to keep bindings.ts free of a value import on
|
|
24
|
+
* extract.ts. Returns the def's scope segment (bare name, except a Go method
|
|
25
|
+
* which is receiver-qualified — `Receiver.method` — exactly like extract.ts's
|
|
26
|
+
* `idName`, so a binding recorded inside a Go method body is stored under the
|
|
27
|
+
* same scope key extract.ts's walk will look it up with), or null if `node`
|
|
28
|
+
* isn't a definition. */
|
|
29
|
+
export function defName(node, lang) {
|
|
30
|
+
if (lang === "java") {
|
|
31
|
+
return JAVA_DEF_TYPES.has(node.type) ? (node.childForFieldName("name")?.text ?? null) : null;
|
|
32
|
+
}
|
|
33
|
+
if (lang === "go") {
|
|
34
|
+
if (node.type === "method_declaration") {
|
|
35
|
+
const name = node.childForFieldName("name")?.text;
|
|
36
|
+
if (!name)
|
|
37
|
+
return null;
|
|
38
|
+
const recv = goReceiverTypeOf(node);
|
|
39
|
+
return recv ? `${recv}.${name}` : name;
|
|
40
|
+
}
|
|
41
|
+
if (node.type === "function_declaration" || node.type === "type_spec") {
|
|
42
|
+
return node.childForFieldName("name")?.text ?? null;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
if (lang === "r")
|
|
47
|
+
return rDefName(node);
|
|
48
|
+
if (lang === "swift")
|
|
49
|
+
return swiftDefName(node);
|
|
50
|
+
if (lang === "php") {
|
|
51
|
+
const phpDefTypes = new Set([
|
|
52
|
+
"class_declaration",
|
|
53
|
+
"interface_declaration",
|
|
54
|
+
"trait_declaration",
|
|
55
|
+
"enum_declaration",
|
|
56
|
+
"method_declaration",
|
|
57
|
+
"function_definition",
|
|
58
|
+
]);
|
|
59
|
+
if (phpDefTypes.has(node.type))
|
|
60
|
+
return node.childForFieldName("name")?.text ?? null;
|
|
61
|
+
// Closures push a scope segment in extract.ts too — mirror it so a typed
|
|
62
|
+
// parameter bound inside a closure is keyed under the same scope path.
|
|
63
|
+
if (node.type === "anonymous_function" || node.type === "arrow_function")
|
|
64
|
+
return phpClosureName(node);
|
|
65
|
+
// Anonymous classes likewise mint an `{anonymous}` scope segment (#144).
|
|
66
|
+
if (node.type === "anonymous_class")
|
|
67
|
+
return "{anonymous}";
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const defTypes = lang === "python"
|
|
71
|
+
? new Set(["class_definition", "function_definition"])
|
|
72
|
+
: new Set([
|
|
73
|
+
"class_declaration",
|
|
74
|
+
"abstract_class_declaration",
|
|
75
|
+
"function_declaration",
|
|
76
|
+
"generator_function_declaration",
|
|
77
|
+
"method_definition",
|
|
78
|
+
"interface_declaration",
|
|
79
|
+
"type_alias_declaration",
|
|
80
|
+
"enum_declaration",
|
|
81
|
+
]);
|
|
82
|
+
if (defTypes.has(node.type))
|
|
83
|
+
return node.childForFieldName("name")?.text ?? null;
|
|
84
|
+
if ((lang === "typescript" || lang === "tsx") && node.type === "variable_declarator") {
|
|
85
|
+
const value = node.childForFieldName("value");
|
|
86
|
+
if (value && FN_VALUE_TYPES.has(value.type))
|
|
87
|
+
return node.childForFieldName("name")?.text ?? null;
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
/** The scope segment a Swift definition pushes, mirroring extract.ts's
|
|
92
|
+
* `describeSwift` (duplicated, not imported, per this file's
|
|
93
|
+
* no-value-import-of-extract rule): types and extensions push the type's name
|
|
94
|
+
* (an extension is named after the type it extends), functions their own name,
|
|
95
|
+
* and an `init` the enclosing type's name — extract.ts names initializers after
|
|
96
|
+
* their type, so the two scope stacks stay in lockstep inside an init body.
|
|
97
|
+
* Typealias and top-level properties DO mint nodes in extract.ts but are
|
|
98
|
+
* deliberately absent here: neither has a body a binding could be set in (a
|
|
99
|
+
* property initializer's closure is the one vanishing exception, mis-keying
|
|
100
|
+
* only bindings set inside itself). */
|
|
101
|
+
function swiftDefName(node) {
|
|
102
|
+
if (node.type === "class_declaration") {
|
|
103
|
+
if (node.children.some((c) => c.type === "extension")) {
|
|
104
|
+
const ut = node.namedChildren.find((c) => c.type === "user_type");
|
|
105
|
+
const ids = ut?.namedChildren.filter((c) => c.type === "type_identifier") ?? [];
|
|
106
|
+
return ids.at(-1)?.text ?? null;
|
|
107
|
+
}
|
|
108
|
+
return node.namedChildren.find((c) => c.type === "type_identifier")?.text ?? null;
|
|
109
|
+
}
|
|
110
|
+
if (node.type === "protocol_declaration") {
|
|
111
|
+
return node.namedChildren.find((c) => c.type === "type_identifier")?.text ?? null;
|
|
112
|
+
}
|
|
113
|
+
if (node.type === "function_declaration" || node.type === "protocol_function_declaration") {
|
|
114
|
+
return node.namedChildren.find((c) => c.type === "simple_identifier")?.text ?? null;
|
|
115
|
+
}
|
|
116
|
+
if (node.type === "init_declaration") {
|
|
117
|
+
const owner = node.parent?.parent; // class_body / protocol_body → the declaration
|
|
118
|
+
return owner ? swiftDefName(owner) : null;
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
const R_ASSIGN_OPS = new Set(["<-", "<<-", "="]);
|
|
123
|
+
const R_RIGHT_ASSIGN_OPS = new Set(["->", "->>"]);
|
|
124
|
+
/**
|
|
125
|
+
* The bare name a `binary_operator` (left-assign) or `function_definition`
|
|
126
|
+
* (right-assign) node defines, for R's two plain-function assignment shapes —
|
|
127
|
+
* this file's own `defName` uses it directly. extract.ts's `describeR`
|
|
128
|
+
* duplicates the same op-filtering check rather than importing this (same
|
|
129
|
+
* reasoning as the Go receiver helpers below: bindings.ts can't take a value
|
|
130
|
+
* import back on extract.ts), and additionally needs to distinguish an S3
|
|
131
|
+
* `generic.Class` method and R6/S4 class/method shapes this function doesn't
|
|
132
|
+
* know about — bindings.ts has no equivalent need since no `handleR` binding
|
|
133
|
+
* collector exists yet (R6/S4/S3 don't get a member/receiver-type table in
|
|
134
|
+
* this pass; `self`/`private` resolve directly via `ctx.enclosingClass`
|
|
135
|
+
* instead, needing no lookup). See `describeR`'s doc comment for why
|
|
136
|
+
* right-assign's AST shape needs its own branch rather than mirroring
|
|
137
|
+
* left-assign's (empirically, not assumed — `->`'s low precedence means it's
|
|
138
|
+
* absorbed into the function's own `body` field, not an outer wrapper).
|
|
139
|
+
* Null if `node` isn't one of these two shapes.
|
|
140
|
+
*/
|
|
141
|
+
export function rDefName(node) {
|
|
142
|
+
if (node.type === "binary_operator") {
|
|
143
|
+
const op = node.childForFieldName("operator")?.text;
|
|
144
|
+
if (!op || !R_ASSIGN_OPS.has(op))
|
|
145
|
+
return null;
|
|
146
|
+
const lhs = node.childForFieldName("lhs");
|
|
147
|
+
const rhs = node.childForFieldName("rhs");
|
|
148
|
+
return lhs?.type === "identifier" && rhs?.type === "function_definition" ? lhs.text : null;
|
|
149
|
+
}
|
|
150
|
+
if (node.type === "function_definition") {
|
|
151
|
+
const body = node.childForFieldName("body");
|
|
152
|
+
if (body?.type !== "binary_operator")
|
|
153
|
+
return null;
|
|
154
|
+
const op = body.childForFieldName("operator")?.text;
|
|
155
|
+
if (!op || !R_RIGHT_ASSIGN_OPS.has(op))
|
|
156
|
+
return null;
|
|
157
|
+
const rhs = body.childForFieldName("rhs");
|
|
158
|
+
return rhs?.type === "identifier" ? rhs.text : null;
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
/** The receiver parameter's own variable name for a Go method (`func (w *Worker) …`
|
|
163
|
+
* → `w`). Null if it can't be read. */
|
|
164
|
+
export function goReceiverVarOf(node) {
|
|
165
|
+
const recv = node.childForFieldName("receiver");
|
|
166
|
+
const param = recv?.namedChildren.find((c) => c.type === "parameter_declaration");
|
|
167
|
+
return param?.childForFieldName("name")?.text ?? null;
|
|
168
|
+
}
|
|
169
|
+
/** The receiver's base type name for a Go method, unwrapping a pointer receiver
|
|
170
|
+
* (`func (w *Worker) …` → `Worker`). Mirrors extract.ts's own `goReceiverType`
|
|
171
|
+
* (duplicated, not imported, per this file's no-value-import-of-extract rule).
|
|
172
|
+
* Null if it can't be read. */
|
|
173
|
+
function goReceiverTypeOf(node) {
|
|
174
|
+
const recv = node.childForFieldName("receiver");
|
|
175
|
+
const param = recv?.namedChildren.find((c) => c.type === "parameter_declaration");
|
|
176
|
+
let type = param?.childForFieldName("type");
|
|
177
|
+
if (type?.type === "pointer_type")
|
|
178
|
+
type = type.namedChildren.at(-1) ?? null;
|
|
179
|
+
return type?.type === "type_identifier" ? type.text : null;
|
|
180
|
+
}
|
|
181
|
+
/** Resolves a call site's receiver text (from `calleeName`) to a bound type
|
|
182
|
+
* name, given the enclosing walk state. `self`/`cls`/`this`/the Go receiver
|
|
183
|
+
* var resolve directly to the enclosing class; `super` — R6's `super$` and
|
|
184
|
+
* Swift's `super.` alike — resolves to the PARENT class instead
|
|
185
|
+
* (`ctx.rSuperClass`, not `ctx.enclosingClass` — a super call must climb past
|
|
186
|
+
* the current class's own same-named override, not find it); anything else is
|
|
187
|
+
* a bindings-map lookup, normalizing `this.` to `self.` since both are stored
|
|
188
|
+
* the same way. */
|
|
189
|
+
export function resolveRecvType(receiver, ctx) {
|
|
190
|
+
if (!receiver)
|
|
191
|
+
return undefined;
|
|
192
|
+
if (receiver === "self" || receiver === "cls" || receiver === "this")
|
|
193
|
+
return ctx.enclosingClass ?? undefined;
|
|
194
|
+
if (receiver === "super")
|
|
195
|
+
return ctx.rSuperClass ?? undefined;
|
|
196
|
+
if (receiver.startsWith("self.") || receiver.startsWith("this.")) {
|
|
197
|
+
return (ctx.bindings.lookup(ctx.scope, receiver) ??
|
|
198
|
+
ctx.bindings.lookup(ctx.scope, receiver.replace(/^this\./, "self.")) ??
|
|
199
|
+
undefined);
|
|
200
|
+
}
|
|
201
|
+
// PHP static call `Foo::bar()`: the scope operand is a class name, so it *is*
|
|
202
|
+
// the receiver type. (Member calls pass a `$var` receiver, filtered by the `$`.)
|
|
203
|
+
if (ctx.lang === "php" && !receiver.startsWith("$"))
|
|
204
|
+
return receiver;
|
|
205
|
+
return ((ctx.lang === "go" && receiver === ctx.goReceiverVar ? ctx.enclosingClass : undefined) ??
|
|
206
|
+
ctx.bindings.lookup(ctx.scope, receiver) ??
|
|
207
|
+
// Swift type-member call `Animal.staticThing()`: an uppercase receiver with no
|
|
208
|
+
// local binding is the type itself (Swift naming: types are UpperCamelCase,
|
|
209
|
+
// values lowerCamelCase — and a shadowing binding was already tried above).
|
|
210
|
+
(ctx.lang === "swift" && /^[A-Z]/.test(receiver) ? receiver : undefined) ??
|
|
211
|
+
undefined);
|
|
212
|
+
}
|
|
213
|
+
function isClassNode(node, lang) {
|
|
214
|
+
if (lang === "python")
|
|
215
|
+
return node.type === "class_definition";
|
|
216
|
+
if (lang === "java")
|
|
217
|
+
return JAVA_TYPE_DECLS.has(node.type);
|
|
218
|
+
if (lang === "typescript" || lang === "tsx") {
|
|
219
|
+
return node.type === "class_declaration" || node.type === "abstract_class_declaration";
|
|
220
|
+
}
|
|
221
|
+
// Swift: class_declaration covers class/struct/enum/actor/extension — all can
|
|
222
|
+
// hold members whose `self.field` bindings live at the type's scope.
|
|
223
|
+
if (lang === "swift") {
|
|
224
|
+
return node.type === "class_declaration" || node.type === "protocol_declaration";
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
/** Java declarations that push a scope segment — mirrors extract.ts's JAVA_KINDS. */
|
|
229
|
+
const JAVA_DEF_TYPES = new Set([
|
|
230
|
+
"class_declaration",
|
|
231
|
+
"interface_declaration",
|
|
232
|
+
"enum_declaration",
|
|
233
|
+
"record_declaration",
|
|
234
|
+
"annotation_type_declaration",
|
|
235
|
+
"annotation_type_element_declaration",
|
|
236
|
+
"method_declaration",
|
|
237
|
+
"constructor_declaration",
|
|
238
|
+
]);
|
|
239
|
+
/** The subset of the above that owns `this.field` bindings. */
|
|
240
|
+
const JAVA_TYPE_DECLS = new Set([
|
|
241
|
+
"class_declaration",
|
|
242
|
+
"interface_declaration",
|
|
243
|
+
"enum_declaration",
|
|
244
|
+
"record_declaration",
|
|
245
|
+
"annotation_type_declaration",
|
|
246
|
+
]);
|
|
247
|
+
/** Pass 1 over a parsed file: collect variable->type bindings. Pure. */
|
|
248
|
+
export function collectBindings(root, lang) {
|
|
249
|
+
const bindings = new FileBindings();
|
|
250
|
+
const aliases = new Map();
|
|
251
|
+
collectAliases(root, lang, aliases);
|
|
252
|
+
visit(root, lang, [], null, bindings, aliases);
|
|
253
|
+
return bindings;
|
|
254
|
+
}
|
|
255
|
+
/** Import aliases (`... as F`) can be declared anywhere relative to their use
|
|
256
|
+
* textually, so this scans the whole tree once, ahead of the scope-aware walk. */
|
|
257
|
+
function collectAliases(node, lang, aliases) {
|
|
258
|
+
if (lang === "python" && node.type === "aliased_import") {
|
|
259
|
+
const nameNode = node.childForFieldName("name");
|
|
260
|
+
const aliasNode = node.childForFieldName("alias");
|
|
261
|
+
if (nameNode && aliasNode) {
|
|
262
|
+
const orig = nameNode.type === "dotted_name" ? (nameNode.namedChildren.at(-1)?.text ?? nameNode.text) : nameNode.text;
|
|
263
|
+
aliases.set(aliasNode.text, orig);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
else if ((lang === "typescript" || lang === "tsx") && node.type === "import_specifier") {
|
|
267
|
+
const nameNode = node.childForFieldName("name");
|
|
268
|
+
const aliasNode = node.childForFieldName("alias");
|
|
269
|
+
if (nameNode && aliasNode)
|
|
270
|
+
aliases.set(aliasNode.text, nameNode.text);
|
|
271
|
+
}
|
|
272
|
+
for (const child of node.namedChildren)
|
|
273
|
+
collectAliases(child, lang, aliases);
|
|
274
|
+
}
|
|
275
|
+
/** `scope`/`classScope` mirror extract.ts's walk: `scope` is the enclosing
|
|
276
|
+
* definition-name stack; `classScope` is the nearest enclosing class's scope
|
|
277
|
+
* path (distinct from `scope` once we're inside one of its methods) — that's
|
|
278
|
+
* where `self.attr`/`this.attr` bindings live. */
|
|
279
|
+
function visit(node, lang, scope, classScope, bindings, aliases) {
|
|
280
|
+
if (lang === "python")
|
|
281
|
+
handlePy(node, scope, classScope, bindings, aliases);
|
|
282
|
+
else if (lang === "go")
|
|
283
|
+
handleGo(node, scope, bindings);
|
|
284
|
+
// R Phase 1 has no classes, so there's no member/receiver-type binding to
|
|
285
|
+
// collect yet (see extract.ts's calleeName R branch) — no handleR needed.
|
|
286
|
+
else if (lang === "r")
|
|
287
|
+
void 0;
|
|
288
|
+
else if (lang === "java")
|
|
289
|
+
handleJava(node, scope, classScope, bindings);
|
|
290
|
+
else if (lang === "swift")
|
|
291
|
+
handleSwift(node, scope, classScope, bindings);
|
|
292
|
+
else if (lang === "php")
|
|
293
|
+
handlePhp(node, scope, bindings);
|
|
294
|
+
else
|
|
295
|
+
handleTs(node, scope, classScope, bindings, aliases);
|
|
296
|
+
const name = defName(node, lang);
|
|
297
|
+
let childScope = scope;
|
|
298
|
+
let childClassScope = classScope;
|
|
299
|
+
if (name !== null) {
|
|
300
|
+
childScope = [...scope, name];
|
|
301
|
+
if (isClassNode(node, lang))
|
|
302
|
+
childClassScope = childScope.join(".");
|
|
303
|
+
}
|
|
304
|
+
for (const child of node.namedChildren)
|
|
305
|
+
visit(child, lang, childScope, childClassScope, bindings, aliases);
|
|
306
|
+
}
|
|
307
|
+
/** Resolves a bare type name through `aliases` — every annotation path must
|
|
308
|
+
* consult it, so an aliased import (`import Foo as Bar`) still binds to the
|
|
309
|
+
* original name callers actually search for. See the "aliases already
|
|
310
|
+
* resolved" contract above. */
|
|
311
|
+
function resolveAlias(name, aliases) {
|
|
312
|
+
return aliases.get(name) ?? name;
|
|
313
|
+
}
|
|
314
|
+
function pyTypeName(node, aliases) {
|
|
315
|
+
if (!node)
|
|
316
|
+
return null;
|
|
317
|
+
if (node.type === "identifier")
|
|
318
|
+
return resolveAlias(node.text, aliases);
|
|
319
|
+
if (node.type === "type") {
|
|
320
|
+
const inner = node.namedChildren[0];
|
|
321
|
+
return inner?.type === "identifier" ? resolveAlias(inner.text, aliases) : null;
|
|
322
|
+
}
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
function callTypeName(node, aliases) {
|
|
326
|
+
if (node?.type !== "call")
|
|
327
|
+
return null;
|
|
328
|
+
const fn = node.childForFieldName("function");
|
|
329
|
+
if (fn?.type !== "identifier")
|
|
330
|
+
return null;
|
|
331
|
+
return aliases.get(fn.text) ?? fn.text;
|
|
332
|
+
}
|
|
333
|
+
/** Swift variable->type bindings from the confident, syntax-local clues:
|
|
334
|
+
* a typed parameter (`func feed(animal: Animal)`, `init(keeper k: Keeper)` —
|
|
335
|
+
* the LAST simple_identifier before the `:` is the local name, the first may be
|
|
336
|
+
* an external argument label), a typed property (`var d: Doctor`), and an
|
|
337
|
+
* initializer-call assignment (`let vet = Vet()` — an initializer call is an
|
|
338
|
+
* ordinary call whose callee is the type's own UpperCamelCase name; Swift's
|
|
339
|
+
* naming convention makes the case split reliable, the same way Go's `NewX`
|
|
340
|
+
* convention is trusted in handleGo). A property directly inside a type body is
|
|
341
|
+
* a field: bound at the type's scope, both bare (`repo.save()`) and
|
|
342
|
+
* `self.`-prefixed (`self.repo.save()`), like Java's fields. */
|
|
343
|
+
function handleSwift(node, scope, classScope, bindings) {
|
|
344
|
+
const scopePath = scope.join(".");
|
|
345
|
+
if (node.type === "parameter") {
|
|
346
|
+
const ids = node.namedChildren.filter((c) => c.type === "simple_identifier");
|
|
347
|
+
const name = ids.at(-1)?.text;
|
|
348
|
+
const type = swiftTypeName(node.namedChildren.find((c) => c.type === "user_type" || c.type === "optional_type"));
|
|
349
|
+
if (name && type)
|
|
350
|
+
bindings.set(scopePath, name, type);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
if (node.type !== "property_declaration")
|
|
354
|
+
return;
|
|
355
|
+
const name = node.namedChildren
|
|
356
|
+
.find((c) => c.type === "pattern")
|
|
357
|
+
?.namedChildren.find((c) => c.type === "simple_identifier")?.text;
|
|
358
|
+
if (!name)
|
|
359
|
+
return;
|
|
360
|
+
const annotated = node.namedChildren
|
|
361
|
+
.find((c) => c.type === "type_annotation")
|
|
362
|
+
?.namedChildren.find((c) => c.type === "user_type" || c.type === "optional_type");
|
|
363
|
+
const type = swiftTypeName(annotated) ??
|
|
364
|
+
swiftCtorTypeName(node.namedChildren.find((c) => c.type === "call_expression"));
|
|
365
|
+
if (!type)
|
|
366
|
+
return;
|
|
367
|
+
const isField = node.parent?.type === "class_body" || node.parent?.type === "protocol_body";
|
|
368
|
+
const target = isField ? (classScope ?? scopePath) : scopePath;
|
|
369
|
+
bindings.set(target, name, type);
|
|
370
|
+
if (isField)
|
|
371
|
+
bindings.set(target, `self.${name}`, type);
|
|
372
|
+
}
|
|
373
|
+
/** A Swift type node's bare name: a `user_type`'s LAST type_identifier (so a
|
|
374
|
+
* module-qualified `Foundation.Date` binds as `Date`, generic arguments live in
|
|
375
|
+
* nested nodes and never leak in), unwrapping one level of optional (`Animal?`).
|
|
376
|
+
* Collections, tuples, and function types bind nothing — no single confident
|
|
377
|
+
* receiver type to name. */
|
|
378
|
+
function swiftTypeName(node) {
|
|
379
|
+
if (!node)
|
|
380
|
+
return null;
|
|
381
|
+
if (node.type === "optional_type") {
|
|
382
|
+
return swiftTypeName(node.namedChildren.find((c) => c.type === "user_type"));
|
|
383
|
+
}
|
|
384
|
+
if (node.type !== "user_type")
|
|
385
|
+
return null;
|
|
386
|
+
const ids = node.namedChildren.filter((c) => c.type === "type_identifier");
|
|
387
|
+
return ids.at(-1)?.text ?? null;
|
|
388
|
+
}
|
|
389
|
+
/** The type constructed by an initializer call (`Vet()` → `Vet`), or null when
|
|
390
|
+
* the callee isn't a bare UpperCamelCase name — a lowercase callee is an
|
|
391
|
+
* ordinary function whose return type a single-file pass cannot know. */
|
|
392
|
+
function swiftCtorTypeName(call) {
|
|
393
|
+
if (call?.type !== "call_expression")
|
|
394
|
+
return null;
|
|
395
|
+
const fn = call.namedChildren[0];
|
|
396
|
+
if (fn?.type !== "simple_identifier")
|
|
397
|
+
return null;
|
|
398
|
+
return /^[A-Z]/.test(fn.text) ? fn.text : null;
|
|
399
|
+
}
|
|
400
|
+
/** PHP variable->type bindings from the two confident, syntax-local clues:
|
|
401
|
+
* a type-hinted parameter (`function f(Foo $x)`) and a `new` assignment
|
|
402
|
+
* (`$x = new Foo()`). Keyed by the `$var` text (with the `$`) so a
|
|
403
|
+
* `$var->method()` call site resolves through resolveRecvType's bindings
|
|
404
|
+
* lookup, exactly like Python's annotated params and Go's receiver. */
|
|
405
|
+
function handlePhp(node, scope, bindings) {
|
|
406
|
+
if (node.type === "simple_parameter") {
|
|
407
|
+
const type = phpTypeName(node.childForFieldName("type"));
|
|
408
|
+
const name = node.childForFieldName("name");
|
|
409
|
+
if (type && name?.type === "variable_name")
|
|
410
|
+
bindings.set(scope.join("."), name.text, type);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
if (node.type === "assignment_expression") {
|
|
414
|
+
const left = node.childForFieldName("left");
|
|
415
|
+
const right = node.childForFieldName("right");
|
|
416
|
+
if (left?.type === "variable_name" && right?.type === "object_creation_expression") {
|
|
417
|
+
const type = phpNewType(right);
|
|
418
|
+
if (type)
|
|
419
|
+
bindings.set(scope.join("."), left.text, type);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/** Closure name, duplicated from extract.ts's `phpClosureName` (this file must
|
|
424
|
+
* not value-import extract.ts) so the two scope stacks agree on the segment a
|
|
425
|
+
* closure pushes. The right-hand-side check compares node `.id` rather than
|
|
426
|
+
* `===` on wrappers for the same reason as extract.ts: wrapper identity is not
|
|
427
|
+
* stable across traversals, so `===` can spuriously fall through to `{closure}`
|
|
428
|
+
* and desync this scope segment from the one extract.ts mints. */
|
|
429
|
+
function phpClosureName(node) {
|
|
430
|
+
const parent = node.parent;
|
|
431
|
+
if (parent?.type === "assignment_expression" && parent.childForFieldName("right")?.id === node.id) {
|
|
432
|
+
const left = parent.childForFieldName("left");
|
|
433
|
+
if (left?.type === "variable_name")
|
|
434
|
+
return left.text.replace(/^\$/, "");
|
|
435
|
+
}
|
|
436
|
+
return "{closure}";
|
|
437
|
+
}
|
|
438
|
+
/** A PHP type hint's class name: unwrap `?T` (optional_type) and `named_type`,
|
|
439
|
+
* de-qualify a namespaced name to its trailing segment. Null for primitives,
|
|
440
|
+
* unions, and intersections (no single confident class to bind). */
|
|
441
|
+
function phpTypeName(node) {
|
|
442
|
+
if (!node)
|
|
443
|
+
return null;
|
|
444
|
+
if (node.type === "named_type" || node.type === "optional_type") {
|
|
445
|
+
return phpTypeName(node.namedChildren[0] ?? null);
|
|
446
|
+
}
|
|
447
|
+
if (node.type === "name")
|
|
448
|
+
return node.text;
|
|
449
|
+
if (node.type === "qualified_name")
|
|
450
|
+
return node.text.replace(/^.*\\/, "");
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
/** The class name of a `new Foo()` / `new App\Foo()`, de-qualified. */
|
|
454
|
+
function phpNewType(node) {
|
|
455
|
+
const cls = node.namedChildren.find((c) => c.type === "name" || c.type === "qualified_name");
|
|
456
|
+
return cls ? cls.text.replace(/^.*\\/, "") : null;
|
|
457
|
+
}
|
|
458
|
+
function handlePy(node, scope, classScope, bindings, aliases) {
|
|
459
|
+
const scopePath = scope.join(".");
|
|
460
|
+
if (node.type === "typed_parameter") {
|
|
461
|
+
const nameNode = node.namedChildren.find((c) => c.type === "identifier");
|
|
462
|
+
const typeName = pyTypeName(node.childForFieldName("type"), aliases);
|
|
463
|
+
if (nameNode && typeName)
|
|
464
|
+
bindings.set(scopePath, nameNode.text, typeName);
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
if (node.type !== "assignment")
|
|
468
|
+
return;
|
|
469
|
+
const left = node.childForFieldName("left");
|
|
470
|
+
const right = node.childForFieldName("right");
|
|
471
|
+
if (!left)
|
|
472
|
+
return;
|
|
473
|
+
if (left.type === "identifier") {
|
|
474
|
+
const typeField = node.childForFieldName("type");
|
|
475
|
+
const typeName = typeField ? pyTypeName(typeField, aliases) : callTypeName(right, aliases);
|
|
476
|
+
if (typeName)
|
|
477
|
+
bindings.set(scopePath, left.text, typeName);
|
|
478
|
+
}
|
|
479
|
+
else if (left.type === "attribute") {
|
|
480
|
+
const obj = left.childForFieldName("object");
|
|
481
|
+
const attr = left.childForFieldName("attribute");
|
|
482
|
+
if (obj?.type === "identifier" && (obj.text === "self" || obj.text === "cls") && attr) {
|
|
483
|
+
const typeName = callTypeName(right, aliases);
|
|
484
|
+
if (typeName)
|
|
485
|
+
bindings.set(classScope ?? scopePath, `self.${attr.text}`, typeName);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
function tsAnnotationTypeName(typeAnn, aliases) {
|
|
490
|
+
if (!typeAnn || typeAnn.type !== "type_annotation")
|
|
491
|
+
return null;
|
|
492
|
+
const t = typeAnn.namedChildren[0];
|
|
493
|
+
return t?.type === "type_identifier" ? resolveAlias(t.text, aliases) : null;
|
|
494
|
+
}
|
|
495
|
+
function tsNewTypeName(value, aliases) {
|
|
496
|
+
if (value?.type !== "new_expression")
|
|
497
|
+
return null;
|
|
498
|
+
const ctor = value.childForFieldName("constructor");
|
|
499
|
+
if (ctor?.type !== "identifier")
|
|
500
|
+
return null;
|
|
501
|
+
return aliases.get(ctor.text) ?? ctor.text;
|
|
502
|
+
}
|
|
503
|
+
function handleTs(node, scope, classScope, bindings, aliases) {
|
|
504
|
+
const scopePath = scope.join(".");
|
|
505
|
+
if (node.type === "variable_declarator") {
|
|
506
|
+
const value = node.childForFieldName("value");
|
|
507
|
+
if (value && FN_VALUE_TYPES.has(value.type))
|
|
508
|
+
return; // a function def, not a type binding
|
|
509
|
+
const name = node.childForFieldName("name");
|
|
510
|
+
if (name?.type !== "identifier")
|
|
511
|
+
return;
|
|
512
|
+
const typeName = tsNewTypeName(value, aliases) ?? tsAnnotationTypeName(node.childForFieldName("type"), aliases);
|
|
513
|
+
if (typeName)
|
|
514
|
+
bindings.set(scopePath, name.text, typeName);
|
|
515
|
+
}
|
|
516
|
+
else if (node.type === "public_field_definition") {
|
|
517
|
+
const name = node.childForFieldName("name");
|
|
518
|
+
if (!name)
|
|
519
|
+
return;
|
|
520
|
+
const typeName = tsAnnotationTypeName(node.childForFieldName("type"), aliases) ??
|
|
521
|
+
tsNewTypeName(node.childForFieldName("value"), aliases);
|
|
522
|
+
if (typeName)
|
|
523
|
+
bindings.set(classScope ?? scopePath, `this.${name.text}`, typeName);
|
|
524
|
+
}
|
|
525
|
+
else if (node.type === "required_parameter") {
|
|
526
|
+
const pattern = node.childForFieldName("pattern");
|
|
527
|
+
if (pattern?.type !== "identifier")
|
|
528
|
+
return;
|
|
529
|
+
const typeName = tsAnnotationTypeName(node.childForFieldName("type"), aliases);
|
|
530
|
+
if (!typeName)
|
|
531
|
+
return;
|
|
532
|
+
bindings.set(scopePath, pattern.text, typeName);
|
|
533
|
+
// A parameter PROPERTY (`constructor(private readonly svc: Svc){}`) is a parameter
|
|
534
|
+
// AND a class field, so `this.svc` must resolve to its type — the default DI idiom
|
|
535
|
+
// in NestJS/Angular. The plain-parameter binding above keys on the bare name and at
|
|
536
|
+
// the constructor scope, which `this.svc.method()` call sites never reach; without
|
|
537
|
+
// the field-style binding here their recvType is undefined and the call edge is
|
|
538
|
+
// dropped (#76). Detected by the modifier child a plain parameter never carries.
|
|
539
|
+
const isParamProperty = node.children.some((c) => c.type === "accessibility_modifier" || c.type === "readonly" || c.type === "override_modifier");
|
|
540
|
+
if (isParamProperty)
|
|
541
|
+
bindings.set(classScope ?? scopePath, `this.${pattern.text}`, typeName);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Java bindings: locals, parameters, and fields.
|
|
546
|
+
*
|
|
547
|
+
* Java looks like the easy case — it is statically typed, so a declaration states
|
|
548
|
+
* its own type with no inference needed. In practice modern Java leans on `var`,
|
|
549
|
+
* which carries no type at the declaration site. Upstream's documented limit was
|
|
550
|
+
* that a `var` local's member calls stay unresolved; this pass recovers them by
|
|
551
|
+
* falling back to a `new X()` initializer when the declared type is absent or
|
|
552
|
+
* `var`, covering locals, fields, and try-with-resources the same way.
|
|
553
|
+
*
|
|
554
|
+
* Varargs (`String... xs`), try-with-resources (`try (Foo f = ...)`),
|
|
555
|
+
* enhanced-for (`for (Foo x : xs)`), and catch parameters (`catch (E e)`) also
|
|
556
|
+
* bind their names, so a member call on any of them resolves through the bound
|
|
557
|
+
* type rather than falling back to name-only resolution.
|
|
558
|
+
*
|
|
559
|
+
* Fields are recorded twice: bare (`repo.save()`) and `self.`-prefixed
|
|
560
|
+
* (`this.repo.save()`), since resolveRecvType normalizes `this.` to `self.`.
|
|
561
|
+
*/
|
|
562
|
+
function handleJava(node, scope, classScope, bindings) {
|
|
563
|
+
const scopePath = scope.join(".");
|
|
564
|
+
// formal_parameter: `Foo bar` in method/constructor signatures
|
|
565
|
+
if (node.type === "formal_parameter") {
|
|
566
|
+
const type = javaTypeName(node.childForFieldName("type"));
|
|
567
|
+
const name = node.childForFieldName("name");
|
|
568
|
+
if (type && name?.type === "identifier")
|
|
569
|
+
bindings.set(scopePath, name.text, type);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
// spread_parameter (varargs): `Foo... args` — tree-sitter gives this a distinct
|
|
573
|
+
// node type with no field names; the type is the first named child and the name
|
|
574
|
+
// lives inside a `variable_declarator`.
|
|
575
|
+
if (node.type === "spread_parameter") {
|
|
576
|
+
const typeNode = node.namedChildren.find((c) => c.type !== "variable_declarator");
|
|
577
|
+
const name = node.namedChildren.find((c) => c.type === "variable_declarator")?.childForFieldName("name");
|
|
578
|
+
const type = javaTypeName(typeNode);
|
|
579
|
+
if (type && name?.type === "identifier")
|
|
580
|
+
bindings.set(scopePath, name.text, type);
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
// resource (try-with-resources): `try (Foo f = new Foo())` — the `resource` node
|
|
584
|
+
// has `type`, `name`, and `value` fields, binding like a local. `var f = new Foo()`
|
|
585
|
+
// falls back to the constructed type.
|
|
586
|
+
if (node.type === "resource") {
|
|
587
|
+
const name = node.childForFieldName("name");
|
|
588
|
+
const type = javaTypeName(node.childForFieldName("type")) ?? javaNewTypeName(node.childForFieldName("value"));
|
|
589
|
+
if (type && name?.type === "identifier")
|
|
590
|
+
bindings.set(scopePath, name.text, type);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
// enhanced_for_statement: `for (Foo f : items)` — the loop variable `f` is typed
|
|
594
|
+
// by the `type` field; bind it under the lexical scope so `f.method()` inside the
|
|
595
|
+
// loop body resolves.
|
|
596
|
+
if (node.type === "enhanced_for_statement") {
|
|
597
|
+
const name = node.childForFieldName("name");
|
|
598
|
+
const type = javaTypeName(node.childForFieldName("type"));
|
|
599
|
+
if (type && name?.type === "identifier")
|
|
600
|
+
bindings.set(scopePath, name.text, type);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
// catch_formal_parameter: `catch (Exception e)` — tree-sitter gives this a
|
|
604
|
+
// distinct node type (not `formal_parameter`); the type lives in a `catch_type`
|
|
605
|
+
// child (which holds one `type_identifier`, or several for multi-catch
|
|
606
|
+
// `IOException | BizException` — bind the first).
|
|
607
|
+
if (node.type === "catch_formal_parameter") {
|
|
608
|
+
const name = node.childForFieldName("name");
|
|
609
|
+
const catchType = node.namedChildren.find((c) => c.type === "catch_type");
|
|
610
|
+
const typeNode = catchType?.namedChildren.find((c) => c.type === "type_identifier" || c.type === "scoped_type_identifier" || c.type === "identifier");
|
|
611
|
+
const type = javaTypeName(typeNode);
|
|
612
|
+
if (type && name?.type === "identifier")
|
|
613
|
+
bindings.set(scopePath, name.text, type);
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
if (node.type !== "local_variable_declaration" && node.type !== "field_declaration")
|
|
617
|
+
return;
|
|
618
|
+
const isField = node.type === "field_declaration";
|
|
619
|
+
const target = isField ? (classScope ?? scopePath) : scopePath;
|
|
620
|
+
for (const d of node.namedChildren) {
|
|
621
|
+
if (d.type !== "variable_declarator")
|
|
622
|
+
continue;
|
|
623
|
+
const name = d.childForFieldName("name");
|
|
624
|
+
if (name?.type !== "identifier")
|
|
625
|
+
continue;
|
|
626
|
+
// Declared type first; fall back to a `new X()` initializer when the type is
|
|
627
|
+
// absent or `var` (upstream's documented limit) — recovers the common
|
|
628
|
+
// `var x = new Foo()` shape without guessing at call-return inference.
|
|
629
|
+
const type = javaTypeName(node.childForFieldName("type")) ?? javaNewTypeName(d.childForFieldName("value"));
|
|
630
|
+
if (!type)
|
|
631
|
+
continue;
|
|
632
|
+
bindings.set(target, name.text, type);
|
|
633
|
+
if (isField)
|
|
634
|
+
bindings.set(target, `self.${name.text}`, type);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
/** A Java type node's bare name. `var` is the inferred-local keyword and states no
|
|
638
|
+
* type, so it binds nothing. A generic binds to its erasure (`List<Order>` → `List`),
|
|
639
|
+
* a qualified type to its final segment (`java.util.List` → `List`), and an array
|
|
640
|
+
* to its element type (`Foo[]` → `Foo`). */
|
|
641
|
+
function javaTypeName(node) {
|
|
642
|
+
if (!node)
|
|
643
|
+
return null;
|
|
644
|
+
if (node.type === "type_identifier")
|
|
645
|
+
return node.text === "var" ? null : node.text;
|
|
646
|
+
if (node.type === "generic_type") {
|
|
647
|
+
const base = node.namedChildren[0];
|
|
648
|
+
return base ? javaTypeName(base) : null;
|
|
649
|
+
}
|
|
650
|
+
if (node.type === "scoped_type_identifier") {
|
|
651
|
+
return node.namedChildren.at(-1)?.text ?? null;
|
|
652
|
+
}
|
|
653
|
+
if (node.type === "array_type") {
|
|
654
|
+
const el = node.childForFieldName("element") ?? node.namedChildren.find((c) => c.type !== "dimensions");
|
|
655
|
+
return el ? javaTypeName(el) : null;
|
|
656
|
+
}
|
|
657
|
+
return null;
|
|
658
|
+
}
|
|
659
|
+
/** The type constructed by a `new X(...)` expression, or null when the value is
|
|
660
|
+
* not an `object_creation_expression` (or the constructed type isn't a bare
|
|
661
|
+
* `type_identifier`/`scoped_type_identifier`/`generic_type`). Used as the
|
|
662
|
+
* fallback for a `var`-typed or untyped local/field/resource whose initializer
|
|
663
|
+
* is a construction — the one shape a single-file pass can infer with no
|
|
664
|
+
* return-type analysis. */
|
|
665
|
+
function javaNewTypeName(value) {
|
|
666
|
+
if (value?.type !== "object_creation_expression")
|
|
667
|
+
return null;
|
|
668
|
+
return javaTypeName(value.childForFieldName("type"));
|
|
669
|
+
}
|
|
670
|
+
function handleGo(node, scope, bindings) {
|
|
671
|
+
const scopePath = scope.join(".");
|
|
672
|
+
if (node.type === "var_spec") {
|
|
673
|
+
const name = node.childForFieldName("name");
|
|
674
|
+
let type = node.childForFieldName("type");
|
|
675
|
+
if (type?.type === "pointer_type")
|
|
676
|
+
type = type.namedChildren.at(-1) ?? null;
|
|
677
|
+
if (name?.type === "identifier" && type?.type === "type_identifier") {
|
|
678
|
+
bindings.set(scopePath, name.text, type.text);
|
|
679
|
+
}
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
if (node.type !== "short_var_declaration")
|
|
683
|
+
return;
|
|
684
|
+
const left = node.childForFieldName("left");
|
|
685
|
+
const right = node.childForFieldName("right");
|
|
686
|
+
if (!left || !right)
|
|
687
|
+
return;
|
|
688
|
+
const names = left.namedChildren;
|
|
689
|
+
const exprs = right.namedChildren;
|
|
690
|
+
for (let i = 0; i < names.length; i++) {
|
|
691
|
+
const nameNode = names[i];
|
|
692
|
+
let expr = exprs[i];
|
|
693
|
+
if (!nameNode || nameNode.type !== "identifier" || !expr)
|
|
694
|
+
continue;
|
|
695
|
+
if (expr.type === "unary_expression") {
|
|
696
|
+
expr = expr.namedChildren.find((c) => c.type === "composite_literal") ?? expr;
|
|
697
|
+
}
|
|
698
|
+
let typeName = null;
|
|
699
|
+
if (expr.type === "composite_literal") {
|
|
700
|
+
const t = expr.childForFieldName("type");
|
|
701
|
+
typeName = t?.type === "type_identifier" ? t.text : null;
|
|
702
|
+
}
|
|
703
|
+
else if (expr.type === "call_expression") {
|
|
704
|
+
const fn = expr.childForFieldName("function");
|
|
705
|
+
// Go convention: NewX(...) binds to X.
|
|
706
|
+
if (fn?.type === "identifier" && /^New[A-Z]/.test(fn.text))
|
|
707
|
+
typeName = fn.text.slice(3);
|
|
708
|
+
}
|
|
709
|
+
if (typeName)
|
|
710
|
+
bindings.set(scopePath, nameNode.text, typeName);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
//# sourceMappingURL=bindings.js.map
|