@backbencher/brain 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/CHANGELOG.md +298 -0
  2. package/EMBEDDINGS.md +355 -0
  3. package/LICENSE +21 -0
  4. package/README.md +415 -2
  5. package/bin/bb +13 -0
  6. package/dist/analysis-exclusions-7ZJDXOVZ.js +35 -0
  7. package/dist/brain-index-health-KY7K552E.js +17 -0
  8. package/dist/brain-relationship-enrichment-QH7OOHUF.js +558 -0
  9. package/dist/brain.sql-EIM4WS4D.js +29 -0
  10. package/dist/chunk-2BSKD7O3.js +40 -0
  11. package/dist/chunk-2DE27DVC.js +1314 -0
  12. package/dist/chunk-2RRBMNBQ.js +322 -0
  13. package/dist/chunk-2RTN2DFU.js +711 -0
  14. package/dist/chunk-2WXYNLBA.js +29 -0
  15. package/dist/chunk-3CTFIJJB.js +17 -0
  16. package/dist/chunk-3LFTSMIV.js +174 -0
  17. package/dist/chunk-47HKX4AJ.js +930 -0
  18. package/dist/chunk-4H22TLOT.js +543 -0
  19. package/dist/chunk-5SD45FLC.js +818 -0
  20. package/dist/chunk-66A5ZFYA.js +1758 -0
  21. package/dist/chunk-6AIRWAO2.js +247 -0
  22. package/dist/chunk-6WNGD3NN.js +196 -0
  23. package/dist/chunk-7AN7U5IZ.js +371 -0
  24. package/dist/chunk-BHB7BYYI.js +626 -0
  25. package/dist/chunk-BQ3OVQ3P.js +125 -0
  26. package/dist/chunk-CW4XXSNN.js +1479 -0
  27. package/dist/chunk-D2Q4Y47A.js +53 -0
  28. package/dist/chunk-DIYAGQJL.js +34 -0
  29. package/dist/chunk-DYM4FQEE.js +90 -0
  30. package/dist/chunk-EWMWK7WN.js +75 -0
  31. package/dist/chunk-FVVQTSIM.js +3427 -0
  32. package/dist/chunk-FWSL4VG6.js +1290 -0
  33. package/dist/chunk-GBI7V7KY.js +69 -0
  34. package/dist/chunk-GEFFO6O2.js +152 -0
  35. package/dist/chunk-HOWAQXJO.js +236 -0
  36. package/dist/chunk-HQSPJDHI.js +613 -0
  37. package/dist/chunk-IFZNR5UJ.js +2863 -0
  38. package/dist/chunk-J4PMBXQQ.js +336 -0
  39. package/dist/chunk-KAET47ZL.js +125 -0
  40. package/dist/chunk-KCDECRJY.js +440 -0
  41. package/dist/chunk-KLK3PBTO.js +1119 -0
  42. package/dist/chunk-L5TDYKYK.js +76 -0
  43. package/dist/chunk-MLKGABMK.js +9 -0
  44. package/dist/chunk-OWISBAOF.js +61 -0
  45. package/dist/chunk-PJTNGD3Z.js +6924 -0
  46. package/dist/chunk-QLK6ED4Q.js +235 -0
  47. package/dist/chunk-R2GW4F6R.js +19 -0
  48. package/dist/chunk-RCMTFSEF.js +87 -0
  49. package/dist/chunk-RH7KC5HU.js +12050 -0
  50. package/dist/chunk-RM3PY6TG.js +376 -0
  51. package/dist/chunk-ROMM6KMC.js +433 -0
  52. package/dist/chunk-SK6YVHFZ.js +211 -0
  53. package/dist/chunk-SM7RFQRO.js +214 -0
  54. package/dist/chunk-UFE77L67.js +782 -0
  55. package/dist/chunk-UGR4QIGS.js +67 -0
  56. package/dist/chunk-UUNHHX4M.js +13 -0
  57. package/dist/chunk-V44PGPA6.js +2104 -0
  58. package/dist/chunk-VL52PL2T.js +71 -0
  59. package/dist/chunk-VURYFIHW.js +201 -0
  60. package/dist/chunk-XJKJYIPP.js +7436 -0
  61. package/dist/chunk-YI6FF2ZR.js +340 -0
  62. package/dist/cli/index.js +37 -0
  63. package/dist/config-HZAAYDP3.js +10 -0
  64. package/dist/content-search-642F7E5V.js +593 -0
  65. package/dist/database-TCTZDLE5.js +9 -0
  66. package/dist/doctor-GXCKSJOX.js +395 -0
  67. package/dist/edit-engine-KM7MPFEC.js +51 -0
  68. package/dist/engine-42TZFNIZ.js +11 -0
  69. package/dist/engine-LO6L4JLQ.js +18 -0
  70. package/dist/fingerprint-XDXFRWO6.js +33 -0
  71. package/dist/framework-intelligence-DWFCKV44.js +860 -0
  72. package/dist/freshness-3K6VU5OT.js +174 -0
  73. package/dist/graph-engine-PL5YA7BA.js +21 -0
  74. package/dist/graph_request-MM4REP6H.js +350 -0
  75. package/dist/impact_request-WDE47IZ5.js +68 -0
  76. package/dist/index-space-IUUN5WYV.js +15 -0
  77. package/dist/index-status-6BD7UBHR.js +34 -0
  78. package/dist/index.js +159 -0
  79. package/dist/instance-FO6QZRLH.js +19 -0
  80. package/dist/language-detection-DFCAU5DZ.js +11 -0
  81. package/dist/lsp/server.js +4301 -0
  82. package/dist/mcp/server.js +132 -0
  83. package/dist/onboard-DIQZV2NW.js +161 -0
  84. package/dist/override-companion-pass-XR7MHTP7.js +117 -0
  85. package/dist/parallel-indexer-4PW3AFXP.js +88 -0
  86. package/dist/pool-worker.js +1153 -0
  87. package/dist/project-health-ZS5TS2Z6.js +94 -0
  88. package/dist/project-index-5SDPHITE.js +57 -0
  89. package/dist/project-registry-DGZBIZS7.js +355 -0
  90. package/dist/real-bash-analyzer-SXSV67E2.js +2201 -0
  91. package/dist/real-c-analyzer-SY7FTZ6W.js +5942 -0
  92. package/dist/real-clean-analyzer-IGDHHLZK.js +3470 -0
  93. package/dist/real-clojure-analyzer-4OH7IWLB.js +2818 -0
  94. package/dist/real-cpp-analyzer-7LTDRJRJ.js +4101 -0
  95. package/dist/real-csharp-analyzer-KICU3TLH.js +3298 -0
  96. package/dist/real-css-analyzer-HPU277Q6.js +15 -0
  97. package/dist/real-dart-analyzer-7LZ5LCMW.js +3944 -0
  98. package/dist/real-elixir-analyzer-BE3MEVZO.js +2192 -0
  99. package/dist/real-erlang-analyzer-BZMAKYBK.js +1731 -0
  100. package/dist/real-fsharp-analyzer-5QLTOV3E.js +2390 -0
  101. package/dist/real-go-analyzer-POD7MZQR.js +4126 -0
  102. package/dist/real-graphql-analyzer-MAQRZ6QW.js +1442 -0
  103. package/dist/real-groovy-analyzer-MEWSUPMJ.js +2285 -0
  104. package/dist/real-haskell-analyzer-I5L2GR3Y.js +2533 -0
  105. package/dist/real-hcl-analyzer-DBOPXSWJ.js +725 -0
  106. package/dist/real-html-analyzer-O63XZLZD.js +1759 -0
  107. package/dist/real-java-analyzer-CHCW3EKA.js +4677 -0
  108. package/dist/real-javascript-analyzer-QAAJQYZE.js +14 -0
  109. package/dist/real-json-analyzer-UGBR7YQN.js +1640 -0
  110. package/dist/real-julia-analyzer-35Q4GHOZ.js +2085 -0
  111. package/dist/real-kotlin-analyzer-GRAYCWW2.js +3956 -0
  112. package/dist/real-lua-analyzer-5BAPDZDF.js +1957 -0
  113. package/dist/real-makefile-analyzer-YJKAHNAS.js +920 -0
  114. package/dist/real-markdown-analyzer-UKUQZO4F.js +1215 -0
  115. package/dist/real-matlab-analyzer-FVIKQZKG.js +480 -0
  116. package/dist/real-nim-analyzer-M7FAIABG.js +3603 -0
  117. package/dist/real-objective-c-analyzer-XMYQIGQI.js +1518 -0
  118. package/dist/real-perl-analyzer-ZLY6M2DZ.js +1865 -0
  119. package/dist/real-php-analyzer-KI2ZAM7X.js +9368 -0
  120. package/dist/real-powershell-analyzer-B3T5ZP6U.js +2915 -0
  121. package/dist/real-protobuf-analyzer-23OZ75XV.js +867 -0
  122. package/dist/real-python-analyzer-I4TIUB6D.js +4880 -0
  123. package/dist/real-r-analyzer-FJZJXXS6.js +2596 -0
  124. package/dist/real-ruby-analyzer-M3UFIVTQ.js +2429 -0
  125. package/dist/real-rust-analyzer-LVSONPAN.js +3359 -0
  126. package/dist/real-scala-analyzer-CWPI33Q2.js +3293 -0
  127. package/dist/real-scss-analyzer-TGRJQ7TH.js +1515 -0
  128. package/dist/real-solidity-analyzer-4P2VBVWA.js +2608 -0
  129. package/dist/real-sql-analyzer-J7DYZOZR.js +3840 -0
  130. package/dist/real-svelte-analyzer-NHEN2SX5.js +2532 -0
  131. package/dist/real-swift-analyzer-2NSYULWI.js +2311 -0
  132. package/dist/real-toml-analyzer-L3C66L7Q.js +929 -0
  133. package/dist/real-typescript-analyzer-FTC6ETRQ.js +14 -0
  134. package/dist/real-vb-analyzer-ORY7LAQS.js +3145 -0
  135. package/dist/real-vba-analyzer-JH2TTUFI.js +466 -0
  136. package/dist/real-vue-analyzer-OO4FUGBV.js +2680 -0
  137. package/dist/real-xml-analyzer-6CQVR477.js +2405 -0
  138. package/dist/real-yaml-analyzer-J6MQG3YX.js +3528 -0
  139. package/dist/real-zig-analyzer-EFKCPJNU.js +2430 -0
  140. package/dist/regex-search-OPTLKUN5.js +239 -0
  141. package/dist/rules-I453JTRC.js +152 -0
  142. package/dist/scoped-path-MJYWJZQX.js +11 -0
  143. package/dist/setup-show-Y5GB5KXA.js +15 -0
  144. package/dist/setup-wizard-G5YYR5T6.js +24 -0
  145. package/dist/symbol-search-KB4MU4SI.js +16 -0
  146. package/dist/taint-YOTN5X55.js +202 -0
  147. package/dist/taint-analyzer-N7YLZU3N.js +163 -0
  148. package/dist/tool-handlers-G4NAGJIH.js +72 -0
  149. package/dist/tool-registry-BPEJNSZG.js +17 -0
  150. package/dist/tool-validation-RF675A3C.js +32 -0
  151. package/dist/type-inference-4Y7WTMFE.js +13 -0
  152. package/dist/vector-binary-LMY4QGAN.js +19 -0
  153. package/dist/version-LXGNFO37.js +9 -0
  154. package/dist/wasm-NMWO3WXY.js +16 -0
  155. package/docs/EMBEDDINGS.md +132 -0
  156. package/docs/README.md +178 -0
  157. package/docs/data/m10-baseline.json +602 -0
  158. package/docs/data/m10-benchmark-baseline.json +57 -0
  159. package/docs/data/m10-benchmark-last-run.json +127 -0
  160. package/docs/data/m10-final-audit.json +215 -0
  161. package/docs/data/m12-final-audit.json +138 -0
  162. package/docs/data/m12-surface-matrix.json +50 -0
  163. package/docs/data/public-tools.json +1902 -0
  164. package/docs/indexing/DEAD-ASSETS.md +88 -0
  165. package/docs/indexing/INDEXER-REVIEW.md +634 -0
  166. package/docs/indexing/PERFORMANCE-FINDINGS.md +106 -0
  167. package/docs/indexing/README.md +427 -0
  168. package/docs/indexing/discovery-matrix.md +41 -0
  169. package/docs/indexing/embeddings.md +325 -0
  170. package/docs/indexing/environment-variables.md +77 -0
  171. package/docs/indexing/performance.md +323 -0
  172. package/docs/indexing/resume.md +345 -0
  173. package/docs/indexing/troubleshooting.md +391 -0
  174. package/docs/man/bb.1 +190 -0
  175. package/docs/tools/bb_analyze.md +147 -0
  176. package/docs/tools/bb_annotate.md +110 -0
  177. package/docs/tools/bb_annotations.md +106 -0
  178. package/docs/tools/bb_ask.md +101 -0
  179. package/docs/tools/bb_cross_language.md +103 -0
  180. package/docs/tools/bb_doc.md +169 -0
  181. package/docs/tools/bb_edit.md +185 -0
  182. package/docs/tools/bb_graph.md +169 -0
  183. package/docs/tools/bb_health.md +156 -0
  184. package/docs/tools/bb_impact.md +117 -0
  185. package/docs/tools/bb_index.md +108 -0
  186. package/docs/tools/bb_migrate.md +135 -0
  187. package/docs/tools/bb_patterns.md +140 -0
  188. package/docs/tools/bb_search.md +150 -0
  189. package/docs/tools/bb_security.md +100 -0
  190. package/docs/tools/bb_visualize.md +184 -0
  191. package/grammars/README.md +57 -0
  192. package/grammars/THIRD-PARTY-NOTICES.md +50 -0
  193. package/grammars/tree-sitter-c/LICENSE +21 -0
  194. package/grammars/tree-sitter-clojure/LICENSE.md +21 -0
  195. package/grammars/tree-sitter-cpp/LICENSE +21 -0
  196. package/grammars/tree-sitter-csharp/LICENSE +21 -0
  197. package/grammars/tree-sitter-css/LICENSE +21 -0
  198. package/grammars/tree-sitter-css/README.md +21 -0
  199. package/grammars/tree-sitter-dart/LICENSE +20 -0
  200. package/grammars/tree-sitter-dart-upstream/LICENSE +20 -0
  201. package/grammars/tree-sitter-dart-upstream/README.md +18 -0
  202. package/grammars/tree-sitter-elixir/LICENSE +176 -0
  203. package/grammars/tree-sitter-elixir/README.md +11 -0
  204. package/grammars/tree-sitter-fsharp/LICENSE +21 -0
  205. package/grammars/tree-sitter-fsharp/README.md +45 -0
  206. package/grammars/tree-sitter-graphql/LICENSE +21 -0
  207. package/grammars/tree-sitter-graphql/README.md +106 -0
  208. package/grammars/tree-sitter-groovy/LICENSE +21 -0
  209. package/grammars/tree-sitter-groovy/README.md +4 -0
  210. package/grammars/tree-sitter-haskell/LICENSE +21 -0
  211. package/grammars/tree-sitter-haskell/README.md +394 -0
  212. package/grammars/tree-sitter-hcl/CHANGELOG.md +102 -0
  213. package/grammars/tree-sitter-hcl/LICENSE +201 -0
  214. package/grammars/tree-sitter-hcl/README.md +39 -0
  215. package/grammars/tree-sitter-html/LICENSE +21 -0
  216. package/grammars/tree-sitter-html/README.md +21 -0
  217. package/grammars/tree-sitter-julia/LICENSE +21 -0
  218. package/grammars/tree-sitter-julia/README.md +24 -0
  219. package/grammars/tree-sitter-kotlin/LICENSE +9 -0
  220. package/grammars/tree-sitter-lua/LICENSE.md +21 -0
  221. package/grammars/tree-sitter-lua/README.md +29 -0
  222. package/grammars/tree-sitter-make/LICENSE +21 -0
  223. package/grammars/tree-sitter-matlab/LICENSE +19 -0
  224. package/grammars/tree-sitter-matlab/README.md +99 -0
  225. package/grammars/tree-sitter-nim/LICENSE +373 -0
  226. package/grammars/tree-sitter-nim/README.md +46 -0
  227. package/grammars/tree-sitter-objc/LICENSE +21 -0
  228. package/grammars/tree-sitter-objc/README.md +20 -0
  229. package/grammars/tree-sitter-perl/LICENSE +7 -0
  230. package/grammars/tree-sitter-perl/README.md +100 -0
  231. package/grammars/tree-sitter-powershell/LICENSE +21 -0
  232. package/grammars/tree-sitter-powershell/README.md +7 -0
  233. package/grammars/tree-sitter-proto/LICENSE +21 -0
  234. package/grammars/tree-sitter-proto/README.md +105 -0
  235. package/grammars/tree-sitter-r/LICENSE +9 -0
  236. package/grammars/tree-sitter-r/README.md +66 -0
  237. package/grammars/tree-sitter-ruby/LICENSE +22 -0
  238. package/grammars/tree-sitter-scss/LICENSE +21 -0
  239. package/grammars/tree-sitter-scss/README.md +17 -0
  240. package/grammars/tree-sitter-solidity/LICENSE +7 -0
  241. package/grammars/tree-sitter-sql/LICENSE +21 -0
  242. package/grammars/tree-sitter-typescript/LICENSE +21 -0
  243. package/grammars/tree-sitter-vba/LICENSE +21 -0
  244. package/grammars/tree-sitter-vba/README.md +738 -0
  245. package/grammars/tree-sitter-vbnet/LICENSE +21 -0
  246. package/grammars/tree-sitter-vbnet/README.md +322 -0
  247. package/grammars/tree-sitter-xml/LICENSE +19 -0
  248. package/grammars/tree-sitter-yaml/LICENSE +20 -0
  249. package/grammars/tree-sitter-yaml/README.md +21 -0
  250. package/package.json +184 -4
  251. package/wasm/dart.wasm +0 -0
  252. package/wasm/tree-sitter-bash.wasm +0 -0
  253. package/wasm/tree-sitter-c.wasm +0 -0
  254. package/wasm/tree-sitter-c_sharp.wasm +0 -0
  255. package/wasm/tree-sitter-clean.wasm +0 -0
  256. package/wasm/tree-sitter-clojure.wasm +0 -0
  257. package/wasm/tree-sitter-core_schema.wasm +0 -0
  258. package/wasm/tree-sitter-cpp.wasm +0 -0
  259. package/wasm/tree-sitter-css.wasm +0 -0
  260. package/wasm/tree-sitter-dart.wasm +0 -0
  261. package/wasm/tree-sitter-elisp.wasm +0 -0
  262. package/wasm/tree-sitter-elixir.wasm +0 -0
  263. package/wasm/tree-sitter-elm.wasm +0 -0
  264. package/wasm/tree-sitter-embedded_template.wasm +0 -0
  265. package/wasm/tree-sitter-erlang.wasm +0 -0
  266. package/wasm/tree-sitter-fsharp.wasm +0 -0
  267. package/wasm/tree-sitter-fsharp_signature.wasm +0 -0
  268. package/wasm/tree-sitter-go.wasm +0 -0
  269. package/wasm/tree-sitter-graphql.wasm +0 -0
  270. package/wasm/tree-sitter-groovy.wasm +0 -0
  271. package/wasm/tree-sitter-haskell.wasm +0 -0
  272. package/wasm/tree-sitter-hcl.wasm +0 -0
  273. package/wasm/tree-sitter-html.wasm +0 -0
  274. package/wasm/tree-sitter-java.wasm +0 -0
  275. package/wasm/tree-sitter-javascript.wasm +0 -0
  276. package/wasm/tree-sitter-json.wasm +0 -0
  277. package/wasm/tree-sitter-json_schema.wasm +0 -0
  278. package/wasm/tree-sitter-julia.wasm +0 -0
  279. package/wasm/tree-sitter-kotlin.wasm +0 -0
  280. package/wasm/tree-sitter-lua.wasm +0 -0
  281. package/wasm/tree-sitter-make.wasm +0 -0
  282. package/wasm/tree-sitter-markdown.wasm +0 -0
  283. package/wasm/tree-sitter-markdown_inline.wasm +0 -0
  284. package/wasm/tree-sitter-matlab.wasm +0 -0
  285. package/wasm/tree-sitter-nim.wasm +0 -0
  286. package/wasm/tree-sitter-objc.wasm +0 -0
  287. package/wasm/tree-sitter-ocaml.wasm +0 -0
  288. package/wasm/tree-sitter-perl.wasm +0 -0
  289. package/wasm/tree-sitter-php.wasm +0 -0
  290. package/wasm/tree-sitter-php_only.wasm +0 -0
  291. package/wasm/tree-sitter-powershell.wasm +0 -0
  292. package/wasm/tree-sitter-protobuf.wasm +0 -0
  293. package/wasm/tree-sitter-python.wasm +0 -0
  294. package/wasm/tree-sitter-ql.wasm +0 -0
  295. package/wasm/tree-sitter-r.wasm +0 -0
  296. package/wasm/tree-sitter-rescript.wasm +0 -0
  297. package/wasm/tree-sitter-ruby.wasm +0 -0
  298. package/wasm/tree-sitter-rust.wasm +0 -0
  299. package/wasm/tree-sitter-scala.wasm +0 -0
  300. package/wasm/tree-sitter-scss.wasm +0 -0
  301. package/wasm/tree-sitter-solidity.wasm +0 -0
  302. package/wasm/tree-sitter-sql.wasm +0 -0
  303. package/wasm/tree-sitter-svelte.wasm +0 -0
  304. package/wasm/tree-sitter-swift.wasm +0 -0
  305. package/wasm/tree-sitter-systemrdl.wasm +0 -0
  306. package/wasm/tree-sitter-terraform.wasm +0 -0
  307. package/wasm/tree-sitter-tlaplus.wasm +0 -0
  308. package/wasm/tree-sitter-toml.wasm +0 -0
  309. package/wasm/tree-sitter-tsx.wasm +0 -0
  310. package/wasm/tree-sitter-typescript.wasm +0 -0
  311. package/wasm/tree-sitter-vba.wasm +0 -0
  312. package/wasm/tree-sitter-vbnet.wasm +0 -0
  313. package/wasm/tree-sitter-vue.wasm +0 -0
  314. package/wasm/tree-sitter-xml.wasm +0 -0
  315. package/wasm/tree-sitter-yaml.wasm +0 -0
  316. package/wasm/tree-sitter-zig.wasm +0 -0
  317. package/wasm/tree-sitter.wasm +0 -0
  318. package/wasm/tsx.wasm +0 -0
  319. package/wasm/typescript.wasm +0 -0
@@ -0,0 +1,920 @@
1
+ import {
2
+ ASTEngine
3
+ } from "./chunk-V44PGPA6.js";
4
+ import "./chunk-BQ3OVQ3P.js";
5
+ import "./chunk-SK6YVHFZ.js";
6
+ import "./chunk-2BSKD7O3.js";
7
+ import "./chunk-KAET47ZL.js";
8
+ import "./chunk-KCDECRJY.js";
9
+ import "./chunk-MLKGABMK.js";
10
+
11
+ // src/ast/real-makefile-analyzer.ts
12
+ var GNU_MAKE_NAMESPACE = /* @__PURE__ */ new Set([
13
+ // builtin and implicit variables (the same spellings the analyzer's inner list uses)
14
+ "MAKE",
15
+ "MAKEFILE_LIST",
16
+ "MAKEFILES",
17
+ "MAKEFLAGS",
18
+ "MAKECMDGOALS",
19
+ "MAKELEVEL",
20
+ "CURDIR",
21
+ "SUFFIXES",
22
+ ".DEFAULT_GOAL",
23
+ "VPATH",
24
+ "SHELL",
25
+ "MFLAGS",
26
+ "CC",
27
+ "CXX",
28
+ "CPP",
29
+ "AR",
30
+ "ARFLAGS",
31
+ "AS",
32
+ "ASFLAGS",
33
+ "LD",
34
+ "LDFLAGS",
35
+ "LDLIBS",
36
+ "RM",
37
+ "CFLAGS",
38
+ "CXXFLAGS",
39
+ "CPPFLAGS",
40
+ "YFLAGS",
41
+ "LEX",
42
+ "YACC",
43
+ "AWK",
44
+ "FC",
45
+ "GET",
46
+ "PC",
47
+ "TEX",
48
+ "TEXI2DVI",
49
+ "WEAVE",
50
+ "CWEAVE",
51
+ "CTANGLE",
52
+ // automatic variables, as emitted
53
+ "$@",
54
+ "$%",
55
+ "$<",
56
+ "$?",
57
+ "$^",
58
+ "$+",
59
+ "$*",
60
+ "$|",
61
+ "$(@D)",
62
+ "$(@F)",
63
+ "$(%D)",
64
+ "$(%F)",
65
+ "$(<D)",
66
+ "$(<F)",
67
+ "$(?D)",
68
+ "$(?F)",
69
+ "$(^D)",
70
+ "$(^F)",
71
+ "$(+D)",
72
+ "$(+F)",
73
+ "$(*D)",
74
+ "$(*F)",
75
+ "$(|D)",
76
+ "$(|F)"
77
+ ]);
78
+ var GNU_MAKE_NAMESPACE_ROOTS = [...GNU_MAKE_NAMESPACE];
79
+ function isBareMakeName(s) {
80
+ if (s.length === 0) return false;
81
+ const first = s.charCodeAt(0);
82
+ if (!(first >= 65 && first <= 90 || first >= 97 && first <= 122 || first === 95)) return false;
83
+ for (let i = 1; i < s.length; i++) {
84
+ const c = s.charCodeAt(i);
85
+ if (!(c >= 65 && c <= 90 || c >= 97 && c <= 122 || c >= 48 && c <= 57 || c === 95)) return false;
86
+ }
87
+ return true;
88
+ }
89
+ function makeExternalClaim(kind, target, evidenceClass) {
90
+ if (kind !== ASTEngine.RelationshipType.Uses) return {};
91
+ if (GNU_MAKE_NAMESPACE.has(target)) return { languageNamespace: GNU_MAKE_NAMESPACE_ROOTS };
92
+ if (evidenceClass === "external" && isBareMakeName(target)) return { isExternal: true };
93
+ return {};
94
+ }
95
+ var RealMakefileAnalyzer = class {
96
+ analyze(rootNode, content, filePath) {
97
+ const symbols = [];
98
+ const relationships = [];
99
+ const imports = [];
100
+ const exports = [];
101
+ const errors = [];
102
+ const patterns = [];
103
+ const moduleName = this.moduleName(filePath);
104
+ const byKey = /* @__PURE__ */ new Map();
105
+ const relSeen = /* @__PURE__ */ new Set();
106
+ const declared = /* @__PURE__ */ new Set();
107
+ const localBinders = /* @__PURE__ */ new Set();
108
+ const declaredTargets = /* @__PURE__ */ new Set();
109
+ const valuesByName = /* @__PURE__ */ new Map();
110
+ const edgeCount = { references: 0, uses: 0, calls: 0, contains: 0, exports: 0, imports: 0 };
111
+ let conditionals = 0;
112
+ const declareSymbol = (name, kind, node, metadata) => {
113
+ if (!name) return null;
114
+ declared.add(name);
115
+ const key = `${name}\0${kind}`;
116
+ const existing = byKey.get(key);
117
+ if (existing) {
118
+ const m = existing.metadata;
119
+ if (metadata.value !== void 0) m.value = metadata.value;
120
+ if (metadata.operator !== void 0) m.operator = metadata.operator;
121
+ if (metadata.redeclared) m.redeclared = true;
122
+ return existing;
123
+ }
124
+ const sym = {
125
+ name,
126
+ kind,
127
+ range: this.nodeToRange(node),
128
+ visibility: "global",
129
+ metadata
130
+ };
131
+ byKey.set(key, sym);
132
+ symbols.push(sym);
133
+ return sym;
134
+ };
135
+ const addRel = (source, type, target, line, metadata) => {
136
+ if (!source || !target || source === target) return;
137
+ const key = `${source}\0${type}\0${target}\0${line}`;
138
+ if (relSeen.has(key)) return;
139
+ relSeen.add(key);
140
+ edgeCount[type] = (edgeCount[type] ?? 0) + 1;
141
+ relationships.push({
142
+ source,
143
+ target,
144
+ type,
145
+ confidence: 1,
146
+ metadata: metadata ?? {},
147
+ line_number: line,
148
+ line
149
+ });
150
+ };
151
+ const moduleSymbol = declareSymbol(moduleName, ASTEngine.SymbolKind.Module, rootNode, {
152
+ nodeType: "makefile",
153
+ isMakeModule: true,
154
+ filePath
155
+ });
156
+ const module = moduleName;
157
+ const staged = [];
158
+ const BUILTIN_VARIABLES = /* @__PURE__ */ new Set([
159
+ "MAKE",
160
+ "MAKEFILE_LIST",
161
+ "MAKEFILES",
162
+ "MAKEFLAGS",
163
+ "MAKECMDGOALS",
164
+ "MAKELEVEL",
165
+ "CURDIR",
166
+ "SUFFIXES",
167
+ ".DEFAULT_GOAL",
168
+ "VPATH",
169
+ "SHELL",
170
+ "MFLAGS",
171
+ "CC",
172
+ "CXX",
173
+ "CPP",
174
+ "AR",
175
+ "ARFLAGS",
176
+ "AS",
177
+ "ASFLAGS",
178
+ "LD",
179
+ "LDFLAGS",
180
+ "LDLIBS",
181
+ "RM",
182
+ "CFLAGS",
183
+ "CXXFLAGS",
184
+ "CPPFLAGS",
185
+ "YFLAGS",
186
+ "LEX",
187
+ "YACC",
188
+ "AWK",
189
+ "FC",
190
+ "GET",
191
+ "PC",
192
+ "TEX",
193
+ "TEXI2DVI",
194
+ "WEAVE",
195
+ "CWEAVE",
196
+ "CTANGLE"
197
+ ]);
198
+ const BUILTIN_FUNCTIONS = /* @__PURE__ */ new Set([
199
+ "subst",
200
+ "patsubst",
201
+ "strip",
202
+ "findstring",
203
+ "filter",
204
+ "filter-out",
205
+ "sort",
206
+ "word",
207
+ "wordlist",
208
+ "words",
209
+ "firstword",
210
+ "lastword",
211
+ "dir",
212
+ "notdir",
213
+ "suffix",
214
+ "basename",
215
+ "addsuffix",
216
+ "addprefix",
217
+ "join",
218
+ "wildcard",
219
+ "realpath",
220
+ "abspath",
221
+ "if",
222
+ "or",
223
+ "and",
224
+ "foreach",
225
+ "file",
226
+ "call",
227
+ "value",
228
+ "eval",
229
+ "origin",
230
+ "flavor",
231
+ "shell",
232
+ "error",
233
+ "warning",
234
+ "info"
235
+ ]);
236
+ const KEYWORDS = /* @__PURE__ */ new Set([
237
+ "export",
238
+ "unexport",
239
+ "override",
240
+ "private",
241
+ "define",
242
+ "endef",
243
+ "include",
244
+ "-include",
245
+ "sinclude",
246
+ "vpath",
247
+ "undefine",
248
+ "ifeq",
249
+ "ifneq",
250
+ "ifdef",
251
+ "ifndef",
252
+ "else",
253
+ "endif",
254
+ "silent",
255
+ "quiet"
256
+ ]);
257
+ const stack = [{ node: rootNode, owner: module }];
258
+ const trimOperator = (raw) => {
259
+ let end = raw.length;
260
+ while (end > 0) {
261
+ const c = raw.charCodeAt(end - 1);
262
+ if (c === 63 || c === 43 || c === 61 || c === 33 || c === 58) end--;
263
+ else break;
264
+ }
265
+ return raw.slice(0, end).trim();
266
+ };
267
+ const normaliseExpression = (raw) => {
268
+ const t = raw.trim();
269
+ const braced = t.length > 3 && t.startsWith("$(") && t.endsWith(")");
270
+ const curly = t.length > 3 && t.startsWith("${") && t.endsWith("}");
271
+ if (braced || curly) {
272
+ const inner = t.slice(2, -1).trim();
273
+ if (inner.length > 0 && this.isPlainIdentifier(inner)) return { name: inner, isExpression: false };
274
+ return { name: inner, isExpression: true };
275
+ }
276
+ return { name: t, isExpression: false };
277
+ };
278
+ const declaredName = (node) => {
279
+ const w = this.firstChildOfType(node, /* @__PURE__ */ new Set(["word"]));
280
+ if (!w) return "";
281
+ const raw = w.text.trim();
282
+ if (!raw) return "";
283
+ const trimmed = trimOperator(raw);
284
+ if (!trimmed || KEYWORDS.has(trimmed)) return "";
285
+ return trimmed;
286
+ };
287
+ const markExported = (name, node, via) => {
288
+ if (!name) return;
289
+ const existing = symbols.find((s) => s.name === name);
290
+ if (existing) existing.metadata.isExported = true;
291
+ exports.push({
292
+ name,
293
+ kind: existing?.kind ?? ASTEngine.SymbolKind.Constant,
294
+ range: this.nodeToRange(node),
295
+ metadata: { via }
296
+ });
297
+ addRel(module, ASTEngine.RelationshipType.Exports, name, node.startPosition.row + 1, { via, evidenceClass: "export_directive" });
298
+ };
299
+ const deferred = [];
300
+ const declaredAtLines = /* @__PURE__ */ new Map();
301
+ const overrideSites = [];
302
+ while (stack.length > 0) {
303
+ const frame = stack.pop();
304
+ const node = frame.node;
305
+ const owner = frame.owner;
306
+ const type = node.type;
307
+ const line = node.startPosition.row + 1;
308
+ let childOwner = owner;
309
+ switch (type) {
310
+ // ---- variables --------------------------------------------------
311
+ case "variable_assignment":
312
+ case "shell_assignment": {
313
+ const name = declaredName(node);
314
+ if (name) {
315
+ const valueNode = this.firstChildOfType(node, /* @__PURE__ */ new Set(["text", "shell_command"]));
316
+ const value = valueNode?.text?.trim() ?? "";
317
+ if (!valuesByName.has(name)) valuesByName.set(name, value);
318
+ declareSymbol(name, ASTEngine.SymbolKind.Constant, node, {
319
+ nodeType: type,
320
+ isMakeVariable: true,
321
+ operator: this.assignmentOperator(node),
322
+ value: value || void 0
323
+ });
324
+ patterns.push("Make variables");
325
+ addRel(module, ASTEngine.RelationshipType.Contains, name, line, { role: "declaration", evidenceClass: "declared_in_file" });
326
+ declaredAtLines.set(name, [...declaredAtLines.get(name) ?? [], line]);
327
+ childOwner = name;
328
+ }
329
+ break;
330
+ }
331
+ // A macro is a FUNCTION, not a constant: `$(call NAME)` is a call, and a
332
+ // call that resolves to a Constant is a callee that cannot be called.
333
+ case "define_directive": {
334
+ const name = declaredName(node);
335
+ if (name) {
336
+ const body = this.firstChildOfType(node, /* @__PURE__ */ new Set(["raw_text"]));
337
+ if (!valuesByName.has(name)) valuesByName.set(name, body?.text ?? "");
338
+ declareSymbol(name, ASTEngine.SymbolKind.Function, node, {
339
+ nodeType: type,
340
+ isMakeMacro: true,
341
+ operator: "define",
342
+ value: body?.text?.trim() || void 0
343
+ });
344
+ patterns.push("Make macros");
345
+ addRel(module, ASTEngine.RelationshipType.Contains, name, line, { role: "declaration", evidenceClass: "declared_in_file" });
346
+ childOwner = name;
347
+ }
348
+ break;
349
+ }
350
+ // ---- rules ------------------------------------------------------
351
+ case "rule": {
352
+ const targetsNode = this.firstChildOfType(node, /* @__PURE__ */ new Set(["targets"]));
353
+ const literalTargets = [];
354
+ if (targetsNode) {
355
+ for (let i = 0; i < targetsNode.namedChildCount; i++) {
356
+ const child = targetsNode.namedChild(i);
357
+ if (!child) continue;
358
+ const raw = child.text.trim();
359
+ if (!raw) continue;
360
+ if (child.type === "word") {
361
+ if (KEYWORDS.has(raw)) continue;
362
+ if (raw.startsWith(".")) continue;
363
+ literalTargets.push(raw);
364
+ declaredTargets.add(raw);
365
+ declareSymbol(raw, ASTEngine.SymbolKind.Function, node, {
366
+ nodeType: "rule",
367
+ isMakeTarget: true,
368
+ targetName: raw
369
+ });
370
+ addRel(module, ASTEngine.RelationshipType.Contains, raw, line, { role: "declaration", evidenceClass: "declared_in_file" });
371
+ patterns.push("Make rules");
372
+ } else {
373
+ this.collectFrom(
374
+ child,
375
+ (refName, intent, refLine) => {
376
+ const { name: norm } = normaliseExpression(refName);
377
+ staged.push({ source: module, target: norm || refName, line: refLine, intent, role: "computed_target", node: child });
378
+ },
379
+ (binder) => localBinders.add(binder)
380
+ );
381
+ }
382
+ }
383
+ }
384
+ for (let i = 0; i < node.namedChildCount; i++) {
385
+ const child = node.namedChild(i);
386
+ if (child?.type !== "prerequisites") continue;
387
+ for (let j = 0; j < child.namedChildCount; j++) {
388
+ const prereq = child.namedChild(j);
389
+ if (!prereq) continue;
390
+ const raw = prereq.text.trim();
391
+ if (!raw) continue;
392
+ const { name } = normaliseExpression(raw);
393
+ if (!name || KEYWORDS.has(name)) continue;
394
+ for (const t of literalTargets.length ? literalTargets : [module]) {
395
+ staged.push({ source: t, target: name, line: prereq.startPosition.row + 1, intent: "ref", role: "prerequisite", node: prereq });
396
+ }
397
+ }
398
+ }
399
+ if (literalTargets.length > 0) childOwner = literalTargets[0];
400
+ break;
401
+ }
402
+ // ---- includes ---------------------------------------------------
403
+ case "include_directive": {
404
+ const isOptional = node.text.trim().startsWith("-") || node.text.trim().startsWith("s");
405
+ const listNode = this.firstChildOfType(node, /* @__PURE__ */ new Set(["list"]));
406
+ if (listNode) {
407
+ for (let i = 0; i < listNode.namedChildCount; i++) {
408
+ const child = listNode.namedChild(i);
409
+ if (!child) continue;
410
+ if (child.type === "word") {
411
+ const lit = child.text.trim();
412
+ if (lit && !KEYWORDS.has(lit)) {
413
+ const litLine = child.startPosition.row + 1;
414
+ imports.push({ module: lit, items: [], importType: "make_include", lineNumber: litLine, line: litLine, range: this.nodeToRange(node), isExternal: false, isOptional });
415
+ addRel(module, ASTEngine.RelationshipType.Imports, lit, litLine, { isMakeInclude: true, isOptional });
416
+ this.addIncludePartOf(addRel, module, lit, litLine, { isOptional, evidenceClass: "include_literal" });
417
+ }
418
+ continue;
419
+ }
420
+ if (child.type === "function_call" || child.type === "variable_reference" || child.type === "shell_function") {
421
+ const expr = child.text.trim();
422
+ const eLine = child.startPosition.row + 1;
423
+ if (expr) {
424
+ imports.push({ module: expr, items: [], importType: "make_include", lineNumber: eLine, line: eLine, range: this.nodeToRange(node), isExternal: false, isOptional, isComputed: true });
425
+ addRel(module, ASTEngine.RelationshipType.Imports, expr, eLine, { isMakeInclude: true, isOptional, isComputed: true, evidenceClass: "include_computed" });
426
+ }
427
+ continue;
428
+ }
429
+ this.collectFrom(child, (refName, _intent, refLine) => {
430
+ const mod = refName.trim();
431
+ if (!mod || KEYWORDS.has(mod)) return;
432
+ imports.push({
433
+ module: mod,
434
+ items: [],
435
+ importType: "make_include",
436
+ lineNumber: refLine,
437
+ line: refLine,
438
+ range: this.nodeToRange(node),
439
+ isExternal: false,
440
+ isOptional
441
+ });
442
+ addRel(module, ASTEngine.RelationshipType.Imports, mod, refLine, { isMakeInclude: true, isOptional, evidenceClass: "include_literal" });
443
+ });
444
+ }
445
+ } else {
446
+ this.collectFrom(node, () => {
447
+ });
448
+ const expr = listNode ? "" : node.text.trim();
449
+ if (expr) {
450
+ const eLine = node.startPosition.row + 1;
451
+ imports.push({ module: expr, items: [], importType: "make_include", lineNumber: eLine, line: eLine, range: this.nodeToRange(node), isExternal: false, isOptional, isComputed: true });
452
+ addRel(module, ASTEngine.RelationshipType.Imports, expr, eLine, { isMakeInclude: true, isOptional, isComputed: true });
453
+ }
454
+ this.collectFrom(node, (refName, _intent, refLine) => {
455
+ const mod = refName.trim();
456
+ if (!mod || KEYWORDS.has(mod)) return;
457
+ imports.push({ module: mod, items: [], importType: "make_include", lineNumber: refLine, line: refLine, range: this.nodeToRange(node), isExternal: false, isOptional });
458
+ addRel(module, ASTEngine.RelationshipType.Imports, mod, refLine, { isMakeInclude: true, isOptional });
459
+ });
460
+ }
461
+ patterns.push("Make includes");
462
+ break;
463
+ }
464
+ // ---- export -----------------------------------------------------
465
+ // `export FOO = 1` wraps an assignment (the generic walk already reaches
466
+ // it); `export FOO` wraps a `list` and is the ONLY place that name
467
+ // appears, so without this branch the export is invisible entirely.
468
+ case "export_directive": {
469
+ const listNode = this.firstChildOfType(node, /* @__PURE__ */ new Set(["list"]));
470
+ if (listNode) {
471
+ for (let i = 0; i < listNode.namedChildCount; i++) {
472
+ const w = listNode.namedChild(i);
473
+ if (!w) continue;
474
+ const name = trimOperator(w.text.trim());
475
+ if (!name || KEYWORDS.has(name)) continue;
476
+ if (!declared.has(name)) {
477
+ declareSymbol(name, ASTEngine.SymbolKind.Constant, w, { nodeType: "export_directive", isMakeVariable: true, declaredBy: "export" });
478
+ patterns.push("Make variables");
479
+ addRel(module, ASTEngine.RelationshipType.Contains, name, w.startPosition.row + 1, { role: "declaration", evidenceClass: "declared_in_file" });
480
+ }
481
+ markExported(name, w, "export_directive");
482
+ }
483
+ } else {
484
+ const inner = this.firstChildOfType(node, /* @__PURE__ */ new Set(["variable_assignment", "shell_assignment"]));
485
+ const name = inner ? declaredName(inner) : "";
486
+ if (name) markExported(name, node, "export_directive");
487
+ }
488
+ break;
489
+ }
490
+ case "unexport_directive": {
491
+ const listNode = this.firstChildOfType(node, /* @__PURE__ */ new Set(["list"]));
492
+ for (let i = 0; listNode && i < listNode.namedChildCount; i++) {
493
+ const w = listNode.namedChild(i);
494
+ if (!w) continue;
495
+ const name = trimOperator(w.text.trim());
496
+ if (!name) continue;
497
+ const s = symbols.find((x) => x.name === name);
498
+ if (s) s.metadata.isExported = false;
499
+ for (let k = exports.length - 1; k >= 0; k--) {
500
+ if (exports[k].name === name) exports.splice(k, 1);
501
+ }
502
+ for (let k = relationships.length - 1; k >= 0; k--) {
503
+ const r = relationships[k];
504
+ if (r.type === ASTEngine.RelationshipType.Exports && r.target === name) {
505
+ relationships.splice(k, 1);
506
+ edgeCount[ASTEngine.RelationshipType.Exports] = (edgeCount[ASTEngine.RelationshipType.Exports] ?? 1) - 1;
507
+ relSeen.delete(`${r.source}\0${r.type}\0${r.target}\0${r.line_number}`);
508
+ }
509
+ }
510
+ }
511
+ break;
512
+ }
513
+ case "vpath_directive": {
514
+ patterns.push("Make vpath");
515
+ break;
516
+ }
517
+ // MAKE-G1, closed. `VPATH = src:include` is the ASSIGNMENT spelling of the
518
+ // search path; the sibling `vpath %.c src` DIRECTIVE has been recorded all
519
+ // along, so the two spellings of one feature were deliberately asymmetric
520
+ // pending corpus evidence, and the corpus had none (0 occurrences in the
521
+ // 100 pinned files).
522
+ //
523
+ // What was actually lost is not a "coverage" gap in the abstract: because
524
+ // `VPATH` was never declared, a reference to it fell to `uses` — the class
525
+ // this lane reserves for names nothing can declare — even though THIS file
526
+ // is the thing that declares it. `exports := $(VPATH)` in a file that sets
527
+ // `VPATH = src` was published as a read of something undeclared.
528
+ //
529
+ // So it is declared, as a `constant`: `VPATH` is a GNU Make builtin whose
530
+ // value a makefile may set, exactly like `CURDIR` or `MAKEFILE_LIST`, and
531
+ // recording it as an ordinary assignment is what makes the reference to it
532
+ // a `references` edge. The search directories are kept in metadata as a
533
+ // list, because the value text is colon-separated and a consumer asking
534
+ // "where does this makefile look for `foo.o`?" wants the list, not the
535
+ // string it was written as.
536
+ case "VPATH_assignment": {
537
+ const pathsNode = this.firstChildOfType(node, /* @__PURE__ */ new Set(["paths"]));
538
+ const dirs = [];
539
+ if (pathsNode) {
540
+ for (let i = 0; i < pathsNode.namedChildCount; i++) {
541
+ const w = pathsNode.namedChild(i);
542
+ if (w?.type === "word") {
543
+ const d = w.text.trim();
544
+ if (d) dirs.push(d);
545
+ }
546
+ }
547
+ }
548
+ const value = dirs.join(":");
549
+ if (!declared.has("VPATH")) {
550
+ declareSymbol("VPATH", ASTEngine.SymbolKind.Constant, node, {
551
+ nodeType: "VPATH_assignment",
552
+ isMakeVariable: true,
553
+ isMakeSearchPath: true,
554
+ operator: this.assignmentOperator(node),
555
+ value: value || void 0,
556
+ searchPaths: dirs.length ? dirs : void 0
557
+ });
558
+ patterns.push("Make vpath");
559
+ addRel(module, ASTEngine.RelationshipType.Contains, "VPATH", node.startPosition.row + 1, {
560
+ role: "declaration",
561
+ evidenceClass: "declared_in_file"
562
+ });
563
+ }
564
+ break;
565
+ }
566
+ // ---- control flow ------------------------------------------------
567
+ case "conditional":
568
+ case "ifeq_directive":
569
+ case "ifneq_directive":
570
+ case "ifdef_directive":
571
+ case "ifndef_directive":
572
+ case "else_directive":
573
+ case "elsif_directive": {
574
+ conditionals++;
575
+ break;
576
+ }
577
+ case "override_directive":
578
+ case "private_directive":
579
+ case "undefine_directive": {
580
+ let name = "";
581
+ if (type === "undefine_directive") {
582
+ const operand = node.childForFieldName("variable");
583
+ name = operand ? trimOperator(operand.text.trim()) : "";
584
+ } else {
585
+ const inner = this.firstChildOfType(node, /* @__PURE__ */ new Set(["variable_assignment", "shell_assignment"]));
586
+ name = inner ? declaredName(inner) : "";
587
+ }
588
+ if (name) {
589
+ const key = type === "private_directive" ? "isPrivate" : type === "override_directive" ? "isOverride" : "isUndefine";
590
+ deferred.push({ name, key, line: node.startPosition.row + 1 });
591
+ if (type === "override_directive") overrideSites.push({ name, line: node.startPosition.row + 1 });
592
+ const s = symbols.find((x) => x.name === name);
593
+ if (s) s.metadata[key] = true;
594
+ }
595
+ childOwner = name || owner;
596
+ break;
597
+ }
598
+ // ---- references --------------------------------------------------
599
+ // Handled wherever they appear, not only beneath an assignment or a
600
+ // rule. A bare top-level `$(foreach t,… $(eval $(call mk,$(t))))` — the
601
+ // idiom nomad/GNUmakefile uses to reify its package targets — is a
602
+ // `function_call` directly under `makefile`, and because the old walk
603
+ // only asked for references from two branches, that line contributed
604
+ // nothing at all.
605
+ case "variable_reference":
606
+ case "substitution_reference":
607
+ case "automatic_variable":
608
+ case "function_call": {
609
+ const parentType = this.parentType(node);
610
+ if (parentType !== "prerequisites" && parentType !== "targets") {
611
+ this.collectFrom(
612
+ node,
613
+ (refName, intent, refLine) => {
614
+ staged.push({ source: owner, target: refName, line: refLine, intent, role: type, node });
615
+ },
616
+ (binder) => localBinders.add(binder)
617
+ );
618
+ }
619
+ break;
620
+ }
621
+ }
622
+ for (let i = node.namedChildCount - 1; i >= 0; i--) {
623
+ const child = node.namedChild(i);
624
+ if (child) stack.push({ node: child, owner: childOwner });
625
+ }
626
+ }
627
+ for (const d of deferred) {
628
+ const s = symbols.find((x) => x.name === d.name);
629
+ if (s) s.metadata[d.key] = true;
630
+ }
631
+ for (const site of overrideSites) {
632
+ const base = (declaredAtLines.get(site.name) ?? []).filter((l) => l !== site.line);
633
+ if (base.length === 0) continue;
634
+ addRel(module, ASTEngine.RelationshipType.Overrides, site.name, site.line, {
635
+ role: "redefinition",
636
+ via: "override_directive",
637
+ overrideLine: site.line,
638
+ baseLine: Math.min(...base),
639
+ evidenceClass: "redefinition"
640
+ });
641
+ }
642
+ for (const e of staged) {
643
+ if (!e.target) continue;
644
+ const isBuiltinVar = BUILTIN_VARIABLES.has(e.target);
645
+ let kind;
646
+ let label;
647
+ if (e.intent === "call") {
648
+ kind = ASTEngine.RelationshipType.Calls;
649
+ label = "call";
650
+ } else if (declared.has(e.target)) {
651
+ kind = ASTEngine.RelationshipType.References;
652
+ label = "reference";
653
+ } else {
654
+ kind = ASTEngine.RelationshipType.Uses;
655
+ label = e.target.startsWith("$$") ? "shell_variable" : e.role === "automatic_variable" ? "automatic" : localBinders.has(e.target) ? "local_binding" : isBuiltinVar ? "builtin" : e.role === "prerequisite" ? "external_prerequisite" : "external";
656
+ }
657
+ addRel(e.source, kind, e.target, e.line, {
658
+ role: e.role,
659
+ evidenceClass: label,
660
+ isBuiltin: isBuiltinVar,
661
+ ...makeExternalClaim(kind, e.target, label)
662
+ });
663
+ }
664
+ for (const t of declaredTargets) {
665
+ if (symbols.some((s) => s.name === t && s.metadata?.isExported === true)) continue;
666
+ const sym = symbols.find((s) => s.name === t);
667
+ exports.push({ name: t, kind: ASTEngine.SymbolKind.Function, range: sym?.range, metadata: { via: "target" } });
668
+ addRel(module, ASTEngine.RelationshipType.Exports, t, sym?.range?.startLine ?? 1, { via: "target", evidenceClass: "export_target" });
669
+ }
670
+ return {
671
+ language: "make",
672
+ symbols,
673
+ relationships,
674
+ imports,
675
+ exports,
676
+ errors,
677
+ metadata: {
678
+ // A Make-specific, RELATIVE complexity: buildable targets plus decision
679
+ // points. Absolute timings are meaningless across 99 files of very
680
+ // different sizes, and this is only ever compared within the analyzer
681
+ // family, so it is documented as a count and not as a cost.
682
+ complexity: declaredTargets.size + conditionals,
683
+ linesOfCode: content.split("\n").length,
684
+ patterns: [...new Set(patterns)],
685
+ framework: "Make",
686
+ variableCount: valuesByName.size,
687
+ targetCount: declaredTargets.size,
688
+ conditionalCount: conditionals,
689
+ moduleName,
690
+ edgeCount
691
+ }
692
+ };
693
+ }
694
+ /** The assignment operator between name and value, from node positions. */
695
+ assignmentOperator(node) {
696
+ const nameNode = this.firstChildOfType(node, /* @__PURE__ */ new Set(["word"]));
697
+ const valueNode = this.firstChildOfType(node, /* @__PURE__ */ new Set(["text", "shell_command"]));
698
+ if (nameNode && valueNode) {
699
+ const text = node.text ?? "";
700
+ const gap = text.slice(nameNode.endIndex - node.startIndex, valueNode.startIndex - node.startIndex).trim();
701
+ if (gap) return gap;
702
+ }
703
+ return "=";
704
+ }
705
+ /**
706
+ * Every reference inside `node`, as (name, intent, line).
707
+ *
708
+ * Handles the four reference-bearing node types the grammar produces and
709
+ * nothing else. `substitution_reference` is a sibling of `variable_reference`,
710
+ * not a child of it, so reading only the latter loses `$(VAR:.c=.o)`.
711
+ */
712
+ collectFrom(node, emit, onForeachBinder = () => {
713
+ }) {
714
+ const BUILTIN_FUNCTIONS = /* @__PURE__ */ new Set([
715
+ "subst",
716
+ "patsubst",
717
+ "strip",
718
+ "findstring",
719
+ "filter",
720
+ "filter-out",
721
+ "sort",
722
+ "word",
723
+ "wordlist",
724
+ "words",
725
+ "firstword",
726
+ "lastword",
727
+ "dir",
728
+ "notdir",
729
+ "suffix",
730
+ "basename",
731
+ "addsuffix",
732
+ "addprefix",
733
+ "join",
734
+ "wildcard",
735
+ "realpath",
736
+ "abspath",
737
+ "if",
738
+ "or",
739
+ "and",
740
+ "foreach",
741
+ "file",
742
+ "call",
743
+ "value",
744
+ "eval",
745
+ "origin",
746
+ "flavor",
747
+ "shell",
748
+ "error",
749
+ "warning",
750
+ "info"
751
+ ]);
752
+ const stack = [node];
753
+ while (stack.length > 0) {
754
+ const n = stack.pop();
755
+ const line = n.startPosition.row + 1;
756
+ if (n.type === "variable_reference" || n.type === "substitution_reference") {
757
+ if (n.text.startsWith("$$")) {
758
+ for (let i = n.namedChildCount - 1; i >= 0; i--) {
759
+ const c = n.namedChild(i);
760
+ if (c) stack.push(c);
761
+ }
762
+ continue;
763
+ }
764
+ const w = this.firstChildOfType(n, /* @__PURE__ */ new Set(["word"]));
765
+ const name = w?.text?.trim() ?? "";
766
+ if (name) {
767
+ if (!this.isAllDigits(name)) emit(name, "ref", line);
768
+ } else {
769
+ const cat = this.firstChildOfType(n, /* @__PURE__ */ new Set(["concatenation"]));
770
+ const catName = cat?.text?.trim() ?? "";
771
+ if (catName && !this.isAllDigits(catName)) emit(catName, "ref", line);
772
+ }
773
+ } else if (n.type === "automatic_variable") {
774
+ const w = this.firstChildOfType(n, /* @__PURE__ */ new Set(["word"]));
775
+ emit(w?.text?.trim() || n.text.trim(), "ref", line);
776
+ } else if (n.type === "function_call") {
777
+ const argsNode = this.firstChildOfType(n, /* @__PURE__ */ new Set(["arguments"]));
778
+ const nameEnd = argsNode ? argsNode.startIndex - n.startIndex : Math.max(0, n.text.length - 1);
779
+ const name = this.firstToken(n.text.slice(2, nameEnd).trim());
780
+ if (name === "foreach" && argsNode) {
781
+ const binder = (argsNode.text ?? "").split(",")[0]?.trim() ?? "";
782
+ if (binder) onForeachBinder(binder);
783
+ }
784
+ if (name === "call") {
785
+ const callee = (argsNode?.text ?? "").split(",")[0]?.trim() ?? "";
786
+ if (callee && !BUILTIN_FUNCTIONS.has(callee) && !this.isAllDigits(callee)) emit(callee, "call", line);
787
+ } else if (name && !BUILTIN_FUNCTIONS.has(name)) {
788
+ emit(name, "ref", line);
789
+ }
790
+ }
791
+ for (let i = n.namedChildCount - 1; i >= 0; i--) {
792
+ const c = n.namedChild(i);
793
+ if (c) stack.push(c);
794
+ }
795
+ }
796
+ }
797
+ parentType(node) {
798
+ const p = node.parent;
799
+ return p ? String(p.type) : "";
800
+ }
801
+ /**
802
+ * The module symbol's name: the file's own name.
803
+ *
804
+ * The path is split by CHARACTER CODE, not by a pattern. This function used
805
+ * to end in a `String.prototype.split` on a two-character regular expression,
806
+ * which was the only regex literal in the file, and
807
+ * `script/m12/make-contract-probe.ts`'s "analyzer source has no regex
808
+ * literals" check found it — a gate that existed, ran, and had simply never
809
+ * been executed for this lane. A rule that is never run is not a rule.
810
+ *
811
+ * (The comment above used to quote the old expression verbatim, which made the
812
+ * detector fire on the COMMENT. The detector only exempts `//` line comments,
813
+ * and that strictness is correct: a regex quoted in a doc comment reads to the
814
+ * next maintainer as a regex in the file.)
815
+ */
816
+ moduleName(filePath) {
817
+ if (!filePath) return "makefile";
818
+ let end = filePath.length;
819
+ while (end > 0) {
820
+ const c = filePath.charCodeAt(end - 1);
821
+ if (c === 47 || c === 92) break;
822
+ end--;
823
+ }
824
+ return filePath.slice(end) || "makefile";
825
+ }
826
+ /**
827
+ * The module-symbol name an included path would carry, or "" when the path's
828
+ * last segment is an expression or syntax rather than a name.
829
+ *
830
+ * Every makefile is given ONE module symbol named for its file (the same
831
+ * spelling `moduleName()` produces), so the symbol-shaped target for an
832
+ * include is the INCLUDED FILE'S BASENAME — never the written path, which
833
+ * the resolver has no space for. The path is kept in `metadata.partPath`
834
+ * where a reader can check it against the source line. A glob (`*.mk`) or a
835
+ * path whose last segment contains `$`, quotes or shell metacharacters names
836
+ * no file this parse can know, so it is refused rather than guessed at.
837
+ */
838
+ includePartSymbol(pathText) {
839
+ const slash = pathText.lastIndexOf("/");
840
+ const base = slash >= 0 ? pathText.slice(slash + 1) : pathText;
841
+ if (base.length === 0) return "";
842
+ for (let i = 0; i < base.length; i++) {
843
+ const c = base.charCodeAt(i);
844
+ if (c <= 32 || c === 34 || c === 39 || c === 96 || c === 36 || c === 40 || c === 41 || c === 123 || c === 125 || c === 91 || c === 93 || c === 42 || c === 63 || c === 59 || c === 124 || c === 38 || c === 60 || c === 62 || c === 92 || c === 126) {
845
+ return "";
846
+ }
847
+ }
848
+ return base;
849
+ }
850
+ /**
851
+ * `include` IS the textual-inclusion construct: make splices the included
852
+ * file's text into THIS make instance's scope — the same single-shared-scope
853
+ * fact bash's `source` asserts — so a literal include earns a `part_of` edge
854
+ * from this file's module to the INCLUDED file's module symbol.
855
+ *
856
+ * Computed includes (`include $(shell …)`) and glob operands name no file
857
+ * this parse can know, so they earn no edge here: the `imports` row already
858
+ * records the expression, and a `part_of` whose target is an expression
859
+ * string would be an edge to nothing.
860
+ */
861
+ addIncludePartOf(addRel, source, pathText, line, extra) {
862
+ const partSymbol = this.includePartSymbol(pathText);
863
+ if (!partSymbol) return;
864
+ addRel(source, ASTEngine.RelationshipType.PartOf, partSymbol, line, {
865
+ // MANDATORY on every `part_of` row: the direction is the directive's own,
866
+ // and this file carries it and names the part.
867
+ partRole: "library",
868
+ partPath: pathText,
869
+ partSymbol,
870
+ isMakeIncludePart: true,
871
+ ...extra
872
+ });
873
+ }
874
+ isPlainIdentifier(s) {
875
+ if (s.length === 0) return false;
876
+ const first = s.charCodeAt(0);
877
+ const okFirst = (c) => c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95;
878
+ if (!okFirst(first)) return false;
879
+ for (let i = 1; i < s.length; i++) {
880
+ const c = s.charCodeAt(i);
881
+ if (!okFirst(c) && !(c >= 48 && c <= 57) && c !== 46 && c !== 45 && c !== 47) return false;
882
+ }
883
+ return true;
884
+ }
885
+ firstChildOfType(node, types) {
886
+ for (let i = 0; i < node.namedChildCount; i++) {
887
+ const child = node.namedChild(i);
888
+ if (child && types.has(child.type)) return child;
889
+ }
890
+ return null;
891
+ }
892
+ isAllDigits(name) {
893
+ if (name.length === 0) return false;
894
+ for (let i = 0; i < name.length; i++) {
895
+ const c = name.charCodeAt(i);
896
+ if (c < 48 || c > 57) return false;
897
+ }
898
+ return true;
899
+ }
900
+ firstToken(raw) {
901
+ for (let i = 0; i < raw.length; i++) {
902
+ const c = raw[i];
903
+ if (c === " " || c === " " || c === "," || c === "(") return raw.slice(0, i);
904
+ }
905
+ return raw;
906
+ }
907
+ nodeToRange(node) {
908
+ return {
909
+ startLine: node.startPosition.row + 1,
910
+ startColumn: node.startPosition.column,
911
+ endLine: node.endPosition.row + 1,
912
+ endColumn: node.endPosition.column,
913
+ startIndex: node.startIndex,
914
+ endIndex: node.endIndex
915
+ };
916
+ }
917
+ };
918
+ export {
919
+ RealMakefileAnalyzer
920
+ };