@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,222 @@
1
+ /**
2
+ * The files a bundler's JavaScript API builds from, read from the build scripts a
3
+ * manifest's scripts run: the strings an options object passes as the bundler's entries.
4
+ * A script is read without running it, so a value that is not written out, a computed
5
+ * path or an options object built at run time among them, names nothing.
6
+ */
7
+ import { isArrowFunction, isCallExpression, isConstructorDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isIdentifier, isMethodDeclaration, isNewExpression, isSetAccessorDeclaration, isVariableDeclaration, } from "@typescript/native/ast";
8
+ import { declarationOf, membersNamed, staticModule } from "./static-module.js";
9
+ import { filesNamedBy } from "./configuration-files.js";
10
+ import { ancestors, dirnamePath, isExplicitPath, relativePath, resolvePath } from "../paths.js";
11
+ import { bytewise } from "../text/compare.js";
12
+ import { unwrapped } from "../unwrap.js";
13
+ import { holdsManifest, inInstalledPackages, manifestAt } from "../fs/manifest.js";
14
+ import { globExpression } from "../text/glob.js";
15
+ import { pathsNamed, readCommands } from "../commands/read.js";
16
+ import { manifestCommands } from "../roots/manifest.js";
17
+ import { extensionOf, MODULE_EXTENSIONS } from "../extensions.js";
18
+ /**
19
+ * The bundlers whose build call names its entries: esbuild resolves `entryPoints` against
20
+ * `absWorkingDir` (https://esbuild.github.io/api/#working-directory), webpack `entry`
21
+ * against `context` (https://webpack.js.org/configuration/entry-context/), and Rollup
22
+ * `input` against the working directory, each the manifest's directory when its script runs.
23
+ */
24
+ const BUNDLERS = [
25
+ {
26
+ module: "esbuild",
27
+ calls: ["build", "buildSync", "context"],
28
+ option: "entryPoints",
29
+ base: "absWorkingDir",
30
+ paths: true,
31
+ },
32
+ { module: "webpack", calls: ["default"], option: "entry", base: "context", paths: false },
33
+ { module: "rollup", calls: ["rollup", "watch"], option: "input", base: "", paths: true },
34
+ ];
35
+ /** The one value an object writes last for a key, undefined where it writes none or may hide it. */
36
+ function lastMember(object, key) {
37
+ return membersNamed(object, key)?.at(-1);
38
+ }
39
+ /**
40
+ * The path one entry value writes, read against `dir`: a literal, or a join of the
41
+ * script's own directory and literals, read against that directory.
42
+ */
43
+ function pathOf(value, dir, scriptDir) {
44
+ if (value.kind === "text") {
45
+ const { text } = value;
46
+ const request = !isExplicitPath(text);
47
+ return { path: resolvePath(dir, text), text, request };
48
+ }
49
+ if (value.kind === "directory") {
50
+ const joined = value.segments.join("/");
51
+ return { path: resolvePath(scriptDir, joined), text: joined, request: false };
52
+ }
53
+ return undefined;
54
+ }
55
+ /** The entry values one entries option writes: a value, an array of them, an object of them. */
56
+ function entryValues(value) {
57
+ if (value.kind === "array") {
58
+ return value.elements.flatMap(entryValues);
59
+ }
60
+ if (value.kind === "object") {
61
+ const imported = lastMember(value, "import") ?? lastMember(value, "in");
62
+ if (imported !== undefined) {
63
+ return entryValues(imported);
64
+ }
65
+ return value.members.flatMap((member) => entryValues(member.value));
66
+ }
67
+ return [value];
68
+ }
69
+ /** The own files one entry string names, read as `api` reads it. */
70
+ function entriesNamed(files, api, entry) {
71
+ if (!api.paths && entry.request) {
72
+ return [];
73
+ }
74
+ if (api.paths && /[*?[{]/u.test(entry.text)) {
75
+ const expression = globExpression(entry.path);
76
+ return [...files.byName.values()].filter((file) => expression.test(file.fileName));
77
+ }
78
+ const dir = dirnamePath(entry.path);
79
+ return filesNamedBy(files, dir, entry.path.slice(dir.length + 1));
80
+ }
81
+ /** Whether one node is a function, whose body runs only where something calls it. */
82
+ function isFunction(node) {
83
+ return (isFunctionDeclaration(node) ||
84
+ isFunctionExpression(node) ||
85
+ isArrowFunction(node) ||
86
+ isMethodDeclaration(node) ||
87
+ isConstructorDeclaration(node) ||
88
+ isGetAccessorDeclaration(node) ||
89
+ isSetAccessorDeclaration(node));
90
+ }
91
+ /**
92
+ * The calls one build script runs: those of its top level, and those of each function a
93
+ * call it runs calls or passes on, as a callee, an argument or a function called where it
94
+ * is written, a name read through to the function it declares.
95
+ */
96
+ function runCalls(file, each) {
97
+ const ran = new Set();
98
+ const run = (fn) => {
99
+ if (!ran.has(fn)) {
100
+ ran.add(fn);
101
+ fn.forEachChild(visit);
102
+ }
103
+ };
104
+ const runs = (node) => {
105
+ const at = unwrapped(node);
106
+ const declared = isIdentifier(at) ? declarationOf(at) : undefined;
107
+ const fn = declared !== undefined && isVariableDeclaration(declared) && declared.initializer
108
+ ? unwrapped(declared.initializer)
109
+ : (declared ?? at);
110
+ if (isFunction(fn)) {
111
+ run(fn);
112
+ }
113
+ };
114
+ const visit = (node) => {
115
+ if (isFunction(node)) {
116
+ return;
117
+ }
118
+ if (isCallExpression(node) || isNewExpression(node)) {
119
+ if (isCallExpression(node)) {
120
+ each(node);
121
+ }
122
+ runs(node.expression);
123
+ for (const argument of node.arguments ?? []) {
124
+ runs(argument);
125
+ }
126
+ }
127
+ node.forEachChild(visit);
128
+ };
129
+ file.forEachChild(visit);
130
+ }
131
+ /** The entries every bundler call one build script runs names, read against `dir`. */
132
+ function scriptEntries(file, dir, files) {
133
+ const module = staticModule(file);
134
+ const building = new Map();
135
+ for (const api of BUNDLERS) {
136
+ for (const one of module.calls(api.module)) {
137
+ if (api.calls.includes(one.export)) {
138
+ building.set(one.call, api);
139
+ }
140
+ }
141
+ }
142
+ const scriptDir = dirnamePath(file.fileName);
143
+ const found = [];
144
+ runCalls(file, (call) => {
145
+ const api = building.get(call);
146
+ if (api === undefined) {
147
+ return;
148
+ }
149
+ for (const options of module.argument(call)) {
150
+ const entries = lastMember(options, api.option);
151
+ const base = api.base === "" ? undefined : lastMember(options, api.base);
152
+ const against = base === undefined ? { path: dir } : pathOf(base, dir, scriptDir);
153
+ if (entries === undefined || against === undefined) {
154
+ continue;
155
+ }
156
+ for (const value of entryValues(entries)) {
157
+ const named = pathOf(value, against.path, scriptDir);
158
+ if (named === undefined) {
159
+ continue;
160
+ }
161
+ for (const entry of entriesNamed(files, api, named)) {
162
+ found.push({ file: entry, source: named.text });
163
+ }
164
+ }
165
+ }
166
+ });
167
+ return found;
168
+ }
169
+ /** The modules one manifest's command strings run or name, by absolute path, each below the target root. */
170
+ function scriptModules(host, root, dir) {
171
+ const manifest = manifestAt(host, dir);
172
+ const found = new Set();
173
+ for (const { command } of manifest === undefined ? [] : manifestCommands(host, dir, manifest)) {
174
+ for (const { path } of pathsNamed(readCommands(command, dir))) {
175
+ if (extensionOf(path, MODULE_EXTENSIONS) !== undefined &&
176
+ relativePath(root, path) !== undefined &&
177
+ !inInstalledPackages(path) &&
178
+ host.kindOf(path) === "file") {
179
+ found.add(path);
180
+ }
181
+ }
182
+ }
183
+ return [...found].sort(bytewise);
184
+ }
185
+ /**
186
+ * Every own file of one project a build script names as a bundler's entry: a module a
187
+ * script of a manifest at or above an own file runs, below the target root, read from
188
+ * the program where it holds the module and parsed alone otherwise, where a parser is given.
189
+ */
190
+ export function buildScriptEntries(host, targetRoot, files, parse) {
191
+ const root = resolvePath(host.workingDirectory(), targetRoot);
192
+ const dirs = new Set([root]);
193
+ for (const file of files.byName.values()) {
194
+ for (const dir of ancestors(dirnamePath(file.fileName), root)) {
195
+ if (dirs.has(dir)) {
196
+ break;
197
+ }
198
+ dirs.add(dir);
199
+ }
200
+ }
201
+ const found = [];
202
+ for (const dir of [...dirs].sort(bytewise)) {
203
+ if (!holdsManifest(host, dir)) {
204
+ continue;
205
+ }
206
+ for (const path of scriptModules(host, root, dir)) {
207
+ let script = files.byName.get(path);
208
+ if (script === undefined && parse !== undefined) {
209
+ try {
210
+ script = parse(path, host.readFile(path));
211
+ }
212
+ catch {
213
+ continue;
214
+ }
215
+ }
216
+ if (script !== undefined) {
217
+ found.push(...scriptEntries(script, dir, files));
218
+ }
219
+ }
220
+ }
221
+ return found;
222
+ }
@@ -6,29 +6,32 @@
6
6
  * every string either holds as it likes, so each one that spells a declared dependency
7
7
  * uses it and each relative one that names a source file of the program roots the file.
8
8
  */
9
- import { isCallExpression, isExportDeclaration, isIdentifier, isImportDeclaration, isNoSubstitutionTemplateLiteral, isStringLiteral, SyntaxKind, } from "@typescript/native/ast";
10
- import { dirnamePath, joinPath, relativePath, resolvePath } from "./paths.js";
11
- const MANIFEST = "package.json";
9
+ import { isNoSubstitutionTemplateLiteral, isStringLiteral, } from "@typescript/native/ast";
10
+ import { relativeSpecifiers } from "./static-module.js";
11
+ import { ancestors, dirnamePath, isAbsolutePath, joinPath, relativePath, resolvePath, startsRelativePath, } from "../paths.js";
12
+ import { bytewise } from "../text/compare.js";
13
+ import { isRecord } from "../json-document.js";
14
+ import { filesIn } from "../fs/tree.js";
15
+ import { DEPENDENCY_SECTIONS, holdsManifest, inInstalledPackages, manifestAt, readJSON, } from "../fs/manifest.js";
16
+ import { readCommands } from "../commands/read.js";
17
+ import { manifestCommands } from "../roots/manifest.js";
18
+ import { APPENDED_EXTENSIONS, extensionOf, MODULE_EXTENSIONS } from "../extensions.js";
19
+ /** The extensions of a configuration module, as an expression's alternatives. */
20
+ const MODULE_NAME = MODULE_EXTENSIONS.map((one) => one.slice(1)).join("|");
12
21
  /** A configuration module's name, each form with the spelling a root reports it by. */
13
22
  const MODULE_FORMS = [
14
- { name: /^[\w-]+\.config\.(?:js|mjs|cjs|ts|mts|cts)$/u, form: "<stem>.config.<ext>" },
15
23
  {
16
- name: /^[\w-]+\.[\w-]+\.config\.(?:js|mjs|cjs|ts|mts|cts)$/u,
24
+ name: new RegExp(String.raw `^[\w-]+\.config\.(?:${MODULE_NAME})$`, "u"),
25
+ form: "<stem>.config.<ext>",
26
+ },
27
+ {
28
+ name: new RegExp(String.raw `^[\w-]+\.[\w-]+\.config\.(?:${MODULE_NAME})$`, "u"),
17
29
  form: "<stem>.<qualifier>.config.<ext>",
18
30
  },
19
31
  { name: /^\.[\w-]+rc\.(?:js|mjs|cjs)$/u, form: ".<stem>rc.<ext>" },
20
32
  ];
21
33
  /** A JSON configuration file's name. */
22
34
  const DOCUMENT_NAME = /^(?:[\w-]+(?:\.[\w-]+)?\.config\.json|\.[\w-]+rc(?:\.json)?)$/u;
23
- /** The manifest members a dependency is declared in. */
24
- const DEPENDENCY_MEMBERS = [
25
- "dependencies",
26
- "devDependencies",
27
- "peerDependencies",
28
- "optionalDependencies",
29
- ];
30
- /** The prefixes a string names a file with, relative to the file that writes it. */
31
- const RELATIVE_PREFIXES = ["./", "../"];
32
35
  /** The JavaScript extensions a relative specifier from a configuration file stands for TypeScript under. */
33
36
  const COUNTERPARTS = [
34
37
  [".js", [".ts", ".tsx"]],
@@ -36,8 +39,6 @@ const COUNTERPARTS = [
36
39
  [".mjs", [".mts"]],
37
40
  [".cjs", [".cts"]],
38
41
  ];
39
- /** The extensions appended to a relative specifier from a configuration file, in order. */
40
- const APPENDED = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
41
42
  /** The extensions the program's module resolution appends to a specifier written without one. */
42
43
  export const RESOLVED_EXTENSIONS = [
43
44
  ".ts",
@@ -50,18 +51,14 @@ export const RESOLVED_EXTENSIONS = [
50
51
  ".mjs",
51
52
  ".cjs",
52
53
  ];
53
- /** The directory a package manager installs packages into, whose files are no project's own. */
54
- const MODULES_DIR = "node_modules";
55
54
  /** The file's name, the last segment of its path. */
56
55
  function basename(path) {
57
56
  return path.slice(path.lastIndexOf("/") + 1);
58
57
  }
59
58
  /** Whether one path is the project's own: below the target root and in no `node_modules`. */
60
59
  function isProjectPath(root, path) {
61
- return relativePath(root, path)?.split("/").includes(MODULES_DIR) === false;
62
- }
63
- function isRecord(value) {
64
- return typeof value === "object" && value !== null && !Array.isArray(value);
60
+ const below = relativePath(root, path);
61
+ return below !== undefined && !inInstalledPackages(below);
65
62
  }
66
63
  /** The form one file name is as a configuration module, or undefined where it is none. */
67
64
  export function configurationModuleForm(name) {
@@ -71,161 +68,26 @@ export function configurationModuleForm(name) {
71
68
  export function isConfigurationDocumentName(name) {
72
69
  return DOCUMENT_NAME.test(name);
73
70
  }
74
- /** The flags a tool's command line names its configuration file with. */
75
- const CONFIG_FLAGS = new Set(["--config", "-c"]);
76
- /** The extensions of a module a configuration flag may name. */
77
- const MODULE_EXTENSIONS = [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"];
78
- /** The characters that end a word outside quotes and separate nothing: blanks. */
79
- // Stryker disable next-line Regex: its \v to \V mutant is no valid escape under the u flag, so the whole module fails to parse
80
- const BLANK = /[ \t\r\f\v]/u;
81
- /** The characters that end a word outside quotes and begin an operator: newline included. */
82
- const OPERATOR = /[\n;&|()<>]/u;
83
- /** The characters a backslash escapes inside double quotes; before any other it stands for itself. */
84
- const DOUBLE_QUOTE_ESCAPES = new Set(["$", "`", '"', "\\"]);
85
- /**
86
- * The words of one command line, as POSIX token recognition reads quotes, backslashes,
87
- * line continuations, comments and operators. A word an expansion may change (an unquoted
88
- * `$`, backquote, glob character or leading `~`, or a `$` or backquote in double quotes)
89
- * is computed, and so is the rest of a line whose quote is never closed. A computed word
90
- * and each operator are undefined, so a flag's file is never read across them.
91
- */
92
- function shellWords(command) {
93
- const words = [];
94
- let word;
95
- let computed = false;
96
- const end = () => {
97
- if (word !== undefined) {
98
- words.push(computed ? undefined : word);
99
- }
100
- word = undefined;
101
- computed = false;
102
- };
103
- for (let at = 0; at < command.length; at += 1) {
104
- const char = command.charAt(at);
105
- if (char === "\\" && command.charAt(at + 1) === "\n") {
106
- at += 1;
107
- }
108
- else if (BLANK.test(char)) {
109
- end();
110
- }
111
- else if (OPERATOR.test(char)) {
112
- end();
113
- words.push(undefined);
114
- }
115
- else if (char === "#" && word === undefined) {
116
- const newline = command.indexOf("\n", at);
117
- at = newline < 0 ? command.length : newline - 1;
118
- }
119
- else if (char === "\\") {
120
- at += 1;
121
- word = (word ?? "") + command.charAt(at);
122
- }
123
- else if (char === "'" || char === '"') {
124
- const close = closingQuote(command, at);
125
- if (close < 0) {
126
- word ??= "";
127
- computed = true;
128
- break;
129
- }
130
- const quoted = char === "'"
131
- ? { text: command.slice(at + 1, close), computed: false }
132
- : doubleQuoted(command.slice(at + 1, close));
133
- word = (word ?? "") + quoted.text;
134
- computed ||= quoted.computed;
135
- at = close;
136
- }
137
- else {
138
- computed ||= /[$`*?[]/u.test(char) || (char === "~" && word === undefined);
139
- word = (word ?? "") + char;
140
- }
141
- }
142
- end();
143
- return words;
144
- }
145
- /** The text between one pair of double quotes, unescaped, and whether an expansion may change it. */
146
- function doubleQuoted(inner) {
147
- let text = "";
148
- let computed = false;
149
- for (let at = 0; at < inner.length; at += 1) {
150
- const char = inner.charAt(at);
151
- const next = inner.charAt(at + 1);
152
- if (char === "\\" && next === "\n") {
153
- at += 1;
154
- }
155
- else if (char === "\\" && DOUBLE_QUOTE_ESCAPES.has(next)) {
156
- text += next;
157
- at += 1;
158
- }
159
- else {
160
- computed ||= char === "$" || char === "`";
161
- text += char;
162
- }
163
- }
164
- return { text, computed };
165
- }
166
- /** The index of the quote that closes the one at `open`, or -1 where none does. */
167
- function closingQuote(command, open) {
168
- const quote = command.charAt(open);
169
- for (let at = open + 1; at < command.length; at += 1) {
170
- const char = command.charAt(at);
171
- if (char === quote) {
172
- return at;
173
- }
174
- if (quote === '"' && char === "\\") {
175
- at += 1;
176
- }
177
- }
178
- return -1;
179
- }
180
71
  /**
181
- * The files the scripts of the manifest in one directory name after a configuration flag,
182
- * `--config <file>`, `-c <file>` or `--config=<file>`, each a JSON file or a module below
183
- * the target root and in no `node_modules`.
72
+ * The files the command strings of the manifest in one directory name after a configuration
73
+ * flag, as `commands/read.ts` reads them against the directory each command runs in, each a
74
+ * JSON file or a module below the target root and in no `node_modules`.
184
75
  */
185
76
  function scriptConfigurations(host, root, dir) {
186
- let scripts;
187
- try {
188
- const manifest = JSON.parse(host.readFile(joinPath(dir, MANIFEST)));
189
- scripts = isRecord(manifest) ? manifest["scripts"] : undefined;
190
- }
191
- catch {
192
- return [];
193
- }
194
- if (!isRecord(scripts)) {
195
- return [];
196
- }
77
+ const manifest = manifestAt(host, dir);
197
78
  const found = [];
198
- for (const command of Object.values(scripts)) {
199
- if (typeof command !== "string") {
200
- continue;
201
- }
202
- const words = shellWords(command);
203
- words.forEach((word, at) => {
204
- const named = word !== undefined && CONFIG_FLAGS.has(word)
205
- ? words[at + 1]
206
- : word === undefined
207
- ? undefined
208
- : /^--config=(.+)$/su.exec(word)?.[1];
209
- const path = named === undefined ? undefined : resolvePath(dir, named);
210
- if (path !== undefined &&
211
- [".json", ...MODULE_EXTENSIONS].some((extension) => path.endsWith(extension)) &&
79
+ for (const { command } of manifest === undefined ? [] : manifestCommands(host, dir, manifest)) {
80
+ for (const { dir: runs, written } of readCommands(command, dir).configurations) {
81
+ const path = resolvePath(runs, written);
82
+ if ([".json", ...MODULE_EXTENSIONS].some((extension) => path.endsWith(extension)) &&
212
83
  isProjectPath(root, path) &&
213
84
  host.kindOf(path) === "file") {
214
85
  found.push(path);
215
86
  }
216
- });
87
+ }
217
88
  }
218
89
  return found;
219
90
  }
220
- /** The decoded value of one JSON file, or undefined where it cannot be read or parsed. */
221
- function readDocument(host, path) {
222
- try {
223
- return JSON.parse(host.readFile(path));
224
- }
225
- catch {
226
- return undefined;
227
- }
228
- }
229
91
  /** Every string value one decoded JSON value holds at any depth. */
230
92
  export function documentStrings(value) {
231
93
  if (typeof value === "string") {
@@ -258,10 +120,10 @@ export function moduleStrings(file) {
258
120
  export function configurationFiles(host, targetRoot, files, parse) {
259
121
  const root = resolvePath(host.workingDirectory(), targetRoot);
260
122
  const manifests = new Map();
261
- const holdsManifest = (dir) => {
123
+ const manifestHeld = (dir) => {
262
124
  let held = manifests.get(dir);
263
125
  if (held === undefined) {
264
- held = host.kindOf(joinPath(dir, MANIFEST)) === "file";
126
+ held = holdsManifest(host, dir);
265
127
  manifests.set(dir, held);
266
128
  }
267
129
  return held;
@@ -271,30 +133,23 @@ export function configurationFiles(host, targetRoot, files, parse) {
271
133
  for (const file of files.byPath.values()) {
272
134
  const form = configurationModuleForm(basename(file.fileName));
273
135
  const fileDir = dirnamePath(file.fileName);
274
- if (form !== undefined && holdsManifest(fileDir)) {
136
+ if (form !== undefined && manifestHeld(fileDir)) {
275
137
  modules.push({ file, form, manifestDir: fileDir });
276
138
  }
277
- for (let dir = dirnamePath(file.fileName); relativePath(root, dir) !== undefined && !dirs.has(dir); dir = dirnamePath(dir)) {
139
+ for (const dir of ancestors(dirnamePath(file.fileName), root)) {
140
+ if (dirs.has(dir)) {
141
+ break;
142
+ }
278
143
  dirs.add(dir);
279
144
  }
280
145
  }
281
146
  const pending = [];
282
147
  const named = [];
283
- for (const dir of [...dirs].sort()) {
284
- if (!holdsManifest(dir)) {
148
+ for (const dir of [...dirs].sort(bytewise)) {
149
+ if (!manifestHeld(dir)) {
285
150
  continue;
286
151
  }
287
- let names;
288
- try {
289
- names = host
290
- .readDirectory(dir)
291
- .filter((entry) => !entry.directory && isConfigurationDocumentName(entry.name))
292
- .map((entry) => entry.name)
293
- .sort();
294
- }
295
- catch {
296
- names = [];
297
- }
152
+ const names = filesIn(host, dir, isConfigurationDocumentName);
298
153
  pending.push(...names.map((name) => ({ path: joinPath(dir, name), manifestDir: dir })));
299
154
  for (const path of scriptConfigurations(host, root, dir)) {
300
155
  const held = files.byName.get(path);
@@ -318,7 +173,7 @@ export function configurationFiles(host, targetRoot, files, parse) {
318
173
  continue;
319
174
  }
320
175
  if (document === undefined) {
321
- const value = readDocument(host, next.path);
176
+ const value = readJSON(host, next.path);
322
177
  if (value === undefined) {
323
178
  unreadable.add(next.path);
324
179
  continue;
@@ -328,9 +183,7 @@ export function configurationFiles(host, targetRoot, files, parse) {
328
183
  }
329
184
  document.manifestDirs.push(next.manifestDir);
330
185
  for (const text of document.strings) {
331
- const path = RELATIVE_PREFIXES.some((prefix) => text.startsWith(prefix))
332
- ? resolvePath(dirnamePath(next.path), text)
333
- : undefined;
186
+ const path = startsRelativePath(text) ? resolvePath(dirnamePath(next.path), text) : undefined;
334
187
  if (path?.endsWith(".json") === true &&
335
188
  isProjectPath(root, path) &&
336
189
  host.kindOf(path) === "file") {
@@ -343,50 +196,9 @@ export function configurationFiles(host, targetRoot, files, parse) {
343
196
  documents: [...documents.values()],
344
197
  outside: parse === undefined
345
198
  ? []
346
- : outsideModules(host, root, [...dirs], files, holdsManifest, parse, named),
199
+ : outsideModules(host, root, [...dirs], files, manifestHeld, parse, named),
347
200
  };
348
201
  }
349
- /** The literal module specifier one `require(...)` or `import(...)` call names, if any. */
350
- function calledSpecifier(node) {
351
- if (!isCallExpression(node) || node.arguments.length !== 1) {
352
- return undefined;
353
- }
354
- const callee = node.expression;
355
- const loads = callee.kind === SyntaxKind.ImportKeyword || (isIdentifier(callee) && callee.text === "require");
356
- return loads ? node.arguments[0] : undefined;
357
- }
358
- /**
359
- * The relative specifiers one file's imports and re-exports name, and those its
360
- * `require(...)` and `import(...)` calls name by a literal.
361
- */
362
- export function relativeSpecifiers(file) {
363
- const known = specifiersOf.get(file);
364
- if (known !== undefined) {
365
- return known;
366
- }
367
- const found = [];
368
- const named = (specifier) => {
369
- if (specifier !== undefined &&
370
- (isStringLiteral(specifier) || isNoSubstitutionTemplateLiteral(specifier)) &&
371
- RELATIVE_PREFIXES.some((prefix) => specifier.text.startsWith(prefix))) {
372
- found.push(specifier.text);
373
- }
374
- };
375
- const visit = (node) => {
376
- named(calledSpecifier(node));
377
- node.forEachChild(visit);
378
- };
379
- for (const statement of file.statements) {
380
- named(isImportDeclaration(statement) || isExportDeclaration(statement)
381
- ? statement.moduleSpecifier
382
- : undefined);
383
- visit(statement);
384
- }
385
- specifiersOf.set(file, found);
386
- return found;
387
- }
388
- /** What {@link relativeSpecifiers} found in each file, which every project of a run reads alike. */
389
- const specifiersOf = new WeakMap();
390
202
  /**
391
203
  * The files no program holds that a chain from `seeds` reads: each seed, and each file
392
204
  * below the target root one imports, re-exports or loads by a relative specifier that no
@@ -407,7 +219,7 @@ export function outsideChain(host, targetRoot, files, parse, seeds) {
407
219
  export function specifierCandidates(dir, specifier) {
408
220
  const path = resolvePath(dir, specifier);
409
221
  const candidates = [];
410
- if (APPENDED.some((extension) => path.endsWith(extension))) {
222
+ if (extensionOf(path, APPENDED_EXTENSIONS) !== undefined) {
411
223
  candidates.push(path);
412
224
  }
413
225
  for (const [extension, counterparts] of COUNTERPARTS) {
@@ -416,8 +228,8 @@ export function specifierCandidates(dir, specifier) {
416
228
  candidates.push(...counterparts.map((one) => stem + one));
417
229
  }
418
230
  }
419
- candidates.push(...APPENDED.map((extension) => path + extension));
420
- candidates.push(...APPENDED.map((extension) => joinPath(path, `index${extension}`)));
231
+ candidates.push(...APPENDED_EXTENSIONS.map((extension) => path + extension));
232
+ candidates.push(...APPENDED_EXTENSIONS.map((extension) => joinPath(path, `index${extension}`)));
421
233
  return candidates;
422
234
  }
423
235
  /** The file on disk one relative specifier from a configuration file reaches, or undefined. */
@@ -429,23 +241,13 @@ export function resolveRelativeSpecifier(host, dir, specifier) {
429
241
  * does not hold, and the project files below `root` they import by a relative specifier,
430
242
  * until no further file joins. A file that cannot be read is skipped.
431
243
  */
432
- function outsideModules(host, root, dirs, files, holdsManifest, parse, named) {
244
+ function outsideModules(host, root, dirs, files, manifestHeld, parse, named) {
433
245
  const pending = [...named];
434
- for (const dir of [...dirs].sort()) {
435
- if (!holdsManifest(dir)) {
436
- continue;
437
- }
438
- let names;
439
- try {
440
- names = host
441
- .readDirectory(dir)
442
- .filter((entry) => !entry.directory && configurationModuleForm(entry.name) !== undefined)
443
- .map((entry) => entry.name)
444
- .sort();
445
- }
446
- catch {
246
+ for (const dir of [...dirs].sort(bytewise)) {
247
+ if (!manifestHeld(dir)) {
447
248
  continue;
448
249
  }
250
+ const names = filesIn(host, dir, (name) => configurationModuleForm(name) !== undefined);
449
251
  pending.push(...names.map((name) => ({ path: joinPath(dir, name), manifestDir: dir })));
450
252
  }
451
253
  const found = new Map();
@@ -481,18 +283,12 @@ function outsideModules(host, root, dirs, files, holdsManifest, parse, named) {
481
283
  }
482
284
  /** Every dependency the manifest in one directory declares, or none where it holds none to read. */
483
285
  export function declaredIn(host, dir) {
484
- let value;
485
- try {
486
- value = JSON.parse(host.readFile(joinPath(dir, MANIFEST)));
487
- }
488
- catch {
489
- return [];
490
- }
491
- if (!isRecord(value)) {
286
+ const value = manifestAt(host, dir);
287
+ if (value === undefined) {
492
288
  return [];
493
289
  }
494
290
  const names = new Set();
495
- for (const member of DEPENDENCY_MEMBERS) {
291
+ for (const member of DEPENDENCY_SECTIONS) {
496
292
  const section = value[member];
497
293
  if (isRecord(section)) {
498
294
  Object.keys(section).forEach((name) => names.add(name));
@@ -511,7 +307,7 @@ export function dependenciesNamed(text, declared) {
511
307
  * none.
512
308
  */
513
309
  export function filesNamedBy(files, dir, text) {
514
- if (text === "" || text.startsWith("/") || /[*?[{]/u.test(text)) {
310
+ if (text === "" || isAbsolutePath(text) || /[*?[{]/u.test(text)) {
515
311
  return [];
516
312
  }
517
313
  const path = resolvePath(dir, text);