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

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 (402) 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 +2 -7
  6. package/dist/src/amd.js +81 -0
  7. package/dist/src/analysis.js +269 -432
  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/calls.js +279 -43
  12. package/dist/src/commands/held.js +499 -0
  13. package/dist/src/commands/read.js +161 -0
  14. package/dist/src/commands/shell.js +169 -0
  15. package/dist/src/commands/tools.js +1847 -0
  16. package/dist/src/component-files.js +3 -2
  17. package/dist/src/component-layer.js +4 -2
  18. package/dist/src/config.js +6 -82
  19. package/dist/src/conformance-record.js +1 -1
  20. package/dist/src/consumers.js +10 -38
  21. package/dist/src/contextual-uses.js +57 -26
  22. package/dist/src/contract/config.generated.js +561 -0
  23. package/dist/src/contract/contract.generated.js +1369 -0
  24. package/dist/src/contract/report.generated.js +866 -0
  25. package/dist/src/dependencies.js +164 -121
  26. package/dist/src/destructuring.js +1 -19
  27. package/dist/src/edges.js +38 -122
  28. package/dist/src/element-access.js +181 -168
  29. package/dist/src/entries/build-scripts.js +222 -0
  30. package/dist/src/{configuration-files.js → entries/configuration-files.js} +52 -256
  31. package/dist/src/{convention-rows.js → entries/convention-rows.js} +170 -30
  32. package/dist/src/entries/conventions.js +740 -0
  33. package/dist/src/{html-entries.js → entries/html-entries.js} +12 -42
  34. package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +5 -28
  35. package/dist/src/entries/run-directories.js +77 -0
  36. package/dist/src/entries/sources.js +144 -0
  37. package/dist/src/entries/static-module.js +670 -0
  38. package/dist/src/entries/test-runners.js +650 -0
  39. package/dist/src/entries/workflow-steps.js +345 -0
  40. package/dist/src/enum-group.js +3 -10
  41. package/dist/src/erased-stores.js +4 -6
  42. package/dist/src/exempt-classes.js +1 -63
  43. package/dist/src/exempt.js +21 -66
  44. package/dist/src/exposure.js +400 -0
  45. package/dist/src/extensions.js +37 -0
  46. package/dist/src/facts.js +38 -0
  47. package/dist/src/failure.js +36 -0
  48. package/dist/src/file-facts.js +3 -26
  49. package/dist/src/findings/completion.js +109 -56
  50. package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
  51. package/dist/src/findings/emitters.js +27 -41
  52. package/dist/src/{implementations.js → findings/implementations.js} +3 -3
  53. package/dist/src/{in-operands.js → findings/in-operands.js} +3 -2
  54. package/dist/src/findings/interfaces.js +4 -5
  55. package/dist/src/findings/intra-function.js +16 -13
  56. package/dist/src/findings/non-code-artifacts.js +17 -12
  57. package/dist/src/findings/reads-and-writes.js +86 -27
  58. package/dist/src/findings/self-check.js +44 -30
  59. package/dist/src/findings/unused-declarations.js +29 -45
  60. package/dist/src/findings/visibility-narrowing.js +23 -31
  61. package/dist/src/findings-pass.js +13 -21
  62. package/dist/src/framework-lifecycle.js +46 -19
  63. package/dist/src/fs/document.js +52 -0
  64. package/dist/src/fs/manifest.js +67 -0
  65. package/dist/src/fs/tree.js +88 -0
  66. package/dist/src/generated-file.js +174 -28
  67. package/dist/src/git-ignore.js +39 -26
  68. package/dist/src/import-bindings.js +73 -28
  69. package/dist/src/index/sites.js +557 -0
  70. package/dist/src/index.js +2 -2
  71. package/dist/src/indexed-access.js +523 -478
  72. package/dist/src/injection-container.js +2 -2
  73. package/dist/src/interface-satisfaction.js +1 -1
  74. package/dist/src/intra-function-parts.js +63 -43
  75. package/dist/src/inventory/commonjs.js +507 -0
  76. package/dist/src/inventory/enumerate.js +167 -0
  77. package/dist/src/inventory/syntax.js +236 -0
  78. package/dist/src/inventory.js +323 -724
  79. package/dist/src/javascript-file.js +48 -0
  80. package/dist/src/json-document.js +198 -67
  81. package/dist/src/keyof-comparisons.js +126 -107
  82. package/dist/src/kinds.js +3 -366
  83. package/dist/src/{components.js → liveness/components.js} +2 -3
  84. package/dist/src/{graph.js → liveness/graph.js} +52 -28
  85. package/dist/src/liveness/matrix.js +99 -0
  86. package/dist/src/liveness/sweep.js +558 -0
  87. package/dist/src/load/classify.js +289 -0
  88. package/dist/src/load/diagnostics.js +87 -0
  89. package/dist/src/load/discover.js +285 -0
  90. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  91. package/dist/src/load/expected-module.js +136 -0
  92. package/dist/src/load/load.js +27 -0
  93. package/dist/src/load/module-lookup.js +37 -0
  94. package/dist/src/load/package-scope.js +56 -0
  95. package/dist/src/load/plan.js +313 -0
  96. package/dist/src/load/specifiers.js +113 -0
  97. package/dist/src/load/synthesize.js +152 -0
  98. package/dist/src/load/test-globals.js +207 -0
  99. package/dist/src/load/test-joins.js +82 -0
  100. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
  101. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
  102. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +24 -66
  103. package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
  104. package/dist/src/{workspace.js → load/workspace.js} +62 -124
  105. package/dist/src/module-declarations.js +70 -85
  106. package/dist/src/overrides.js +134 -112
  107. package/dist/src/partial.js +2 -1
  108. package/dist/src/paths.js +82 -16
  109. package/dist/src/platform-calls.js +78 -0
  110. package/dist/src/platform-symbols.js +134 -0
  111. package/dist/src/position.js +43 -1
  112. package/dist/src/print.js +11 -79
  113. package/dist/src/product.js +13 -0
  114. package/dist/src/query.js +47 -0
  115. package/dist/src/ref.js +12 -20
  116. package/dist/src/references/read-rule.js +1 -0
  117. package/dist/src/references/read-rules.js +48 -0
  118. package/dist/src/references/sink.js +237 -0
  119. package/dist/src/references/sources.js +450 -0
  120. package/dist/src/references.js +117 -1074
  121. package/dist/src/report-schema.js +51 -0
  122. package/dist/src/report.js +57 -41
  123. package/dist/src/reporters/annotations.js +15 -8
  124. package/dist/src/reporters/sarif.js +16 -10
  125. package/dist/src/reporters/template.js +4 -19
  126. package/dist/src/resolve.js +246 -730
  127. package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +22 -24
  128. package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +6 -15
  129. package/dist/src/roots/manifest.js +216 -0
  130. package/dist/src/roots/published-reach.js +412 -0
  131. package/dist/src/roots/root-set.js +487 -0
  132. package/dist/src/roots/unseen-loads.js +236 -0
  133. package/dist/src/run.js +66 -77
  134. package/dist/src/schema.js +320 -343
  135. package/dist/src/scope.js +38 -115
  136. package/dist/src/serialization-contract.js +601 -22
  137. package/dist/src/session.js +37 -29
  138. package/dist/src/source-files.js +6 -10
  139. package/dist/src/stores.js +4 -2
  140. package/dist/src/suppress-file.js +25 -28
  141. package/dist/src/suppress-inline.js +36 -83
  142. package/dist/src/suppress.js +50 -71
  143. package/dist/src/symbol-keys.js +92 -88
  144. package/dist/src/template-field.js +9 -19
  145. package/dist/src/tests/file-class.js +76 -0
  146. package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
  147. package/dist/src/{test-support.js → tests/support.js} +5 -12
  148. package/dist/src/text/compare.js +26 -0
  149. package/dist/src/text/glob.js +194 -0
  150. package/dist/src/text/named-files.js +298 -0
  151. package/dist/src/text/yaml.js +684 -0
  152. package/dist/src/type-errors.js +11 -232
  153. package/dist/src/type-parameter-reads.js +178 -139
  154. package/dist/src/unimplemented-callees.js +262 -242
  155. package/dist/src/unwrap.js +23 -0
  156. package/dist/src/usage.js +10 -0
  157. package/dist/src/vendor/unbash/ansi-c.js +132 -0
  158. package/dist/src/vendor/unbash/arithmetic-parts.js +37 -0
  159. package/dist/src/vendor/unbash/arithmetic.js +591 -0
  160. package/dist/src/vendor/unbash/assignment.js +131 -0
  161. package/dist/src/vendor/unbash/chars.js +48 -0
  162. package/dist/src/vendor/unbash/command.js +41 -0
  163. package/dist/src/vendor/unbash/expansion.js +80 -0
  164. package/dist/src/vendor/unbash/glob.js +268 -0
  165. package/dist/src/vendor/unbash/heredoc.js +27 -0
  166. package/dist/src/vendor/unbash/internal-types.js +1 -0
  167. package/dist/src/vendor/unbash/lexer.js +4274 -0
  168. package/dist/src/vendor/unbash/limits.js +3 -0
  169. package/dist/src/vendor/unbash/parser.js +1366 -0
  170. package/dist/src/vendor/unbash/parts.js +57 -0
  171. package/dist/src/vendor/unbash/substitution-context.js +8 -0
  172. package/dist/src/vendor/unbash/traversal.js +212 -0
  173. package/dist/src/vendor/unbash/types.js +1 -0
  174. package/dist/src/vendor/unbash/word-value.js +61 -0
  175. package/dist/src/vendor/unbash/word.js +40 -0
  176. package/dist/src/verbs/analyze.js +194 -127
  177. package/dist/src/verbs/describe.js +13 -18
  178. package/dist/src/verbs/explain.js +85 -139
  179. package/dist/src/verbs/print-config.js +2 -1
  180. package/dist/src/verbs/print-projects.js +6 -4
  181. package/dist/src/verbs/print-retained.js +7 -5
  182. package/dist/src/verbs/print-roots.js +4 -2
  183. package/dist/src/verbs/verb.js +1 -5
  184. package/dist/src/verbs/version.js +14 -3
  185. package/jsr.json +2 -1
  186. package/package.json +14 -8
  187. package/src/alias-chain.ts +2 -9
  188. package/src/amd.ts +130 -0
  189. package/src/analysis.ts +424 -650
  190. package/src/augmentations.ts +93 -4
  191. package/src/automatic-types.ts +12 -30
  192. package/src/bindings.ts +460 -0
  193. package/src/calls.ts +338 -46
  194. package/src/commands/held.ts +632 -0
  195. package/src/commands/read.ts +242 -0
  196. package/src/commands/shell.ts +228 -0
  197. package/src/commands/tools.ts +2382 -0
  198. package/src/component-files.ts +4 -2
  199. package/src/component-layer.ts +4 -2
  200. package/src/config.ts +31 -302
  201. package/src/conformance-record.ts +1 -1
  202. package/src/consumers.ts +16 -66
  203. package/src/contextual-uses.ts +66 -34
  204. package/src/contract/config.generated.ts +821 -0
  205. package/src/contract/contract.generated.ts +1452 -0
  206. package/src/contract/report.generated.ts +1241 -0
  207. package/src/dependencies.ts +222 -127
  208. package/src/destructuring.ts +1 -31
  209. package/src/edges.ts +41 -140
  210. package/src/element-access.ts +190 -187
  211. package/src/entries/build-scripts.ts +292 -0
  212. package/src/{configuration-files.ts → entries/configuration-files.ts} +68 -278
  213. package/src/{convention-rows.ts → entries/convention-rows.ts} +227 -31
  214. package/src/{conventions.ts → entries/conventions.ts} +367 -583
  215. package/src/{html-entries.ts → entries/html-entries.ts} +22 -48
  216. package/src/{mdx-entries.ts → entries/mdx-entries.ts} +7 -30
  217. package/src/entries/run-directories.ts +108 -0
  218. package/src/entries/sources.ts +266 -0
  219. package/src/entries/static-module.ts +858 -0
  220. package/src/entries/test-runners.ts +835 -0
  221. package/src/entries/workflow-steps.ts +432 -0
  222. package/src/enum-group.ts +2 -11
  223. package/src/erased-stores.ts +3 -7
  224. package/src/exempt-classes.ts +1 -75
  225. package/src/exempt.ts +70 -98
  226. package/src/exposure.ts +492 -0
  227. package/src/extensions.ts +45 -0
  228. package/src/facts.ts +46 -0
  229. package/src/failure.ts +63 -0
  230. package/src/file-facts.ts +15 -25
  231. package/src/finding.ts +10 -10
  232. package/src/findings/boundary.ts +11 -0
  233. package/src/findings/completion.ts +133 -64
  234. package/src/findings/dependencies-and-module-machinery.ts +4 -7
  235. package/src/findings/emitter.ts +9 -10
  236. package/src/findings/emitters.ts +38 -52
  237. package/src/{implementations.ts → findings/implementations.ts} +4 -4
  238. package/src/{in-operands.ts → findings/in-operands.ts} +4 -3
  239. package/src/findings/interfaces.ts +7 -9
  240. package/src/findings/intra-function.ts +16 -14
  241. package/src/findings/non-code-artifacts.ts +24 -15
  242. package/src/findings/reads-and-writes.ts +118 -41
  243. package/src/findings/self-check.ts +51 -38
  244. package/src/findings/unused-declarations.ts +31 -49
  245. package/src/findings/visibility-narrowing.ts +36 -40
  246. package/src/findings-pass.ts +15 -31
  247. package/src/framework-lifecycle.ts +47 -19
  248. package/src/fs/document.ts +70 -0
  249. package/src/fs/manifest.ts +96 -0
  250. package/src/fs/tree.ts +110 -0
  251. package/src/generated-file.ts +242 -35
  252. package/src/git-ignore.ts +50 -26
  253. package/src/host.ts +12 -5
  254. package/src/import-bindings.ts +98 -29
  255. package/src/index/sites.ts +781 -0
  256. package/src/index.ts +2 -2
  257. package/src/indexed-access.ts +570 -527
  258. package/src/injection-container.ts +2 -2
  259. package/src/interface-satisfaction.ts +2 -2
  260. package/src/intra-function-parts.ts +73 -44
  261. package/src/inventory/commonjs.ts +696 -0
  262. package/src/inventory/enumerate.ts +203 -0
  263. package/src/inventory/syntax.ts +311 -0
  264. package/src/inventory.ts +442 -895
  265. package/src/javascript-file.ts +54 -0
  266. package/src/json-document.ts +241 -76
  267. package/src/keyof-comparisons.ts +133 -122
  268. package/src/kinds.ts +5 -413
  269. package/src/{components.ts → liveness/components.ts} +4 -6
  270. package/src/{graph.ts → liveness/graph.ts} +100 -35
  271. package/src/liveness/matrix.ts +162 -0
  272. package/src/liveness/sweep.ts +855 -0
  273. package/src/load/classify.ts +433 -0
  274. package/src/load/diagnostics.ts +154 -0
  275. package/src/load/discover.ts +471 -0
  276. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  277. package/src/load/expected-module.ts +194 -0
  278. package/src/load/load.ts +73 -0
  279. package/src/load/module-lookup.ts +50 -0
  280. package/src/load/package-scope.ts +74 -0
  281. package/src/load/plan.ts +513 -0
  282. package/src/load/specifiers.ts +171 -0
  283. package/src/load/synthesize.ts +230 -0
  284. package/src/load/test-globals.ts +251 -0
  285. package/src/load/test-joins.ts +98 -0
  286. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
  287. package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
  288. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +41 -77
  289. package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
  290. package/src/{workspace.ts → load/workspace.ts} +90 -134
  291. package/src/module-declarations.ts +74 -98
  292. package/src/overrides.ts +162 -134
  293. package/src/partial.ts +3 -2
  294. package/src/paths.ts +92 -16
  295. package/src/platform-calls.ts +119 -0
  296. package/src/platform-symbols.ts +189 -0
  297. package/src/position.ts +44 -1
  298. package/src/print.ts +12 -92
  299. package/src/product.ts +18 -0
  300. package/src/query.ts +92 -0
  301. package/src/ref.ts +12 -20
  302. package/src/references/read-rule.ts +60 -0
  303. package/src/references/read-rules.ts +55 -0
  304. package/src/references/sink.ts +314 -0
  305. package/src/references/sources.ts +632 -0
  306. package/src/references.ts +187 -1450
  307. package/src/report-schema.ts +68 -0
  308. package/src/report.ts +103 -226
  309. package/src/reporters/annotations.ts +22 -11
  310. package/src/reporters/json.ts +1 -1
  311. package/src/reporters/reporter.ts +2 -4
  312. package/src/reporters/reporters.ts +1 -1
  313. package/src/reporters/sarif.ts +29 -16
  314. package/src/reporters/template.ts +4 -20
  315. package/src/reporters/text.ts +3 -3
  316. package/src/resolve.ts +284 -1115
  317. package/src/{configured-declarations.ts → roots/configured-declarations.ts} +27 -29
  318. package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +7 -16
  319. package/src/roots/manifest.ts +303 -0
  320. package/src/roots/published-reach.ts +486 -0
  321. package/src/{roots.ts → roots/root-set.ts} +286 -469
  322. package/src/roots/unseen-loads.ts +345 -0
  323. package/src/run.ts +75 -91
  324. package/src/schema.ts +391 -388
  325. package/src/scope.ts +46 -138
  326. package/src/serialization-contract.ts +769 -23
  327. package/src/session.ts +87 -55
  328. package/src/source-files.ts +6 -11
  329. package/src/stores.ts +15 -3
  330. package/src/suppress-file.ts +24 -33
  331. package/src/suppress-inline.ts +55 -91
  332. package/src/suppress.ts +78 -79
  333. package/src/symbol-keys.ts +104 -107
  334. package/src/template-field.ts +15 -25
  335. package/src/tests/file-class.ts +135 -0
  336. package/src/{outside-tests.ts → tests/outside.ts} +16 -10
  337. package/src/{test-support.ts → tests/support.ts} +15 -21
  338. package/src/text/compare.ts +27 -0
  339. package/src/text/glob.ts +210 -0
  340. package/src/text/named-files.ts +388 -0
  341. package/src/text/yaml.ts +747 -0
  342. package/src/type-errors.ts +18 -288
  343. package/src/type-parameter-reads.ts +187 -158
  344. package/src/unimplemented-callees.ts +297 -280
  345. package/src/unwrap.ts +34 -0
  346. package/src/usage.ts +10 -0
  347. package/src/vendor/unbash/LICENSE +15 -0
  348. package/src/vendor/unbash/VENDORED.md +16 -0
  349. package/src/vendor/unbash/ansi-c.ts +132 -0
  350. package/src/vendor/unbash/arithmetic-parts.ts +53 -0
  351. package/src/vendor/unbash/arithmetic.ts +641 -0
  352. package/src/vendor/unbash/assignment.ts +163 -0
  353. package/src/vendor/unbash/chars.ts +48 -0
  354. package/src/vendor/unbash/command.ts +47 -0
  355. package/src/vendor/unbash/expansion.ts +144 -0
  356. package/src/vendor/unbash/glob.ts +284 -0
  357. package/src/vendor/unbash/heredoc.ts +34 -0
  358. package/src/vendor/unbash/internal-types.ts +94 -0
  359. package/src/vendor/unbash/lexer.ts +4352 -0
  360. package/src/vendor/unbash/limits.ts +3 -0
  361. package/src/vendor/unbash/parser.ts +1612 -0
  362. package/src/vendor/unbash/parts.ts +96 -0
  363. package/src/vendor/unbash/substitution-context.ts +20 -0
  364. package/src/vendor/unbash/traversal.ts +182 -0
  365. package/src/vendor/unbash/types.ts +660 -0
  366. package/src/vendor/unbash/word-value.ts +64 -0
  367. package/src/vendor/unbash/word.ts +50 -0
  368. package/src/verbs/analyze.ts +255 -164
  369. package/src/verbs/describe.ts +19 -17
  370. package/src/verbs/explain.ts +93 -169
  371. package/src/verbs/print-config.ts +2 -1
  372. package/src/verbs/print-projects.ts +6 -4
  373. package/src/verbs/print-retained.ts +7 -5
  374. package/src/verbs/print-roots.ts +4 -2
  375. package/src/verbs/verb.ts +2 -8
  376. package/src/verbs/version.ts +15 -3
  377. package/dist/src/base-url.js +0 -18
  378. package/dist/src/conventions.js +0 -937
  379. package/dist/src/discover.js +0 -468
  380. package/dist/src/entry-points.js +0 -529
  381. package/dist/src/glob.js +0 -65
  382. package/dist/src/manifest.js +0 -165
  383. package/dist/src/matrix.js +0 -246
  384. package/dist/src/pnpm-workspace.js +0 -120
  385. package/dist/src/roots.js +0 -672
  386. package/dist/src/setup-failure.js +0 -23
  387. package/dist/src/sweep.js +0 -224
  388. package/dist/src/test-joins.js +0 -101
  389. package/dist/src/version.js +0 -7
  390. package/dist/src/workflow-steps.js +0 -185
  391. package/src/base-url.ts +0 -24
  392. package/src/discover.ts +0 -653
  393. package/src/entry-points.ts +0 -687
  394. package/src/glob.ts +0 -67
  395. package/src/manifest.ts +0 -234
  396. package/src/matrix.ts +0 -423
  397. package/src/pnpm-workspace.ts +0 -135
  398. package/src/setup-failure.ts +0 -39
  399. package/src/sweep.ts +0 -347
  400. package/src/test-joins.ts +0 -120
  401. package/src/version.ts +0 -7
  402. package/src/workflow-steps.ts +0 -216
@@ -41,12 +41,9 @@ import {
41
41
  type SourceFile,
42
42
  } from "@typescript/native/ast";
43
43
  import type { Type } from "@typescript/native/sync";
44
- import type { AliasChains } from "./alias-chain.ts";
45
- import { nodeKey, type Inventory } from "./inventory.ts";
46
- import { renderPosition } from "./position.ts";
47
44
  import { UNANSWERED } from "./query.ts";
48
- import type { Reference } from "./references.ts";
49
- import type { ProjectView } from "./session.ts";
45
+ import type { Read, ReadRule } from "./references/read-rule.ts";
46
+ import { parenthesesRemoved } from "./unwrap.ts";
50
47
 
51
48
  type Use = "read" | "write" | "both";
52
49
 
@@ -93,13 +90,9 @@ function useOf(node: Node): Use {
93
90
  return "read";
94
91
  }
95
92
 
96
- function unwrapped(node: Expression): Expression {
97
- return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
98
- }
99
-
100
93
  /** Whether an index is a literal the checker resolves to a member by its own text. */
101
94
  function isLiteralIndex(node: Expression): boolean {
102
- const at = unwrapped(node);
95
+ const at = parenthesesRemoved(node);
103
96
  return isStringLiteral(at) || isNumericLiteral(at) || isNoSubstitutionTemplateLiteral(at);
104
97
  }
105
98
 
@@ -245,190 +238,200 @@ interface Candidate {
245
238
  }
246
239
 
247
240
  /**
248
- * The references the element accesses of one project's own files make to the members their
249
- * index's literal type names, each made by the declaration holding the access or the call.
241
+ * The reads the element accesses of a side's files make of the members their index's literal
242
+ * type names, each made by the declaration holding the access or the call. A type the checker
243
+ * leaves unanswered holds what its answer could have read.
250
244
  */
251
- export function elementAccessReferences<Brand>(
252
- project: ProjectView<Brand>,
253
- held: Inventory,
254
- chains: AliasChains,
255
- root: string,
256
- testFiles: ReadonlySet<string>,
257
- ): readonly Reference[] {
258
- const queries = project.queries;
259
- const candidates: Candidate[] = [];
260
- const calls = new Map<Node, { readonly file: SourceFile; readonly from: string }>();
261
- const names: Identifier[] = [];
262
-
263
- for (const file of project.ownSourceFiles()) {
264
- const fileId = held.declarations.get(nodeKey(file, file));
265
- if (fileId === undefined) {
266
- continue;
267
- }
268
- const visit = (node: Node, from: string): void => {
269
- const holder = held.declarations.get(nodeKey(file, node)) ?? from;
270
- if (isElementAccessExpression(node) && !isLiteralIndex(node.argumentExpression)) {
271
- candidates.push({ file, from: holder, access: node, use: useOf(node) });
272
- }
273
- if (isCallExpression(node)) {
274
- calls.set(node, { file, from: holder });
275
- }
276
- if (isIdentifier(node)) {
277
- names.push(node);
278
- }
279
- node.forEachChild((child) => {
280
- visit(child, holder);
281
- });
282
- };
283
- file.forEachChild((child) => {
284
- visit(child, fileId);
285
- });
286
- }
287
- if (candidates.length === 0) {
288
- return [];
289
- }
290
-
291
- // A parameter index is decided at the calls only where the function is a callable every
292
- // use of which is a call, so the symbols of the parameters and of every name are read.
293
- const parameterOf = new Map<Candidate, { callable: Callable; at: number }>();
294
- const byCallable = new Map<Identifier, Candidate[]>();
295
- for (const candidate of candidates) {
296
- const index = unwrapped(candidate.access.argumentExpression);
297
- const fn = isIdentifier(index) ? enclosingFunction(candidate.access) : undefined;
298
- const callable = fn === undefined ? undefined : callableOf(fn);
299
- if (callable === undefined || !isIdentifier(index)) {
300
- continue;
301
- }
302
- const at = callable.parameters.findIndex(
303
- (parameter) => isIdentifier(parameter.name) && parameter.name.text === index.text,
304
- );
305
- if (at < 0 || assigns(callable.body, index.text)) {
306
- continue;
307
- }
308
- parameterOf.set(candidate, { callable, at });
309
- byCallable.set(callable.name, [...(byCallable.get(callable.name) ?? []), candidate]);
310
- }
311
- const callableNames = [...byCallable.keys()];
312
- const spelled = new Set(callableNames.map((name) => name.text));
313
- const sameName = names.filter((name) => spelled.has(name.text));
314
- const symbols = queries.symbolsAt([...callableNames, ...sameName]);
315
- const symbolOf = new Map<Node, unknown>();
316
- [...callableNames, ...sameName].forEach((node, at) => {
317
- const symbol = symbols[at];
318
- if (symbol !== UNANSWERED && symbol !== undefined) {
319
- symbolOf.set(node, symbol);
320
- }
321
- });
322
- const callsOf = new Map<Node, CallExpression[] | undefined>();
323
- for (const name of callableNames) {
324
- const symbol = symbolOf.get(name);
325
- let found: CallExpression[] | undefined = symbol === undefined ? undefined : [];
326
- for (const use of sameName) {
327
- if (found === undefined) {
328
- break;
329
- }
330
- if (use === name || symbolOf.get(use) !== symbol) {
331
- continue;
332
- }
333
- const parent = use.parent;
334
- found =
335
- isCallExpression(parent) && parent.expression === use ? [...found, parent] : undefined;
336
- }
337
- callsOf.set(name, found);
338
- }
339
-
340
- const lookups: Lookup[] = [];
341
- for (const candidate of candidates) {
342
- const deferred = parameterOf.get(candidate);
343
- const sites = deferred === undefined ? undefined : callsOf.get(deferred.callable.name);
344
- if (deferred === undefined || sites === undefined) {
345
- lookups.push({
346
- file: candidate.file,
347
- from: candidate.from,
348
- at: candidate.access.argumentExpression,
349
- object: candidate.access.expression,
350
- index: candidate.access.argumentExpression,
351
- use: candidate.use,
352
- });
353
- continue;
354
- }
355
- // An object that is a parameter too is read as the argument each call passes there.
356
- const object = unwrapped(candidate.access.expression);
357
- const objectAt = isIdentifier(object)
358
- ? deferred.callable.parameters.findIndex(
359
- (parameter) => isIdentifier(parameter.name) && parameter.name.text === object.text,
360
- )
361
- : -1;
362
- for (const call of sites) {
363
- const parameter = deferred.callable.parameters[deferred.at];
364
- const index = call.arguments[deferred.at] ?? parameter?.initializer;
365
- const site = calls.get(call);
366
- if (index === undefined || site === undefined) {
367
- continue;
368
- }
369
- lookups.push({
370
- file: site.file,
371
- from: site.from,
372
- at: call,
373
- object:
374
- (objectAt < 0 ? undefined : call.arguments[objectAt]) ?? candidate.access.expression,
375
- index,
376
- use: candidate.use,
377
- });
378
- }
379
- }
380
-
381
- const nodes = lookups.flatMap((one) => [one.index, one.object]);
382
- const types = queries.typesAt(nodes);
383
- const typeOf = (node: Node, at: number): Type | undefined => {
384
- const type = types[at];
385
- return nodes[at] === node && type !== UNANSWERED ? type : undefined;
386
- };
387
- // A type parameter's body serves every instantiation, so it reads what its constraint admits.
388
- const keysOf = (type: Type): Type => {
389
- if (!type.isTypeParameter()) {
390
- return type;
391
- }
392
- const constraint = queries.constraintOf(type);
393
- return constraint === UNANSWERED || constraint === undefined ? type : constraint;
394
- };
395
- const partsOf = (type: Type): readonly Type[] => {
396
- const parts = queries.constituents(type);
397
- return parts === UNANSWERED ? [type] : parts;
398
- };
245
+ export const elementAccess: ReadRule = {
246
+ start() {
247
+ const candidates: Candidate[] = [];
248
+ const calls = new Map<Node, { readonly file: SourceFile; readonly from: string }>();
249
+ const names: Identifier[] = [];
250
+ return {
251
+ visit(node, { file, from }) {
252
+ if (isElementAccessExpression(node) && !isLiteralIndex(node.argumentExpression)) {
253
+ candidates.push({ file, from, access: node, use: useOf(node) });
254
+ }
255
+ if (isCallExpression(node)) {
256
+ calls.set(node, { file, from });
257
+ }
258
+ if (isIdentifier(node)) {
259
+ names.push(node);
260
+ }
261
+ },
262
+ reads({ project, chains }) {
263
+ const found: Read[] = [];
264
+ if (candidates.length === 0) {
265
+ return found;
266
+ }
267
+ const queries = project.queries;
268
+ // A parameter index is decided at the calls only where the function is a callable every
269
+ // use of which is a call, so the symbols of the parameters and of every name are read.
270
+ const parameterOf = new Map<Candidate, { callable: Callable; at: number }>();
271
+ const byCallable = new Map<Identifier, Candidate[]>();
272
+ for (const candidate of candidates) {
273
+ const index = parenthesesRemoved(candidate.access.argumentExpression);
274
+ const fn = isIdentifier(index) ? enclosingFunction(candidate.access) : undefined;
275
+ const callable = fn === undefined ? undefined : callableOf(fn);
276
+ if (callable === undefined || !isIdentifier(index)) {
277
+ continue;
278
+ }
279
+ const at = callable.parameters.findIndex(
280
+ (parameter) => isIdentifier(parameter.name) && parameter.name.text === index.text,
281
+ );
282
+ if (at < 0 || assigns(callable.body, index.text)) {
283
+ continue;
284
+ }
285
+ parameterOf.set(candidate, { callable, at });
286
+ byCallable.set(callable.name, [...(byCallable.get(callable.name) ?? []), candidate]);
287
+ }
288
+ const callableNames = [...byCallable.keys()];
289
+ const spelled = new Set(callableNames.map((name) => name.text));
290
+ const sameName = names.filter((name) => spelled.has(name.text));
291
+ const asked = [...callableNames, ...sameName];
292
+ const symbols = queries.symbolsAt(asked);
293
+ const symbolOf = new Map<Node, unknown>();
294
+ asked.forEach((node, at) => {
295
+ const symbol = symbols[at];
296
+ if (symbol !== undefined) {
297
+ symbolOf.set(node, symbol);
298
+ }
299
+ });
300
+ const callsOf = new Map<Node, CallExpression[] | undefined>();
301
+ for (const name of callableNames) {
302
+ const symbol = symbolOf.get(name);
303
+ let sites: CallExpression[] | undefined =
304
+ symbol === undefined || symbol === UNANSWERED ? undefined : [];
305
+ for (const use of sameName) {
306
+ if (sites === undefined) {
307
+ break;
308
+ }
309
+ const other = symbolOf.get(use);
310
+ if (use === name || (other !== symbol && other !== UNANSWERED)) {
311
+ continue;
312
+ }
313
+ // A use the checker could not resolve may be the function's, read where it is not called.
314
+ const parent = use.parent;
315
+ sites =
316
+ other !== UNANSWERED && isCallExpression(parent) && parent.expression === use
317
+ ? [...sites, parent]
318
+ : undefined;
319
+ }
320
+ callsOf.set(name, sites);
321
+ }
399
322
 
400
- const found: Reference[] = [];
401
- lookups.forEach((lookup, at) => {
402
- const indexType = typeOf(lookup.index, 2 * at);
403
- const objectType = typeOf(lookup.object, 2 * at + 1);
404
- const literals = indexType === undefined ? undefined : literalNames(partsOf(keysOf(indexType)));
405
- if (objectType === undefined || literals === undefined) {
406
- return;
407
- }
408
- const position = renderPosition(lookup.file, root, lookup.at.getStart());
409
- for (const part of partsOf(objectType)) {
410
- const properties = queries.propertiesOf(part);
411
- for (const property of properties === UNANSWERED ? [] : properties) {
412
- if (!literals.has(property.escapedName)) {
413
- continue;
323
+ const lookups: Lookup[] = [];
324
+ for (const candidate of candidates) {
325
+ const deferred = parameterOf.get(candidate);
326
+ const sites = deferred === undefined ? undefined : callsOf.get(deferred.callable.name);
327
+ if (deferred === undefined || sites === undefined) {
328
+ lookups.push({
329
+ file: candidate.file,
330
+ from: candidate.from,
331
+ at: candidate.access.argumentExpression,
332
+ object: candidate.access.expression,
333
+ index: candidate.access.argumentExpression,
334
+ use: candidate.use,
335
+ });
336
+ continue;
337
+ }
338
+ // An object that is a parameter too is read as the argument each call passes there.
339
+ const object = parenthesesRemoved(candidate.access.expression);
340
+ const objectAt = isIdentifier(object)
341
+ ? deferred.callable.parameters.findIndex(
342
+ (parameter) => isIdentifier(parameter.name) && parameter.name.text === object.text,
343
+ )
344
+ : -1;
345
+ for (const call of sites) {
346
+ const parameter = deferred.callable.parameters[deferred.at];
347
+ const index = call.arguments[deferred.at] ?? parameter?.initializer;
348
+ const site = calls.get(call);
349
+ if (index === undefined || site === undefined) {
350
+ continue;
351
+ }
352
+ lookups.push({
353
+ file: site.file,
354
+ from: site.from,
355
+ at: call,
356
+ object:
357
+ (objectAt < 0 ? undefined : call.arguments[objectAt]) ??
358
+ candidate.access.expression,
359
+ index,
360
+ use: candidate.use,
361
+ });
362
+ }
414
363
  }
415
- for (const to of chains.declarationsOf(property)) {
416
- for (const use of lookup.use === "both" ? (["read", "write"] as const) : [lookup.use]) {
364
+
365
+ const nodes = lookups.flatMap((one) => [one.index, one.object]);
366
+ const types = queries.typesAt(nodes);
367
+ // A type parameter's body serves every instantiation, so it reads what its constraint admits.
368
+ const keysOf = (type: Type): Type => {
369
+ if (!type.isTypeParameter()) {
370
+ return type;
371
+ }
372
+ const constraint = queries.constraintOf(type);
373
+ return constraint === UNANSWERED || constraint === undefined ? type : constraint;
374
+ };
375
+ const partsOf = (type: Type): readonly Type[] => {
376
+ const parts = queries.constituents(type);
377
+ return parts === UNANSWERED ? [type] : parts;
378
+ };
379
+ lookups.forEach((lookup, at) => {
380
+ const indexType = types[2 * at];
381
+ const objectType = types[2 * at + 1];
382
+ const literals =
383
+ indexType === undefined || indexType === UNANSWERED
384
+ ? undefined
385
+ : literalNames(partsOf(keysOf(indexType)));
386
+ if (indexType === UNANSWERED || objectType === UNANSWERED) {
417
387
  found.push({
388
+ kind: "held",
418
389
  from: lookup.from,
419
- to,
420
- position,
421
- use,
422
- resolution: "keyed",
423
- test: testFiles.has(position.path),
390
+ ...(literals === undefined ? {} : { names: [...literals] }),
391
+ ...(objectType === UNANSWERED || objectType === undefined
392
+ ? literals === undefined
393
+ ? { members: true as const }
394
+ : {}
395
+ : { types: partsOf(objectType) }),
424
396
  });
397
+ return;
425
398
  }
426
- }
427
- }
428
- }
429
- });
430
- return found;
431
- }
399
+ if (objectType === undefined || literals === undefined) {
400
+ return;
401
+ }
402
+ for (const part of partsOf(objectType)) {
403
+ const properties = queries.propertiesOf(part);
404
+ if (properties === UNANSWERED) {
405
+ found.push({ kind: "held", from: lookup.from, names: [...literals] });
406
+ continue;
407
+ }
408
+ for (const property of properties) {
409
+ if (!literals.has(property.escapedName)) {
410
+ continue;
411
+ }
412
+ for (const to of chains.declarationsOf(property)) {
413
+ for (const use of lookup.use === "both"
414
+ ? (["read", "write"] as const)
415
+ : [lookup.use]) {
416
+ found.push({
417
+ kind: "named",
418
+ from: lookup.from,
419
+ to,
420
+ file: lookup.file,
421
+ at: lookup.at,
422
+ use,
423
+ via: "keyed",
424
+ });
425
+ }
426
+ }
427
+ }
428
+ }
429
+ });
430
+ return found;
431
+ },
432
+ };
433
+ },
434
+ };
432
435
 
433
436
  /** The names a union of literal types spells, or none where a constituent is no string or number literal. */
434
437
  function literalNames(parts: readonly Type[]): ReadonlySet<string> | undefined {