@cplieger/deadset-ts 8.0.0-dev.6 → 8.0.0-dev.8

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 (193) hide show
  1. package/dist/bin/mapper-connection.js +2 -1
  2. package/dist/bin/node-host.js +24 -5
  3. package/dist/src/analysis.js +37 -56
  4. package/dist/src/automatic-types.js +10 -29
  5. package/dist/src/build-scripts.js +17 -29
  6. package/dist/src/component-layer.js +4 -2
  7. package/dist/src/components.js +2 -3
  8. package/dist/src/config.js +6 -82
  9. package/dist/src/configuration-files.js +27 -168
  10. package/dist/src/configured-declarations.js +15 -20
  11. package/dist/src/consumers.js +2 -2
  12. package/dist/src/contract/config.generated.js +544 -0
  13. package/dist/src/contract/contract.generated.js +13 -0
  14. package/dist/src/contract/report.generated.js +3 -2
  15. package/dist/src/conventions.js +20 -60
  16. package/dist/src/dependencies.js +25 -43
  17. package/dist/src/discover.js +14 -40
  18. package/dist/src/edges.js +38 -122
  19. package/dist/src/element-access.js +4 -6
  20. package/dist/src/entry-point-gaps.js +2 -8
  21. package/dist/src/entry-points.js +3 -10
  22. package/dist/src/enum-group.js +3 -10
  23. package/dist/src/erased-stores.js +4 -6
  24. package/dist/src/exempt-classes.js +0 -4
  25. package/dist/src/exempt.js +6 -22
  26. package/dist/src/file-facts.js +2 -25
  27. package/dist/src/findings/completion.js +5 -4
  28. package/dist/src/findings/emitters.js +1 -1
  29. package/dist/src/findings/intra-function.js +1 -1
  30. package/dist/src/findings/non-code-artifacts.js +2 -2
  31. package/dist/src/findings/reads-and-writes.js +2 -1
  32. package/dist/src/findings/self-check.js +3 -2
  33. package/dist/src/findings/unused-declarations.js +1 -1
  34. package/dist/src/findings/visibility-narrowing.js +2 -2
  35. package/dist/src/findings-pass.js +7 -12
  36. package/dist/src/framework-lifecycle.js +7 -7
  37. package/dist/src/fs/document.js +59 -0
  38. package/dist/src/fs/manifest.js +43 -0
  39. package/dist/src/fs/tree.js +88 -0
  40. package/dist/src/git-ignore.js +34 -25
  41. package/dist/src/html-entries.js +6 -33
  42. package/dist/src/in-operands.js +2 -1
  43. package/dist/src/injection-container.js +1 -1
  44. package/dist/src/intra-function-parts.js +10 -13
  45. package/dist/src/inventory.js +2 -21
  46. package/dist/src/json-document.js +198 -67
  47. package/dist/src/keyof-comparisons.js +4 -6
  48. package/dist/src/kinds.js +0 -7
  49. package/dist/src/manifest.js +5 -43
  50. package/dist/src/mdx-entries.js +3 -26
  51. package/dist/src/partial.js +2 -1
  52. package/dist/src/paths.js +26 -15
  53. package/dist/src/position.js +2 -1
  54. package/dist/src/print.js +11 -79
  55. package/dist/src/product.js +13 -0
  56. package/dist/src/references.js +14 -27
  57. package/dist/src/report-schema.js +3 -225
  58. package/dist/src/report.js +22 -31
  59. package/dist/src/reporters/sarif.js +4 -2
  60. package/dist/src/reporters/template.js +4 -19
  61. package/dist/src/resolve.js +245 -724
  62. package/dist/src/roots.js +7 -17
  63. package/dist/src/run.js +55 -61
  64. package/dist/src/schema.js +320 -343
  65. package/dist/src/scope.js +34 -103
  66. package/dist/src/serialization-contract.js +5 -9
  67. package/dist/src/session.js +2 -1
  68. package/dist/src/suppress-file.js +21 -25
  69. package/dist/src/suppress.js +3 -3
  70. package/dist/src/symbol-keys.js +3 -5
  71. package/dist/src/template-field.js +9 -19
  72. package/dist/src/test-globals.js +6 -28
  73. package/dist/src/test-joins.js +6 -6
  74. package/dist/src/text/compare.js +26 -0
  75. package/dist/src/text/glob.js +194 -0
  76. package/dist/src/text/shell.js +159 -0
  77. package/dist/src/{yaml-document.js → text/yaml.js} +38 -0
  78. package/dist/src/type-errors.js +14 -38
  79. package/dist/src/unseen-loads.js +2 -9
  80. package/dist/src/unwrap.js +23 -0
  81. package/dist/src/usage.js +10 -0
  82. package/dist/src/verbs/analyze.js +25 -26
  83. package/dist/src/verbs/describe.js +4 -4
  84. package/dist/src/verbs/explain.js +8 -6
  85. package/dist/src/verbs/print-projects.js +4 -3
  86. package/dist/src/verbs/print-retained.js +2 -1
  87. package/dist/src/verbs/print-roots.js +2 -1
  88. package/dist/src/verbs/version.js +2 -1
  89. package/dist/src/workflow-steps.js +9 -46
  90. package/dist/src/workspace-manifests.js +2 -2
  91. package/dist/src/workspace-programs.js +5 -3
  92. package/dist/src/workspace-resolution.js +13 -17
  93. package/dist/src/workspace.js +28 -116
  94. package/jsr.json +1 -1
  95. package/package.json +1 -1
  96. package/src/analysis.ts +55 -76
  97. package/src/automatic-types.ts +11 -29
  98. package/src/build-scripts.ts +17 -38
  99. package/src/component-layer.ts +4 -2
  100. package/src/components.ts +2 -4
  101. package/src/config.ts +31 -296
  102. package/src/configuration-files.ts +27 -170
  103. package/src/configured-declarations.ts +18 -23
  104. package/src/consumers.ts +4 -4
  105. package/src/contract/config.generated.ts +798 -0
  106. package/src/contract/contract.generated.ts +25 -0
  107. package/src/contract/report.generated.ts +3 -2
  108. package/src/conventions.ts +26 -74
  109. package/src/dependencies.ts +32 -50
  110. package/src/discover.ts +15 -40
  111. package/src/edges.ts +41 -140
  112. package/src/element-access.ts +4 -7
  113. package/src/entry-point-gaps.ts +3 -9
  114. package/src/entry-points.ts +2 -13
  115. package/src/enum-group.ts +2 -11
  116. package/src/erased-stores.ts +3 -7
  117. package/src/exempt-classes.ts +0 -5
  118. package/src/exempt.ts +8 -30
  119. package/src/file-facts.ts +6 -24
  120. package/src/findings/completion.ts +5 -6
  121. package/src/findings/emitter.ts +2 -2
  122. package/src/findings/emitters.ts +1 -1
  123. package/src/findings/intra-function.ts +1 -1
  124. package/src/findings/non-code-artifacts.ts +4 -4
  125. package/src/findings/reads-and-writes.ts +2 -1
  126. package/src/findings/self-check.ts +3 -2
  127. package/src/findings/unused-declarations.ts +1 -1
  128. package/src/findings/visibility-narrowing.ts +2 -2
  129. package/src/findings-pass.ts +9 -15
  130. package/src/framework-lifecycle.ts +7 -7
  131. package/src/fs/document.ts +74 -0
  132. package/src/fs/manifest.ts +52 -0
  133. package/src/fs/tree.ts +110 -0
  134. package/src/git-ignore.ts +38 -25
  135. package/src/host.ts +12 -5
  136. package/src/html-entries.ts +6 -33
  137. package/src/in-operands.ts +2 -1
  138. package/src/injection-container.ts +1 -1
  139. package/src/intra-function-parts.ts +10 -14
  140. package/src/inventory.ts +2 -20
  141. package/src/json-document.ts +241 -76
  142. package/src/keyof-comparisons.ts +3 -7
  143. package/src/kinds.ts +0 -8
  144. package/src/manifest.ts +5 -46
  145. package/src/mdx-entries.ts +3 -26
  146. package/src/partial.ts +2 -1
  147. package/src/paths.ts +27 -15
  148. package/src/position.ts +2 -1
  149. package/src/print.ts +12 -92
  150. package/src/product.ts +18 -0
  151. package/src/references.ts +14 -29
  152. package/src/report-schema.ts +3 -301
  153. package/src/report.ts +24 -34
  154. package/src/reporters/sarif.ts +4 -4
  155. package/src/reporters/template.ts +4 -20
  156. package/src/resolve.ts +283 -1114
  157. package/src/roots.ts +7 -20
  158. package/src/run.ts +57 -75
  159. package/src/schema.ts +391 -388
  160. package/src/scope.ts +40 -126
  161. package/src/serialization-contract.ts +5 -10
  162. package/src/session.ts +2 -1
  163. package/src/suppress-file.ts +21 -29
  164. package/src/suppress.ts +3 -3
  165. package/src/symbol-keys.ts +2 -5
  166. package/src/template-field.ts +15 -25
  167. package/src/test-globals.ts +9 -27
  168. package/src/test-joins.ts +6 -8
  169. package/src/text/compare.ts +27 -0
  170. package/src/text/glob.ts +210 -0
  171. package/src/text/shell.ts +161 -0
  172. package/src/{yaml-document.ts → text/yaml.ts} +46 -0
  173. package/src/type-errors.ts +25 -36
  174. package/src/unseen-loads.ts +1 -12
  175. package/src/unwrap.ts +34 -0
  176. package/src/usage.ts +10 -0
  177. package/src/verbs/analyze.ts +32 -42
  178. package/src/verbs/describe.ts +4 -4
  179. package/src/verbs/explain.ts +8 -10
  180. package/src/verbs/print-projects.ts +4 -3
  181. package/src/verbs/print-retained.ts +2 -1
  182. package/src/verbs/print-roots.ts +2 -1
  183. package/src/verbs/verb.ts +2 -2
  184. package/src/verbs/version.ts +2 -1
  185. package/src/workflow-steps.ts +9 -44
  186. package/src/workspace-manifests.ts +2 -2
  187. package/src/workspace-programs.ts +5 -3
  188. package/src/workspace-resolution.ts +21 -17
  189. package/src/workspace.ts +35 -121
  190. package/dist/src/glob.js +0 -65
  191. package/dist/src/pnpm-workspace.js +0 -120
  192. package/src/glob.ts +0 -67
  193. package/src/pnpm-workspace.ts +0 -135
@@ -19,10 +19,13 @@ import {
19
19
  type SourceFile,
20
20
  } from "@typescript/native/ast";
21
21
  import type { Host } from "./host.ts";
22
- import { dirnamePath, joinPath, relativePath, resolvePath } from "./paths.ts";
22
+ import { ancestors, dirnamePath, joinPath, relativePath, resolvePath } from "./paths.ts";
23
23
  import type { SourceFiles } from "./source-files.ts";
24
-
25
- const MANIFEST = "package.json";
24
+ import { bytewise } from "./text/compare.ts";
25
+ import { isRecord } from "./json-document.ts";
26
+ import { filesIn } from "./fs/tree.ts";
27
+ import { holdsManifest, inInstalledPackages, manifestAt, readJSON } from "./fs/manifest.ts";
28
+ import { shellWords } from "./text/shell.ts";
26
29
 
27
30
  /** A configuration module's name, each form with the spelling a root reports it by. */
28
31
  const MODULE_FORMS: readonly { readonly name: RegExp; readonly form: string }[] = [
@@ -72,9 +75,6 @@ export const RESOLVED_EXTENSIONS = [
72
75
  ".cjs",
73
76
  ] as const;
74
77
 
75
- /** The directory a package manager installs packages into, whose files are no project's own. */
76
- const MODULES_DIR = "node_modules";
77
-
78
78
  /** The file's name, the last segment of its path. */
79
79
  function basename(path: string): string {
80
80
  return path.slice(path.lastIndexOf("/") + 1);
@@ -82,11 +82,8 @@ function basename(path: string): string {
82
82
 
83
83
  /** Whether one path is the project's own: below the target root and in no `node_modules`. */
84
84
  function isProjectPath(root: string, path: string): boolean {
85
- return relativePath(root, path)?.split("/").includes(MODULES_DIR) === false;
86
- }
87
-
88
- function isRecord(value: unknown): value is Record<string, unknown> {
89
- return typeof value === "object" && value !== null && !Array.isArray(value);
85
+ const below = relativePath(root, path);
86
+ return below !== undefined && !inInstalledPackages(below);
90
87
  }
91
88
 
92
89
  /** The form one file name is as a configuration module, or undefined where it is none. */
@@ -126,120 +123,13 @@ const CONFIG_FLAGS: ReadonlySet<string> = new Set(["--config", "-c"]);
126
123
  /** The extensions of a module a configuration flag may name. */
127
124
  const MODULE_EXTENSIONS = [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"] as const;
128
125
 
129
- /** The characters that end a word outside quotes and separate nothing: blanks. */
130
- // Stryker disable next-line Regex: its \v to \V mutant is no valid escape under the u flag, so the whole module fails to parse
131
- const BLANK = /[ \t\r\f\v]/u;
132
-
133
- /** The characters that end a word outside quotes and begin an operator: newline included. */
134
- const OPERATOR = /[\n;&|()<>]/u;
135
-
136
- /** The characters a backslash escapes inside double quotes; before any other it stands for itself. */
137
- const DOUBLE_QUOTE_ESCAPES = new Set(["$", "`", '"', "\\"]);
138
-
139
- /**
140
- * The words of one command line, as POSIX token recognition reads quotes, backslashes,
141
- * line continuations, comments and operators. A word an expansion may change (an unquoted
142
- * `$`, backquote, glob character or leading `~`, or a `$` or backquote in double quotes)
143
- * is computed, and so is the rest of a line whose quote is never closed. A computed word
144
- * and each operator are undefined, so a flag's file is never read across them.
145
- */
146
- function shellWords(command: string): readonly (string | undefined)[] {
147
- const words: (string | undefined)[] = [];
148
- let word: string | undefined;
149
- let computed = false;
150
- const end = (): void => {
151
- if (word !== undefined) {
152
- words.push(computed ? undefined : word);
153
- }
154
- word = undefined;
155
- computed = false;
156
- };
157
- for (let at = 0; at < command.length; at += 1) {
158
- const char = command.charAt(at);
159
- if (char === "\\" && command.charAt(at + 1) === "\n") {
160
- at += 1;
161
- } else if (BLANK.test(char)) {
162
- end();
163
- } else if (OPERATOR.test(char)) {
164
- end();
165
- words.push(undefined);
166
- } else if (char === "#" && word === undefined) {
167
- const newline = command.indexOf("\n", at);
168
- at = newline < 0 ? command.length : newline - 1;
169
- } else if (char === "\\") {
170
- at += 1;
171
- word = (word ?? "") + command.charAt(at);
172
- } else if (char === "'" || char === '"') {
173
- const close = closingQuote(command, at);
174
- if (close < 0) {
175
- word ??= "";
176
- computed = true;
177
- break;
178
- }
179
- const quoted =
180
- char === "'"
181
- ? { text: command.slice(at + 1, close), computed: false }
182
- : doubleQuoted(command.slice(at + 1, close));
183
- word = (word ?? "") + quoted.text;
184
- computed ||= quoted.computed;
185
- at = close;
186
- } else {
187
- computed ||= /[$`*?[]/u.test(char) || (char === "~" && word === undefined);
188
- word = (word ?? "") + char;
189
- }
190
- }
191
- end();
192
- return words;
193
- }
194
-
195
- /** The text between one pair of double quotes, unescaped, and whether an expansion may change it. */
196
- function doubleQuoted(inner: string): { readonly text: string; readonly computed: boolean } {
197
- let text = "";
198
- let computed = false;
199
- for (let at = 0; at < inner.length; at += 1) {
200
- const char = inner.charAt(at);
201
- const next = inner.charAt(at + 1);
202
- if (char === "\\" && next === "\n") {
203
- at += 1;
204
- } else if (char === "\\" && DOUBLE_QUOTE_ESCAPES.has(next)) {
205
- text += next;
206
- at += 1;
207
- } else {
208
- computed ||= char === "$" || char === "`";
209
- text += char;
210
- }
211
- }
212
- return { text, computed };
213
- }
214
-
215
- /** The index of the quote that closes the one at `open`, or -1 where none does. */
216
- function closingQuote(command: string, open: number): number {
217
- const quote = command.charAt(open);
218
- for (let at = open + 1; at < command.length; at += 1) {
219
- const char = command.charAt(at);
220
- if (char === quote) {
221
- return at;
222
- }
223
- if (quote === '"' && char === "\\") {
224
- at += 1;
225
- }
226
- }
227
- return -1;
228
- }
229
-
230
126
  /**
231
127
  * The files the scripts of the manifest in one directory name after a configuration flag,
232
128
  * `--config <file>`, `-c <file>` or `--config=<file>`, each a JSON file or a module below
233
129
  * the target root and in no `node_modules`.
234
130
  */
235
131
  function scriptConfigurations(host: Host, root: string, dir: string): readonly string[] {
236
- let scripts: unknown;
237
- try {
238
- const manifest: unknown = JSON.parse(host.readFile(joinPath(dir, MANIFEST)));
239
- scripts = isRecord(manifest) ? manifest["scripts"] : undefined;
240
- } catch {
241
- return [];
242
- }
132
+ const scripts = manifestAt(host, dir)?.["scripts"];
243
133
  if (!isRecord(scripts)) {
244
134
  return [];
245
135
  }
@@ -270,15 +160,6 @@ function scriptConfigurations(host: Host, root: string, dir: string): readonly s
270
160
  return found;
271
161
  }
272
162
 
273
- /** The decoded value of one JSON file, or undefined where it cannot be read or parsed. */
274
- function readDocument(host: Host, path: string): unknown {
275
- try {
276
- return JSON.parse(host.readFile(path)) as unknown;
277
- } catch {
278
- return undefined;
279
- }
280
- }
281
-
282
163
  /** The configuration files one project holds and sits beside. */
283
164
  interface ConfigurationFiles {
284
165
  /**
@@ -346,10 +227,10 @@ export function configurationFiles(
346
227
  ): ConfigurationFiles {
347
228
  const root = resolvePath(host.workingDirectory(), targetRoot);
348
229
  const manifests = new Map<string, boolean>();
349
- const holdsManifest = (dir: string): boolean => {
230
+ const manifestHeld = (dir: string): boolean => {
350
231
  let held = manifests.get(dir);
351
232
  if (held === undefined) {
352
- held = host.kindOf(joinPath(dir, MANIFEST)) === "file";
233
+ held = holdsManifest(host, dir);
353
234
  manifests.set(dir, held);
354
235
  }
355
236
  return held;
@@ -360,34 +241,24 @@ export function configurationFiles(
360
241
  for (const file of files.byPath.values()) {
361
242
  const form = configurationModuleForm(basename(file.fileName));
362
243
  const fileDir = dirnamePath(file.fileName);
363
- if (form !== undefined && holdsManifest(fileDir)) {
244
+ if (form !== undefined && manifestHeld(fileDir)) {
364
245
  modules.push({ file, form, manifestDir: fileDir });
365
246
  }
366
- for (
367
- let dir = dirnamePath(file.fileName);
368
- relativePath(root, dir) !== undefined && !dirs.has(dir);
369
- dir = dirnamePath(dir)
370
- ) {
247
+ for (const dir of ancestors(dirnamePath(file.fileName), root)) {
248
+ if (dirs.has(dir)) {
249
+ break;
250
+ }
371
251
  dirs.add(dir);
372
252
  }
373
253
  }
374
254
 
375
255
  const pending: { path: string; manifestDir: string }[] = [];
376
256
  const named: { path: string; manifestDir: string }[] = [];
377
- for (const dir of [...dirs].sort()) {
378
- if (!holdsManifest(dir)) {
257
+ for (const dir of [...dirs].sort(bytewise)) {
258
+ if (!manifestHeld(dir)) {
379
259
  continue;
380
260
  }
381
- let names: readonly string[];
382
- try {
383
- names = host
384
- .readDirectory(dir)
385
- .filter((entry) => !entry.directory && isConfigurationDocumentName(entry.name))
386
- .map((entry) => entry.name)
387
- .sort();
388
- } catch {
389
- names = [];
390
- }
261
+ const names = filesIn(host, dir, isConfigurationDocumentName);
391
262
  pending.push(...names.map((name) => ({ path: joinPath(dir, name), manifestDir: dir })));
392
263
  for (const path of scriptConfigurations(host, root, dir)) {
393
264
  const held = files.byName.get(path);
@@ -410,7 +281,7 @@ export function configurationFiles(
410
281
  continue;
411
282
  }
412
283
  if (document === undefined) {
413
- const value = readDocument(host, next.path);
284
+ const value = readJSON(host, next.path);
414
285
  if (value === undefined) {
415
286
  unreadable.add(next.path);
416
287
  continue;
@@ -438,7 +309,7 @@ export function configurationFiles(
438
309
  outside:
439
310
  parse === undefined
440
311
  ? []
441
- : outsideModules(host, root, [...dirs], files, holdsManifest, parse, named),
312
+ : outsideModules(host, root, [...dirs], files, manifestHeld, parse, named),
442
313
  };
443
314
  }
444
315
 
@@ -551,25 +422,16 @@ function outsideModules(
551
422
  root: string,
552
423
  dirs: readonly string[],
553
424
  files: SourceFiles,
554
- holdsManifest: (dir: string) => boolean,
425
+ manifestHeld: (dir: string) => boolean,
555
426
  parse: ParseFile,
556
427
  named: readonly { readonly path: string; readonly manifestDir: string }[],
557
428
  ): readonly OutsideModule[] {
558
429
  const pending: { path: string; manifestDir: string }[] = [...named];
559
- for (const dir of [...dirs].sort()) {
560
- if (!holdsManifest(dir)) {
561
- continue;
562
- }
563
- let names: readonly string[];
564
- try {
565
- names = host
566
- .readDirectory(dir)
567
- .filter((entry) => !entry.directory && configurationModuleForm(entry.name) !== undefined)
568
- .map((entry) => entry.name)
569
- .sort();
570
- } catch {
430
+ for (const dir of [...dirs].sort(bytewise)) {
431
+ if (!manifestHeld(dir)) {
571
432
  continue;
572
433
  }
434
+ const names = filesIn(host, dir, (name) => configurationModuleForm(name) !== undefined);
573
435
  pending.push(...names.map((name) => ({ path: joinPath(dir, name), manifestDir: dir })));
574
436
  }
575
437
  const found = new Map<string, { file: SourceFile; manifestDirs: string[] }>();
@@ -607,13 +469,8 @@ function outsideModules(
607
469
 
608
470
  /** Every dependency the manifest in one directory declares, or none where it holds none to read. */
609
471
  export function declaredIn(host: Host, dir: string): readonly string[] {
610
- let value: unknown;
611
- try {
612
- value = JSON.parse(host.readFile(joinPath(dir, MANIFEST)));
613
- } catch {
614
- return [];
615
- }
616
- if (!isRecord(value)) {
472
+ const value = manifestAt(host, dir);
473
+ if (value === undefined) {
617
474
  return [];
618
475
  }
619
476
  const names = new Set<string>();
@@ -19,7 +19,7 @@ import {
19
19
  import { SymbolFlags, type NodeHandle, type Symbol as TSSymbol } from "@typescript/native/sync";
20
20
  import type { AliasChains } from "./alias-chain.ts";
21
21
  import { resolvedTargets } from "./calls.ts";
22
- import type { Config, DeclarationEntry } from "./config.ts";
22
+ import type { DeclarationEntry, ResolvedConfig } from "./config.ts";
23
23
  import { declaredComponent, type Inventory } from "./inventory.ts";
24
24
  import { must, Unanswerable } from "./query.ts";
25
25
  import { nameComponent } from "./ref.ts";
@@ -252,21 +252,21 @@ export function resolveEntries<Brand>(
252
252
  }
253
253
  const modules = modulesNamed(
254
254
  project,
255
- new Set(entries.flatMap((entry) => (entry.shape === "module" ? [entry.module] : []))),
255
+ new Set(entries.flatMap((entry) => ("module" in entry ? [entry.module] : []))),
256
256
  );
257
257
  return entries.map((entry) => {
258
- if (entry.shape === "symbol") {
258
+ if ("symbol" in entry) {
259
259
  return { entry, handles: new Set<string>(), ids: new Set(byRef.get(entry.symbol) ?? []) };
260
260
  }
261
261
  const { components, static: isStatic } = componentsOf(
262
- entry.shape === "module" ? entry.name : entry.global,
262
+ "module" in entry ? entry.name : entry.global,
263
263
  );
264
264
  const [first = "", ...rest] = components;
265
265
  let start: TSSymbol | undefined;
266
266
  if (isStatic && rest.length === 0) {
267
267
  // Only a member is static, and a path of one component names no member.
268
268
  start = undefined;
269
- } else if (entry.shape === "module") {
269
+ } else if ("module" in entry) {
270
270
  const module = modules.get(entry.module);
271
271
  start = module === undefined ? undefined : memberOf(project, module, first, false);
272
272
  } else if (nameComponent(first) === first) {
@@ -329,14 +329,10 @@ export function entriesAt<Brand>(
329
329
  * program the display name the inventory gives it.
330
330
  */
331
331
  export function spelledEntry(entry: DeclarationEntry, held: Inventory): string {
332
- switch (entry.shape) {
333
- case "symbol":
334
- return held.symbols.find((symbol) => symbol.ref === entry.symbol)?.name ?? entry.symbol;
335
- case "module":
336
- return entry.name;
337
- case "global":
338
- return entry.global;
332
+ if ("symbol" in entry) {
333
+ return held.symbols.find((symbol) => symbol.ref === entry.symbol)?.name ?? entry.symbol;
339
334
  }
335
+ return "module" in entry ? entry.name : entry.global;
340
336
  }
341
337
 
342
338
  /** One entry of a configuration key that names a declaration, and the key's dotted path. */
@@ -353,14 +349,17 @@ const LIFECYCLE_KEY = "ts.lifecycle_contracts";
353
349
  * the injection registrations, each lifecycle contract's components and then its bases,
354
350
  * and the serializers.
355
351
  */
356
- export function configuredDeclarations(config: Config): readonly ConfiguredDeclaration[] {
352
+ export function configuredDeclarations(config: ResolvedConfig): readonly ConfiguredDeclaration[] {
357
353
  return [
358
- ...config.ts.injectionRegistrations.map((entry) => ({
354
+ ...config.ts.injection_registrations.map((entry) => ({
359
355
  key: "ts.injection_registrations",
360
356
  entry,
361
357
  })),
362
- ...config.ts.lifecycleContracts.flatMap((contract) =>
363
- [...contract.components, ...contract.bases].map((entry) => ({ key: LIFECYCLE_KEY, entry })),
358
+ ...config.ts.lifecycle_contracts.flatMap((contract) =>
359
+ [...(contract.components ?? []), ...(contract.bases ?? [])].map((entry) => ({
360
+ key: LIFECYCLE_KEY,
361
+ entry,
362
+ })),
364
363
  ),
365
364
  ...config.ts.serializers.map((entry) => ({ key: "ts.serializers", entry })),
366
365
  ];
@@ -396,12 +395,8 @@ export function declarationsNamed<Brand>(
396
395
  * sign and its name, and a global entry's path after a number sign.
397
396
  */
398
397
  export function configuredRef(entry: DeclarationEntry): string {
399
- switch (entry.shape) {
400
- case "symbol":
401
- return entry.symbol;
402
- case "module":
403
- return `${entry.module}#${entry.name}`;
404
- case "global":
405
- return `#${entry.global}`;
398
+ if ("symbol" in entry) {
399
+ return entry.symbol;
406
400
  }
401
+ return "module" in entry ? `${entry.module}#${entry.name}` : `#${entry.global}`;
407
402
  }
package/src/consumers.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * snapshot, and whose references to the target's declarations count against them.
5
5
  */
6
6
 
7
- import type { Config } from "./config.ts";
7
+ import type { PartialConfig } from "./config.ts";
8
8
  import { consumerProjects } from "./discover.ts";
9
9
  import type { Host } from "./host.ts";
10
10
  import { inventory, packageScope } from "./inventory.ts";
@@ -68,7 +68,7 @@ export function consumerReferences<Brand>(
68
68
  host: Host,
69
69
  targetRoot: string,
70
70
  consumer: ConsumerSide,
71
- config: Config,
71
+ config: PartialConfig,
72
72
  ): readonly Reference[] {
73
73
  const held = inventory(
74
74
  narrowedTo(project, (file) => relativePath(targetRoot, file.fileName) !== undefined),
@@ -76,10 +76,10 @@ export function consumerReferences<Brand>(
76
76
  targetRoot,
77
77
  );
78
78
  const found = references(project, held, targetRoot, {
79
- testFiles: config.ts.testFiles,
79
+ testFiles: config.ts.test_files,
80
80
  consumer,
81
81
  }).references;
82
- if (config.analysis.consumerTests !== "production") {
82
+ if (config.analysis.consumer_tests !== "production") {
83
83
  return found;
84
84
  }
85
85
  return found.map((reference) => (reference.test ? { ...reference, test: false } : reference));