@cplieger/deadset-ts 7.0.0-dev.1 → 7.0.0-dev.3

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 (113) hide show
  1. package/dist/src/analysis.js +95 -60
  2. package/dist/src/augmentations.js +14 -12
  3. package/dist/src/component-layer.js +1 -1
  4. package/dist/src/components.js +62 -20
  5. package/dist/src/configuration-files.js +230 -30
  6. package/dist/src/conformance-record.js +1 -1
  7. package/dist/src/contextual-uses.js +104 -13
  8. package/dist/src/convention-rows.js +10 -0
  9. package/dist/src/conventions.js +35 -1
  10. package/dist/src/dependencies.js +90 -32
  11. package/dist/src/discover.js +1 -1
  12. package/dist/src/edges.js +1 -1
  13. package/dist/src/element-access.js +341 -0
  14. package/dist/src/erased-stores.js +317 -0
  15. package/dist/src/exempt-classes.js +9 -22
  16. package/dist/src/exempt.js +3 -15
  17. package/dist/src/findings/completion.js +78 -16
  18. package/dist/src/findings/dependencies-and-module-machinery.js +1 -1
  19. package/dist/src/findings/emitters.js +1 -5
  20. package/dist/src/findings/self-check.js +27 -10
  21. package/dist/src/findings-pass.js +6 -5
  22. package/dist/src/in-operands.js +30 -0
  23. package/dist/src/indexed-access.js +264 -119
  24. package/dist/src/intra-function-parts.js +25 -11
  25. package/dist/src/inventory.js +28 -12
  26. package/dist/src/keyof-comparisons.js +170 -0
  27. package/dist/src/kinds.js +17 -7
  28. package/dist/src/manifest.js +6 -16
  29. package/dist/src/matrix.js +20 -2
  30. package/dist/src/query.js +3 -0
  31. package/dist/src/references.js +14 -3
  32. package/dist/src/report.js +4 -1
  33. package/dist/src/reporters/sarif.js +4 -0
  34. package/dist/src/roots.js +0 -1
  35. package/dist/src/run.js +0 -2
  36. package/dist/src/schema.js +1 -1
  37. package/dist/src/scope.js +2 -2
  38. package/dist/src/serialization-contract.js +43 -14
  39. package/dist/src/session.js +12 -8
  40. package/dist/src/suppress-file.js +58 -6
  41. package/dist/src/suppress-inline.js +14 -5
  42. package/dist/src/suppress.js +64 -35
  43. package/dist/src/unimplemented-callees.js +312 -0
  44. package/dist/src/value-reach.js +7 -7
  45. package/dist/src/verbs/analyze.js +11 -9
  46. package/dist/src/workspace-programs.js +0 -3
  47. package/dist/src/workspace-resolution.js +0 -2
  48. package/dist/src/workspace.js +0 -3
  49. package/jsr.json +1 -1
  50. package/package.json +3 -2
  51. package/src/analysis.ts +145 -82
  52. package/src/augmentations.ts +14 -11
  53. package/src/calls.ts +3 -3
  54. package/src/component-files.ts +7 -7
  55. package/src/component-layer.ts +2 -2
  56. package/src/components.ts +104 -22
  57. package/src/config.ts +4 -4
  58. package/src/configuration-files.ts +250 -31
  59. package/src/conformance-record.ts +1 -1
  60. package/src/contextual-uses.ts +135 -17
  61. package/src/convention-rows.ts +23 -0
  62. package/src/conventions.ts +53 -1
  63. package/src/dependencies.ts +119 -38
  64. package/src/discover.ts +3 -3
  65. package/src/edges.ts +3 -3
  66. package/src/element-access.ts +446 -0
  67. package/src/entry-points.ts +1 -1
  68. package/src/erased-stores.ts +413 -0
  69. package/src/exempt-classes.ts +10 -24
  70. package/src/exempt.ts +5 -29
  71. package/src/file-facts.ts +3 -1
  72. package/src/finding.ts +3 -1
  73. package/src/findings/completion.ts +97 -21
  74. package/src/findings/dependencies-and-module-machinery.ts +1 -1
  75. package/src/findings/emitters.ts +4 -9
  76. package/src/findings/self-check.ts +31 -14
  77. package/src/findings-pass.ts +14 -7
  78. package/src/graph.ts +2 -2
  79. package/src/html-entries.ts +1 -1
  80. package/src/in-operands.ts +45 -0
  81. package/src/indexed-access.ts +303 -137
  82. package/src/intra-function-parts.ts +41 -16
  83. package/src/inventory.ts +37 -33
  84. package/src/json-document.ts +1 -1
  85. package/src/keyof-comparisons.ts +211 -0
  86. package/src/kinds.ts +20 -7
  87. package/src/manifest.ts +7 -22
  88. package/src/matrix.ts +34 -2
  89. package/src/namespace-objects.ts +1 -1
  90. package/src/pnpm-workspace.ts +1 -1
  91. package/src/query.ts +10 -0
  92. package/src/references.ts +30 -7
  93. package/src/report.ts +11 -5
  94. package/src/reporters/sarif.ts +4 -0
  95. package/src/roots.ts +0 -3
  96. package/src/run.ts +0 -2
  97. package/src/schema.ts +2 -2
  98. package/src/scope.ts +2 -2
  99. package/src/serialization-contract.ts +53 -14
  100. package/src/session.ts +34 -31
  101. package/src/stores.ts +1 -1
  102. package/src/suppress-file.ts +68 -5
  103. package/src/suppress-inline.ts +17 -7
  104. package/src/suppress.ts +79 -47
  105. package/src/template-field.ts +1 -1
  106. package/src/unimplemented-callees.ts +411 -0
  107. package/src/value-reach.ts +12 -8
  108. package/src/verbs/analyze.ts +15 -9
  109. package/src/verbs/verb.ts +1 -4
  110. package/src/workspace-programs.ts +2 -9
  111. package/src/workspace-resolution.ts +0 -3
  112. package/src/workspace-run.ts +1 -1
  113. package/src/workspace.ts +1 -9
package/src/analysis.ts CHANGED
@@ -1,11 +1,9 @@
1
1
  /**
2
- * One run's passes, composed: the projects discovery names, opened in one snapshot
3
- * of one client, each read through the stages in the order they depend on each
4
- * other, and the per-project answers merged into the answer for the run.
5
- *
6
- * The stages take a project's view, which only this composition makes: a view
7
- * carries a project's identity in its type so a handle cannot cross to another
8
- * project's checker, and that holds only for views the session itself hands out.
2
+ * One run's passes, composed: the projects discovery names, opened in one snapshot of one
3
+ * client, each read through the stages in dependency order, and the per-project answers
4
+ * merged into the run's. The stages take a project's view, which only this composition
5
+ * makes: a view carries a project's identity in its type so a handle cannot cross to
6
+ * another project's checker, which holds only for views the session hands out.
9
7
  */
10
8
 
11
9
  import { lineOf, readComponent } from "./component-files.ts";
@@ -40,10 +38,12 @@ import {
40
38
  readConventions,
41
39
  type AppliedConvention,
42
40
  type ConventionManifest,
41
+ type Conventions,
43
42
  } from "./conventions.ts";
44
43
  import { readEdgeSides } from "./edges.ts";
45
44
  import { enumGroup } from "./enum-group.ts";
46
45
  import { generatedFile, generatedFilesOf } from "./generated-file.ts";
46
+ import { inOperandNames } from "./in-operands.ts";
47
47
  import { sourceFilesOf } from "./source-files.ts";
48
48
  import {
49
49
  evidenceRecords,
@@ -62,11 +62,7 @@ import { globExpression } from "./glob.ts";
62
62
  import type { Finding } from "./finding.ts";
63
63
  import { findingsPass, recordedFindings, rowKey, type PassResult } from "./findings-pass.ts";
64
64
  import type { EmitterInput } from "./findings/emitter.ts";
65
- import {
66
- NO_SELF_CHECK,
67
- unmatchedRootFindings,
68
- type SelfCheckFacts,
69
- } from "./findings/self-check.ts";
65
+ import { unmatchedRootFindings, type SelfCheckFacts } from "./findings/self-check.ts";
70
66
  import { frameworkLifecycle } from "./framework-lifecycle.ts";
71
67
  import type { Host } from "./host.ts";
72
68
  import { implementations, mergeImplementations } from "./implementations.ts";
@@ -98,13 +94,26 @@ import {
98
94
  } from "./type-errors.ts";
99
95
  import { reflectiveLookup } from "./reflective-lookup.ts";
100
96
  import { references, testFileRulesOf, type Reference, type TestFileRule } from "./references.ts";
101
- import { roots, unmatchedEverywhere, type RootKind, type Roots } from "./roots.ts";
97
+ import {
98
+ roots,
99
+ unmatchedEverywhere,
100
+ type RootKind,
101
+ type RootOptions,
102
+ type Roots,
103
+ } from "./roots.ts";
102
104
  import type { Scope } from "./scope.ts";
103
105
  import { serializationContract } from "./serialization-contract.ts";
104
106
  import { outsideTestReferences, testFilesAt, type OutsideTest } from "./outside-tests.ts";
105
107
  import { joinedTestFiles, withJoinedTests } from "./test-joins.ts";
106
108
  import { supportReferences, testSupportFiles } from "./test-support.ts";
107
- import { diagnosticsOf, ownedAs, runSession, type Engine, type ProjectView } from "./session.ts";
109
+ import {
110
+ diagnosticsOf,
111
+ ownedAs,
112
+ runSession,
113
+ type Engine,
114
+ type OpenedFiles,
115
+ type ProjectView,
116
+ } from "./session.ts";
108
117
  import { accessorsOf, storesOf } from "./stores.ts";
109
118
  import { isPartKind, type SuppressionRecord, type Suppressions, type Verdict } from "./suppress.ts";
110
119
  import { bindRows, readBaseline, readIgnoreFile, type Recorded } from "./suppress-file.ts";
@@ -194,6 +203,8 @@ interface ProjectRead {
194
203
  readonly skipped: readonly SkippedUnit[];
195
204
  /** The project's generated files, by path below the target root, each with the detail its retentions name. */
196
205
  readonly generated: ReadonlyMap<string, string>;
206
+ /** The files, absolute, an applied convention row names as test files. */
207
+ readonly testFileNames: ReadonlySet<string>;
197
208
  }
198
209
 
199
210
  /** One target project the run analyzes, as its stage is handed it. */
@@ -227,32 +238,73 @@ interface ReadProjects<Answer> {
227
238
  readonly conventionUses: readonly string[];
228
239
  /** The directory of every workspace member, absolute. */
229
240
  readonly memberDirs: readonly string[];
241
+ /** The directory of every nested package, absolute. */
242
+ readonly nestedDirs: readonly string[];
230
243
  /** The test files below the target root no project the run reads holds, parsed. */
231
244
  readonly outsideTests: readonly OutsideTest[];
232
245
  }
233
246
 
234
247
  /**
235
248
  * The manifests the analysis reads, each once: the target's own, then every workspace
236
- * member's below the target root.
249
+ * member's and every nested package's below the target root.
237
250
  */
238
251
  function conventionManifests(
239
252
  host: Host,
240
253
  targetRoot: string,
241
254
  memberDirs: readonly string[],
255
+ nestedDirs: readonly string[],
242
256
  ): readonly ConventionManifest[] {
243
257
  const found = new Map<string, ConventionManifest>();
244
258
  if (host.kindOf(joinPath(targetRoot, "package.json")) === "file") {
245
259
  found.set(targetRoot, { dir: targetRoot, path: "package.json" });
246
260
  }
247
- for (const dir of memberDirs) {
248
- const below = relativePath(targetRoot, dir);
249
- if (below !== undefined && !found.has(dir)) {
250
- found.set(dir, { dir, path: `${below}/package.json` });
261
+ for (const [dirs, nested] of [
262
+ [memberDirs, false],
263
+ [nestedDirs, true],
264
+ ] as const) {
265
+ for (const dir of dirs) {
266
+ const below = relativePath(targetRoot, dir);
267
+ if (below !== undefined && !found.has(dir)) {
268
+ found.set(dir, { dir, path: `${below}/package.json`, nested });
269
+ }
251
270
  }
252
271
  }
253
272
  return [...found.values()];
254
273
  }
255
274
 
275
+ /**
276
+ * The nested packages of a run: each directory below the target root, in no `node_modules`
277
+ * directory and none of `known`, that holds a `package.json` and lies at or above one of
278
+ * `files`, the program's source files and the compiler configuration files, in path order.
279
+ */
280
+ function nestedPackageDirs(
281
+ host: Host,
282
+ targetRoot: string,
283
+ files: Iterable<string>,
284
+ known: ReadonlySet<string>,
285
+ ): readonly string[] {
286
+ const seen = new Set<string>();
287
+ const found: string[] = [];
288
+ for (const file of files) {
289
+ for (
290
+ let dir = dirnamePath(file);
291
+ dir !== targetRoot && !seen.has(dir) && relativePath(targetRoot, dir) !== undefined;
292
+ dir = dirnamePath(dir)
293
+ ) {
294
+ seen.add(dir);
295
+ const below = relativePath(targetRoot, dir) ?? "";
296
+ if (
297
+ !below.split("/").includes("node_modules") &&
298
+ !known.has(dir) &&
299
+ host.kindOf(joinPath(dir, "package.json")) === "file"
300
+ ) {
301
+ found.push(dir);
302
+ }
303
+ }
304
+ }
305
+ return found.sort(compare);
306
+ }
307
+
256
308
  /**
257
309
  * Reads every project the scope discovers, and each declared consumer's, in one snapshot,
258
310
  * each checked for errors first. `stage` is handed a target project and enumerates and roots
@@ -270,6 +322,12 @@ function readProjects<Answer>(
270
322
  ): ReadProjects<Answer> {
271
323
  const targetRoot = scope.target.path;
272
324
  const discovered = discoverProjects(engine, host, scope, config.analysis.configurations);
325
+ if (discovered.configFiles.length === 0 && discovered.notBuilt.length === 0) {
326
+ throw new DiscoveryError(
327
+ `${targetRoot} holds no compiler configuration, so the run holds no program`,
328
+ [],
329
+ );
330
+ }
273
331
  const ids = new Map(discovered.projects.map((project) => [project.configFile, project.id]));
274
332
  const loads = consumerLoads(engine, host, scope, discovered.configFiles);
275
333
  const consumerOf = new Map(
@@ -285,33 +343,45 @@ function readProjects<Answer>(
285
343
  discovered.configFiles,
286
344
  readManifest(host, targetRoot),
287
345
  );
288
- const conventions = readConventions(
289
- host,
290
- (fileName, text) => engine.parseSourceFile(fileName, text),
291
- conventionManifests(host, absoluteRoot, workspace?.memberDirs ?? []),
292
- config.ts.disabledConventions,
293
- );
294
- const options = {
295
- host,
296
- manifest: workspace?.manifest ?? readManifest(host, targetRoot),
297
- otherPackages: [
298
- ...(workspace?.entries ?? []),
299
- ...packageEntries(
300
- host,
301
- normalizePath(absoluteRoot),
302
- discovered.configFiles,
303
- new Set(workspace?.memberDirs ?? []),
346
+ const parse = (fileName: string, text: string) => engine.parseSourceFile(fileName, text);
347
+ const memberDirs = workspace?.memberDirs ?? [];
348
+ // The nested packages are known only once every program is open, and every visit reads
349
+ // the conventions and options they decide, so both are set in the session's first step.
350
+ let nestedDirs: readonly string[] = [];
351
+ let conventions = readConventions(host, parse, [], config.ts.disabledConventions);
352
+ let options: RootOptions & { readonly parse: typeof parse; readonly conventions: Conventions };
353
+ const readManifests = (opened: readonly OpenedFiles[]): void => {
354
+ nestedDirs = nestedPackageDirs(
355
+ host,
356
+ normalizePath(absoluteRoot),
357
+ opened
358
+ .filter((one) => !consumerOf.has(one.configFile))
359
+ .flatMap((one) => [one.configFile, ...one.fileNames()]),
360
+ new Set(memberDirs),
361
+ );
362
+ conventions = readConventions(
363
+ host,
364
+ parse,
365
+ conventionManifests(host, absoluteRoot, memberDirs, nestedDirs),
366
+ config.ts.disabledConventions,
367
+ );
368
+ options = {
369
+ host,
370
+ manifest: workspace?.manifest ?? readManifest(host, targetRoot),
371
+ otherPackages: [
372
+ ...(workspace?.entries ?? []),
373
+ ...packageEntries(host, normalizePath(absoluteRoot), nestedDirs),
374
+ ],
375
+ patterns: config.rootPatterns,
376
+ entryFiles: config.ts.entryFiles,
377
+ conventions,
378
+ testFiles: config.ts.testFiles,
379
+ parse,
380
+ publishedAPI: config.targetKind === "library",
381
+ publishedMembers: new Set(
382
+ (workspace?.entries ?? []).filter((entry) => entry.published).map((entry) => entry.dir),
304
383
  ),
305
- ],
306
- patterns: config.rootPatterns,
307
- entryFiles: config.ts.entryFiles,
308
- conventions,
309
- testFiles: config.ts.testFiles,
310
- parse: (fileName: string, text: string) => engine.parseSourceFile(fileName, text),
311
- publishedAPI: config.targetKind === "library",
312
- publishedMembers: new Set(
313
- (workspace?.entries ?? []).filter((entry) => entry.published).map((entry) => entry.dir),
314
- ),
384
+ };
315
385
  };
316
386
  const notBuilt: NotBuilt[] = [...discovered.notBuilt];
317
387
  const dropped = (configFile: string, error: string): void => {
@@ -460,6 +530,7 @@ function readProjects<Answer>(
460
530
  .filter((file) => referenceOnly(file.fileName))
461
531
  .flatMap((file) => relativePath(absoluteRoot, file.fileName) ?? []),
462
532
  generated: generatedFilesOf(own, generatedFiles(conventions, own)),
533
+ testFileNames: conventions.testFiles,
463
534
  };
464
535
  };
465
536
  for (const file of project.ownSourceFiles()) {
@@ -478,9 +549,10 @@ function readProjects<Answer>(
478
549
  sourcePaths(host, targetRoot).filter(
479
550
  (path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path)),
480
551
  ),
481
- options.parse,
552
+ parse,
482
553
  );
483
554
  },
555
+ readManifests,
484
556
  );
485
557
  for (const configFile of session.unopened) {
486
558
  if (consumerOf.has(configFile) || !isGuess(discovered, configFile)) {
@@ -519,7 +591,8 @@ function readProjects<Answer>(
519
591
  componentsUnread: workspace?.componentsUnread ?? [],
520
592
  conventionsApplied: conventions.applied,
521
593
  conventionUses: conventions.uses,
522
- memberDirs: workspace?.memberDirs ?? [],
594
+ memberDirs,
595
+ nestedDirs,
523
596
  outsideTests,
524
597
  };
525
598
  }
@@ -649,7 +722,7 @@ export interface ComponentWarning {
649
722
  }
650
723
 
651
724
  /** The exemption classes this analyzer detects, each by its detector; any other retains nothing. */
652
- const DETECTORS: Detectors = new Map<TSExemptionClass, Detector>([
725
+ export const DETECTORS: Detectors = new Map<TSExemptionClass, Detector>([
653
726
  ["interface-satisfaction", interfaceSatisfaction],
654
727
  ["enum-group", enumGroup],
655
728
  ["generated-file", generatedFile],
@@ -708,6 +781,8 @@ interface ReadRun<Extra> {
708
781
  readonly conventionUses: readonly string[];
709
782
  /** The directory of every workspace member, absolute. */
710
783
  readonly memberDirs: readonly string[];
784
+ /** The directory of every nested package, absolute. */
785
+ readonly nestedDirs: readonly string[];
711
786
  }
712
787
 
713
788
  /**
@@ -727,6 +802,7 @@ function readRun<Extra>(
727
802
  project: ProjectView<Brand>,
728
803
  read: ProjectRead,
729
804
  references: readonly Reference[],
805
+ testFiles: readonly string[],
730
806
  ) => Extra,
731
807
  ): ReadRun<Extra> {
732
808
  const targetRoot = scope.target.path;
@@ -739,6 +815,7 @@ function readRun<Extra>(
739
815
  const projectRead = opened.read();
740
816
  const resolved = references(project, projectRead.held, targetRoot, {
741
817
  testFiles: config.ts.testFiles,
818
+ testFileNames: projectRead.testFileNames,
742
819
  });
743
820
  const evidence = evidenceRecords(
744
821
  {
@@ -771,7 +848,7 @@ function readRun<Extra>(
771
848
  reason: warning.reason,
772
849
  })),
773
850
  ),
774
- extra: extra(project, projectRead, resolved.references),
851
+ extra: extra(project, projectRead, resolved.references, resolved.testFilePaths),
775
852
  };
776
853
  });
777
854
  const outsidePaths = read.outsideTests.map((one) => one.path);
@@ -799,7 +876,6 @@ function readRun<Extra>(
799
876
  const { projectRead } = one;
800
877
  const satisfied = settled[index];
801
878
  const detected = heldRecords(satisfied?.evidence ?? one.evidence, {
802
- disabled,
803
879
  mode,
804
880
  testFiles: new Set([...one.testFiles, ...support]),
805
881
  });
@@ -817,6 +893,9 @@ function readRun<Extra>(
817
893
  ...(projectRead.referenceOnly.length === 0
818
894
  ? {}
819
895
  : { referenceOnly: projectRead.referenceOnly }),
896
+ ...(projectRead.held.dependents.size === 0
897
+ ? {}
898
+ : { dependents: projectRead.held.dependents }),
820
899
  };
821
900
  return {
822
901
  configFile: projectRead.configFile,
@@ -866,6 +945,7 @@ function readRun<Extra>(
866
945
  conventionsApplied: read.conventionsApplied,
867
946
  conventionUses: read.conventionUses,
868
947
  memberDirs: read.memberDirs,
948
+ nestedDirs: read.nestedDirs,
869
949
  };
870
950
  }
871
951
 
@@ -1011,14 +1091,12 @@ function sweptOf<Extra>(
1011
1091
  }
1012
1092
 
1013
1093
  /**
1014
- * Sweeps the run the scope and the configuration describe. Each project's references
1015
- * and exemptions are read against its own inventory while its view is open; the
1016
- * projects then merge into one matrix in the run's order, which is swept under the
1017
- * caller's marks and mode with the exemptions every project found. A record found in
1018
- * one configuration holds in every configuration that holds its declaration, because
1019
- * an exemption is evidence of a use the analysis cannot see and a use in one
1020
- * configuration is a use. A project that carries an error ends the run before any
1021
- * project is swept.
1094
+ * Sweeps the run the scope and the configuration describe. Each project's references and
1095
+ * exemptions are read against its own inventory while its view is open; the projects then
1096
+ * merge into one matrix in run order, swept under the caller's marks and mode with every
1097
+ * project's exemptions. A record found in one configuration holds in every configuration
1098
+ * that holds its declaration, because an exemption evidences a use the analysis cannot see.
1099
+ * A project that carries an error ends the run before any project is swept.
1022
1100
  */
1023
1101
  export function runSweep(
1024
1102
  engine: Engine,
@@ -1042,6 +1120,7 @@ interface EmitterExtra {
1042
1120
  readonly implementations: ReturnType<typeof implementations>;
1043
1121
  readonly heldByInclusion: readonly string[];
1044
1122
  readonly generated: readonly string[];
1123
+ readonly inOperands: readonly string[];
1045
1124
  readonly rooted: Roots;
1046
1125
  readonly directives: readonly InlineDirective[];
1047
1126
  readonly declarationsNamed: readonly boolean[];
@@ -1049,7 +1128,7 @@ interface EmitterExtra {
1049
1128
  }
1050
1129
 
1051
1130
  /** Reads a run's projects with every per-project fact an emitter reads. */
1052
- function readEmitterRun(
1131
+ export function readEmitterRun(
1053
1132
  engine: Engine,
1054
1133
  host: Host,
1055
1134
  scope: Scope,
@@ -1065,7 +1144,7 @@ function readEmitterRun(
1065
1144
  config,
1066
1145
  mode,
1067
1146
  detectors,
1068
- (project, read, references) => ({
1147
+ (project, read, references, testFiles) => ({
1069
1148
  deprecation: deprecatedDeclarations(project, read.held),
1070
1149
  accessors: accessorsOf(project, read.held),
1071
1150
  needs: projectNeeds(project, read.held, host, targetRoot, (fileName, text) =>
@@ -1074,6 +1153,7 @@ function readEmitterRun(
1074
1153
  implementations: implementations(project, read.held),
1075
1154
  heldByInclusion: heldByInclusion(project, targetRoot),
1076
1155
  generated: [...read.generated.keys()],
1156
+ inOperands: inOperandNames(project, targetRoot, testFiles),
1077
1157
  rooted: read.rooted,
1078
1158
  directives: inlineDirectives(project, read.held, targetRoot).filter(
1079
1159
  (directive) => !read.referenceOnly.includes(directive.site.path),
@@ -1135,7 +1215,7 @@ function nearestManifestDir(host: Host, root: string, file: string): string {
1135
1215
  * The input every emitter reads over one sweep of a read run: the facts beside the sweep
1136
1216
  * each kind family reads, every per-project one read in the same session as the sweep.
1137
1217
  */
1138
- function emitterInputOver(
1218
+ export function emitterInputOver(
1139
1219
  host: Host,
1140
1220
  scope: Scope,
1141
1221
  config: Config,
@@ -1166,12 +1246,14 @@ function emitterInputOver(
1166
1246
  swept.sweep.candidates.map((candidate) => candidate.id),
1167
1247
  members.read,
1168
1248
  members.unbuilt,
1249
+ read.nestedDirs,
1169
1250
  ),
1170
1251
  implementations: mergeImplementations(projects.map((one) => one.extra.implementations)),
1171
1252
  files: {
1172
1253
  tree: sourceTree(host, targetRoot),
1173
1254
  heldByInclusion: new Set(projects.flatMap((one) => one.extra.heldByInclusion)),
1174
1255
  generated: new Set(projects.flatMap((one) => one.extra.generated)),
1256
+ inOperands: new Set(projects.flatMap((one) => one.extra.inOperands)),
1175
1257
  },
1176
1258
  boundary: {
1177
1259
  consumers: {
@@ -1190,25 +1272,6 @@ function emitterInputOver(
1190
1272
  };
1191
1273
  }
1192
1274
 
1193
- /**
1194
- * What every emitter reads of the run the scope and the configuration describe, swept
1195
- * under the caller's marks: the run's sweep, the facts beside it each kind family reads,
1196
- * and the sides of the target's declared cross-language edges that name a symbol of this
1197
- * language. The run reads no suppression document, so the self-check family has nothing
1198
- * to report.
1199
- */
1200
- export function runEmitterInput(
1201
- engine: Engine,
1202
- host: Host,
1203
- scope: Scope,
1204
- config: Config,
1205
- input: Pick<SweepInput, "marked" | "mode">,
1206
- detectors: Detectors = DETECTORS,
1207
- ): EmitterInput {
1208
- const read = readEmitterRun(engine, host, scope, config, input.mode, detectors);
1209
- return emitterInputOver(host, scope, config, read, input, NO_SELF_CHECK);
1210
- }
1211
-
1212
1275
  /** One run read for its findings: the input swept with and without its suppressions' marks. */
1213
1276
  export interface AnalysisInputs {
1214
1277
  /** The run swept under the marks of every bound suppression record. */
@@ -1338,7 +1401,7 @@ export interface RunProject {
1338
1401
  }
1339
1402
 
1340
1403
  /** What a report states about the run beside its findings. */
1341
- export interface RunFacts {
1404
+ interface RunFacts {
1342
1405
  /** The projects the run analyzed, in the run's order. */
1343
1406
  readonly projects: readonly RunProject[];
1344
1407
  /** The rules that classified files as test files, each counted over every project at once. */
@@ -1360,7 +1423,7 @@ export interface RunFacts {
1360
1423
  }
1361
1424
 
1362
1425
  /** One configuration whose component files a run cannot read. */
1363
- export interface ComponentsUnread {
1426
+ interface ComponentsUnread {
1364
1427
  readonly configFile: string;
1365
1428
  readonly reason: string;
1366
1429
  }
@@ -1,9 +1,10 @@
1
1
  /**
2
- * The references a use of an augmentation's declaration makes to what holds it. No name
3
- * spells a `declare global` block, so a use of a declaration it holds is a use of the
4
- * block. An interface or namespace an augmentation block holds merges with the one of its
5
- * name, which the language or a library may type a value by where the target never names
6
- * it, as it types `import.meta` or `process.env`, so a use of its member is a use of it.
2
+ * The references a use of an augmentation's declaration makes to what holds it. A use of
3
+ * a declaration a `declare global` block or a module declaration holds is a use of the
4
+ * block, which no name spells or no import may name. An interface or namespace such a
5
+ * block, or the top level of a file that is no module, holds merges with the one of its
6
+ * name, which the language or a library types values by where the target never names it,
7
+ * as `import.meta` or `process.env`, so a use of its member is a use of it.
7
8
  */
8
9
 
9
10
  import type { Inventory, InventorySymbol } from "./inventory.ts";
@@ -24,19 +25,21 @@ function isGlobalBlock(
24
25
  }
25
26
 
26
27
  /**
27
- * For each reference to a declaration an augmentation block holds, a read at the same place
28
- * of every interface and namespace between it and the block, and of a `declare global` block
29
- * itself.
28
+ * For each reference to a declaration an augmentation block, or the global scope of a
29
+ * file in `scripts`, holds, a read at the same place of every interface and namespace
30
+ * between it and the block or the file, and of the block itself. `scripts` holds the
31
+ * files that are no module, by identifier.
30
32
  */
31
33
  export function augmentationReferences(
32
34
  held: Inventory,
33
35
  found: readonly Reference[],
36
+ scripts: ReadonlySet<string> = new Set(),
34
37
  ): readonly Reference[] {
35
38
  const files = new Set(held.symbols.filter((one) => one.kind === "file").map((one) => one.id));
36
39
  const globals = new Set(
37
40
  held.symbols.filter((one) => isGlobalBlock(one, held, files)).map((one) => one.id),
38
41
  );
39
- if (globals.size === 0 && held.modules.size === 0) {
42
+ if (globals.size === 0 && held.modules.size === 0 && scripts.size === 0) {
40
43
  return [];
41
44
  }
42
45
  const byId = new Map(held.symbols.map((one) => [one.id, one]));
@@ -47,10 +50,10 @@ export function augmentationReferences(
47
50
  at !== undefined;
48
51
  at = byId.get(at.parent)
49
52
  ) {
50
- if (globals.has(at.id)) {
53
+ if (globals.has(at.id) || held.modules.has(at.id)) {
51
54
  return [...ids, at.id];
52
55
  }
53
- if (held.modules.has(at.id)) {
56
+ if (scripts.has(at.id)) {
54
57
  return ids;
55
58
  }
56
59
  if (at.kind === "interface" || at.kind === "namespace") {
package/src/calls.ts CHANGED
@@ -30,7 +30,7 @@ import { must } from "./query.ts";
30
30
  import type { ProjectView } from "./session.ts";
31
31
 
32
32
  /** One value written where a call passes it, and the node its declaration is resolved from. */
33
- export interface PassedValue {
33
+ interface PassedValue {
34
34
  /** Where the value is written, which is where a record of it sits. */
35
35
  readonly site: Node;
36
36
  /** The name the value is resolved through, or the shorthand assignment that holds it. */
@@ -39,7 +39,7 @@ export interface PassedValue {
39
39
  }
40
40
 
41
41
  /** One class of the target a call passes or a decorator is attached to, and where. */
42
- export interface ClassUse {
42
+ interface ClassUse {
43
43
  /** The inventory's identifier of the class. */
44
44
  readonly id: string;
45
45
  readonly site: Node;
@@ -182,7 +182,7 @@ export function classesPassed<Brand>(
182
182
  }
183
183
 
184
184
  /** One class declaration of the target and the decorators written on it. */
185
- export interface DecoratedClass {
185
+ interface DecoratedClass {
186
186
  readonly id: string;
187
187
  readonly decorators: readonly Decorator[];
188
188
  }
@@ -7,10 +7,10 @@
7
7
  */
8
8
 
9
9
  /** The language one block is written in, as the module's virtual extension spells it. */
10
- export type BlockLanguage = "ts" | "tsx" | "js" | "jsx";
10
+ type BlockLanguage = "ts" | "tsx" | "js" | "jsx";
11
11
 
12
12
  /** One block the module holds, the frontmatter included. */
13
- export interface Block {
13
+ interface Block {
14
14
  /** The offset the block's markup starts at: the `<` of its start tag, or 0 for frontmatter. */
15
15
  readonly tagStart: number;
16
16
  readonly contentStart: number;
@@ -20,7 +20,7 @@ export interface Block {
20
20
  }
21
21
 
22
22
  /** One file a `<script src>` element names, which the module imports whole. */
23
- export interface SourceImport {
23
+ interface SourceImport {
24
24
  /** The specifier the module imports, relative to the component file. */
25
25
  readonly specifier: string;
26
26
  /** The offsets of the `src` attribute, name and value. */
@@ -29,14 +29,14 @@ export interface SourceImport {
29
29
  }
30
30
 
31
31
  /** A `<script` start tag beginning a line that the module holds no block for. */
32
- export interface ComponentWarning {
32
+ interface ComponentWarning {
33
33
  /** The offset of the tag's `<`. */
34
34
  readonly offset: number;
35
35
  readonly reason: string;
36
36
  }
37
37
 
38
38
  /** One run of markup an expression or an attribute value is written in. */
39
- export interface MarkupAction {
39
+ interface MarkupAction {
40
40
  /** The offset of the run's first code unit. */
41
41
  readonly start: number;
42
42
  readonly text: string;
@@ -45,7 +45,7 @@ export interface MarkupAction {
45
45
  }
46
46
 
47
47
  /** What one component file's text is read as. */
48
- export interface ComponentFile {
48
+ interface ComponentFile {
49
49
  readonly blocks: readonly Block[];
50
50
  readonly imports: readonly SourceImport[];
51
51
  readonly warnings: readonly ComponentWarning[];
@@ -54,7 +54,7 @@ export interface ComponentFile {
54
54
  }
55
55
 
56
56
  /** The module the compiler reads in place of one component file. */
57
- export interface ComponentModule {
57
+ interface ComponentModule {
58
58
  /** The module's text: the file's length, then what the module appends. */
59
59
  readonly text: string;
60
60
  /** The virtual extension: the strongest language any block names, `.ts` for none. */
@@ -11,10 +11,10 @@ import type { Host } from "./host.ts";
11
11
  import { dirnamePath, joinPath } from "./paths.ts";
12
12
 
13
13
  /** The name the mapper's manifest declares and every configuration's entry names. */
14
- export const MAPPER_PACKAGE = "deadset-ts-component-files";
14
+ const MAPPER_PACKAGE = "deadset-ts-component-files";
15
15
 
16
16
  /** The file system one snapshot is created with. */
17
- export type SnapshotFileSystem = NonNullable<CreateSnapshotParams["fileSystem"]>;
17
+ type SnapshotFileSystem = NonNullable<CreateSnapshotParams["fileSystem"]>;
18
18
 
19
19
  /** The manifest of the mapper's package, which runs `command`. */
20
20
  export function mapperManifest(command: readonly string[]): string {