@cplieger/deadset-ts 8.0.0-dev.2 → 8.0.0-dev.21

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 (431) hide show
  1. package/README.md +3 -1
  2. package/THIRD_PARTY_NOTICES.md +27 -0
  3. package/dist/bin/mapper-connection.js +2 -1
  4. package/dist/bin/node-host.js +24 -5
  5. package/dist/src/alias-chain.js +35 -9
  6. package/dist/src/amd.js +81 -0
  7. package/dist/src/analysis.js +274 -496
  8. package/dist/src/augmentations.js +64 -3
  9. package/dist/src/automatic-types.js +10 -29
  10. package/dist/src/bindings.js +382 -0
  11. package/dist/src/commands/held.js +499 -0
  12. package/dist/src/commands/read.js +161 -0
  13. package/dist/src/commands/shell.js +169 -0
  14. package/dist/src/commands/tools.js +1847 -0
  15. package/dist/src/component-files.js +3 -2
  16. package/dist/src/component-layer.js +4 -2
  17. package/dist/src/config.js +6 -82
  18. package/dist/src/conformance-record.js +2 -2
  19. package/dist/src/consumers.js +10 -38
  20. package/dist/src/contextual-uses.js +57 -26
  21. package/dist/src/contract/config.generated.js +561 -0
  22. package/dist/src/contract/contract.generated.js +1370 -0
  23. package/dist/src/contract/report.generated.js +866 -0
  24. package/dist/src/dependencies.js +165 -122
  25. package/dist/src/destructuring.js +1 -19
  26. package/dist/src/edges.js +38 -122
  27. package/dist/src/element-access.js +181 -168
  28. package/dist/src/entries/build-scripts.js +222 -0
  29. package/dist/src/{configuration-files.js → entries/configuration-files.js} +52 -256
  30. package/dist/src/{convention-rows.js → entries/convention-rows.js} +170 -30
  31. package/dist/src/entries/conventions.js +740 -0
  32. package/dist/src/{html-entries.js → entries/html-entries.js} +12 -42
  33. package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +5 -28
  34. package/dist/src/entries/run-directories.js +77 -0
  35. package/dist/src/entries/sources.js +144 -0
  36. package/dist/src/entries/static-module.js +670 -0
  37. package/dist/src/entries/test-runners.js +650 -0
  38. package/dist/src/entries/workflow-steps.js +345 -0
  39. package/dist/src/exemptions/argument-places.js +131 -0
  40. package/dist/src/exemptions/calls.js +338 -0
  41. package/dist/src/exemptions/classes.js +13 -0
  42. package/dist/src/{decorator.js → exemptions/decorator.js} +19 -30
  43. package/dist/src/exemptions/detectors.js +48 -0
  44. package/dist/src/{enum-group.js → exemptions/enum-group.js} +9 -16
  45. package/dist/src/{erased-stores.js → exemptions/erased-stores.js} +7 -11
  46. package/dist/src/{framework-lifecycle.js → exemptions/framework-lifecycle.js} +76 -54
  47. package/dist/src/exemptions/generated-file.js +241 -0
  48. package/dist/src/{injection-container.js → exemptions/injection-container.js} +20 -26
  49. package/dist/src/exemptions/installed-globals.js +173 -0
  50. package/dist/src/{interface-satisfaction.js → exemptions/interface-satisfaction.js} +52 -121
  51. package/dist/src/exemptions/lifecycle.js +150 -0
  52. package/dist/src/{reflective-lookup.js → exemptions/reflective-lookup.js} +3 -3
  53. package/dist/src/exemptions/serialization-contract.js +1276 -0
  54. package/dist/src/exemptions/sites.js +182 -0
  55. package/dist/src/{template-field.js → exemptions/template-field.js} +13 -23
  56. package/dist/src/{value-reach.js → exemptions/value-reach.js} +14 -7
  57. package/dist/src/exposure.js +400 -0
  58. package/dist/src/extensions.js +37 -0
  59. package/dist/src/facts.js +38 -0
  60. package/dist/src/failure.js +36 -0
  61. package/dist/src/file-facts.js +3 -26
  62. package/dist/src/findings/completion.js +109 -56
  63. package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
  64. package/dist/src/findings/emitters.js +27 -41
  65. package/dist/src/{implementations.js → findings/implementations.js} +3 -3
  66. package/dist/src/{in-operands.js → findings/in-operands.js} +3 -2
  67. package/dist/src/findings/interfaces.js +4 -5
  68. package/dist/src/findings/intra-function.js +16 -13
  69. package/dist/src/findings/non-code-artifacts.js +17 -12
  70. package/dist/src/findings/reads-and-writes.js +86 -27
  71. package/dist/src/findings/self-check.js +44 -30
  72. package/dist/src/findings/unused-declarations.js +29 -45
  73. package/dist/src/findings/visibility-narrowing.js +23 -31
  74. package/dist/src/findings-pass.js +13 -21
  75. package/dist/src/fs/document.js +52 -0
  76. package/dist/src/fs/manifest.js +67 -0
  77. package/dist/src/fs/tree.js +88 -0
  78. package/dist/src/git-ignore.js +39 -26
  79. package/dist/src/import-bindings.js +73 -28
  80. package/dist/src/index/sites.js +557 -0
  81. package/dist/src/index/values.js +124 -0
  82. package/dist/src/index.js +2 -2
  83. package/dist/src/indexed-access.js +523 -478
  84. package/dist/src/intra-function-parts.js +63 -43
  85. package/dist/src/inventory/commonjs.js +507 -0
  86. package/dist/src/inventory/enumerate.js +167 -0
  87. package/dist/src/inventory/syntax.js +236 -0
  88. package/dist/src/inventory.js +323 -724
  89. package/dist/src/javascript-file.js +48 -0
  90. package/dist/src/json-document.js +198 -67
  91. package/dist/src/keyof-comparisons.js +126 -107
  92. package/dist/src/kinds.js +3 -366
  93. package/dist/src/{components.js → liveness/components.js} +2 -3
  94. package/dist/src/{graph.js → liveness/graph.js} +52 -28
  95. package/dist/src/liveness/matrix.js +99 -0
  96. package/dist/src/liveness/sweep.js +558 -0
  97. package/dist/src/load/classify.js +289 -0
  98. package/dist/src/load/diagnostics.js +87 -0
  99. package/dist/src/load/discover.js +285 -0
  100. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  101. package/dist/src/load/expected-module.js +136 -0
  102. package/dist/src/load/load.js +27 -0
  103. package/dist/src/load/module-lookup.js +37 -0
  104. package/dist/src/load/package-scope.js +56 -0
  105. package/dist/src/load/plan.js +313 -0
  106. package/dist/src/load/specifiers.js +113 -0
  107. package/dist/src/load/synthesize.js +152 -0
  108. package/dist/src/load/test-globals.js +207 -0
  109. package/dist/src/load/test-joins.js +82 -0
  110. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
  111. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
  112. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +24 -66
  113. package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
  114. package/dist/src/{workspace.js → load/workspace.js} +62 -124
  115. package/dist/src/module-declarations.js +70 -85
  116. package/dist/src/overrides.js +134 -112
  117. package/dist/src/partial.js +2 -1
  118. package/dist/src/paths.js +82 -16
  119. package/dist/src/platform-calls.js +78 -0
  120. package/dist/src/platform-symbols.js +134 -0
  121. package/dist/src/position.js +43 -1
  122. package/dist/src/print.js +11 -79
  123. package/dist/src/product.js +13 -0
  124. package/dist/src/query.js +95 -0
  125. package/dist/src/ref.js +12 -20
  126. package/dist/src/references/read-rule.js +1 -0
  127. package/dist/src/references/read-rules.js +48 -0
  128. package/dist/src/references/sink.js +237 -0
  129. package/dist/src/references/sources.js +450 -0
  130. package/dist/src/references.js +117 -1074
  131. package/dist/src/report-schema.js +51 -0
  132. package/dist/src/report.js +57 -41
  133. package/dist/src/reporters/annotations.js +15 -8
  134. package/dist/src/reporters/sarif.js +16 -10
  135. package/dist/src/reporters/template.js +4 -19
  136. package/dist/src/resolve.js +246 -730
  137. package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +22 -24
  138. package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +6 -15
  139. package/dist/src/roots/manifest.js +216 -0
  140. package/dist/src/roots/published-reach.js +412 -0
  141. package/dist/src/roots/root-set.js +487 -0
  142. package/dist/src/roots/unseen-loads.js +236 -0
  143. package/dist/src/run.js +66 -77
  144. package/dist/src/schema.js +320 -343
  145. package/dist/src/scope.js +38 -115
  146. package/dist/src/session.js +37 -29
  147. package/dist/src/source-files.js +6 -10
  148. package/dist/src/stores.js +4 -2
  149. package/dist/src/suppress-file.js +25 -28
  150. package/dist/src/suppress-inline.js +36 -83
  151. package/dist/src/suppress.js +50 -71
  152. package/dist/src/symbol-keys.js +92 -88
  153. package/dist/src/tests/file-class.js +76 -0
  154. package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
  155. package/dist/src/{test-support.js → tests/support.js} +5 -12
  156. package/dist/src/text/compare.js +26 -0
  157. package/dist/src/text/glob.js +194 -0
  158. package/dist/src/text/named-files.js +298 -0
  159. package/dist/src/text/yaml.js +684 -0
  160. package/dist/src/type-errors.js +11 -232
  161. package/dist/src/type-parameter-reads.js +178 -139
  162. package/dist/src/unimplemented-callees.js +262 -242
  163. package/dist/src/unwrap.js +23 -0
  164. package/dist/src/usage.js +10 -0
  165. package/dist/src/vendor/unbash/ansi-c.js +132 -0
  166. package/dist/src/vendor/unbash/arithmetic-parts.js +37 -0
  167. package/dist/src/vendor/unbash/arithmetic.js +591 -0
  168. package/dist/src/vendor/unbash/assignment.js +131 -0
  169. package/dist/src/vendor/unbash/chars.js +48 -0
  170. package/dist/src/vendor/unbash/command.js +41 -0
  171. package/dist/src/vendor/unbash/expansion.js +80 -0
  172. package/dist/src/vendor/unbash/glob.js +268 -0
  173. package/dist/src/vendor/unbash/heredoc.js +27 -0
  174. package/dist/src/vendor/unbash/internal-types.js +1 -0
  175. package/dist/src/vendor/unbash/lexer.js +4274 -0
  176. package/dist/src/vendor/unbash/limits.js +3 -0
  177. package/dist/src/vendor/unbash/parser.js +1366 -0
  178. package/dist/src/vendor/unbash/parts.js +57 -0
  179. package/dist/src/vendor/unbash/substitution-context.js +8 -0
  180. package/dist/src/vendor/unbash/traversal.js +212 -0
  181. package/dist/src/vendor/unbash/types.js +1 -0
  182. package/dist/src/vendor/unbash/word-value.js +61 -0
  183. package/dist/src/vendor/unbash/word.js +40 -0
  184. package/dist/src/verbs/analyze.js +194 -127
  185. package/dist/src/verbs/describe.js +13 -18
  186. package/dist/src/verbs/explain.js +85 -139
  187. package/dist/src/verbs/print-config.js +2 -1
  188. package/dist/src/verbs/print-projects.js +6 -4
  189. package/dist/src/verbs/print-retained.js +30 -6
  190. package/dist/src/verbs/print-roots.js +4 -2
  191. package/dist/src/verbs/verb.js +1 -5
  192. package/dist/src/verbs/version.js +14 -3
  193. package/jsr.json +2 -1
  194. package/package.json +14 -8
  195. package/src/alias-chain.ts +40 -11
  196. package/src/amd.ts +130 -0
  197. package/src/analysis.ts +426 -733
  198. package/src/augmentations.ts +93 -4
  199. package/src/automatic-types.ts +12 -30
  200. package/src/bindings.ts +460 -0
  201. package/src/commands/held.ts +632 -0
  202. package/src/commands/read.ts +242 -0
  203. package/src/commands/shell.ts +228 -0
  204. package/src/commands/tools.ts +2382 -0
  205. package/src/component-files.ts +4 -2
  206. package/src/component-layer.ts +4 -2
  207. package/src/config.ts +31 -302
  208. package/src/conformance-record.ts +2 -2
  209. package/src/consumers.ts +16 -66
  210. package/src/contextual-uses.ts +66 -34
  211. package/src/contract/config.generated.ts +821 -0
  212. package/src/contract/contract.generated.ts +1453 -0
  213. package/src/contract/report.generated.ts +1241 -0
  214. package/src/dependencies.ts +223 -128
  215. package/src/destructuring.ts +1 -31
  216. package/src/edges.ts +41 -140
  217. package/src/element-access.ts +190 -187
  218. package/src/entries/build-scripts.ts +292 -0
  219. package/src/{configuration-files.ts → entries/configuration-files.ts} +68 -278
  220. package/src/{convention-rows.ts → entries/convention-rows.ts} +227 -31
  221. package/src/{conventions.ts → entries/conventions.ts} +367 -583
  222. package/src/{html-entries.ts → entries/html-entries.ts} +22 -48
  223. package/src/{mdx-entries.ts → entries/mdx-entries.ts} +7 -30
  224. package/src/entries/run-directories.ts +108 -0
  225. package/src/entries/sources.ts +266 -0
  226. package/src/entries/static-module.ts +858 -0
  227. package/src/entries/test-runners.ts +835 -0
  228. package/src/entries/workflow-steps.ts +432 -0
  229. package/src/exemptions/argument-places.ts +198 -0
  230. package/src/exemptions/calls.ts +483 -0
  231. package/src/exemptions/classes.ts +49 -0
  232. package/src/exemptions/decorator.ts +56 -0
  233. package/src/exemptions/detectors.ts +75 -0
  234. package/src/{enum-group.ts → exemptions/enum-group.ts} +10 -19
  235. package/src/{erased-stores.ts → exemptions/erased-stores.ts} +7 -14
  236. package/src/{framework-lifecycle.ts → exemptions/framework-lifecycle.ts} +85 -66
  237. package/src/exemptions/generated-file.ts +318 -0
  238. package/src/{injection-container.ts → exemptions/injection-container.ts} +29 -34
  239. package/src/exemptions/installed-globals.ts +255 -0
  240. package/src/{interface-satisfaction.ts → exemptions/interface-satisfaction.ts} +69 -160
  241. package/src/exemptions/lifecycle.ts +286 -0
  242. package/src/{reflective-lookup.ts → exemptions/reflective-lookup.ts} +5 -5
  243. package/src/exemptions/serialization-contract.ts +1729 -0
  244. package/src/exemptions/sites.ts +293 -0
  245. package/src/{template-field.ts → exemptions/template-field.ts} +22 -32
  246. package/src/{value-reach.ts → exemptions/value-reach.ts} +16 -8
  247. package/src/exposure.ts +492 -0
  248. package/src/extensions.ts +45 -0
  249. package/src/facts.ts +46 -0
  250. package/src/failure.ts +63 -0
  251. package/src/file-facts.ts +15 -25
  252. package/src/finding.ts +10 -10
  253. package/src/findings/boundary.ts +11 -0
  254. package/src/findings/completion.ts +133 -64
  255. package/src/findings/dependencies-and-module-machinery.ts +4 -7
  256. package/src/findings/emitter.ts +9 -10
  257. package/src/findings/emitters.ts +38 -52
  258. package/src/{implementations.ts → findings/implementations.ts} +4 -4
  259. package/src/{in-operands.ts → findings/in-operands.ts} +4 -3
  260. package/src/findings/interfaces.ts +7 -9
  261. package/src/findings/intra-function.ts +16 -14
  262. package/src/findings/non-code-artifacts.ts +24 -15
  263. package/src/findings/reads-and-writes.ts +118 -41
  264. package/src/findings/self-check.ts +51 -38
  265. package/src/findings/unused-declarations.ts +31 -49
  266. package/src/findings/visibility-narrowing.ts +36 -40
  267. package/src/findings-pass.ts +15 -31
  268. package/src/fs/document.ts +70 -0
  269. package/src/fs/manifest.ts +96 -0
  270. package/src/fs/tree.ts +110 -0
  271. package/src/git-ignore.ts +50 -26
  272. package/src/host.ts +12 -5
  273. package/src/import-bindings.ts +98 -29
  274. package/src/index/sites.ts +781 -0
  275. package/src/index/values.ts +170 -0
  276. package/src/index.ts +2 -2
  277. package/src/indexed-access.ts +570 -527
  278. package/src/intra-function-parts.ts +73 -44
  279. package/src/inventory/commonjs.ts +696 -0
  280. package/src/inventory/enumerate.ts +203 -0
  281. package/src/inventory/syntax.ts +311 -0
  282. package/src/inventory.ts +442 -895
  283. package/src/javascript-file.ts +54 -0
  284. package/src/json-document.ts +241 -76
  285. package/src/keyof-comparisons.ts +133 -122
  286. package/src/kinds.ts +5 -413
  287. package/src/{components.ts → liveness/components.ts} +4 -6
  288. package/src/{graph.ts → liveness/graph.ts} +100 -35
  289. package/src/liveness/matrix.ts +162 -0
  290. package/src/liveness/sweep.ts +855 -0
  291. package/src/load/classify.ts +433 -0
  292. package/src/load/diagnostics.ts +154 -0
  293. package/src/load/discover.ts +471 -0
  294. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  295. package/src/load/expected-module.ts +194 -0
  296. package/src/load/load.ts +73 -0
  297. package/src/load/module-lookup.ts +50 -0
  298. package/src/load/package-scope.ts +74 -0
  299. package/src/load/plan.ts +513 -0
  300. package/src/load/specifiers.ts +171 -0
  301. package/src/load/synthesize.ts +230 -0
  302. package/src/load/test-globals.ts +251 -0
  303. package/src/load/test-joins.ts +98 -0
  304. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
  305. package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
  306. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +41 -77
  307. package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
  308. package/src/{workspace.ts → load/workspace.ts} +90 -134
  309. package/src/module-declarations.ts +74 -98
  310. package/src/overrides.ts +162 -134
  311. package/src/partial.ts +3 -2
  312. package/src/paths.ts +92 -16
  313. package/src/platform-calls.ts +119 -0
  314. package/src/platform-symbols.ts +189 -0
  315. package/src/position.ts +44 -1
  316. package/src/print.ts +12 -92
  317. package/src/product.ts +18 -0
  318. package/src/query.ts +201 -10
  319. package/src/ref.ts +12 -20
  320. package/src/references/read-rule.ts +60 -0
  321. package/src/references/read-rules.ts +55 -0
  322. package/src/references/sink.ts +314 -0
  323. package/src/references/sources.ts +632 -0
  324. package/src/references.ts +187 -1450
  325. package/src/report-schema.ts +68 -0
  326. package/src/report.ts +103 -226
  327. package/src/reporters/annotations.ts +22 -11
  328. package/src/reporters/json.ts +1 -1
  329. package/src/reporters/reporter.ts +2 -4
  330. package/src/reporters/reporters.ts +1 -1
  331. package/src/reporters/sarif.ts +29 -16
  332. package/src/reporters/template.ts +4 -20
  333. package/src/reporters/text.ts +3 -3
  334. package/src/resolve.ts +284 -1115
  335. package/src/{configured-declarations.ts → roots/configured-declarations.ts} +26 -29
  336. package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +7 -16
  337. package/src/roots/manifest.ts +303 -0
  338. package/src/roots/published-reach.ts +486 -0
  339. package/src/{roots.ts → roots/root-set.ts} +286 -469
  340. package/src/roots/unseen-loads.ts +345 -0
  341. package/src/run.ts +75 -91
  342. package/src/schema.ts +391 -388
  343. package/src/scope.ts +46 -138
  344. package/src/session.ts +87 -55
  345. package/src/source-files.ts +6 -11
  346. package/src/stores.ts +15 -3
  347. package/src/suppress-file.ts +24 -33
  348. package/src/suppress-inline.ts +55 -91
  349. package/src/suppress.ts +78 -79
  350. package/src/symbol-keys.ts +104 -107
  351. package/src/tests/file-class.ts +135 -0
  352. package/src/{outside-tests.ts → tests/outside.ts} +16 -10
  353. package/src/{test-support.ts → tests/support.ts} +15 -21
  354. package/src/text/compare.ts +27 -0
  355. package/src/text/glob.ts +210 -0
  356. package/src/text/named-files.ts +388 -0
  357. package/src/text/yaml.ts +747 -0
  358. package/src/type-errors.ts +18 -288
  359. package/src/type-parameter-reads.ts +187 -158
  360. package/src/unimplemented-callees.ts +297 -280
  361. package/src/unwrap.ts +34 -0
  362. package/src/usage.ts +10 -0
  363. package/src/vendor/unbash/LICENSE +15 -0
  364. package/src/vendor/unbash/VENDORED.md +16 -0
  365. package/src/vendor/unbash/ansi-c.ts +132 -0
  366. package/src/vendor/unbash/arithmetic-parts.ts +53 -0
  367. package/src/vendor/unbash/arithmetic.ts +641 -0
  368. package/src/vendor/unbash/assignment.ts +163 -0
  369. package/src/vendor/unbash/chars.ts +48 -0
  370. package/src/vendor/unbash/command.ts +47 -0
  371. package/src/vendor/unbash/expansion.ts +144 -0
  372. package/src/vendor/unbash/glob.ts +284 -0
  373. package/src/vendor/unbash/heredoc.ts +34 -0
  374. package/src/vendor/unbash/internal-types.ts +94 -0
  375. package/src/vendor/unbash/lexer.ts +4352 -0
  376. package/src/vendor/unbash/limits.ts +3 -0
  377. package/src/vendor/unbash/parser.ts +1612 -0
  378. package/src/vendor/unbash/parts.ts +96 -0
  379. package/src/vendor/unbash/substitution-context.ts +20 -0
  380. package/src/vendor/unbash/traversal.ts +182 -0
  381. package/src/vendor/unbash/types.ts +660 -0
  382. package/src/vendor/unbash/word-value.ts +64 -0
  383. package/src/vendor/unbash/word.ts +50 -0
  384. package/src/verbs/analyze.ts +255 -164
  385. package/src/verbs/describe.ts +19 -17
  386. package/src/verbs/explain.ts +93 -169
  387. package/src/verbs/print-config.ts +2 -1
  388. package/src/verbs/print-projects.ts +6 -4
  389. package/src/verbs/print-retained.ts +36 -6
  390. package/src/verbs/print-roots.ts +4 -2
  391. package/src/verbs/verb.ts +2 -8
  392. package/src/verbs/version.ts +15 -3
  393. package/dist/src/base-url.js +0 -18
  394. package/dist/src/calls.js +0 -155
  395. package/dist/src/conventions.js +0 -937
  396. package/dist/src/discover.js +0 -468
  397. package/dist/src/entry-points.js +0 -529
  398. package/dist/src/exempt-classes.js +0 -75
  399. package/dist/src/exempt.js +0 -209
  400. package/dist/src/generated-file.js +0 -95
  401. package/dist/src/glob.js +0 -65
  402. package/dist/src/manifest.js +0 -165
  403. package/dist/src/matrix.js +0 -246
  404. package/dist/src/pnpm-workspace.js +0 -120
  405. package/dist/src/roots.js +0 -672
  406. package/dist/src/serialization-contract.js +0 -611
  407. package/dist/src/setup-failure.js +0 -23
  408. package/dist/src/sweep.js +0 -224
  409. package/dist/src/test-joins.js +0 -101
  410. package/dist/src/value-flow.js +0 -74
  411. package/dist/src/version.js +0 -7
  412. package/dist/src/workflow-steps.js +0 -185
  413. package/src/base-url.ts +0 -24
  414. package/src/calls.ts +0 -225
  415. package/src/decorator.ts +0 -78
  416. package/src/discover.ts +0 -653
  417. package/src/entry-points.ts +0 -687
  418. package/src/exempt-classes.ts +0 -123
  419. package/src/exempt.ts +0 -323
  420. package/src/generated-file.ts +0 -111
  421. package/src/glob.ts +0 -67
  422. package/src/manifest.ts +0 -234
  423. package/src/matrix.ts +0 -423
  424. package/src/pnpm-workspace.ts +0 -135
  425. package/src/serialization-contract.ts +0 -849
  426. package/src/setup-failure.ts +0 -39
  427. package/src/sweep.ts +0 -347
  428. package/src/test-joins.ts +0 -120
  429. package/src/value-flow.ts +0 -104
  430. package/src/version.ts +0 -7
  431. package/src/workflow-steps.ts +0 -216
@@ -0,0 +1,471 @@
1
+ import type { BuildConfiguration, ProjectConfiguration } from "../config.ts";
2
+ import { LANGUAGE_ROWS } from "../contract/contract.generated.ts";
3
+ import { filesBelow, filesIn } from "../fs/tree.ts";
4
+ import type { Host } from "../host.ts";
5
+ import { packageScope } from "./package-scope.ts";
6
+ import { dirnamePath, joinPath, relativePath, resolvePath } from "../paths.ts";
7
+ import { LANGUAGE, message } from "../product.ts";
8
+ import type { Module, Scope } from "../scope.ts";
9
+ import type { Engine } from "../session.ts";
10
+ import { globExpression } from "../text/glob.ts";
11
+ import { failureExit, type Failure, type FailureExit } from "../failure.ts";
12
+ import { MANIFEST } from "../fs/manifest.ts";
13
+
14
+ /** The names of the files a program of the language is read from. */
15
+ export const MARKERS = LANGUAGE_ROWS[LANGUAGE].markers;
16
+ const MARKER_EXPRESSIONS = MARKERS.map(globExpression);
17
+
18
+ /** Whether one file name is a compiler configuration's: one of the language row's markers. */
19
+ function isConfigFile(name: string): boolean {
20
+ return MARKER_EXPRESSIONS.some((marker) => marker.test(name));
21
+ }
22
+
23
+ /**
24
+ * Where one configuration of a run comes from, which decides what a failure to build it
25
+ * does: a guess discovery derived is dropped, any other ends the run.
26
+ */
27
+ export type Origin = "declared" | "scope" | "derived" | "consumer";
28
+
29
+ /** One consumer the run loads. */
30
+ export interface LoadedConsumer {
31
+ /** The name the consumer publishes itself under, which every finding names it by. */
32
+ readonly id: string;
33
+ /** The consumer's directory, absolute. */
34
+ readonly path: string;
35
+ }
36
+
37
+ /** One compiler configuration a run opens. */
38
+ export interface Configuration {
39
+ /**
40
+ * The name a run gives the project: the identifier the build matrix declares for it, or,
41
+ * for a derived one, its configuration file's path below the target root, else its
42
+ * absolute path. A consumer's is its configuration file's absolute path.
43
+ */
44
+ readonly id: string;
45
+ /** The compiler configuration file, absolute. */
46
+ readonly configFile: string;
47
+ readonly origin: Origin;
48
+ /** The compiler's parse of the configuration, which discovery could read and found not circular. */
49
+ readonly parsed: Parsed;
50
+ /** The consumer the configuration loads, for one whose origin is `consumer`. */
51
+ readonly consumer?: LoadedConsumer | undefined;
52
+ /**
53
+ * The configuration of a program the run forms for JavaScript files, which no file holds,
54
+ * so `configFile` is a free path the snapshot alone holds it at.
55
+ */
56
+ readonly written?: Readonly<Record<string, unknown>> | undefined;
57
+ }
58
+
59
+ /** Whether the run analyzes one configuration as the target's. */
60
+ export function isTargetConfiguration(configuration: Configuration): boolean {
61
+ return configuration.origin !== "consumer";
62
+ }
63
+
64
+ /**
65
+ * One project discovery derived and the run could not build, with the first line of the
66
+ * error that dropped it.
67
+ */
68
+ export interface NotBuilt {
69
+ /** The name the project would have carried, as {@link Configuration.id} spells it. */
70
+ readonly id: string;
71
+ /** The compiler configuration file, absolute. */
72
+ readonly configFile: string;
73
+ /** The error's first line, every path below the target root spelled relative to it. */
74
+ readonly error: string;
75
+ /** The setup failures that dropped it, where one did. */
76
+ readonly failures?: readonly [Failure, ...Failure[]];
77
+ }
78
+
79
+ /**
80
+ * One entry of the target's matrix: a configuration discovery read, or a tree the plan forms
81
+ * programs over for the JavaScript files no configuration lists.
82
+ */
83
+ type Target =
84
+ | { readonly kind: "configuration"; readonly configuration: Configuration }
85
+ /** The target tree of a derived matrix. */
86
+ | { readonly kind: "derived" }
87
+ /** The directory of a matrix entry naming its `package.json`, at the absolute `manifest`. */
88
+ | { readonly kind: "declared"; readonly id: string; readonly manifest: string };
89
+
90
+ /** Every configuration file a run opens, the target's in discovery order, then each consumer's. */
91
+ export interface Discovery {
92
+ /** Whether the matrix is the configuration document's or one discovery derived. */
93
+ readonly mode: "declared" | "derived";
94
+ /** The target's entries, in the order a declared matrix lists them, a derived tree last. */
95
+ readonly targets: readonly Target[];
96
+ /** Every configuration of {@link targets}, in its order, then each consumer's. */
97
+ readonly configurations: readonly Configuration[];
98
+ /** The derived configurations the compiler could not read, in discovery order. */
99
+ readonly notBuilt: readonly NotBuilt[];
100
+ /** Every declared consumer, in the scope's order. */
101
+ readonly consumers: readonly LoadedConsumer[];
102
+ /** The consumers holding no configuration, which the plan forms programs over. */
103
+ readonly unconfigured: readonly LoadedConsumer[];
104
+ }
105
+
106
+ /**
107
+ * The first line of one error about the target, every mention of the target root spelled
108
+ * relative to it: a path below the root loses the root and its separator, and the root
109
+ * itself is `.`.
110
+ */
111
+ export function targetRelative(text: string, targetRoot: string): string {
112
+ const root = targetRoot.endsWith("/") ? targetRoot.slice(0, -1) : targetRoot;
113
+ const [first = ""] = text.split(/\r?\n/u);
114
+ const spelled = first.split(`${root}/`).join("").split(root).join(".").trim();
115
+ return spelled === "" ? "the configuration could not be built" : spelled;
116
+ }
117
+
118
+ /**
119
+ * Whether a derived matrix leaves one configuration file unopened: a `jsconfig.json` beside a
120
+ * `tsconfig.json`, because the compiler's editor host opens the directory's `tsconfig.json`
121
+ * first and so never its `jsconfig.json`.
122
+ */
123
+ function shadowed(host: Host, configFile: string): boolean {
124
+ return (
125
+ configFile.endsWith("/jsconfig.json") &&
126
+ host.kindOf(joinPath(dirnamePath(configFile), "tsconfig.json")) === "file"
127
+ );
128
+ }
129
+
130
+ /** The configuration files directly in `dir` a derived matrix opens, by name. */
131
+ export function configFilesIn(host: Host, dir: string): readonly string[] {
132
+ return filesIn(host, dir, isConfigFile).filter((name) => !shadowed(host, joinPath(dir, name)));
133
+ }
134
+
135
+ /** The configuration files below `root` a derived matrix opens, by absolute path in ascending order. */
136
+ function configFilesUnder(host: Host, root: string): readonly string[] {
137
+ return filesBelow(host, root, isConfigFile)
138
+ .map((path) => joinPath(root, path))
139
+ .filter((path) => !shadowed(host, path));
140
+ }
141
+
142
+ export type Parsed = ReturnType<Engine["parseConfigFile"]>;
143
+
144
+ /** The configuration files one parsed configuration's `references` name. */
145
+ function referencesOf(parsed: Parsed): readonly string[] {
146
+ // The parse answers a directory reference as the directory; the compiler reads a
147
+ // path not ending `.json` as its `tsconfig.json`:
148
+ // https://github.com/microsoft/typescript-go/blob/89d5d5b2849a0db0957065889ca58536fa6d2e4a/internal/core/projectreference.go#L18
149
+ return (parsed.projectReferences ?? []).map(({ path }) =>
150
+ path.endsWith(".json") ? path : joinPath(path, "tsconfig.json"),
151
+ );
152
+ }
153
+
154
+ /**
155
+ * The code of a configuration whose `extends` chain returns to a configuration it already
156
+ * passed. A snapshot that opens two configurations whose `extends` chains reach one such
157
+ * cycle panics (`OwnerCache.AddOwner: entry not found`, typescript 7.1.0-dev.20261014.1),
158
+ * so the analysis refuses one before any snapshot is asked to open it.
159
+ */
160
+ const CIRCULAR_EXTENDS = 18000;
161
+
162
+ /** One configuration file's parse, or why it cannot be read. */
163
+ function readConfiguration(
164
+ engine: Engine,
165
+ configFile: string,
166
+ ): { readonly parsed: Parsed } | { readonly reason: string } {
167
+ try {
168
+ const parsed = engine.parseConfigFile(configFile);
169
+ const circular = parsed.errors.find(({ code }) => code === CIRCULAR_EXTENDS);
170
+ return circular === undefined
171
+ ? { parsed }
172
+ : { reason: `TS${String(circular.code)}: ${circular.text}` };
173
+ } catch (error: unknown) {
174
+ return { reason: message(error) };
175
+ }
176
+ }
177
+
178
+ /** One configuration file the compiler parsed with no circular `extends`, and its parse. */
179
+ interface Read {
180
+ readonly configFile: string;
181
+ readonly parsed: Parsed;
182
+ }
183
+
184
+ /**
185
+ * Every configuration file reached from `pending`, each once, each followed by the
186
+ * configurations it references that `follows` admits, transitively. `unreadable` is told
187
+ * each configuration the compiler cannot read, which the walk then goes on without.
188
+ */
189
+ function derivedFrom(
190
+ engine: Engine,
191
+ host: Host,
192
+ pending: string[],
193
+ follows: (reference: string) => boolean,
194
+ unreadable: (configFile: string, reason: string) => void,
195
+ ): Read[] {
196
+ const seen = new Set<string>();
197
+ const found: Read[] = [];
198
+ for (let configFile = pending.shift(); configFile !== undefined; configFile = pending.shift()) {
199
+ const path = resolvePath(host.workingDirectory(), configFile);
200
+ if (seen.has(path)) {
201
+ continue;
202
+ }
203
+ seen.add(path);
204
+ const read = readConfiguration(engine, path);
205
+ if ("reason" in read) {
206
+ unreadable(path, read.reason);
207
+ continue;
208
+ }
209
+ found.push({ configFile: path, parsed: read.parsed });
210
+ pending.push(...referencesOf(read.parsed).filter(follows));
211
+ }
212
+ return found;
213
+ }
214
+
215
+ /** The name one module publishes itself under: the scope's, else its manifest's. */
216
+ export function moduleIdentity(host: Host, module: Module): string {
217
+ return module.id === "" ? packageScope(host, module.path)("index.ts").package : module.id;
218
+ }
219
+
220
+ /**
221
+ * The compiler configurations one consumer is loaded through: every one under its root and
222
+ * each one those reference, transitively. A consumer that is absent, no directory or holds a
223
+ * configuration the compiler cannot read ends the run naming it, because a finding computed
224
+ * without a declared consumer would claim a reference set the run never read.
225
+ */
226
+ function consumerProjects(engine: Engine, host: Host, root: string): readonly Configuration[] {
227
+ const kind = host.kindOf(root);
228
+ if (kind === "absent") {
229
+ throw failureExit(
230
+ "missing-consumer",
231
+ `the scope declares the consumer ${root}, and nothing is at that path: check the consumer out at ${root} and install its dependencies`,
232
+ );
233
+ }
234
+ if (kind !== "directory") {
235
+ throw failureExit(
236
+ "missing-consumer",
237
+ `the scope declares the consumer ${root}, which is not a directory: check the consumer out at ${root}`,
238
+ );
239
+ }
240
+ const found = derivedFrom(
241
+ engine,
242
+ host,
243
+ [...configFilesUnder(host, root)],
244
+ () => true,
245
+ (configFile, reason) => {
246
+ throw failureExit(
247
+ "missing-consumer",
248
+ `the consumer ${root} does not load, ${configFile} cannot be read as a compiler configuration: ${reason}`,
249
+ );
250
+ },
251
+ );
252
+ return found.map(({ configFile, parsed }) => ({
253
+ id: configFile,
254
+ configFile,
255
+ origin: "consumer" as const,
256
+ parsed,
257
+ }));
258
+ }
259
+
260
+ /** The failure of a consumer that holds no configuration and no JavaScript file a program is formed over. */
261
+ export function consumerWithoutSources(root: string): FailureExit {
262
+ return failureExit(
263
+ "missing-consumer",
264
+ `the consumer ${root} holds no compiler configuration and no JavaScript file, so none of its references can be read: check the consumer out at ${root} with its ${MARKERS.join(", ")} or its JavaScript sources`,
265
+ );
266
+ }
267
+
268
+ /** The failure of a target that holds no configuration and no JavaScript file a program is formed over. */
269
+ export function targetWithoutSources(target: string): FailureExit {
270
+ return failureExit(
271
+ "no-program",
272
+ `${target} holds no compiler configuration, no file named ${MARKERS.join(", ")}, and no JavaScript file: run from the directory that holds one, or name the languages to analyze`,
273
+ );
274
+ }
275
+
276
+ /** A target configuration a matrix or the invocation names that cannot be built, ending the run. */
277
+ function unbuilt(
278
+ named: string,
279
+ reason: string,
280
+ failureClass: Failure["failureClass"] = "no-program",
281
+ ): never {
282
+ throw failureExit(failureClass, unreadableDetail(named, reason));
283
+ }
284
+
285
+ /** What fails and the fix, for a configuration `named` that `reason` keeps from being built. */
286
+ export function unreadableDetail(named: string, reason: string): string {
287
+ return `${named} ${reason}: correct the configuration, or name the configurations to analyze`;
288
+ }
289
+
290
+ /**
291
+ * The projects a build matrix declares, in its order, each a file below the target root, a
292
+ * `package.json` entry a tree for the plan to form in its place. An entry naming an absent file,
293
+ * a directory or a file the compiler cannot read ends the run naming it; one naming an earlier
294
+ * entry's file adds nothing. A reference below the root the matrix does not name ends the run
295
+ * naming both, because the compiler builds a referenced project's sources into the referencing
296
+ * program without reporting their diagnostics. A reference outside the root is an outside project.
297
+ */
298
+ function declaredProjects(
299
+ engine: Engine,
300
+ host: Host,
301
+ targetRoot: string,
302
+ entries: readonly ProjectConfiguration[],
303
+ ): { readonly targets: readonly Target[]; readonly notBuilt: readonly NotBuilt[] } {
304
+ const targets: Target[] = [];
305
+ const projects: Configuration[] = [];
306
+ const references = new Map<string, readonly string[]>();
307
+ const manifests = new Set<string>();
308
+ for (const entry of entries) {
309
+ const configFile = joinPath(targetRoot, entry.project);
310
+ const named = `the project ${JSON.stringify(entry.id)} (${configFile})`;
311
+ const kind = host.kindOf(configFile);
312
+ if (kind !== "file") {
313
+ unbuilt(
314
+ named,
315
+ kind === "absent"
316
+ ? "does not exist"
317
+ : "is a directory, and a project names its compiler configuration file",
318
+ );
319
+ }
320
+ if (references.has(configFile) || manifests.has(configFile)) {
321
+ continue;
322
+ }
323
+ if (configFile.endsWith(`/${MANIFEST}`)) {
324
+ manifests.add(configFile);
325
+ targets.push({ kind: "declared", id: entry.id, manifest: configFile });
326
+ continue;
327
+ }
328
+ const read = readConfiguration(engine, configFile);
329
+ if ("reason" in read) {
330
+ unbuilt(
331
+ named,
332
+ `cannot be read as a compiler configuration: ${read.reason}`,
333
+ "unreadable-configuration",
334
+ );
335
+ }
336
+ references.set(configFile, referencesOf(read.parsed));
337
+ const configuration: Configuration = {
338
+ id: entry.id,
339
+ configFile,
340
+ origin: "declared",
341
+ parsed: read.parsed,
342
+ };
343
+ projects.push(configuration);
344
+ targets.push({ kind: "configuration", configuration });
345
+ }
346
+ for (const project of projects) {
347
+ const unnamed = references
348
+ .get(project.configFile)
349
+ ?.find((path) => !references.has(path) && relativePath(targetRoot, path) !== undefined);
350
+ if (unnamed !== undefined) {
351
+ unbuilt(
352
+ `the project ${JSON.stringify(project.id)} (${project.configFile})`,
353
+ `references ${unnamed}, which the build matrix does not name. A referenced project is built into the program that references it, so the matrix names it too`,
354
+ );
355
+ }
356
+ }
357
+ return { targets, notBuilt: [] };
358
+ }
359
+
360
+ /**
361
+ * The projects a run derives where the matrix declares none: the configuration the scope
362
+ * names for the target where its path names one, every compiler configuration under the
363
+ * target root outside a skipped directory, then each configuration below the root those
364
+ * reference, transitively, each once. A configuration the scope names ends the run where it
365
+ * cannot be read; one the walk found is dropped and named. Where the scope names none, the
366
+ * plan forms programs over the target's JavaScript files no configuration lists.
367
+ */
368
+ function derivedProjects(
369
+ engine: Engine,
370
+ host: Host,
371
+ scope: Scope,
372
+ ): { readonly targets: readonly Target[]; readonly notBuilt: readonly NotBuilt[] } {
373
+ const targetRoot = scope.target.path;
374
+ const fromScope = scope.target.path.endsWith(".json")
375
+ ? [resolvePath(host.workingDirectory(), scope.target.path)]
376
+ : [];
377
+ const absoluteRoot = resolvePath(host.workingDirectory(), targetRoot);
378
+ const rootDir = resolvePath(
379
+ host.workingDirectory(),
380
+ fromScope.length > 0 ? dirnamePath(targetRoot) : targetRoot,
381
+ );
382
+ const idOf = (configFile: string): string => relativePath(targetRoot, configFile) ?? configFile;
383
+ const notBuilt: NotBuilt[] = [];
384
+ const found = derivedFrom(
385
+ engine,
386
+ host,
387
+ [...fromScope, ...configFilesUnder(host, targetRoot)],
388
+ (reference) => relativePath(rootDir, reference) !== undefined,
389
+ (configFile, reason) => {
390
+ const why = `cannot be read as a compiler configuration: ${reason}`;
391
+ if (fromScope.includes(configFile)) {
392
+ unbuilt(configFile, why, "unreadable-configuration");
393
+ }
394
+ const failure: Failure = {
395
+ failureClass: "unreadable-configuration",
396
+ detail: targetRelative(unreadableDetail(idOf(configFile), why), absoluteRoot),
397
+ };
398
+ notBuilt.push({
399
+ id: idOf(configFile),
400
+ configFile,
401
+ error: targetRelative(reason, absoluteRoot),
402
+ failures: [failure],
403
+ });
404
+ },
405
+ );
406
+ const configurations = found.map(({ configFile, parsed }): Configuration => ({
407
+ id: idOf(configFile),
408
+ configFile,
409
+ origin: fromScope.includes(configFile) ? "scope" : "derived",
410
+ parsed,
411
+ }));
412
+ return {
413
+ targets: [
414
+ ...configurations.map((configuration) => ({ kind: "configuration" as const, configuration })),
415
+ ...(fromScope.length > 0 ? [] : [{ kind: "derived" as const }]),
416
+ ],
417
+ notBuilt,
418
+ };
419
+ }
420
+
421
+ /**
422
+ * Every configuration file one run opens: the build matrix's project entries in its order,
423
+ * or, where it holds none, those derived from the scope and the target tree, then each
424
+ * declared consumer's, a configuration the target or an earlier consumer opens being theirs
425
+ * alone. The consumers are read first, so one that cannot be read ends the run before any
426
+ * failure of the target: the Contract's failure-class table lists `missing-consumer` before
427
+ * `no-program`.
428
+ */
429
+ export function discoverProjects(
430
+ engine: Engine,
431
+ host: Host,
432
+ scope: Scope,
433
+ configurations: readonly BuildConfiguration[] = [],
434
+ ): Discovery {
435
+ const consumers = scope.consumers.map((module) => {
436
+ const projects = consumerProjects(engine, host, module.path);
437
+ return { consumer: { id: moduleIdentity(host, module), path: module.path }, projects };
438
+ });
439
+ const declared = configurations.filter(
440
+ (entry): entry is ProjectConfiguration => "project" in entry,
441
+ );
442
+ const target =
443
+ declared.length > 0
444
+ ? {
445
+ mode: "declared" as const,
446
+ ...declaredProjects(engine, host, scope.target.path, declared),
447
+ }
448
+ : { mode: "derived" as const, ...derivedProjects(engine, host, scope) };
449
+
450
+ const read = target.targets.flatMap((one) =>
451
+ one.kind === "configuration" ? [one.configuration] : [],
452
+ );
453
+ const opened = new Set(read.map((one) => one.configFile));
454
+ const consumed: Configuration[] = [];
455
+ for (const { consumer, projects } of consumers) {
456
+ for (const one of projects.filter(({ configFile }) => !opened.has(configFile))) {
457
+ opened.add(one.configFile);
458
+ consumed.push({ ...one, consumer });
459
+ }
460
+ }
461
+ return {
462
+ mode: target.mode,
463
+ targets: target.targets,
464
+ configurations: [...read, ...consumed],
465
+ notBuilt: target.notBuilt,
466
+ consumers: consumers.map(({ consumer }) => consumer),
467
+ unconfigured: consumers
468
+ .filter(({ projects }) => projects.length === 0)
469
+ .map(({ consumer }) => consumer),
470
+ };
471
+ }
@@ -5,7 +5,7 @@
5
5
  * whether the path is the target's own or a workspace package's.
6
6
  */
7
7
 
8
- import { dirnamePath, joinPath, relativePath } from "./paths.ts";
8
+ import { dirnamePath, joinPath, relativePath } from "../paths.ts";
9
9
 
10
10
  /** The source extensions the compiler emits each output extension from. */
11
11
  const EMITTED: readonly { readonly emitted: string; readonly sources: readonly string[] }[] = [
@@ -0,0 +1,194 @@
1
+ import type { SourceFile } from "@typescript/native/ast";
2
+ import {
3
+ isNoSubstitutionTemplateLiteral,
4
+ isStringLiteral,
5
+ type Node,
6
+ } from "@typescript/native/ast";
7
+ import { packageOfSpecifier } from "../dependencies.ts";
8
+ import { MANIFEST } from "../fs/manifest.ts";
9
+ import { entriesOf } from "../fs/tree.ts";
10
+ import type { Host } from "../host.ts";
11
+ import {
12
+ cannotStartPackageName,
13
+ dirnamePath,
14
+ joinPath,
15
+ relativePath,
16
+ resolvePath,
17
+ } from "../paths.ts";
18
+ import { dependencySpecifiers, installedPackage, manifestsAbove } from "./module-lookup.ts";
19
+ import type { CompilerOptions } from "./plan.ts";
20
+
21
+ /** Where one project reads what its imports may name. */
22
+ export interface ModuleContext {
23
+ readonly host: Host;
24
+ /** The root of the module the project is the target's or a consumer's, absolute. */
25
+ readonly targetRoot: string;
26
+ /** The project configuration's `paths` mapping. */
27
+ readonly paths: PathsMapping;
28
+ /** Whether one manifest is a workspace member's, whose dependencies the workspace installs. */
29
+ readonly member: (manifest: string) => boolean;
30
+ }
31
+
32
+ /** One configuration's `paths` mapping, its targets read against `base`. */
33
+ interface PathsMapping {
34
+ readonly base: string;
35
+ readonly entries: readonly { readonly key: string; readonly targets: readonly string[] }[];
36
+ }
37
+
38
+ /** The string literal holding one offset, innermost first, a doc comment's included. */
39
+ function literalAt(file: SourceFile, offset: number): string | undefined {
40
+ let found: string | undefined;
41
+ const visit = (node: Node): void => {
42
+ if (offset < node.pos || offset >= node.end) {
43
+ return;
44
+ }
45
+ if (isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node)) {
46
+ found = node.text;
47
+ }
48
+ // `forEachChild` does not enter a doc comment, where a JavaScript file imports types.
49
+ for (const doc of (node as { readonly jsDoc?: readonly Node[] }).jsDoc ?? []) {
50
+ visit(doc);
51
+ }
52
+ node.forEachChild(visit);
53
+ };
54
+ file.forEachChild(visit);
55
+ return found;
56
+ }
57
+
58
+ /**
59
+ * What one `paths` key's `*` matches in one specifier, `""` for a key with no `*` that
60
+ * is the specifier, or `undefined` where the key does not match it.
61
+ */
62
+ function mappedBy(key: string, specifier: string): string | undefined {
63
+ const star = key.indexOf("*");
64
+ if (star < 0) {
65
+ return key === specifier ? "" : undefined;
66
+ }
67
+ const prefix = key.slice(0, star);
68
+ const suffix = key.slice(star + 1);
69
+ return specifier.length >= prefix.length + suffix.length &&
70
+ specifier.startsWith(prefix) &&
71
+ specifier.endsWith(suffix)
72
+ ? specifier.slice(prefix.length, specifier.length - suffix.length)
73
+ : undefined;
74
+ }
75
+
76
+ /**
77
+ * One `paths` target, its first `*` replaced by `star` taken literally, as the compiler does:
78
+ * https://github.com/microsoft/typescript-go/blob/89d5d5b2849a0db0957065889ca58536fa6d2e4a/internal/module/resolver.go#L1282
79
+ */
80
+ function substituted(target: string, star: string): string {
81
+ const at = target.indexOf("*");
82
+ return at < 0 ? target : target.slice(0, at) + star + target.slice(at + 1);
83
+ }
84
+
85
+ /**
86
+ * Whether a path names something on disk, as written or with any extension; under
87
+ * `fileOnly`, only a file counts.
88
+ */
89
+ function provided(host: Host, path: string, fileOnly: boolean): boolean {
90
+ const counts = (at: string): boolean =>
91
+ fileOnly ? host.kindOf(at) === "file" : host.kindOf(at) !== "absent";
92
+ if (counts(path)) {
93
+ return true;
94
+ }
95
+ const dir = dirnamePath(path);
96
+ const stem = `${path.slice(dir.length + 1)}.`;
97
+ return entriesOf(host, dir).some(
98
+ (entry) => entry.name.startsWith(stem) && counts(joinPath(dir, entry.name)),
99
+ );
100
+ }
101
+
102
+ /** The manifest at or above `dir`, no higher than the target root, that declares `name`. */
103
+ function declaringManifest(
104
+ host: Host,
105
+ dir: string,
106
+ targetRoot: string,
107
+ name: string,
108
+ ): string | undefined {
109
+ for (const { dir: at, manifest } of manifestsAbove(host, dir, targetRoot)) {
110
+ if (dependencySpecifiers(manifest, name).length > 0) {
111
+ return joinPath(at, MANIFEST);
112
+ }
113
+ }
114
+ return undefined;
115
+ }
116
+
117
+ /**
118
+ * Why one import that the compiler cannot resolve names a module the project expects,
119
+ * with the fix, or undefined where the module is one the project does not expect.
120
+ */
121
+ function expectedModule(
122
+ context: ModuleContext,
123
+ importer: string,
124
+ specifier: string,
125
+ ): string | undefined {
126
+ const { host, targetRoot } = context;
127
+ const fix = "run the generator or the build that writes it";
128
+ if (cannotStartPackageName(specifier)) {
129
+ return provided(host, resolvePath(dirnamePath(importer), specifier), false)
130
+ ? undefined
131
+ : `which names no file of the target: ${fix}`;
132
+ }
133
+ if (specifier.startsWith("#")) {
134
+ return `which the manifest's imports map to no file: ${fix}`;
135
+ }
136
+ const mapped = context.paths.entries.flatMap(({ key, targets }) => {
137
+ const star = mappedBy(key, specifier);
138
+ return star === undefined
139
+ ? []
140
+ : targets.map((target) => resolvePath(context.paths.base, substituted(target, star)));
141
+ });
142
+ const name = packageOfSpecifier(specifier);
143
+ // The compiler looks up in `node_modules` what `paths` does not resolve, so the error
144
+ // of an installed package's import is the import's own, a subpath its exports omit:
145
+ // https://github.com/microsoft/typescript-go/blob/89d5d5b2849a0db0957065889ca58536fa6d2e4a/internal/module/resolver.go#L548-L575
146
+ if (name !== undefined && installedPackage(host, dirnamePath(importer), name) !== undefined) {
147
+ return undefined;
148
+ }
149
+ if (mapped.length > 0) {
150
+ return mapped.some((path) => provided(host, path, true))
151
+ ? undefined
152
+ : `which the compiler configuration's paths map to no file: ${fix}`;
153
+ }
154
+ const manifest =
155
+ name === undefined
156
+ ? undefined
157
+ : declaringManifest(host, dirnamePath(importer), targetRoot, name);
158
+ // No run requires a nested package that is no workspace member to be installed.
159
+ if (
160
+ manifest === undefined ||
161
+ (dirnamePath(manifest) !== targetRoot && !context.member(manifest))
162
+ ) {
163
+ return undefined;
164
+ }
165
+ const where = relativePath(targetRoot, manifest) ?? manifest;
166
+ return `a dependency ${where} declares that is not installed: run the package manager's install`;
167
+ }
168
+
169
+ /** The `paths` mapping of the configuration at `configFile` whose parse answered `options`. */
170
+ export function pathsOf(configFile: string, options: CompilerOptions): PathsMapping {
171
+ // The parse answers `pathsBasePath`, the directory of the configuration that writes
172
+ // `paths` (an extended one included), though the client's option type omits it:
173
+ // https://github.com/microsoft/typescript-go/blob/89d5d5b2849a0db0957065889ca58536fa6d2e4a/internal/tsoptions/tsconfigparsing.go#L1120
174
+ const declaredAt = (options as { readonly pathsBasePath?: unknown }).pathsBasePath;
175
+ return {
176
+ base: typeof declaredAt === "string" ? declaredAt : dirnamePath(configFile),
177
+ entries: Object.entries(options.paths ?? {}).map(([key, targets]) => ({ key, targets })),
178
+ };
179
+ }
180
+
181
+ /**
182
+ * Why one import the compiler cannot resolve, at `offset` of `file`, names a module the project
183
+ * expects and nothing provides, with the fix; undefined where the project does not expect it.
184
+ */
185
+ export function missingModule(
186
+ context: ModuleContext,
187
+ file: SourceFile,
188
+ offset: number,
189
+ ): { readonly specifier: string; readonly reason: string } | undefined {
190
+ const specifier = literalAt(file, offset);
191
+ const reason =
192
+ specifier === undefined ? undefined : expectedModule(context, file.fileName, specifier);
193
+ return specifier === undefined || reason === undefined ? undefined : { specifier, reason };
194
+ }