@untangle-code/parser-registry 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 (345) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +90 -0
  3. package/README.md +352 -2
  4. package/THIRD_PARTY_LICENSES.md +91 -0
  5. package/dist/boundaries/expression.d.ts +10 -0
  6. package/dist/boundaries/expression.d.ts.map +1 -0
  7. package/dist/boundaries/expression.js +95 -0
  8. package/dist/boundaries/expression.js.map +1 -0
  9. package/dist/boundaries/extract.d.ts +12 -0
  10. package/dist/boundaries/extract.d.ts.map +1 -0
  11. package/dist/boundaries/extract.js +259 -0
  12. package/dist/boundaries/extract.js.map +1 -0
  13. package/dist/boundaries/python.d.ts +6 -0
  14. package/dist/boundaries/python.d.ts.map +1 -0
  15. package/dist/boundaries/python.js +154 -0
  16. package/dist/boundaries/python.js.map +1 -0
  17. package/dist/index.d.ts +26 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +19 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/languages/astgrep-backend/adapter.d.ts +101 -0
  22. package/dist/languages/astgrep-backend/adapter.d.ts.map +1 -0
  23. package/dist/languages/astgrep-backend/adapter.js +130 -0
  24. package/dist/languages/astgrep-backend/adapter.js.map +1 -0
  25. package/dist/languages/astgrep-backend/index.d.ts +29 -0
  26. package/dist/languages/astgrep-backend/index.d.ts.map +1 -0
  27. package/dist/languages/astgrep-backend/index.js +28 -0
  28. package/dist/languages/astgrep-backend/index.js.map +1 -0
  29. package/dist/languages/astgrep-backend/lang/bash.d.ts +38 -0
  30. package/dist/languages/astgrep-backend/lang/bash.d.ts.map +1 -0
  31. package/dist/languages/astgrep-backend/lang/bash.js +42 -0
  32. package/dist/languages/astgrep-backend/lang/bash.js.map +1 -0
  33. package/dist/languages/astgrep-backend/lang/c.d.ts +33 -0
  34. package/dist/languages/astgrep-backend/lang/c.d.ts.map +1 -0
  35. package/dist/languages/astgrep-backend/lang/c.js +85 -0
  36. package/dist/languages/astgrep-backend/lang/c.js.map +1 -0
  37. package/dist/languages/astgrep-backend/lang/cpp.d.ts +27 -0
  38. package/dist/languages/astgrep-backend/lang/cpp.d.ts.map +1 -0
  39. package/dist/languages/astgrep-backend/lang/cpp.js +38 -0
  40. package/dist/languages/astgrep-backend/lang/cpp.js.map +1 -0
  41. package/dist/languages/astgrep-backend/lang/csharp.d.ts +24 -0
  42. package/dist/languages/astgrep-backend/lang/csharp.d.ts.map +1 -0
  43. package/dist/languages/astgrep-backend/lang/csharp.js +102 -0
  44. package/dist/languages/astgrep-backend/lang/csharp.js.map +1 -0
  45. package/dist/languages/astgrep-backend/lang/index.d.ts +29 -0
  46. package/dist/languages/astgrep-backend/lang/index.d.ts.map +1 -0
  47. package/dist/languages/astgrep-backend/lang/index.js +22 -0
  48. package/dist/languages/astgrep-backend/lang/index.js.map +1 -0
  49. package/dist/languages/astgrep-backend/lang/java.d.ts +26 -0
  50. package/dist/languages/astgrep-backend/lang/java.d.ts.map +1 -0
  51. package/dist/languages/astgrep-backend/lang/java.js +89 -0
  52. package/dist/languages/astgrep-backend/lang/java.js.map +1 -0
  53. package/dist/languages/astgrep-backend/lang/kotlin.d.ts +44 -0
  54. package/dist/languages/astgrep-backend/lang/kotlin.d.ts.map +1 -0
  55. package/dist/languages/astgrep-backend/lang/kotlin.js +94 -0
  56. package/dist/languages/astgrep-backend/lang/kotlin.js.map +1 -0
  57. package/dist/languages/astgrep-backend/lang/php.d.ts +23 -0
  58. package/dist/languages/astgrep-backend/lang/php.d.ts.map +1 -0
  59. package/dist/languages/astgrep-backend/lang/php.js +80 -0
  60. package/dist/languages/astgrep-backend/lang/php.js.map +1 -0
  61. package/dist/languages/astgrep-backend/lang/ruby.d.ts +37 -0
  62. package/dist/languages/astgrep-backend/lang/ruby.d.ts.map +1 -0
  63. package/dist/languages/astgrep-backend/lang/ruby.js +70 -0
  64. package/dist/languages/astgrep-backend/lang/ruby.js.map +1 -0
  65. package/dist/languages/astgrep-backend/lang/swift.d.ts +34 -0
  66. package/dist/languages/astgrep-backend/lang/swift.d.ts.map +1 -0
  67. package/dist/languages/astgrep-backend/lang/swift.js +86 -0
  68. package/dist/languages/astgrep-backend/lang/swift.js.map +1 -0
  69. package/dist/languages/astgrep-backend/languages.d.ts +55 -0
  70. package/dist/languages/astgrep-backend/languages.d.ts.map +1 -0
  71. package/dist/languages/astgrep-backend/languages.js +214 -0
  72. package/dist/languages/astgrep-backend/languages.js.map +1 -0
  73. package/dist/languages/astgrep-backend/napi.d.ts +71 -0
  74. package/dist/languages/astgrep-backend/napi.d.ts.map +1 -0
  75. package/dist/languages/astgrep-backend/napi.js +176 -0
  76. package/dist/languages/astgrep-backend/napi.js.map +1 -0
  77. package/dist/languages/astgrep-backend/syntax.d.ts +88 -0
  78. package/dist/languages/astgrep-backend/syntax.d.ts.map +1 -0
  79. package/dist/languages/astgrep-backend/syntax.js +180 -0
  80. package/dist/languages/astgrep-backend/syntax.js.map +1 -0
  81. package/dist/languages/index.d.ts +14 -0
  82. package/dist/languages/index.d.ts.map +1 -0
  83. package/dist/languages/index.js +37 -0
  84. package/dist/languages/index.js.map +1 -0
  85. package/dist/languages/javascript/index.d.ts +4 -0
  86. package/dist/languages/javascript/index.d.ts.map +1 -0
  87. package/dist/languages/javascript/index.js +7 -0
  88. package/dist/languages/javascript/index.js.map +1 -0
  89. package/dist/languages/jsx/index.d.ts +4 -0
  90. package/dist/languages/jsx/index.d.ts.map +1 -0
  91. package/dist/languages/jsx/index.js +7 -0
  92. package/dist/languages/jsx/index.js.map +1 -0
  93. package/dist/languages/prose/index.d.ts +53 -0
  94. package/dist/languages/prose/index.d.ts.map +1 -0
  95. package/dist/languages/prose/index.js +172 -0
  96. package/dist/languages/prose/index.js.map +1 -0
  97. package/dist/languages/prose/line-bytes.d.ts +31 -0
  98. package/dist/languages/prose/line-bytes.d.ts.map +1 -0
  99. package/dist/languages/prose/line-bytes.js +39 -0
  100. package/dist/languages/prose/line-bytes.js.map +1 -0
  101. package/dist/languages/python/create-adapter.d.ts +20 -0
  102. package/dist/languages/python/create-adapter.d.ts.map +1 -0
  103. package/dist/languages/python/create-adapter.js +9 -0
  104. package/dist/languages/python/create-adapter.js.map +1 -0
  105. package/dist/languages/python/index.d.ts +4 -0
  106. package/dist/languages/python/index.d.ts.map +1 -0
  107. package/dist/languages/python/index.js +6 -0
  108. package/dist/languages/python/index.js.map +1 -0
  109. package/dist/languages/python/profile.d.ts +36 -0
  110. package/dist/languages/python/profile.d.ts.map +1 -0
  111. package/dist/languages/python/profile.js +282 -0
  112. package/dist/languages/python/profile.js.map +1 -0
  113. package/dist/languages/python/signature.d.ts +53 -0
  114. package/dist/languages/python/signature.d.ts.map +1 -0
  115. package/dist/languages/python/signature.js +188 -0
  116. package/dist/languages/python/signature.js.map +1 -0
  117. package/dist/languages/python/table.d.ts +46 -0
  118. package/dist/languages/python/table.d.ts.map +1 -0
  119. package/dist/languages/python/table.js +88 -0
  120. package/dist/languages/python/table.js.map +1 -0
  121. package/dist/languages/shared/call-detection.d.ts +17 -0
  122. package/dist/languages/shared/call-detection.d.ts.map +1 -0
  123. package/dist/languages/shared/call-detection.js +86 -0
  124. package/dist/languages/shared/call-detection.js.map +1 -0
  125. package/dist/languages/shared/chunks.d.ts +28 -0
  126. package/dist/languages/shared/chunks.d.ts.map +1 -0
  127. package/dist/languages/shared/chunks.js +181 -0
  128. package/dist/languages/shared/chunks.js.map +1 -0
  129. package/dist/languages/shared/create-adapter.d.ts +11 -0
  130. package/dist/languages/shared/create-adapter.d.ts.map +1 -0
  131. package/dist/languages/shared/create-adapter.js +90 -0
  132. package/dist/languages/shared/create-adapter.js.map +1 -0
  133. package/dist/languages/shared/decisions.d.ts +45 -0
  134. package/dist/languages/shared/decisions.d.ts.map +1 -0
  135. package/dist/languages/shared/decisions.js +141 -0
  136. package/dist/languages/shared/decisions.js.map +1 -0
  137. package/dist/languages/shared/dialect.d.ts +18 -0
  138. package/dist/languages/shared/dialect.d.ts.map +1 -0
  139. package/dist/languages/shared/dialect.js +37 -0
  140. package/dist/languages/shared/dialect.js.map +1 -0
  141. package/dist/languages/shared/doc-binding.d.ts +26 -0
  142. package/dist/languages/shared/doc-binding.d.ts.map +1 -0
  143. package/dist/languages/shared/doc-binding.js +50 -0
  144. package/dist/languages/shared/doc-binding.js.map +1 -0
  145. package/dist/languages/shared/engine.d.ts +49 -0
  146. package/dist/languages/shared/engine.d.ts.map +1 -0
  147. package/dist/languages/shared/engine.js +317 -0
  148. package/dist/languages/shared/engine.js.map +1 -0
  149. package/dist/languages/shared/extract-symbols.d.ts +5 -0
  150. package/dist/languages/shared/extract-symbols.d.ts.map +1 -0
  151. package/dist/languages/shared/extract-symbols.js +31 -0
  152. package/dist/languages/shared/extract-symbols.js.map +1 -0
  153. package/dist/languages/shared/fingerprint.d.ts +7 -0
  154. package/dist/languages/shared/fingerprint.d.ts.map +1 -0
  155. package/dist/languages/shared/fingerprint.js +95 -0
  156. package/dist/languages/shared/fingerprint.js.map +1 -0
  157. package/dist/languages/shared/grammar-loader.d.ts +15 -0
  158. package/dist/languages/shared/grammar-loader.d.ts.map +1 -0
  159. package/dist/languages/shared/grammar-loader.js +48 -0
  160. package/dist/languages/shared/grammar-loader.js.map +1 -0
  161. package/dist/languages/shared/import-detection.d.ts +24 -0
  162. package/dist/languages/shared/import-detection.d.ts.map +1 -0
  163. package/dist/languages/shared/import-detection.js +138 -0
  164. package/dist/languages/shared/import-detection.js.map +1 -0
  165. package/dist/languages/shared/js-family-profile.d.ts +5 -0
  166. package/dist/languages/shared/js-family-profile.d.ts.map +1 -0
  167. package/dist/languages/shared/js-family-profile.js +179 -0
  168. package/dist/languages/shared/js-family-profile.js.map +1 -0
  169. package/dist/languages/shared/node-kinds.d.ts +78 -0
  170. package/dist/languages/shared/node-kinds.d.ts.map +1 -0
  171. package/dist/languages/shared/node-kinds.js +141 -0
  172. package/dist/languages/shared/node-kinds.js.map +1 -0
  173. package/dist/languages/shared/node-utils.d.ts +31 -0
  174. package/dist/languages/shared/node-utils.d.ts.map +1 -0
  175. package/dist/languages/shared/node-utils.js +89 -0
  176. package/dist/languages/shared/node-utils.js.map +1 -0
  177. package/dist/languages/shared/parse-diagnostics.d.ts +44 -0
  178. package/dist/languages/shared/parse-diagnostics.d.ts.map +1 -0
  179. package/dist/languages/shared/parse-diagnostics.js +64 -0
  180. package/dist/languages/shared/parse-diagnostics.js.map +1 -0
  181. package/dist/languages/shared/parse-limits.d.ts +24 -0
  182. package/dist/languages/shared/parse-limits.d.ts.map +1 -0
  183. package/dist/languages/shared/parse-limits.js +134 -0
  184. package/dist/languages/shared/parse-limits.js.map +1 -0
  185. package/dist/languages/shared/profile.d.ts +149 -0
  186. package/dist/languages/shared/profile.d.ts.map +1 -0
  187. package/dist/languages/shared/profile.js +9 -0
  188. package/dist/languages/shared/profile.js.map +1 -0
  189. package/dist/languages/shared/scope-model.d.ts +32 -0
  190. package/dist/languages/shared/scope-model.d.ts.map +1 -0
  191. package/dist/languages/shared/scope-model.js +2 -0
  192. package/dist/languages/shared/scope-model.js.map +1 -0
  193. package/dist/languages/shared/scope-naming.d.ts +20 -0
  194. package/dist/languages/shared/scope-naming.d.ts.map +1 -0
  195. package/dist/languages/shared/scope-naming.js +118 -0
  196. package/dist/languages/shared/scope-naming.js.map +1 -0
  197. package/dist/languages/shared/scope-signature.d.ts +14 -0
  198. package/dist/languages/shared/scope-signature.d.ts.map +1 -0
  199. package/dist/languages/shared/scope-signature.js +82 -0
  200. package/dist/languages/shared/scope-signature.js.map +1 -0
  201. package/dist/languages/shared/signature.d.ts +55 -0
  202. package/dist/languages/shared/signature.d.ts.map +1 -0
  203. package/dist/languages/shared/signature.js +147 -0
  204. package/dist/languages/shared/signature.js.map +1 -0
  205. package/dist/languages/shared/syntax.d.ts +115 -0
  206. package/dist/languages/shared/syntax.d.ts.map +1 -0
  207. package/dist/languages/shared/syntax.js +2 -0
  208. package/dist/languages/shared/syntax.js.map +1 -0
  209. package/dist/languages/shared/table-profile-decisions.d.ts +54 -0
  210. package/dist/languages/shared/table-profile-decisions.d.ts.map +1 -0
  211. package/dist/languages/shared/table-profile-decisions.js +245 -0
  212. package/dist/languages/shared/table-profile-decisions.js.map +1 -0
  213. package/dist/languages/shared/table-profile-module-facts.d.ts +29 -0
  214. package/dist/languages/shared/table-profile-module-facts.d.ts.map +1 -0
  215. package/dist/languages/shared/table-profile-module-facts.js +139 -0
  216. package/dist/languages/shared/table-profile-module-facts.js.map +1 -0
  217. package/dist/languages/shared/table-profile-queries.d.ts +27 -0
  218. package/dist/languages/shared/table-profile-queries.d.ts.map +1 -0
  219. package/dist/languages/shared/table-profile-queries.js +70 -0
  220. package/dist/languages/shared/table-profile-queries.js.map +1 -0
  221. package/dist/languages/shared/table-profile-scopes.d.ts +46 -0
  222. package/dist/languages/shared/table-profile-scopes.d.ts.map +1 -0
  223. package/dist/languages/shared/table-profile-scopes.js +180 -0
  224. package/dist/languages/shared/table-profile-scopes.js.map +1 -0
  225. package/dist/languages/shared/table-profile.d.ts +302 -0
  226. package/dist/languages/shared/table-profile.d.ts.map +1 -0
  227. package/dist/languages/shared/table-profile.js +125 -0
  228. package/dist/languages/shared/table-profile.js.map +1 -0
  229. package/dist/languages/shared/tree-sitter-types.d.ts +44 -0
  230. package/dist/languages/shared/tree-sitter-types.d.ts.map +1 -0
  231. package/dist/languages/shared/tree-sitter-types.js +2 -0
  232. package/dist/languages/shared/tree-sitter-types.js.map +1 -0
  233. package/dist/languages/structured-text/index.d.ts +48 -0
  234. package/dist/languages/structured-text/index.d.ts.map +1 -0
  235. package/dist/languages/structured-text/index.js +120 -0
  236. package/dist/languages/structured-text/index.js.map +1 -0
  237. package/dist/languages/tsx/index.d.ts +4 -0
  238. package/dist/languages/tsx/index.d.ts.map +1 -0
  239. package/dist/languages/tsx/index.js +7 -0
  240. package/dist/languages/tsx/index.js.map +1 -0
  241. package/dist/languages/typescript/index.d.ts +4 -0
  242. package/dist/languages/typescript/index.d.ts.map +1 -0
  243. package/dist/languages/typescript/index.js +7 -0
  244. package/dist/languages/typescript/index.js.map +1 -0
  245. package/dist/languages/vue/index.d.ts +21 -0
  246. package/dist/languages/vue/index.d.ts.map +1 -0
  247. package/dist/languages/vue/index.js +234 -0
  248. package/dist/languages/vue/index.js.map +1 -0
  249. package/dist/languages/vue/mapping.d.ts +11 -0
  250. package/dist/languages/vue/mapping.d.ts.map +1 -0
  251. package/dist/languages/vue/mapping.js +77 -0
  252. package/dist/languages/vue/mapping.js.map +1 -0
  253. package/dist/registry.d.ts +24 -0
  254. package/dist/registry.d.ts.map +1 -0
  255. package/dist/registry.js +42 -0
  256. package/dist/registry.js.map +1 -0
  257. package/dist/text/byte-offset-table.d.ts +27 -0
  258. package/dist/text/byte-offset-table.d.ts.map +1 -0
  259. package/dist/text/byte-offset-table.js +39 -0
  260. package/dist/text/byte-offset-table.js.map +1 -0
  261. package/package.json +125 -3
  262. package/src/boundaries/expression.ts +95 -0
  263. package/src/boundaries/extract.ts +307 -0
  264. package/src/boundaries/python.ts +181 -0
  265. package/src/index.ts +51 -0
  266. package/src/languages/__golden__/javascript-basic.json +32 -0
  267. package/src/languages/__golden__/tsx-basic.json +19 -0
  268. package/src/languages/__golden__/typescript-basic.json +37 -0
  269. package/src/languages/astgrep-backend/GRAMMARS.md +86 -0
  270. package/src/languages/astgrep-backend/README.md +112 -0
  271. package/src/languages/astgrep-backend/__golden__/bash-basic.sh +53 -0
  272. package/src/languages/astgrep-backend/__golden__/c-basic.c +64 -0
  273. package/src/languages/astgrep-backend/__golden__/cpp-basic.cpp +65 -0
  274. package/src/languages/astgrep-backend/__golden__/csharp-basic.cs +73 -0
  275. package/src/languages/astgrep-backend/__golden__/go-basic.go +93 -0
  276. package/src/languages/astgrep-backend/__golden__/java-basic.java +62 -0
  277. package/src/languages/astgrep-backend/__golden__/kotlin-basic.kt +58 -0
  278. package/src/languages/astgrep-backend/__golden__/php-basic.php +72 -0
  279. package/src/languages/astgrep-backend/__golden__/ruby-basic.rb +62 -0
  280. package/src/languages/astgrep-backend/__golden__/rust-basic.rs +82 -0
  281. package/src/languages/astgrep-backend/__golden__/swift-basic.swift +73 -0
  282. package/src/languages/astgrep-backend/adapter.ts +240 -0
  283. package/src/languages/astgrep-backend/index.ts +44 -0
  284. package/src/languages/astgrep-backend/lang/README.md +115 -0
  285. package/src/languages/astgrep-backend/lang/bash.ts +78 -0
  286. package/src/languages/astgrep-backend/lang/c.ts +119 -0
  287. package/src/languages/astgrep-backend/lang/cpp.ts +65 -0
  288. package/src/languages/astgrep-backend/lang/csharp.ts +125 -0
  289. package/src/languages/astgrep-backend/lang/index.ts +61 -0
  290. package/src/languages/astgrep-backend/lang/java.ts +115 -0
  291. package/src/languages/astgrep-backend/lang/kotlin.ts +136 -0
  292. package/src/languages/astgrep-backend/lang/php.ts +105 -0
  293. package/src/languages/astgrep-backend/lang/ruby.ts +105 -0
  294. package/src/languages/astgrep-backend/lang/swift.ts +118 -0
  295. package/src/languages/astgrep-backend/languages.ts +238 -0
  296. package/src/languages/astgrep-backend/napi.ts +261 -0
  297. package/src/languages/astgrep-backend/syntax.ts +242 -0
  298. package/src/languages/index.ts +53 -0
  299. package/src/languages/javascript/index.ts +9 -0
  300. package/src/languages/jsx/index.ts +9 -0
  301. package/src/languages/prose/index.ts +270 -0
  302. package/src/languages/prose/line-bytes.ts +52 -0
  303. package/src/languages/python/README.md +246 -0
  304. package/src/languages/python/__golden__/python-basic.json +44 -0
  305. package/src/languages/python/create-adapter.ts +29 -0
  306. package/src/languages/python/index.ts +8 -0
  307. package/src/languages/python/profile.ts +341 -0
  308. package/src/languages/python/signature.ts +183 -0
  309. package/src/languages/python/table.ts +135 -0
  310. package/src/languages/shared/__fixtures__/large-over-32kib.ts.txt +1207 -0
  311. package/src/languages/shared/call-detection.ts +112 -0
  312. package/src/languages/shared/chunks.ts +255 -0
  313. package/src/languages/shared/create-adapter.ts +136 -0
  314. package/src/languages/shared/decisions.ts +204 -0
  315. package/src/languages/shared/dialect.ts +55 -0
  316. package/src/languages/shared/doc-binding.ts +78 -0
  317. package/src/languages/shared/engine.ts +461 -0
  318. package/src/languages/shared/extract-symbols.ts +35 -0
  319. package/src/languages/shared/fingerprint.ts +99 -0
  320. package/src/languages/shared/grammar-loader.ts +67 -0
  321. package/src/languages/shared/import-detection.ts +154 -0
  322. package/src/languages/shared/js-family-profile.ts +246 -0
  323. package/src/languages/shared/node-kinds.ts +153 -0
  324. package/src/languages/shared/node-utils.ts +120 -0
  325. package/src/languages/shared/parse-diagnostics.ts +125 -0
  326. package/src/languages/shared/parse-limits.ts +147 -0
  327. package/src/languages/shared/profile.ts +184 -0
  328. package/src/languages/shared/scope-model.ts +43 -0
  329. package/src/languages/shared/scope-naming.ts +124 -0
  330. package/src/languages/shared/scope-signature.ts +108 -0
  331. package/src/languages/shared/signature.ts +149 -0
  332. package/src/languages/shared/syntax.ts +116 -0
  333. package/src/languages/shared/table-profile-decisions.ts +251 -0
  334. package/src/languages/shared/table-profile-module-facts.ts +177 -0
  335. package/src/languages/shared/table-profile-queries.ts +85 -0
  336. package/src/languages/shared/table-profile-scopes.ts +198 -0
  337. package/src/languages/shared/table-profile.ts +427 -0
  338. package/src/languages/shared/tree-sitter-types.ts +46 -0
  339. package/src/languages/structured-text/index.ts +192 -0
  340. package/src/languages/tsx/index.ts +9 -0
  341. package/src/languages/typescript/index.ts +9 -0
  342. package/src/languages/vue/index.ts +312 -0
  343. package/src/languages/vue/mapping.ts +93 -0
  344. package/src/registry.ts +61 -0
  345. package/src/text/byte-offset-table.ts +63 -0
package/NOTICE ADDED
@@ -0,0 +1,90 @@
1
+ # NOTICE
2
+
3
+ Copyright (C) 2026 Luke Bölling and contributors.
4
+
5
+ This attribution covers original Untangle work. Contributors retain copyright in
6
+ their contributions. Third-party packages, grammars and other materials retain
7
+ their own copyright holders, licenses and notices; this line does not replace them.
8
+
9
+ ## License — binding decision
10
+
11
+ Untangle is licensed under the **GNU Affero General Public License, Version 3
12
+ (AGPL-3.0-only)**. See [`LICENSE`](./LICENSE).
13
+
14
+ This decision is **final, not provisional**, and was explicitly instructed by
15
+ the project owner. No contributor, agent or tool may change it without a new
16
+ explicit instruction.
17
+
18
+ The repository-wide license covers Untangle's first-party source code, scripts,
19
+ tests, fixtures, configuration, documentation, website and brand artwork, including
20
+ the logo and 3D yarn illustrations. Every workspace `package.json` declares
21
+ `"license": "AGPL-3.0-only"`. There is no separately licensed enterprise component
22
+ or separate permissive license for documentation or brand assets.
23
+
24
+ Third-party code, embedded grammars, dependency assets and their notices retain
25
+ their original licenses. Their inclusion does not relicense those works. The
26
+ repository license does not grant trademark rights or change the license of a
27
+ repository analyzed with Untangle. See the repository's `docs/LICENSING.md` for
28
+ scope and verification details.
29
+
30
+ This resolves the license question left open in `vision.md` §14 and completes
31
+ `product.md` §16, item 2.
32
+
33
+ ## Rationale
34
+
35
+ - **Network copyleft fits the intended product model.** AGPL §13 sets source
36
+ availability requirements for modified versions used through a computer network.
37
+ The current local CLI/stdio-MCP entry and future shared-server modes share the
38
+ same license.
39
+ - **Local-first analysis has a clear boundary.** Running Untangle against a codebase
40
+ does not replace that codebase's own license with Untangle's license.
41
+ - **First-party components share one license.** Implemented components and future
42
+ official plugins use this repository's licensing policy. Planned integrations do
43
+ not establish implemented or published products.
44
+
45
+ ## Deliberately accepted consequence
46
+
47
+ The project deliberately chooses AGPL rather than a permissive embedding license.
48
+ Redistribution, modifications and combined works must be assessed against the
49
+ actual terms in `LICENSE`, including applicable Corresponding Source requirements.
50
+ No permissive exception, commercial dual license or special contract-only package
51
+ license is granted or promised by this notice.
52
+
53
+ ## Dependencies
54
+
55
+ Third-party runtime dependencies are checked against the allowlist in
56
+ `scripts/check-licenses.mjs`. Their licenses and copyright notices remain unchanged
57
+ and traceable through package `THIRD_PARTY_LICENSES.md` files, grammar provenance,
58
+ the lockfile and release SBOM. The allowlist includes MIT / Apache-2.0 / BSD / ISC
59
+ and other explicitly listed licenses; it is not a license grant for dependencies.
60
+
61
+ The allowlist in `scripts/check-licenses.mjs` applies to **dependencies**, not
62
+ workspace packages. Untangle's own packages carry AGPL-3.0-only and are excluded
63
+ from that check.
64
+
65
+ ## Clean room
66
+
67
+ Untangle is an independent implementation with its own data models, APIs, tool
68
+ names, tests and sources. Feature ideas may be derived from publicly observable
69
+ behavior and generally known techniques. Third-party source code is not copied,
70
+ including from AGPL projects even where the license would permit it.
71
+
72
+ ## Contribution terms
73
+
74
+ Pull requests are welcome under the repository's existing AGPL-3.0-only license.
75
+ No separate CLA, copyright assignment or DCO sign-off is required. Contributors
76
+ must have the right to submit their work under those terms. See CONTRIBUTING.md.
77
+
78
+ ## Release decisions
79
+
80
+ - [x] Copyright attribution: Luke Bölling, with contributors retaining their rights.
81
+ - [x] Contributions use AGPL-3.0-only without an additional CLA or DCO gate.
82
+
83
+ ## Open legal items before public beta
84
+
85
+ - [ ] Trademark search for the product name `Untangle`.
86
+ - [ ] Registration and legal review of the npm scope `@untangle-code`.
87
+ - [ ] Verify source availability and notices for each released network daemon/server
88
+ mode (WP-59). The current stdio MCP `untangle_about` already reports the license,
89
+ source repository and build commit when supplied; metadata alone does not prove
90
+ that a concrete deployed version's source is available.
package/README.md CHANGED
@@ -1,3 +1,353 @@
1
- # Temporary Holding Version
1
+ # @untangle-code/parser-registry
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ WP-06: the `ParserRegistry` implementation (a port from `@untangle-code/domain`), plus
4
+ `LanguageAdapter` implementations for TypeScript, JavaScript, TSX, JSX and Vue SFCs,
5
+ Python, additional native languages, prose and structured text. This package is part
6
+ of Untangle's public package surface.
7
+
8
+ **Two backends (WP-220).** Since WP-220, two parser backends operate behind the same
9
+ `LanguageAdapter` contract: **tree-sitter** for TypeScript/JavaScript/TSX/JSX (measured
10
+ 3.74× faster traversal, lower memory use, complete `nodeIsMissing` support) and
11
+ **ast-grep** for Go and Rust — languages that would not be available without existing
12
+ third-party grammars. `src/languages/astgrep-backend/README.md` documents which backend
13
+ serves each language, **why**, and the differences (size limit, heuristic
14
+ `missingNodeCount`, separate `parser_version`). The unified traversal in
15
+ `src/languages/shared/` serves both backends; native tree-sitter shapes satisfy the
16
+ tree contract structurally, so the faster backend pays no abstraction cost.
17
+
18
+ Normative sources: spec.md §7.1–§7.3, §8.2–§8.3, §14.2, §16.2–§16.7, §17.3;
19
+ architecture.md §6.5, §15.1. All types (`LanguageAdapter`, `ParsedAst`, `ExtractedSymbol`,
20
+ `RawImport`, `RawCall`, `ComplexityFacts`, `HalsteadTokens`, `AstRegion`, `ParserRegistry`
21
+ and others) come unchanged from `@untangle-code/domain`; this package defines no
22
+ competing types.
23
+
24
+ <a id="grammatik-wahl"></a>
25
+
26
+ ## Grammar selection
27
+
28
+ Tested under Node 22/26, ESM, `verbatimModuleSyntax`:
29
+
30
+ - **web-tree-sitter (WASM)**: `Parser.init()`/`Language.load()` must be `async`.
31
+ The domain's `LanguageAdapter.parse()` is **synchronous**. A WASM load cannot be
32
+ hidden cleanly before the first `parse()` call without loading all languages at
33
+ startup (prohibited by the task) or requiring an async registry factory (outside
34
+ the port contract). Rejected.
35
+ - **typescript (`ts.createSourceFile`) as a fallback**: allowed by the task, but only
36
+ for the TS/JS family. It provides no AST for actual JSX in JS without a TS compiler
37
+ mode, no uniform byte-range API, and a completely different compatibility path
38
+ for later languages such as Python. Unnecessary because the next option works.
39
+ - **`tree-sitter` (native N-API bindings) + `tree-sitter-typescript` + `tree-sitter-javascript`**:
40
+ selected. Empirically verified (see this package's test history): on Node 22/26
41
+ arm64/Darwin, `npm install` supplies working precompiled binaries immediately
42
+ (`node-gyp-build` finds them in the package; no compilation required).
43
+ `parser.parse(text)` is fully **synchronous**. `tree-sitter-javascript` also parses
44
+ JSX natively, which is why `jsx` uses the same grammar loader as `javascript` below.
45
+ Version constraint: `tree-sitter@0.21.1` + `tree-sitter-typescript@0.23.2` +
46
+ `tree-sitter-javascript@0.23.1` (newer `tree-sitter-javascript`/`-typescript` versions
47
+ require `tree-sitter@^0.25`, conflicting with `tree-sitter-typescript`'s `^0.21.0`
48
+ peer dependency; this combination is the only one jointly resolvable at that point).
49
+
50
+ **Language → grammar mapping** (`languages/shared/dialect.ts`):
51
+
52
+ | languageId | Extensions | Grammar module | Export |
53
+ |---|---|---|---|
54
+ | `typescript` | `.ts .mts .cts` | `tree-sitter-typescript` | `.typescript` |
55
+ | `tsx` | `.tsx` | `tree-sitter-typescript` | `.tsx` |
56
+ | `javascript` | `.js .mjs .cjs` | `tree-sitter-javascript` | (default) |
57
+ | `jsx` | `.jsx` | `tree-sitter-javascript` | (default) |
58
+ | `vue` | `.vue` | `@vue/compiler-sfc` for block boundaries; existing JS/TS grammars for inline scripts | See below |
59
+
60
+ `javascript` and `jsx` are two **separate** `LanguageAdapter` instances (their own
61
+ `languageId`/extensions, as required by the task's “four LanguageAdapters”). Internally
62
+ they share a grammar because `tree-sitter-javascript` parses JSX without extra configuration.
63
+
64
+ <a id="vue-ausführbaren-quelltext-messen-sfc-grenzen-sichtbar-halten"></a>
65
+
66
+ ### Vue: measure executable source and expose SFC boundaries
67
+
68
+ `createVueAdapter()` registers `.vue` at support level `structural`. The official
69
+ [`@vue/compiler-sfc` parser](https://github.com/vuejs/core/tree/main/packages/compiler-sfc)
70
+ identifies SFC block boundaries and loads only on `parse()`. The adapter passes the
71
+ unchanged contents of `<script>` and `<script setup>` to the existing JS, TS, JSX or
72
+ TSX adapters. It neither generates nor measures compiled render or setup code; existing
73
+ rules for decisions, Halstead and symbol detection stay the same.
74
+
75
+ All ranges are then shifted to the original UTF-8 bytes and lines of the `.vue` file,
76
+ including imports, calls, comments and diagnostics. A single script block retains its
77
+ qualified symbol names. With two blocks, `script.<Name>` and `setup.<Name>` distinguish
78
+ the execution contexts. File facts share one file scope; child script scopes and logical
79
+ decision groups remain distinct. This does not model Vue runtime bindings between blocks.
80
+
81
+ The single chunk root covers the entire original file. Template, style and custom blocks
82
+ therefore remain searchable as text. Their complexity, directives, template calls,
83
+ component use and CSS dependencies are **not** captured as code facts. Each such block
84
+ receives a warning with `kind: "other"`, `code: "analysis_scope_limited"`, the prefix
85
+ `Vue analysis scope:` and its original range. `parseQuality: "complete"` means the SFC
86
+ structure and analyzed inline scripts are syntactically valid; it claims neither complete
87
+ Vue semantics nor successful Vue compilation.
88
+
89
+ Template-only files, external `script src`, unsupported script languages, different
90
+ `lang` attributes on the two scripts and syntax damage produce `partial` with specific
91
+ diagnostics. External scripts must be analyzed as separate source files. Without an
92
+ analyzed inline script, no executable scopes or artificial complexity values are created.
93
+ The SFC input has the same 8 MiB byte limit as the existing tree-sitter adapters. The
94
+ separate parser version `untangle-parser-vue-sfc-v1` distinguishes this analysis from
95
+ earlier text fallbacks.
96
+
97
+ `src/languages/vue/adapter.test.ts` checks real SFCs with all four script dialects,
98
+ Options API, both scripts, Unicode/CRLF offsets, imports/calls, nested symbol regions,
99
+ unchanged TS facts, invalid and external scripts, and visible analysis limits.
100
+
101
+ **Implication for later languages** (documented as the task requires): Python (WP-09)
102
+ can also use native `tree-sitter` bindings (recommended, following the same pattern)
103
+ or another approach. The registry itself is grammar-independent (`register(adapter)`);
104
+ nothing in `registry.ts` or `languages/index.ts` needs to change.
105
+
106
+ ## Lazy Loading
107
+
108
+ `createParserRegistry()` registers four `LanguageAdapter` objects without loading **any**
109
+ native module. `languages/shared/grammar-loader.ts` loads `tree-sitter` itself and each
110
+ grammar only on the first `parse()` call for that language, through
111
+ `node:module#createRequire` (synchronous CJS `require` from ESM, needed because `parse()`
112
+ must be synchronous), with a module-level cache. A CLI reading only TypeScript files
113
+ never loads `tree-sitter-javascript`.
114
+
115
+ <a id="eine-einzige-analyse-pro-datei"></a>
116
+
117
+ ## One analysis per file
118
+
119
+ Every `LanguageAdapter` method (`extractSymbols`, `extractImports`, `extractCalls`,
120
+ `computeComplexity`, `tokenizeForHalstead`, `extractChunks`) is a thin projection over
121
+ **one** `AnalysisResult`. `languages/shared/engine.ts#analyzeTree` computes it in a single
122
+ AST traversal, and `create-adapter.ts` memoizes it per `ParsedAst` through a `WeakMap`.
123
+ This also guarantees consistency: a `SymbolScopeFact`'s `symbolScopeId`
124
+ (`computeComplexity`) is exactly the same string as a `RawCall`'s `callerScopeId`
125
+ (`extractCalls`) for a call inside that scope. Both come from the same live scope stack
126
+ frame in the same traversal, rather than independently reconstructed scope ID algorithms
127
+ that could diverge.
128
+
129
+ <a id="traversierung-cursor-nicht-children-wp-95"></a>
130
+
131
+ ## Traversal: cursors instead of `.children` (WP-95)
132
+
133
+ Traversal navigates through the **cursor API** (`tree.walk()`, `gotoFirstChild`,
134
+ `gotoNextSibling`, `gotoParent`), never `node.children`. There are two reasons, and the
135
+ second matters more than the first.
136
+
137
+ **Speed.** Each `.children` access creates a JS array of node wrappers and crosses the
138
+ native library boundary once per node. Measured against this repository (738 files,
139
+ 134,782 lines, `pnpm walk:messung`):
140
+
141
+ | Stage | Through `.children` | Through cursors | Factor |
142
+ |---|---:|---:|---:|
143
+ | `parse` (including parse diagnostics) | 2,803 ms | 853 ms | 3.29× |
144
+ | Traversal (`computeComplexity`) | 16,596 ms | 4,662 ms | 3.56× |
145
+ | **Total** | **19,440 ms** (6.93 kLOC/s) | **5,541 ms** (24.32 kLOC/s) | **3.51×** |
146
+
147
+ **Correctness.** `tree-sitter@0.21.1` reports a node's type reliably only when the cursor
148
+ **descended from the root**. Neither `node.children` nor a cursor reset to a subtree
149
+ (`node.walk()`) knows the parent node's alias context. In this repository both reported
150
+ **1,411 comment nodes in 207 files** as `interface_body`. The previous traversal therefore
151
+ failed to recognize them as comments: they were absent from `ComplexityFacts.comments`,
152
+ counted as Halstead **operators**, and included in `astHash` and `tokenFingerprint`,
153
+ contrary to `fingerprint.ts`'s promise that both fingerprints exclude comments. A comment-only
154
+ edit therefore appeared to change the symbol's structure (`spec.md` §17.3).
155
+
156
+ Measured across this repository: **1,411** comments counted as Halstead operators
157
+ (out of 133,282) and were missing from `comments` (6,821 instead of 8,232);
158
+ **531 of 10,328** symbols (5.1%) now have corrected fingerprints. Cyclomatic and cognitive
159
+ complexity do **not** change: neither calculation includes comments.
160
+
161
+ Three rules follow for this package:
162
+
163
+ 1. `engine.ts#analyzeTree` creates **one** cursor at the root and passes it through.
164
+ Every helper that moves it returns it to its original position.
165
+ 2. `computeAstHash`/`computeTokenFingerprint` accept **this** cursor, not a node.
166
+ Switching them back to `node.walk()` would reintroduce the defect.
167
+ 3. A `SyntaxNode` wrapper is created only where a detector actually needs it
168
+ (`engine.ts#visitInnerNode`, prefilter `decisions.ts#mayCarryDecisionOrNesting`).
169
+
170
+ Verified by `languages/shared/cursor-walk.test.ts` (regression: all four assertions fail
171
+ before WP-95) and `scripts/walk-gegenprobe.mjs`, which runs both approaches over every
172
+ source file and checks that **every** difference has precisely this cause.
173
+
174
+ <a id="byte-offsets--kritische-falle"></a>
175
+
176
+ ## Byte offsets — a critical pitfall
177
+
178
+ The domain contract defines `SourceRange.startByte`/`endByte` as **UTF-8 bytes**. Native
179
+ `tree-sitter` Node bindings return `startIndex`/`endIndex` in **UTF-16 code units**
180
+ (empirically verified: a 4-byte astral character increases `endIndex` by 2, not 4).
181
+ `text/byte-offset-table.ts#buildByteOffsetTable` builds one prefix-sum table per file
182
+ (O(n) construction, O(1) lookup). **Every** `SourceRange` construction in this package
183
+ goes through `node-utils.ts#rangeOf`, which uses that table. Never copy
184
+ `node.startIndex`/`endIndex` directly into a `SourceRange`.
185
+
186
+ <a id="signaturnormalisierung-specmd-55"></a>
187
+
188
+ ## Signature normalization (spec.md §5.5)
189
+
190
+ See the detailed documentation in the header comment of `languages/shared/signature.ts`.
191
+ The rules are:
192
+
193
+ 1. **Whitespace**: arbitrary runs collapse to one space; spacing around `,`/`:`/`(`/`)`/
194
+ `<`/`>`/`?:` is canonicalized instead of copied literally.
195
+ 2. **Default values** (`= <expr>`) are removed from parameters AND generic type parameters
196
+ (a depth scanner over `(`/`[`/`{`/`<`, splitting top-level commas first; see
197
+ `splitTopLevel`/`stripDefaultValue`).
198
+ 3. **Optional markers** (`?`) are retained and canonicalized immediately before `:`
199
+ (`a ?: string` and `a?:string` → `a?: string`); they change the call contract
200
+ independently of defaults.
201
+ 4. **Type annotations** are preserved literally, subject to the whitespace rules.
202
+
203
+ Known documented limit: the depth scanner treats `<`/`>` as generic brackets. A comparison
204
+ operator `<`/`>` **inside a default value** (`(a = b < c ? 1 : 2)`) can confuse depth
205
+ counting for that parameter. This is accepted as a rare case outside the chosen scope.
206
+
207
+ <a id="entscheidungen"></a>
208
+
209
+ ## Decisions
210
+
211
+ 1. **One AST traversal instead of six independent method implementations.** See “One
212
+ analysis per file” above. `create-adapter.ts` caches per `ParsedAst`.
213
+ 2. **`RawImportKind` has no `require` value.** `require("x")` maps to `importKind: "import"`
214
+ (functionally a synchronous import); `"package_dependency"` is reserved for an edge
215
+ **resolved** by the import resolver/file graph, rather than a source syntax form.
216
+ 3. **The `namespace` scope kind maps to chunk kind `"module"`.** `ChunkKind` (domain) has
217
+ no `"namespace"` member; a TS `namespace`/`module` block is itself a module-like
218
+ grouping of symbols.
219
+ 4. **`exportedNames` recognizes only direct wrapping.** `export function f() {}` and
220
+ `export default class {}` are recognized. A later `export { f }` elsewhere in the file,
221
+ or `export default f;` as a separate statement referencing an already declared name,
222
+ is NOT traced back (see `scope-naming.ts#resolveExportedNames`). This can be added
223
+ when a consumer needs it.
224
+ 5. **The `parse()` return value has no `parserVersion` field.** The WP-06 task mentions it,
225
+ but `ParseResult` (domain `analysis.ts`) defines exactly `{parseQuality, ast, diagnostics,
226
+ errorNodeCount, missingNodeCount}`, without `parserVersion`. Because the domain defines
227
+ the contracts exactly and this package may not add competing fields, the field is NOT
228
+ appended (see openIssues: “belongs in domain”).
229
+ 6. **`failed` at ≥50% damaged nodes.** tree-sitter's error recovery almost always produces
230
+ a usable tree; a small absolute number of `ERROR`/missing nodes means `partial`,
231
+ while a mostly damaged file means `failed` (`ast: null`). Neither spec.md nor
232
+ architecture.md specifies a normative value; this is the package's documented
233
+ threshold (`parse-diagnostics.ts`).
234
+ 7. **Guard clause heuristic**: an `if` without `else` whose only consequence is a
235
+ `return`/`throw`/`break`/`continue` is classified as `DecisionKind: "guard"` instead of
236
+ `"if"` (spec.md §16.2: “guards when they create independent paths”).
237
+ 8. **Property fields are separate scopes**, unless their initializer is itself a
238
+ function/class (`class C { handler = () => {} }`). The function then receives the
239
+ scope (borrowing the field's name), avoiding duplicated `C.handler.handler`
240
+ (`scope-naming.ts#fieldDelegatesToFunctionValue`).
241
+ 9. **Halstead classification**: brackets/commas/semicolons/periods (`( ) { } [ ] , ; .`)
242
+ do **not** count as operators. All other symbol/keyword terminals count as operators;
243
+ identifiers/`this`/`super` and literals (including template text fragments) count as
244
+ operands. TS type keywords such as `number`/`string`/`void` (kind `predefined_type`)
245
+ do **not** count: they are pure type syntax, not values. Grammar pitfall: the `string`
246
+ type keyword node has the same `node.type` as a string literal container; see the
247
+ comment in `engine.ts`.
248
+ 10. **`property_group` chunks combine consecutive class fields**; a method/constructor
249
+ chunk interrupts the group. A class can have multiple groups.
250
+ 11. **The file region is always exactly one `AstRegion` of `ChunkKind: "module"`**, with
251
+ `children` for top-level symbols (and recursively for class members). The region
252
+ contract is documented normatively in exactly ONE place: the `AstRegion` type in
253
+ `packages/domain/src/analysis.ts`. The chunker unpacks the root region and handles
254
+ each `chunkKind` according to its kind at every depth. Symbol chunks
255
+ (function/method/constructor/class_overview) therefore exist even when the entire
256
+ file fits within the token budget (spec.md §8.3 steps 3–5).
257
+ 12. **Symbol regions include the `export` wrapper.** The tree-sitter scope node is only
258
+ the declaration (`function_declaration`, etc.); the enclosing `export_statement`
259
+ belongs to the symbol's chunk, rather than a module-level gap. `chunks.ts#ownRange`
260
+ expands the region accordingly, in addition to the already associated documentation/
261
+ decorator range (spec.md §8.3 step 2).
262
+ 13. **`static { ... }` blocks are modeled as separate child regions of the class**
263
+ (`chunkKind: "property_group"`, not splittable). They open no symbol scope (no name
264
+ or stable symbol ID), but contain executable content that would otherwise escape
265
+ the chunker's member traversal (spec.md §8.4, no silent data loss). Comparable
266
+ unmodeled constructs in a class body (comments between methods, delimiters) are
267
+ covered by the chunker's gap handling; see region contract item 4 in
268
+ `domain/src/analysis.ts`.
269
+
270
+ ## Tests
271
+
272
+ `npx vitest run` (55 tests, co-located `*.test.ts`):
273
+
274
+ - `text/byte-offset-table.test.ts` — UTF-8/UTF-16 conversion, including astral characters.
275
+ - `languages/shared/signature.test.ts` — whitespace/default/optional-marker normalization.
276
+ - `languages/shared/grammar-loader.test.ts` — caching, end-to-end parse sanity.
277
+ - `registry.test.ts` — extension/language resolution, override semantics.
278
+ - `languages/golden.test.ts` — golden fixtures (`__golden__/*.json`) for TS/JS/TSX: symbols,
279
+ imports, calls, decision kinds, scope ID consistency, AST depth.
280
+ - `languages/adapters.test.ts` — syntax errors → `partial`/`failed` without crashing;
281
+ classes with multiple methods → separate, non-overlapping regions; dynamic imports
282
+ and re-exports; signature normalization stable under whitespace changes (including
283
+ the cross-check “same result with different formatting, different result for actual
284
+ semantic changes such as optional instead of default”); astHash stable under whitespace
285
+ reformatting and literal-only edits; tokenFingerprint changes under literal edits;
286
+ guard clause detection.
287
+ - `index.test.ts` — `createParserRegistry()` correctly registers all four MVP languages.
288
+
289
+ <a id="verifikation"></a>
290
+
291
+ ## Verification
292
+
293
+ ```
294
+ npx tsc -p tsconfig.typecheck.json # 0 errors
295
+ npx tsc -p tsconfig.json # Build, 0 errors
296
+ npx vitest run # 55/55 passing
297
+ npx eslint packages/parser-registry # 0 errors, 0 warnings
298
+ ```
299
+
300
+ <a id="e4-ehrlichkeitspruefung-wp-165"></a>
301
+
302
+ ## E4 honesty check (WP-165)
303
+
304
+ `src/honesty.test.ts` runs `assertHonestUnderDamage` from `@untangle-code/testkit` against
305
+ both adapter families — TypeScript (tree-sitter) and Python (this package's handwritten
306
+ tokenizer/parser) — using ONE shared adapter instance per family, so concurrency damage
307
+ can affect shared state (grammar cache, offset tables).
308
+
309
+ It does not check symbol counts (shorter input may correctly reduce them). It checks that
310
+ the returned region tree still spans the entire input, all reported ranges lie within the
311
+ input, and the single `"module"` root required by the adapter contract is present.
312
+
313
+ **Result: both adapters pass every damage case.** For damaged structure, the Python
314
+ adapter reports seven diagnostics and lowers quality; the TypeScript adapter keeps its
315
+ promises unchanged. Also checked and correct: byte offsets for characters outside the
316
+ BMP (emoji) and umlauts. The classic UTF-16-instead-of-byte error is absent here.
317
+
318
+ <a id="bekannte-grenzen-e4"></a>
319
+
320
+ ### Known limits (E4)
321
+
322
+ - **Not every `.children` use in this package has been converted.** The three traversals
323
+ covering the entire tree have been converted: `engine.ts`, `fingerprint.ts` and
324
+ `parse-diagnostics.ts`. Targeted accesses in `import-detection.ts`, `scope-signature.ts`,
325
+ `scope-naming.ts`, `chunks.ts` and `node-utils.ts` still use `.children`. They are not
326
+ measurably expensive (each sees only a handful of children), but share the type defect
327
+ described above: a comment node could appear under the wrong type. This currently
328
+ causes no damage because each location checks specific type names (`import_clause`,
329
+ `get`, `set`, `*`, `default`, `class_static_block`, …), none of which is the observed
330
+ incorrect type `interface_body`. `scripts/walk-gegenprobe.mjs` verifies that imports,
331
+ regions, chunk IDs and call edges remain unchanged. A different incorrect type with
332
+ another grammar could change this; those accesses would then need conversion too.
333
+ - **`LanguageAdapter.parse/extractChunks/extractSymbols` accept no `AbortSignal`.** The
334
+ signature belongs to `@untangle-code/domain` (`analysis.ts`) and cannot be changed
335
+ here; spec.md §22 requires cancellation support for public APIs. The `abort_signal`
336
+ damage case is therefore waived for precisely this reason and appears in the test
337
+ report's skip ledger.
338
+
339
+ <a id="lizenz"></a>
340
+
341
+ ## License
342
+
343
+ **AGPL-3.0-only.** This package includes the full license text in [`LICENSE`](./LICENSE),
344
+ the rationale for the license choice in [`NOTICE`](./NOTICE), and the licenses of all
345
+ third-party production dependencies in [`THIRD_PARTY_LICENSES.md`](./THIRD_PARTY_LICENSES.md).
346
+ All three files are part of the npm tarball — AGPL-3.0-only §4 and §5 require every recipient
347
+ to receive the license, and a README alone is not a copy of the license.
348
+
349
+ Local use creates no obligation. Copyleft obligations apply to redistribution and provision
350
+ as a network service (AGPL §13).
351
+
352
+ The corresponding TypeScript source is included under `src/` in the same tarball; the full
353
+ repository is available at <https://github.com/lboel/untangle>.
@@ -0,0 +1,91 @@
1
+ # Third-party licenses — @untangle-code/parser-registry
2
+
3
+ Generated by `pnpm third-party-licenses` from this package's installed
4
+ production dependency tree: transitive `dependencies`, across
5
+ workspace edges, with no `devDependencies` included. The generator reads
6
+ each resolved package's `package.json` in `node_modules`; nothing is maintained by hand
7
+ or estimated.
8
+
9
+ Do not edit manually: `pnpm third-party-licenses --check` fails on drift,
10
+ and `pnpm check-publishable` rejects packages without a current file.
11
+
12
+ This file exists because `docs/BUILD_PLAN.md`, risk R6, makes
13
+ per-package `THIRD_PARTY_LICENSES.md` a release gate for npm publication.
14
+
15
+ Untangle itself is **AGPL-3.0-only** (see `LICENSE` and `NOTICE` in
16
+ this package). The packages below are third-party works; their own
17
+ licenses and copyright notices continue to apply unchanged. Workspace
18
+ packages (`@untangle-code/*`) are not listed here; they belong to the same
19
+ work and use the same AGPL-3.0-only license.
20
+
21
+ ## Production dependencies (transitive, 25)
22
+
23
+ | Package | Version | License | Project |
24
+ | --- | --- | --- | --- |
25
+ | `@ast-grep/lang-python` | 0.0.6 | ISC | — |
26
+ | `@ast-grep/napi` | 0.45.3 | MIT | <https://ast-grep.github.io> |
27
+ | `@ast-grep/setup-lang` | 0.0.6 | ISC | — |
28
+ | `@babel/helper-string-parser` | 7.29.7 | MIT | <https://babel.dev/docs/en/next/babel-helper-string-parser> |
29
+ | `@babel/helper-validator-identifier` | 7.29.7 | MIT | <https://github.com/babel/babel> |
30
+ | `@babel/parser` | 7.29.9 | MIT | <https://babel.dev/docs/en/next/babel-parser> |
31
+ | `@babel/types` | 7.29.8 | MIT | <https://babel.dev/docs/en/next/babel-types> |
32
+ | `@jridgewell/sourcemap-codec` | 1.6.0 | MIT | <https://github.com/jridgewell/sourcemaps/tree/main/packages/sourcemap-codec> |
33
+ | `@vue/compiler-core` | 3.5.44 | MIT | <https://github.com/vuejs/core/tree/main/packages/compiler-core#readme> |
34
+ | `@vue/compiler-dom` | 3.5.44 | MIT | <https://github.com/vuejs/core/tree/main/packages/compiler-dom#readme> |
35
+ | `@vue/compiler-sfc` | 3.5.44 | MIT | <https://github.com/vuejs/core/tree/main/packages/compiler-sfc#readme> |
36
+ | `@vue/compiler-ssr` | 3.5.44 | MIT | <https://github.com/vuejs/core/tree/main/packages/compiler-ssr#readme> |
37
+ | `@vue/shared` | 3.5.44 | MIT | <https://github.com/vuejs/core/tree/main/packages/shared#readme> |
38
+ | `entities` | 7.0.1 | BSD-2-Clause | <https://github.com/fb55/entities> |
39
+ | `estree-walker` | 2.0.2 | MIT | <https://github.com/Rich-Harris/estree-walker> |
40
+ | `magic-string` | 0.30.21 | MIT | <https://github.com/Rich-Harris/magic-string> |
41
+ | `nanoid` | 3.3.20 | MIT | `ai/nanoid` |
42
+ | `node-addon-api` | 8.9.2 | MIT | <https://github.com/nodejs/node-addon-api> |
43
+ | `node-gyp-build` | 4.8.4 | MIT | <https://github.com/prebuild/node-gyp-build> |
44
+ | `picocolors` | 1.1.1 | ISC | `alexeyraspopov/picocolors` |
45
+ | `postcss` | 8.5.31 | MIT | <https://postcss.org/> |
46
+ | `source-map-js` | 1.2.2 | BSD-3-Clause | <https://github.com/7rulnik/source-map-js> |
47
+ | `tree-sitter` | 0.21.1 | MIT | <http://github.com/tree-sitter/node-tree-sitter> |
48
+ | `tree-sitter-javascript` | 0.23.1 | MIT | <https://github.com/tree-sitter/tree-sitter-javascript> |
49
+ | `tree-sitter-typescript` | 0.23.2 | MIT | <https://github.com/tree-sitter/tree-sitter-typescript> |
50
+
51
+ The allowlist (MIT / Apache-2.0 / BSD / ISC / …) is checked by
52
+ `scripts/check-licenses.mjs` against this exact tree on every run;
53
+ the GPL family is excluded (architecture.md §2.4, BUILD_PLAN R6).
54
+
55
+ ## Embedded tree-sitter grammars (12)
56
+
57
+ The `@ast-grep/lang-*` packages distribute third-party tree-sitter grammars:
58
+ their `src/parser.c` files are byte-identical to the listed grammar versions,
59
+ as verified by `pnpm grammar-provenance --update`
60
+ (field `parserMatchesGrammar`). However, their own `LICENSE` only names
61
+ `Copyright (c) 2025 ast-grep`; the grammar authors are not listed there.
62
+ Untangle therefore records their notices here.
63
+
64
+ | Language package | Dependency | Grammar | License | Copyright notice |
65
+ | --- | --- | --- | --- | --- |
66
+ | `@ast-grep/lang-bash` | optional; install separately | `tree-sitter-bash` 0.25.1 | MIT | Copyright (c) 2017 Max Brunsfeld |
67
+ | `@ast-grep/lang-c` | optional; install separately | `tree-sitter-c` 0.24.1 | MIT | Copyright (c) 2014 Max Brunsfeld |
68
+ | `@ast-grep/lang-cpp` | optional; install separately | `tree-sitter-cpp` 0.23.4 | MIT | Copyright (c) 2014 Max Brunsfeld |
69
+ | `@ast-grep/lang-csharp` | optional; install separately | `tree-sitter-c-sharp` 0.23.1 | MIT | Copyright (c) 2014-2023 Max Brunsfeld, Damien Guard, Amaan Qureshi, and contributors. |
70
+ | `@ast-grep/lang-go` | optional; install separately | `tree-sitter-go` 0.25.0 | MIT | Copyright (c) 2014 Max Brunsfeld |
71
+ | `@ast-grep/lang-java` | optional; install separately | `tree-sitter-java` 0.23.5 | MIT | Copyright (c) 2017 Ayman Nadeem |
72
+ | `@ast-grep/lang-kotlin` | optional; install separately | `tree-sitter-kotlin` 0.3.8 | MIT | Copyright (c) 2019 fwcd |
73
+ | `@ast-grep/lang-php` | optional; install separately | `tree-sitter-php` 0.24.2 | MIT | Copyright (c) 2017 Josh Vera, GitHub<br>Copyright (c) 2019 Max Brunsfeld, Amaan Qureshi, Christian Frøystad, Caleb White |
74
+ | `@ast-grep/lang-python` | Dependency | `tree-sitter-python` 0.25.0 | MIT | Copyright (c) 2016 Max Brunsfeld |
75
+ | `@ast-grep/lang-ruby` | optional; install separately | `tree-sitter-ruby` 0.23.1 | MIT | Copyright (c) 2016 Rob Rix |
76
+ | `@ast-grep/lang-rust` | optional; install separately | `tree-sitter-rust` 0.23.2 | MIT | Copyright (c) 2017 Maxim Sokolov |
77
+ | `@ast-grep/lang-swift` | optional; install separately | `tree-sitter-swift` 0.7.1 | MIT | Copyright (c) 2021 alex-pinkus |
78
+
79
+ **An unresolved question that Untangle cannot decide.** All language packages above
80
+ declare `"license": "ISC"` in `package.json`, but include an **MIT** license text.
81
+ Both declarations cannot apply simultaneously. Which declaration ast-grep intends
82
+ cannot be determined externally; this file records
83
+ the contradiction instead of inventing a resolution. For the embedded
84
+ grammars, the license is unambiguous: the table uses the license text
85
+ inside each grammar version's tarball rather than its
86
+ registry metadata's `license` field.
87
+
88
+ Packages marked *optional* are not included in an Untangle installation:
89
+ they are optional `peerDependencies`, which npm
90
+ does not install automatically. They are listed for users who
91
+ add them to enable the corresponding language.
@@ -0,0 +1,10 @@
1
+ import type { HttpExpressionV1 } from "@untangle-code/domain";
2
+ import type { SyntaxNode } from "../languages/shared/syntax.js";
3
+ export declare function namedChildren(node: SyntaxNode): SyntaxNode[];
4
+ export declare function field(node: SyntaxNode, name: string): SyntaxNode | null;
5
+ export declare function unknown(detail: string): HttpExpressionV1;
6
+ /** Only unescaped literals are accepted. Unsupported escapes remain explicit unknowns. */
7
+ export declare function stringValue(node: SyntaxNode | null): string | null;
8
+ /** Interpret syntax, never execute source expressions or scan comments/string contents as code. */
9
+ export declare function expression(node: SyntaxNode | null, depth?: number): HttpExpressionV1;
10
+ //# sourceMappingURL=expression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../src/boundaries/expression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,EAAE,CAE5D;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAEvE;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAExD;AAED,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,EAAE,KAAK,SAAI,GAAG,gBAAgB,CAmE/E"}
@@ -0,0 +1,95 @@
1
+ export function namedChildren(node) {
2
+ return node.children.filter((child) => child.isNamed && child.type !== "comment");
3
+ }
4
+ export function field(node, name) {
5
+ return node.childForFieldName(name);
6
+ }
7
+ export function unknown(detail) {
8
+ return { kind: "unknown", detail };
9
+ }
10
+ /** Only unescaped literals are accepted. Unsupported escapes remain explicit unknowns. */
11
+ export function stringValue(node) {
12
+ if (node === null || (node.type !== "string" && node.type !== "string_literal"))
13
+ return null;
14
+ const raw = node.text;
15
+ const quote = raw[0];
16
+ if ((quote !== "'" && quote !== '"') || raw.at(-1) !== quote || raw.includes("\\"))
17
+ return null;
18
+ if (raw.startsWith(quote.repeat(3)))
19
+ return null;
20
+ return raw.slice(1, -1);
21
+ }
22
+ /** Interpret syntax, never execute source expressions or scan comments/string contents as code. */
23
+ export function expression(node, depth = 0) {
24
+ if (node === null)
25
+ return unknown("missing expression");
26
+ if (depth > 40)
27
+ return unknown("expression depth budget exceeded");
28
+ const next = (child) => expression(child, depth + 1);
29
+ const string = stringValue(node);
30
+ if (string !== null)
31
+ return { kind: "string", value: string };
32
+ if (node.type === "identifier" || node.type === "shorthand_property_identifier") {
33
+ return node.text === "undefined" ? { kind: "undefined" } : { kind: "name", name: node.text };
34
+ }
35
+ if (["parenthesized_expression", "as_expression", "type_assertion", "await_expression"].includes(node.type)) {
36
+ return next(namedChildren(node)[0] ?? null);
37
+ }
38
+ if (node.type === "member_expression" || node.type === "attribute") {
39
+ const property = field(node, "property") ?? field(node, "attribute");
40
+ return property === null
41
+ ? unknown("computed member")
42
+ : {
43
+ kind: "member",
44
+ object: next(field(node, "object")),
45
+ property: property.text,
46
+ };
47
+ }
48
+ if (node.type === "call_expression" || node.type === "call") {
49
+ return {
50
+ kind: "call",
51
+ callee: next(field(node, "function")),
52
+ arguments: namedChildren(field(node, "arguments") ?? node).map(next),
53
+ };
54
+ }
55
+ if (node.type === "template_string") {
56
+ const parts = [];
57
+ for (const child of namedChildren(node)) {
58
+ if (child.type === "string_fragment")
59
+ parts.push(child.text);
60
+ else if (child.type === "template_substitution")
61
+ parts.push(next(namedChildren(child)[0] ?? null));
62
+ else
63
+ return unknown("escaped or unsupported template segment");
64
+ }
65
+ return { kind: "template", parts };
66
+ }
67
+ if (node.type === "binary_expression" &&
68
+ node.children.some((child) => child.text === "+" && !child.isNamed)) {
69
+ return { kind: "template", parts: [next(field(node, "left")), next(field(node, "right"))] };
70
+ }
71
+ if (node.type === "object") {
72
+ const entries = [];
73
+ for (const child of namedChildren(node)) {
74
+ if (child.type === "spread_element")
75
+ entries.push({ spread: next(namedChildren(child)[0] ?? null) });
76
+ else if (child.type === "pair") {
77
+ const key = field(child, "key");
78
+ const literalKey = stringValue(key);
79
+ if (key === null || (literalKey === null && key.type !== "property_identifier")) {
80
+ entries.push({ spread: unknown("computed object key") });
81
+ }
82
+ else
83
+ entries.push({ key: literalKey ?? key.text, value: next(field(child, "value")) });
84
+ }
85
+ else if (child.type === "shorthand_property_identifier") {
86
+ entries.push({ key: child.text, value: next(child) });
87
+ }
88
+ else
89
+ entries.push({ spread: unknown("unsupported object entry") });
90
+ }
91
+ return { kind: "object", entries };
92
+ }
93
+ return unknown(`unsupported ${node.type}`);
94
+ }
95
+ //# sourceMappingURL=expression.js.map