@backbencher/brain 0.0.0-stage → 0.1.1
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/CHANGELOG.md +298 -0
- package/EMBEDDINGS.md +355 -0
- package/LICENSE +21 -0
- package/README.md +415 -2
- package/bin/bb +13 -0
- package/dist/analysis-exclusions-7ZJDXOVZ.js +35 -0
- package/dist/brain-index-health-Q5APTJQL.js +17 -0
- package/dist/brain-relationship-enrichment-MYR2AM4F.js +558 -0
- package/dist/brain.sql-EIM4WS4D.js +29 -0
- package/dist/chunk-22V37YTK.js +1758 -0
- package/dist/chunk-2BSKD7O3.js +40 -0
- package/dist/chunk-2DE27DVC.js +1314 -0
- package/dist/chunk-2RRBMNBQ.js +322 -0
- package/dist/chunk-2WXYNLBA.js +29 -0
- package/dist/chunk-3CTFIJJB.js +17 -0
- package/dist/chunk-3ZTOHHSW.js +2104 -0
- package/dist/chunk-4H22TLOT.js +543 -0
- package/dist/chunk-5BVAH26D.js +340 -0
- package/dist/chunk-62DHLYW6.js +3427 -0
- package/dist/chunk-7AN7U5IZ.js +371 -0
- package/dist/chunk-7DRPNVIN.js +782 -0
- package/dist/chunk-7MBYT777.js +174 -0
- package/dist/chunk-AHDWGM7Q.js +236 -0
- package/dist/chunk-B5GEAAYF.js +818 -0
- package/dist/chunk-BEIZZ73B.js +1479 -0
- package/dist/chunk-BQ3OVQ3P.js +125 -0
- package/dist/chunk-D2Q4Y47A.js +53 -0
- package/dist/chunk-DIYAGQJL.js +34 -0
- package/dist/chunk-DWKXZ6IF.js +336 -0
- package/dist/chunk-DYM4FQEE.js +90 -0
- package/dist/chunk-ENW4BTBA.js +930 -0
- package/dist/chunk-EWMWK7WN.js +75 -0
- package/dist/chunk-EY5ZZUUA.js +626 -0
- package/dist/chunk-GBI7V7KY.js +69 -0
- package/dist/chunk-GEFFO6O2.js +152 -0
- package/dist/chunk-HJEWO5EV.js +247 -0
- package/dist/chunk-HQSPJDHI.js +613 -0
- package/dist/chunk-KAET47ZL.js +125 -0
- package/dist/chunk-KCDECRJY.js +440 -0
- package/dist/chunk-L5TDYKYK.js +76 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-NO3U3FJQ.js +201 -0
- package/dist/chunk-OWISBAOF.js +61 -0
- package/dist/chunk-QKTRECYS.js +1119 -0
- package/dist/chunk-QLK6ED4Q.js +235 -0
- package/dist/chunk-R2GW4F6R.js +19 -0
- package/dist/chunk-RCMTFSEF.js +87 -0
- package/dist/chunk-RM3PY6TG.js +376 -0
- package/dist/chunk-ROMM6KMC.js +433 -0
- package/dist/chunk-SGGCSHAX.js +12050 -0
- package/dist/chunk-SK6YVHFZ.js +211 -0
- package/dist/chunk-SM7RFQRO.js +214 -0
- package/dist/chunk-UGR4QIGS.js +67 -0
- package/dist/chunk-UQNQZXHY.js +711 -0
- package/dist/chunk-UUNHHX4M.js +13 -0
- package/dist/chunk-VL52PL2T.js +71 -0
- package/dist/chunk-WIG36E67.js +196 -0
- package/dist/chunk-XHK3WWGB.js +7436 -0
- package/dist/chunk-XTQM2IP3.js +2863 -0
- package/dist/chunk-ZE2LG76D.js +1296 -0
- package/dist/chunk-ZETTGPAW.js +6950 -0
- package/dist/cli/index.js +37 -0
- package/dist/config-HZAAYDP3.js +10 -0
- package/dist/content-search-7XIP555Q.js +593 -0
- package/dist/database-76RP44JG.js +9 -0
- package/dist/doctor-ANGETYMN.js +395 -0
- package/dist/edit-engine-CG72LDZD.js +51 -0
- package/dist/engine-BKEOGN7N.js +11 -0
- package/dist/engine-VIW6NSKO.js +18 -0
- package/dist/fingerprint-OBLIMZLP.js +33 -0
- package/dist/framework-intelligence-3LORTPOX.js +860 -0
- package/dist/freshness-3K6VU5OT.js +174 -0
- package/dist/graph-engine-HBSQNPTB.js +21 -0
- package/dist/graph_request-Q6NKB6N2.js +350 -0
- package/dist/impact_request-LYP672WE.js +68 -0
- package/dist/index-space-IUUN5WYV.js +15 -0
- package/dist/index-status-7OVGYSGW.js +34 -0
- package/dist/index.js +159 -0
- package/dist/instance-FO6QZRLH.js +19 -0
- package/dist/language-detection-DFCAU5DZ.js +11 -0
- package/dist/lsp/server.js +4301 -0
- package/dist/mcp/server.js +132 -0
- package/dist/onboard-DIQZV2NW.js +161 -0
- package/dist/override-companion-pass-XR7MHTP7.js +117 -0
- package/dist/parallel-indexer-FK2XKZXY.js +88 -0
- package/dist/pool-worker.js +1153 -0
- package/dist/project-health-6XPENVAA.js +94 -0
- package/dist/project-index-5SDPHITE.js +57 -0
- package/dist/project-registry-ZJ3DVUGO.js +355 -0
- package/dist/real-bash-analyzer-EJAU5LW5.js +2201 -0
- package/dist/real-c-analyzer-HBD3FNNH.js +5942 -0
- package/dist/real-clean-analyzer-4EEZLPV5.js +3470 -0
- package/dist/real-clojure-analyzer-Q55EBOO2.js +2818 -0
- package/dist/real-cpp-analyzer-IVVOD25R.js +4101 -0
- package/dist/real-csharp-analyzer-ZBNLNJZJ.js +3298 -0
- package/dist/real-css-analyzer-6XRQLUN7.js +15 -0
- package/dist/real-dart-analyzer-OLR72EFW.js +3944 -0
- package/dist/real-elixir-analyzer-MQWGAH2I.js +2192 -0
- package/dist/real-erlang-analyzer-7BVPQEHO.js +1731 -0
- package/dist/real-fsharp-analyzer-C2UPFNOA.js +2390 -0
- package/dist/real-go-analyzer-UKGI43YS.js +4126 -0
- package/dist/real-graphql-analyzer-VE2EEFII.js +1442 -0
- package/dist/real-groovy-analyzer-W26VACFW.js +2285 -0
- package/dist/real-haskell-analyzer-5CVVAJRX.js +2533 -0
- package/dist/real-hcl-analyzer-5ZT4U43N.js +725 -0
- package/dist/real-html-analyzer-JWNX3C6I.js +1759 -0
- package/dist/real-java-analyzer-GU42VBGQ.js +4677 -0
- package/dist/real-javascript-analyzer-QA4QOJ6W.js +14 -0
- package/dist/real-json-analyzer-MPA6PRXL.js +1640 -0
- package/dist/real-julia-analyzer-22CWYQMN.js +2085 -0
- package/dist/real-kotlin-analyzer-QDZJLXXU.js +3956 -0
- package/dist/real-lua-analyzer-G7NHLYKS.js +1957 -0
- package/dist/real-makefile-analyzer-OCY3GT5N.js +920 -0
- package/dist/real-markdown-analyzer-TEJK2JXJ.js +1215 -0
- package/dist/real-matlab-analyzer-Q5SWLN7Z.js +480 -0
- package/dist/real-nim-analyzer-YLXSK563.js +3603 -0
- package/dist/real-objective-c-analyzer-D23ACC2R.js +1518 -0
- package/dist/real-perl-analyzer-WWTRHYDT.js +1865 -0
- package/dist/real-php-analyzer-JNKJHTCL.js +9368 -0
- package/dist/real-powershell-analyzer-XRSNQERV.js +2915 -0
- package/dist/real-protobuf-analyzer-3OKUCZ7T.js +867 -0
- package/dist/real-python-analyzer-VXAFWI72.js +4880 -0
- package/dist/real-r-analyzer-ZGAIDVI4.js +2596 -0
- package/dist/real-ruby-analyzer-X2KTLVBH.js +2429 -0
- package/dist/real-rust-analyzer-OFFHPL2A.js +3359 -0
- package/dist/real-scala-analyzer-TSTW27J6.js +3293 -0
- package/dist/real-scss-analyzer-AVWYPSOQ.js +1515 -0
- package/dist/real-solidity-analyzer-UCI2KWUB.js +2608 -0
- package/dist/real-sql-analyzer-F77ZMQXR.js +3840 -0
- package/dist/real-svelte-analyzer-SF7NRUO5.js +2532 -0
- package/dist/real-swift-analyzer-MN5QT3QN.js +2311 -0
- package/dist/real-toml-analyzer-66L7BDCQ.js +929 -0
- package/dist/real-typescript-analyzer-6KEMVDWQ.js +14 -0
- package/dist/real-vb-analyzer-VICVPOP7.js +3145 -0
- package/dist/real-vba-analyzer-HXLTTHKM.js +466 -0
- package/dist/real-vue-analyzer-QXR56CFV.js +2680 -0
- package/dist/real-xml-analyzer-YL465ZJW.js +2405 -0
- package/dist/real-yaml-analyzer-SUBCBNSI.js +3528 -0
- package/dist/real-zig-analyzer-HIQLZMGY.js +2430 -0
- package/dist/regex-search-NJKHMZNO.js +239 -0
- package/dist/rules-ACHPB7QU.js +152 -0
- package/dist/scoped-path-MJYWJZQX.js +11 -0
- package/dist/setup-show-NT5ZHYNE.js +15 -0
- package/dist/setup-wizard-G5YYR5T6.js +24 -0
- package/dist/symbol-search-GZJIM2J2.js +16 -0
- package/dist/taint-KXUHHPIE.js +202 -0
- package/dist/taint-analyzer-N7YLZU3N.js +163 -0
- package/dist/tool-handlers-OJDC35DI.js +72 -0
- package/dist/tool-registry-BPEJNSZG.js +17 -0
- package/dist/tool-validation-Q57YMMBX.js +32 -0
- package/dist/type-inference-QMT2RMLV.js +13 -0
- package/dist/vector-binary-LMY4QGAN.js +19 -0
- package/dist/version-ABP2TUL2.js +9 -0
- package/dist/wasm-NMWO3WXY.js +16 -0
- package/docs/EMBEDDINGS.md +132 -0
- package/docs/README.md +178 -0
- package/docs/data/m10-baseline.json +602 -0
- package/docs/data/m10-benchmark-baseline.json +57 -0
- package/docs/data/m10-benchmark-last-run.json +127 -0
- package/docs/data/m10-final-audit.json +215 -0
- package/docs/data/m12-final-audit.json +138 -0
- package/docs/data/m12-surface-matrix.json +50 -0
- package/docs/data/public-tools.json +1902 -0
- package/docs/indexing/DEAD-ASSETS.md +88 -0
- package/docs/indexing/INDEXER-REVIEW.md +634 -0
- package/docs/indexing/PERFORMANCE-FINDINGS.md +106 -0
- package/docs/indexing/README.md +427 -0
- package/docs/indexing/discovery-matrix.md +41 -0
- package/docs/indexing/embeddings.md +325 -0
- package/docs/indexing/environment-variables.md +77 -0
- package/docs/indexing/performance.md +323 -0
- package/docs/indexing/resume.md +345 -0
- package/docs/indexing/troubleshooting.md +391 -0
- package/docs/man/bb.1 +190 -0
- package/docs/tools/bb_analyze.md +147 -0
- package/docs/tools/bb_annotate.md +110 -0
- package/docs/tools/bb_annotations.md +106 -0
- package/docs/tools/bb_ask.md +101 -0
- package/docs/tools/bb_cross_language.md +103 -0
- package/docs/tools/bb_doc.md +169 -0
- package/docs/tools/bb_edit.md +185 -0
- package/docs/tools/bb_graph.md +169 -0
- package/docs/tools/bb_health.md +156 -0
- package/docs/tools/bb_impact.md +117 -0
- package/docs/tools/bb_index.md +108 -0
- package/docs/tools/bb_migrate.md +135 -0
- package/docs/tools/bb_patterns.md +140 -0
- package/docs/tools/bb_search.md +150 -0
- package/docs/tools/bb_security.md +100 -0
- package/docs/tools/bb_visualize.md +184 -0
- package/grammars/README.md +57 -0
- package/grammars/THIRD-PARTY-NOTICES.md +50 -0
- package/grammars/tree-sitter-c/LICENSE +21 -0
- package/grammars/tree-sitter-clojure/LICENSE.md +21 -0
- package/grammars/tree-sitter-cpp/LICENSE +21 -0
- package/grammars/tree-sitter-csharp/LICENSE +21 -0
- package/grammars/tree-sitter-css/LICENSE +21 -0
- package/grammars/tree-sitter-css/README.md +21 -0
- package/grammars/tree-sitter-dart/LICENSE +20 -0
- package/grammars/tree-sitter-dart-upstream/LICENSE +20 -0
- package/grammars/tree-sitter-dart-upstream/README.md +18 -0
- package/grammars/tree-sitter-elixir/LICENSE +176 -0
- package/grammars/tree-sitter-elixir/README.md +11 -0
- package/grammars/tree-sitter-fsharp/LICENSE +21 -0
- package/grammars/tree-sitter-fsharp/README.md +45 -0
- package/grammars/tree-sitter-graphql/LICENSE +21 -0
- package/grammars/tree-sitter-graphql/README.md +106 -0
- package/grammars/tree-sitter-groovy/LICENSE +21 -0
- package/grammars/tree-sitter-groovy/README.md +4 -0
- package/grammars/tree-sitter-haskell/LICENSE +21 -0
- package/grammars/tree-sitter-haskell/README.md +394 -0
- package/grammars/tree-sitter-hcl/CHANGELOG.md +102 -0
- package/grammars/tree-sitter-hcl/LICENSE +201 -0
- package/grammars/tree-sitter-hcl/README.md +39 -0
- package/grammars/tree-sitter-html/LICENSE +21 -0
- package/grammars/tree-sitter-html/README.md +21 -0
- package/grammars/tree-sitter-julia/LICENSE +21 -0
- package/grammars/tree-sitter-julia/README.md +24 -0
- package/grammars/tree-sitter-kotlin/LICENSE +9 -0
- package/grammars/tree-sitter-lua/LICENSE.md +21 -0
- package/grammars/tree-sitter-lua/README.md +29 -0
- package/grammars/tree-sitter-make/LICENSE +21 -0
- package/grammars/tree-sitter-matlab/LICENSE +19 -0
- package/grammars/tree-sitter-matlab/README.md +99 -0
- package/grammars/tree-sitter-nim/LICENSE +373 -0
- package/grammars/tree-sitter-nim/README.md +46 -0
- package/grammars/tree-sitter-objc/LICENSE +21 -0
- package/grammars/tree-sitter-objc/README.md +20 -0
- package/grammars/tree-sitter-perl/LICENSE +7 -0
- package/grammars/tree-sitter-perl/README.md +100 -0
- package/grammars/tree-sitter-powershell/LICENSE +21 -0
- package/grammars/tree-sitter-powershell/README.md +7 -0
- package/grammars/tree-sitter-proto/LICENSE +21 -0
- package/grammars/tree-sitter-proto/README.md +105 -0
- package/grammars/tree-sitter-r/LICENSE +9 -0
- package/grammars/tree-sitter-r/README.md +66 -0
- package/grammars/tree-sitter-ruby/LICENSE +22 -0
- package/grammars/tree-sitter-scss/LICENSE +21 -0
- package/grammars/tree-sitter-scss/README.md +17 -0
- package/grammars/tree-sitter-solidity/LICENSE +7 -0
- package/grammars/tree-sitter-sql/LICENSE +21 -0
- package/grammars/tree-sitter-typescript/LICENSE +21 -0
- package/grammars/tree-sitter-vba/LICENSE +21 -0
- package/grammars/tree-sitter-vba/README.md +738 -0
- package/grammars/tree-sitter-vbnet/LICENSE +21 -0
- package/grammars/tree-sitter-vbnet/README.md +322 -0
- package/grammars/tree-sitter-xml/LICENSE +19 -0
- package/grammars/tree-sitter-yaml/LICENSE +20 -0
- package/grammars/tree-sitter-yaml/README.md +21 -0
- package/package.json +184 -4
- package/wasm/dart.wasm +0 -0
- package/wasm/tree-sitter-bash.wasm +0 -0
- package/wasm/tree-sitter-c.wasm +0 -0
- package/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/wasm/tree-sitter-clean.wasm +0 -0
- package/wasm/tree-sitter-clojure.wasm +0 -0
- package/wasm/tree-sitter-core_schema.wasm +0 -0
- package/wasm/tree-sitter-cpp.wasm +0 -0
- package/wasm/tree-sitter-css.wasm +0 -0
- package/wasm/tree-sitter-dart.wasm +0 -0
- package/wasm/tree-sitter-elisp.wasm +0 -0
- package/wasm/tree-sitter-elixir.wasm +0 -0
- package/wasm/tree-sitter-elm.wasm +0 -0
- package/wasm/tree-sitter-embedded_template.wasm +0 -0
- package/wasm/tree-sitter-erlang.wasm +0 -0
- package/wasm/tree-sitter-fsharp.wasm +0 -0
- package/wasm/tree-sitter-fsharp_signature.wasm +0 -0
- package/wasm/tree-sitter-go.wasm +0 -0
- package/wasm/tree-sitter-graphql.wasm +0 -0
- package/wasm/tree-sitter-groovy.wasm +0 -0
- package/wasm/tree-sitter-haskell.wasm +0 -0
- package/wasm/tree-sitter-hcl.wasm +0 -0
- package/wasm/tree-sitter-html.wasm +0 -0
- package/wasm/tree-sitter-java.wasm +0 -0
- package/wasm/tree-sitter-javascript.wasm +0 -0
- package/wasm/tree-sitter-json.wasm +0 -0
- package/wasm/tree-sitter-json_schema.wasm +0 -0
- package/wasm/tree-sitter-julia.wasm +0 -0
- package/wasm/tree-sitter-kotlin.wasm +0 -0
- package/wasm/tree-sitter-lua.wasm +0 -0
- package/wasm/tree-sitter-make.wasm +0 -0
- package/wasm/tree-sitter-markdown.wasm +0 -0
- package/wasm/tree-sitter-markdown_inline.wasm +0 -0
- package/wasm/tree-sitter-matlab.wasm +0 -0
- package/wasm/tree-sitter-nim.wasm +0 -0
- package/wasm/tree-sitter-objc.wasm +0 -0
- package/wasm/tree-sitter-ocaml.wasm +0 -0
- package/wasm/tree-sitter-perl.wasm +0 -0
- package/wasm/tree-sitter-php.wasm +0 -0
- package/wasm/tree-sitter-php_only.wasm +0 -0
- package/wasm/tree-sitter-powershell.wasm +0 -0
- package/wasm/tree-sitter-protobuf.wasm +0 -0
- package/wasm/tree-sitter-python.wasm +0 -0
- package/wasm/tree-sitter-ql.wasm +0 -0
- package/wasm/tree-sitter-r.wasm +0 -0
- package/wasm/tree-sitter-rescript.wasm +0 -0
- package/wasm/tree-sitter-ruby.wasm +0 -0
- package/wasm/tree-sitter-rust.wasm +0 -0
- package/wasm/tree-sitter-scala.wasm +0 -0
- package/wasm/tree-sitter-scss.wasm +0 -0
- package/wasm/tree-sitter-solidity.wasm +0 -0
- package/wasm/tree-sitter-sql.wasm +0 -0
- package/wasm/tree-sitter-svelte.wasm +0 -0
- package/wasm/tree-sitter-swift.wasm +0 -0
- package/wasm/tree-sitter-systemrdl.wasm +0 -0
- package/wasm/tree-sitter-terraform.wasm +0 -0
- package/wasm/tree-sitter-tlaplus.wasm +0 -0
- package/wasm/tree-sitter-toml.wasm +0 -0
- package/wasm/tree-sitter-tsx.wasm +0 -0
- package/wasm/tree-sitter-typescript.wasm +0 -0
- package/wasm/tree-sitter-vba.wasm +0 -0
- package/wasm/tree-sitter-vbnet.wasm +0 -0
- package/wasm/tree-sitter-vue.wasm +0 -0
- package/wasm/tree-sitter-xml.wasm +0 -0
- package/wasm/tree-sitter-yaml.wasm +0 -0
- package/wasm/tree-sitter-zig.wasm +0 -0
- package/wasm/tree-sitter.wasm +0 -0
- package/wasm/tsx.wasm +0 -0
- package/wasm/typescript.wasm +0 -0
|
@@ -0,0 +1,2104 @@
|
|
|
1
|
+
import {
|
|
2
|
+
create
|
|
3
|
+
} from "./chunk-BQ3OVQ3P.js";
|
|
4
|
+
import {
|
|
5
|
+
ensureWasmRegistry,
|
|
6
|
+
hasWasmInRegistry,
|
|
7
|
+
isWasmRegistryLoaded,
|
|
8
|
+
loadWebTreeSitter,
|
|
9
|
+
resolveWasmAsset
|
|
10
|
+
} from "./chunk-SK6YVHFZ.js";
|
|
11
|
+
import {
|
|
12
|
+
RelationshipType,
|
|
13
|
+
decodeSourceText
|
|
14
|
+
} from "./chunk-KAET47ZL.js";
|
|
15
|
+
import {
|
|
16
|
+
detectLanguageFromPath
|
|
17
|
+
} from "./chunk-KCDECRJY.js";
|
|
18
|
+
|
|
19
|
+
// src/util/lazy.ts
|
|
20
|
+
function lazy(fn) {
|
|
21
|
+
let value;
|
|
22
|
+
let loaded = false;
|
|
23
|
+
const result = () => {
|
|
24
|
+
if (loaded) return value;
|
|
25
|
+
value = fn();
|
|
26
|
+
loaded = true;
|
|
27
|
+
return value;
|
|
28
|
+
};
|
|
29
|
+
result.reset = () => {
|
|
30
|
+
loaded = false;
|
|
31
|
+
value = void 0;
|
|
32
|
+
};
|
|
33
|
+
result.loaded = () => loaded;
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/ast/engine.ts
|
|
38
|
+
import { fileURLToPath } from "url";
|
|
39
|
+
import { createRequire } from "module";
|
|
40
|
+
var __dirname = fileURLToPath(new URL(".", import.meta.url)).replace(/[\\/]+$/, "");
|
|
41
|
+
var require2 = createRequire(import.meta.url);
|
|
42
|
+
var log = create({ service: "ast-engine" });
|
|
43
|
+
var wasmTemps = /* @__PURE__ */ new Set();
|
|
44
|
+
var wasmCleanupHooked = false;
|
|
45
|
+
function trackWasmTemp(p) {
|
|
46
|
+
wasmTemps.add(p);
|
|
47
|
+
if (wasmCleanupHooked) return;
|
|
48
|
+
wasmCleanupHooked = true;
|
|
49
|
+
const sweep = () => {
|
|
50
|
+
for (const f of wasmTemps) {
|
|
51
|
+
try {
|
|
52
|
+
require2("fs").unlinkSync(f);
|
|
53
|
+
} catch {
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
wasmTemps.clear();
|
|
57
|
+
};
|
|
58
|
+
process.on("exit", sweep);
|
|
59
|
+
for (const sig of ["SIGINT", "SIGTERM"]) {
|
|
60
|
+
process.on(sig, () => {
|
|
61
|
+
sweep();
|
|
62
|
+
process.exit(0);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
var ASTEngine;
|
|
67
|
+
((ASTEngine2) => {
|
|
68
|
+
const languages = /* @__PURE__ */ new Map();
|
|
69
|
+
const parsers = /* @__PURE__ */ new Map();
|
|
70
|
+
const MAX_CONCURRENT_PARSERS = 20;
|
|
71
|
+
const MAX_PARSER_CACHE_SIZE = 30;
|
|
72
|
+
const MAX_PARSE_BYTES = 16 * 1024 * 1024;
|
|
73
|
+
ASTEngine2.parseTruncation = {
|
|
74
|
+
/** how many files were truncated */
|
|
75
|
+
files: 0,
|
|
76
|
+
/** total bytes dropped before parsing */
|
|
77
|
+
bytesDropped: 0,
|
|
78
|
+
/** worst offenders, largest loss first, for a report that names names */
|
|
79
|
+
worst: []
|
|
80
|
+
};
|
|
81
|
+
function recordTruncation(filePath, originalBytes, parsedBytes) {
|
|
82
|
+
const dropped = originalBytes - parsedBytes;
|
|
83
|
+
ASTEngine2.parseTruncation.files++;
|
|
84
|
+
ASTEngine2.parseTruncation.bytesDropped += dropped;
|
|
85
|
+
ASTEngine2.parseTruncation.worst.push({ filePath, bytesDropped: dropped });
|
|
86
|
+
ASTEngine2.parseTruncation.worst.sort((a, b) => b.bytesDropped - a.bytesDropped);
|
|
87
|
+
if (ASTEngine2.parseTruncation.worst.length > 20) ASTEngine2.parseTruncation.worst.length = 20;
|
|
88
|
+
}
|
|
89
|
+
let totalFilesParsed = 0;
|
|
90
|
+
let lastMemoryReport = 0;
|
|
91
|
+
const parserUsage = /* @__PURE__ */ new Map();
|
|
92
|
+
const parseCount = /* @__PURE__ */ new Map();
|
|
93
|
+
const grammarLoads = /* @__PURE__ */ new Map();
|
|
94
|
+
const treeSitterCore = lazy(async () => {
|
|
95
|
+
const WebTreeSitter = await loadWebTreeSitter();
|
|
96
|
+
const Parser = WebTreeSitter.Parser ?? WebTreeSitter.default ?? WebTreeSitter;
|
|
97
|
+
const Language = WebTreeSitter.Language ?? WebTreeSitter.default?.Language;
|
|
98
|
+
const treePath = resolveWasmCore("tree-sitter.wasm");
|
|
99
|
+
const coreWasm = hasWasmInRegistry("tree-sitter.wasm");
|
|
100
|
+
let wasmFile = treePath;
|
|
101
|
+
if (coreWasm) {
|
|
102
|
+
const os = require2("os");
|
|
103
|
+
const p = require2("path");
|
|
104
|
+
const fsModule = require2("fs");
|
|
105
|
+
for (const tmpDir of [os.tmpdir(), "/tmp", process.cwd()]) {
|
|
106
|
+
try {
|
|
107
|
+
const tmp = p.join(tmpDir, "bb-ts-core.wasm");
|
|
108
|
+
fsModule.writeFileSync(tmp, coreWasm);
|
|
109
|
+
wasmFile = tmp;
|
|
110
|
+
break;
|
|
111
|
+
} catch (e) {
|
|
112
|
+
log.debug("resolveWasm: temp file fallback failed", { error: e?.message });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const initFn = WebTreeSitter.init ?? Parser.init ?? Parser.init;
|
|
117
|
+
if (initFn) {
|
|
118
|
+
try {
|
|
119
|
+
await initFn({ locateFile() {
|
|
120
|
+
return wasmFile;
|
|
121
|
+
} });
|
|
122
|
+
log.info("tree-sitter core initialized", { wasmFile });
|
|
123
|
+
} catch (e1) {
|
|
124
|
+
log.warn("core init via locateFile failed, trying default", { wasmFile, error: e1 });
|
|
125
|
+
try {
|
|
126
|
+
if (wasmFile !== treePath) await initFn({ locateFile() {
|
|
127
|
+
return treePath;
|
|
128
|
+
} });
|
|
129
|
+
else await initFn();
|
|
130
|
+
log.info("tree-sitter core initialized via fallback");
|
|
131
|
+
} catch (e2) {
|
|
132
|
+
log.error("tree-sitter core init failed", { error: e2 });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const lang = Language ?? WebTreeSitter.default?.Language ?? Parser.Language;
|
|
137
|
+
return { Parser, Language: lang };
|
|
138
|
+
});
|
|
139
|
+
function cleanupParsers() {
|
|
140
|
+
while (parsers.size >= MAX_PARSER_CACHE_SIZE) {
|
|
141
|
+
let oldestLang = null;
|
|
142
|
+
let oldestTime = Infinity;
|
|
143
|
+
parserUsage.forEach((time, language) => {
|
|
144
|
+
if (time < oldestTime) {
|
|
145
|
+
oldestTime = time;
|
|
146
|
+
oldestLang = language;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
if (!oldestLang) break;
|
|
150
|
+
const parser = parsers.get(oldestLang);
|
|
151
|
+
if (parser && typeof parser.delete === "function") {
|
|
152
|
+
parser.delete();
|
|
153
|
+
}
|
|
154
|
+
parsers.delete(oldestLang);
|
|
155
|
+
languages.delete(oldestLang);
|
|
156
|
+
parserUsage.delete(oldestLang);
|
|
157
|
+
log.debug("evicted parser from cache, freed WASM memory", {
|
|
158
|
+
language: oldestLang,
|
|
159
|
+
remainingParsers: parsers.size,
|
|
160
|
+
totalFilesParsed
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function resolveWasmCore(asset) {
|
|
165
|
+
return resolveWasmAsset(asset);
|
|
166
|
+
}
|
|
167
|
+
const SUPPORTED_LANGUAGES = {
|
|
168
|
+
// === CORE WEB TECHNOLOGIES ===
|
|
169
|
+
typescript: "tree-sitter-typescript/typescript",
|
|
170
|
+
tsx: "tree-sitter-typescript/tsx",
|
|
171
|
+
javascript: "tree-sitter-javascript",
|
|
172
|
+
html: "tree-sitter-html",
|
|
173
|
+
css: "tree-sitter-css",
|
|
174
|
+
scss: "tree-sitter-css",
|
|
175
|
+
sass: "tree-sitter-css",
|
|
176
|
+
svelte: "tree-sitter-svelte",
|
|
177
|
+
json: "tree-sitter-json",
|
|
178
|
+
perl: "tree-sitter-perl",
|
|
179
|
+
yaml: "tree-sitter-yaml",
|
|
180
|
+
// === SYSTEMS PROGRAMMING ===
|
|
181
|
+
c: "tree-sitter-c",
|
|
182
|
+
cpp: "tree-sitter-cpp",
|
|
183
|
+
rust: "tree-sitter-rust",
|
|
184
|
+
go: "tree-sitter-go",
|
|
185
|
+
// === ENTERPRISE & JVM ===
|
|
186
|
+
java: "tree-sitter-java",
|
|
187
|
+
kotlin: "tree-sitter-kotlin",
|
|
188
|
+
scala: "tree-sitter-scala",
|
|
189
|
+
// === SCRIPTING & DYNAMIC ===
|
|
190
|
+
python: "tree-sitter-python",
|
|
191
|
+
ruby: "tree-sitter-ruby",
|
|
192
|
+
php: "tree-sitter-php",
|
|
193
|
+
lua: "tree-sitter-lua",
|
|
194
|
+
elixir: "tree-sitter-elixir",
|
|
195
|
+
// === FUNCTIONAL PROGRAMMING ===
|
|
196
|
+
erlang: "tree-sitter-erlang",
|
|
197
|
+
haskell: "tree-sitter-haskell",
|
|
198
|
+
clean: "tree-sitter-clean",
|
|
199
|
+
clojure: "tree-sitter-clojure",
|
|
200
|
+
// === MOBILE & MODERN ===
|
|
201
|
+
swift: "tree-sitter-swift",
|
|
202
|
+
dart: "tree-sitter-dart",
|
|
203
|
+
// === SCIENTIFIC / DYNAMIC ===
|
|
204
|
+
julia: "tree-sitter-julia",
|
|
205
|
+
// === MICROSOFT ECOSYSTEM ===
|
|
206
|
+
csharp: "tree-sitter-c-sharp",
|
|
207
|
+
// === DATA SCIENCE & STATS ===
|
|
208
|
+
r: "tree-sitter-r",
|
|
209
|
+
sql: "tree-sitter-sql",
|
|
210
|
+
// === SHELL & SYSTEM ===
|
|
211
|
+
bash: "tree-sitter-bash",
|
|
212
|
+
powershell: "tree-sitter-powershell",
|
|
213
|
+
"objective-c": "tree-sitter-objc",
|
|
214
|
+
groovy: "tree-sitter-groovy",
|
|
215
|
+
vue: "tree-sitter-vue",
|
|
216
|
+
hcl: "tree-sitter-hcl",
|
|
217
|
+
terraform: "tree-sitter-hcl",
|
|
218
|
+
graphql: "tree-sitter-graphql",
|
|
219
|
+
zig: "tree-sitter-zig",
|
|
220
|
+
fsharp: "tree-sitter-fsharp",
|
|
221
|
+
markdown: "tree-sitter-markdown",
|
|
222
|
+
toml: "tree-sitter-toml",
|
|
223
|
+
xml: "tree-sitter-xml",
|
|
224
|
+
make: "tree-sitter-make",
|
|
225
|
+
// === SYSTEMS & COMPILING LANGUAGES (a real parser each) ===
|
|
226
|
+
//
|
|
227
|
+
// `nim` appeared TWICE in this object: here as the real grammar, and again
|
|
228
|
+
// under "LANGUAGES WITHOUT DEDICATED PARSER" as `"__generic__"`. The later
|
|
229
|
+
// key won, so the map claimed nim had no parser while the wasm switch below,
|
|
230
|
+
// the vendored `grammars/tree-sitter-nim/`, the 5.8 MB
|
|
231
|
+
// `wasm/tree-sitter-nim.wasm` and a pinned fixture set all said otherwise.
|
|
232
|
+
//
|
|
233
|
+
// Two reasons it cost nothing measurable, which is why it survived until the
|
|
234
|
+
// type checker objected: this map's VALUES are never read (only its keys are
|
|
235
|
+
// — see the solidity note below), and the wasm switch is keyed off the
|
|
236
|
+
// language NAME, so .nim files loaded the real grammar either way. Measured
|
|
237
|
+
// before the fix, a .nim file declaring a type and a proc produced 3 real
|
|
238
|
+
// symbols (struct:Person, property:name, function:greet) — already correct.
|
|
239
|
+
//
|
|
240
|
+
// So removing the later entry is behaviour-NEUTRAL, and that is the point: the
|
|
241
|
+
// object no longer contradicts the grammar it points at. The M60 VB note
|
|
242
|
+
// below describes the same hazard for `vb`, where the outcome really was a
|
|
243
|
+
// silent regex pass. nim got lucky.
|
|
244
|
+
nim: "tree-sitter-nim",
|
|
245
|
+
// M60 VB wave. `vb` was `__generic__` until 2026-09-27: `.vb` was a routed
|
|
246
|
+
// extension and `vb` a declared DetectedLanguage, but there was no VB.NET
|
|
247
|
+
// grammar on npm at all (`tree-sitter-vb` and `tree-sitter-visual-basic` are
|
|
248
|
+
// both 404, and the `tree-sitter-wasms` bundle that supplies 39 of this
|
|
249
|
+
// repo's grammars ships no VB), so the file was "analysed" by a regex generic
|
|
250
|
+
// pass that cannot see a Class, a Function, an Implements clause or a call
|
|
251
|
+
// site -- and reported as covered rather than refused.
|
|
252
|
+
//
|
|
253
|
+
// The grammar is a vendored and repaired tree-sitter-vbnet; its pin, its 18
|
|
254
|
+
// patches, its source<->wasm proof and its measured parse success are in
|
|
255
|
+
// grammars/tree-sitter-vbnet/PIN.md and validation/m14/grammar-pins.json.
|
|
256
|
+
// Measured: 90.89 % clean over 1185 files on four independent corpora with
|
|
257
|
+
// 0 crash files, up from 38.67 % on Microsoft's own VisualBasic.Core when
|
|
258
|
+
// the upstream grammar was first wired.
|
|
259
|
+
vb: "tree-sitter-vbnet",
|
|
260
|
+
vba: "tree-sitter-vba",
|
|
261
|
+
matlab: "tree-sitter-matlab",
|
|
262
|
+
// === LANGUAGES WITHOUT DEDICATED PARSER (fallback to GenericAnalyzer) ===
|
|
263
|
+
// (the `nim: "__generic__"` line that used to sit here is gone — see below)
|
|
264
|
+
// Protobuf: the vendored, patched tree-sitter-proto. See
|
|
265
|
+
// grammars/tree-sitter-proto/README.md — the node surface is snake_case and
|
|
266
|
+
// is a contract, and this is the ONE routed language whose grammar had to be
|
|
267
|
+
// cloned and patched because no protobuf grammar is published on npm.
|
|
268
|
+
protobuf: "tree-sitter-protobuf",
|
|
269
|
+
// Solidity (SOL-21). ABSENT until now, and that was a real defect rather than
|
|
270
|
+
// a missing feature: the engine had a `case "solidity"` in the wasm switch
|
|
271
|
+
// below, a `case "solidity"` in getAnalyzer, a pinned grammar
|
|
272
|
+
// (validation/m14/grammar-pins.json), a real analyzer, and `DetectedLanguage`
|
|
273
|
+
// admitting "solidity" — but no key here, and this map is what
|
|
274
|
+
// `isSupportedLanguage` reads. Measured through the CLI, on an index holding
|
|
275
|
+
// the five symbols bb extracted from a Vault.sol:
|
|
276
|
+
//
|
|
277
|
+
// $ bb search --dir <proj> --language solidity Vault
|
|
278
|
+
// ✗ unknown language "solidity". Run `bb index --help` for supported
|
|
279
|
+
// languages, or `bb projects` to see which are in this index.
|
|
280
|
+
//
|
|
281
|
+
// byte-identical to the answer for a genuine typo, from a filter whose whole
|
|
282
|
+
// purpose (see isSupportedLanguage) is to tell "not a language bb knows"
|
|
283
|
+
// apart from "this project has none of that language". The data was in the
|
|
284
|
+
// index and the filter refused the name.
|
|
285
|
+
//
|
|
286
|
+
// Parsing was never affected — the wasm switch and getAnalyzer key off the
|
|
287
|
+
// language name, not this map — which is exactly why it survived: the index
|
|
288
|
+
// looked correct, and the only symptom was a rejected flag.
|
|
289
|
+
//
|
|
290
|
+
// The value is the grammar package name, matching every other entry. Only the
|
|
291
|
+
// KEYS are read at runtime: isSupportedLanguage, supportedLanguageNames, and
|
|
292
|
+
// `language in SUPPORTED_LANGUAGES`.
|
|
293
|
+
solidity: "tree-sitter-solidity"
|
|
294
|
+
};
|
|
295
|
+
function isSupportedLanguage(name) {
|
|
296
|
+
if (typeof name !== "string") return false;
|
|
297
|
+
const n = name.trim().toLowerCase();
|
|
298
|
+
if (!n) return false;
|
|
299
|
+
if (Object.prototype.hasOwnProperty.call(SUPPORTED_LANGUAGES, n)) return true;
|
|
300
|
+
const aliases = {
|
|
301
|
+
ts: "typescript",
|
|
302
|
+
tsx: "tsx",
|
|
303
|
+
js: "javascript",
|
|
304
|
+
jsx: "javascript",
|
|
305
|
+
py: "python",
|
|
306
|
+
rb: "ruby",
|
|
307
|
+
rs: "rust",
|
|
308
|
+
csharp: "csharp",
|
|
309
|
+
"c#": "csharp",
|
|
310
|
+
golang: "go",
|
|
311
|
+
kt: "kotlin",
|
|
312
|
+
sh: "bash",
|
|
313
|
+
shell: "bash",
|
|
314
|
+
yml: "yaml",
|
|
315
|
+
md: "markdown"
|
|
316
|
+
};
|
|
317
|
+
const target = aliases[n];
|
|
318
|
+
return !!target && Object.prototype.hasOwnProperty.call(SUPPORTED_LANGUAGES, target);
|
|
319
|
+
}
|
|
320
|
+
ASTEngine2.isSupportedLanguage = isSupportedLanguage;
|
|
321
|
+
function supportedLanguageNames() {
|
|
322
|
+
return Object.keys(SUPPORTED_LANGUAGES).sort();
|
|
323
|
+
}
|
|
324
|
+
ASTEngine2.supportedLanguageNames = supportedLanguageNames;
|
|
325
|
+
let SymbolKind;
|
|
326
|
+
((SymbolKind2) => {
|
|
327
|
+
SymbolKind2["Function"] = "function";
|
|
328
|
+
SymbolKind2["Class"] = "class";
|
|
329
|
+
SymbolKind2["Variable"] = "variable";
|
|
330
|
+
SymbolKind2["Constant"] = "constant";
|
|
331
|
+
SymbolKind2["Interface"] = "interface";
|
|
332
|
+
SymbolKind2["Enum"] = "enum";
|
|
333
|
+
SymbolKind2["EnumMember"] = "enum_member";
|
|
334
|
+
SymbolKind2["Type"] = "type";
|
|
335
|
+
SymbolKind2["Import"] = "import";
|
|
336
|
+
SymbolKind2["Export"] = "export";
|
|
337
|
+
SymbolKind2["Method"] = "method";
|
|
338
|
+
SymbolKind2["Property"] = "property";
|
|
339
|
+
SymbolKind2["Constructor"] = "constructor";
|
|
340
|
+
SymbolKind2["Namespace"] = "namespace";
|
|
341
|
+
SymbolKind2["Module"] = "module";
|
|
342
|
+
SymbolKind2["Table"] = "class";
|
|
343
|
+
SymbolKind2["Service"] = "class";
|
|
344
|
+
SymbolKind2["Resource"] = "class";
|
|
345
|
+
SymbolKind2["TypeAlias"] = "type";
|
|
346
|
+
SymbolKind2["Event"] = "event";
|
|
347
|
+
SymbolKind2["Delegate"] = "delegate";
|
|
348
|
+
SymbolKind2["Object"] = "class";
|
|
349
|
+
SymbolKind2["Record"] = "type";
|
|
350
|
+
SymbolKind2["Macro"] = "macro";
|
|
351
|
+
SymbolKind2["Trait"] = "trait";
|
|
352
|
+
SymbolKind2["Struct"] = "struct";
|
|
353
|
+
SymbolKind2["Impl"] = "impl";
|
|
354
|
+
SymbolKind2["Actor"] = "actor";
|
|
355
|
+
SymbolKind2["Union"] = "union";
|
|
356
|
+
SymbolKind2["Mixin"] = "mixin";
|
|
357
|
+
SymbolKind2["Extension"] = "extension";
|
|
358
|
+
SymbolKind2["Instance"] = "instance";
|
|
359
|
+
})(SymbolKind = ASTEngine2.SymbolKind || (ASTEngine2.SymbolKind = {}));
|
|
360
|
+
ASTEngine2.RelationshipType = RelationshipType;
|
|
361
|
+
const PATCHED_GRAMMAR_SHA256 = {
|
|
362
|
+
"tree-sitter-typescript.wasm": "b75fa34cfde954d15429b39062d217e6fa99b425a0c3f1aaedd082116dd20335",
|
|
363
|
+
// P3 `.RECIPEPREFIX`: the wired build is regenerated from `grammars/tree-sitter-make/recipeprefix/`
|
|
364
|
+
// (external scanner + grammar). Without this entry the resolver served the DEPENDENCY build, whose
|
|
365
|
+
// `_recipeprefix` is the hardcoded tab — so the fixture's `>` recipes parsed as ERROR nodes and the
|
|
366
|
+
// rule after them (`clean:`) was never published. Measured: `tree-sitter` CLI build, 192,211 bytes.
|
|
367
|
+
"tree-sitter-make.wasm": "af93a7597fd11dda62f5c4496fff828956c0a78656323785975ab96e3ae900ab",
|
|
368
|
+
// The two dedicated-root lanes (matlab, vba). Both are WIRED FROM THE REPO'S OWN wasm/ DIRECTORY — no
|
|
369
|
+
// npm package publishes a wasm for either grammar (matlab is an in-tree patch of acristoffers/
|
|
370
|
+
// tree-sitter-matlab 1.3.1; vba is the vendored tree-sitter-vba 0.14.5 under grammars/tree-sitter-vba/) —
|
|
371
|
+
// and both files were left UNTRACKED by the one-branch consolidation, so a fresh clone silently had no
|
|
372
|
+
// grammar for two of the 50 lanes. Pinning the bytes here is what makes the resolver serve them AT ALL
|
|
373
|
+
// (resolveWasm serves repo wasm only through this digest table), so the pin and the tracking are the
|
|
374
|
+
// same fix. The digests are the ones the lanes' own pin records verified: validation/m14/
|
|
375
|
+
// {matlab,vba}-grammar-pin.json.
|
|
376
|
+
"tree-sitter-matlab.wasm": "0f2f381f010d81af18a9f132e77606dceb02ae705c5b2e3cb0eabff3f42083c3",
|
|
377
|
+
"tree-sitter-vba.wasm": "9e0615ad1a4fdf3abff07265fe84d95ba1f392df6f4bbecd0f3ddea92aee00de"
|
|
378
|
+
};
|
|
379
|
+
function resolveWasm(relativePath) {
|
|
380
|
+
const fs = require2("fs");
|
|
381
|
+
const path = require2("path");
|
|
382
|
+
const isCompiled = typeof BB_POOL_WORKER_PATH !== "undefined";
|
|
383
|
+
if (isCompiled) {
|
|
384
|
+
const data = hasWasmInRegistry(relativePath);
|
|
385
|
+
if (data) {
|
|
386
|
+
return relativePath;
|
|
387
|
+
}
|
|
388
|
+
throw new Error(`WASM not in compiled registry: ${relativePath}`);
|
|
389
|
+
}
|
|
390
|
+
const argv0 = process.argv?.[0];
|
|
391
|
+
let execDir = argv0 && fs.existsSync(argv0) ? path.dirname(argv0) : path.dirname(process.execPath);
|
|
392
|
+
try {
|
|
393
|
+
const metaDir = path.dirname(require2("url").fileURLToPath(import.meta.url));
|
|
394
|
+
const metaCheck = path.join(metaDir, "tree-sitter.wasm");
|
|
395
|
+
if (fs.existsSync(metaCheck)) {
|
|
396
|
+
execDir = metaDir;
|
|
397
|
+
}
|
|
398
|
+
} catch (e) {
|
|
399
|
+
log.debug("resolveWasm: temp file fallback failed", { error: e?.message });
|
|
400
|
+
}
|
|
401
|
+
const flatWasmName = relativePath.split("/").pop() || "";
|
|
402
|
+
const siblingPath = `${execDir}/${flatWasmName}`;
|
|
403
|
+
if (fs.existsSync(siblingPath)) {
|
|
404
|
+
return siblingPath;
|
|
405
|
+
}
|
|
406
|
+
{
|
|
407
|
+
const pinned = PATCHED_GRAMMAR_SHA256[flatWasmName];
|
|
408
|
+
if (pinned) {
|
|
409
|
+
try {
|
|
410
|
+
const repoWasm = path.resolve(
|
|
411
|
+
path.dirname(require2("url").fileURLToPath(import.meta.url)),
|
|
412
|
+
"..",
|
|
413
|
+
"..",
|
|
414
|
+
"wasm",
|
|
415
|
+
flatWasmName
|
|
416
|
+
);
|
|
417
|
+
if (fs.existsSync(repoWasm)) {
|
|
418
|
+
const crypto = require2("crypto");
|
|
419
|
+
const actual = crypto.createHash("sha256").update(fs.readFileSync(repoWasm)).digest("hex");
|
|
420
|
+
if (actual === pinned) return repoWasm;
|
|
421
|
+
log.warn(
|
|
422
|
+
`resolveWasm: REFUSING the pinned patched grammar ${flatWasmName} \u2014 its bytes are ${actual.slice(0, 16)}\u2026 but the table pins ${pinned.slice(0, 16)}\u2026. Falling through to the dependency tree.`
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
} catch (e) {
|
|
426
|
+
log.debug("resolveWasm: patched-grammar probe failed", { error: e?.message });
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
const resolved = require2.resolve(relativePath);
|
|
432
|
+
return resolved;
|
|
433
|
+
} catch {
|
|
434
|
+
const packageName = relativePath.split("/")[0];
|
|
435
|
+
const wasmFile = relativePath.split("/")[1] || relativePath.split("/").pop();
|
|
436
|
+
const _dirname = typeof __dirname !== "undefined" ? __dirname : fileURLToPath(import.meta.url) ? require2("path").dirname(fileURLToPath(import.meta.url)) : process.cwd();
|
|
437
|
+
const possiblePaths = [
|
|
438
|
+
`${process.cwd()}/node_modules/${packageName}/${wasmFile}`,
|
|
439
|
+
`${process.cwd()}/node_modules/.bun/${packageName}@*/node_modules/${packageName}/${wasmFile}`,
|
|
440
|
+
`${_dirname}/../../../../node_modules/${packageName}/${wasmFile}`
|
|
441
|
+
];
|
|
442
|
+
for (const path2 of possiblePaths) {
|
|
443
|
+
try {
|
|
444
|
+
if (path2.includes("*")) {
|
|
445
|
+
const globPart = path2.substring(0, path2.indexOf("*"));
|
|
446
|
+
const afterGlob = path2.substring(path2.indexOf("*") + 1);
|
|
447
|
+
try {
|
|
448
|
+
const dirs = fs.readdirSync(globPart.substring(0, globPart.lastIndexOf("/")));
|
|
449
|
+
for (const dir of dirs) {
|
|
450
|
+
const fullPath = `${globPart}${dir}${afterGlob}`;
|
|
451
|
+
if (fs.existsSync(fullPath)) {
|
|
452
|
+
return fullPath;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
} catch (e) {
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
} else {
|
|
459
|
+
if (fs.existsSync(path2)) {
|
|
460
|
+
return path2;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
} catch (e) {
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
const fallback = {
|
|
468
|
+
"tree-sitter-clean/tree-sitter-clean.wasm": [
|
|
469
|
+
"tree-sitter-clean/tree-sitter-clean.wasm"
|
|
470
|
+
],
|
|
471
|
+
"tree-sitter-kotlin/tree-sitter-kotlin.wasm": ["tree-sitter-wasms/out/tree-sitter-kotlin.wasm"],
|
|
472
|
+
"tree-sitter-swift/tree-sitter-swift.wasm": ["tree-sitter-wasms/out/tree-sitter-swift.wasm"],
|
|
473
|
+
"tree-sitter-r/tree-sitter-r.wasm": ["@eagleoutice/tree-sitter-r/tree-sitter-r.wasm"],
|
|
474
|
+
"tree-sitter-dart/tree-sitter-dart.wasm": [
|
|
475
|
+
"tree-sitter-dart/tree-sitter-dart.wasm"
|
|
476
|
+
],
|
|
477
|
+
"tree-sitter-yaml/tree-sitter-yaml.wasm": [
|
|
478
|
+
"@tree-sitter-grammars/tree-sitter-yaml/tree-sitter-yaml.wasm",
|
|
479
|
+
"tree-sitter-wasms/out/tree-sitter-yaml.wasm",
|
|
480
|
+
"tree-sitter-wasm-prebuilt/lib/tree-sitter-yaml.wasm"
|
|
481
|
+
],
|
|
482
|
+
"tree-sitter-sql/tree-sitter-sql.wasm": ["@derekstride/tree-sitter-sql/src/parser"],
|
|
483
|
+
"tree-sitter-zig/tree-sitter-zig.wasm": [
|
|
484
|
+
"tree-sitter-wasms/out/tree-sitter-zig.wasm",
|
|
485
|
+
"@opentui/core/assets/zig/tree-sitter-zig.wasm"
|
|
486
|
+
],
|
|
487
|
+
"tree-sitter-hcl/tree-sitter-hcl.wasm": [
|
|
488
|
+
"@tree-sitter-grammars/tree-sitter-hcl/tree-sitter-hcl.wasm",
|
|
489
|
+
"tree-sitter-hcl/tree-sitter-hcl.wasm"
|
|
490
|
+
],
|
|
491
|
+
"tree-sitter-lua/tree-sitter-lua.wasm": ["tree-sitter-lua/tree-sitter-lua.wasm", "tree-sitter-wasms/out/tree-sitter-lua.wasm"],
|
|
492
|
+
// The nim grammar has no published npm tarball wasm (see
|
|
493
|
+
// grammars/tree-sitter-nim/PIN.md), so the only alternative that can
|
|
494
|
+
// resolve is a sibling checkout of the vendored source.
|
|
495
|
+
"tree-sitter-nim/tree-sitter-nim.wasm": ["tree-sitter-nim/tree-sitter-nim.wasm"],
|
|
496
|
+
"tree-sitter-erlang/tree-sitter-erlang.wasm": ["tree-sitter-erlang/tree-sitter-erlang.wasm"],
|
|
497
|
+
"tree-sitter-clojure/tree-sitter-clojure.wasm": ["tree-sitter-clojure/tree-sitter-clojure.wasm"],
|
|
498
|
+
"tree-sitter-groovy/tree-sitter-groovy.wasm": ["tree-sitter-groovy/tree-sitter-groovy.wasm"],
|
|
499
|
+
"tree-sitter-perl/tree-sitter-perl.wasm": ["tree-sitter-perl/tree-sitter-perl.wasm"],
|
|
500
|
+
"tree-sitter-scala/tree-sitter-scala.wasm": ["tree-sitter-scala/tree-sitter-scala.wasm"],
|
|
501
|
+
"tree-sitter-elixir/tree-sitter-elixir.wasm": ["tree-sitter-elixir/tree-sitter-elixir.wasm"],
|
|
502
|
+
"tree-sitter-haskell/tree-sitter-haskell.wasm": ["tree-sitter-haskell/tree-sitter-haskell.wasm"],
|
|
503
|
+
"tree-sitter-fsharp/tree-sitter-fsharp.wasm": ["tree-sitter-fsharp/tree-sitter-fsharp.wasm"]
|
|
504
|
+
};
|
|
505
|
+
const extra = fallback[relativePath] ?? [];
|
|
506
|
+
for (const item of extra) {
|
|
507
|
+
try {
|
|
508
|
+
const resolved = require2.resolve(item);
|
|
509
|
+
if (fs.existsSync(resolved)) return resolved;
|
|
510
|
+
} catch (e) {
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
const data = hasWasmInRegistry(relativePath);
|
|
515
|
+
if (data) {
|
|
516
|
+
try {
|
|
517
|
+
const os = require2("os");
|
|
518
|
+
const procTag = `${process.pid}_${(process.hrtime?.bigint?.() ?? BigInt(0)).toString(36)}`;
|
|
519
|
+
const base = "bb-wasm_" + relativePath.replace(/\//g, "_").replace(/\\/g, "_");
|
|
520
|
+
const tmp = path.join(os.tmpdir(), `${base}_${procTag}.partial`);
|
|
521
|
+
const final = path.join(os.tmpdir(), `${base}_${procTag}`);
|
|
522
|
+
fs.writeFileSync(tmp, data);
|
|
523
|
+
fs.renameSync(tmp, final);
|
|
524
|
+
trackWasmTemp(final);
|
|
525
|
+
return final;
|
|
526
|
+
} catch (e) {
|
|
527
|
+
log.debug("resolveWasm: temp file fallback failed", { error: e?.message });
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return relativePath;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
function getCachedParser2(language) {
|
|
534
|
+
return parsers.get(language);
|
|
535
|
+
}
|
|
536
|
+
ASTEngine2.getCachedParser = getCachedParser2;
|
|
537
|
+
async function getParser2(language) {
|
|
538
|
+
await ensureWasmRegistry();
|
|
539
|
+
totalFilesParsed++;
|
|
540
|
+
const MEMORY_REPORT_INTERVAL = 100;
|
|
541
|
+
if (totalFilesParsed - lastMemoryReport >= MEMORY_REPORT_INTERVAL) {
|
|
542
|
+
log.debug("parser memory report", {
|
|
543
|
+
totalFilesParsed,
|
|
544
|
+
cachedParsers: parsers.size,
|
|
545
|
+
maxParsers: MAX_PARSER_CACHE_SIZE
|
|
546
|
+
});
|
|
547
|
+
lastMemoryReport = totalFilesParsed;
|
|
548
|
+
}
|
|
549
|
+
if (parsers.size >= MAX_CONCURRENT_PARSERS) {
|
|
550
|
+
cleanupParsers();
|
|
551
|
+
}
|
|
552
|
+
const currentCount = parseCount.get(language) || 0;
|
|
553
|
+
if (currentCount >= 500 && parsers.has(language)) {
|
|
554
|
+
const p = parsers.get(language);
|
|
555
|
+
try {
|
|
556
|
+
if (typeof p.delete === "function") p.delete();
|
|
557
|
+
} catch {
|
|
558
|
+
}
|
|
559
|
+
parsers.delete(language);
|
|
560
|
+
parserUsage.delete(language);
|
|
561
|
+
parseCount.set(language, 0);
|
|
562
|
+
}
|
|
563
|
+
if (parsers.has(language)) {
|
|
564
|
+
parserUsage.set(language, Date.now());
|
|
565
|
+
parseCount.set(language, currentCount + 1);
|
|
566
|
+
return parsers.get(language);
|
|
567
|
+
}
|
|
568
|
+
const { Parser, Language } = await treeSitterCore();
|
|
569
|
+
let languageWasmPath;
|
|
570
|
+
try {
|
|
571
|
+
switch (language) {
|
|
572
|
+
// === WEB TECHNOLOGIES ===
|
|
573
|
+
case "typescript": {
|
|
574
|
+
languageWasmPath = resolveWasm("tree-sitter-typescript/tree-sitter-typescript.wasm");
|
|
575
|
+
break;
|
|
576
|
+
}
|
|
577
|
+
case "tsx": {
|
|
578
|
+
languageWasmPath = resolveWasm("tree-sitter-typescript/tree-sitter-tsx.wasm");
|
|
579
|
+
break;
|
|
580
|
+
}
|
|
581
|
+
case "javascript": {
|
|
582
|
+
languageWasmPath = resolveWasm("tree-sitter-javascript/tree-sitter-javascript.wasm");
|
|
583
|
+
break;
|
|
584
|
+
}
|
|
585
|
+
case "html": {
|
|
586
|
+
languageWasmPath = resolveWasm("tree-sitter-html/tree-sitter-html.wasm");
|
|
587
|
+
break;
|
|
588
|
+
}
|
|
589
|
+
case "css": {
|
|
590
|
+
languageWasmPath = resolveWasm("tree-sitter-css/tree-sitter-css.wasm");
|
|
591
|
+
break;
|
|
592
|
+
}
|
|
593
|
+
// scss is its OWN grammar and its own lane, not a dialect flag on the CSS one.
|
|
594
|
+
// The two were conflated until this change and the conflation was measurable:
|
|
595
|
+
// 254 `.scss` files were routed to a grammar with no `$variables`, no
|
|
596
|
+
// `@mixin`/`@include` and no interpolation, and 43 of the 244 non-empty ones
|
|
597
|
+
// parsed clean. `.sass` (indented syntax, a genuinely different grammar) and
|
|
598
|
+
// `.less` stay on the CSS wasm and stay DECLARED — measured 0 files of each in
|
|
599
|
+
// 13 corpora, so neither is a claim this repo can support or refute.
|
|
600
|
+
case "scss": {
|
|
601
|
+
languageWasmPath = resolveWasm("tree-sitter-scss.wasm");
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
case "sass": {
|
|
605
|
+
languageWasmPath = resolveWasm("tree-sitter-css/tree-sitter-css.wasm");
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
case "json": {
|
|
609
|
+
languageWasmPath = resolveWasm("tree-sitter-json/tree-sitter-json.wasm");
|
|
610
|
+
break;
|
|
611
|
+
}
|
|
612
|
+
case "perl": {
|
|
613
|
+
languageWasmPath = resolveWasm("tree-sitter-perl/tree-sitter-perl.wasm");
|
|
614
|
+
break;
|
|
615
|
+
}
|
|
616
|
+
case "yaml": {
|
|
617
|
+
languageWasmPath = resolveWasm("tree-sitter-yaml/tree-sitter-yaml.wasm");
|
|
618
|
+
break;
|
|
619
|
+
}
|
|
620
|
+
// === SYSTEMS PROGRAMMING ===
|
|
621
|
+
case "c": {
|
|
622
|
+
languageWasmPath = resolveWasm("tree-sitter-c/tree-sitter-c.wasm");
|
|
623
|
+
break;
|
|
624
|
+
}
|
|
625
|
+
case "cpp": {
|
|
626
|
+
languageWasmPath = resolveWasm("tree-sitter-cpp/tree-sitter-cpp.wasm");
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
case "rust": {
|
|
630
|
+
languageWasmPath = resolveWasm("tree-sitter-rust/tree-sitter-rust.wasm");
|
|
631
|
+
break;
|
|
632
|
+
}
|
|
633
|
+
case "go": {
|
|
634
|
+
languageWasmPath = resolveWasm("tree-sitter-go/tree-sitter-go.wasm");
|
|
635
|
+
break;
|
|
636
|
+
}
|
|
637
|
+
// === ENTERPRISE & JVM ===
|
|
638
|
+
case "java": {
|
|
639
|
+
languageWasmPath = resolveWasm("tree-sitter-java/tree-sitter-java.wasm");
|
|
640
|
+
break;
|
|
641
|
+
}
|
|
642
|
+
case "kotlin": {
|
|
643
|
+
languageWasmPath = resolveWasm("tree-sitter-kotlin/tree-sitter-kotlin.wasm");
|
|
644
|
+
break;
|
|
645
|
+
}
|
|
646
|
+
case "scala": {
|
|
647
|
+
languageWasmPath = resolveWasm("tree-sitter-scala/tree-sitter-scala.wasm");
|
|
648
|
+
break;
|
|
649
|
+
}
|
|
650
|
+
// === SCRIPTING & DYNAMIC ===
|
|
651
|
+
case "python": {
|
|
652
|
+
languageWasmPath = resolveWasm("tree-sitter-python/tree-sitter-python.wasm");
|
|
653
|
+
break;
|
|
654
|
+
}
|
|
655
|
+
case "ruby": {
|
|
656
|
+
languageWasmPath = resolveWasm("tree-sitter-ruby/tree-sitter-ruby.wasm");
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
659
|
+
case "php": {
|
|
660
|
+
languageWasmPath = resolveWasm("tree-sitter-php/tree-sitter-php.wasm");
|
|
661
|
+
break;
|
|
662
|
+
}
|
|
663
|
+
case "lua": {
|
|
664
|
+
try {
|
|
665
|
+
languageWasmPath = resolveWasm("tree-sitter-lua/tree-sitter-lua.wasm");
|
|
666
|
+
} catch {
|
|
667
|
+
languageWasmPath = resolveWasm("@tree-sitter-grammars/tree-sitter-lua/tree-sitter-lua.wasm");
|
|
668
|
+
}
|
|
669
|
+
break;
|
|
670
|
+
}
|
|
671
|
+
case "elixir": {
|
|
672
|
+
languageWasmPath = resolveWasm("tree-sitter-elixir/tree-sitter-elixir.wasm");
|
|
673
|
+
break;
|
|
674
|
+
}
|
|
675
|
+
case "erlang": {
|
|
676
|
+
try {
|
|
677
|
+
languageWasmPath = resolveWasm("tree-sitter-erlang/tree-sitter-erlang.wasm");
|
|
678
|
+
} catch {
|
|
679
|
+
languageWasmPath = resolveWasm("@lumis-sh/wasm-erlang/tree-sitter-erlang.wasm");
|
|
680
|
+
}
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
683
|
+
// === FUNCTIONAL PROGRAMMING ===
|
|
684
|
+
case "haskell": {
|
|
685
|
+
try {
|
|
686
|
+
languageWasmPath = resolveWasm("tree-sitter-haskell/tree-sitter-haskell.wasm");
|
|
687
|
+
} catch {
|
|
688
|
+
languageWasmPath = resolveWasm("@tree-sitter-grammars/tree-sitter-haskell/tree-sitter-haskell.wasm");
|
|
689
|
+
}
|
|
690
|
+
break;
|
|
691
|
+
}
|
|
692
|
+
case "julia": {
|
|
693
|
+
languageWasmPath = resolveWasm("tree-sitter-julia/tree-sitter-julia.wasm");
|
|
694
|
+
break;
|
|
695
|
+
}
|
|
696
|
+
case "clean": {
|
|
697
|
+
languageWasmPath = resolveWasm("tree-sitter-clean/tree-sitter-clean.wasm");
|
|
698
|
+
break;
|
|
699
|
+
}
|
|
700
|
+
case "clojure": {
|
|
701
|
+
languageWasmPath = resolveWasm("tree-sitter-clojure/tree-sitter-clojure.wasm");
|
|
702
|
+
break;
|
|
703
|
+
}
|
|
704
|
+
// === MOBILE & MODERN ===
|
|
705
|
+
case "swift": {
|
|
706
|
+
languageWasmPath = resolveWasm("tree-sitter-swift/tree-sitter-swift.wasm");
|
|
707
|
+
break;
|
|
708
|
+
}
|
|
709
|
+
case "dart": {
|
|
710
|
+
languageWasmPath = resolveWasm("tree-sitter-dart/tree-sitter-dart.wasm");
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
// === MICROSOFT ECOSYSTEM ===
|
|
714
|
+
case "csharp": {
|
|
715
|
+
languageWasmPath = resolveWasm("tree-sitter-c-sharp/tree-sitter-c_sharp.wasm");
|
|
716
|
+
break;
|
|
717
|
+
}
|
|
718
|
+
// === DATA SCIENCE & STATS ===
|
|
719
|
+
case "r": {
|
|
720
|
+
languageWasmPath = resolveWasm("tree-sitter-r/tree-sitter-r.wasm");
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
case "sql": {
|
|
724
|
+
languageWasmPath = resolveWasm("tree-sitter-sql/tree-sitter-sql.wasm");
|
|
725
|
+
break;
|
|
726
|
+
}
|
|
727
|
+
// === SHELL & SYSTEM ===
|
|
728
|
+
case "bash": {
|
|
729
|
+
languageWasmPath = resolveWasm("tree-sitter-bash/tree-sitter-bash.wasm");
|
|
730
|
+
break;
|
|
731
|
+
}
|
|
732
|
+
case "objective-c": {
|
|
733
|
+
languageWasmPath = resolveWasm("tree-sitter-objc/tree-sitter-objc.wasm");
|
|
734
|
+
break;
|
|
735
|
+
}
|
|
736
|
+
case "groovy": {
|
|
737
|
+
languageWasmPath = resolveWasm("tree-sitter-groovy/tree-sitter-groovy.wasm");
|
|
738
|
+
break;
|
|
739
|
+
}
|
|
740
|
+
case "vue": {
|
|
741
|
+
languageWasmPath = resolveWasm("tree-sitter-vue/tree-sitter-vue.wasm");
|
|
742
|
+
break;
|
|
743
|
+
}
|
|
744
|
+
case "svelte": {
|
|
745
|
+
languageWasmPath = resolveWasm("tree-sitter-svelte/tree-sitter-svelte.wasm");
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
case "hcl":
|
|
749
|
+
case "terraform": {
|
|
750
|
+
languageWasmPath = resolveWasm("tree-sitter-hcl/tree-sitter-hcl.wasm");
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
case "graphql": {
|
|
754
|
+
languageWasmPath = resolveWasm("tree-sitter-graphql/tree-sitter-graphql.wasm");
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
case "zig": {
|
|
758
|
+
languageWasmPath = resolveWasm("tree-sitter-zig/tree-sitter-zig.wasm");
|
|
759
|
+
break;
|
|
760
|
+
}
|
|
761
|
+
case "nim": {
|
|
762
|
+
languageWasmPath = resolveWasm("tree-sitter-nim/tree-sitter-nim.wasm");
|
|
763
|
+
break;
|
|
764
|
+
}
|
|
765
|
+
case "fsharp": {
|
|
766
|
+
languageWasmPath = resolveWasm("tree-sitter-fsharp/tree-sitter-fsharp.wasm");
|
|
767
|
+
break;
|
|
768
|
+
}
|
|
769
|
+
case "powershell": {
|
|
770
|
+
languageWasmPath = resolveWasm("tree-sitter-powershell/tree-sitter-powershell.wasm");
|
|
771
|
+
break;
|
|
772
|
+
}
|
|
773
|
+
// The Solidity pin names the wired bytes at `wasm/tree-sitter-solidity.wasm`
|
|
774
|
+
// (script/m14/verify-grammar-pins.ts, LANES.solidity), byte-identical to the
|
|
775
|
+
// npm tarball tree-sitter-solidity@1.2.13. The resolver keys on the basename,
|
|
776
|
+
// so this spelling and the pin's `wired` field name the same file — a swap
|
|
777
|
+
// here is a swap the pin gate catches.
|
|
778
|
+
case "solidity": {
|
|
779
|
+
languageWasmPath = resolveWasm("tree-sitter-solidity.wasm");
|
|
780
|
+
break;
|
|
781
|
+
}
|
|
782
|
+
// M60 VB wave. The wasm name is the GRAMMAR's name, not the language's:
|
|
783
|
+
// the lane reads `tree-sitter-vbnet`, and the pin's `wired` field names
|
|
784
|
+
// the same file, so a swap of the wasm here is a swap the pin catches.
|
|
785
|
+
// See grammars/tree-sitter-vbnet/PIN.md.
|
|
786
|
+
case "vb": {
|
|
787
|
+
languageWasmPath = resolveWasm("tree-sitter-vbnet/tree-sitter-vbnet.wasm");
|
|
788
|
+
break;
|
|
789
|
+
}
|
|
790
|
+
case "vba": {
|
|
791
|
+
languageWasmPath = resolveWasm("tree-sitter-vba.wasm");
|
|
792
|
+
break;
|
|
793
|
+
}
|
|
794
|
+
case "matlab": {
|
|
795
|
+
languageWasmPath = resolveWasm("tree-sitter-matlab.wasm");
|
|
796
|
+
break;
|
|
797
|
+
}
|
|
798
|
+
// === MARKUP & DATA ===
|
|
799
|
+
case "markdown": {
|
|
800
|
+
languageWasmPath = resolveWasm("tree-sitter-markdown/tree-sitter-markdown.wasm");
|
|
801
|
+
break;
|
|
802
|
+
}
|
|
803
|
+
case "toml": {
|
|
804
|
+
languageWasmPath = resolveWasm("tree-sitter-toml/tree-sitter-toml.wasm");
|
|
805
|
+
break;
|
|
806
|
+
}
|
|
807
|
+
case "xml": {
|
|
808
|
+
languageWasmPath = resolveWasm("tree-sitter-xml/tree-sitter-xml.wasm");
|
|
809
|
+
break;
|
|
810
|
+
}
|
|
811
|
+
case "make": {
|
|
812
|
+
languageWasmPath = resolveWasm("tree-sitter-make/tree-sitter-make.wasm");
|
|
813
|
+
break;
|
|
814
|
+
}
|
|
815
|
+
case "protobuf": {
|
|
816
|
+
languageWasmPath = resolveWasm("tree-sitter-protobuf/tree-sitter-protobuf.wasm");
|
|
817
|
+
break;
|
|
818
|
+
}
|
|
819
|
+
default:
|
|
820
|
+
throw new Error(`Language ${language} parser not yet implemented. Add the WASM loading case.`);
|
|
821
|
+
}
|
|
822
|
+
} catch (error) {
|
|
823
|
+
throw new Error(
|
|
824
|
+
`Failed to determine WASM path for ${language}: ${error instanceof Error ? error.message : String(error)}`
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
let wasmBuffer;
|
|
828
|
+
const registryData = hasWasmInRegistry(languageWasmPath);
|
|
829
|
+
if (registryData) {
|
|
830
|
+
wasmBuffer = registryData;
|
|
831
|
+
} else if (isWasmRegistryLoaded()) {
|
|
832
|
+
throw new Error(`WASM not found in registry for ${language} (${languageWasmPath})`);
|
|
833
|
+
} else {
|
|
834
|
+
const fs = require2("fs");
|
|
835
|
+
wasmBuffer = new Uint8Array(fs.readFileSync(languageWasmPath));
|
|
836
|
+
}
|
|
837
|
+
let languageGrammar = languages.get(language);
|
|
838
|
+
if (!languageGrammar) {
|
|
839
|
+
try {
|
|
840
|
+
if (!wasmBuffer) throw new Error(`WASM buffer is undefined for ${language}`);
|
|
841
|
+
let inflight = grammarLoads.get(language);
|
|
842
|
+
if (!inflight) {
|
|
843
|
+
inflight = (async () => {
|
|
844
|
+
const g = await Promise.race([
|
|
845
|
+
new Promise((resolve, reject) => {
|
|
846
|
+
try {
|
|
847
|
+
resolve(Language.load(wasmBuffer));
|
|
848
|
+
} catch (e) {
|
|
849
|
+
reject(e);
|
|
850
|
+
}
|
|
851
|
+
}),
|
|
852
|
+
new Promise((_, r) => setTimeout(() => r(new Error("load timeout")), 1e4))
|
|
853
|
+
]);
|
|
854
|
+
languages.set(language, g);
|
|
855
|
+
log.info("language grammar allocated", { language });
|
|
856
|
+
return g;
|
|
857
|
+
})();
|
|
858
|
+
grammarLoads.set(language, inflight);
|
|
859
|
+
inflight.catch(() => {
|
|
860
|
+
}).finally(() => grammarLoads.delete(language));
|
|
861
|
+
}
|
|
862
|
+
languageGrammar = await inflight;
|
|
863
|
+
} catch (e) {
|
|
864
|
+
throw new Error(`Language.load failed for ${language}: ${e?.message || String(e)}`);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
const parser = new Parser();
|
|
868
|
+
parser.setLanguage(languageGrammar);
|
|
869
|
+
const existing = parsers.get(language);
|
|
870
|
+
if (existing && existing !== parser) {
|
|
871
|
+
try {
|
|
872
|
+
if (typeof parser.delete === "function") parser.delete();
|
|
873
|
+
} catch {
|
|
874
|
+
}
|
|
875
|
+
parserUsage.set(language, Date.now());
|
|
876
|
+
return existing;
|
|
877
|
+
}
|
|
878
|
+
languages.set(language, languageGrammar);
|
|
879
|
+
parsers.set(language, parser);
|
|
880
|
+
parserUsage.set(language, Date.now());
|
|
881
|
+
parseCount.set(language, 1);
|
|
882
|
+
log.info("language parser loaded", { language, wasmPath: languageWasmPath });
|
|
883
|
+
return parser;
|
|
884
|
+
}
|
|
885
|
+
ASTEngine2.getParser = getParser2;
|
|
886
|
+
function detectLanguage(filePath, content) {
|
|
887
|
+
return detectLanguageFromPath(filePath, content);
|
|
888
|
+
}
|
|
889
|
+
ASTEngine2.detectLanguage = detectLanguage;
|
|
890
|
+
function extractHtmlEmbeddedBlocks(rootNode, content) {
|
|
891
|
+
const out = [];
|
|
892
|
+
const stack = [rootNode];
|
|
893
|
+
while (stack.length > 0) {
|
|
894
|
+
const n = stack.pop();
|
|
895
|
+
if (n.type === "script_element" || n.type === "style_element") {
|
|
896
|
+
const isStyle = n.type === "style_element";
|
|
897
|
+
let rawText = null;
|
|
898
|
+
let lang = isStyle ? "css" : "js";
|
|
899
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
900
|
+
const c = n.namedChild(i);
|
|
901
|
+
if (!c) continue;
|
|
902
|
+
if (c.type === "raw_text") rawText = c;
|
|
903
|
+
if (c.type === "start_tag") {
|
|
904
|
+
for (let j = 0; j < c.namedChildCount; j++) {
|
|
905
|
+
const a = c.namedChild(j);
|
|
906
|
+
if (a && a.type === "attribute") {
|
|
907
|
+
const attrName = findAttributeName(a);
|
|
908
|
+
if (isStyle) {
|
|
909
|
+
if (attrName === "lang") {
|
|
910
|
+
const v = findAttributeValue(a);
|
|
911
|
+
if (v === "css" || v === "text/css") lang = "css";
|
|
912
|
+
else lang = "js";
|
|
913
|
+
}
|
|
914
|
+
} else if (attrName === "lang") {
|
|
915
|
+
const v = findAttributeValue(a);
|
|
916
|
+
if (v === "ts" || v === "typescript") lang = "ts";
|
|
917
|
+
else if (v === "tsx") lang = "tsx";
|
|
918
|
+
} else if (attrName === "type") {
|
|
919
|
+
const v = findAttributeValue(a);
|
|
920
|
+
const lowered = v.toLowerCase();
|
|
921
|
+
if (lowered === "module" || lowered === "text/javascript" || lowered === "application/javascript" || lowered === "text/ecmascript" || lowered === "module/javascript") lang = "js";
|
|
922
|
+
else if (lowered === "text/typescript" || lowered === "application/typescript" || lowered === "ts") lang = "ts";
|
|
923
|
+
else if (lowered === "text/tsx" || lowered === "tsx") lang = "tsx";
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
if (rawText) {
|
|
930
|
+
const body = content.substring(rawText.startIndex, rawText.endIndex);
|
|
931
|
+
if (body.trim().length > 0) {
|
|
932
|
+
out.push({
|
|
933
|
+
body,
|
|
934
|
+
lang,
|
|
935
|
+
startLine: rawText.startPosition.row + 1,
|
|
936
|
+
startColumn: rawText.startPosition.column,
|
|
937
|
+
startIndex: rawText.startIndex
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
for (let i = n.namedChildCount - 1; i >= 0; i--) {
|
|
943
|
+
const c = n.namedChild(i);
|
|
944
|
+
if (c) stack.push(c);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
return out;
|
|
948
|
+
}
|
|
949
|
+
ASTEngine2.extractHtmlEmbeddedBlocks = extractHtmlEmbeddedBlocks;
|
|
950
|
+
function extractSfcScriptBlocks(rootNode, content) {
|
|
951
|
+
const out = [];
|
|
952
|
+
const stack = [rootNode];
|
|
953
|
+
while (stack.length > 0) {
|
|
954
|
+
const n = stack.pop();
|
|
955
|
+
if (n.type === "script_element") {
|
|
956
|
+
let rawText = null;
|
|
957
|
+
let lang = "js";
|
|
958
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
959
|
+
const c = n.namedChild(i);
|
|
960
|
+
if (!c) continue;
|
|
961
|
+
if (c.type === "raw_text") rawText = c;
|
|
962
|
+
if (c.type === "start_tag") {
|
|
963
|
+
for (let j = 0; j < c.namedChildCount; j++) {
|
|
964
|
+
const a = c.namedChild(j);
|
|
965
|
+
if (a && a.type === "attribute") {
|
|
966
|
+
const attrName = findAttributeName(a);
|
|
967
|
+
if (attrName === "lang") {
|
|
968
|
+
let v = findAttributeValue(a);
|
|
969
|
+
if (v === "ts") lang = "ts";
|
|
970
|
+
else if (v === "tsx") lang = "tsx";
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
if (rawText) {
|
|
977
|
+
const body = content.substring(rawText.startIndex, rawText.endIndex);
|
|
978
|
+
if (body.trim().length > 0) {
|
|
979
|
+
out.push({
|
|
980
|
+
body,
|
|
981
|
+
lang,
|
|
982
|
+
startLine: rawText.startPosition.row + 1,
|
|
983
|
+
startColumn: rawText.startPosition.column,
|
|
984
|
+
// H3 (vue review wave): script-relative symbol indices need
|
|
985
|
+
// this SFC base to become file-coherent (lines/cols alone
|
|
986
|
+
// leave index-based consumers misaligned).
|
|
987
|
+
startIndex: rawText.startIndex
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
for (let i = n.namedChildCount - 1; i >= 0; i--) {
|
|
993
|
+
const c = n.namedChild(i);
|
|
994
|
+
if (c) stack.push(c);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
return out;
|
|
998
|
+
}
|
|
999
|
+
ASTEngine2.extractSfcScriptBlocks = extractSfcScriptBlocks;
|
|
1000
|
+
function extractMarkdownInlineBlocks(rootNode) {
|
|
1001
|
+
const out = [];
|
|
1002
|
+
const stack = [rootNode];
|
|
1003
|
+
while (stack.length > 0) {
|
|
1004
|
+
const n = stack.pop();
|
|
1005
|
+
if (n.type === "inline") {
|
|
1006
|
+
out.push({
|
|
1007
|
+
startIndex: n.startIndex,
|
|
1008
|
+
endIndex: n.endIndex,
|
|
1009
|
+
startPosition: { row: n.startPosition.row, column: n.startPosition.column }
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
for (let i = n.namedChildCount - 1; i >= 0; i--) {
|
|
1013
|
+
const c = n.namedChild(i);
|
|
1014
|
+
if (c) stack.push(c);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
return out.sort((a, b) => a.startIndex - b.startIndex);
|
|
1018
|
+
}
|
|
1019
|
+
async function getMarkdownInlineParser() {
|
|
1020
|
+
const key = "__markdown_inline__";
|
|
1021
|
+
await ensureWasmRegistry();
|
|
1022
|
+
if (parsers.has(key)) {
|
|
1023
|
+
parserUsage.set(key, Date.now());
|
|
1024
|
+
return parsers.get(key);
|
|
1025
|
+
}
|
|
1026
|
+
const { Parser, Language } = await treeSitterCore();
|
|
1027
|
+
const wasmPath = resolveWasm("tree-sitter-markdown_inline/tree-sitter-markdown_inline.wasm");
|
|
1028
|
+
let wasmBuffer;
|
|
1029
|
+
const registryData = hasWasmInRegistry(wasmPath);
|
|
1030
|
+
if (registryData) {
|
|
1031
|
+
wasmBuffer = registryData;
|
|
1032
|
+
} else if (isWasmRegistryLoaded()) {
|
|
1033
|
+
throw new Error(`WASM not found in registry for markdown_inline (${wasmPath})`);
|
|
1034
|
+
} else {
|
|
1035
|
+
const fs = require2("fs");
|
|
1036
|
+
wasmBuffer = new Uint8Array(fs.readFileSync(wasmPath));
|
|
1037
|
+
}
|
|
1038
|
+
const languageGrammar = await Language.load(wasmBuffer);
|
|
1039
|
+
const parser = new Parser();
|
|
1040
|
+
parser.setLanguage(languageGrammar);
|
|
1041
|
+
languages.set(key, languageGrammar);
|
|
1042
|
+
parsers.set(key, parser);
|
|
1043
|
+
parserUsage.set(key, Date.now());
|
|
1044
|
+
parseCount.set(key, 1);
|
|
1045
|
+
log.debug("language parser loaded", { language: "markdown_inline", wasmPath });
|
|
1046
|
+
return parser;
|
|
1047
|
+
}
|
|
1048
|
+
function findAttributeName(attr) {
|
|
1049
|
+
for (let i = 0; i < attr.namedChildCount; i++) {
|
|
1050
|
+
const c = attr.namedChild(i);
|
|
1051
|
+
if (c && c.type === "attribute_name") return c.text;
|
|
1052
|
+
}
|
|
1053
|
+
return "";
|
|
1054
|
+
}
|
|
1055
|
+
function findAttributeValue(attr) {
|
|
1056
|
+
const stack = [];
|
|
1057
|
+
for (let i = 0; i < attr.namedChildCount; i++) {
|
|
1058
|
+
const c = attr.namedChild(i);
|
|
1059
|
+
if (c) stack.push(c);
|
|
1060
|
+
}
|
|
1061
|
+
while (stack.length > 0) {
|
|
1062
|
+
const n = stack.pop();
|
|
1063
|
+
if (n.type === "attribute_value") return n.text;
|
|
1064
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
1065
|
+
const c = n.namedChild(i);
|
|
1066
|
+
if (c) stack.push(c);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
return "";
|
|
1070
|
+
}
|
|
1071
|
+
async function parseRaw(filePath, content, language) {
|
|
1072
|
+
let parser;
|
|
1073
|
+
let transientLuaGrammar = null;
|
|
1074
|
+
if (language === "lua") {
|
|
1075
|
+
const fs = require2("fs");
|
|
1076
|
+
const WebTreeSitter = await loadWebTreeSitter();
|
|
1077
|
+
const ParserCtor = WebTreeSitter.Parser ?? WebTreeSitter.default ?? WebTreeSitter;
|
|
1078
|
+
const LanguageCtor = WebTreeSitter.Language ?? WebTreeSitter.default?.Language;
|
|
1079
|
+
const initFn = WebTreeSitter.init ?? ParserCtor.init ?? ParserCtor.init;
|
|
1080
|
+
if (initFn) await initFn({ locateFile: () => resolveWasmAsset("tree-sitter.wasm") });
|
|
1081
|
+
transientLuaGrammar = await LanguageCtor.load(
|
|
1082
|
+
new Uint8Array(fs.readFileSync(resolveWasmAsset("tree-sitter-lua.wasm")))
|
|
1083
|
+
);
|
|
1084
|
+
parser = new ParserCtor();
|
|
1085
|
+
parser.setLanguage(transientLuaGrammar);
|
|
1086
|
+
} else {
|
|
1087
|
+
parser = await getParser2(language);
|
|
1088
|
+
}
|
|
1089
|
+
let truncated = null;
|
|
1090
|
+
if (content.length > MAX_PARSE_BYTES) {
|
|
1091
|
+
log.warn("large file detected, using truncated content", {
|
|
1092
|
+
filePath,
|
|
1093
|
+
originalSize: content.length,
|
|
1094
|
+
truncatedSize: MAX_PARSE_BYTES
|
|
1095
|
+
});
|
|
1096
|
+
recordTruncation(filePath, content.length, MAX_PARSE_BYTES);
|
|
1097
|
+
truncated = { originalSize: content.length, parsedSize: MAX_PARSE_BYTES };
|
|
1098
|
+
content = content.substring(0, MAX_PARSE_BYTES);
|
|
1099
|
+
}
|
|
1100
|
+
const blankKeepingNewlines = (match) => match.replace(/[^\n]/g, " ");
|
|
1101
|
+
if (language === "c" || language === "cpp") {
|
|
1102
|
+
content = content.replace(/__attribute__\s*\(\([\s\S]*?\)\)/g, blankKeepingNewlines).replace(/__declspec\s*\([\s\S]*?\)/g, blankKeepingNewlines).replace(/__restrict__/g, " ").replace(/__restrict/g, " ").replace(/__volatile__/g, " ").replace(/__inline__/g, " ").replace(/__forceinline/g, " ").replace(/__cdecl/g, " ").replace(/__stdcall/g, " ").replace(/__fastcall/g, " ").replace(/__stored_key/g, " ");
|
|
1103
|
+
}
|
|
1104
|
+
const parseBomb = setTimeout(() => {
|
|
1105
|
+
process.stderr.write(`[BB-HANG] parser stuck 120s on ${filePath} \u2014 exiting
|
|
1106
|
+
`);
|
|
1107
|
+
process.exit(1);
|
|
1108
|
+
}, 12e4);
|
|
1109
|
+
let tree;
|
|
1110
|
+
try {
|
|
1111
|
+
tree = parser.parse(content);
|
|
1112
|
+
} finally {
|
|
1113
|
+
clearTimeout(parseBomb);
|
|
1114
|
+
}
|
|
1115
|
+
if (!tree) {
|
|
1116
|
+
throw new Error(`Failed to parse file: ${filePath}`);
|
|
1117
|
+
}
|
|
1118
|
+
if (language === "sql") {
|
|
1119
|
+
try {
|
|
1120
|
+
const mod = await import("./real-sql-analyzer-F77ZMQXR.js");
|
|
1121
|
+
const grammar = parser.language;
|
|
1122
|
+
if (grammar) mod.RealSqlAnalyzer.setGrammar?.(grammar, parser.constructor);
|
|
1123
|
+
} catch {
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
return { parser, tree, transientLuaGrammar, truncated };
|
|
1127
|
+
}
|
|
1128
|
+
async function parseWithTimeout(filePath, content, language) {
|
|
1129
|
+
const parsePromise = parseRaw(filePath, content, language);
|
|
1130
|
+
let timeoutId;
|
|
1131
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
1132
|
+
timeoutId = setTimeout(() => {
|
|
1133
|
+
log.error("parser timeout - forcefully aborting", { filePath });
|
|
1134
|
+
reject(new Error(`Parser timeout for ${filePath}`));
|
|
1135
|
+
}, 12e4);
|
|
1136
|
+
});
|
|
1137
|
+
try {
|
|
1138
|
+
const result = await Promise.race([parsePromise, timeoutPromise]);
|
|
1139
|
+
clearTimeout(timeoutId);
|
|
1140
|
+
return result;
|
|
1141
|
+
} catch (error) {
|
|
1142
|
+
clearTimeout(timeoutId);
|
|
1143
|
+
throw error;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
async function parseTree(filePath, content) {
|
|
1147
|
+
const language = detectLanguage(filePath, content);
|
|
1148
|
+
if (!language) {
|
|
1149
|
+
throw new Error(`Unsupported file type: ${filePath}`);
|
|
1150
|
+
}
|
|
1151
|
+
const { parser, tree, transientLuaGrammar } = await parseWithTimeout(filePath, content, language);
|
|
1152
|
+
return { language, tree, parser, transientLuaGrammar };
|
|
1153
|
+
}
|
|
1154
|
+
ASTEngine2.parseTree = parseTree;
|
|
1155
|
+
async function parseFile2(filePath, content, context) {
|
|
1156
|
+
const language = detectLanguage(filePath, content);
|
|
1157
|
+
if (!language) {
|
|
1158
|
+
throw new Error(`Unsupported file type: ${filePath}`);
|
|
1159
|
+
}
|
|
1160
|
+
const { parser, tree, transientLuaGrammar, truncated } = await parseWithTimeout(filePath, content, language);
|
|
1161
|
+
const treeErrors = [];
|
|
1162
|
+
if (tree.rootNode.hasError) {
|
|
1163
|
+
const traverse = (node) => {
|
|
1164
|
+
if (node.type === "ERROR" || node.isMissing) {
|
|
1165
|
+
treeErrors.push({
|
|
1166
|
+
message: `Syntax error (${node.isMissing ? "missing" : "unexpected"} node)`,
|
|
1167
|
+
range: {
|
|
1168
|
+
startLine: node.startPosition.row + 1,
|
|
1169
|
+
startColumn: node.startPosition.column + 1,
|
|
1170
|
+
endLine: node.endPosition.row + 1,
|
|
1171
|
+
endColumn: node.endPosition.column + 1
|
|
1172
|
+
},
|
|
1173
|
+
severity: `warning`
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
const children = node.children;
|
|
1177
|
+
for (let i = 0; i < children.length; i++) {
|
|
1178
|
+
if (treeErrors.length < 50) traverse(children[i]);
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
traverse(tree.rootNode);
|
|
1182
|
+
if (treeErrors.length === 0) {
|
|
1183
|
+
treeErrors.push({
|
|
1184
|
+
message: `Syntax error present in file (hidden MISSING node)`,
|
|
1185
|
+
range: {
|
|
1186
|
+
startLine: tree.rootNode.startPosition.row + 1,
|
|
1187
|
+
startColumn: tree.rootNode.startPosition.column + 1,
|
|
1188
|
+
endLine: tree.rootNode.endPosition.row + 1,
|
|
1189
|
+
endColumn: tree.rootNode.endPosition.column + 1
|
|
1190
|
+
},
|
|
1191
|
+
severity: `warning`
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
log.debug("parsed file", {
|
|
1196
|
+
filePath,
|
|
1197
|
+
language,
|
|
1198
|
+
nodeCount: tree.rootNode.namedChildCount
|
|
1199
|
+
});
|
|
1200
|
+
const analyzePromise = (async () => {
|
|
1201
|
+
const analyzer = await getAnalyzer(language);
|
|
1202
|
+
let analysisResult;
|
|
1203
|
+
if ((language === "vue" || language === "svelte") && tree?.rootNode) {
|
|
1204
|
+
try {
|
|
1205
|
+
const scriptBlocks = extractSfcScriptBlocks(tree.rootNode, content);
|
|
1206
|
+
if (scriptBlocks.length > 0) {
|
|
1207
|
+
const sfcScriptTrees = [];
|
|
1208
|
+
const sfcScriptLines = [];
|
|
1209
|
+
const sfcScriptCols = [];
|
|
1210
|
+
const sfcScriptStartIndex = [];
|
|
1211
|
+
for (const block of scriptBlocks) {
|
|
1212
|
+
const subLang = block.lang === "ts" ? "typescript" : block.lang === "tsx" ? "tsx" : "javascript";
|
|
1213
|
+
const subParser = await getParser2(subLang);
|
|
1214
|
+
const subTree = subParser.parse(block.body);
|
|
1215
|
+
sfcScriptTrees.push(subTree);
|
|
1216
|
+
sfcScriptLines.push(block.startLine);
|
|
1217
|
+
sfcScriptCols.push(block.startColumn);
|
|
1218
|
+
sfcScriptStartIndex.push(block.startIndex);
|
|
1219
|
+
}
|
|
1220
|
+
context = {
|
|
1221
|
+
...context,
|
|
1222
|
+
sfcScriptTrees,
|
|
1223
|
+
sfcScriptLines,
|
|
1224
|
+
sfcScriptCols,
|
|
1225
|
+
sfcScriptStartIndex,
|
|
1226
|
+
sfcScriptLangs: scriptBlocks.map((b) => b.lang)
|
|
1227
|
+
};
|
|
1228
|
+
}
|
|
1229
|
+
} catch (e) {
|
|
1230
|
+
log.debug("sfc script sub-parse failed", { error: e?.message });
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
if (language === "html" && tree?.rootNode) {
|
|
1234
|
+
try {
|
|
1235
|
+
const blocks = extractHtmlEmbeddedBlocks(tree.rootNode, content);
|
|
1236
|
+
if (blocks.length > 0) {
|
|
1237
|
+
const trees = [];
|
|
1238
|
+
for (const block of blocks) {
|
|
1239
|
+
const subParser = await getParser2(block.lang === "ts" ? "typescript" : block.lang === "tsx" ? "tsx" : block.lang === "css" ? "css" : "javascript");
|
|
1240
|
+
trees.push(subParser.parse(block.body));
|
|
1241
|
+
}
|
|
1242
|
+
context = {
|
|
1243
|
+
...context,
|
|
1244
|
+
htmlEmbeddedTrees: trees,
|
|
1245
|
+
htmlEmbeddedLangs: blocks.map((b) => b.lang),
|
|
1246
|
+
htmlEmbeddedStartLines: blocks.map((b) => b.startLine),
|
|
1247
|
+
htmlEmbeddedStartColumns: blocks.map((b) => b.startColumn),
|
|
1248
|
+
htmlEmbeddedStartIndices: blocks.map((b) => b.startIndex)
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
} catch (e) {
|
|
1252
|
+
log.debug("html embedded sub-parse failed", { error: e?.message });
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
if (language === "markdown" && tree?.rootNode) {
|
|
1256
|
+
try {
|
|
1257
|
+
const inlineBlocks = extractMarkdownInlineBlocks(tree.rootNode);
|
|
1258
|
+
if (inlineBlocks.length > 0) {
|
|
1259
|
+
const inlineParser = await getMarkdownInlineParser();
|
|
1260
|
+
const mdInlineTrees = [];
|
|
1261
|
+
const mdInlineStarts = [];
|
|
1262
|
+
const mdInlineLines = [];
|
|
1263
|
+
for (const block of inlineBlocks) {
|
|
1264
|
+
const inlineText = content.substring(block.startIndex, block.endIndex);
|
|
1265
|
+
if (inlineText.trim().length === 0) continue;
|
|
1266
|
+
const subTree = inlineParser.parse(inlineText);
|
|
1267
|
+
mdInlineTrees.push(subTree);
|
|
1268
|
+
mdInlineStarts.push(block.startIndex);
|
|
1269
|
+
mdInlineLines.push(block.startPosition.row + 1);
|
|
1270
|
+
}
|
|
1271
|
+
context = {
|
|
1272
|
+
...context,
|
|
1273
|
+
mdInlineTrees,
|
|
1274
|
+
mdInlineStarts,
|
|
1275
|
+
mdInlineLines
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
} catch (e) {
|
|
1279
|
+
log.debug("markdown inline sub-parse failed", { error: e?.message });
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
const TypeInference = (await import("./type-inference-QMT2RMLV.js")).TypeInference;
|
|
1283
|
+
const enhancedAnalyzer = TypeInference.enhanceAnalyzerWithTypeInference(analyzer, language);
|
|
1284
|
+
analysisResult = enhancedAnalyzer.analyze(tree.rootNode, content, filePath, context);
|
|
1285
|
+
const FrameworkIntelligence = (await import("./framework-intelligence-3LORTPOX.js")).FrameworkIntelligence;
|
|
1286
|
+
analysisResult = FrameworkIntelligence.enhanceWithFrameworkIntelligence(analysisResult, content, language);
|
|
1287
|
+
return analysisResult;
|
|
1288
|
+
})();
|
|
1289
|
+
let timeoutId2;
|
|
1290
|
+
const analyzeTimeoutPromise = new Promise((_, reject) => {
|
|
1291
|
+
timeoutId2 = setTimeout(() => {
|
|
1292
|
+
log.error("analyzer timeout - forcefully aborting", { filePath });
|
|
1293
|
+
reject(new Error(`Analyzer timeout for ${filePath}`));
|
|
1294
|
+
}, 12e4);
|
|
1295
|
+
});
|
|
1296
|
+
let result;
|
|
1297
|
+
try {
|
|
1298
|
+
try {
|
|
1299
|
+
result = await Promise.race([analyzePromise, analyzeTimeoutPromise]);
|
|
1300
|
+
clearTimeout(timeoutId2);
|
|
1301
|
+
} catch (error) {
|
|
1302
|
+
clearTimeout(timeoutId2);
|
|
1303
|
+
log.warn("analyzer timeout, returning basic parse result", {
|
|
1304
|
+
filePath,
|
|
1305
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1306
|
+
});
|
|
1307
|
+
return {
|
|
1308
|
+
language,
|
|
1309
|
+
symbols: [],
|
|
1310
|
+
relationships: [],
|
|
1311
|
+
imports: [],
|
|
1312
|
+
exports: [],
|
|
1313
|
+
errors: [
|
|
1314
|
+
{
|
|
1315
|
+
message: error instanceof Error ? error.message : String(error),
|
|
1316
|
+
range: { startLine: 1, startColumn: 1, endLine: 1, endColumn: 1 },
|
|
1317
|
+
severity: "error"
|
|
1318
|
+
}
|
|
1319
|
+
],
|
|
1320
|
+
rawContent: content,
|
|
1321
|
+
metadata: {
|
|
1322
|
+
complexity: 0,
|
|
1323
|
+
linesOfCode: content.split("\n").length,
|
|
1324
|
+
cyclomaticComplexity: 0,
|
|
1325
|
+
framework: "unknown",
|
|
1326
|
+
architecture: "unknown",
|
|
1327
|
+
patterns: [],
|
|
1328
|
+
detectedFrameworks: [],
|
|
1329
|
+
frameworkPatterns: [],
|
|
1330
|
+
architecturalInsights: [],
|
|
1331
|
+
architecturalScore: 0,
|
|
1332
|
+
codeQuality: "unknown",
|
|
1333
|
+
hasTypeInference: false,
|
|
1334
|
+
hasFrameworkIntelligence: false,
|
|
1335
|
+
analysisVersion: "2.0-basic-fallback"
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
const meta = result.metadata || {};
|
|
1340
|
+
if (language === "html" || language === "vue" || language === "svelte") {
|
|
1341
|
+
const polyglotSymbols = [];
|
|
1342
|
+
const polyglotRels = [];
|
|
1343
|
+
const polyglotImports = [];
|
|
1344
|
+
for (const sym of result.symbols) {
|
|
1345
|
+
if (sym.metadata?.embeddedScriptContent || sym.metadata?.embeddedStyleContent) {
|
|
1346
|
+
const langName = sym.metadata?.embeddedScriptContent ? "inline.js" : "inline.css";
|
|
1347
|
+
const snip = content.substring(sym.range.startIndex, sym.range.endIndex);
|
|
1348
|
+
let match = null;
|
|
1349
|
+
if (langName === "inline.js") match = snip.match(/<script[^>]*>([\s\S]*?)<\/script>/i);
|
|
1350
|
+
else match = snip.match(/<style[^>]*>([\s\S]*?)<\/style>/i);
|
|
1351
|
+
if (match && match[1] && match[1].trim().length > 0) {
|
|
1352
|
+
const innerCode = match[1];
|
|
1353
|
+
const offsetIndex = sym.range.startIndex + match.index + match[0].indexOf(innerCode);
|
|
1354
|
+
const preCode = content.substring(0, offsetIndex);
|
|
1355
|
+
const offsetLine = preCode.split("\n").length - 1;
|
|
1356
|
+
const offsetCol = preCode.length - preCode.lastIndexOf("\n") - 1;
|
|
1357
|
+
try {
|
|
1358
|
+
if (filePath.includes("UltimateSvelteTest.svelte")) {
|
|
1359
|
+
require2("fs").writeFileSync("/tmp/svelte_inner_" + langName + ".txt", innerCode);
|
|
1360
|
+
}
|
|
1361
|
+
const subParse = await ASTEngine2.parseFile(filePath + "." + langName, innerCode);
|
|
1362
|
+
for (const jsSym of subParse.symbols) {
|
|
1363
|
+
jsSym.range.startIndex += offsetIndex;
|
|
1364
|
+
jsSym.range.endIndex += offsetIndex;
|
|
1365
|
+
jsSym.range.startLine += offsetLine;
|
|
1366
|
+
jsSym.range.endLine += offsetLine;
|
|
1367
|
+
jsSym.ownerName = jsSym.ownerName || sym.name;
|
|
1368
|
+
jsSym.metadata = { ...jsSym.metadata, polyglotHost: sym.name, embeddedIn: filePath };
|
|
1369
|
+
polyglotSymbols.push(jsSym);
|
|
1370
|
+
}
|
|
1371
|
+
for (const jsRel of subParse.relationships) {
|
|
1372
|
+
polyglotRels.push(jsRel);
|
|
1373
|
+
}
|
|
1374
|
+
for (const jsImp of subParse.imports) {
|
|
1375
|
+
if (jsImp.range) {
|
|
1376
|
+
if (jsImp.range.startIndex !== void 0) jsImp.range.startIndex += offsetIndex;
|
|
1377
|
+
if (jsImp.range.endIndex !== void 0) jsImp.range.endIndex += offsetIndex;
|
|
1378
|
+
jsImp.range.startLine += offsetLine;
|
|
1379
|
+
jsImp.range.endLine += offsetLine;
|
|
1380
|
+
}
|
|
1381
|
+
polyglotImports.push(jsImp);
|
|
1382
|
+
}
|
|
1383
|
+
} catch (e) {
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
result.symbols.push(...polyglotSymbols);
|
|
1389
|
+
result.relationships.push(...polyglotRels);
|
|
1390
|
+
result.imports.push(...polyglotImports);
|
|
1391
|
+
}
|
|
1392
|
+
return {
|
|
1393
|
+
language,
|
|
1394
|
+
symbols: result.symbols || [],
|
|
1395
|
+
relationships: result.relationships || [],
|
|
1396
|
+
imports: result.imports || [],
|
|
1397
|
+
exports: result.exports || [],
|
|
1398
|
+
errors: [
|
|
1399
|
+
...result.errors || [],
|
|
1400
|
+
...treeErrors,
|
|
1401
|
+
// PY-19: see the truncation branch above. Declared as an error because a partial parse is
|
|
1402
|
+
// exactly what a caller reading `errors` needs to know, and `severity: "warning"` because
|
|
1403
|
+
// the analysis that WAS produced is sound — it is incomplete, not wrong. The percentage is
|
|
1404
|
+
// in the message on purpose: "1 file was truncated" is not actionable, "75% of this file
|
|
1405
|
+
// was never parsed" is.
|
|
1406
|
+
...truncated ? [
|
|
1407
|
+
{
|
|
1408
|
+
message: `input truncated at the 1 MiB parse limit: ${truncated.parsedSize} of ${truncated.originalSize} bytes parsed (${Math.round(100 * truncated.parsedSize / truncated.originalSize)}%), so symbols, relationships and imports below may be incomplete`,
|
|
1409
|
+
range: { startLine: 1, startColumn: 1, endLine: 1, endColumn: 1 },
|
|
1410
|
+
severity: `warning`
|
|
1411
|
+
}
|
|
1412
|
+
] : []
|
|
1413
|
+
],
|
|
1414
|
+
rawContent: result.rawContent,
|
|
1415
|
+
metadata: {
|
|
1416
|
+
// The analyzer's OWN metadata is spread FIRST, so a lane's own keys
|
|
1417
|
+
// survive the trip to the production entry. This object used to be a
|
|
1418
|
+
// fixed allowlist of thirteen fields, and every key outside that list
|
|
1419
|
+
// was silently dropped — which is how the VB lane's `vbGaps` (its
|
|
1420
|
+
// disclosed gaps, the thing the lane exists to report) never reached
|
|
1421
|
+
// `parseFile`, and how `analysisVersion` read `m10.06-cut` for a lane
|
|
1422
|
+
// whose analyzer stamps `m60-vb-1`. A disclosure that is computed and
|
|
1423
|
+
// then thrown away is not a disclosure.
|
|
1424
|
+
...meta,
|
|
1425
|
+
// PY-19: the same disclosure as the `errors` entry, but STRUCTURED. The message is for
|
|
1426
|
+
// a human reading a result; this is for a caller that has to reproduce the parse
|
|
1427
|
+
// exactly — the M14 oracle mirrors the engine's byte-for-byte, and it used to do that
|
|
1428
|
+
// by copying the 1 MiB constant out of this file. A copied constant drifts silently:
|
|
1429
|
+
// move the limit and the oracle keeps cutting at the old value, the two sides parse
|
|
1430
|
+
// different byte ranges, and every relationship past the cut reports as a phantom
|
|
1431
|
+
// analyzer defect. Reading the limit back from here means there is nothing to drift.
|
|
1432
|
+
//
|
|
1433
|
+
// Spread CONDITIONALLY. A `truncated: null` on every file in the corpus would be true
|
|
1434
|
+
// and useless, and it would put a new key into the FILE-level metadata of every lane's
|
|
1435
|
+
// results in order to say nothing. Only a truncated file learns that it was truncated,
|
|
1436
|
+
// which also means no other lane's metadata shape changes at all.
|
|
1437
|
+
...truncated ? { truncated } : {},
|
|
1438
|
+
complexity: meta.complexity || 0,
|
|
1439
|
+
linesOfCode: content.split("\n").length,
|
|
1440
|
+
// These two publish `undefined` as a PRESENT key when the analyzer did
|
|
1441
|
+
// not set them, which is the same defect as the eight scored keys below —
|
|
1442
|
+
// found by the corrected `verify-lua-published-claims` check, which
|
|
1443
|
+
// compares the pipeline's keys against the analyzer's own and named
|
|
1444
|
+
// `architecture` as the one a Lua file receives without producing.
|
|
1445
|
+
//
|
|
1446
|
+
// `framework` is DELIBERATELY left as a plain assignment, and the reason
|
|
1447
|
+
// is a consumer: `script/m60/framework-surface-probe.ts` reports a lane as
|
|
1448
|
+
// missing if `"framework" in meta` is false, so omitting the key would turn
|
|
1449
|
+
// a language that never set it into a reported defect. That is the one
|
|
1450
|
+
// place in the tree where presence is the contract, so presence is kept
|
|
1451
|
+
// there and nowhere else. Making these two conditional is safe for the same
|
|
1452
|
+
// reason the eight are: nothing tests them for presence (0 call sites).
|
|
1453
|
+
...meta.cyclomaticComplexity !== void 0 && { cyclomaticComplexity: meta.cyclomaticComplexity },
|
|
1454
|
+
framework: meta.framework,
|
|
1455
|
+
...meta.architecture !== void 0 && { architecture: meta.architecture },
|
|
1456
|
+
patterns: meta.patterns || [],
|
|
1457
|
+
// NEW: Enhanced intelligence metadata
|
|
1458
|
+
detectedFrameworks: meta.detectedFrameworks || [],
|
|
1459
|
+
frameworkPatterns: meta.frameworkPatterns || [],
|
|
1460
|
+
architecturalInsights: meta.architecturalInsights || [],
|
|
1461
|
+
architecturalScore: meta.architecturalScore || 0,
|
|
1462
|
+
codeQuality: meta.codeQuality || "unknown",
|
|
1463
|
+
// NOT hardcoded `true`. These two are CLAIMS a lane makes about
|
|
1464
|
+
// itself, and lanes make them honestly in both directions: the VB
|
|
1465
|
+
// analyzer reports `false` for both, because it does no type inference
|
|
1466
|
+
// and has no framework intelligence, and the hardcode overwrote that
|
|
1467
|
+
// with `true` on the way out — the product asserting a capability the
|
|
1468
|
+
// lane has explicitly said it lacks. The `?? true` default keeps every
|
|
1469
|
+
// lane that says nothing behaving exactly as it did before, so the only
|
|
1470
|
+
// behaviour that changes is a lane that made the claim and was
|
|
1471
|
+
// overwritten. (kotlin's spec already records this field as real:
|
|
1472
|
+
// "metadata.hasTypeInference stays — declared-type extraction IS real
|
|
1473
|
+
// inference input.")
|
|
1474
|
+
hasTypeInference: meta.hasTypeInference ?? true,
|
|
1475
|
+
hasFrameworkIntelligence: meta.hasFrameworkIntelligence ?? true,
|
|
1476
|
+
// M14 (#888): FORWARD the analyzer's own scored metrics, and do it
|
|
1477
|
+
// WITHOUT materialising the key for a language that did not produce it.
|
|
1478
|
+
//
|
|
1479
|
+
// This object is a fresh literal, so anything an analyzer computes and
|
|
1480
|
+
// this list omits is computed and DISCARDED — silently, because
|
|
1481
|
+
// `FileMetadata` carries an index signature and the extra key
|
|
1482
|
+
// typechecks. The html analyzer measured exactly that: it computed
|
|
1483
|
+
// accessibility / semantic / performance scores, a `score` breakdown and
|
|
1484
|
+
// a `documentMetrics` census, none of which appeared in the parse result
|
|
1485
|
+
// (`"accessibilityScore" in metadata === false`).
|
|
1486
|
+
//
|
|
1487
|
+
// The first version of this fix added the keys as plain assignments:
|
|
1488
|
+
//
|
|
1489
|
+
// accessibilityScore: (meta as any).accessibilityScore,
|
|
1490
|
+
//
|
|
1491
|
+
// and justified it with "each key reads `undefined` for every other
|
|
1492
|
+
// language, which is identical to the key being absent — so this is
|
|
1493
|
+
// additive by construction, not a change to any other lane's payload."
|
|
1494
|
+
//
|
|
1495
|
+
// THAT IS FALSE, and it is worth being precise about why, because the
|
|
1496
|
+
// comment three lines above it is the evidence:
|
|
1497
|
+
//
|
|
1498
|
+
// { x: 1, y: undefined } -> "y" in obj === true, Object.keys === ["x","y"]
|
|
1499
|
+
// { x: 1 } -> "y" in obj === false, Object.keys === ["x"]
|
|
1500
|
+
//
|
|
1501
|
+
// `undefined` is only invisible to `JSON.stringify`, which is the one
|
|
1502
|
+
// operation that drops such keys. `"k" in metadata` and `Object.keys()`
|
|
1503
|
+
// both see them, and a key's PRESENCE is a claim: a consumer testing
|
|
1504
|
+
// `if (metadata.elementCount)` behaves identically, but one testing
|
|
1505
|
+
// `"elementCount" in metadata` — the exact form this file used to prove
|
|
1506
|
+
// the html lane's key was missing — now reads TRUE for every language on
|
|
1507
|
+
// earth. Eight keys were added to all 44 lanes' metadata.
|
|
1508
|
+
//
|
|
1509
|
+
// Found by the LUA lane's `verify-lua-published-claims`, whose eleventh
|
|
1510
|
+
// check asserts the pipeline does not synthesise a metadata block that was
|
|
1511
|
+
// never mapped, because that is precisely the class of defect it exists to
|
|
1512
|
+
// catch: a value that reaches a consumer shaped like a measurement and is
|
|
1513
|
+
// not one. Before this, a Lua file's metadata reported
|
|
1514
|
+
// `documentMetrics`, `elementCount`, `accessibilityScore`, `score` and four
|
|
1515
|
+
// more — all undefined, all belonging to html and toml.
|
|
1516
|
+
//
|
|
1517
|
+
// So a key is added only when the analyzer actually produced it. html and
|
|
1518
|
+
// toml keep theirs; every other language gets the object it had before
|
|
1519
|
+
// #888, which is the "not a change to any other lane's payload" claim
|
|
1520
|
+
// this comment originally intended to make.
|
|
1521
|
+
...meta.accessibilityScore !== void 0 && { accessibilityScore: meta.accessibilityScore },
|
|
1522
|
+
...meta.semanticScore !== void 0 && { semanticScore: meta.semanticScore },
|
|
1523
|
+
...meta.performanceScore !== void 0 && { performanceScore: meta.performanceScore },
|
|
1524
|
+
...meta.score !== void 0 && { score: meta.score },
|
|
1525
|
+
...meta.documentMetrics !== void 0 && { documentMetrics: meta.documentMetrics },
|
|
1526
|
+
...meta.elementCount !== void 0 && { elementCount: meta.elementCount },
|
|
1527
|
+
...meta.addressableNodeCount !== void 0 && { addressableNodeCount: meta.addressableNodeCount },
|
|
1528
|
+
...meta.maxElementDepth !== void 0 && { maxElementDepth: meta.maxElementDepth },
|
|
1529
|
+
analysisVersion: meta.analysisVersion || "m10.06-cut"
|
|
1530
|
+
}
|
|
1531
|
+
};
|
|
1532
|
+
} finally {
|
|
1533
|
+
if (tree && typeof tree.delete === "function") {
|
|
1534
|
+
tree.delete();
|
|
1535
|
+
}
|
|
1536
|
+
if (language === "lua" && transientLuaGrammar) {
|
|
1537
|
+
try {
|
|
1538
|
+
if (parser && typeof parser.delete === "function") parser.delete();
|
|
1539
|
+
} catch {
|
|
1540
|
+
}
|
|
1541
|
+
try {
|
|
1542
|
+
if (typeof transientLuaGrammar.delete === "function") transientLuaGrammar.delete();
|
|
1543
|
+
} catch {
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
ASTEngine2.parseFile = parseFile2;
|
|
1549
|
+
async function getAnalyzer(language) {
|
|
1550
|
+
switch (language) {
|
|
1551
|
+
case "typescript":
|
|
1552
|
+
case "tsx":
|
|
1553
|
+
return new (await import("./real-typescript-analyzer-6KEMVDWQ.js")).RealTypeScriptAnalyzer();
|
|
1554
|
+
case "javascript":
|
|
1555
|
+
return new (await import("./real-javascript-analyzer-QA4QOJ6W.js")).RealJavaScriptAnalyzer();
|
|
1556
|
+
case "html":
|
|
1557
|
+
return new (await import("./real-html-analyzer-JWNX3C6I.js")).RealHtmlAnalyzer();
|
|
1558
|
+
case "css":
|
|
1559
|
+
case "sass":
|
|
1560
|
+
return new (await import("./real-css-analyzer-6XRQLUN7.js")).RealCssAnalyzer();
|
|
1561
|
+
case "scss":
|
|
1562
|
+
return new (await import("./real-scss-analyzer-AVWYPSOQ.js")).RealScssAnalyzer();
|
|
1563
|
+
case "json":
|
|
1564
|
+
return new (await import("./real-json-analyzer-MPA6PRXL.js")).RealJsonAnalyzer();
|
|
1565
|
+
case "yaml":
|
|
1566
|
+
return new (await import("./real-yaml-analyzer-SUBCBNSI.js")).RealYamlAnalyzer();
|
|
1567
|
+
case "perl":
|
|
1568
|
+
return new (await import("./real-perl-analyzer-WWTRHYDT.js")).RealPerlAnalyzer();
|
|
1569
|
+
case "c":
|
|
1570
|
+
return new (await import("./real-c-analyzer-HBD3FNNH.js")).RealCAnalyzer();
|
|
1571
|
+
case "cpp":
|
|
1572
|
+
return new (await import("./real-cpp-analyzer-IVVOD25R.js")).RealCppAnalyzer();
|
|
1573
|
+
case "rust":
|
|
1574
|
+
return new (await import("./real-rust-analyzer-OFFHPL2A.js")).RealRustAnalyzer();
|
|
1575
|
+
case "go":
|
|
1576
|
+
return new (await import("./real-go-analyzer-UKGI43YS.js")).RealGoAnalyzer();
|
|
1577
|
+
case "java":
|
|
1578
|
+
return new (await import("./real-java-analyzer-GU42VBGQ.js")).RealJavaAnalyzer();
|
|
1579
|
+
case "kotlin":
|
|
1580
|
+
return new (await import("./real-kotlin-analyzer-QDZJLXXU.js")).RealKotlinAnalyzer();
|
|
1581
|
+
case "scala":
|
|
1582
|
+
return new (await import("./real-scala-analyzer-TSTW27J6.js")).RealScalaAnalyzer();
|
|
1583
|
+
case "python":
|
|
1584
|
+
return new (await import("./real-python-analyzer-VXAFWI72.js")).RealPythonAnalyzer();
|
|
1585
|
+
case "ruby":
|
|
1586
|
+
return new (await import("./real-ruby-analyzer-X2KTLVBH.js")).RealRubyAnalyzer();
|
|
1587
|
+
case "php":
|
|
1588
|
+
return new (await import("./real-php-analyzer-JNKJHTCL.js")).RealPhpAnalyzer();
|
|
1589
|
+
case "lua":
|
|
1590
|
+
return new (await import("./real-lua-analyzer-G7NHLYKS.js")).RealLuaAnalyzer();
|
|
1591
|
+
case "elixir":
|
|
1592
|
+
return new (await import("./real-elixir-analyzer-MQWGAH2I.js")).RealElixirAnalyzer();
|
|
1593
|
+
case "erlang":
|
|
1594
|
+
return new (await import("./real-erlang-analyzer-7BVPQEHO.js")).RealErlangAnalyzer();
|
|
1595
|
+
case "haskell":
|
|
1596
|
+
return new (await import("./real-haskell-analyzer-5CVVAJRX.js")).RealHaskellAnalyzer();
|
|
1597
|
+
case "clean":
|
|
1598
|
+
return new (await import("./real-clean-analyzer-4EEZLPV5.js")).RealCleanAnalyzer();
|
|
1599
|
+
case "clojure":
|
|
1600
|
+
return new (await import("./real-clojure-analyzer-Q55EBOO2.js")).RealClojureAnalyzer();
|
|
1601
|
+
case "swift":
|
|
1602
|
+
return new (await import("./real-swift-analyzer-MN5QT3QN.js")).RealSwiftAnalyzer();
|
|
1603
|
+
case "julia":
|
|
1604
|
+
return new (await import("./real-julia-analyzer-22CWYQMN.js")).RealJuliaAnalyzer();
|
|
1605
|
+
case "dart":
|
|
1606
|
+
return new (await import("./real-dart-analyzer-OLR72EFW.js")).RealDartAnalyzer();
|
|
1607
|
+
case "csharp":
|
|
1608
|
+
return new (await import("./real-csharp-analyzer-ZBNLNJZJ.js")).RealCSharpAnalyzer();
|
|
1609
|
+
case "r":
|
|
1610
|
+
return new (await import("./real-r-analyzer-ZGAIDVI4.js")).RealRAnalyzer();
|
|
1611
|
+
case "sql":
|
|
1612
|
+
return new (await import("./real-sql-analyzer-F77ZMQXR.js")).RealSqlAnalyzer();
|
|
1613
|
+
case "bash":
|
|
1614
|
+
return new (await import("./real-bash-analyzer-EJAU5LW5.js")).RealBashAnalyzer();
|
|
1615
|
+
case "objective-c":
|
|
1616
|
+
return new (await import("./real-objective-c-analyzer-D23ACC2R.js")).RealObjectiveCAnalyzer();
|
|
1617
|
+
case "groovy":
|
|
1618
|
+
return new (await import("./real-groovy-analyzer-W26VACFW.js")).RealGroovyAnalyzer();
|
|
1619
|
+
case "vue":
|
|
1620
|
+
return new (await import("./real-vue-analyzer-QXR56CFV.js")).RealVueAnalyzer();
|
|
1621
|
+
case "svelte":
|
|
1622
|
+
return new (await import("./real-svelte-analyzer-SF7NRUO5.js")).RealSvelteAnalyzer();
|
|
1623
|
+
case "hcl":
|
|
1624
|
+
case "terraform":
|
|
1625
|
+
return new (await import("./real-hcl-analyzer-5ZT4U43N.js")).RealHclAnalyzer();
|
|
1626
|
+
case "graphql":
|
|
1627
|
+
return new (await import("./real-graphql-analyzer-VE2EEFII.js")).RealGraphqlAnalyzer();
|
|
1628
|
+
// Protobuf: the vendored, patched tree-sitter-proto (see the name map
|
|
1629
|
+
// above and grammars/tree-sitter-proto/README.md).
|
|
1630
|
+
case "protobuf":
|
|
1631
|
+
return new (await import("./real-protobuf-analyzer-3OKUCZ7T.js")).RealProtobufAnalyzer();
|
|
1632
|
+
case "zig":
|
|
1633
|
+
return new (await import("./real-zig-analyzer-HIQLZMGY.js")).RealZigAnalyzer();
|
|
1634
|
+
case "nim":
|
|
1635
|
+
return new (await import("./real-nim-analyzer-YLXSK563.js")).RealNimAnalyzer();
|
|
1636
|
+
case "fsharp":
|
|
1637
|
+
return new (await import("./real-fsharp-analyzer-C2UPFNOA.js")).RealFsharpAnalyzer();
|
|
1638
|
+
case "powershell":
|
|
1639
|
+
return new (await import("./real-powershell-analyzer-XRSNQERV.js")).RealPowershellAnalyzer();
|
|
1640
|
+
case "solidity":
|
|
1641
|
+
return new (await import("./real-solidity-analyzer-UCI2KWUB.js")).RealSolidityAnalyzer();
|
|
1642
|
+
case "make":
|
|
1643
|
+
return new (await import("./real-makefile-analyzer-OCY3GT5N.js")).RealMakefileAnalyzer();
|
|
1644
|
+
case "xml":
|
|
1645
|
+
return new (await import("./real-xml-analyzer-YL465ZJW.js")).RealXmlAnalyzer();
|
|
1646
|
+
case "markdown":
|
|
1647
|
+
return new (await import("./real-markdown-analyzer-TEJK2JXJ.js")).RealMarkdownAnalyzer();
|
|
1648
|
+
case "vb":
|
|
1649
|
+
return new (await import("./real-vb-analyzer-VICVPOP7.js")).RealVbAnalyzer();
|
|
1650
|
+
case "vba":
|
|
1651
|
+
return new (await import("./real-vba-analyzer-HXLTTHKM.js")).RealVbaAnalyzer();
|
|
1652
|
+
case "matlab":
|
|
1653
|
+
return new (await import("./real-matlab-analyzer-Q5SWLN7Z.js")).RealMatlabAnalyzer();
|
|
1654
|
+
case "toml":
|
|
1655
|
+
return new (await import("./real-toml-analyzer-66L7BDCQ.js")).RealTomlAnalyzer();
|
|
1656
|
+
default:
|
|
1657
|
+
return new GenericAnalyzer();
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
const JAVA_STDLIB_TYPES = /* @__PURE__ */ new Set([
|
|
1661
|
+
"String",
|
|
1662
|
+
"Integer",
|
|
1663
|
+
"Boolean",
|
|
1664
|
+
"Long",
|
|
1665
|
+
"Double",
|
|
1666
|
+
"Float",
|
|
1667
|
+
"Byte",
|
|
1668
|
+
"Short",
|
|
1669
|
+
"Character",
|
|
1670
|
+
"Object",
|
|
1671
|
+
"Class",
|
|
1672
|
+
"Number",
|
|
1673
|
+
"Void",
|
|
1674
|
+
"BigDecimal",
|
|
1675
|
+
"BigInteger",
|
|
1676
|
+
"List",
|
|
1677
|
+
"Map",
|
|
1678
|
+
"Set",
|
|
1679
|
+
"Collection",
|
|
1680
|
+
"ArrayList",
|
|
1681
|
+
"HashMap",
|
|
1682
|
+
"HashSet",
|
|
1683
|
+
"Optional",
|
|
1684
|
+
"Stream",
|
|
1685
|
+
"File",
|
|
1686
|
+
"Path",
|
|
1687
|
+
"IOException",
|
|
1688
|
+
"Exception",
|
|
1689
|
+
"RuntimeException",
|
|
1690
|
+
"Thread",
|
|
1691
|
+
"Runnable",
|
|
1692
|
+
"Callable",
|
|
1693
|
+
"Future",
|
|
1694
|
+
"CompletableFuture",
|
|
1695
|
+
"StringBuilder",
|
|
1696
|
+
"StringBuffer",
|
|
1697
|
+
"Pattern",
|
|
1698
|
+
"Matcher"
|
|
1699
|
+
]);
|
|
1700
|
+
const PYTHON_STDLIB_TYPES = /* @__PURE__ */ new Set([
|
|
1701
|
+
"str",
|
|
1702
|
+
"int",
|
|
1703
|
+
"float",
|
|
1704
|
+
"bool",
|
|
1705
|
+
"list",
|
|
1706
|
+
"dict",
|
|
1707
|
+
"set",
|
|
1708
|
+
"tuple",
|
|
1709
|
+
"bytes",
|
|
1710
|
+
"bytearray",
|
|
1711
|
+
"memoryview",
|
|
1712
|
+
"complex",
|
|
1713
|
+
"frozenset",
|
|
1714
|
+
"range",
|
|
1715
|
+
"slice",
|
|
1716
|
+
"type",
|
|
1717
|
+
"object",
|
|
1718
|
+
"Exception",
|
|
1719
|
+
"ValueError",
|
|
1720
|
+
"TypeError",
|
|
1721
|
+
"KeyError",
|
|
1722
|
+
"os",
|
|
1723
|
+
"sys",
|
|
1724
|
+
"json",
|
|
1725
|
+
"re",
|
|
1726
|
+
"datetime",
|
|
1727
|
+
"collections",
|
|
1728
|
+
"itertools",
|
|
1729
|
+
"functools",
|
|
1730
|
+
"pathlib",
|
|
1731
|
+
"Path",
|
|
1732
|
+
"IO",
|
|
1733
|
+
"TextIO"
|
|
1734
|
+
]);
|
|
1735
|
+
const JS_BUILTIN_TYPES = /* @__PURE__ */ new Set([
|
|
1736
|
+
"String",
|
|
1737
|
+
"Number",
|
|
1738
|
+
"Boolean",
|
|
1739
|
+
"Array",
|
|
1740
|
+
"Object",
|
|
1741
|
+
"Function",
|
|
1742
|
+
"Symbol",
|
|
1743
|
+
"Map",
|
|
1744
|
+
"Set",
|
|
1745
|
+
"WeakMap",
|
|
1746
|
+
"WeakSet",
|
|
1747
|
+
"Promise",
|
|
1748
|
+
"RegExp",
|
|
1749
|
+
"Date",
|
|
1750
|
+
"Error",
|
|
1751
|
+
"JSON",
|
|
1752
|
+
"Math",
|
|
1753
|
+
"Intl",
|
|
1754
|
+
"console",
|
|
1755
|
+
"Buffer",
|
|
1756
|
+
"process",
|
|
1757
|
+
"BigInt",
|
|
1758
|
+
"ArrayBuffer",
|
|
1759
|
+
"DataView",
|
|
1760
|
+
"Float32Array",
|
|
1761
|
+
"Float64Array",
|
|
1762
|
+
"Int8Array",
|
|
1763
|
+
"Int16Array",
|
|
1764
|
+
"Int32Array",
|
|
1765
|
+
"Uint8Array",
|
|
1766
|
+
"Uint16Array",
|
|
1767
|
+
"Uint32Array"
|
|
1768
|
+
]);
|
|
1769
|
+
const GO_STDLIB_TYPES = /* @__PURE__ */ new Set([
|
|
1770
|
+
"string",
|
|
1771
|
+
"int",
|
|
1772
|
+
"int8",
|
|
1773
|
+
"int16",
|
|
1774
|
+
"int32",
|
|
1775
|
+
"int64",
|
|
1776
|
+
"uint",
|
|
1777
|
+
"uint8",
|
|
1778
|
+
"uint16",
|
|
1779
|
+
"uint32",
|
|
1780
|
+
"uint64",
|
|
1781
|
+
"uintptr",
|
|
1782
|
+
"float32",
|
|
1783
|
+
"float64",
|
|
1784
|
+
"complex64",
|
|
1785
|
+
"complex128",
|
|
1786
|
+
"bool",
|
|
1787
|
+
"byte",
|
|
1788
|
+
"rune",
|
|
1789
|
+
"error",
|
|
1790
|
+
"Context",
|
|
1791
|
+
"Reader",
|
|
1792
|
+
"Writer",
|
|
1793
|
+
"Closer",
|
|
1794
|
+
"Seeker",
|
|
1795
|
+
"Scanner",
|
|
1796
|
+
"Builder",
|
|
1797
|
+
"File",
|
|
1798
|
+
"ResponseWriter",
|
|
1799
|
+
"Request",
|
|
1800
|
+
"http",
|
|
1801
|
+
"os",
|
|
1802
|
+
"io",
|
|
1803
|
+
"fmt",
|
|
1804
|
+
"strings",
|
|
1805
|
+
"strconv",
|
|
1806
|
+
"time",
|
|
1807
|
+
"sync",
|
|
1808
|
+
"json",
|
|
1809
|
+
"net",
|
|
1810
|
+
"url",
|
|
1811
|
+
"crypto",
|
|
1812
|
+
"encoding"
|
|
1813
|
+
]);
|
|
1814
|
+
const RUST_STDLIB_TYPES = /* @__PURE__ */ new Set([
|
|
1815
|
+
"String",
|
|
1816
|
+
"str",
|
|
1817
|
+
"Vec",
|
|
1818
|
+
"Option",
|
|
1819
|
+
"Result",
|
|
1820
|
+
"Box",
|
|
1821
|
+
"Rc",
|
|
1822
|
+
"Arc",
|
|
1823
|
+
"HashMap",
|
|
1824
|
+
"HashSet",
|
|
1825
|
+
"BTreeMap",
|
|
1826
|
+
"BTreeSet",
|
|
1827
|
+
"LinkedList",
|
|
1828
|
+
"VecDeque",
|
|
1829
|
+
"i8",
|
|
1830
|
+
"i16",
|
|
1831
|
+
"i32",
|
|
1832
|
+
"i64",
|
|
1833
|
+
"i128",
|
|
1834
|
+
"isize",
|
|
1835
|
+
"u8",
|
|
1836
|
+
"u16",
|
|
1837
|
+
"u32",
|
|
1838
|
+
"u64",
|
|
1839
|
+
"u128",
|
|
1840
|
+
"usize",
|
|
1841
|
+
"f32",
|
|
1842
|
+
"f64",
|
|
1843
|
+
"bool",
|
|
1844
|
+
"char",
|
|
1845
|
+
"Path",
|
|
1846
|
+
"PathBuf",
|
|
1847
|
+
"File",
|
|
1848
|
+
"Error",
|
|
1849
|
+
"Iterator",
|
|
1850
|
+
"Clone",
|
|
1851
|
+
"Copy",
|
|
1852
|
+
"Debug",
|
|
1853
|
+
"Display",
|
|
1854
|
+
"std",
|
|
1855
|
+
"core",
|
|
1856
|
+
"alloc",
|
|
1857
|
+
"collections"
|
|
1858
|
+
]);
|
|
1859
|
+
const SWIFT_STDLIB_TYPES = /* @__PURE__ */ new Set([
|
|
1860
|
+
"String",
|
|
1861
|
+
"Int",
|
|
1862
|
+
"Double",
|
|
1863
|
+
"Float",
|
|
1864
|
+
"Bool",
|
|
1865
|
+
"Character",
|
|
1866
|
+
"Array",
|
|
1867
|
+
"Dictionary",
|
|
1868
|
+
"Set",
|
|
1869
|
+
"Optional",
|
|
1870
|
+
"Result",
|
|
1871
|
+
"Data",
|
|
1872
|
+
"URL",
|
|
1873
|
+
"Date",
|
|
1874
|
+
"UUID",
|
|
1875
|
+
"Error",
|
|
1876
|
+
"AnyObject",
|
|
1877
|
+
"AnyClass",
|
|
1878
|
+
"UIView",
|
|
1879
|
+
"UIViewController"
|
|
1880
|
+
]);
|
|
1881
|
+
const ALL_STDLIB_TYPES = /* @__PURE__ */ new Set([
|
|
1882
|
+
...JAVA_STDLIB_TYPES,
|
|
1883
|
+
...PYTHON_STDLIB_TYPES,
|
|
1884
|
+
...JS_BUILTIN_TYPES,
|
|
1885
|
+
...GO_STDLIB_TYPES,
|
|
1886
|
+
...RUST_STDLIB_TYPES,
|
|
1887
|
+
...SWIFT_STDLIB_TYPES
|
|
1888
|
+
]);
|
|
1889
|
+
class GenericAnalyzer {
|
|
1890
|
+
analyze(rootNode, content, filePath, _context) {
|
|
1891
|
+
const symbols = [];
|
|
1892
|
+
const relationships = [];
|
|
1893
|
+
const imports = [];
|
|
1894
|
+
const exports = [];
|
|
1895
|
+
const errors = [];
|
|
1896
|
+
this.traverseNode(rootNode, symbols, content);
|
|
1897
|
+
return {
|
|
1898
|
+
symbols,
|
|
1899
|
+
relationships,
|
|
1900
|
+
imports,
|
|
1901
|
+
exports,
|
|
1902
|
+
errors,
|
|
1903
|
+
metadata: {
|
|
1904
|
+
complexity: this.calculateComplexity(rootNode),
|
|
1905
|
+
patterns: []
|
|
1906
|
+
}
|
|
1907
|
+
};
|
|
1908
|
+
}
|
|
1909
|
+
traverseNode(rootNode, symbols, content) {
|
|
1910
|
+
const walkStack = [rootNode];
|
|
1911
|
+
while (walkStack.length > 0) {
|
|
1912
|
+
const node = walkStack.pop();
|
|
1913
|
+
if (node.isNamed) {
|
|
1914
|
+
const isReasonablySmall = node.endIndex - node.startIndex < 100;
|
|
1915
|
+
if (isReasonablySmall) {
|
|
1916
|
+
const text = node.text;
|
|
1917
|
+
if (text) {
|
|
1918
|
+
let kind = this.mapNodeTypeToSymbolKind(node.type);
|
|
1919
|
+
const upgraded = this.upgradeStdlibKind(text, kind);
|
|
1920
|
+
if (upgraded) kind = upgraded;
|
|
1921
|
+
symbols.push({
|
|
1922
|
+
name: text,
|
|
1923
|
+
kind,
|
|
1924
|
+
range: {
|
|
1925
|
+
startLine: node.startPosition.row + 1,
|
|
1926
|
+
startColumn: node.startPosition.column + 1,
|
|
1927
|
+
endLine: node.endPosition.row + 1,
|
|
1928
|
+
endColumn: node.endPosition.column + 1,
|
|
1929
|
+
startIndex: node.startIndex,
|
|
1930
|
+
endIndex: node.endIndex
|
|
1931
|
+
},
|
|
1932
|
+
metadata: {
|
|
1933
|
+
nodeType: node.type,
|
|
1934
|
+
raw: true
|
|
1935
|
+
}
|
|
1936
|
+
});
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
const childCount = node.namedChildCount;
|
|
1941
|
+
for (let i = childCount - 1; i >= 0; i--) {
|
|
1942
|
+
const child = node.namedChild(i);
|
|
1943
|
+
if (child) {
|
|
1944
|
+
walkStack.push(child);
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
mapNodeTypeToSymbolKind(nodeType) {
|
|
1950
|
+
if (nodeType.includes("function")) return "function" /* Function */;
|
|
1951
|
+
if (nodeType.includes("method")) return "method" /* Method */;
|
|
1952
|
+
if (nodeType.includes("class")) return "class" /* Class */;
|
|
1953
|
+
if (nodeType.includes("interface")) return "interface" /* Interface */;
|
|
1954
|
+
if (nodeType.includes("enum")) return "enum" /* Enum */;
|
|
1955
|
+
if (nodeType.includes("struct")) return "struct" /* Struct */;
|
|
1956
|
+
if (nodeType.includes("trait")) return "trait" /* Trait */;
|
|
1957
|
+
if (nodeType.includes("impl")) return "impl" /* Impl */;
|
|
1958
|
+
if (nodeType.includes("mixin")) return "mixin" /* Mixin */;
|
|
1959
|
+
if (nodeType.includes("extension")) return "extension" /* Extension */;
|
|
1960
|
+
if (nodeType.includes("namespace") || nodeType.includes("module")) return "namespace" /* Namespace */;
|
|
1961
|
+
if (nodeType.includes("constructor")) return "constructor" /* Constructor */;
|
|
1962
|
+
if (nodeType.includes("property") || nodeType.includes("field")) return "property" /* Property */;
|
|
1963
|
+
if (nodeType.includes("variable") || nodeType.includes("identifier") || nodeType.includes("parameter")) return "variable" /* Variable */;
|
|
1964
|
+
if (nodeType.includes("constant")) return "constant" /* Constant */;
|
|
1965
|
+
if (nodeType.includes("import")) return "import" /* Import */;
|
|
1966
|
+
if (nodeType.includes("export")) return "export" /* Export */;
|
|
1967
|
+
if (nodeType.includes("type_alias") || nodeType.includes("type_annotation")) return "type" /* Type */;
|
|
1968
|
+
return "variable" /* Variable */;
|
|
1969
|
+
}
|
|
1970
|
+
// Recognizes common stdlib type names across all 40 languages.
|
|
1971
|
+
// Tree-sitter sees these as plain identifiers (not class_declarations),
|
|
1972
|
+
// so the GenericAnalyzer defaults them to Variable. This upgrades them.
|
|
1973
|
+
// The import-only filter in parallel-indexer catches the rest at storage level.
|
|
1974
|
+
upgradeStdlibKind(name, currentKind) {
|
|
1975
|
+
if (currentKind !== "variable" /* Variable */ && currentKind !== "unknown") return null;
|
|
1976
|
+
if (ALL_STDLIB_TYPES.has(name)) return "class" /* Class */;
|
|
1977
|
+
if (name.length > 1 && name[0] === name[0].toUpperCase() && name[0] !== name[0].toLowerCase()) {
|
|
1978
|
+
return "class" /* Class */;
|
|
1979
|
+
}
|
|
1980
|
+
return null;
|
|
1981
|
+
}
|
|
1982
|
+
calculateComplexity(rootNode) {
|
|
1983
|
+
let complexity = 1;
|
|
1984
|
+
const walkStack = [rootNode];
|
|
1985
|
+
while (walkStack.length > 0) {
|
|
1986
|
+
const node = walkStack.pop();
|
|
1987
|
+
complexity++;
|
|
1988
|
+
const childCount = node.namedChildCount;
|
|
1989
|
+
for (let i = childCount - 1; i >= 0; i--) {
|
|
1990
|
+
const child = node.namedChild(i);
|
|
1991
|
+
if (child) {
|
|
1992
|
+
walkStack.push(child);
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
return Math.min(complexity, 100);
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
async function findSymbol(projectId, symbolName, filePath, lineStart) {
|
|
2000
|
+
const { BrainDatabase } = await import("./database-76RP44JG.js");
|
|
2001
|
+
const db = await BrainDatabase.getReadOnlyInstance(projectId);
|
|
2002
|
+
const { BrainSymbolTable, BrainFileTable } = await import("./brain.sql-EIM4WS4D.js");
|
|
2003
|
+
const { eq, and, like } = await import("drizzle-orm");
|
|
2004
|
+
const conditions = [eq(BrainSymbolTable.project_id, projectId), eq(BrainSymbolTable.name, symbolName)];
|
|
2005
|
+
if (filePath) {
|
|
2006
|
+
const fp = filePath.replace(/\\/g, "/");
|
|
2007
|
+
if (fp.includes("/")) {
|
|
2008
|
+
conditions.push(eq(BrainFileTable.path, fp));
|
|
2009
|
+
} else {
|
|
2010
|
+
conditions.push(like(BrainFileTable.path, `%/${fp}`));
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
let results = await db.select({
|
|
2014
|
+
id: BrainSymbolTable.id,
|
|
2015
|
+
fileId: BrainFileTable.path,
|
|
2016
|
+
name: BrainSymbolTable.name,
|
|
2017
|
+
symbolType: BrainSymbolTable.symbol_type,
|
|
2018
|
+
lineStart: BrainSymbolTable.line_start,
|
|
2019
|
+
byteStart: BrainSymbolTable.byte_start,
|
|
2020
|
+
byteEnd: BrainSymbolTable.byte_end,
|
|
2021
|
+
// The file row is already joined in, so the language is free here. It was
|
|
2022
|
+
// absent, so `bb search --mode symbol` rendered `alpha0 [function]
|
|
2023
|
+
// (m0.ts:1)` with no language while the DEFAULT mode printed
|
|
2024
|
+
// `(typescript, m0.ts:1)` — the two modes disagreed about the same symbol.
|
|
2025
|
+
language: BrainFileTable.language,
|
|
2026
|
+
relativePath: BrainFileTable.relative_path
|
|
2027
|
+
}).from(BrainSymbolTable).innerJoin(BrainFileTable, eq(BrainSymbolTable.file_id, BrainFileTable.id)).where(and(...conditions)).all();
|
|
2028
|
+
if (results.length === 0 && filePath && filePath.includes("/")) {
|
|
2029
|
+
const fp = filePath.replace(/\\/g, "/");
|
|
2030
|
+
results = await db.select({
|
|
2031
|
+
id: BrainSymbolTable.id,
|
|
2032
|
+
fileId: BrainFileTable.path,
|
|
2033
|
+
name: BrainSymbolTable.name,
|
|
2034
|
+
symbolType: BrainSymbolTable.symbol_type,
|
|
2035
|
+
lineStart: BrainSymbolTable.line_start,
|
|
2036
|
+
byteStart: BrainSymbolTable.byte_start,
|
|
2037
|
+
byteEnd: BrainSymbolTable.byte_end,
|
|
2038
|
+
// This fallback SELECT omitted the file columns entirely, so a match
|
|
2039
|
+
// resolved through a relative `filePath` came back with no language
|
|
2040
|
+
// and could not be noise-classified by its relative path.
|
|
2041
|
+
language: BrainFileTable.language,
|
|
2042
|
+
relativePath: BrainFileTable.relative_path
|
|
2043
|
+
}).from(BrainSymbolTable).innerJoin(BrainFileTable, eq(BrainSymbolTable.file_id, BrainFileTable.id)).where(and(
|
|
2044
|
+
eq(BrainSymbolTable.project_id, projectId),
|
|
2045
|
+
eq(BrainSymbolTable.name, symbolName),
|
|
2046
|
+
like(BrainFileTable.path, `%${fp}`)
|
|
2047
|
+
)).all();
|
|
2048
|
+
}
|
|
2049
|
+
for (const r of results) {
|
|
2050
|
+
if ((r.byteStart == null || r.byteEnd == null || r.byteEnd <= r.byteStart) && r.fileId && r.lineStart != null) {
|
|
2051
|
+
try {
|
|
2052
|
+
const fs = require2("fs");
|
|
2053
|
+
const content = decodeSourceText(fs.readFileSync(r.fileId)).text;
|
|
2054
|
+
const lines = content.split("\n");
|
|
2055
|
+
let offset = 0;
|
|
2056
|
+
for (let i = 0; i < Math.min(r.lineStart, lines.length); i++) {
|
|
2057
|
+
offset += lines[i].length + 1;
|
|
2058
|
+
}
|
|
2059
|
+
r.byteStart = offset;
|
|
2060
|
+
const lineEnd = r.lineEnd ?? null;
|
|
2061
|
+
if (lineEnd != null && lineEnd >= r.lineStart) {
|
|
2062
|
+
let endOffset = offset;
|
|
2063
|
+
for (let i = r.lineStart; i < Math.min(lineEnd + 1, lines.length); i++) {
|
|
2064
|
+
endOffset += lines[i].length + 1;
|
|
2065
|
+
}
|
|
2066
|
+
r.byteEnd = endOffset;
|
|
2067
|
+
} else {
|
|
2068
|
+
r.byteEnd = offset + (lines[Math.min(r.lineStart, lines.length - 1)]?.length || 0);
|
|
2069
|
+
}
|
|
2070
|
+
} catch (e) {
|
|
2071
|
+
log.debug("findSymbol: byte-offset repair failed", { error: e?.message });
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
let matches = results;
|
|
2076
|
+
const { isHardNoisePath } = await import("./analysis-exclusions-7ZJDXOVZ.js");
|
|
2077
|
+
matches = matches.filter((m) => !isHardNoisePath(m.relativePath ?? m.fileId ?? ""));
|
|
2078
|
+
if (matches.length > 1 && filePath) {
|
|
2079
|
+
const classSymbols = matches.filter((m) => m.symbolType === "class" || m.symbolType === "interface");
|
|
2080
|
+
if (classSymbols.length === 1) {
|
|
2081
|
+
matches = classSymbols;
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
if (lineStart !== void 0) {
|
|
2085
|
+
matches = matches.filter((m) => m.lineStart === lineStart);
|
|
2086
|
+
}
|
|
2087
|
+
return { matches };
|
|
2088
|
+
}
|
|
2089
|
+
ASTEngine2.findSymbol = findSymbol;
|
|
2090
|
+
function isLanguageSupported(language) {
|
|
2091
|
+
return language in SUPPORTED_LANGUAGES;
|
|
2092
|
+
}
|
|
2093
|
+
ASTEngine2.isLanguageSupported = isLanguageSupported;
|
|
2094
|
+
})(ASTEngine || (ASTEngine = {}));
|
|
2095
|
+
var parseFile = ASTEngine.parseFile;
|
|
2096
|
+
var getParser = ASTEngine.getParser;
|
|
2097
|
+
var getCachedParser = ASTEngine.getCachedParser;
|
|
2098
|
+
|
|
2099
|
+
export {
|
|
2100
|
+
ASTEngine,
|
|
2101
|
+
parseFile,
|
|
2102
|
+
getParser,
|
|
2103
|
+
getCachedParser
|
|
2104
|
+
};
|