@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
@@ -4,10 +4,9 @@
4
4
  * that parameter, and a call of a method of a generic receiver fixes the receiver's by its
5
5
  * type arguments. The type query of a type-query alias is no reference.
6
6
  */
7
- import { isArrowFunction, isBindingElement, isCallExpression, isClassDeclaration, isClassExpression, isConstructorDeclaration, isConstructorTypeNode, isFunctionDeclaration, isFunctionExpression, isFunctionTypeNode, isIdentifier, isIndexedAccessTypeNode, isInterfaceDeclaration, isLiteralTypeNode, isMappedTypeNode, isMethodDeclaration, isMethodSignatureDeclaration, isNewExpression, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectBindingPattern, isParenthesizedTypeNode, isPropertyAccessExpression, isPropertyAssignment, isPropertySignatureDeclaration, isStringLiteral, isTypeAliasDeclaration, isTypeOperatorNode, isTypeReferenceNode, isUnionTypeNode, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
7
+ import { isArrowFunction, isBindingElement, isCallExpression, isClassDeclaration, isClassExpression, isConstructorDeclaration, isConstructorTypeNode, isFunctionDeclaration, isFunctionExpression, isFunctionTypeNode, isIdentifier, isIndexedAccessTypeNode, isInterfaceDeclaration, isLiteralTypeNode, isMappedTypeNode, isMethodDeclaration, isMethodSignatureDeclaration, isNewExpression, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectBindingPattern, isParenthesizedTypeNode, isPropertyAccessExpression, isPropertyAssignment, isPropertySignatureDeclaration, isSourceFile, isStringLiteral, isTypeAliasDeclaration, isTypeOperatorNode, isTypeReferenceNode, isUnionTypeNode, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
8
8
  import { SignatureKind, SymbolFlags, } from "@typescript/native/sync";
9
9
  import { nodeKey } from "./inventory.js";
10
- import { renderPosition } from "./position.js";
11
10
  import { UNANSWERED } from "./query.js";
12
11
  import { typeQueryAliases } from "./type-query-alias.js";
13
12
  function isGeneric(node) {
@@ -242,497 +241,543 @@ function carriedIn(generic) {
242
241
  visit(generic);
243
242
  return found;
244
243
  }
244
+ /** The generics enclosing one node, itself included, outermost first. */
245
+ function enclosingGenerics(node) {
246
+ const found = [];
247
+ for (let at = node; !isSourceFile(at); at = at.parent) {
248
+ if (isGeneric(at)) {
249
+ found.push(at);
250
+ }
251
+ }
252
+ return found.reverse();
253
+ }
245
254
  /**
246
- * The references the indexed-access types of one project's own files make to the members
247
- * they name, each made by the declaration that holds the type, the reference or the call,
248
- * or by the file.
255
+ * The reads the indexed-access types of a side's files make of the members they name, each
256
+ * made by the declaration that holds the type, the reference or the call, or by the file. A
257
+ * question the checker leaves unanswered holds what its answer could have read.
249
258
  */
250
- export function indexedAccessReferences(project, held, chains, root, testFiles) {
251
- const queries = project.queries;
252
- const accesses = [];
253
- const carried = new Map();
254
- const names = new Set();
255
- const sites = [];
256
- /** Accesses indexed by a type parameter whose constraint is no `keyof`: it requires each key it names. */
257
- const constrained = [];
258
- /** Calls passing an argument, which a generic declared outside the own files may fix. */
259
- const argumentCalls = [];
260
- const carry = (generic, one) => {
261
- const known = carried.get(generic) ?? [];
262
- const same = known.some((other) => JSON.stringify(sideKey(other)) === JSON.stringify(sideKey(one)));
263
- if (same) {
264
- return false;
265
- }
266
- carried.set(generic, [...known, one]);
267
- const name = calledName(generic);
268
- if (name !== undefined) {
269
- names.add(name);
270
- }
271
- return true;
272
- };
273
- for (const file of project.ownSourceFiles()) {
274
- const fileId = held.declarations.get(nodeKey(file, file));
275
- if (fileId === undefined) {
276
- continue;
277
- }
278
- const aliasTypes = new Set(typeQueryAliases(file).map((alias) => alias.type));
279
- const visit = (node, from, enclosing) => {
280
- const own = held.declarations.get(nodeKey(file, node));
281
- const holder = own ?? from;
282
- const inside = isGeneric(node) ? [...enclosing, node] : enclosing;
283
- if (isGeneric(node) || takesKeyof(node)) {
284
- carriedIn(node).forEach((one) => carry(node, one));
259
+ export const indexedAccess = {
260
+ start() {
261
+ const accesses = [];
262
+ const carried = new Map();
263
+ const names = new Set();
264
+ const sites = [];
265
+ /** Accesses indexed by a type parameter whose constraint is no `keyof`: it requires each key it names. */
266
+ const constrained = [];
267
+ /** Calls passing an argument, which a generic declared outside the own files may fix. */
268
+ const argumentCalls = [];
269
+ const carry = (generic, one) => {
270
+ const known = carried.get(generic) ?? [];
271
+ const same = known.some((other) => JSON.stringify(sideKey(other)) === JSON.stringify(sideKey(one)));
272
+ if (same) {
273
+ return false;
285
274
  }
286
- if (isIndexedAccessTypeNode(node) && !aliasTypes.has(node)) {
287
- const literal = literalNames(node.indexType);
288
- const parameter = literal === undefined ? namedParameter(node.indexType, inside) : undefined;
289
- const constraint = parameter === undefined
290
- ? undefined
291
- : parameter.generic.typeParameters?.[parameter.index]?.constraint;
292
- if (literal !== undefined) {
293
- accesses.push({ file, from: holder, at: node, object: node.objectType, index: literal });
294
- }
295
- else if (constraint !== undefined &&
296
- keyofOperands(constraint).length === 0 &&
297
- namedParameter(node.objectType, inside) === undefined) {
298
- constrained.push({ file, from: holder, at: node, object: node.objectType, constraint });
299
- }
275
+ carried.set(generic, [...known, one]);
276
+ const name = calledName(generic);
277
+ if (name !== undefined) {
278
+ names.add(name);
300
279
  }
301
- if (isTypeReferenceNode(node) &&
302
- node.typeArguments !== undefined &&
303
- isIdentifier(node.typeName)) {
304
- sites.push({ file, from: holder, node, name: node.typeName.text, enclosing: inside });
280
+ return true;
281
+ };
282
+ const aliasTypes = new Map();
283
+ const aliasTypesOf = (file) => {
284
+ let known = aliasTypes.get(file);
285
+ if (known === undefined) {
286
+ known = new Set(typeQueryAliases(file).map((alias) => alias.type));
287
+ aliasTypes.set(file, known);
305
288
  }
306
- if (isCallExpression(node) || isNewExpression(node)) {
307
- const callee = node.expression;
308
- const name = isIdentifier(callee)
309
- ? callee.text
310
- : isPropertyAccessExpression(callee) && isIdentifier(callee.name)
311
- ? callee.name.text
312
- : undefined;
313
- if (name !== undefined) {
314
- const site = { file, from: holder, node, name, enclosing: inside };
315
- sites.push(site);
316
- if (argumentsOf(node).length > 0) {
317
- argumentCalls.push(site);
289
+ return known;
290
+ };
291
+ return {
292
+ visit(node, { file, from }) {
293
+ const holder = from;
294
+ const inside = enclosingGenerics(node);
295
+ if (isGeneric(node) || takesKeyof(node)) {
296
+ carriedIn(node).forEach((one) => carry(node, one));
297
+ }
298
+ if (isIndexedAccessTypeNode(node) && !aliasTypesOf(file).has(node)) {
299
+ const literal = literalNames(node.indexType);
300
+ const parameter = literal === undefined ? namedParameter(node.indexType, inside) : undefined;
301
+ const constraint = parameter === undefined
302
+ ? undefined
303
+ : parameter.generic.typeParameters?.[parameter.index]?.constraint;
304
+ if (literal !== undefined) {
305
+ accesses.push({
306
+ file,
307
+ from: holder,
308
+ at: node,
309
+ object: node.objectType,
310
+ index: literal,
311
+ });
312
+ }
313
+ else if (constraint !== undefined &&
314
+ keyofOperands(constraint).length === 0 &&
315
+ namedParameter(node.objectType, inside) === undefined) {
316
+ constrained.push({ file, from: holder, at: node, object: node.objectType, constraint });
318
317
  }
319
318
  }
320
- }
321
- node.forEachChild((child) => {
322
- visit(child, holder, inside);
323
- });
324
- };
325
- file.forEachChild((child) => {
326
- visit(child, fileId, []);
327
- });
328
- }
329
- /** The literal keys one constraint names, through the type aliases it references. */
330
- const requiredNames = (node, seen) => {
331
- const type = unwrappedType(node);
332
- if (isUnionTypeNode(type)) {
333
- return type.types.flatMap((one) => requiredNames(one, seen));
334
- }
335
- if (!isTypeReferenceNode(type) || type.typeArguments !== undefined) {
336
- return literalNames(type) ?? [];
337
- }
338
- const [symbol] = queries.symbolsAt([type.typeName]);
339
- if (symbol === UNANSWERED || symbol === undefined) {
340
- return [];
341
- }
342
- return symbol.declarations.flatMap((handle) => {
343
- const declared = project.declarationAt(handle)?.node;
344
- return declared !== undefined &&
345
- isTypeAliasDeclaration(declared) &&
346
- declared.typeParameters === undefined &&
347
- !seen.has(declared)
348
- ? requiredNames(declared.type, new Set([...seen, declared]))
349
- : [];
350
- });
351
- };
352
- for (const { constraint, ...access } of constrained) {
353
- const index = requiredNames(constraint, new Set());
354
- if (index.length > 0) {
355
- accesses.push({ ...access, index });
356
- }
357
- }
358
- function partsOf(type) {
359
- const parts = queries.constituents(type);
360
- return parts === UNANSWERED ? [type] : parts;
361
- }
362
- /** The generics one symbol declares, through the alias it may be. */
363
- const genericsOf = (symbol) => {
364
- const target = (symbol.flags & SymbolFlags.Alias) === 0 ? symbol : queries.aliased(symbol);
365
- if (target === UNANSWERED) {
366
- return [];
367
- }
368
- return target.declarations.flatMap((handle) => {
369
- const node = project.declarationAt(handle)?.node;
370
- const generic = node === undefined ? undefined : genericOf(node);
371
- return generic === undefined ? [] : [generic];
372
- });
373
- };
374
- /**
375
- * The type a call's callee is read off: the receiver of a property access, the value an
376
- * object binding pattern destructures the callee from, or the value whose member a
377
- * variable holding the callee is initialized with.
378
- */
379
- const receiverTypeOf = (callee) => {
380
- let operand;
381
- if (isPropertyAccessExpression(callee)) {
382
- const type = queries.typeAt(callee.expression);
383
- operand = type === UNANSWERED ? undefined : type;
384
- const args = operand === undefined ? [] : queries.typeArguments(operand);
385
- if (operand !== undefined && args !== UNANSWERED && args.length > 0) {
386
- return operand;
387
- }
388
- }
389
- const name = isPropertyAccessExpression(callee) ? callee.name : callee;
390
- const [named] = queries.symbolsAt([name]);
391
- const symbol = named === UNANSWERED || named === undefined || (named.flags & SymbolFlags.Alias) === 0
392
- ? named
393
- : queries.aliased(named);
394
- if (symbol === UNANSWERED || symbol === undefined) {
395
- return operand;
396
- }
397
- for (const handle of symbol.declarations) {
398
- const node = project.declarationAt(handle)?.node;
399
- const holder = node !== undefined &&
400
- isBindingElement(node) &&
401
- isObjectBindingPattern(node.parent) &&
402
- isVariableDeclaration(node.parent.parent)
403
- ? node.parent.parent.initializer
404
- : node !== undefined &&
405
- isVariableDeclaration(node) &&
406
- node.initializer !== undefined &&
407
- isPropertyAccessExpression(node.initializer)
408
- ? node.initializer.expression
409
- : undefined;
410
- const type = holder === undefined ? undefined : queries.typeAt(holder);
411
- if (type !== UNANSWERED && type !== undefined) {
412
- return type;
413
- }
414
- }
415
- return operand;
416
- };
417
- /**
418
- * The instantiation of `owner` a receiver's type is, or the first one among the base
419
- * types it extends, breadth first: a subclass fixes its base's type parameters, and
420
- * `this` stands for its class.
421
- */
422
- const instantiationOf = (type, owner) => {
423
- const seen = new Set();
424
- for (let queue = [type]; queue.length > 0;) {
425
- const next = [];
426
- for (const at of queue) {
427
- if (seen.has(at.id)) {
428
- continue;
319
+ if (isTypeReferenceNode(node) &&
320
+ node.typeArguments !== undefined &&
321
+ isIdentifier(node.typeName)) {
322
+ sites.push({ file, from: holder, node, name: node.typeName.text, enclosing: inside });
429
323
  }
430
- seen.add(at.id);
431
- const target = at.isTypeReference() ? queries.targetOf(at) : at;
432
- const symbol = target === UNANSWERED ? undefined : queries.symbolOfType(target);
433
- const declares = symbol !== undefined &&
434
- symbol !== UNANSWERED &&
435
- symbol.declarations.some((handle) => project.declarationAt(handle)?.node === owner);
436
- if (declares) {
437
- return at;
324
+ if (isCallExpression(node) || isNewExpression(node)) {
325
+ const callee = node.expression;
326
+ const name = isIdentifier(callee)
327
+ ? callee.text
328
+ : isPropertyAccessExpression(callee) && isIdentifier(callee.name)
329
+ ? callee.name.text
330
+ : undefined;
331
+ if (name !== undefined) {
332
+ const site = { file, from: holder, node, name, enclosing: inside };
333
+ sites.push(site);
334
+ if (argumentsOf(node).length > 0) {
335
+ argumentCalls.push(site);
336
+ }
337
+ }
438
338
  }
439
- const constraint = at.isTypeParameter() ? queries.constraintOf(at) : undefined;
440
- const bases = at.isTypeParameter() ? [] : queries.baseTypes(at);
441
- next.push(...(bases === UNANSWERED ? [] : bases));
442
- if (constraint !== undefined && constraint !== UNANSWERED) {
443
- next.push(constraint);
339
+ },
340
+ reads({ project, chains }) {
341
+ const queries = project.queries;
342
+ const found = [];
343
+ /**
344
+ * A site whose generic the checker cannot name may fix any generic of its name, whose
345
+ * accesses may then read any member.
346
+ */
347
+ const holdSite = (site) => {
348
+ found.push({ kind: "held", from: site.from, members: true });
349
+ };
350
+ /** The literal keys one constraint names, through the type aliases it references. */
351
+ const requiredNames = (node, seen) => {
352
+ const type = unwrappedType(node);
353
+ if (isUnionTypeNode(type)) {
354
+ return type.types.flatMap((one) => requiredNames(one, seen));
355
+ }
356
+ if (!isTypeReferenceNode(type) || type.typeArguments !== undefined) {
357
+ return literalNames(type) ?? [];
358
+ }
359
+ const [symbol] = queries.symbolsAt([type.typeName]);
360
+ if (symbol === UNANSWERED || symbol === undefined) {
361
+ return [];
362
+ }
363
+ return symbol.declarations.flatMap((handle) => {
364
+ const declared = project.declarationAt(handle)?.node;
365
+ return declared !== undefined &&
366
+ isTypeAliasDeclaration(declared) &&
367
+ declared.typeParameters === undefined &&
368
+ !seen.has(declared)
369
+ ? requiredNames(declared.type, new Set([...seen, declared]))
370
+ : [];
371
+ });
372
+ };
373
+ for (const { constraint, ...access } of constrained) {
374
+ const index = requiredNames(constraint, new Set());
375
+ if (index.length > 0) {
376
+ accesses.push({ ...access, index });
377
+ }
444
378
  }
445
- }
446
- queue = next;
447
- }
448
- return type;
449
- };
450
- /** What one site fixes for one side of a carried access. */
451
- const fixedAt = (site, side, generic) => {
452
- if (side.kind === "written") {
453
- return { kind: "node", node: side.node };
454
- }
455
- const { node } = site;
456
- if (side.kind === "receiver") {
457
- const callee = isCallExpression(node) ? node.expression : undefined;
458
- const owner = receiverOf(generic);
459
- const typed = callee === undefined ? undefined : receiverTypeOf(callee);
460
- const receiver = typed === undefined || owner === undefined ? typed : instantiationOf(typed, owner);
461
- if (receiver === undefined) {
462
- return undefined;
463
- }
464
- const args = queries.typeArguments(receiver);
465
- const type = args === UNANSWERED ? undefined : args[side.index];
466
- return type === undefined ? undefined : { kind: "type", type };
467
- }
468
- if (side.kind === "argument") {
469
- const argument = isTypeReferenceNode(node) ? undefined : node.arguments?.[side.index];
470
- const type = argument === undefined ? undefined : queries.typeAt(argument);
471
- return type === UNANSWERED || type === undefined ? undefined : { kind: "type", type };
472
- }
473
- const written = node.typeArguments?.[side.index];
474
- if (written !== undefined) {
475
- const passed = namedParameter(written, site.enclosing);
476
- const mapped = passed === undefined ? mappedConstraint(written) : undefined;
477
- return passed !== undefined
478
- ? { kind: "passed", generic: passed.generic, index: passed.index }
479
- : { kind: "node", node: mapped ?? written };
480
- }
481
- if (isTypeReferenceNode(node)) {
482
- return undefined;
483
- }
484
- const at = parametersOf(generic).findIndex((parameter) => {
485
- const type = parameter.type === undefined ? undefined : unwrappedType(parameter.type);
486
- return (type !== undefined &&
487
- isTypeReferenceNode(type) &&
488
- isIdentifier(type.typeName) &&
489
- parameterAt(generic, type.typeName.text) === side.index);
490
- });
491
- if (at < 0) {
492
- return undefined;
493
- }
494
- const resolved = queries.resolvedSignature(node);
495
- if (resolved === UNANSWERED || resolved === undefined) {
496
- return undefined;
497
- }
498
- const type = queries.typeAtPosition(resolved, at);
499
- return type === UNANSWERED ? undefined : { kind: "type", type };
500
- };
501
- /** Reads one carried access at one site: an access where both sides are fixed, a carry where one is passed on. */
502
- const readAt = (site, generic, one) => {
503
- const object = fixedAt(site, one.object, generic);
504
- const index = object === undefined ? undefined : fixedAt(site, one.index, generic);
505
- if (object === undefined || index === undefined) {
506
- return false;
507
- }
508
- const passed = [object, index].find((fixed) => fixed.kind === "passed");
509
- if (passed !== undefined) {
510
- const side = (fixed) => fixed.kind === "passed"
511
- ? fixed.generic === passed.generic
512
- ? { kind: "parameter", index: fixed.index }
513
- : undefined
514
- : fixed.kind === "node"
515
- ? { kind: "written", node: fixed.node }
516
- : undefined;
517
- const objectSide = side(object);
518
- const indexSide = side(index);
519
- return objectSide !== undefined && indexSide !== undefined
520
- ? carry(passed.generic, { object: objectSide, index: indexSide })
521
- : false;
522
- }
523
- const objectAt = concrete(object);
524
- const indexAt = concrete(index);
525
- if (objectAt === undefined || indexAt === undefined) {
526
- return false;
527
- }
528
- accesses.push({
529
- file: site.file,
530
- from: site.from,
531
- at: site.node,
532
- object: objectAt,
533
- index: "kind" in indexAt ? (literalNames(indexAt) ?? indexAt) : indexAt,
534
- });
535
- return false;
536
- };
537
- // A site passing a type parameter on carries the access to its own generic, so the
538
- // sites are read again until no generic gains an access.
539
- const resolvedGenerics = new Map();
540
- const read = new Set();
541
- for (let changed = true; changed;) {
542
- changed = false;
543
- const pending = sites.filter((site) => names.has(site.name) && !resolvedGenerics.has(site));
544
- const typeSites = pending.filter((site) => isTypeReferenceNode(site.node));
545
- const symbols = typeSites.length === 0
546
- ? []
547
- : queries.symbolsAt(typeSites.map((site) => site.node.typeName));
548
- typeSites.forEach((site, at) => {
549
- const symbol = symbols[at];
550
- resolvedGenerics.set(site, symbol === UNANSWERED || symbol === undefined ? [] : genericsOf(symbol));
551
- });
552
- for (const site of pending.filter((one) => !isTypeReferenceNode(one.node))) {
553
- const resolved = queries.resolvedSignature(site.node);
554
- const declaration = resolved === UNANSWERED || resolved?.declaration === undefined
555
- ? undefined
556
- : project.declarationAt(resolved.declaration)?.node;
557
- const generic = declaration === undefined ? undefined : genericOf(declaration);
558
- resolvedGenerics.set(site, generic === undefined ? [] : [generic]);
559
- }
560
- sites.forEach((site, siteAt) => {
561
- for (const generic of resolvedGenerics.get(site) ?? []) {
562
- (carried.get(generic) ?? []).forEach((one, at) => {
563
- const key = `${String(siteAt)}:${String(at)}:${nodeKey(generic.getSourceFile(), generic)}`;
564
- if (read.has(key)) {
565
- return;
566
- }
567
- read.add(key);
568
- changed = readAt(site, generic, one) || changed;
569
- });
570
- }
571
- });
572
- }
573
- // A generic declared outside the project's own files carries what its own text indexes
574
- // by its type parameters and its receiver's. Only a call passing an argument the compiler
575
- // types as a literal can fix an index, so only such a call's signature is resolved.
576
- const outside = argumentCalls.filter((site) => !resolvedGenerics.has(site));
577
- const argumentNodes = argumentCalls.flatMap((site) => argumentsOf(site.node));
578
- const argumentTypes = queries.typesAt(argumentNodes);
579
- const literalArgument = new Set();
580
- argumentTypes.forEach((type, at) => {
581
- const node = argumentNodes[at];
582
- if (node !== undefined &&
583
- type !== UNANSWERED &&
584
- type !== undefined &&
585
- literalTypeNames(type, partsOf).length > 0) {
586
- literalArgument.add(node);
587
- }
588
- });
589
- const own = project.ownPaths();
590
- for (const site of outside) {
591
- if (!argumentsOf(site.node).some((one) => literalArgument.has(one))) {
592
- continue;
593
- }
594
- const resolved = queries.resolvedSignature(site.node);
595
- const handle = resolved === UNANSWERED || resolved === undefined ? undefined : resolved.declaration;
596
- if (handle === undefined || own.has(handle.path)) {
597
- continue;
598
- }
599
- const node = project.declarationAt(handle)?.node;
600
- const generic = node === undefined ? undefined : genericOf(node);
601
- if (generic === undefined) {
602
- continue;
603
- }
604
- for (const one of carriedIn(generic)) {
605
- readAt(site, generic, one);
606
- }
607
- }
608
- for (const site of argumentCalls) {
609
- if (argumentsOf(site.node).some((one) => literalArgument.has(one))) {
610
- accesses.push(...instantiatedAccesses(site));
611
- }
612
- }
613
- /**
614
- * The indexed accesses the generic signature a call instantiates holds, read through the
615
- * checker: the signature its receiver's instantiation gives, so an object type its
616
- * receiver fixes is concrete whatever declaration spells the receiver's type, a type
617
- * literal a generic function returns among them. An index naming a type parameter is the
618
- * literal type the call passes at each parameter of that type.
619
- */
620
- function instantiatedAccesses(site) {
621
- const resolved = queries.resolvedSignature(site.node);
622
- const generic = resolved === UNANSWERED || resolved === undefined ? undefined : queries.genericOf(resolved);
623
- if (resolved === UNANSWERED ||
624
- resolved === undefined ||
625
- generic === UNANSWERED ||
626
- generic === undefined) {
627
- return [];
628
- }
629
- const count = argumentsOf(site.node).length;
630
- const parameters = [];
631
- for (let at = 0; at < count; at += 1) {
632
- const type = queries.parameterType(generic, at);
633
- if (type !== UNANSWERED && type !== undefined) {
634
- parameters[at] = type;
635
- }
636
- }
637
- const result = queries.returnTypeOf(generic);
638
- const held = [
639
- ...parameters,
640
- ...(result === UNANSWERED || result === undefined ? [] : [result]),
641
- ];
642
- // A parameter of a callback and a type argument, a rest tuple's among them, hold the
643
- // accesses one level down: `fn: (payload: M[K]) => void` and `...[M[K]]`.
644
- const nested = held.flatMap((type) => [
645
- ...partsOf(type),
646
- ...partsOf(type).flatMap((part) => {
647
- const args = queries.typeArguments(part);
648
- const calls = queries.signaturesOf(part, SignatureKind.Call);
649
- return [
650
- ...(args === UNANSWERED ? [] : args),
651
- ...(calls === UNANSWERED ? [] : calls).flatMap((signature) => signature.parameters.flatMap((_parameter, index) => {
652
- const one = queries.parameterType(signature, index);
653
- return one === UNANSWERED || one === undefined ? [] : [one];
654
- })),
655
- ];
656
- }),
657
- ]);
658
- const found = [];
659
- for (const type of nested) {
660
- const access = queries.indexedAccessOf(type);
661
- if (access === UNANSWERED || access === undefined || access.object.isTypeParameter()) {
662
- continue;
663
- }
664
- const names = access.index.isTypeParameter()
665
- ? parameters.flatMap((parameter, at) => {
666
- if (!partsOf(parameter).some((part) => part.id === access.index.id)) {
379
+ function partsOf(type) {
380
+ const parts = queries.constituents(type);
381
+ return parts === UNANSWERED ? [type] : parts;
382
+ }
383
+ /** The generics one symbol declares, through the alias it may be. */
384
+ const genericsOf = (symbol) => {
385
+ const target = (symbol.flags & SymbolFlags.Alias) === 0 ? symbol : queries.aliased(symbol);
386
+ if (target === UNANSWERED) {
667
387
  return [];
668
388
  }
669
- const passed = queries.typeAtPosition(resolved, at);
670
- return passed === UNANSWERED ? [] : literalTypeNames(passed, partsOf);
671
- })
672
- : literalTypeNames(access.index, partsOf);
673
- if (names.length > 0) {
674
- found.push({
675
- file: site.file,
676
- from: site.from,
677
- at: site.node,
678
- object: access.object,
679
- index: names,
389
+ return target.declarations.flatMap((handle) => {
390
+ const node = project.declarationAt(handle)?.node;
391
+ const generic = node === undefined ? undefined : genericOf(node);
392
+ return generic === undefined ? [] : [generic];
393
+ });
394
+ };
395
+ /**
396
+ * The type a call's callee is read off: the receiver of a property access, the value an
397
+ * object binding pattern destructures the callee from, or the value whose member a
398
+ * variable holding the callee is initialized with.
399
+ */
400
+ const receiverTypeOf = (callee) => {
401
+ let operand;
402
+ if (isPropertyAccessExpression(callee)) {
403
+ const type = queries.typeAt(callee.expression);
404
+ operand = type === UNANSWERED ? undefined : type;
405
+ const args = operand === undefined ? [] : queries.typeArguments(operand);
406
+ if (operand !== undefined && args !== UNANSWERED && args.length > 0) {
407
+ return operand;
408
+ }
409
+ }
410
+ const name = isPropertyAccessExpression(callee) ? callee.name : callee;
411
+ const [named] = queries.symbolsAt([name]);
412
+ const symbol = named === UNANSWERED || named === undefined || (named.flags & SymbolFlags.Alias) === 0
413
+ ? named
414
+ : queries.aliased(named);
415
+ if (symbol === UNANSWERED || symbol === undefined) {
416
+ return operand;
417
+ }
418
+ for (const handle of symbol.declarations) {
419
+ const node = project.declarationAt(handle)?.node;
420
+ const holder = node !== undefined &&
421
+ isBindingElement(node) &&
422
+ isObjectBindingPattern(node.parent) &&
423
+ isVariableDeclaration(node.parent.parent)
424
+ ? node.parent.parent.initializer
425
+ : node !== undefined &&
426
+ isVariableDeclaration(node) &&
427
+ node.initializer !== undefined &&
428
+ isPropertyAccessExpression(node.initializer)
429
+ ? node.initializer.expression
430
+ : undefined;
431
+ const type = holder === undefined ? undefined : queries.typeAt(holder);
432
+ if (type !== UNANSWERED && type !== undefined) {
433
+ return type;
434
+ }
435
+ }
436
+ return operand;
437
+ };
438
+ /**
439
+ * The instantiation of `owner` a receiver's type is, or the first one among the base
440
+ * types it extends, breadth first: a subclass fixes its base's type parameters, and
441
+ * `this` stands for its class.
442
+ */
443
+ const instantiationOf = (type, owner) => {
444
+ const seen = new Set();
445
+ for (let queue = [type]; queue.length > 0;) {
446
+ const next = [];
447
+ for (const at of queue) {
448
+ if (seen.has(at.id)) {
449
+ continue;
450
+ }
451
+ seen.add(at.id);
452
+ const target = at.isTypeReference() ? queries.targetOf(at) : at;
453
+ const symbol = target === UNANSWERED ? undefined : queries.symbolOfType(target);
454
+ const declares = symbol !== undefined &&
455
+ symbol !== UNANSWERED &&
456
+ symbol.declarations.some((handle) => project.declarationAt(handle)?.node === owner);
457
+ if (declares) {
458
+ return at;
459
+ }
460
+ const constraint = at.isTypeParameter() ? queries.constraintOf(at) : undefined;
461
+ const bases = at.isTypeParameter() ? [] : queries.baseTypes(at);
462
+ next.push(...(bases === UNANSWERED ? [] : bases));
463
+ if (constraint !== undefined && constraint !== UNANSWERED) {
464
+ next.push(constraint);
465
+ }
466
+ }
467
+ queue = next;
468
+ }
469
+ return type;
470
+ };
471
+ /** What one site fixes for one side of a carried access. */
472
+ const fixedAt = (site, side, generic) => {
473
+ if (side.kind === "written") {
474
+ return { kind: "node", node: side.node };
475
+ }
476
+ const { node } = site;
477
+ if (side.kind === "receiver") {
478
+ const callee = isCallExpression(node) ? node.expression : undefined;
479
+ const owner = receiverOf(generic);
480
+ const typed = callee === undefined ? undefined : receiverTypeOf(callee);
481
+ const receiver = typed === undefined || owner === undefined ? typed : instantiationOf(typed, owner);
482
+ if (receiver === undefined) {
483
+ return undefined;
484
+ }
485
+ const args = queries.typeArguments(receiver);
486
+ const type = args === UNANSWERED ? undefined : args[side.index];
487
+ return type === undefined ? undefined : { kind: "type", type };
488
+ }
489
+ if (side.kind === "argument") {
490
+ const argument = isTypeReferenceNode(node) ? undefined : node.arguments?.[side.index];
491
+ const type = argument === undefined ? undefined : queries.typeAt(argument);
492
+ return type === UNANSWERED || type === undefined ? undefined : { kind: "type", type };
493
+ }
494
+ const written = node.typeArguments?.[side.index];
495
+ if (written !== undefined) {
496
+ const passed = namedParameter(written, site.enclosing);
497
+ const mapped = passed === undefined ? mappedConstraint(written) : undefined;
498
+ return passed !== undefined
499
+ ? { kind: "passed", generic: passed.generic, index: passed.index }
500
+ : { kind: "node", node: mapped ?? written };
501
+ }
502
+ if (isTypeReferenceNode(node)) {
503
+ return undefined;
504
+ }
505
+ const at = parametersOf(generic).findIndex((parameter) => {
506
+ const type = parameter.type === undefined ? undefined : unwrappedType(parameter.type);
507
+ return (type !== undefined &&
508
+ isTypeReferenceNode(type) &&
509
+ isIdentifier(type.typeName) &&
510
+ parameterAt(generic, type.typeName.text) === side.index);
511
+ });
512
+ if (at < 0) {
513
+ return undefined;
514
+ }
515
+ const resolved = queries.resolvedSignature(node);
516
+ if (resolved === UNANSWERED || resolved === undefined) {
517
+ return undefined;
518
+ }
519
+ const type = queries.typeAtPosition(resolved, at);
520
+ return type === UNANSWERED ? undefined : { kind: "type", type };
521
+ };
522
+ /** Reads one carried access at one site: an access where both sides are fixed, a carry where one is passed on. */
523
+ const readAt = (site, generic, one) => {
524
+ const object = fixedAt(site, one.object, generic);
525
+ const index = object === undefined ? undefined : fixedAt(site, one.index, generic);
526
+ if (object === undefined || index === undefined) {
527
+ return false;
528
+ }
529
+ const passed = [object, index].find((fixed) => fixed.kind === "passed");
530
+ if (passed !== undefined) {
531
+ const side = (fixed) => fixed.kind === "passed"
532
+ ? fixed.generic === passed.generic
533
+ ? { kind: "parameter", index: fixed.index }
534
+ : undefined
535
+ : fixed.kind === "node"
536
+ ? { kind: "written", node: fixed.node }
537
+ : undefined;
538
+ const objectSide = side(object);
539
+ const indexSide = side(index);
540
+ return objectSide !== undefined && indexSide !== undefined
541
+ ? carry(passed.generic, { object: objectSide, index: indexSide })
542
+ : false;
543
+ }
544
+ const objectAt = concrete(object);
545
+ const indexAt = concrete(index);
546
+ if (objectAt === undefined || indexAt === undefined) {
547
+ return false;
548
+ }
549
+ accesses.push({
550
+ file: site.file,
551
+ from: site.from,
552
+ at: site.node,
553
+ object: objectAt,
554
+ index: "kind" in indexAt ? (literalNames(indexAt) ?? indexAt) : indexAt,
555
+ });
556
+ return false;
557
+ };
558
+ // A site passing a type parameter on carries the access to its own generic, so the
559
+ // sites are read again until no generic gains an access.
560
+ const resolvedGenerics = new Map();
561
+ const read = new Set();
562
+ for (let changed = true; changed;) {
563
+ changed = false;
564
+ const pending = sites.filter((site) => names.has(site.name) && !resolvedGenerics.has(site));
565
+ const typeSites = pending.filter((site) => isTypeReferenceNode(site.node));
566
+ const symbols = typeSites.length === 0
567
+ ? []
568
+ : queries.symbolsAt(typeSites.map((site) => site.node.typeName));
569
+ typeSites.forEach((site, at) => {
570
+ const symbol = symbols[at];
571
+ if (symbol === UNANSWERED) {
572
+ holdSite(site);
573
+ }
574
+ resolvedGenerics.set(site, symbol === UNANSWERED || symbol === undefined ? [] : genericsOf(symbol));
575
+ });
576
+ for (const site of pending.filter((one) => !isTypeReferenceNode(one.node))) {
577
+ const resolved = queries.resolvedSignature(site.node);
578
+ if (resolved === UNANSWERED) {
579
+ holdSite(site);
580
+ }
581
+ const declaration = resolved === UNANSWERED || resolved?.declaration === undefined
582
+ ? undefined
583
+ : project.declarationAt(resolved.declaration)?.node;
584
+ const generic = declaration === undefined ? undefined : genericOf(declaration);
585
+ resolvedGenerics.set(site, generic === undefined ? [] : [generic]);
586
+ }
587
+ sites.forEach((site, siteAt) => {
588
+ for (const generic of resolvedGenerics.get(site) ?? []) {
589
+ (carried.get(generic) ?? []).forEach((one, at) => {
590
+ const key = `${String(siteAt)}:${String(at)}:${nodeKey(generic.getSourceFile(), generic)}`;
591
+ if (read.has(key)) {
592
+ return;
593
+ }
594
+ read.add(key);
595
+ changed = readAt(site, generic, one) || changed;
596
+ });
597
+ }
598
+ });
599
+ }
600
+ // A generic declared outside the project's own files carries what its own text indexes
601
+ // by its type parameters and its receiver's. Only a call passing an argument the compiler
602
+ // types as a literal can fix an index, so only such a call's signature is resolved.
603
+ const outside = argumentCalls.filter((site) => !resolvedGenerics.has(site));
604
+ const argumentNodes = argumentCalls.flatMap((site) => argumentsOf(site.node));
605
+ const argumentTypes = queries.typesAt(argumentNodes);
606
+ const literalArgument = new Set();
607
+ argumentTypes.forEach((type, at) => {
608
+ const node = argumentNodes[at];
609
+ if (node !== undefined &&
610
+ type !== UNANSWERED &&
611
+ type !== undefined &&
612
+ literalTypeNames(type, partsOf).length > 0) {
613
+ literalArgument.add(node);
614
+ }
680
615
  });
681
- }
682
- }
683
- return found;
684
- }
685
- const typeNodes = accesses.flatMap((one) => [
686
- ...("kind" in one.object ? [one.object] : []),
687
- ...(!Array.isArray(one.index) && "kind" in one.index ? [one.index] : []),
688
- ]);
689
- const typeOf = new Map();
690
- queries.typesAt(typeNodes).forEach((answer, index) => {
691
- const node = typeNodes[index];
692
- if (answer !== UNANSWERED && answer !== undefined && node !== undefined) {
693
- typeOf.set(node, answer);
694
- }
695
- });
696
- const asType = (side) => "kind" in side ? typeOf.get(side) : side;
697
- const found = [];
698
- for (const access of accesses) {
699
- const type = asType(access.object);
700
- const indexType = Array.isArray(access.index)
701
- ? undefined
702
- : asType(access.index);
703
- const accessed = Array.isArray(access.index)
704
- ? access.index
705
- : indexType === undefined
706
- ? undefined
707
- : literalTypeNames(indexType, partsOf);
708
- if (type === undefined || accessed === undefined) {
709
- continue;
710
- }
711
- const position = renderPosition(access.file, root, access.at.getStart());
712
- for (const part of partsOf(type)) {
713
- const properties = queries.propertiesOf(part);
714
- if (properties === UNANSWERED) {
715
- continue;
716
- }
717
- for (const property of properties) {
718
- if (!accessed.includes(property.escapedName)) {
719
- continue;
616
+ const own = project.ownPaths();
617
+ for (const site of outside) {
618
+ if (!argumentsOf(site.node).some((one) => literalArgument.has(one))) {
619
+ continue;
620
+ }
621
+ const resolved = queries.resolvedSignature(site.node);
622
+ const handle = resolved === UNANSWERED || resolved === undefined ? undefined : resolved.declaration;
623
+ if (handle === undefined || own.has(handle.path)) {
624
+ continue;
625
+ }
626
+ const node = project.declarationAt(handle)?.node;
627
+ const generic = node === undefined ? undefined : genericOf(node);
628
+ if (generic === undefined) {
629
+ continue;
630
+ }
631
+ for (const one of carriedIn(generic)) {
632
+ readAt(site, generic, one);
633
+ }
720
634
  }
721
- for (const to of chains.declarationsOf(property)) {
722
- found.push({
723
- from: access.from,
724
- to,
725
- position,
726
- use: "read",
727
- resolution: "batch",
728
- test: testFiles.has(position.path),
729
- });
635
+ for (const site of argumentCalls) {
636
+ if (argumentsOf(site.node).some((one) => literalArgument.has(one))) {
637
+ accesses.push(...instantiatedAccesses(site));
638
+ }
730
639
  }
731
- }
732
- }
733
- }
734
- return found;
735
- }
640
+ /**
641
+ * The indexed accesses the generic signature a call instantiates holds, read through the
642
+ * checker: the signature its receiver's instantiation gives, so an object type its
643
+ * receiver fixes is concrete whatever declaration spells the receiver's type, a type
644
+ * literal a generic function returns among them. An index naming a type parameter is the
645
+ * literal type the call passes at each parameter of that type.
646
+ */
647
+ function instantiatedAccesses(site) {
648
+ const resolved = queries.resolvedSignature(site.node);
649
+ const generic = resolved === UNANSWERED || resolved === undefined
650
+ ? undefined
651
+ : queries.genericOf(resolved);
652
+ if (resolved === UNANSWERED ||
653
+ resolved === undefined ||
654
+ generic === UNANSWERED ||
655
+ generic === undefined) {
656
+ return [];
657
+ }
658
+ const count = argumentsOf(site.node).length;
659
+ const parameters = [];
660
+ for (let at = 0; at < count; at += 1) {
661
+ const type = queries.parameterType(generic, at);
662
+ if (type !== UNANSWERED && type !== undefined) {
663
+ parameters[at] = type;
664
+ }
665
+ }
666
+ const result = queries.returnTypeOf(generic);
667
+ const held = [
668
+ ...parameters,
669
+ ...(result === UNANSWERED || result === undefined ? [] : [result]),
670
+ ];
671
+ // A parameter of a callback and a type argument, a rest tuple's among them, hold the
672
+ // accesses one level down: `fn: (payload: M[K]) => void` and `...[M[K]]`.
673
+ const nested = held.flatMap((type) => [
674
+ ...partsOf(type),
675
+ ...partsOf(type).flatMap((part) => {
676
+ const args = queries.typeArguments(part);
677
+ const calls = queries.signaturesOf(part, SignatureKind.Call);
678
+ return [
679
+ ...(args === UNANSWERED ? [] : args),
680
+ ...(calls === UNANSWERED ? [] : calls).flatMap((signature) => signature.parameters.flatMap((_parameter, index) => {
681
+ const one = queries.parameterType(signature, index);
682
+ return one === UNANSWERED || one === undefined ? [] : [one];
683
+ })),
684
+ ];
685
+ }),
686
+ ]);
687
+ const found = [];
688
+ for (const type of nested) {
689
+ const access = queries.indexedAccessOf(type);
690
+ if (access === UNANSWERED || access === undefined || access.object.isTypeParameter()) {
691
+ continue;
692
+ }
693
+ const names = access.index.isTypeParameter()
694
+ ? parameters.flatMap((parameter, at) => {
695
+ if (!partsOf(parameter).some((part) => part.id === access.index.id)) {
696
+ return [];
697
+ }
698
+ const passed = queries.typeAtPosition(resolved, at);
699
+ return passed === UNANSWERED ? [] : literalTypeNames(passed, partsOf);
700
+ })
701
+ : literalTypeNames(access.index, partsOf);
702
+ if (names.length > 0) {
703
+ found.push({
704
+ file: site.file,
705
+ from: site.from,
706
+ at: site.node,
707
+ object: access.object,
708
+ index: names,
709
+ });
710
+ }
711
+ }
712
+ return found;
713
+ }
714
+ const typeNodes = accesses.flatMap((one) => [
715
+ ...("kind" in one.object ? [one.object] : []),
716
+ ...(!Array.isArray(one.index) && "kind" in one.index ? [one.index] : []),
717
+ ]);
718
+ const typeOf = new Map();
719
+ queries.typesAt(typeNodes).forEach((answer, index) => {
720
+ const node = typeNodes[index];
721
+ if (answer !== undefined && node !== undefined) {
722
+ typeOf.set(node, answer);
723
+ }
724
+ });
725
+ const asType = (side) => "kind" in side ? typeOf.get(side) : side;
726
+ for (const access of accesses) {
727
+ const type = asType(access.object);
728
+ const indexType = Array.isArray(access.index)
729
+ ? undefined
730
+ : asType(access.index);
731
+ const accessed = Array.isArray(access.index)
732
+ ? access.index
733
+ : indexType === undefined || indexType === UNANSWERED
734
+ ? undefined
735
+ : literalTypeNames(indexType, partsOf);
736
+ if (type === UNANSWERED || indexType === UNANSWERED) {
737
+ found.push({
738
+ kind: "held",
739
+ from: access.from,
740
+ ...(accessed === undefined ? {} : { names: accessed }),
741
+ ...(type === UNANSWERED || type === undefined
742
+ ? accessed === undefined
743
+ ? { members: true }
744
+ : {}
745
+ : { types: partsOf(type) }),
746
+ });
747
+ continue;
748
+ }
749
+ if (type === undefined || accessed === undefined) {
750
+ continue;
751
+ }
752
+ for (const part of partsOf(type)) {
753
+ const properties = queries.propertiesOf(part);
754
+ if (properties === UNANSWERED) {
755
+ found.push({ kind: "held", from: access.from, names: accessed });
756
+ continue;
757
+ }
758
+ for (const property of properties) {
759
+ if (!accessed.includes(property.escapedName)) {
760
+ continue;
761
+ }
762
+ for (const to of chains.declarationsOf(property)) {
763
+ found.push({
764
+ kind: "named",
765
+ from: access.from,
766
+ to,
767
+ file: access.file,
768
+ at: access.at,
769
+ use: "read",
770
+ via: "batch",
771
+ });
772
+ }
773
+ }
774
+ }
775
+ }
776
+ return found;
777
+ },
778
+ };
779
+ },
780
+ };
736
781
  /** The arguments a call or a `new` expression passes, none for a type reference. */
737
782
  function argumentsOf(node) {
738
783
  return isTypeReferenceNode(node) ? [] : (node.arguments ?? []);