@cplieger/deadset-ts 8.0.0-dev.7 → 8.0.0-dev.9

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 (137) hide show
  1. package/dist/bin/node-host.js +21 -3
  2. package/dist/src/analysis.js +94 -299
  3. package/dist/src/config.js +6 -83
  4. package/dist/src/configuration-files.js +2 -9
  5. package/dist/src/configured-declarations.js +15 -20
  6. package/dist/src/consumers.js +3 -30
  7. package/dist/src/contract/config.generated.js +544 -0
  8. package/dist/src/contract/contract.generated.js +20 -10
  9. package/dist/src/contract/report.generated.js +3 -2
  10. package/dist/src/conventions.js +3 -8
  11. package/dist/src/edges.js +36 -112
  12. package/dist/src/exempt-classes.js +0 -2
  13. package/dist/src/exempt.js +1 -1
  14. package/dist/src/failure.js +36 -0
  15. package/dist/src/findings/completion.js +5 -4
  16. package/dist/src/findings/emitters.js +1 -1
  17. package/dist/src/findings/intra-function.js +1 -1
  18. package/dist/src/findings/non-code-artifacts.js +2 -2
  19. package/dist/src/findings/unused-declarations.js +1 -1
  20. package/dist/src/findings/visibility-narrowing.js +2 -2
  21. package/dist/src/findings-pass.js +1 -1
  22. package/dist/src/framework-lifecycle.js +7 -7
  23. package/dist/src/fs/document.js +52 -0
  24. package/dist/src/fs/manifest.js +7 -0
  25. package/dist/src/injection-container.js +1 -1
  26. package/dist/src/json-document.js +194 -67
  27. package/dist/src/kinds.js +0 -7
  28. package/dist/src/load/classify.js +236 -0
  29. package/dist/src/load/diagnostics.js +79 -0
  30. package/dist/src/load/discover.js +230 -0
  31. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  32. package/dist/src/load/expected-module.js +136 -0
  33. package/dist/src/load/load.js +22 -0
  34. package/dist/src/load/module-lookup.js +37 -0
  35. package/dist/src/load/plan.js +155 -0
  36. package/dist/src/{test-globals.js → load/test-globals.js} +51 -56
  37. package/dist/src/load/test-joins.js +82 -0
  38. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +3 -3
  39. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +37 -40
  40. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +21 -59
  41. package/dist/src/{workspace-run.js → load/workspace-run.js} +4 -3
  42. package/dist/src/{workspace.js → load/workspace.js} +21 -17
  43. package/dist/src/outside-tests.js +1 -1
  44. package/dist/src/print.js +10 -79
  45. package/dist/src/report-schema.js +3 -224
  46. package/dist/src/resolve.js +245 -715
  47. package/dist/src/run.js +59 -72
  48. package/dist/src/schema.js +320 -344
  49. package/dist/src/scope.js +37 -113
  50. package/dist/src/serialization-contract.js +1 -1
  51. package/dist/src/session.js +22 -28
  52. package/dist/src/source-files.js +1 -1
  53. package/dist/src/suppress-file.js +15 -17
  54. package/dist/src/suppress.js +3 -3
  55. package/dist/src/template-field.js +4 -4
  56. package/dist/src/type-errors.js +11 -216
  57. package/dist/src/usage.js +10 -0
  58. package/dist/src/verbs/analyze.js +100 -122
  59. package/dist/src/verbs/describe.js +5 -12
  60. package/dist/src/verbs/explain.js +3 -3
  61. package/dist/src/verbs/print-projects.js +2 -2
  62. package/dist/src/verbs/version.js +12 -2
  63. package/jsr.json +1 -1
  64. package/package.json +1 -1
  65. package/src/analysis.ts +95 -460
  66. package/src/config.ts +31 -298
  67. package/src/configuration-files.ts +8 -10
  68. package/src/configured-declarations.ts +18 -23
  69. package/src/consumers.ts +6 -57
  70. package/src/contract/config.generated.ts +798 -0
  71. package/src/contract/contract.generated.ts +20 -10
  72. package/src/contract/report.generated.ts +3 -2
  73. package/src/conventions.ts +6 -12
  74. package/src/edges.ts +39 -124
  75. package/src/exempt-classes.ts +0 -5
  76. package/src/exempt.ts +4 -4
  77. package/src/failure.ts +63 -0
  78. package/src/findings/completion.ts +5 -6
  79. package/src/findings/emitter.ts +2 -2
  80. package/src/findings/emitters.ts +1 -1
  81. package/src/findings/intra-function.ts +1 -1
  82. package/src/findings/non-code-artifacts.ts +4 -4
  83. package/src/findings/unused-declarations.ts +1 -1
  84. package/src/findings/visibility-narrowing.ts +2 -2
  85. package/src/findings-pass.ts +3 -3
  86. package/src/framework-lifecycle.ts +7 -7
  87. package/src/fs/document.ts +70 -0
  88. package/src/fs/manifest.ts +8 -0
  89. package/src/host.ts +12 -5
  90. package/src/injection-container.ts +1 -1
  91. package/src/json-document.ts +236 -76
  92. package/src/kinds.ts +0 -8
  93. package/src/load/classify.ts +352 -0
  94. package/src/load/diagnostics.ts +141 -0
  95. package/src/load/discover.ts +378 -0
  96. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  97. package/src/load/expected-module.ts +188 -0
  98. package/src/load/load.ts +61 -0
  99. package/src/load/module-lookup.ts +50 -0
  100. package/src/load/plan.ts +258 -0
  101. package/src/{test-globals.ts → load/test-globals.ts} +59 -65
  102. package/src/load/test-joins.ts +98 -0
  103. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +4 -4
  104. package/src/{workspace-programs.ts → load/workspace-programs.ts} +59 -53
  105. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +31 -78
  106. package/src/{workspace-run.ts → load/workspace-run.ts} +14 -11
  107. package/src/{workspace.ts → load/workspace.ts} +28 -21
  108. package/src/outside-tests.ts +1 -1
  109. package/src/partial.ts +1 -1
  110. package/src/print.ts +11 -92
  111. package/src/report-schema.ts +3 -299
  112. package/src/resolve.ts +281 -1105
  113. package/src/run.ts +68 -80
  114. package/src/schema.ts +391 -389
  115. package/src/scope.ts +45 -131
  116. package/src/serialization-contract.ts +1 -1
  117. package/src/session.ts +52 -53
  118. package/src/source-files.ts +1 -1
  119. package/src/suppress-file.ts +15 -20
  120. package/src/suppress.ts +3 -3
  121. package/src/template-field.ts +10 -7
  122. package/src/type-errors.ts +18 -288
  123. package/src/usage.ts +10 -0
  124. package/src/verbs/analyze.ts +139 -157
  125. package/src/verbs/describe.ts +4 -11
  126. package/src/verbs/explain.ts +3 -7
  127. package/src/verbs/print-projects.ts +2 -2
  128. package/src/verbs/verb.ts +2 -2
  129. package/src/verbs/version.ts +13 -2
  130. package/dist/src/base-url.js +0 -18
  131. package/dist/src/discover.js +0 -374
  132. package/dist/src/setup-failure.js +0 -19
  133. package/dist/src/test-joins.js +0 -101
  134. package/src/base-url.ts +0 -24
  135. package/src/discover.ts +0 -548
  136. package/src/setup-failure.ts +0 -37
  137. package/src/test-joins.ts +0 -118
package/src/analysis.ts CHANGED
@@ -8,13 +8,8 @@
8
8
 
9
9
  import { isStringLiteralLikeNode, type SourceFile } from "@typescript/native/ast";
10
10
  import { lineOf, readComponent } from "./component-files.ts";
11
- import { kindOf, type Config, type Provenance } from "./config.ts";
12
- import {
13
- consumerLoads,
14
- consumerReferences,
15
- moduleIdentity,
16
- type LoadedConsumer,
17
- } from "./consumers.ts";
11
+ import { kindOf, type PartialConfig, type Provenance, type ResolvedConfig } from "./config.ts";
12
+ import { consumerReferences } from "./consumers.ts";
18
13
  import {
19
14
  configuredDeclarations,
20
15
  configuredRef,
@@ -23,26 +18,10 @@ import {
23
18
  import { decorator } from "./decorator.ts";
24
19
  import { configurationNeeds, dependenciesOf, projectNeeds } from "./dependencies.ts";
25
20
  import { deprecatedDeclarations, type Deprecation } from "./deprecation.ts";
26
- import {
27
- discoverProjects,
28
- DiscoveryError,
29
- isGuess,
30
- MISSING_GLOBAL_TYPE,
31
- projectErrors,
32
- renderDiagnostic,
33
- targetRelative,
34
- withBaseUrlPaths,
35
- type LocatedDiagnostic,
36
- type NotBuilt,
37
- } from "./discover.ts";
38
- import {
39
- conventionFailuresFor,
40
- generatedFiles,
41
- readConventions,
42
- type AppliedConvention,
43
- type ConventionManifest,
44
- type Conventions,
45
- } from "./conventions.ts";
21
+ import { moduleIdentity, type LoadedConsumer, type NotBuilt } from "./load/discover.ts";
22
+ import type { LibraryUnfound } from "./load/classify.ts";
23
+ import { loadRun, type LoadedRun } from "./load/load.ts";
24
+ import { generatedFiles, type AppliedConvention } from "./conventions.ts";
46
25
  import { readEdgeSides } from "./edges.ts";
47
26
  import { enumGroup } from "./enum-group.ts";
48
27
  import { generatedFile, generatedFilesOf } from "./generated-file.ts";
@@ -73,7 +52,7 @@ import { injectionContainer } from "./injection-container.ts";
73
52
  import { interfaceSatisfaction, settledSatisfaction } from "./interface-satisfaction.ts";
74
53
  import { intraFunctionFacts, projectParts, type ProjectParts } from "./intra-function-parts.ts";
75
54
  import { inventory, type Inventory, type InventorySymbol } from "./inventory.ts";
76
- import { packageEntries, readManifest, type ManifestEntry } from "./manifest.ts";
55
+ import { readManifest, type ManifestEntry } from "./manifest.ts";
77
56
  import {
78
57
  liveFilesAt,
79
58
  matrixOf,
@@ -88,58 +67,33 @@ import {
88
67
  dirnamePath,
89
68
  extensionOf,
90
69
  joinPath,
91
- normalizePath,
92
70
  relativePath,
93
71
  resolvePath,
94
72
  } from "./paths.ts";
95
73
  import type { UnansweredQuestion } from "./query.ts";
96
74
  import { byPosition, isComponentFile, type Position } from "./position.ts";
97
75
  import type { TypeErrorSkip, UnansweredCount } from "./report.ts";
98
- import { SetupError, setupLine, type SetupFailure } from "./setup-failure.ts";
99
- import {
100
- pathsOf,
101
- readErrors,
102
- skippedRoots,
103
- skippedUnits,
104
- type SkippedUnit,
105
- } from "./type-errors.ts";
76
+ import { skippedRoots, skippedUnits, type SkippedUnit } from "./type-errors.ts";
106
77
  import { reflectiveLookup } from "./reflective-lookup.ts";
107
78
  import { references, testFileRulesOf, type Reference, type TestFileRule } from "./references.ts";
108
- import {
109
- roots,
110
- unmatchedEverywhere,
111
- type Root,
112
- type RootKind,
113
- type RootOptions,
114
- type Roots,
115
- } from "./roots.ts";
79
+ import { roots, unmatchedEverywhere, type Root, type RootKind, type Roots } from "./roots.ts";
116
80
  import type { Scope } from "./scope.ts";
117
81
  import { decodedMembers, serializationContract, type Decoded } from "./serialization-contract.ts";
118
82
  import { outsideTestReferences, testFilesAt, type OutsideTest } from "./outside-tests.ts";
119
83
  import { mergedGlobalInterfaces } from "./augmentations.ts";
120
84
  import { unseenLoadsOf, type UnseenLoad } from "./unseen-loads.ts";
121
- import { joinedTestFiles, withJoinedTests } from "./test-joins.ts";
122
- import { GLOBALS_RUNNER, namesTestGlobals, withTestGlobals } from "./test-globals.ts";
85
+ import { GLOBALS_RUNNER, namesTestGlobals } from "./load/test-globals.ts";
123
86
  import { supportReferences, testSupportFiles, type TestEvidence } from "./test-support.ts";
124
- import {
125
- diagnosticsOf,
126
- ownedAs,
127
- runSession,
128
- type Engine,
129
- type OpenedFiles,
130
- type ProjectView,
131
- } from "./session.ts";
87
+ import type { Engine, ProjectView } from "./session.ts";
132
88
  import { accessorsOf, storesOf } from "./stores.ts";
133
89
  import { isPartKind, type SuppressionRecord, type Suppressions, type Verdict } from "./suppress.ts";
134
90
  import { bindRows, readBaseline, readIgnoreFile, type Recorded } from "./suppress-file.ts";
135
91
  import { inlineDirectives, inlineSuppressions, type InlineDirective } from "./suppress-inline.ts";
136
92
  import type { Exemption, Mode, SweepInput } from "./sweep.ts";
137
93
  import { readTemplates, templateField } from "./template-field.ts";
138
- import { ownErrors, workspaceRun } from "./workspace-run.ts";
139
94
  import { bytewise } from "./text/compare.ts";
140
- import { holdsManifest, inInstalledPackages, MANIFEST, manifestAt } from "./fs/manifest.ts";
95
+ import { holdsManifest, manifestAt } from "./fs/manifest.ts";
141
96
  import { globExpression } from "./text/glob.ts";
142
- import { LANGUAGE } from "./product.ts";
143
97
 
144
98
  /** The setting whose source decides where a finding about a configured root sits. */
145
99
  const ROOTS_SETTING = "roots.patterns";
@@ -225,330 +179,48 @@ interface OpenedProject {
225
179
  readonly read: () => ProjectRead;
226
180
  }
227
181
 
228
- /** What a run read of the consumers its scope declares. */
229
- interface ConsumerReads {
230
- /** Every declared consumer, each loaded, in the scope's order. */
231
- readonly loaded: readonly LoadedConsumer[];
182
+ /** What reading a loaded run's projects answered. */
183
+ interface ProjectsRead<Answer> {
184
+ readonly answers: readonly Answer[];
232
185
  /** Every reference a consumer makes to a declaration of the target, each once. */
233
186
  readonly references: readonly Reference[];
234
- }
235
-
236
- /** What a run read of its projects: each target project's answer, and its consumers. */
237
- interface ReadProjects<Answer> {
238
- readonly answers: readonly Answer[];
239
- readonly consumers: ConsumerReads;
240
- /** The derived configurations the run dropped, in the order it met them. */
241
- readonly notBuilt: readonly NotBuilt[];
242
- /** Every question the checker could not answer, each once. */
243
- readonly unanswered: readonly UnansweredQuestion[];
244
- /** Per configuration whose component files the run cannot read, the reason. */
245
- readonly componentsUnread: readonly ComponentsUnread[];
246
- /** Per analyzed configuration, each library it names that the compiler cannot find. */
247
- readonly librariesUnfound: readonly LibraryUnfound[];
248
- /** The convention rows the run applied. */
249
- readonly conventionsApplied: readonly AppliedConvention[];
250
- /** The dependencies the applied rows' short names use. */
251
- readonly conventionUses: readonly string[];
252
- /** The directory of every workspace member, absolute. */
253
- readonly memberDirs: readonly string[];
254
- /** The directory of every nested package, absolute. */
255
- readonly nestedDirs: readonly string[];
256
187
  /** The test files below the target root no project the run reads holds, parsed. */
257
188
  readonly outsideTests: readonly OutsideTest[];
258
189
  }
259
190
 
260
191
  /**
261
- * The manifests the analysis reads, each once: the target's own, then every workspace
262
- * member's and every nested package's below the target root.
263
- */
264
- function conventionManifests(
265
- host: Host,
266
- targetRoot: string,
267
- memberDirs: readonly string[],
268
- nestedDirs: readonly string[],
269
- ): readonly ConventionManifest[] {
270
- const found = new Map<string, ConventionManifest>();
271
- if (holdsManifest(host, targetRoot)) {
272
- found.set(targetRoot, { dir: targetRoot, path: MANIFEST });
273
- }
274
- for (const [dirs, nested] of [
275
- [memberDirs, false],
276
- [nestedDirs, true],
277
- ] as const) {
278
- for (const dir of dirs) {
279
- const below = relativePath(targetRoot, dir);
280
- if (below !== undefined && !found.has(dir)) {
281
- found.set(dir, { dir, path: `${below}/package.json`, nested });
282
- }
283
- }
284
- }
285
- return [...found.values()];
286
- }
287
-
288
- /**
289
- * The nested packages of a run: each directory below the target root, in no `node_modules`
290
- * directory and none of `known`, that holds a `package.json` and lies at or above one of
291
- * `files`, the program's source files and the compiler configuration files, in path order.
292
- */
293
- function nestedPackageDirs(
294
- host: Host,
295
- targetRoot: string,
296
- files: Iterable<string>,
297
- known: ReadonlySet<string>,
298
- ): readonly string[] {
299
- const seen = new Set<string>();
300
- const found: string[] = [];
301
- for (const file of files) {
302
- for (const dir of ancestors(dirnamePath(file), targetRoot)) {
303
- if (seen.has(dir) || relativePath(targetRoot, dir) === undefined) {
304
- break;
305
- }
306
- seen.add(dir);
307
- const below = relativePath(targetRoot, dir) ?? "";
308
- if (!inInstalledPackages(below) && !known.has(dir) && holdsManifest(host, dir)) {
309
- found.push(dir);
310
- }
311
- }
312
- }
313
- return found.sort(bytewise);
314
- }
315
-
316
- /**
317
- * Reads every project the scope discovers, and each declared consumer's, in one snapshot,
318
- * each checked for errors first. `stage` is handed a target project and enumerates and roots
319
- * it if it reads it; a consumer project is read for its references to the target. A type error
320
- * in an own file skips the unit holding it. A guess that does not load or meets a setup failure
321
- * is dropped into `notBuilt` (see {@link isGuess}); any other such project fails the run, as
322
- * does a run whose every guess was dropped.
192
+ * Reads every project the load phase analyzes through `stage`, which enumerates and roots one
193
+ * if it reads it, and each declared consumer's project for its references to the target,
194
+ * in the same snapshot. A type error in an own file skips the unit holding it.
323
195
  */
324
196
  function readProjects<Answer>(
325
197
  engine: Engine,
326
198
  host: Host,
327
199
  scope: Scope,
328
- config: Config,
200
+ config: PartialConfig,
329
201
  stage: <Brand>(project: ProjectView<Brand>, opened: OpenedProject) => Answer,
330
- ): ReadProjects<Answer> {
202
+ ): LoadedRun<ProjectsRead<Answer>> {
331
203
  const targetRoot = scope.target.path;
332
- const discovered = discoverProjects(engine, host, scope, config.analysis.configurations);
333
- if (discovered.configFiles.length === 0 && discovered.notBuilt.length === 0) {
334
- throw new DiscoveryError(
335
- `${targetRoot} holds no compiler configuration, so the run holds no program`,
336
- [],
337
- );
338
- }
339
- const ids = new Map(discovered.projects.map((project) => [project.configFile, project.id]));
340
- const loads = consumerLoads(engine, host, scope, discovered.configFiles);
341
- const consumerOf = new Map(
342
- loads.flatMap((load) =>
343
- load.configFiles.map((configFile) => [configFile, load.consumer] as const),
344
- ),
345
- );
346
204
  const absoluteRoot = resolvePath(host.workingDirectory(), targetRoot);
347
- const workspace = workspaceRun(
348
- engine,
349
- host,
350
- absoluteRoot,
351
- discovered.configFiles,
352
- readManifest(host, targetRoot),
353
- );
205
+ const testPatterns = config.ts.test_files.map(globExpression);
354
206
  const parse = (fileName: string, text: string) => engine.parseSourceFile(fileName, text);
355
- const memberDirs = workspace?.memberDirs ?? [];
356
- // The nested packages are known only once every program is open, and every visit reads
357
- // the conventions and options they decide, so both are set in the session's first step.
358
- let nestedDirs: readonly string[] = [];
359
- let conventions = readConventions(host, parse, [], config.ts.disabledConventions);
360
- let options: RootOptions & { readonly parse: typeof parse; readonly conventions: Conventions };
361
- const readManifests = (opened: readonly OpenedFiles[]): void => {
362
- nestedDirs = nestedPackageDirs(
363
- host,
364
- normalizePath(absoluteRoot),
365
- opened
366
- .filter((one) => !consumerOf.has(one.configFile))
367
- .flatMap((one) => [one.configFile, ...one.fileNames()]),
368
- new Set(memberDirs),
369
- );
370
- conventions = readConventions(
371
- host,
372
- parse,
373
- conventionManifests(host, absoluteRoot, memberDirs, nestedDirs),
374
- config.ts.disabledConventions,
375
- );
376
- options = {
207
+ return loadRun(engine, host, scope, config, ({ plan, classified, runFiles }) => {
208
+ const { packages, conventions } = plan;
209
+ const options = {
377
210
  host,
378
- manifest: workspace?.manifest ?? readManifest(host, targetRoot),
379
- otherPackages: [
380
- ...(workspace?.entries ?? []),
381
- ...packageEntries(host, normalizePath(absoluteRoot), nestedDirs),
382
- ],
383
- patterns: config.rootPatterns,
384
- entryFiles: config.ts.entryFiles,
211
+ manifest: packages.manifest,
212
+ otherPackages: packages.entries,
213
+ patterns: config.roots.patterns,
214
+ entryFiles: config.ts.entry_files,
385
215
  conventions,
386
- testFiles: config.ts.testFiles,
216
+ testFiles: config.ts.test_files,
387
217
  parse,
388
- publishedAPI: config.targetKind !== "" && kindOf(config.targetKind, LANGUAGE) === "library",
389
- publishedMembers: new Set(
390
- (workspace?.entries ?? []).filter((entry) => entry.published).map((entry) => entry.dir),
391
- ),
392
- runFiles: new Set(
393
- opened.flatMap((one) =>
394
- one.fileNames().map((name) => resolvePath(host.workingDirectory(), name)),
395
- ),
396
- ),
218
+ publishedAPI: config.target.kind !== undefined && kindOf(config.target.kind) === "library",
219
+ publishedMembers: packages.published,
220
+ runFiles,
397
221
  };
398
- };
399
- const notBuilt: NotBuilt[] = [...discovered.notBuilt];
400
- const dropped = (configFile: string, error: string): void => {
401
- notBuilt.push({
402
- id: ids.get(configFile) ?? configFile,
403
- configFile,
404
- error: targetRelative(error, absoluteRoot),
405
- });
406
- };
407
- const failures: LocatedDiagnostic[] = [];
408
- const unbuildable: SetupFailure[] = [];
409
- const setupDropped: SetupFailure[] = [];
410
- const librariesUnfound: LibraryUnfound[] = [];
411
- const consumed = new Map<string, Reference>();
412
- const heldFiles = new Set<string>();
413
- let outsideTests: readonly OutsideTest[] = [];
414
- const setupMet = (configFile: string, met: readonly SetupFailure[]): void => {
415
- const [first] = met;
416
- if (first !== undefined && isGuess(discovered, configFile)) {
417
- dropped(configFile, setupLine(first));
418
- setupDropped.push(...met);
419
- } else {
420
- unbuildable.push(...met);
421
- }
422
- };
423
- const testPatterns = config.ts.testFiles.map(globExpression);
424
- const joins = discovered.derived
425
- ? joinedTestFiles(engine, host, absoluteRoot, discovered.configFiles, testPatterns)
426
- : new Map<string, readonly string[]>();
427
- const programs = withTestGlobals(
428
- engine,
429
- host,
430
- parse,
431
- discovered.configFiles,
432
- withBaseUrlPaths(
433
- engine,
434
- host,
435
- [...discovered.configFiles, ...consumerOf.keys()],
436
- workspace?.programs ?? new Map(),
437
- ),
438
- );
439
- const session = runSession(
440
- engine,
441
- [...discovered.configFiles, ...consumerOf.keys()],
442
- (opened) => {
443
- const consumer = consumerOf.get(opened.configFile);
444
- const setup = consumer === undefined ? workspace?.unbuildable(opened.configFile) : undefined;
445
- if (setup !== undefined) {
446
- setupMet(opened.configFile, [
447
- { setupClass: "workspace-member-without-source", detail: setup },
448
- ]);
449
- return undefined;
450
- }
451
- const referenceOnly =
452
- workspace === undefined || consumer !== undefined
453
- ? () => false
454
- : workspace.referenceOnly(opened.configFile, opened.rootFiles);
455
- const project =
456
- workspace === undefined || consumer !== undefined
457
- ? opened
458
- : ownedAs(opened, (file, fromExternalLibrary) =>
459
- workspace.ownFile(file, fromExternalLibrary),
460
- );
461
- const raw = projectErrors(diagnosticsOf(project));
462
- const errors = { load: raw.load, check: ownErrors(raw.check, referenceOnly) };
463
- const [unloaded] = errors.load;
464
- if (
465
- unloaded !== undefined &&
466
- consumer === undefined &&
467
- isGuess(discovered, project.configFile)
468
- ) {
469
- dropped(
470
- project.configFile,
471
- renderDiagnostic(unloaded, (path) => relativePath(absoluteRoot, path) ?? path),
472
- );
473
- return undefined;
474
- }
475
- if (errors.load.length > 0) {
476
- failures.push(...errors.load);
477
- return undefined;
478
- }
479
- const reading = readErrors(project, errors.check, {
480
- host,
481
- targetRoot:
482
- consumer === undefined
483
- ? absoluteRoot
484
- : resolvePath(host.workingDirectory(), consumer.path),
485
- paths: pathsOf(engine, project.configFile),
486
- });
487
- if (consumer !== undefined && reading.missing.length > 0) {
488
- unbuildable.push(
489
- ...reading.missing.map((one) => ({
490
- setupClass: "missing-consumer" as const,
491
- detail: `the consumer ${consumer.path} does not build, its dependencies not installed: ${one.detail}`,
492
- })),
493
- );
494
- return undefined;
495
- }
496
- if (reading.missing.length > 0) {
497
- setupMet(project.configFile, reading.missing);
498
- return undefined;
499
- }
500
- const unconventional =
501
- consumer === undefined
502
- ? conventionFailuresFor(
503
- conventions,
504
- project.configFile,
505
- project.ownSourceFiles().map((file) => file.fileName),
506
- )
507
- : [];
508
- if (unconventional.length > 0) {
509
- setupMet(project.configFile, unconventional);
510
- return undefined;
511
- }
512
- if (consumer !== undefined) {
513
- for (const reference of consumerReferences(
514
- project,
515
- host,
516
- targetRoot,
517
- {
518
- id: consumer.id,
519
- root: consumer.path,
520
- },
521
- config,
522
- )) {
523
- consumed.set(referenceKey(reference), reference);
524
- }
525
- return undefined;
526
- }
527
- librariesUnfound.push(
528
- ...raw.unfound.map((one) => ({
529
- configFile: project.configFile,
530
- error: renderDiagnostic(one, (path) => relativePath(absoluteRoot, path) ?? path),
531
- })),
532
- );
533
- const missingGlobal = raw.unfound.find(
534
- ({ diagnostic }) => diagnostic.code === MISSING_GLOBAL_TYPE,
535
- );
536
- const skips =
537
- missingGlobal === undefined
538
- ? reading.skips
539
- : [
540
- ...reading.skips,
541
- ...project.ownSourceFiles().map((file) => ({
542
- record: {
543
- path: relativePath(absoluteRoot, file.fileName) ?? file.fileName,
544
- line: 1,
545
- message: missingGlobal.diagnostic.text,
546
- },
547
- file,
548
- unit: file,
549
- })),
550
- ];
551
- const configuration = ids.get(project.configFile) ?? project.configFile;
222
+ const heldFiles = new Set<string>();
223
+ const answers = classified.analyzed.map(({ plan: planned, project, skips, referenceOnly }) => {
552
224
  const read = (): ProjectRead => {
553
225
  const held = inventory(project, host, targetRoot);
554
226
  const found = roots(project, held, targetRoot, options);
@@ -565,7 +237,7 @@ function readProjects<Answer>(
565
237
  };
566
238
  const own = sourceFilesOf(project, targetRoot);
567
239
  return {
568
- configuration,
240
+ configuration: planned.id,
569
241
  configFile: project.configFile,
570
242
  held,
571
243
  rooted,
@@ -582,64 +254,25 @@ function readProjects<Answer>(
582
254
  for (const file of project.ownSourceFiles()) {
583
255
  heldFiles.add(relativePath(absoluteRoot, file.fileName) ?? file.fileName);
584
256
  }
585
- return stage(project, { configuration, read });
586
- },
587
- discovered.derived ? "record" : "refuse",
588
- joins.size === 0 ? programs : withJoinedTests(engine, host, programs, joins),
589
- () => {
590
- outsideTests = testFilesAt(
591
- host,
592
- targetRoot,
593
- sourcePaths(host, targetRoot).filter(
594
- (path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path)),
595
- ),
596
- parse,
597
- );
598
- },
599
- readManifests,
600
- );
601
- for (const configFile of session.unopened) {
602
- if (consumerOf.has(configFile) || !isGuess(discovered, configFile)) {
603
- throw new DiscoveryError(`${configFile} opened no project`, []);
257
+ return stage(project, { configuration: planned.id, read });
258
+ });
259
+ const consumed = new Map<string, Reference>();
260
+ for (const { project, consumer } of classified.consumed) {
261
+ const side = { id: consumer.id, root: consumer.path };
262
+ for (const reference of consumerReferences(project, host, targetRoot, side, config)) {
263
+ consumed.set(referenceKey(reference), reference);
264
+ }
604
265
  }
605
- dropped(configFile, "the compiler opened no project for the configuration");
606
- }
607
- if (unbuildable.length > 0) {
608
- throw new SetupError(unbuildable);
609
- }
610
- if (failures.length > 0) {
611
- throw new DiscoveryError(
612
- `${String(failures.length)} error(s), so no answer was produced`,
613
- failures,
614
- );
615
- }
616
- const answers = session.projects.filter((answer): answer is Answer => answer !== undefined);
617
- const [first] = notBuilt;
618
- if (answers.length === 0 && setupDropped.length > 0) {
619
- throw new SetupError(setupDropped);
620
- }
621
- if (answers.length === 0 && first !== undefined) {
622
- throw new DiscoveryError(
623
- `no configuration discovery derived could be built; ${first.id}: ${first.error}`,
624
- [],
266
+ const outsideTests = testFilesAt(
267
+ host,
268
+ targetRoot,
269
+ sourcePaths(host, targetRoot).filter(
270
+ (path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path)),
271
+ ),
272
+ parse,
625
273
  );
626
- }
627
- return {
628
- answers,
629
- consumers: {
630
- loaded: loads.map((load) => load.consumer),
631
- references: [...consumed.values()],
632
- },
633
- notBuilt,
634
- unanswered: session.unanswered,
635
- componentsUnread: workspace?.componentsUnread ?? [],
636
- librariesUnfound,
637
- conventionsApplied: conventions.applied,
638
- conventionUses: conventions.uses,
639
- memberDirs,
640
- nestedDirs,
641
- outsideTests,
642
- };
274
+ return { answers, references: [...consumed.values()], outsideTests };
275
+ });
643
276
  }
644
277
 
645
278
  /** The projects one run analyzes, and what reading them left out. */
@@ -657,7 +290,12 @@ interface RunProjects {
657
290
  * for the errors and setup failures that decide whether it is analyzed, dropped or
658
291
  * fails the run, exactly as the analysis reads them.
659
292
  */
660
- export function runProjects(engine: Engine, host: Host, scope: Scope, config: Config): RunProjects {
293
+ export function runProjects(
294
+ engine: Engine,
295
+ host: Host,
296
+ scope: Scope,
297
+ config: PartialConfig,
298
+ ): RunProjects {
661
299
  const read = readProjects(
662
300
  engine,
663
301
  host,
@@ -665,7 +303,11 @@ export function runProjects(engine: Engine, host: Host, scope: Scope, config: Co
665
303
  config,
666
304
  (_project, opened) => opened.configuration,
667
305
  );
668
- return { configurations: read.answers, notBuilt: read.notBuilt, unanswered: read.unanswered };
306
+ return {
307
+ configurations: read.result.answers,
308
+ notBuilt: read.classified.notBuilt,
309
+ unanswered: read.unanswered,
310
+ };
669
311
  }
670
312
 
671
313
  /**
@@ -678,12 +320,12 @@ export function runRoots(
678
320
  engine: Engine,
679
321
  host: Host,
680
322
  scope: Scope,
681
- config: Config,
323
+ config: ResolvedConfig,
682
324
  provenance: Provenance,
683
325
  ): RunRoots {
684
326
  const targetRoot = scope.target.path;
685
327
  const read = readProjects(engine, host, scope, config, (_project, opened) => opened.read());
686
- const projects = read.answers;
328
+ const projects = read.result.answers;
687
329
 
688
330
  const configurations: string[] = [];
689
331
  const merged = new Map<string, Omit<RunRoot, "configurations"> & { configurations: string[] }>();
@@ -719,7 +361,7 @@ export function runRoots(
719
361
  bytewise(a.source, b.source),
720
362
  );
721
363
  const unmatched = unmatchedEverywhere(
722
- config.rootPatterns,
364
+ config.roots.patterns,
723
365
  projects.map((answer) => answer.rooted),
724
366
  );
725
367
  return {
@@ -729,7 +371,7 @@ export function runRoots(
729
371
  unmatched,
730
372
  documentOf(host, provenance, ROOTS_SETTING, targetRoot),
731
373
  ),
732
- notBuilt: read.notBuilt,
374
+ notBuilt: read.classified.notBuilt,
733
375
  unanswered: read.unanswered,
734
376
  };
735
377
  }
@@ -761,7 +403,7 @@ export interface RunSweep {
761
403
  }
762
404
 
763
405
  /** One `<script` start tag of a component file the run read no block for. */
764
- export interface ComponentWarning {
406
+ interface ComponentWarning {
765
407
  /** The file, below the target root. */
766
408
  readonly path: string;
767
409
  readonly line: number;
@@ -899,7 +541,7 @@ function readRun<Extra>(
899
541
  engine: Engine,
900
542
  host: Host,
901
543
  scope: Scope,
902
- config: Config,
544
+ config: ResolvedConfig,
903
545
  mode: Mode,
904
546
  detectors: Detectors,
905
547
  extra: <Brand>(
@@ -912,13 +554,13 @@ function readRun<Extra>(
912
554
  const targetRoot = scope.target.path;
913
555
  const disabled = disabledClasses(config);
914
556
  const templates = disabled.has("template-field")
915
- ? { delimiters: config.analysis.templateDelimiters, files: [] }
557
+ ? { delimiters: config.analysis.template_delimiters, files: [] }
916
558
  : readTemplates(host, targetRoot, config.analysis);
917
559
  const consumers = scope.consumers.map((consumer) => consumer.path);
918
560
  const read = readProjects<ReadProject<Extra>>(engine, host, scope, config, (project, opened) => {
919
561
  const projectRead = opened.read();
920
562
  const resolved = references(project, projectRead.held, targetRoot, {
921
- testFiles: config.ts.testFiles,
563
+ testFiles: config.ts.test_files,
922
564
  testFileNames: projectRead.testFileNames,
923
565
  });
924
566
  const evidence = evidenceRecords(
@@ -929,7 +571,7 @@ function readRun<Extra>(
929
571
  templates,
930
572
  ts: config.ts,
931
573
  consumers,
932
- ...(config.analysis.generatedFiles === "include"
574
+ ...(config.analysis.generated_files === "include"
933
575
  ? {}
934
576
  : { generated: projectRead.generated }),
935
577
  },
@@ -987,12 +629,12 @@ function readRun<Extra>(
987
629
  extra: extra(project, projectRead, resolved.references, resolved.testFilePaths),
988
630
  };
989
631
  });
990
- const outsidePaths = read.outsideTests.map((one) => one.path);
991
- const withOutside = read.answers.map((one) => ({
632
+ const outsidePaths = read.result.outsideTests.map((one) => one.path);
633
+ const withOutside = read.result.answers.map((one) => ({
992
634
  ...one,
993
635
  references: [
994
636
  ...one.references,
995
- ...outsideTestReferences(read.outsideTests, one.projectRead.held, targetRoot),
637
+ ...outsideTestReferences(read.result.outsideTests, one.projectRead.held, targetRoot),
996
638
  ],
997
639
  testFiles: [...one.testFiles, ...outsidePaths],
998
640
  }));
@@ -1008,7 +650,7 @@ function readRun<Extra>(
1008
650
  // A member a decode fills or a copy carries is written: a value decoded and sent again carries it on.
1009
651
  const written = new Set([
1010
652
  ...countedWrites(
1011
- [...withOutside.flatMap((one) => one.references), ...read.consumers.references],
653
+ [...withOutside.flatMap((one) => one.references), ...read.result.references],
1012
654
  support,
1013
655
  mode,
1014
656
  ),
@@ -1024,7 +666,7 @@ function readRun<Extra>(
1024
666
  evidence: evidence[index] ?? [],
1025
667
  held: one.projectRead.held,
1026
668
  })),
1027
- [...withOutside.flatMap((one) => one.references), ...read.consumers.references],
669
+ [...withOutside.flatMap((one) => one.references), ...read.result.references],
1028
670
  );
1029
671
  const answers = withOutside.map((one, index): SweptProject<Extra> => {
1030
672
  const { projectRead } = one;
@@ -1078,7 +720,7 @@ function readRun<Extra>(
1078
720
  extra: one.extra,
1079
721
  };
1080
722
  });
1081
- const consumed = read.consumers.references;
723
+ const consumed = read.result.references;
1082
724
  const projects = answers.map((one) =>
1083
725
  consumed.length === 0
1084
726
  ? one
@@ -1100,15 +742,15 @@ function readRun<Extra>(
1100
742
  ]),
1101
743
  ],
1102
744
  projects,
1103
- consumers: read.consumers.loaded,
1104
- notBuilt: read.notBuilt,
745
+ consumers: read.plan.discovery.consumers,
746
+ notBuilt: read.classified.notBuilt,
1105
747
  unanswered: read.unanswered,
1106
- componentsUnread: read.componentsUnread,
1107
- librariesUnfound: read.librariesUnfound,
1108
- conventionsApplied: read.conventionsApplied,
1109
- conventionUses: read.conventionUses,
1110
- memberDirs: read.memberDirs,
1111
- nestedDirs: read.nestedDirs,
748
+ componentsUnread: read.plan.workspace?.componentsUnread ?? [],
749
+ librariesUnfound: read.classified.librariesUnfound,
750
+ conventionsApplied: read.plan.conventions.applied,
751
+ conventionUses: read.plan.conventions.uses,
752
+ memberDirs: read.plan.packages.members,
753
+ nestedDirs: read.plan.packages.nested,
1112
754
  };
1113
755
  }
1114
756
 
@@ -1281,7 +923,7 @@ export function runSweep(
1281
923
  engine: Engine,
1282
924
  host: Host,
1283
925
  scope: Scope,
1284
- config: Config,
926
+ config: ResolvedConfig,
1285
927
  input: Pick<SweepInput, "marked" | "mode">,
1286
928
  detectors: Detectors = DETECTORS,
1287
929
  ): RunSweep {
@@ -1324,7 +966,7 @@ export function readEmitterRun(
1324
966
  engine: Engine,
1325
967
  host: Host,
1326
968
  scope: Scope,
1327
- config: Config,
969
+ config: ResolvedConfig,
1328
970
  mode: Mode,
1329
971
  detectors: Detectors,
1330
972
  ): ReadRun<EmitterExtra> {
@@ -1417,7 +1059,7 @@ function nearestManifestDir(host: Host, root: string, file: string): string {
1417
1059
  export function emitterInputOver(
1418
1060
  host: Host,
1419
1061
  scope: Scope,
1420
- config: Config,
1062
+ config: ResolvedConfig,
1421
1063
  read: ReadRun<EmitterExtra>,
1422
1064
  input: Pick<SweepInput, "marked" | "mode">,
1423
1065
  selfCheck: SelfCheckFacts,
@@ -1505,7 +1147,7 @@ function readAnalysis(
1505
1147
  engine: Engine,
1506
1148
  host: Host,
1507
1149
  scope: Scope,
1508
- config: Config,
1150
+ config: ResolvedConfig,
1509
1151
  provenance: Provenance,
1510
1152
  mode: Mode,
1511
1153
  detectors: Detectors,
@@ -1526,7 +1168,7 @@ function readAnalysis(
1526
1168
  configFile: one.configFile,
1527
1169
  })),
1528
1170
  testFileRules: testFileRulesOf(
1529
- config.ts.testFiles,
1171
+ config.ts.test_files,
1530
1172
  read.projects.flatMap((one) => one.configured.testFiles),
1531
1173
  read.projects.flatMap((one) => one.configured.supportFiles ?? []),
1532
1174
  ),
@@ -1557,7 +1199,7 @@ function readAnalysis(
1557
1199
  function inputsOver(
1558
1200
  host: Host,
1559
1201
  scope: Scope,
1560
- config: Config,
1202
+ config: ResolvedConfig,
1561
1203
  provenance: Provenance,
1562
1204
  mode: Mode,
1563
1205
  read: ReadRun<EmitterExtra>,
@@ -1571,7 +1213,7 @@ function inputsOver(
1571
1213
  const facts: SelfCheckFacts = {
1572
1214
  refusals: suppressions.refusals,
1573
1215
  unmatchedRoots: unmatchedEverywhere(
1574
- config.rootPatterns,
1216
+ config.roots.patterns,
1575
1217
  read.projects.map((one) => one.extra.rooted),
1576
1218
  ),
1577
1219
  rootsDocument: documentOf(host, provenance, ROOTS_SETTING, targetRoot),
@@ -1654,13 +1296,6 @@ interface ComponentsUnread {
1654
1296
  readonly reason: string;
1655
1297
  }
1656
1298
 
1657
- /** One library an analyzed configuration names that the compiler cannot find. */
1658
- interface LibraryUnfound {
1659
- readonly configFile: string;
1660
- /** The compiler's error, rendered as a dropped configuration's is. */
1661
- readonly error: string;
1662
- }
1663
-
1664
1299
  /** The findings of one run, beside what a report states about the run itself. */
1665
1300
  export interface RunAnalysis {
1666
1301
  readonly result: PassResult;
@@ -1681,7 +1316,7 @@ export function runAnalysis(
1681
1316
  engine: Engine,
1682
1317
  host: Host,
1683
1318
  scope: Scope,
1684
- config: Config,
1319
+ config: ResolvedConfig,
1685
1320
  provenance: Provenance,
1686
1321
  mode: Mode,
1687
1322
  detectors: Detectors = DETECTORS,
@@ -1737,7 +1372,7 @@ export function runBaselineWrite(
1737
1372
  engine: Engine,
1738
1373
  host: Host,
1739
1374
  scope: Scope,
1740
- config: Config,
1375
+ config: ResolvedConfig,
1741
1376
  provenance: Provenance,
1742
1377
  mode: Mode,
1743
1378
  reason: string,