@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
@@ -1,937 +0,0 @@
1
- /**
2
- * The convention rows a run applies, and the files they root. A row applies to a
3
- * manifest that declares its enabling package when the installed package's version is
4
- * in the row's range; its globs are read against that manifest's directory, with every
5
- * directory a configuration property moves read from the property's literal value.
6
- * No configuration file is run.
7
- */
8
- import { isArrayLiteralExpression, isAsExpression, isBinaryExpression, isCallExpression, isClassDeclaration, isComputedPropertyName, isExportAssignment, isExportDeclaration, isExpressionStatement, isFunctionDeclaration, isIdentifier, isImportDeclaration, isNamedExports, isNamespaceImport, isNoSubstitutionTemplateLiteral, isNonNullExpression, isNumericLiteral, isObjectBindingPattern, isObjectLiteralExpression, isParenthesizedExpression, isPropertyAccessExpression, isPropertyAssignment, isSatisfiesExpression, isShorthandPropertyAssignment, isSpreadAssignment, isStringLiteral, isVariableStatement, SyntaxKind, } from "@typescript/native/ast";
9
- import { lineOf } from "./component-files.js";
10
- import { CONVENTION_ROWS, } from "./convention-rows.js";
11
- import { documentStrings } from "./configuration-files.js";
12
- import { globExpression } from "./glob.js";
13
- import { dirnamePath, joinPath, normalizePath, relativePath, resolvePath } from "./paths.js";
14
- import { satisfies } from "./version-range.js";
15
- const JSON_EXTENSION = ".json";
16
- /** A configuration file with no extension that its tool reads as a JSON document. */
17
- const JSON_RC = /^\.[\w-]+rc$/u;
18
- /** The sections an installed package is required by, so its absence fails the run. */
19
- const REQUIRED_SECTIONS = ["dependencies", "devDependencies"];
20
- const DEPENDENCY_SECTIONS = [
21
- ...REQUIRED_SECTIONS,
22
- "peerDependencies",
23
- "optionalDependencies",
24
- ];
25
- function isRecord(value) {
26
- return typeof value === "object" && value !== null && !Array.isArray(value);
27
- }
28
- function readJSON(host, path) {
29
- try {
30
- return JSON.parse(host.readFile(path));
31
- }
32
- catch {
33
- return undefined;
34
- }
35
- }
36
- function declares(manifest, name, sections = DEPENDENCY_SECTIONS) {
37
- if (!isRecord(manifest)) {
38
- return false;
39
- }
40
- return sections.some((section) => {
41
- const held = manifest[section];
42
- return isRecord(held) && Object.hasOwn(held, name);
43
- });
44
- }
45
- /**
46
- * The version the installed package's manifest names, read from the nearest
47
- * `node_modules` at or above `dir` that holds it, `""` where that manifest names
48
- * none, or `undefined` where no `node_modules` holds it.
49
- */
50
- function installedVersion(host, dir, name) {
51
- for (let at = normalizePath(dir);; at = dirnamePath(at)) {
52
- const path = joinPath(at, "node_modules", name, "package.json");
53
- if (host.kindOf(path) === "file") {
54
- const manifest = readJSON(host, path);
55
- const version = isRecord(manifest) ? manifest["version"] : undefined;
56
- return typeof version === "string" ? version : "";
57
- }
58
- if (dirnamePath(at) === at) {
59
- return undefined;
60
- }
61
- }
62
- }
63
- /** Whether one node wraps an expression without changing its value. */
64
- function isWrapper(node) {
65
- return (isParenthesizedExpression(node) ||
66
- isAsExpression(node) ||
67
- isSatisfiesExpression(node) ||
68
- isNonNullExpression(node));
69
- }
70
- /** The expression a wrapper that changes no value holds. */
71
- function unwrapped(node) {
72
- let at = node;
73
- while (isWrapper(at)) {
74
- at = at.expression;
75
- }
76
- return at;
77
- }
78
- /** The key one property is written with, where it is written as a name or as literal text. */
79
- function keyOf(property) {
80
- if (!isPropertyAssignment(property) && !isShorthandPropertyAssignment(property)) {
81
- return undefined;
82
- }
83
- const { name } = property;
84
- const key = isComputedPropertyName(name) ? name.expression : name;
85
- if ((isIdentifier(key) && key === name) ||
86
- isStringLiteral(key) ||
87
- isNoSubstitutionTemplateLiteral(key)) {
88
- return key.text;
89
- }
90
- return undefined;
91
- }
92
- /** Whether one member's computed name is no literal, so it may set any key. */
93
- function computesKey(member) {
94
- const name = member.name;
95
- if (name === undefined || !isComputedPropertyName(name)) {
96
- return false;
97
- }
98
- const key = name.expression;
99
- return !(isStringLiteral(key) || isNumericLiteral(key) || isNoSubstitutionTemplateLiteral(key));
100
- }
101
- /** The values one file's top-level variable declarations bind, by name. */
102
- function declaredValues(file) {
103
- const values = new Map();
104
- for (const statement of file.statements) {
105
- if (isVariableStatement(statement)) {
106
- for (const declaration of statement.declarationList.declarations) {
107
- if (isIdentifier(declaration.name) && declaration.initializer !== undefined) {
108
- values.set(declaration.name.text, declaration.initializer);
109
- }
110
- }
111
- }
112
- }
113
- return values;
114
- }
115
- function isModuleExports(node) {
116
- return (isPropertyAccessExpression(node) &&
117
- isIdentifier(node.expression) &&
118
- node.expression.text === "module" &&
119
- node.name.text === "exports");
120
- }
121
- /**
122
- * Every expression or declaration one file exports as its default, in any module syntax.
123
- * A JSON module's default export is its document's value.
124
- */
125
- function defaultExports(file) {
126
- if (file.fileName.endsWith(JSON_EXTENSION)) {
127
- return file.statements.flatMap((statement) => isExpressionStatement(statement) ? [statement.expression] : []);
128
- }
129
- const found = [];
130
- for (const statement of file.statements) {
131
- if (isExportAssignment(statement)) {
132
- found.push(statement.expression);
133
- }
134
- else if ((isFunctionDeclaration(statement) || isClassDeclaration(statement)) &&
135
- statement.modifiers?.some((one) => one.kind === SyntaxKind.DefaultKeyword) === true) {
136
- found.push(statement);
137
- }
138
- else if (isExportDeclaration(statement) &&
139
- statement.moduleSpecifier === undefined &&
140
- statement.exportClause !== undefined &&
141
- isNamedExports(statement.exportClause)) {
142
- for (const element of statement.exportClause.elements) {
143
- if (element.name.text === "default") {
144
- found.push(element.propertyName ?? element.name);
145
- }
146
- }
147
- }
148
- else if (isExpressionStatement(statement) &&
149
- isBinaryExpression(statement.expression) &&
150
- statement.expression.operatorToken.kind === SyntaxKind.EqualsToken &&
151
- isModuleExports(statement.expression.left)) {
152
- found.push(statement.expression.right);
153
- }
154
- }
155
- return found;
156
- }
157
- /** The declarations whose name is a binding of the scope they are written in. */
158
- const BINDING_KINDS = new Set([
159
- SyntaxKind.VariableDeclaration,
160
- SyntaxKind.Parameter,
161
- SyntaxKind.BindingElement,
162
- SyntaxKind.FunctionDeclaration,
163
- SyntaxKind.ClassDeclaration,
164
- SyntaxKind.ImportClause,
165
- SyntaxKind.ImportSpecifier,
166
- SyntaxKind.NamespaceImport,
167
- SyntaxKind.ImportEqualsDeclaration,
168
- ]);
169
- /** Whether one file declares a binding named `require` at any depth, which shadows the global. */
170
- function declaresRequire(file) {
171
- let found = false;
172
- const visit = (node) => {
173
- const name = node.name;
174
- if (name !== undefined &&
175
- isIdentifier(name) &&
176
- name.text === "require" &&
177
- BINDING_KINDS.has(node.kind)) {
178
- found = true;
179
- }
180
- if (!found) {
181
- node.forEachChild(visit);
182
- }
183
- };
184
- file.forEachChild(visit);
185
- return found;
186
- }
187
- /**
188
- * The top-level `const`, `let` and `var` declarations that bind a `require` of one module,
189
- * written with the module's name as its one string-literal argument, in a file that
190
- * declares no binding named `require`: each binds as an import of the module does.
191
- */
192
- function requireBindings(file, module) {
193
- const found = [];
194
- for (const statement of file.statements) {
195
- if (!isVariableStatement(statement)) {
196
- continue;
197
- }
198
- for (const declaration of statement.declarationList.declarations) {
199
- const value = declaration.initializer === undefined ? undefined : unwrapped(declaration.initializer);
200
- const [argument, ...rest] = value !== undefined && isCallExpression(value) ? value.arguments : [];
201
- if (value === undefined ||
202
- !isCallExpression(value) ||
203
- !isIdentifier(value.expression) ||
204
- value.expression.text !== "require" ||
205
- argument === undefined ||
206
- rest.length > 0 ||
207
- !isStringLiteral(argument) ||
208
- argument.text !== module) {
209
- continue;
210
- }
211
- if (isIdentifier(declaration.name) || isObjectBindingPattern(declaration.name)) {
212
- found.push(declaration.name);
213
- }
214
- }
215
- }
216
- return found.length > 0 && declaresRequire(file) ? [] : found;
217
- }
218
- /**
219
- * The first argument of every call one file makes to one module's export, through a
220
- * named or a namespace import; `undefined` for a call with no argument.
221
- */
222
- function optionsArguments(file, call) {
223
- const names = new Set();
224
- const namespaces = new Set();
225
- for (const name of requireBindings(file, call.module)) {
226
- if (isIdentifier(name)) {
227
- namespaces.add(name.text);
228
- continue;
229
- }
230
- for (const element of name.elements) {
231
- const local = element.name;
232
- const exported = element.propertyName ?? local;
233
- if (element.dotDotDotToken === undefined &&
234
- local !== undefined &&
235
- isIdentifier(local) &&
236
- exported !== undefined &&
237
- (isIdentifier(exported) || isStringLiteral(exported)) &&
238
- exported.text === call.export) {
239
- names.add(local.text);
240
- }
241
- }
242
- }
243
- for (const statement of file.statements) {
244
- const bindings = isImportDeclaration(statement)
245
- ? statement.importClause?.namedBindings
246
- : undefined;
247
- if (bindings === undefined ||
248
- !isImportDeclaration(statement) ||
249
- !isStringLiteral(statement.moduleSpecifier) ||
250
- statement.moduleSpecifier.text !== call.module) {
251
- continue;
252
- }
253
- if (isNamespaceImport(bindings)) {
254
- namespaces.add(bindings.name.text);
255
- continue;
256
- }
257
- for (const element of bindings.elements) {
258
- if ((element.propertyName ?? element.name).text === call.export) {
259
- names.add(element.name.text);
260
- }
261
- }
262
- }
263
- const found = [];
264
- const visit = (node) => {
265
- if (isCallExpression(node)) {
266
- const callee = unwrapped(node.expression);
267
- const named = isIdentifier(callee) && names.has(callee.text);
268
- const throughNamespace = isPropertyAccessExpression(callee) &&
269
- isIdentifier(callee.expression) &&
270
- namespaces.has(callee.expression.text) &&
271
- callee.name.text === call.export;
272
- if (named || throughNamespace) {
273
- found.push(node.arguments[0]);
274
- }
275
- }
276
- node.forEachChild(visit);
277
- };
278
- file.forEachChild(visit);
279
- return found;
280
- }
281
- /**
282
- * The object literal one expression stands for, read through the file's top-level
283
- * declarations and, where `throughCalls`, through a call's first argument: `undefined`
284
- * for a call with no argument, and any other node where the expression is not written
285
- * out as an object literal.
286
- */
287
- function objectOf(node, declared, throughCalls, seen = new Set()) {
288
- const at = unwrapped(node);
289
- if (isIdentifier(at)) {
290
- const value = declared.get(at.text);
291
- if (value !== undefined && !seen.has(at.text)) {
292
- return objectOf(value, declared, throughCalls, new Set([...seen, at.text]));
293
- }
294
- }
295
- else if (throughCalls && isCallExpression(at)) {
296
- const [first] = at.arguments;
297
- return first === undefined ? undefined : objectOf(first, declared, throughCalls, seen);
298
- }
299
- return at;
300
- }
301
- /** The text of a string literal or a template literal with no substitution, or undefined. */
302
- function literalText(node) {
303
- const at = unwrapped(node);
304
- return isStringLiteral(at) || isNoSubstitutionTemplateLiteral(at) ? at.text : undefined;
305
- }
306
- /**
307
- * The literal texts one value at a path's end writes: the literal itself, or, where
308
- * `elements`, each element of an array literal of literals. Undefined for any other value.
309
- */
310
- function literalTexts(held, elements) {
311
- const one = literalText(held);
312
- if (one !== undefined) {
313
- return [one];
314
- }
315
- if (!elements || !isArrayLiteralExpression(held)) {
316
- return undefined;
317
- }
318
- const texts = held.elements.map(literalText);
319
- return texts.every((text) => text !== undefined) ? texts : undefined;
320
- }
321
- /**
322
- * Reads the values at one path of keys below one object literal into `values`, and
323
- * answers the first member that does not write its value out: a spread, a value that is
324
- * not a literal at the path's end, or one that is not an object literal before it.
325
- */
326
- function readPath(object, keys, values, elements) {
327
- const [key, ...rest] = keys;
328
- for (const member of object.properties) {
329
- if (isSpreadAssignment(member) || computesKey(member)) {
330
- return member;
331
- }
332
- if (keyOf(member) !== key) {
333
- continue;
334
- }
335
- const held = isPropertyAssignment(member) ? unwrapped(member.initializer) : undefined;
336
- if (rest.length === 0) {
337
- const texts = held === undefined ? undefined : literalTexts(held, elements);
338
- if (texts === undefined) {
339
- return member;
340
- }
341
- values.push(...texts);
342
- }
343
- else {
344
- if (held === undefined || !isObjectLiteralExpression(held)) {
345
- return member;
346
- }
347
- const failed = readPath(held, rest, values, elements);
348
- if (failed !== undefined) {
349
- return failed;
350
- }
351
- }
352
- }
353
- return undefined;
354
- }
355
- /**
356
- * Every value one file writes at one property's path inside the objects it is read from,
357
- * as {@link readProperty} reads them, whatever else the path holds.
358
- */
359
- function valuesAt(file, property, call) {
360
- const declared = declaredValues(file);
361
- const objects = call === undefined
362
- ? defaultExports(file).map((one) => objectOf(one, declared, true))
363
- : optionsArguments(file, call).map((one) => one === undefined ? undefined : objectOf(one, declared, false));
364
- const found = [];
365
- const visit = (object, keys) => {
366
- if (!isObjectLiteralExpression(object)) {
367
- return;
368
- }
369
- const [key, ...rest] = keys;
370
- for (const member of object.properties) {
371
- if (!isPropertyAssignment(member) || keyOf(member) !== key) {
372
- continue;
373
- }
374
- const held = unwrapped(member.initializer);
375
- if (rest.length > 0) {
376
- visit(held, rest);
377
- }
378
- else {
379
- found.push(held);
380
- }
381
- }
382
- };
383
- for (const object of objects) {
384
- if (object !== undefined) {
385
- visit(object, property.split("."));
386
- }
387
- }
388
- return found;
389
- }
390
- /** The string literals among values: each value itself, or each element of an array value. */
391
- function stringsAt(file, property, call) {
392
- return valuesAt(file, property, call).flatMap((held) => {
393
- if (literalText(held) !== undefined) {
394
- return [held];
395
- }
396
- return isArrayLiteralExpression(held)
397
- ? held.elements.map(unwrapped).filter((one) => literalText(one) !== undefined)
398
- : [];
399
- });
400
- }
401
- /** Whether one value holds a helper setting's value, as {@link HelperReading} states it. */
402
- function holdsValue(held, value) {
403
- if (value === true) {
404
- return held.kind === SyntaxKind.TrueKeyword;
405
- }
406
- if (literalText(held) === value) {
407
- return true;
408
- }
409
- return (isArrayLiteralExpression(held) &&
410
- held.elements.some((element) => {
411
- const one = unwrapped(element);
412
- const first = isArrayLiteralExpression(one) ? one.elements[0] : one;
413
- return first !== undefined && literalText(first) === value;
414
- }));
415
- }
416
- /** The directory one file's test-file strings are read against, as {@link TestFileReading} states it. */
417
- function testFileRoot(file, dir, reading) {
418
- for (const property of reading.roots) {
419
- const values = valuesAt(file, property, reading.call);
420
- if (values.length > 0) {
421
- const texts = new Set(values.map(literalText));
422
- const [text] = texts;
423
- return texts.size === 1 && text !== undefined ? resolvePath(dir, text) : undefined;
424
- }
425
- }
426
- return dir;
427
- }
428
- /** The files an applied row's test-file properties name. */
429
- function testFilesNamed(host, parse, dir, readings, into) {
430
- for (const reading of readings) {
431
- for (const { file } of readingFiles(host, parse, dir, reading.files)) {
432
- const at = testFileRoot(file, dir, reading);
433
- if (at === undefined) {
434
- continue;
435
- }
436
- for (const node of stringsAt(file, reading.property, reading.call)) {
437
- const text = literalText(node);
438
- if (text !== undefined && text !== "") {
439
- into.add(resolvePath(at, text));
440
- }
441
- }
442
- }
443
- }
444
- }
445
- /** The strings an applied row's selection keys hold, added per configuration file to `into`. */
446
- function selectedStrings(host, parse, dir, readings, into) {
447
- for (const reading of readings) {
448
- for (const { name, file } of readingFiles(host, parse, dir, reading.files)) {
449
- const path = joinPath(dir, name);
450
- const held = into.get(path) ?? { starts: new Set(), texts: [] };
451
- for (const node of stringsAt(file, reading.property, reading.call)) {
452
- held.starts.add(node.getStart());
453
- held.texts.push(literalText(node) ?? "");
454
- }
455
- into.set(path, held);
456
- }
457
- }
458
- }
459
- /**
460
- * The dependencies one manifest declares that a string at any depth of one of its members
461
- * names, alone or followed by `/` and a subpath, a member's name aside.
462
- */
463
- function manifestKeyUses(manifest, keys) {
464
- if (!isRecord(manifest)) {
465
- return [];
466
- }
467
- const declared = DEPENDENCY_SECTIONS.flatMap((section) => {
468
- const held = manifest[section];
469
- return isRecord(held) ? Object.keys(held) : [];
470
- });
471
- const strings = keys.flatMap((key) => documentStrings(manifest[key]));
472
- return declared.filter((name) => strings.some((text) => text === name || text.startsWith(`${name}/`)));
473
- }
474
- /** The extensions an entry a manifest entry key names without one may carry. */
475
- const ENTRY_EXTENSIONS = "{js,jsx,mjs,cjs,ts,tsx,mts,cts}";
476
- /** The characters that make a manifest string a pattern rather than a directory's name. */
477
- const PATTERN = /[*?{}[\]]/u;
478
- /**
479
- * The entry globs one applied row's manifest entry keys write, below the manifest's
480
- * directory: a directory's every module, or a file with or without an extension. A string
481
- * that leaves the directory names nothing.
482
- */
483
- function manifestEntryGlobs(manifest, keys) {
484
- const at = (value, path) => {
485
- const [key, ...rest] = path;
486
- if (key === undefined) {
487
- return [value];
488
- }
489
- if (!isRecord(value)) {
490
- return [];
491
- }
492
- const next = key === "*" ? Object.values(value) : Object.hasOwn(value, key) ? [value[key]] : [];
493
- return next.flatMap((one) => at(one, rest));
494
- };
495
- return keys.flatMap(({ key, directory }) => at(manifest, key.split(".")).flatMap((value) => documentStrings(value).flatMap((text) => {
496
- const path = normalizePath(text)
497
- .replace(/^(?:\.\/)+/u, "")
498
- .replace(/\/+$/u, "");
499
- if (path === "" || path === ".." || path.startsWith("../") || path.startsWith("/")) {
500
- return [];
501
- }
502
- if (!directory) {
503
- return [path, `${path}.${ENTRY_EXTENSIONS}`];
504
- }
505
- return PATTERN.test(path) ? [] : [`${path}/**/*.${ENTRY_EXTENSIONS}`];
506
- })));
507
- }
508
- /**
509
- * Every value one file writes at one property's path inside the object it is read from:
510
- * the options argument of every call `call` names, or the file's default export. A string
511
- * literal or a template literal with no substitution is the value, and so is each element
512
- * of an array literal of them where `elements`. A read object, or an object along the
513
- * path, that is not written out as an object literal, or that spreads another object into
514
- * itself, is not a literal, and neither is any other value at the path.
515
- */
516
- export function readProperty(file, property, call, elements = false) {
517
- const declared = declaredValues(file);
518
- const objects = call === undefined
519
- ? defaultExports(file).map((one) => objectOf(one, declared, true))
520
- : optionsArguments(file, call).map((one) => one === undefined ? undefined : objectOf(one, declared, false));
521
- const values = [];
522
- for (const object of objects) {
523
- if (object === undefined) {
524
- continue;
525
- }
526
- const notLiteral = isObjectLiteralExpression(object)
527
- ? readPath(object, property.split("."), values, elements)
528
- : object;
529
- if (notLiteral !== undefined) {
530
- return { values, notLiteral };
531
- }
532
- }
533
- return { values };
534
- }
535
- /** A directory below a manifest's, `.` for the directory itself, `undefined` outside it. */
536
- function below(dir, path) {
537
- return normalizePath(path) === normalizePath(dir) ? "." : relativePath(dir, path);
538
- }
539
- /**
540
- * Every text a template stands for, each placeholder replaced by every directory its move
541
- * resolved to. A placeholder whose move resolved outside the manifest's directory leaves
542
- * the text standing for nothing.
543
- */
544
- function expand(template, resolved) {
545
- const match = /<([A-Za-z]+)>/u.exec(template);
546
- if (match === null) {
547
- return [template];
548
- }
549
- const [placeholder, id = ""] = match;
550
- const out = [];
551
- for (const value of resolved.get(id) ?? []) {
552
- if (value === undefined) {
553
- continue;
554
- }
555
- const replaced = value === "." && template.startsWith(`${placeholder}/`, match.index)
556
- ? template.replace(`${placeholder}/`, "")
557
- : template.replace(placeholder, value);
558
- out.push(...expand(replaced, resolved));
559
- }
560
- return out;
561
- }
562
- /** The configuration files in one directory that one glob names, by name. */
563
- function configurationFiles(host, dir, glob) {
564
- const expression = globExpression(glob);
565
- let entries;
566
- try {
567
- entries = host.readDirectory(dir);
568
- }
569
- catch {
570
- return [];
571
- }
572
- return entries
573
- .filter((entry) => !entry.directory && expression.test(entry.name))
574
- .map((entry) => entry.name)
575
- .sort();
576
- }
577
- function resolveMove(host, parse, dir, row, move, resolved) {
578
- const set = [];
579
- for (const reading of move.readings) {
580
- for (const { name, text, file } of readingFiles(host, parse, dir, reading.files)) {
581
- const read = readProperty(file, reading.property, reading.call);
582
- if (read.notLiteral !== undefined) {
583
- const line = lineOf(text, read.notLiteral.getStart());
584
- return {
585
- failure: `${name}:${String(line)} sets ${reading.property}, which moves a directory ` +
586
- `the convention row ${row.name} reads, to a value that is not a string literal: ` +
587
- `write it as a literal, or name ${row.name} in ts.disabled_conventions and its ` +
588
- `files in ts.entry_files`,
589
- };
590
- }
591
- set.push(...read.values);
592
- }
593
- }
594
- const dirs = [];
595
- for (const base of expand(move.base ?? ".", resolved)) {
596
- const against = joinPath(dir, base);
597
- const texts = set.length > 0 ? set : move.defaults.flatMap((one) => expand(one, resolved));
598
- for (const text of texts) {
599
- dirs.push(below(dir, resolvePath(against, text)));
600
- }
601
- }
602
- return { dirs: [...new Set(dirs)] };
603
- }
604
- /** The texts each configuration file a reading names holds, parsed, in name order. */
605
- function readingFiles(host, parse, dir, files) {
606
- const found = [];
607
- for (const glob of files) {
608
- for (const name of configurationFiles(host, dir, glob)) {
609
- const path = joinPath(dir, name);
610
- let text;
611
- try {
612
- text = host.readFile(path);
613
- }
614
- catch {
615
- continue;
616
- }
617
- found.push({
618
- name,
619
- text,
620
- file: parse(JSON_RC.test(name) ? `${path}${JSON_EXTENSION}` : path, text),
621
- });
622
- }
623
- }
624
- return found;
625
- }
626
- /**
627
- * The dependencies one manifest declares that an applied row's short names use: the
628
- * package each literal value stands for, and, for a value that is not a literal, every
629
- * declared dependency the row's package name stands for with some value.
630
- */
631
- function shortNameUses(host, parse, dir, manifest, readings) {
632
- const declared = new Set(DEPENDENCY_SECTIONS.flatMap((section) => {
633
- const held = isRecord(manifest) ? manifest[section] : undefined;
634
- return isRecord(held) ? Object.keys(held) : [];
635
- }));
636
- const used = new Set();
637
- for (const reading of readings) {
638
- const [before = "", after = ""] = reading.package.split("{}");
639
- for (const { file } of readingFiles(host, parse, dir, reading.files)) {
640
- const read = readProperty(file, reading.property, reading.call, true);
641
- for (const value of read.values) {
642
- used.add(`${before}${value}${after}`);
643
- }
644
- if (read.notLiteral !== undefined) {
645
- for (const name of declared) {
646
- if (name.length >= before.length + after.length &&
647
- name.startsWith(before) &&
648
- name.endsWith(after)) {
649
- used.add(name);
650
- }
651
- }
652
- }
653
- }
654
- }
655
- return [...used].filter((name) => declared.has(name)).sort(compare);
656
- }
657
- /**
658
- * The package one value of a prefixed-name reading names, or none: ESLint's own naming,
659
- * https://github.com/eslint/eslintrc/blob/main/lib/shared/naming.js
660
- */
661
- function prefixedPackage(value, reading) {
662
- const { prefix, marker } = reading;
663
- let name;
664
- if (marker === undefined) {
665
- if (value.includes(":") || value.startsWith(".") || value.startsWith("/")) {
666
- return undefined;
667
- }
668
- const parts = value.split("/");
669
- name = (value.startsWith("@") ? parts.slice(0, 2) : parts.slice(0, 1)).join("/");
670
- }
671
- else {
672
- if (!value.startsWith(marker) || !value.includes("/", marker.length)) {
673
- return undefined;
674
- }
675
- name = value.slice(marker.length, value.lastIndexOf("/"));
676
- }
677
- if (name === "") {
678
- return undefined;
679
- }
680
- if (!name.startsWith("@")) {
681
- return name.startsWith(`${prefix}-`) ? name : `${prefix}-${name}`;
682
- }
683
- const [scope, rest] = name.split("/");
684
- if (rest === undefined || rest === "" || rest === prefix) {
685
- return `${scope ?? name}/${prefix}`;
686
- }
687
- return rest.startsWith(`${prefix}-`) ? name : `${scope ?? name}/${prefix}-${rest}`;
688
- }
689
- /** The declared dependencies an applied row's prefixed names use. */
690
- function prefixedNameUses(host, parse, dir, manifest, readings) {
691
- const declared = new Set(DEPENDENCY_SECTIONS.flatMap((section) => {
692
- const held = isRecord(manifest) ? manifest[section] : undefined;
693
- return isRecord(held) ? Object.keys(held) : [];
694
- }));
695
- const used = new Set();
696
- for (const reading of readings) {
697
- for (const { file } of readingFiles(host, parse, dir, reading.files)) {
698
- for (const value of readProperty(file, reading.property, reading.call, true).values) {
699
- const named = prefixedPackage(value, reading);
700
- if (named !== undefined && declared.has(named)) {
701
- used.add(named);
702
- }
703
- }
704
- }
705
- }
706
- return [...used].sort(compare);
707
- }
708
- /** The declared dependencies an applied row's helper settings use. */
709
- function helperUses(host, parse, dir, manifest, readings) {
710
- const declared = new Set(DEPENDENCY_SECTIONS.flatMap((section) => {
711
- const held = isRecord(manifest) ? manifest[section] : undefined;
712
- return isRecord(held) ? Object.keys(held) : [];
713
- }));
714
- return readings
715
- .filter((reading) => declared.has(reading.package) &&
716
- readingFiles(host, parse, dir, reading.files).some(({ file }) => valuesAt(file, reading.property, reading.call).some((held) => holdsValue(held, reading.value))))
717
- .map((reading) => reading.package);
718
- }
719
- /**
720
- * The dependencies one manifest declares that an applied row's package keys use: each
721
- * whose name a string under a member of a key's name equals, or begins followed by `/` or
722
- * by `:` and a name. A member's own name is no such string.
723
- */
724
- function packageKeyUses(host, parse, dir, manifest, keys) {
725
- const declared = DEPENDENCY_SECTIONS.flatMap((section) => {
726
- const held = isRecord(manifest) ? manifest[section] : undefined;
727
- return isRecord(held) ? Object.keys(held) : [];
728
- });
729
- const strings = [];
730
- const collect = (node) => {
731
- const text = literalText(node);
732
- if (text !== undefined) {
733
- strings.push(text);
734
- }
735
- else if (isPropertyAssignment(node)) {
736
- collect(node.initializer);
737
- }
738
- else {
739
- node.forEachChild(collect);
740
- }
741
- };
742
- for (const { key, files } of keys) {
743
- const visit = (node) => {
744
- if (isPropertyAssignment(node) && keyOf(node) === key) {
745
- collect(node.initializer);
746
- }
747
- node.forEachChild(visit);
748
- };
749
- for (const { file } of readingFiles(host, parse, dir, files)) {
750
- const values = declaredValues(file);
751
- for (const one of defaultExports(file)) {
752
- const object = objectOf(one, values, true);
753
- if (object !== undefined) {
754
- visit(object);
755
- }
756
- }
757
- }
758
- }
759
- return declared.filter((name) => strings.some((text) => text === name ||
760
- text.startsWith(`${name}/`) ||
761
- (text.startsWith(`${name}:`) && text.length > name.length + 1)));
762
- }
763
- /** Two strings ordered bytewise. */
764
- function compare(a, b) {
765
- if (a === b) {
766
- return 0;
767
- }
768
- return a < b ? -1 : 1;
769
- }
770
- /**
771
- * What the rows decide over the manifests the analysis reads. A row `disabled` names
772
- * is skipped before anything is read for it.
773
- */
774
- export function readConventions(host, parse, manifests, disabled, rows = CONVENTION_ROWS) {
775
- const applied = [];
776
- const globs = [];
777
- const generated = [];
778
- const failures = [];
779
- const uses = new Set();
780
- const selected = new Map();
781
- const testFiles = new Set();
782
- for (const manifest of manifests) {
783
- const declared = readJSON(host, joinPath(manifest.dir, "package.json"));
784
- const versions = new Map();
785
- const missing = new Set();
786
- for (const row of rows) {
787
- if (disabled.includes(row.name) || !declares(declared, row.package)) {
788
- continue;
789
- }
790
- if (!versions.has(row.package)) {
791
- versions.set(row.package, installedVersion(host, manifest.dir, row.package));
792
- }
793
- const version = versions.get(row.package);
794
- if (version === undefined) {
795
- if (missing.has(row.package) ||
796
- manifest.nested === true ||
797
- !declares(declared, row.package, REQUIRED_SECTIONS)) {
798
- continue;
799
- }
800
- missing.add(row.package);
801
- failures.push({
802
- dir: manifest.dir,
803
- failure: {
804
- setupClass: "missing-module",
805
- detail: `${manifest.path} declares ${row.package}, which no node_modules at or ` +
806
- `above its directory holds: run the package manager's install`,
807
- },
808
- });
809
- continue;
810
- }
811
- if (!satisfies(version, row.range)) {
812
- continue;
813
- }
814
- const resolved = new Map();
815
- let failed;
816
- for (const move of row.moves) {
817
- const result = resolveMove(host, parse, manifest.dir, row, move, resolved);
818
- if ("failure" in result) {
819
- failed = result.failure;
820
- break;
821
- }
822
- resolved.set(move.id, result.dirs);
823
- }
824
- if (failed !== undefined) {
825
- const where = dirnamePath(manifest.path);
826
- failures.push({
827
- dir: manifest.dir,
828
- failure: {
829
- setupClass: "convention-not-literal",
830
- detail: where === "." ? failed : `${where}/${failed}`,
831
- },
832
- });
833
- continue;
834
- }
835
- applied.push({
836
- name: row.name,
837
- package: row.package,
838
- version,
839
- manifest: manifest.path,
840
- });
841
- for (const name of shortNameUses(host, parse, manifest.dir, declared, row.shortNames ?? [])) {
842
- uses.add(name);
843
- }
844
- const prefixed = row.prefixedNames ?? [];
845
- for (const name of prefixedNameUses(host, parse, manifest.dir, declared, prefixed)) {
846
- uses.add(name);
847
- }
848
- const keys = row.packageKeys ?? [];
849
- for (const name of packageKeyUses(host, parse, manifest.dir, declared, keys)) {
850
- uses.add(name);
851
- }
852
- for (const name of manifestKeyUses(declared, row.manifestKeys ?? [])) {
853
- uses.add(name);
854
- }
855
- for (const name of helperUses(host, parse, manifest.dir, declared, row.helpers ?? [])) {
856
- uses.add(name);
857
- }
858
- selectedStrings(host, parse, manifest.dir, row.selections ?? [], selected);
859
- testFilesNamed(host, parse, manifest.dir, row.testFiles ?? [], testFiles);
860
- const excludes = [
861
- ...new Set((row.excludes ?? []).flatMap((one) => expand(one, resolved))),
862
- ].map(globExpression);
863
- for (const below of new Set((row.generated ?? []).flatMap((one) => expand(one, resolved)))) {
864
- generated.push({ dir: manifest.dir, row: row.name, below });
865
- }
866
- const written = [
867
- ...row.entries.flatMap((entry) => expand(entry, resolved)),
868
- ...manifestEntryGlobs(declared, row.manifestEntries ?? []),
869
- ];
870
- for (const glob of new Set(written)) {
871
- globs.push({
872
- dir: manifest.dir,
873
- row: row.name,
874
- expression: globExpression(glob),
875
- excludes,
876
- });
877
- }
878
- }
879
- }
880
- const unique = [...new Map(applied.map((one) => [JSON.stringify(one), one])).values()];
881
- unique.sort((a, b) => compare(a.name, b.name) ||
882
- compare(a.manifest, b.manifest) ||
883
- compare(JSON.stringify(a), JSON.stringify(b)));
884
- return {
885
- applied: unique,
886
- globs,
887
- generated,
888
- failures,
889
- uses: [...uses].sort(compare),
890
- selected,
891
- testFiles,
892
- };
893
- }
894
- /**
895
- * Every own file of one project below a directory an applied row names as generated, by
896
- * its path below the target root, with the name of the first such row.
897
- */
898
- export function generatedFiles(conventions, files) {
899
- const found = new Map();
900
- for (const { dir, row, below } of conventions.generated) {
901
- const root = joinPath(dir, below);
902
- for (const [path, file] of files.byPath) {
903
- if (!found.has(path) && relativePath(root, file.fileName) !== undefined) {
904
- found.set(path, row);
905
- }
906
- }
907
- }
908
- return found;
909
- }
910
- /** Every own file of one project an applied row's globs match, once per row. */
911
- export function conventionEntries(conventions, files) {
912
- const found = new Map();
913
- for (const glob of conventions.globs) {
914
- for (const file of files.byName.values()) {
915
- const matched = [file.fileName, ...files.writtenAs(file)].some((name) => {
916
- const path = relativePath(glob.dir, name);
917
- return (path !== undefined &&
918
- glob.expression.test(path) &&
919
- !glob.excludes.some((one) => one.test(path)));
920
- });
921
- if (matched) {
922
- found.set(`${file.fileName}\u0000${glob.row}`, { file, row: glob.row });
923
- }
924
- }
925
- }
926
- return [...found.values()];
927
- }
928
- /**
929
- * The failures the rows met that hold for one configuration: those of a manifest whose
930
- * directory holds the configuration file or one of the files the project owns.
931
- */
932
- export function conventionFailuresFor(conventions, configFile, ownFiles) {
933
- return conventions.failures
934
- .filter(({ dir }) => below(dir, dirnamePath(configFile)) !== undefined ||
935
- ownFiles.some((file) => relativePath(dir, file) !== undefined))
936
- .map(({ failure }) => failure);
937
- }