@cplieger/deadset-ts 8.0.0-dev.16 → 8.0.0-dev.17

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 (131) hide show
  1. package/dist/src/alias-chain.js +0 -5
  2. package/dist/src/amd.js +81 -0
  3. package/dist/src/analysis.js +58 -22
  4. package/dist/src/augmentations.js +23 -24
  5. package/dist/src/bindings.js +382 -0
  6. package/dist/src/calls.js +25 -8
  7. package/dist/src/commands/tools.js +5 -9
  8. package/dist/src/component-files.js +3 -2
  9. package/dist/src/conformance-record.js +1 -1
  10. package/dist/src/consumers.js +6 -9
  11. package/dist/src/contextual-uses.js +1 -17
  12. package/dist/src/contract/config.generated.js +4 -1
  13. package/dist/src/contract/report.generated.js +6 -2
  14. package/dist/src/dependencies.js +25 -29
  15. package/dist/src/destructuring.js +1 -19
  16. package/dist/src/element-access.js +179 -164
  17. package/dist/src/entries/build-scripts.js +2 -2
  18. package/dist/src/entries/configuration-files.js +3 -7
  19. package/dist/src/entries/conventions.js +2 -2
  20. package/dist/src/entries/html-entries.js +7 -10
  21. package/dist/src/entries/mdx-entries.js +2 -2
  22. package/dist/src/entries/static-module.js +2 -1
  23. package/dist/src/facts.js +4 -4
  24. package/dist/src/findings/completion.js +40 -4
  25. package/dist/src/{implementations.js → findings/implementations.js} +3 -3
  26. package/dist/src/{in-operands.js → findings/in-operands.js} +2 -2
  27. package/dist/src/framework-lifecycle.js +41 -14
  28. package/dist/src/graph.js +12 -4
  29. package/dist/src/import-bindings.js +73 -28
  30. package/dist/src/index/sites.js +557 -0
  31. package/dist/src/indexed-access.js +523 -478
  32. package/dist/src/interface-satisfaction.js +1 -1
  33. package/dist/src/keyof-comparisons.js +124 -103
  34. package/dist/src/load/expected-module.js +2 -2
  35. package/dist/src/load/specifiers.js +2 -4
  36. package/dist/src/load/synthesize.js +5 -0
  37. package/dist/src/load/workspace-resolution.js +2 -2
  38. package/dist/src/matrix.js +6 -4
  39. package/dist/src/module-declarations.js +70 -85
  40. package/dist/src/overrides.js +134 -112
  41. package/dist/src/paths.js +46 -7
  42. package/dist/src/platform-calls.js +2 -2
  43. package/dist/src/platform-symbols.js +13 -19
  44. package/dist/src/references/read-rule.js +1 -0
  45. package/dist/src/references/read-rules.js +48 -0
  46. package/dist/src/references/sink.js +151 -0
  47. package/dist/src/references/sources.js +450 -0
  48. package/dist/src/references.js +110 -1285
  49. package/dist/src/roots/configured-declarations.js +3 -0
  50. package/dist/src/roots/root-set.js +1 -1
  51. package/dist/src/roots/unseen-loads.js +38 -10
  52. package/dist/src/serialization-contract.js +8 -3
  53. package/dist/src/stores.js +4 -2
  54. package/dist/src/sweep.js +25 -13
  55. package/dist/src/symbol-keys.js +89 -83
  56. package/dist/src/tests/file-class.js +76 -0
  57. package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
  58. package/dist/src/{test-support.js → tests/support.js} +2 -11
  59. package/dist/src/type-parameter-reads.js +178 -139
  60. package/dist/src/unimplemented-callees.js +262 -242
  61. package/dist/src/verbs/analyze.js +3 -3
  62. package/dist/src/verbs/explain.js +50 -28
  63. package/dist/src/verbs/print-retained.js +2 -2
  64. package/jsr.json +1 -1
  65. package/package.json +2 -2
  66. package/src/alias-chain.ts +0 -7
  67. package/src/amd.ts +130 -0
  68. package/src/analysis.ts +86 -23
  69. package/src/augmentations.ts +41 -27
  70. package/src/bindings.ts +460 -0
  71. package/src/calls.ts +25 -7
  72. package/src/commands/tools.ts +5 -11
  73. package/src/component-files.ts +4 -2
  74. package/src/conformance-record.ts +1 -1
  75. package/src/consumers.ts +8 -11
  76. package/src/contextual-uses.ts +2 -22
  77. package/src/contract/config.generated.ts +4 -1
  78. package/src/contract/report.generated.ts +6 -2
  79. package/src/dependencies.ts +27 -28
  80. package/src/destructuring.ts +1 -31
  81. package/src/element-access.ts +188 -182
  82. package/src/entries/build-scripts.ts +2 -2
  83. package/src/entries/configuration-files.ts +11 -8
  84. package/src/entries/conventions.ts +2 -1
  85. package/src/entries/html-entries.ts +15 -14
  86. package/src/entries/mdx-entries.ts +2 -2
  87. package/src/entries/static-module.ts +2 -1
  88. package/src/facts.ts +5 -3
  89. package/src/findings/boundary.ts +2 -0
  90. package/src/findings/completion.ts +43 -4
  91. package/src/findings/emitter.ts +1 -1
  92. package/src/{implementations.ts → findings/implementations.ts} +4 -4
  93. package/src/{in-operands.ts → findings/in-operands.ts} +3 -3
  94. package/src/framework-lifecycle.ts +42 -14
  95. package/src/graph.ts +24 -6
  96. package/src/import-bindings.ts +98 -29
  97. package/src/index/sites.ts +781 -0
  98. package/src/indexed-access.ts +570 -527
  99. package/src/interface-satisfaction.ts +1 -1
  100. package/src/keyof-comparisons.ts +131 -116
  101. package/src/load/expected-module.ts +8 -2
  102. package/src/load/specifiers.ts +8 -5
  103. package/src/load/synthesize.ts +6 -0
  104. package/src/load/workspace-resolution.ts +9 -2
  105. package/src/matrix.ts +6 -3
  106. package/src/module-declarations.ts +74 -98
  107. package/src/overrides.ts +162 -134
  108. package/src/paths.ts +54 -8
  109. package/src/platform-calls.ts +3 -3
  110. package/src/platform-symbols.ts +11 -27
  111. package/src/references/read-rule.ts +60 -0
  112. package/src/references/read-rules.ts +55 -0
  113. package/src/references/sink.ts +213 -0
  114. package/src/references/sources.ts +632 -0
  115. package/src/references.ts +168 -1733
  116. package/src/report.ts +1 -1
  117. package/src/roots/configured-declarations.ts +3 -0
  118. package/src/roots/root-set.ts +1 -1
  119. package/src/roots/unseen-loads.ts +49 -11
  120. package/src/serialization-contract.ts +8 -3
  121. package/src/stores.ts +13 -2
  122. package/src/sweep.ts +37 -14
  123. package/src/symbol-keys.ts +102 -102
  124. package/src/tests/file-class.ts +118 -0
  125. package/src/{outside-tests.ts → tests/outside.ts} +16 -10
  126. package/src/{test-support.ts → tests/support.ts} +9 -20
  127. package/src/type-parameter-reads.ts +187 -158
  128. package/src/unimplemented-callees.ts +297 -280
  129. package/src/verbs/analyze.ts +3 -2
  130. package/src/verbs/explain.ts +74 -31
  131. package/src/verbs/print-retained.ts +2 -2
@@ -1,5 +1,5 @@
1
1
  import { EXIT_CLEAN, EXIT_USAGE } from "../contract/contract.generated.ts";
2
- import { runAnalysis, type RunAnalysis } from "../analysis.ts";
2
+ import { productionMode, runAnalysis, type RunAnalysis } from "../analysis.ts";
3
3
  import { listing } from "../components.ts";
4
4
  import type { Cascade } from "../config.ts";
5
5
  import type { CompletedFinding } from "../finding.ts";
@@ -10,6 +10,8 @@ import { partialNotes } from "../partial.ts";
10
10
  import { resolvePath } from "../paths.ts";
11
11
  import { positionKey } from "../position.ts";
12
12
  import type { Reference } from "../references.ts";
13
+ import type { Mode } from "../sweep.ts";
14
+ import { madeByTestCode, withheldBy } from "../tests/file-class.ts";
13
15
  import { resolve } from "../resolve.ts";
14
16
  import type { Root } from "../roots/root-set.ts";
15
17
  import { type Verb, type VerbOptions } from "./verb.ts";
@@ -141,15 +143,20 @@ type Hop =
141
143
  | { readonly k: "reference"; readonly reference: Reference }
142
144
  | { readonly k: "export"; readonly reference: Reference; readonly to: string };
143
145
 
144
- /** Where a path starts: a root of the run, or a reference a loaded consumer makes. */
146
+ /**
147
+ * Where a path starts: a root of the run, or a reference a loaded consumer or a test file no
148
+ * project holds makes.
149
+ */
145
150
  type Origin =
146
151
  | { readonly k: "root"; readonly root: Root }
147
- | { readonly k: "consumer"; readonly consumer: string };
152
+ | { readonly k: "consumer"; readonly consumer: string }
153
+ | { readonly k: "unheld"; readonly file: string };
148
154
 
149
155
  /**
150
- * The shortest path from a root or a loaded consumer to one declaration, walked breadth first
151
- * from every root at once in the order the run names them, a consumer's reference being the
152
- * first hop of a path of its own, and following the references the sweep follows: a
156
+ * The shortest path from a root, a loaded consumer or a test file no project holds to one
157
+ * declaration, walked breadth first from every root at once in the order the run names them,
158
+ * a reference of a consumer or of such a file being the first hop of a path of its own, as
159
+ * the sweep seeds them, and following the references the sweep follows: a
153
160
  * reference that reads a module reaches what the module exports, and an evaluation or a root
154
161
  * reaches the module alone. Under `production` no reference a test file made is followed,
155
162
  * which is the set the report's sweep counts.
@@ -157,18 +164,26 @@ type Origin =
157
164
  function shortestPath(
158
165
  analysis: RunAnalysis,
159
166
  to: string,
160
- production: boolean,
167
+ mode: Mode,
168
+ support: ReadonlySet<string>,
161
169
  ): { readonly origin: Origin; readonly path: readonly Hop[] } | undefined {
162
170
  const graph = analysis.swept.matrix.union;
163
171
  const out = new Map<string, Reference[]>();
164
- const consumed: (Reference & { readonly consumer: string })[] = [];
172
+ const consumed: { readonly reference: Reference; readonly origin: Origin }[] = [];
165
173
  for (const reference of referencesOf(analysis.configured)) {
166
- if (production && reference.test) {
174
+ if (withheldBy(mode, reference, support)) {
167
175
  continue;
168
176
  }
169
177
  const { consumer } = reference;
170
178
  if (consumer !== undefined) {
171
- consumed.push({ ...reference, consumer });
179
+ consumed.push({ reference, origin: { k: "consumer", consumer } });
180
+ continue;
181
+ }
182
+ if (reference.unheld === true) {
183
+ consumed.push({
184
+ reference,
185
+ origin: { k: "unheld", file: reference.from.replace(/#$/u, "") },
186
+ });
172
187
  continue;
173
188
  }
174
189
  const held = out.get(reference.from);
@@ -210,13 +225,12 @@ function shortestPath(
210
225
  for (const root of rootsOf(analysis.configured)) {
211
226
  enter({ at: root.id, hop: undefined, previous: -1, origin: { k: "root", root } });
212
227
  }
213
- // A consumer's reference is one hop long, so it joins the walk where the roots' first
214
- // hops do.
228
+ // A consumed reference is one hop long, so it joins the walk where the roots' first hops do.
215
229
  const firstHops = steps.length;
216
230
  for (let head = 0; ; head += 1) {
217
231
  if (head === firstHops) {
218
- for (const reference of consumed) {
219
- follow(reference, -1, { k: "consumer", consumer: reference.consumer });
232
+ for (const { reference, origin } of consumed) {
233
+ follow(reference, -1, origin);
220
234
  }
221
235
  }
222
236
  const step = steps[head];
@@ -237,17 +251,35 @@ function shortestPath(
237
251
  return undefined;
238
252
  }
239
253
 
254
+ /** Where a path starts, as a line names it. */
255
+ function originText(origin: Origin): string {
256
+ switch (origin.k) {
257
+ case "root":
258
+ return `root ${origin.root.kind} ${origin.root.id}`;
259
+ case "consumer":
260
+ return `consumer ${origin.consumer}`;
261
+ case "unheld":
262
+ return `test file no project holds ${origin.file}`;
263
+ }
264
+ }
265
+
240
266
  /** What made a reference: a declaration of the target, or a loaded consumer. */
241
267
  function madeBy(reference: Reference): string {
242
268
  return reference.consumer === undefined ? reference.from : `consumer ${reference.consumer}`;
243
269
  }
244
270
 
245
- function referenceLine(reference: Reference, tail: string): string {
246
- return ` reference: ${positionKey(reference.position)}\t${reference.use}\t${tail}${reference.test ? "\tfrom a test file" : ""}\n`;
271
+ /** One reference of an answer, marked where test code made it, a test-support file's included. */
272
+ function referenceLine(reference: Reference, tail: string, support: ReadonlySet<string>): string {
273
+ return ` reference: ${positionKey(reference.position)}\t${reference.use}\t${tail}${madeByTestCode(reference, support) ? "\tfrom a test file" : ""}\n`;
247
274
  }
248
275
 
249
276
  /** Why a declaration no finding names and no exemption held back is live, or how it fell. */
250
- function liveness(analysis: RunAnalysis, subject: InventorySymbol, cascade: Cascade): string {
277
+ function liveness(
278
+ analysis: RunAnalysis,
279
+ subject: InventorySymbol,
280
+ cascade: Cascade,
281
+ mode: Mode,
282
+ ): string {
251
283
  const { sweep } = analysis.swept;
252
284
  const candidate = sweep.candidates.find((one) => one.id === subject.id);
253
285
  if (candidate === undefined && !judged(subject.kind)) {
@@ -258,23 +290,30 @@ function liveness(analysis: RunAnalysis, subject: InventorySymbol, cascade: Casc
258
290
  for (const root of rootsOf(analysis.configured).filter((one) => one.id === subject.id)) {
259
291
  text += ` root: ${root.kind}${root.source === "" ? "" : `\tnamed by ${root.source}`}\n`;
260
292
  }
293
+ const support = new Set(analysis.configured.flatMap((one) => one.supportFiles ?? []));
261
294
  const found =
262
- shortestPath(analysis, subject.id, true) ?? shortestPath(analysis, subject.id, false);
295
+ shortestPath(analysis, subject.id, mode, support) ??
296
+ shortestPath(analysis, subject.id, { production: false }, support);
263
297
  if (found !== undefined && found.path.length > 0) {
264
298
  const { origin } = found;
265
- text += ` reached from: ${origin.k === "root" ? `root ${origin.root.kind} ${origin.root.id}` : `consumer ${origin.consumer}`}\n`;
299
+ text += ` reached from: ${originText(origin)}\n`;
266
300
  for (const hop of found.path) {
267
- text += referenceLine(hop.reference, `${madeBy(hop.reference)} -> ${hop.reference.to}`);
301
+ text += referenceLine(
302
+ hop.reference,
303
+ `${madeBy(hop.reference)} -> ${hop.reference.to}`,
304
+ support,
305
+ );
268
306
  if (hop.k === "export") {
269
307
  text += ` export: ${hop.reference.to} -> ${hop.to}\n`;
270
308
  }
271
309
  }
272
310
  } else if (found === undefined) {
273
311
  const references = referencesOf(analysis.configured).filter((one) => one.to === subject.id);
274
- text += " unreachable: no path of references reaches it from a root or a loaded consumer\n";
312
+ text +=
313
+ " unreachable: no path of references reaches it from a root, a loaded consumer or a test file no project holds\n";
275
314
  text += ` references: ${String(references.length)}\n`;
276
315
  for (const reference of references) {
277
- text += referenceLine(reference, `from ${madeBy(reference)}`);
316
+ text += referenceLine(reference, `from ${madeBy(reference)}`, support);
278
317
  }
279
318
  }
280
319
  if (candidate !== undefined) {
@@ -332,7 +371,12 @@ function namedElsewhere(findings: readonly CompletedFinding[], subject: Inventor
332
371
  }
333
372
 
334
373
  /** The one explanation that applies to a declaration, built whole before it is written. */
335
- function explanation(analysis: RunAnalysis, subject: InventorySymbol, cascade: Cascade): string {
374
+ function explanation(
375
+ analysis: RunAnalysis,
376
+ subject: InventorySymbol,
377
+ cascade: Cascade,
378
+ mode: Mode,
379
+ ): string {
336
380
  const graph = analysis.swept.matrix.union;
337
381
  const at = graph.at(subject.id);
338
382
  let text = `symbol: ${subject.ref}\n`;
@@ -352,7 +396,7 @@ function explanation(analysis: RunAnalysis, subject: InventorySymbol, cascade: C
352
396
  text +=
353
397
  "answer: held\n held by: a question the checker did not answer, which could have kept it live, so no finding names it\n";
354
398
  } else {
355
- text += liveness(analysis, subject, cascade);
399
+ text += liveness(analysis, subject, cascade, mode);
356
400
  }
357
401
  return text + namedElsewhere(analysis.result.findings, subject);
358
402
  }
@@ -361,17 +405,16 @@ function explanation(analysis: RunAnalysis, subject: InventorySymbol, cascade: C
361
405
  * Explains one symbol from the analysis the report is built from: why a reported symbol is
362
406
  * reported, which exemption classes held a retained one back, that an unanswered question held
363
407
  * a held one, and for any other declaration the relations that hold it live and the shortest
364
- * path from a root or a loaded consumer, or the references it has where no path reaches it. A
365
- * request naming no one declaration exits with the usage code and names what partially
366
- * matches it. Where the analysis was partial, the error stream says so.
408
+ * path from a root, a loaded consumer or a test file no project holds, or the references it
409
+ * has where no path reaches it. A request naming no one declaration exits with the usage
410
+ * code and names what partially matches it. Where the analysis was partial, the error stream says so.
367
411
  */
368
412
  export const explainVerb: Verb = ({ out, err, host, inputs, scope, openClient, option }) => {
369
413
  const named = namedSymbol(option);
370
414
  const { config, provenance } = resolve(inputs());
371
415
  const scoped = scope();
372
- const analysis = runAnalysis(openClient(config), host, scoped, config, provenance, {
373
- production: true,
374
- });
416
+ const mode = productionMode(config);
417
+ const analysis = runAnalysis(openClient(config), host, scoped, config, provenance, mode);
375
418
  const { subject, candidates } = subjectOf(analysis.swept.matrix.union.symbols, named);
376
419
  const notes = partialNotes({
377
420
  notBuilt: analysis.run.notBuilt,
@@ -387,7 +430,7 @@ export const explainVerb: Verb = ({ out, err, host, inputs, scope, openClient, o
387
430
  err.write(" no symbol of the target partially matches it either\n");
388
431
  }
389
432
  } else {
390
- out.write(explanation(analysis, subject, config.reporters.cascade));
433
+ out.write(explanation(analysis, subject, config.reporters.cascade, mode));
391
434
  }
392
435
  for (const note of notes) {
393
436
  diagnose(err, note);
@@ -1,5 +1,5 @@
1
1
  import { EXIT_CLEAN } from "../contract/contract.generated.ts";
2
- import { runSweep } from "../analysis.ts";
2
+ import { productionMode, runSweep } from "../analysis.ts";
3
3
  import { retainedLines } from "../exempt.ts";
4
4
  import { partialNotes } from "../partial.ts";
5
5
  import { resolvePath } from "../paths.ts";
@@ -19,7 +19,7 @@ export const printRetainedVerb: Verb = ({ out, err, host, inputs, scope, openCli
19
19
  const scoped = scope();
20
20
  const swept = runSweep(openClient(config), host, scoped, config, {
21
21
  marked: [],
22
- mode: { production: true },
22
+ mode: productionMode(config),
23
23
  });
24
24
  for (const line of retainedLines(swept.matrix.union.symbols, swept.retained)) {
25
25
  out.write(`${line}\n`);