@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
@@ -1,5 +1,5 @@
1
1
  import { randomBytes } from "node:crypto";
2
- import { closeSync, fchmodSync, fsyncSync, mkdtempSync, openSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeSync, } from "node:fs";
2
+ import { closeSync, fchmodSync, fsyncSync, mkdtempSync, openSync, readdirSync, readFileSync, readSync, realpathSync, renameSync, rmSync, statSync, writeSync, } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { basename, dirname, extname, join } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
@@ -77,6 +77,21 @@ function writeAtomically(path, pieces) {
77
77
  throw error;
78
78
  }
79
79
  }
80
+ /** The text of a file's first `limit` bytes, or of all of it where it holds fewer. */
81
+ function readHead(path, limit) {
82
+ const bytes = Buffer.alloc(limit);
83
+ const fd = openSync(path, "r");
84
+ try {
85
+ let held = 0;
86
+ for (let got = -1; got !== 0 && held < limit; held += got) {
87
+ got = readSync(fd, bytes, held, limit - held, null);
88
+ }
89
+ return bytes.toString("utf8", 0, held);
90
+ }
91
+ finally {
92
+ closeSync(fd);
93
+ }
94
+ }
80
95
  /** A new directory under the platform's temporary directory. */
81
96
  function temporaryDirectory() {
82
97
  const path = mkdtempSync(join(tmpdir(), `${PRODUCT}-mapper-`));
@@ -106,7 +121,7 @@ function componentMapperCommand() {
106
121
  export function nodeHost() {
107
122
  return {
108
123
  workingDirectory: () => process.cwd(),
109
- readFile: (path) => readFileSync(path, "utf8"),
124
+ readFile: (path, limit) => limit === undefined ? readFileSync(path, "utf8") : readHead(path, limit),
110
125
  readDirectory: (path) => readdirSync(path, { withFileTypes: true }).map((entry) => ({
111
126
  name: entry.name,
112
127
  directory: entry.isDirectory(),
@@ -116,7 +131,10 @@ export function nodeHost() {
116
131
  if (stat === undefined) {
117
132
  return "absent";
118
133
  }
119
- return stat.isDirectory() ? "directory" : "file";
134
+ if (stat.isDirectory()) {
135
+ return "directory";
136
+ }
137
+ return stat.isFile() ? "file" : "other";
120
138
  },
121
139
  realPath: (path) => realpathSync(path),
122
140
  analyzerVersion: () => {
@@ -8,13 +8,14 @@
8
8
  import { isStringLiteralLikeNode } from "@typescript/native/ast";
9
9
  import { lineOf, readComponent } from "./component-files.js";
10
10
  import { kindOf } from "./config.js";
11
- import { consumerLoads, consumerReferences, moduleIdentity, } from "./consumers.js";
11
+ import { consumerReferences } from "./consumers.js";
12
12
  import { configuredDeclarations, configuredRef, declarationsNamed, } from "./configured-declarations.js";
13
13
  import { decorator } from "./decorator.js";
14
14
  import { configurationNeeds, dependenciesOf, projectNeeds } from "./dependencies.js";
15
15
  import { deprecatedDeclarations } from "./deprecation.js";
16
- import { discoverProjects, DiscoveryError, isGuess, MISSING_GLOBAL_TYPE, projectErrors, renderDiagnostic, targetRelative, withBaseUrlPaths, } from "./discover.js";
17
- import { conventionFailuresFor, generatedFiles, readConventions, } from "./conventions.js";
16
+ import { moduleIdentity } from "./load/discover.js";
17
+ import { loadRun } from "./load/load.js";
18
+ import { generatedFiles } from "./conventions.js";
18
19
  import { readEdgeSides } from "./edges.js";
19
20
  import { enumGroup } from "./enum-group.js";
20
21
  import { generatedFile, generatedFilesOf } from "./generated-file.js";
@@ -30,33 +31,28 @@ import { injectionContainer } from "./injection-container.js";
30
31
  import { interfaceSatisfaction, settledSatisfaction } from "./interface-satisfaction.js";
31
32
  import { intraFunctionFacts, projectParts } from "./intra-function-parts.js";
32
33
  import { inventory } from "./inventory.js";
33
- import { packageEntries, readManifest } from "./manifest.js";
34
+ import { readManifest } from "./manifest.js";
34
35
  import { liveFilesAt, matrixOf, referenceKey, sweepMatrix, } from "./matrix.js";
35
- import { ancestors, dirnamePath, extensionOf, joinPath, normalizePath, relativePath, resolvePath, } from "./paths.js";
36
+ import { ancestors, dirnamePath, extensionOf, joinPath, relativePath, resolvePath, } from "./paths.js";
36
37
  import { byPosition, isComponentFile } from "./position.js";
37
- import { SetupError, setupLine } from "./setup-failure.js";
38
- import { pathsOf, readErrors, skippedRoots, skippedUnits, } from "./type-errors.js";
38
+ import { skippedRoots, skippedUnits } from "./type-errors.js";
39
39
  import { reflectiveLookup } from "./reflective-lookup.js";
40
40
  import { references, testFileRulesOf } from "./references.js";
41
- import { roots, unmatchedEverywhere, } from "./roots.js";
41
+ import { roots, unmatchedEverywhere } from "./roots.js";
42
42
  import { decodedMembers, serializationContract } from "./serialization-contract.js";
43
43
  import { outsideTestReferences, testFilesAt } from "./outside-tests.js";
44
44
  import { mergedGlobalInterfaces } from "./augmentations.js";
45
45
  import { unseenLoadsOf } from "./unseen-loads.js";
46
- import { joinedTestFiles, withJoinedTests } from "./test-joins.js";
47
- import { GLOBALS_RUNNER, namesTestGlobals, withTestGlobals } from "./test-globals.js";
46
+ import { GLOBALS_RUNNER, namesTestGlobals } from "./load/test-globals.js";
48
47
  import { supportReferences, testSupportFiles } from "./test-support.js";
49
- import { diagnosticsOf, ownedAs, runSession, } from "./session.js";
50
48
  import { accessorsOf, storesOf } from "./stores.js";
51
49
  import { isPartKind } from "./suppress.js";
52
50
  import { bindRows, readBaseline, readIgnoreFile } from "./suppress-file.js";
53
51
  import { inlineDirectives, inlineSuppressions } from "./suppress-inline.js";
54
52
  import { readTemplates, templateField } from "./template-field.js";
55
- import { ownErrors, workspaceRun } from "./workspace-run.js";
56
53
  import { bytewise } from "./text/compare.js";
57
- import { holdsManifest, inInstalledPackages, MANIFEST, manifestAt } from "./fs/manifest.js";
54
+ import { holdsManifest, manifestAt } from "./fs/manifest.js";
58
55
  import { globExpression } from "./text/glob.js";
59
- import { LANGUAGE } from "./product.js";
60
56
  /** The setting whose source decides where a finding about a configured root sits. */
61
57
  const ROOTS_SETTING = "roots.patterns";
62
58
  /**
@@ -74,281 +70,76 @@ function documentOf(host, provenance, setting, targetRoot) {
74
70
  return relativePath(resolvePath(host.workingDirectory(), targetRoot), document) ?? "";
75
71
  }
76
72
  /**
77
- * The manifests the analysis reads, each once: the target's own, then every workspace
78
- * member's and every nested package's below the target root.
79
- */
80
- function conventionManifests(host, targetRoot, memberDirs, nestedDirs) {
81
- const found = new Map();
82
- if (holdsManifest(host, targetRoot)) {
83
- found.set(targetRoot, { dir: targetRoot, path: MANIFEST });
84
- }
85
- for (const [dirs, nested] of [
86
- [memberDirs, false],
87
- [nestedDirs, true],
88
- ]) {
89
- for (const dir of dirs) {
90
- const below = relativePath(targetRoot, dir);
91
- if (below !== undefined && !found.has(dir)) {
92
- found.set(dir, { dir, path: `${below}/package.json`, nested });
93
- }
94
- }
95
- }
96
- return [...found.values()];
97
- }
98
- /**
99
- * The nested packages of a run: each directory below the target root, in no `node_modules`
100
- * directory and none of `known`, that holds a `package.json` and lies at or above one of
101
- * `files`, the program's source files and the compiler configuration files, in path order.
102
- */
103
- function nestedPackageDirs(host, targetRoot, files, known) {
104
- const seen = new Set();
105
- const found = [];
106
- for (const file of files) {
107
- for (const dir of ancestors(dirnamePath(file), targetRoot)) {
108
- if (seen.has(dir) || relativePath(targetRoot, dir) === undefined) {
109
- break;
110
- }
111
- seen.add(dir);
112
- const below = relativePath(targetRoot, dir) ?? "";
113
- if (!inInstalledPackages(below) && !known.has(dir) && holdsManifest(host, dir)) {
114
- found.push(dir);
115
- }
116
- }
117
- }
118
- return found.sort(bytewise);
119
- }
120
- /**
121
- * Reads every project the scope discovers, and each declared consumer's, in one snapshot,
122
- * each checked for errors first. `stage` is handed a target project and enumerates and roots
123
- * it if it reads it; a consumer project is read for its references to the target. A type error
124
- * in an own file skips the unit holding it. A guess that does not load or meets a setup failure
125
- * is dropped into `notBuilt` (see {@link isGuess}); any other such project fails the run, as
126
- * does a run whose every guess was dropped.
73
+ * Reads every project the load phase analyzes through `stage`, which enumerates and roots one
74
+ * if it reads it, and each declared consumer's project for its references to the target,
75
+ * in the same snapshot. A type error in an own file skips the unit holding it.
127
76
  */
128
77
  function readProjects(engine, host, scope, config, stage) {
129
78
  const targetRoot = scope.target.path;
130
- const discovered = discoverProjects(engine, host, scope, config.analysis.configurations);
131
- if (discovered.configFiles.length === 0 && discovered.notBuilt.length === 0) {
132
- throw new DiscoveryError(`${targetRoot} holds no compiler configuration, so the run holds no program`, []);
133
- }
134
- const ids = new Map(discovered.projects.map((project) => [project.configFile, project.id]));
135
- const loads = consumerLoads(engine, host, scope, discovered.configFiles);
136
- const consumerOf = new Map(loads.flatMap((load) => load.configFiles.map((configFile) => [configFile, load.consumer])));
137
79
  const absoluteRoot = resolvePath(host.workingDirectory(), targetRoot);
138
- const workspace = workspaceRun(engine, host, absoluteRoot, discovered.configFiles, readManifest(host, targetRoot));
80
+ const testPatterns = config.ts.test_files.map(globExpression);
139
81
  const parse = (fileName, text) => engine.parseSourceFile(fileName, text);
140
- const memberDirs = workspace?.memberDirs ?? [];
141
- // The nested packages are known only once every program is open, and every visit reads
142
- // the conventions and options they decide, so both are set in the session's first step.
143
- let nestedDirs = [];
144
- let conventions = readConventions(host, parse, [], config.ts.disabledConventions);
145
- let options;
146
- const readManifests = (opened) => {
147
- nestedDirs = nestedPackageDirs(host, normalizePath(absoluteRoot), opened
148
- .filter((one) => !consumerOf.has(one.configFile))
149
- .flatMap((one) => [one.configFile, ...one.fileNames()]), new Set(memberDirs));
150
- conventions = readConventions(host, parse, conventionManifests(host, absoluteRoot, memberDirs, nestedDirs), config.ts.disabledConventions);
151
- options = {
82
+ return loadRun(engine, host, scope, config, ({ plan, classified, runFiles }) => {
83
+ const { packages, conventions } = plan;
84
+ const options = {
152
85
  host,
153
- manifest: workspace?.manifest ?? readManifest(host, targetRoot),
154
- otherPackages: [
155
- ...(workspace?.entries ?? []),
156
- ...packageEntries(host, normalizePath(absoluteRoot), nestedDirs),
157
- ],
158
- patterns: config.rootPatterns,
159
- entryFiles: config.ts.entryFiles,
86
+ manifest: packages.manifest,
87
+ otherPackages: packages.entries,
88
+ patterns: config.roots.patterns,
89
+ entryFiles: config.ts.entry_files,
160
90
  conventions,
161
- testFiles: config.ts.testFiles,
91
+ testFiles: config.ts.test_files,
162
92
  parse,
163
- publishedAPI: config.targetKind !== "" && kindOf(config.targetKind, LANGUAGE) === "library",
164
- publishedMembers: new Set((workspace?.entries ?? []).filter((entry) => entry.published).map((entry) => entry.dir)),
165
- runFiles: new Set(opened.flatMap((one) => one.fileNames().map((name) => resolvePath(host.workingDirectory(), name)))),
93
+ publishedAPI: config.target.kind !== undefined && kindOf(config.target.kind) === "library",
94
+ publishedMembers: packages.published,
95
+ runFiles,
166
96
  };
167
- };
168
- const notBuilt = [...discovered.notBuilt];
169
- const dropped = (configFile, error) => {
170
- notBuilt.push({
171
- id: ids.get(configFile) ?? configFile,
172
- configFile,
173
- error: targetRelative(error, absoluteRoot),
174
- });
175
- };
176
- const failures = [];
177
- const unbuildable = [];
178
- const setupDropped = [];
179
- const librariesUnfound = [];
180
- const consumed = new Map();
181
- const heldFiles = new Set();
182
- let outsideTests = [];
183
- const setupMet = (configFile, met) => {
184
- const [first] = met;
185
- if (first !== undefined && isGuess(discovered, configFile)) {
186
- dropped(configFile, setupLine(first));
187
- setupDropped.push(...met);
188
- }
189
- else {
190
- unbuildable.push(...met);
191
- }
192
- };
193
- const testPatterns = config.ts.testFiles.map(globExpression);
194
- const joins = discovered.derived
195
- ? joinedTestFiles(engine, host, absoluteRoot, discovered.configFiles, testPatterns)
196
- : new Map();
197
- const programs = withTestGlobals(engine, host, parse, discovered.configFiles, withBaseUrlPaths(engine, host, [...discovered.configFiles, ...consumerOf.keys()], workspace?.programs ?? new Map()));
198
- const session = runSession(engine, [...discovered.configFiles, ...consumerOf.keys()], (opened) => {
199
- const consumer = consumerOf.get(opened.configFile);
200
- const setup = consumer === undefined ? workspace?.unbuildable(opened.configFile) : undefined;
201
- if (setup !== undefined) {
202
- setupMet(opened.configFile, [
203
- { setupClass: "workspace-member-without-source", detail: setup },
204
- ]);
205
- return undefined;
206
- }
207
- const referenceOnly = workspace === undefined || consumer !== undefined
208
- ? () => false
209
- : workspace.referenceOnly(opened.configFile, opened.rootFiles);
210
- const project = workspace === undefined || consumer !== undefined
211
- ? opened
212
- : ownedAs(opened, (file, fromExternalLibrary) => workspace.ownFile(file, fromExternalLibrary));
213
- const raw = projectErrors(diagnosticsOf(project));
214
- const errors = { load: raw.load, check: ownErrors(raw.check, referenceOnly) };
215
- const [unloaded] = errors.load;
216
- if (unloaded !== undefined &&
217
- consumer === undefined &&
218
- isGuess(discovered, project.configFile)) {
219
- dropped(project.configFile, renderDiagnostic(unloaded, (path) => relativePath(absoluteRoot, path) ?? path));
220
- return undefined;
221
- }
222
- if (errors.load.length > 0) {
223
- failures.push(...errors.load);
224
- return undefined;
225
- }
226
- const reading = readErrors(project, errors.check, {
227
- host,
228
- targetRoot: consumer === undefined
229
- ? absoluteRoot
230
- : resolvePath(host.workingDirectory(), consumer.path),
231
- paths: pathsOf(engine, project.configFile),
97
+ const heldFiles = new Set();
98
+ const answers = classified.analyzed.map(({ plan: planned, project, skips, referenceOnly }) => {
99
+ const read = () => {
100
+ const held = inventory(project, host, targetRoot);
101
+ const found = roots(project, held, targetRoot, options);
102
+ const kept = skippedRoots(project, held, skips);
103
+ const rooted = kept.length === 0
104
+ ? found
105
+ : {
106
+ ...found,
107
+ liveUnderReachability: [
108
+ ...found.liveUnderReachability,
109
+ ...kept.map((id) => ({ id, kind: "type-error", source: "" })),
110
+ ],
111
+ };
112
+ const own = sourceFilesOf(project, targetRoot);
113
+ return {
114
+ configuration: planned.id,
115
+ configFile: project.configFile,
116
+ held,
117
+ rooted,
118
+ typeErrorSkips: skips.map((one) => one.record),
119
+ skipped: skippedUnits(skips, absoluteRoot),
120
+ referenceOnly: project
121
+ .ownSourceFiles()
122
+ .filter((file) => referenceOnly(file.fileName))
123
+ .flatMap((file) => relativePath(absoluteRoot, file.fileName) ?? []),
124
+ generated: generatedFilesOf(own, generatedFiles(conventions, own)),
125
+ testFileNames: conventions.testFiles,
126
+ };
127
+ };
128
+ for (const file of project.ownSourceFiles()) {
129
+ heldFiles.add(relativePath(absoluteRoot, file.fileName) ?? file.fileName);
130
+ }
131
+ return stage(project, { configuration: planned.id, read });
232
132
  });
233
- if (consumer !== undefined && reading.missing.length > 0) {
234
- unbuildable.push(...reading.missing.map((one) => ({
235
- setupClass: "missing-consumer",
236
- detail: `the consumer ${consumer.path} does not build, its dependencies not installed: ${one.detail}`,
237
- })));
238
- return undefined;
239
- }
240
- if (reading.missing.length > 0) {
241
- setupMet(project.configFile, reading.missing);
242
- return undefined;
243
- }
244
- const unconventional = consumer === undefined
245
- ? conventionFailuresFor(conventions, project.configFile, project.ownSourceFiles().map((file) => file.fileName))
246
- : [];
247
- if (unconventional.length > 0) {
248
- setupMet(project.configFile, unconventional);
249
- return undefined;
250
- }
251
- if (consumer !== undefined) {
252
- for (const reference of consumerReferences(project, host, targetRoot, {
253
- id: consumer.id,
254
- root: consumer.path,
255
- }, config)) {
133
+ const consumed = new Map();
134
+ for (const { project, consumer } of classified.consumed) {
135
+ const side = { id: consumer.id, root: consumer.path };
136
+ for (const reference of consumerReferences(project, host, targetRoot, side, config)) {
256
137
  consumed.set(referenceKey(reference), reference);
257
138
  }
258
- return undefined;
259
- }
260
- librariesUnfound.push(...raw.unfound.map((one) => ({
261
- configFile: project.configFile,
262
- error: renderDiagnostic(one, (path) => relativePath(absoluteRoot, path) ?? path),
263
- })));
264
- const missingGlobal = raw.unfound.find(({ diagnostic }) => diagnostic.code === MISSING_GLOBAL_TYPE);
265
- const skips = missingGlobal === undefined
266
- ? reading.skips
267
- : [
268
- ...reading.skips,
269
- ...project.ownSourceFiles().map((file) => ({
270
- record: {
271
- path: relativePath(absoluteRoot, file.fileName) ?? file.fileName,
272
- line: 1,
273
- message: missingGlobal.diagnostic.text,
274
- },
275
- file,
276
- unit: file,
277
- })),
278
- ];
279
- const configuration = ids.get(project.configFile) ?? project.configFile;
280
- const read = () => {
281
- const held = inventory(project, host, targetRoot);
282
- const found = roots(project, held, targetRoot, options);
283
- const kept = skippedRoots(project, held, skips);
284
- const rooted = kept.length === 0
285
- ? found
286
- : {
287
- ...found,
288
- liveUnderReachability: [
289
- ...found.liveUnderReachability,
290
- ...kept.map((id) => ({ id, kind: "type-error", source: "" })),
291
- ],
292
- };
293
- const own = sourceFilesOf(project, targetRoot);
294
- return {
295
- configuration,
296
- configFile: project.configFile,
297
- held,
298
- rooted,
299
- typeErrorSkips: skips.map((one) => one.record),
300
- skipped: skippedUnits(skips, absoluteRoot),
301
- referenceOnly: project
302
- .ownSourceFiles()
303
- .filter((file) => referenceOnly(file.fileName))
304
- .flatMap((file) => relativePath(absoluteRoot, file.fileName) ?? []),
305
- generated: generatedFilesOf(own, generatedFiles(conventions, own)),
306
- testFileNames: conventions.testFiles,
307
- };
308
- };
309
- for (const file of project.ownSourceFiles()) {
310
- heldFiles.add(relativePath(absoluteRoot, file.fileName) ?? file.fileName);
311
- }
312
- return stage(project, { configuration, read });
313
- }, discovered.derived ? "record" : "refuse", joins.size === 0 ? programs : withJoinedTests(engine, host, programs, joins), () => {
314
- outsideTests = testFilesAt(host, targetRoot, sourcePaths(host, targetRoot).filter((path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path))), parse);
315
- }, readManifests);
316
- for (const configFile of session.unopened) {
317
- if (consumerOf.has(configFile) || !isGuess(discovered, configFile)) {
318
- throw new DiscoveryError(`${configFile} opened no project`, []);
319
139
  }
320
- dropped(configFile, "the compiler opened no project for the configuration");
321
- }
322
- if (unbuildable.length > 0) {
323
- throw new SetupError(unbuildable);
324
- }
325
- if (failures.length > 0) {
326
- throw new DiscoveryError(`${String(failures.length)} error(s), so no answer was produced`, failures);
327
- }
328
- const answers = session.projects.filter((answer) => answer !== undefined);
329
- const [first] = notBuilt;
330
- if (answers.length === 0 && setupDropped.length > 0) {
331
- throw new SetupError(setupDropped);
332
- }
333
- if (answers.length === 0 && first !== undefined) {
334
- throw new DiscoveryError(`no configuration discovery derived could be built; ${first.id}: ${first.error}`, []);
335
- }
336
- return {
337
- answers,
338
- consumers: {
339
- loaded: loads.map((load) => load.consumer),
340
- references: [...consumed.values()],
341
- },
342
- notBuilt,
343
- unanswered: session.unanswered,
344
- componentsUnread: workspace?.componentsUnread ?? [],
345
- librariesUnfound,
346
- conventionsApplied: conventions.applied,
347
- conventionUses: conventions.uses,
348
- memberDirs,
349
- nestedDirs,
350
- outsideTests,
351
- };
140
+ const outsideTests = testFilesAt(host, targetRoot, sourcePaths(host, targetRoot).filter((path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path))), parse);
141
+ return { answers, references: [...consumed.values()], outsideTests };
142
+ });
352
143
  }
353
144
  /**
354
145
  * The projects the run the scope and the configuration describe analyzes, each read
@@ -357,7 +148,11 @@ function readProjects(engine, host, scope, config, stage) {
357
148
  */
358
149
  export function runProjects(engine, host, scope, config) {
359
150
  const read = readProjects(engine, host, scope, config, (_project, opened) => opened.configuration);
360
- return { configurations: read.answers, notBuilt: read.notBuilt, unanswered: read.unanswered };
151
+ return {
152
+ configurations: read.result.answers,
153
+ notBuilt: read.classified.notBuilt,
154
+ unanswered: read.unanswered,
155
+ };
361
156
  }
362
157
  /**
363
158
  * The root set of the run the scope and the configuration describe.
@@ -368,7 +163,7 @@ export function runProjects(engine, host, scope, config) {
368
163
  export function runRoots(engine, host, scope, config, provenance) {
369
164
  const targetRoot = scope.target.path;
370
165
  const read = readProjects(engine, host, scope, config, (_project, opened) => opened.read());
371
- const projects = read.answers;
166
+ const projects = read.result.answers;
372
167
  const configurations = [];
373
168
  const merged = new Map();
374
169
  for (const answer of projects) {
@@ -399,12 +194,12 @@ export function runRoots(engine, host, scope, config, provenance) {
399
194
  const ordered = [...merged.values()].sort((a, b) => byPosition(a.position, b.position) ||
400
195
  bytewise(a.kind, b.kind) ||
401
196
  bytewise(a.source, b.source));
402
- const unmatched = unmatchedEverywhere(config.rootPatterns, projects.map((answer) => answer.rooted));
197
+ const unmatched = unmatchedEverywhere(config.roots.patterns, projects.map((answer) => answer.rooted));
403
198
  return {
404
199
  configurations,
405
200
  roots: ordered,
406
201
  findings: unmatchedRootFindings(unmatched, documentOf(host, provenance, ROOTS_SETTING, targetRoot)),
407
- notBuilt: read.notBuilt,
202
+ notBuilt: read.classified.notBuilt,
408
203
  unanswered: read.unanswered,
409
204
  };
410
205
  }
@@ -468,13 +263,13 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
468
263
  const targetRoot = scope.target.path;
469
264
  const disabled = disabledClasses(config);
470
265
  const templates = disabled.has("template-field")
471
- ? { delimiters: config.analysis.templateDelimiters, files: [] }
266
+ ? { delimiters: config.analysis.template_delimiters, files: [] }
472
267
  : readTemplates(host, targetRoot, config.analysis);
473
268
  const consumers = scope.consumers.map((consumer) => consumer.path);
474
269
  const read = readProjects(engine, host, scope, config, (project, opened) => {
475
270
  const projectRead = opened.read();
476
271
  const resolved = references(project, projectRead.held, targetRoot, {
477
- testFiles: config.ts.testFiles,
272
+ testFiles: config.ts.test_files,
478
273
  testFileNames: projectRead.testFileNames,
479
274
  });
480
275
  const evidence = evidenceRecords({
@@ -484,7 +279,7 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
484
279
  templates,
485
280
  ts: config.ts,
486
281
  consumers,
487
- ...(config.analysis.generatedFiles === "include"
282
+ ...(config.analysis.generated_files === "include"
488
283
  ? {}
489
284
  : { generated: projectRead.generated }),
490
285
  }, detectors, disabled);
@@ -525,12 +320,12 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
525
320
  extra: extra(project, projectRead, resolved.references, resolved.testFilePaths),
526
321
  };
527
322
  });
528
- const outsidePaths = read.outsideTests.map((one) => one.path);
529
- const withOutside = read.answers.map((one) => ({
323
+ const outsidePaths = read.result.outsideTests.map((one) => one.path);
324
+ const withOutside = read.result.answers.map((one) => ({
530
325
  ...one,
531
326
  references: [
532
327
  ...one.references,
533
- ...outsideTestReferences(read.outsideTests, one.projectRead.held, targetRoot),
328
+ ...outsideTestReferences(read.result.outsideTests, one.projectRead.held, targetRoot),
534
329
  ],
535
330
  testFiles: [...one.testFiles, ...outsidePaths],
536
331
  }));
@@ -539,7 +334,7 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
539
334
  const { support, testUsed } = testSupportFiles(withOutside.flatMap((one) => one.projectRead.held.symbols), withOutside.flatMap((one) => one.references), withOutside.flatMap((one) => one.projectRead.rooted.liveUnderReachability), withOutside.flatMap((one) => one.testFiles), testEvidence(host, targetRoot, withOutside));
540
335
  // A member a decode fills or a copy carries is written: a value decoded and sent again carries it on.
541
336
  const written = new Set([
542
- ...countedWrites([...withOutside.flatMap((one) => one.references), ...read.consumers.references], support, mode),
337
+ ...countedWrites([...withOutside.flatMap((one) => one.references), ...read.result.references], support, mode),
543
338
  ...withOutside.flatMap((one) => [
544
339
  ...one.decoded.filled,
545
340
  ...one.decoded.parsed,
@@ -550,7 +345,7 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
550
345
  const settled = settledSatisfaction(withOutside.map((one, index) => ({
551
346
  evidence: evidence[index] ?? [],
552
347
  held: one.projectRead.held,
553
- })), [...withOutside.flatMap((one) => one.references), ...read.consumers.references]);
348
+ })), [...withOutside.flatMap((one) => one.references), ...read.result.references]);
554
349
  const answers = withOutside.map((one, index) => {
555
350
  const { projectRead } = one;
556
351
  const satisfied = settled[index];
@@ -603,7 +398,7 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
603
398
  extra: one.extra,
604
399
  };
605
400
  });
606
- const consumed = read.consumers.references;
401
+ const consumed = read.result.references;
607
402
  const projects = answers.map((one) => consumed.length === 0
608
403
  ? one
609
404
  : {
@@ -623,15 +418,15 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
623
418
  ]),
624
419
  ],
625
420
  projects,
626
- consumers: read.consumers.loaded,
627
- notBuilt: read.notBuilt,
421
+ consumers: read.plan.discovery.consumers,
422
+ notBuilt: read.classified.notBuilt,
628
423
  unanswered: read.unanswered,
629
- componentsUnread: read.componentsUnread,
630
- librariesUnfound: read.librariesUnfound,
631
- conventionsApplied: read.conventionsApplied,
632
- conventionUses: read.conventionUses,
633
- memberDirs: read.memberDirs,
634
- nestedDirs: read.nestedDirs,
424
+ componentsUnread: read.plan.workspace?.componentsUnread ?? [],
425
+ librariesUnfound: read.classified.librariesUnfound,
426
+ conventionsApplied: read.plan.conventions.applied,
427
+ conventionUses: read.plan.conventions.uses,
428
+ memberDirs: read.plan.packages.members,
429
+ nestedDirs: read.plan.packages.nested,
635
430
  };
636
431
  }
637
432
  /**
@@ -904,7 +699,7 @@ function readAnalysis(engine, host, scope, config, provenance, mode, detectors)
904
699
  id: one.configured.configuration,
905
700
  configFile: one.configFile,
906
701
  })),
907
- testFileRules: testFileRulesOf(config.ts.testFiles, read.projects.flatMap((one) => one.configured.testFiles), read.projects.flatMap((one) => one.configured.supportFiles ?? [])),
702
+ testFileRules: testFileRulesOf(config.ts.test_files, read.projects.flatMap((one) => one.configured.testFiles), read.projects.flatMap((one) => one.configured.supportFiles ?? [])),
908
703
  typeErrorSkips: read.projects.flatMap((one) => one.typeErrorSkips),
909
704
  componentWarnings: [
910
705
  ...new Map(read.projects
@@ -934,7 +729,7 @@ function inputsOver(host, scope, config, provenance, mode, read, documents) {
934
729
  };
935
730
  const facts = {
936
731
  refusals: suppressions.refusals,
937
- unmatchedRoots: unmatchedEverywhere(config.rootPatterns, read.projects.map((one) => one.extra.rooted)),
732
+ unmatchedRoots: unmatchedEverywhere(config.roots.patterns, read.projects.map((one) => one.extra.rooted)),
938
733
  rootsDocument: documentOf(host, provenance, ROOTS_SETTING, targetRoot),
939
734
  unmatchedDeclarations: configuredDeclarations(config)
940
735
  .filter((_, at) => !read.projects.some((one) => one.extra.declarationsNamed[at] === true))