@cplieger/deadset-ts 8.0.0-dev.1 → 8.0.0-dev.10

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 (276) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/mapper-connection.js +2 -1
  3. package/dist/bin/node-host.js +24 -5
  4. package/dist/src/analysis.js +181 -341
  5. package/dist/src/augmentations.js +106 -13
  6. package/dist/src/automatic-types.js +10 -29
  7. package/dist/src/build-scripts.js +425 -0
  8. package/dist/src/component-layer.js +4 -2
  9. package/dist/src/components.js +2 -3
  10. package/dist/src/config.js +6 -82
  11. package/dist/src/configuration-files.js +28 -176
  12. package/dist/src/configured-declarations.js +15 -20
  13. package/dist/src/conformance-record.js +1 -1
  14. package/dist/src/consumers.js +3 -30
  15. package/dist/src/contextual-uses.js +56 -9
  16. package/dist/src/contract/config.generated.js +558 -0
  17. package/dist/src/contract/contract.generated.js +1244 -0
  18. package/dist/src/contract/report.generated.js +862 -0
  19. package/dist/src/convention-rows.js +73 -3
  20. package/dist/src/conventions.js +36 -66
  21. package/dist/src/dependencies.js +103 -40
  22. package/dist/src/edges.js +38 -122
  23. package/dist/src/element-access.js +4 -6
  24. package/dist/src/entry-point-gaps.js +2 -8
  25. package/dist/src/entry-points.js +11 -27
  26. package/dist/src/enum-group.js +3 -10
  27. package/dist/src/erased-stores.js +4 -6
  28. package/dist/src/exempt-classes.js +1 -63
  29. package/dist/src/exempt.js +21 -40
  30. package/dist/src/failure.js +36 -0
  31. package/dist/src/file-facts.js +2 -25
  32. package/dist/src/findings/completion.js +139 -72
  33. package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
  34. package/dist/src/findings/emitters.js +5 -5
  35. package/dist/src/findings/interfaces.js +4 -5
  36. package/dist/src/findings/intra-function.js +13 -10
  37. package/dist/src/findings/non-code-artifacts.js +7 -8
  38. package/dist/src/findings/reads-and-writes.js +16 -13
  39. package/dist/src/findings/self-check.js +10 -12
  40. package/dist/src/findings/unused-declarations.js +41 -32
  41. package/dist/src/findings/visibility-narrowing.js +19 -16
  42. package/dist/src/findings-pass.js +8 -15
  43. package/dist/src/framework-lifecycle.js +7 -7
  44. package/dist/src/fs/document.js +52 -0
  45. package/dist/src/fs/manifest.js +72 -0
  46. package/dist/src/fs/tree.js +88 -0
  47. package/dist/src/generated-file.js +7 -4
  48. package/dist/src/git-ignore.js +39 -26
  49. package/dist/src/graph.js +5 -3
  50. package/dist/src/html-entries.js +6 -33
  51. package/dist/src/in-operands.js +2 -1
  52. package/dist/src/index.js +1 -1
  53. package/dist/src/injection-container.js +1 -1
  54. package/dist/src/intra-function-parts.js +63 -43
  55. package/dist/src/inventory.js +2 -21
  56. package/dist/src/javascript-file.js +33 -0
  57. package/dist/src/json-document.js +198 -67
  58. package/dist/src/keyof-comparisons.js +4 -6
  59. package/dist/src/kinds.js +3 -366
  60. package/dist/src/load/classify.js +270 -0
  61. package/dist/src/load/diagnostics.js +80 -0
  62. package/dist/src/load/discover.js +277 -0
  63. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  64. package/dist/src/load/expected-module.js +136 -0
  65. package/dist/src/load/load.js +27 -0
  66. package/dist/src/load/module-lookup.js +37 -0
  67. package/dist/src/load/plan.js +313 -0
  68. package/dist/src/load/specifiers.js +115 -0
  69. package/dist/src/load/synthesize.js +140 -0
  70. package/dist/src/load/test-globals.js +207 -0
  71. package/dist/src/load/test-joins.js +82 -0
  72. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
  73. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
  74. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +23 -65
  75. package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
  76. package/dist/src/{workspace.js → load/workspace.js} +62 -124
  77. package/dist/src/manifest.js +49 -54
  78. package/dist/src/matrix.js +76 -4
  79. package/dist/src/mdx-entries.js +3 -26
  80. package/dist/src/outside-tests.js +1 -1
  81. package/dist/src/partial.js +2 -1
  82. package/dist/src/paths.js +26 -15
  83. package/dist/src/position.js +2 -1
  84. package/dist/src/print.js +11 -79
  85. package/dist/src/product.js +13 -0
  86. package/dist/src/query.js +1 -0
  87. package/dist/src/ref.js +1 -0
  88. package/dist/src/references.js +48 -30
  89. package/dist/src/report-schema.js +51 -0
  90. package/dist/src/report.js +57 -41
  91. package/dist/src/reporters/annotations.js +15 -8
  92. package/dist/src/reporters/sarif.js +16 -10
  93. package/dist/src/reporters/template.js +4 -19
  94. package/dist/src/resolve.js +245 -729
  95. package/dist/src/roots.js +273 -87
  96. package/dist/src/run.js +66 -77
  97. package/dist/src/schema.js +320 -343
  98. package/dist/src/scope.js +38 -115
  99. package/dist/src/serialization-contract.js +595 -21
  100. package/dist/src/session.js +34 -29
  101. package/dist/src/source-files.js +1 -1
  102. package/dist/src/suppress-file.js +25 -28
  103. package/dist/src/suppress-inline.js +3 -2
  104. package/dist/src/suppress.js +33 -51
  105. package/dist/src/sweep.js +7 -9
  106. package/dist/src/symbol-keys.js +3 -5
  107. package/dist/src/template-field.js +9 -19
  108. package/dist/src/test-support.js +8 -11
  109. package/dist/src/text/compare.js +26 -0
  110. package/dist/src/text/glob.js +194 -0
  111. package/dist/src/text/named-files.js +54 -0
  112. package/dist/src/text/shell.js +159 -0
  113. package/dist/src/text/yaml.js +393 -0
  114. package/dist/src/type-errors.js +11 -232
  115. package/dist/src/unseen-loads.js +100 -0
  116. package/dist/src/unwrap.js +23 -0
  117. package/dist/src/usage.js +10 -0
  118. package/dist/src/verbs/analyze.js +166 -126
  119. package/dist/src/verbs/describe.js +9 -16
  120. package/dist/src/verbs/explain.js +10 -7
  121. package/dist/src/verbs/print-config.js +2 -1
  122. package/dist/src/verbs/print-projects.js +6 -4
  123. package/dist/src/verbs/print-retained.js +4 -2
  124. package/dist/src/verbs/print-roots.js +4 -2
  125. package/dist/src/verbs/verb.js +1 -5
  126. package/dist/src/verbs/version.js +14 -3
  127. package/dist/src/workflow-steps.js +62 -64
  128. package/jsr.json +1 -1
  129. package/package.json +4 -3
  130. package/src/analysis.ts +245 -502
  131. package/src/augmentations.ts +135 -17
  132. package/src/automatic-types.ts +11 -29
  133. package/src/build-scripts.ts +543 -0
  134. package/src/component-layer.ts +4 -2
  135. package/src/components.ts +2 -4
  136. package/src/config.ts +31 -302
  137. package/src/configuration-files.ts +34 -179
  138. package/src/configured-declarations.ts +18 -23
  139. package/src/conformance-record.ts +1 -1
  140. package/src/consumers.ts +6 -57
  141. package/src/contextual-uses.ts +64 -12
  142. package/src/contract/config.generated.ts +818 -0
  143. package/src/contract/contract.generated.ts +1308 -0
  144. package/src/contract/report.generated.ts +1237 -0
  145. package/src/convention-rows.ts +85 -3
  146. package/src/conventions.ts +46 -84
  147. package/src/dependencies.ts +118 -46
  148. package/src/edges.ts +41 -140
  149. package/src/element-access.ts +4 -7
  150. package/src/entry-point-gaps.ts +3 -9
  151. package/src/entry-points.ts +12 -38
  152. package/src/enum-group.ts +2 -11
  153. package/src/erased-stores.ts +3 -7
  154. package/src/exempt-classes.ts +1 -75
  155. package/src/exempt.ts +36 -50
  156. package/src/failure.ts +63 -0
  157. package/src/file-facts.ts +9 -24
  158. package/src/finding.ts +14 -9
  159. package/src/findings/boundary.ts +2 -0
  160. package/src/findings/completion.ts +181 -84
  161. package/src/findings/dependencies-and-module-machinery.ts +4 -7
  162. package/src/findings/emitter.ts +8 -9
  163. package/src/findings/emitters.ts +7 -7
  164. package/src/findings/interfaces.ts +4 -6
  165. package/src/findings/intra-function.ts +13 -11
  166. package/src/findings/non-code-artifacts.ts +9 -11
  167. package/src/findings/reads-and-writes.ts +20 -16
  168. package/src/findings/self-check.ts +11 -17
  169. package/src/findings/unused-declarations.ts +45 -32
  170. package/src/findings/visibility-narrowing.ts +20 -17
  171. package/src/findings-pass.ts +10 -19
  172. package/src/framework-lifecycle.ts +7 -7
  173. package/src/fs/document.ts +70 -0
  174. package/src/fs/manifest.ts +92 -0
  175. package/src/fs/tree.ts +110 -0
  176. package/src/generated-file.ts +7 -4
  177. package/src/git-ignore.ts +50 -26
  178. package/src/graph.ts +5 -3
  179. package/src/host.ts +12 -5
  180. package/src/html-entries.ts +6 -33
  181. package/src/in-operands.ts +2 -1
  182. package/src/index.ts +1 -1
  183. package/src/injection-container.ts +1 -1
  184. package/src/intra-function-parts.ts +73 -44
  185. package/src/inventory.ts +2 -20
  186. package/src/javascript-file.ts +37 -0
  187. package/src/json-document.ts +241 -76
  188. package/src/keyof-comparisons.ts +3 -7
  189. package/src/kinds.ts +5 -413
  190. package/src/load/classify.ts +397 -0
  191. package/src/load/diagnostics.ts +144 -0
  192. package/src/load/discover.ts +455 -0
  193. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  194. package/src/load/expected-module.ts +188 -0
  195. package/src/load/load.ts +73 -0
  196. package/src/load/module-lookup.ts +50 -0
  197. package/src/load/plan.ts +504 -0
  198. package/src/load/specifiers.ts +168 -0
  199. package/src/load/synthesize.ts +211 -0
  200. package/src/load/test-globals.ts +251 -0
  201. package/src/load/test-joins.ts +98 -0
  202. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
  203. package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
  204. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +33 -76
  205. package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
  206. package/src/{workspace.ts → load/workspace.ts} +90 -134
  207. package/src/manifest.ts +81 -75
  208. package/src/matrix.ts +122 -4
  209. package/src/mdx-entries.ts +3 -26
  210. package/src/outside-tests.ts +1 -1
  211. package/src/partial.ts +3 -2
  212. package/src/paths.ts +27 -15
  213. package/src/position.ts +2 -1
  214. package/src/print.ts +12 -92
  215. package/src/product.ts +18 -0
  216. package/src/query.ts +11 -0
  217. package/src/ref.ts +1 -0
  218. package/src/references.ts +52 -31
  219. package/src/report-schema.ts +68 -0
  220. package/src/report.ts +101 -224
  221. package/src/reporters/annotations.ts +22 -11
  222. package/src/reporters/json.ts +1 -1
  223. package/src/reporters/reporter.ts +2 -4
  224. package/src/reporters/reporters.ts +1 -1
  225. package/src/reporters/sarif.ts +29 -16
  226. package/src/reporters/template.ts +4 -20
  227. package/src/reporters/text.ts +3 -3
  228. package/src/resolve.ts +283 -1114
  229. package/src/roots.ts +339 -104
  230. package/src/run.ts +75 -91
  231. package/src/schema.ts +391 -388
  232. package/src/scope.ts +46 -138
  233. package/src/serialization-contract.ts +763 -22
  234. package/src/session.ts +70 -54
  235. package/src/source-files.ts +1 -1
  236. package/src/suppress-file.ts +24 -33
  237. package/src/suppress-inline.ts +2 -2
  238. package/src/suppress.ts +43 -58
  239. package/src/sweep.ts +23 -9
  240. package/src/symbol-keys.ts +2 -5
  241. package/src/template-field.ts +15 -25
  242. package/src/test-support.ts +17 -13
  243. package/src/text/compare.ts +27 -0
  244. package/src/text/glob.ts +210 -0
  245. package/src/text/named-files.inputs.json +1522 -0
  246. package/src/text/named-files.ts +68 -0
  247. package/src/text/shell.ts +161 -0
  248. package/src/text/yaml.ts +423 -0
  249. package/src/type-errors.ts +18 -288
  250. package/src/unseen-loads.ts +134 -0
  251. package/src/unwrap.ts +34 -0
  252. package/src/usage.ts +10 -0
  253. package/src/verbs/analyze.ts +224 -162
  254. package/src/verbs/describe.ts +14 -15
  255. package/src/verbs/explain.ts +10 -11
  256. package/src/verbs/print-config.ts +2 -1
  257. package/src/verbs/print-projects.ts +6 -4
  258. package/src/verbs/print-retained.ts +4 -2
  259. package/src/verbs/print-roots.ts +4 -2
  260. package/src/verbs/verb.ts +2 -8
  261. package/src/verbs/version.ts +15 -3
  262. package/src/workflow-steps.ts +74 -64
  263. package/dist/src/base-url.js +0 -18
  264. package/dist/src/discover.js +0 -468
  265. package/dist/src/glob.js +0 -65
  266. package/dist/src/pnpm-workspace.js +0 -120
  267. package/dist/src/setup-failure.js +0 -23
  268. package/dist/src/test-joins.js +0 -101
  269. package/dist/src/version.js +0 -7
  270. package/src/base-url.ts +0 -24
  271. package/src/discover.ts +0 -653
  272. package/src/glob.ts +0 -67
  273. package/src/pnpm-workspace.ts +0 -135
  274. package/src/setup-failure.ts +0 -39
  275. package/src/test-joins.ts +0 -120
  276. package/src/version.ts +0 -7
@@ -7,12 +7,21 @@
7
7
  * as `import.meta` or `process.env`, so a use of its member is a use of it.
8
8
  */
9
9
 
10
- import type { Inventory, InventorySymbol } from "./inventory.ts";
10
+ import {
11
+ isInterfaceDeclaration,
12
+ isModuleBlock,
13
+ isModuleDeclaration,
14
+ type Node,
15
+ } from "@typescript/native/ast";
16
+ import { nodeKey, type Inventory, type InventorySymbol } from "./inventory.ts";
11
17
  import { referenceKey } from "./matrix.ts";
12
18
  import type { Reference } from "./references.ts";
19
+ import type { ProjectView } from "./session.ts";
20
+ import type { SourceFiles } from "./source-files.ts";
21
+ import type { NodeHandle } from "@typescript/native/sync";
13
22
 
14
23
  /** Whether one declaration is a `declare global` block: a module-level namespace named `global`. */
15
- function isGlobalBlock(
24
+ export function isGlobalBlock(
16
25
  symbol: InventorySymbol,
17
26
  held: Inventory,
18
27
  files: ReadonlySet<string>,
@@ -26,25 +35,24 @@ function isGlobalBlock(
26
35
  }
27
36
 
28
37
  /**
29
- * For each reference to a declaration an augmentation block, or the global scope of a
30
- * file in `scripts`, holds, a read at the same place of every interface and namespace
31
- * between it and the block or the file, and of the block itself. `scripts` holds the
32
- * files that are no module, by identifier.
38
+ * Per declaration, the interfaces and namespaces between it and the augmentation block or
39
+ * the file in `scripts` that holds it, with the block itself, or none where no such block
40
+ * or file holds it; and whether that holder is the global scope rather than a module
41
+ * declaration. `scripts` holds the files that are no module, by identifier.
33
42
  */
34
- export function augmentationReferences(
43
+ function holdersOf(
35
44
  held: Inventory,
36
- found: readonly Reference[],
37
- scripts: ReadonlySet<string> = new Set(),
38
- ): readonly Reference[] {
45
+ scripts: ReadonlySet<string>,
46
+ ): ((id: string) => { readonly ids: readonly string[]; readonly global: boolean }) | undefined {
39
47
  const files = new Set(held.symbols.filter((one) => one.kind === "file").map((one) => one.id));
40
48
  const globals = new Set(
41
49
  held.symbols.filter((one) => isGlobalBlock(one, held, files)).map((one) => one.id),
42
50
  );
43
51
  if (globals.size === 0 && held.modules.size === 0 && scripts.size === 0) {
44
- return [];
52
+ return undefined;
45
53
  }
46
54
  const byId = new Map(held.symbols.map((one) => [one.id, one]));
47
- const holders = (id: string): string[] => {
55
+ return (id) => {
48
56
  const ids: string[] = [];
49
57
  for (
50
58
  let at = byId.get(byId.get(id)?.parent ?? "");
@@ -52,29 +60,139 @@ export function augmentationReferences(
52
60
  at = byId.get(at.parent)
53
61
  ) {
54
62
  if (globals.has(at.id) || held.modules.has(at.id)) {
55
- return [...ids, at.id];
63
+ return { ids: [...ids, at.id], global: globals.has(at.id) };
56
64
  }
57
65
  if (scripts.has(at.id)) {
58
- return ids;
66
+ return { ids, global: true };
59
67
  }
60
68
  if (at.kind === "interface" || at.kind === "namespace") {
61
69
  ids.push(at.id);
62
70
  }
63
71
  }
72
+ return { ids: [], global: false };
73
+ };
74
+ }
75
+
76
+ /**
77
+ * The ambient interfaces of the global scope among `interfaces`: each one a declaration
78
+ * file or a `declare` holds that a `declare global` block, or the top level of a file in
79
+ * `scripts`, declares, directly or inside a namespace there.
80
+ */
81
+ export function ambientGlobalInterfaces(
82
+ held: Inventory,
83
+ interfaces: readonly string[],
84
+ scripts: ReadonlySet<string>,
85
+ ): readonly string[] {
86
+ const holders = holdersOf(held, scripts);
87
+ return holders === undefined
88
+ ? []
89
+ : interfaces.filter((id) => held.ambient.has(id) && holders(id).global);
90
+ }
91
+
92
+ /**
93
+ * Each ambient global interface of the project's own files that merges into an interface
94
+ * declared outside them, with every interface, namespace and block between it and the
95
+ * global scope: the outside declaration names it wherever a value is typed by it. Where
96
+ * every outside declaration is a package's, not the compiler's library, and declares no
97
+ * member, each member it declares as well: such an interface is a slot the package reads
98
+ * by type, as `keyof` does, in declarations the analysis does not walk.
99
+ */
100
+ export function mergedGlobalInterfaces<Brand>(
101
+ project: ProjectView<Brand>,
102
+ held: Inventory,
103
+ files: SourceFiles,
104
+ ): readonly string[] {
105
+ const scripts = new Set<string>();
106
+ const names = new Map<string, Node>();
107
+ for (const file of files.byName.values()) {
108
+ const fileId = held.declarations.get(nodeKey(file, file));
109
+ if (fileId !== undefined && file.externalModuleIndicator === undefined) {
110
+ scripts.add(fileId);
111
+ }
112
+ const visit = (node: Node): void => {
113
+ if (isInterfaceDeclaration(node)) {
114
+ const id = held.declarations.get(nodeKey(file, node));
115
+ if (id !== undefined) {
116
+ names.set(id, node.name);
117
+ }
118
+ } else if (isModuleDeclaration(node) || isModuleBlock(node)) {
119
+ node.forEachChild(visit);
120
+ }
121
+ };
122
+ file.forEachChild(visit);
123
+ }
124
+ const global = new Set(ambientGlobalInterfaces(held, [...names.keys()], scripts));
125
+ const asked = [...names].filter(([id]) => global.has(id));
126
+ if (asked.length === 0) {
64
127
  return [];
128
+ }
129
+ const answers = project.symbolsAt(asked.map(([, name]) => project.handle(name)));
130
+ const holders = holdersOf(held, scripts);
131
+ const empty = (handle: NodeHandle): boolean => {
132
+ if (project.program.getSourceFileMetadata(handle.path)?.isDefaultLibrary === true) {
133
+ return false;
134
+ }
135
+ const node = project.declarationAt(handle)?.node;
136
+ return node !== undefined && isInterfaceDeclaration(node) && node.members.length === 0;
65
137
  };
138
+ return [
139
+ ...new Set(
140
+ asked.flatMap(([id], at) => {
141
+ const symbol = answers[at];
142
+ if (typeof symbol !== "object") {
143
+ return [];
144
+ }
145
+ const outside = symbol.declarations.filter((handle) => !files.byName.has(handle.path));
146
+ if (outside.length === 0) {
147
+ return [];
148
+ }
149
+ const members = outside.every(empty)
150
+ ? held.symbols.filter((one) => one.parent === id).map((one) => one.id)
151
+ : [];
152
+ return [id, ...(holders?.(id).ids ?? []), ...members];
153
+ }),
154
+ ),
155
+ ];
156
+ }
157
+
158
+ /**
159
+ * For each reference to a declaration an augmentation block, or the global scope of a
160
+ * file in `scripts` (the files that are no module), holds, a read at the same place of
161
+ * every interface and namespace between it and the block or the file, and of the block
162
+ * itself. A read through an interface of `merged`, an ambient global interface merging
163
+ * into a language or library one, is a production read whoever writes it: it types a
164
+ * value the runtime provides, so a test reading a member needs it as code does.
165
+ */
166
+ export function augmentationReferences(
167
+ held: Inventory,
168
+ found: readonly Reference[],
169
+ scripts: ReadonlySet<string> = new Set(),
170
+ merged: ReadonlySet<string> = new Set(),
171
+ ): readonly Reference[] {
172
+ const holders = holdersOf(held, scripts);
173
+ if (holders === undefined) {
174
+ return [];
175
+ }
176
+ const fileOf = new Map(
177
+ held.symbols.filter((one) => one.kind === "file").map((one) => [one.position.path, one.id]),
178
+ );
66
179
  // Two uses at one place of declarations one block holds read the block once there.
67
180
  const made = new Set(found.map(referenceKey));
68
181
  const reads = new Map<string, Reference>();
69
182
  for (const reference of found) {
70
- for (const to of holders(reference.to)) {
183
+ const { ids } = holders(reference.to);
184
+ // A test's read through such an interface is held by the test file, which the test
185
+ // runner loads whichever of its declarations runs.
186
+ const typed = reference.test && ids.some((id) => merged.has(id));
187
+ const from = typed ? (fileOf.get(reference.position.path) ?? reference.from) : reference.from;
188
+ for (const to of ids) {
71
189
  const read: Reference = {
72
- from: reference.from,
190
+ from,
73
191
  to,
74
192
  position: reference.position,
75
193
  use: "read",
76
194
  resolution: reference.resolution,
77
- test: reference.test,
195
+ test: reference.test && !typed,
78
196
  };
79
197
  const key = referenceKey(read);
80
198
  if (!made.has(key) && !reads.has(key)) {
@@ -26,8 +26,10 @@ import {
26
26
  type Statement,
27
27
  } from "@typescript/native/ast";
28
28
  import type { ParseFile } from "./configuration-files.ts";
29
- import type { DirectoryEntry, Host } from "./host.ts";
30
- import { dirnamePath, joinPath, resolvePath } from "./paths.ts";
29
+ import type { Host } from "./host.ts";
30
+ import { ancestors, dirnamePath, joinPath, resolvePath } from "./paths.ts";
31
+ import { entriesOf } from "./fs/tree.ts";
32
+ import { manifestAt } from "./fs/manifest.ts";
31
33
 
32
34
  const TYPE_ROOT = "node_modules/@types";
33
35
 
@@ -122,19 +124,11 @@ function fileDeclarations(file: SourceFile, globals: string[], modules: string[]
122
124
 
123
125
  /** The entry declaration file of one installed type package's directory. */
124
126
  function entryOf(host: Host, dir: string): string {
125
- try {
126
- const manifest: unknown = JSON.parse(host.readFile(joinPath(dir, "package.json")));
127
- const named =
128
- typeof manifest === "object" && manifest !== null
129
- ? ((manifest as Record<string, unknown>)["types"] ??
130
- (manifest as Record<string, unknown>)["typings"])
131
- : undefined;
132
- if (typeof named === "string" && named !== "") {
133
- const path = resolvePath(dir, named);
134
- return path.endsWith(".ts") ? path : `${path}.d.ts`;
135
- }
136
- } catch {
137
- // A package with no readable manifest is read from its index, as the compiler reads it.
127
+ const manifest = manifestAt(host, dir);
128
+ const named = manifest?.["types"] ?? manifest?.["typings"];
129
+ if (typeof named === "string" && named !== "") {
130
+ const path = resolvePath(dir, named);
131
+ return path.endsWith(".ts") ? path : `${path}.d.ts`;
138
132
  }
139
133
  return joinPath(dir, "index.d.ts");
140
134
  }
@@ -201,13 +195,7 @@ export function automaticTypes(
201
195
  };
202
196
  const read = new Set<string>();
203
197
  for (const root of typeRoots(configFile, options)) {
204
- let entries: readonly DirectoryEntry[];
205
- try {
206
- entries = host.readDirectory(root);
207
- } catch {
208
- entries = [];
209
- }
210
- for (const entry of entries) {
198
+ for (const entry of entriesOf(host, root)) {
211
199
  if (read.has(entry.name) || host.kindOf(joinPath(root, entry.name)) !== "directory") {
212
200
  continue;
213
201
  }
@@ -236,11 +224,5 @@ function typeRoots(configFile: string, options: Readonly<Record<string, unknown>
236
224
  (root): root is string => typeof root === "string" && root.endsWith(`/${TYPE_ROOT}`),
237
225
  );
238
226
  }
239
- const roots: string[] = [];
240
- for (let dir = dirnamePath(configFile); ; dir = dirnamePath(dir)) {
241
- roots.push(joinPath(dir, TYPE_ROOT));
242
- if (dirnamePath(dir) === dir) {
243
- return roots;
244
- }
245
- }
227
+ return ancestors(dirnamePath(configFile)).map((dir) => joinPath(dir, TYPE_ROOT));
246
228
  }