@cplieger/deadset-ts 7.2.0-dev.4 → 8.0.0-dev.10
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.
- package/README.md +1 -1
- package/dist/bin/mapper-connection.js +2 -1
- package/dist/bin/node-host.js +24 -5
- package/dist/src/analysis.js +245 -309
- package/dist/src/augmentations.js +124 -18
- package/dist/src/automatic-types.js +170 -0
- package/dist/src/build-scripts.js +425 -0
- package/dist/src/component-layer.js +4 -2
- package/dist/src/components.js +9 -9
- package/dist/src/config.js +6 -81
- package/dist/src/configuration-files.js +78 -188
- package/dist/src/configured-declarations.js +15 -20
- package/dist/src/conformance-record.js +2 -2
- package/dist/src/consumers.js +3 -30
- package/dist/src/contextual-uses.js +56 -9
- package/dist/src/contract/config.generated.js +558 -0
- package/dist/src/contract/contract.generated.js +1244 -0
- package/dist/src/contract/report.generated.js +862 -0
- package/dist/src/convention-rows.js +146 -1
- package/dist/src/conventions.js +136 -70
- package/dist/src/decorator.js +21 -18
- package/dist/src/dependencies.js +280 -62
- package/dist/src/edges.js +38 -122
- package/dist/src/element-access.js +4 -6
- package/dist/src/entry-point-gaps.js +9 -18
- package/dist/src/entry-points.js +106 -21
- package/dist/src/enum-group.js +3 -10
- package/dist/src/erased-stores.js +4 -6
- package/dist/src/exempt-classes.js +1 -63
- package/dist/src/exempt.js +21 -40
- package/dist/src/failure.js +36 -0
- package/dist/src/file-facts.js +2 -25
- package/dist/src/findings/completion.js +225 -63
- package/dist/src/findings/dependencies-and-module-machinery.js +72 -27
- package/dist/src/findings/emitters.js +6 -6
- package/dist/src/findings/interfaces.js +4 -5
- package/dist/src/findings/intra-function.js +53 -19
- package/dist/src/findings/non-code-artifacts.js +71 -39
- package/dist/src/findings/reads-and-writes.js +16 -13
- package/dist/src/findings/self-check.js +10 -12
- package/dist/src/findings/unused-declarations.js +57 -28
- package/dist/src/findings/visibility-narrowing.js +40 -18
- package/dist/src/findings-pass.js +8 -15
- package/dist/src/framework-lifecycle.js +7 -7
- package/dist/src/fs/document.js +52 -0
- package/dist/src/fs/manifest.js +72 -0
- package/dist/src/fs/tree.js +88 -0
- package/dist/src/generated-file.js +18 -4
- package/dist/src/git-ignore.js +99 -0
- package/dist/src/graph.js +9 -4
- package/dist/src/html-entries.js +6 -33
- package/dist/src/import-bindings.js +97 -0
- package/dist/src/in-operands.js +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/indexed-access.js +130 -28
- package/dist/src/injection-container.js +1 -1
- package/dist/src/interface-satisfaction.js +30 -12
- package/dist/src/intra-function-parts.js +341 -69
- package/dist/src/inventory.js +54 -29
- package/dist/src/javascript-file.js +33 -0
- package/dist/src/json-document.js +198 -67
- package/dist/src/keyof-comparisons.js +4 -6
- package/dist/src/kinds.js +3 -366
- package/dist/src/load/classify.js +270 -0
- package/dist/src/load/diagnostics.js +80 -0
- package/dist/src/load/discover.js +277 -0
- package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
- package/dist/src/load/expected-module.js +136 -0
- package/dist/src/load/load.js +27 -0
- package/dist/src/load/module-lookup.js +37 -0
- package/dist/src/load/plan.js +313 -0
- package/dist/src/load/specifiers.js +115 -0
- package/dist/src/load/synthesize.js +140 -0
- package/dist/src/load/test-globals.js +207 -0
- package/dist/src/load/test-joins.js +82 -0
- package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
- package/dist/src/{workspace-programs.js → load/workspace-programs.js} +88 -61
- package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +60 -59
- package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
- package/dist/src/{workspace.js → load/workspace.js} +62 -124
- package/dist/src/manifest.js +49 -54
- package/dist/src/matrix.js +94 -13
- package/dist/src/mdx-entries.js +174 -0
- package/dist/src/module-declarations.js +9 -13
- package/dist/src/outside-tests.js +1 -1
- package/dist/src/overrides.js +41 -10
- package/dist/src/partial.js +2 -1
- package/dist/src/paths.js +26 -15
- package/dist/src/position.js +2 -1
- package/dist/src/print.js +11 -78
- package/dist/src/product.js +13 -0
- package/dist/src/query.js +1 -0
- package/dist/src/ref.js +11 -0
- package/dist/src/references.js +52 -31
- package/dist/src/report-schema.js +51 -0
- package/dist/src/report.js +59 -41
- package/dist/src/reporters/annotations.js +15 -8
- package/dist/src/reporters/sarif.js +16 -10
- package/dist/src/reporters/template.js +4 -19
- package/dist/src/resolve.js +245 -727
- package/dist/src/roots.js +374 -116
- package/dist/src/run.js +66 -77
- package/dist/src/schema.js +320 -342
- package/dist/src/scope.js +38 -115
- package/dist/src/serialization-contract.js +649 -29
- package/dist/src/session.js +41 -29
- package/dist/src/source-files.js +40 -15
- package/dist/src/suppress-file.js +34 -29
- package/dist/src/suppress-inline.js +21 -4
- package/dist/src/suppress.js +40 -56
- package/dist/src/sweep.js +32 -17
- package/dist/src/symbol-keys.js +105 -6
- package/dist/src/template-field.js +9 -19
- package/dist/src/test-support.js +119 -18
- package/dist/src/text/compare.js +26 -0
- package/dist/src/text/glob.js +194 -0
- package/dist/src/text/named-files.js +54 -0
- package/dist/src/text/shell.js +159 -0
- package/dist/src/text/yaml.js +393 -0
- package/dist/src/type-errors.js +27 -221
- package/dist/src/type-parameter-reads.js +172 -0
- package/dist/src/unseen-loads.js +100 -0
- package/dist/src/unwrap.js +23 -0
- package/dist/src/usage.js +10 -0
- package/dist/src/verbs/analyze.js +181 -125
- package/dist/src/verbs/describe.js +9 -16
- package/dist/src/verbs/explain.js +14 -9
- package/dist/src/verbs/print-config.js +2 -1
- package/dist/src/verbs/print-projects.js +6 -4
- package/dist/src/verbs/print-retained.js +4 -2
- package/dist/src/verbs/print-roots.js +4 -2
- package/dist/src/verbs/verb.js +1 -5
- package/dist/src/verbs/version.js +14 -3
- package/dist/src/workflow-steps.js +128 -33
- package/jsr.json +1 -1
- package/package.json +5 -4
- package/src/analysis.ts +333 -457
- package/src/augmentations.ts +152 -23
- package/src/automatic-types.ts +228 -0
- package/src/build-scripts.ts +543 -0
- package/src/component-layer.ts +4 -2
- package/src/components.ts +9 -10
- package/src/config.ts +31 -299
- package/src/configuration-files.ts +100 -191
- package/src/configured-declarations.ts +18 -23
- package/src/conformance-record.ts +2 -2
- package/src/consumers.ts +6 -57
- package/src/contextual-uses.ts +64 -12
- package/src/contract/config.generated.ts +818 -0
- package/src/contract/contract.generated.ts +1308 -0
- package/src/contract/report.generated.ts +1237 -0
- package/src/convention-rows.ts +186 -1
- package/src/conventions.ts +166 -90
- package/src/decorator.ts +28 -18
- package/src/dependencies.ts +356 -78
- package/src/edges.ts +41 -140
- package/src/element-access.ts +4 -7
- package/src/entry-point-gaps.ts +11 -20
- package/src/entry-points.ts +124 -28
- package/src/enum-group.ts +2 -11
- package/src/erased-stores.ts +3 -7
- package/src/exempt-classes.ts +1 -75
- package/src/exempt.ts +36 -50
- package/src/failure.ts +63 -0
- package/src/file-facts.ts +9 -24
- package/src/finding.ts +24 -9
- package/src/findings/boundary.ts +2 -0
- package/src/findings/completion.ts +297 -77
- package/src/findings/dependencies-and-module-machinery.ts +90 -31
- package/src/findings/emitter.ts +8 -9
- package/src/findings/emitters.ts +8 -8
- package/src/findings/interfaces.ts +4 -6
- package/src/findings/intra-function.ts +64 -20
- package/src/findings/non-code-artifacts.ts +88 -50
- package/src/findings/reads-and-writes.ts +20 -16
- package/src/findings/self-check.ts +11 -17
- package/src/findings/unused-declarations.ts +65 -28
- package/src/findings/visibility-narrowing.ts +51 -19
- package/src/findings-pass.ts +10 -19
- package/src/framework-lifecycle.ts +7 -7
- package/src/fs/document.ts +70 -0
- package/src/fs/manifest.ts +92 -0
- package/src/fs/tree.ts +110 -0
- package/src/generated-file.ts +23 -4
- package/src/git-ignore.ts +122 -0
- package/src/graph.ts +11 -3
- package/src/host.ts +17 -14
- package/src/html-entries.ts +6 -33
- package/src/import-bindings.ts +128 -0
- package/src/in-operands.ts +2 -1
- package/src/index.ts +1 -1
- package/src/indexed-access.ts +152 -30
- package/src/injection-container.ts +1 -1
- package/src/interface-satisfaction.ts +33 -13
- package/src/intra-function-parts.ts +449 -85
- package/src/inventory.ts +73 -27
- package/src/javascript-file.ts +37 -0
- package/src/json-document.ts +241 -76
- package/src/keyof-comparisons.ts +3 -7
- package/src/kinds.ts +5 -413
- package/src/load/classify.ts +397 -0
- package/src/load/diagnostics.ts +144 -0
- package/src/load/discover.ts +455 -0
- package/src/{emit-map.ts → load/emit-map.ts} +1 -1
- package/src/load/expected-module.ts +188 -0
- package/src/load/load.ts +73 -0
- package/src/load/module-lookup.ts +50 -0
- package/src/load/plan.ts +504 -0
- package/src/load/specifiers.ts +168 -0
- package/src/load/synthesize.ts +211 -0
- package/src/load/test-globals.ts +251 -0
- package/src/load/test-joins.ts +98 -0
- package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
- package/src/{workspace-programs.ts → load/workspace-programs.ts} +127 -80
- package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +73 -64
- package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
- package/src/{workspace.ts → load/workspace.ts} +90 -134
- package/src/manifest.ts +81 -75
- package/src/matrix.ts +154 -18
- package/src/mdx-entries.ts +218 -0
- package/src/module-declarations.ts +11 -13
- package/src/outside-tests.ts +1 -1
- package/src/overrides.ts +51 -12
- package/src/partial.ts +3 -2
- package/src/paths.ts +27 -15
- package/src/position.ts +2 -1
- package/src/print.ts +12 -91
- package/src/product.ts +18 -0
- package/src/query.ts +11 -0
- package/src/ref.ts +13 -0
- package/src/references.ts +62 -32
- package/src/report-schema.ts +68 -0
- package/src/report.ts +105 -215
- package/src/reporters/annotations.ts +22 -11
- package/src/reporters/json.ts +1 -1
- package/src/reporters/reporter.ts +2 -4
- package/src/reporters/reporters.ts +1 -1
- package/src/reporters/sarif.ts +29 -16
- package/src/reporters/template.ts +4 -20
- package/src/reporters/text.ts +3 -3
- package/src/resolve.ts +283 -1111
- package/src/roots.ts +490 -137
- package/src/run.ts +75 -91
- package/src/schema.ts +391 -387
- package/src/scope.ts +46 -138
- package/src/serialization-contract.ts +818 -26
- package/src/session.ts +77 -54
- package/src/source-files.ts +67 -17
- package/src/suppress-file.ts +36 -34
- package/src/suppress-inline.ts +20 -3
- package/src/suppress.ts +52 -63
- package/src/sweep.ts +53 -18
- package/src/symbol-keys.ts +131 -7
- package/src/template-field.ts +15 -25
- package/src/test-support.ts +155 -18
- package/src/text/compare.ts +27 -0
- package/src/text/glob.ts +210 -0
- package/src/text/named-files.inputs.json +1522 -0
- package/src/text/named-files.ts +68 -0
- package/src/text/shell.ts +161 -0
- package/src/text/yaml.ts +423 -0
- package/src/type-errors.ts +35 -273
- package/src/type-parameter-reads.ts +227 -0
- package/src/unseen-loads.ts +134 -0
- package/src/unwrap.ts +34 -0
- package/src/usage.ts +10 -0
- package/src/verbs/analyze.ts +245 -161
- package/src/verbs/describe.ts +14 -15
- package/src/verbs/explain.ts +15 -13
- package/src/verbs/print-config.ts +2 -1
- package/src/verbs/print-projects.ts +6 -4
- package/src/verbs/print-retained.ts +4 -2
- package/src/verbs/print-roots.ts +4 -2
- package/src/verbs/verb.ts +2 -8
- package/src/verbs/version.ts +15 -3
- package/src/workflow-steps.ts +149 -34
- package/dist/src/discover.js +0 -347
- package/dist/src/glob.js +0 -65
- package/dist/src/pnpm-workspace.js +0 -120
- package/dist/src/setup-failure.js +0 -23
- package/dist/src/test-joins.js +0 -101
- package/dist/src/version.js +0 -7
- package/src/discover.ts +0 -510
- package/src/glob.ts +0 -67
- package/src/pnpm-workspace.ts +0 -135
- package/src/setup-failure.ts +0 -39
- package/src/test-joins.ts +0 -120
- package/src/version.ts +0 -7
package/dist/src/analysis.js
CHANGED
|
@@ -5,23 +5,24 @@
|
|
|
5
5
|
* makes: a view carries a project's identity in its type so a handle cannot cross to
|
|
6
6
|
* another project's checker, which holds only for views the session hands out.
|
|
7
7
|
*/
|
|
8
|
+
import { isStringLiteralLikeNode } from "@typescript/native/ast";
|
|
8
9
|
import { lineOf, readComponent } from "./component-files.js";
|
|
9
10
|
import { kindOf } from "./config.js";
|
|
10
|
-
import {
|
|
11
|
+
import { consumerReferences } from "./consumers.js";
|
|
11
12
|
import { configuredDeclarations, configuredRef, declarationsNamed, } from "./configured-declarations.js";
|
|
12
13
|
import { decorator } from "./decorator.js";
|
|
13
14
|
import { configurationNeeds, dependenciesOf, projectNeeds } from "./dependencies.js";
|
|
14
15
|
import { deprecatedDeclarations } from "./deprecation.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
16
|
+
import { moduleIdentity } from "./load/discover.js";
|
|
17
|
+
import { loadRun } from "./load/load.js";
|
|
18
|
+
import { generatedFiles } from "./conventions.js";
|
|
17
19
|
import { readEdgeSides } from "./edges.js";
|
|
18
20
|
import { enumGroup } from "./enum-group.js";
|
|
19
21
|
import { generatedFile, generatedFilesOf } from "./generated-file.js";
|
|
20
22
|
import { inOperandNames } from "./in-operands.js";
|
|
21
23
|
import { sourceFilesOf } from "./source-files.js";
|
|
22
|
-
import { evidenceRecords, heldRecords, disabledClasses, exemptionsOf, holdingWhile, isUnansweredRecord, retainedIn, } from "./exempt.js";
|
|
24
|
+
import { evidenceRecords, heldRecords, disabledClasses, exemptionsOf, holdingWhile, isUnansweredRecord, retainedIn, writtenRecords, } from "./exempt.js";
|
|
23
25
|
import { heldByInclusion, sourcePaths, sourceTree } from "./file-facts.js";
|
|
24
|
-
import { globExpression } from "./glob.js";
|
|
25
26
|
import { findingsPass, recordedFindings, rowKey } from "./findings-pass.js";
|
|
26
27
|
import { unmatchedRootFindings } from "./findings/self-check.js";
|
|
27
28
|
import { frameworkLifecycle } from "./framework-lifecycle.js";
|
|
@@ -30,27 +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 {
|
|
34
|
+
import { readManifest } from "./manifest.js";
|
|
34
35
|
import { liveFilesAt, matrixOf, referenceKey, sweepMatrix, } from "./matrix.js";
|
|
35
|
-
import { dirnamePath, extensionOf, joinPath,
|
|
36
|
+
import { ancestors, dirnamePath, extensionOf, joinPath, relativePath, resolvePath, } from "./paths.js";
|
|
36
37
|
import { byPosition, isComponentFile } from "./position.js";
|
|
37
|
-
import {
|
|
38
|
-
import { SetupError, setupLine } from "./setup-failure.js";
|
|
39
|
-
import { pathsOf, readErrors, skippedRoots, skippedUnits, } from "./type-errors.js";
|
|
38
|
+
import { skippedRoots, skippedUnits } from "./type-errors.js";
|
|
40
39
|
import { reflectiveLookup } from "./reflective-lookup.js";
|
|
41
40
|
import { references, testFileRulesOf } from "./references.js";
|
|
42
41
|
import { roots, unmatchedEverywhere, } from "./roots.js";
|
|
43
|
-
import { serializationContract } from "./serialization-contract.js";
|
|
42
|
+
import { decodedMembers, serializationContract } from "./serialization-contract.js";
|
|
44
43
|
import { outsideTestReferences, testFilesAt } from "./outside-tests.js";
|
|
45
|
-
import {
|
|
44
|
+
import { mergedGlobalInterfaces } from "./augmentations.js";
|
|
45
|
+
import { unseenLoadsOf } from "./unseen-loads.js";
|
|
46
|
+
import { GLOBALS_RUNNER, namesTestGlobals } from "./load/test-globals.js";
|
|
46
47
|
import { supportReferences, testSupportFiles } from "./test-support.js";
|
|
47
|
-
import { diagnosticsOf, ownedAs, runSession, } from "./session.js";
|
|
48
48
|
import { accessorsOf, storesOf } from "./stores.js";
|
|
49
49
|
import { isPartKind } from "./suppress.js";
|
|
50
50
|
import { bindRows, readBaseline, readIgnoreFile } from "./suppress-file.js";
|
|
51
51
|
import { inlineDirectives, inlineSuppressions } from "./suppress-inline.js";
|
|
52
52
|
import { readTemplates, templateField } from "./template-field.js";
|
|
53
|
-
import {
|
|
53
|
+
import { bytewise } from "./text/compare.js";
|
|
54
|
+
import { holdsManifest, manifestAt } from "./fs/manifest.js";
|
|
55
|
+
import { globExpression } from "./text/glob.js";
|
|
54
56
|
/** The setting whose source decides where a finding about a configured root sits. */
|
|
55
57
|
const ROOTS_SETTING = "roots.patterns";
|
|
56
58
|
/**
|
|
@@ -67,273 +69,77 @@ function documentOf(host, provenance, setting, targetRoot) {
|
|
|
67
69
|
const document = resolvePath(host.workingDirectory(), origin.label);
|
|
68
70
|
return relativePath(resolvePath(host.workingDirectory(), targetRoot), document) ?? "";
|
|
69
71
|
}
|
|
70
|
-
/** Two strings ordered bytewise. */
|
|
71
|
-
function compare(a, b) {
|
|
72
|
-
if (a === b) {
|
|
73
|
-
return 0;
|
|
74
|
-
}
|
|
75
|
-
return a < b ? -1 : 1;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* The manifests the analysis reads, each once: the target's own, then every workspace
|
|
79
|
-
* member's and every nested package's below the target root.
|
|
80
|
-
*/
|
|
81
|
-
function conventionManifests(host, targetRoot, memberDirs, nestedDirs) {
|
|
82
|
-
const found = new Map();
|
|
83
|
-
if (host.kindOf(joinPath(targetRoot, "package.json")) === "file") {
|
|
84
|
-
found.set(targetRoot, { dir: targetRoot, path: "package.json" });
|
|
85
|
-
}
|
|
86
|
-
for (const [dirs, nested] of [
|
|
87
|
-
[memberDirs, false],
|
|
88
|
-
[nestedDirs, true],
|
|
89
|
-
]) {
|
|
90
|
-
for (const dir of dirs) {
|
|
91
|
-
const below = relativePath(targetRoot, dir);
|
|
92
|
-
if (below !== undefined && !found.has(dir)) {
|
|
93
|
-
found.set(dir, { dir, path: `${below}/package.json`, nested });
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return [...found.values()];
|
|
98
|
-
}
|
|
99
72
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*/
|
|
104
|
-
function nestedPackageDirs(host, targetRoot, files, known) {
|
|
105
|
-
const seen = new Set();
|
|
106
|
-
const found = [];
|
|
107
|
-
for (const file of files) {
|
|
108
|
-
for (let dir = dirnamePath(file); dir !== targetRoot && !seen.has(dir) && relativePath(targetRoot, dir) !== undefined; dir = dirnamePath(dir)) {
|
|
109
|
-
seen.add(dir);
|
|
110
|
-
const below = relativePath(targetRoot, dir) ?? "";
|
|
111
|
-
if (!below.split("/").includes("node_modules") &&
|
|
112
|
-
!known.has(dir) &&
|
|
113
|
-
host.kindOf(joinPath(dir, "package.json")) === "file") {
|
|
114
|
-
found.push(dir);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return found.sort(compare);
|
|
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
|
|
80
|
+
const testPatterns = config.ts.test_files.map(globExpression);
|
|
139
81
|
const parse = (fileName, text) => engine.parseSourceFile(fileName, text);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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:
|
|
154
|
-
otherPackages:
|
|
155
|
-
|
|
156
|
-
|
|
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.
|
|
91
|
+
testFiles: config.ts.test_files,
|
|
162
92
|
parse,
|
|
163
|
-
publishedAPI: config.
|
|
164
|
-
publishedMembers:
|
|
93
|
+
publishedAPI: config.target.kind !== undefined && kindOf(config.target.kind) === "library",
|
|
94
|
+
publishedMembers: packages.published,
|
|
95
|
+
runFiles,
|
|
165
96
|
};
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
{ setupClass: "workspace-member-without-source", detail: setup },
|
|
202
|
-
]);
|
|
203
|
-
return undefined;
|
|
204
|
-
}
|
|
205
|
-
const referenceOnly = workspace === undefined || consumer !== undefined
|
|
206
|
-
? () => false
|
|
207
|
-
: workspace.referenceOnly(opened.configFile, opened.rootFiles);
|
|
208
|
-
const project = workspace === undefined || consumer !== undefined
|
|
209
|
-
? opened
|
|
210
|
-
: ownedAs(opened, (file, fromExternalLibrary) => workspace.ownFile(file, fromExternalLibrary));
|
|
211
|
-
const raw = projectErrors(diagnosticsOf(project));
|
|
212
|
-
const errors = { load: raw.load, check: ownErrors(raw.check, referenceOnly) };
|
|
213
|
-
const [unloaded] = errors.load;
|
|
214
|
-
if (unloaded !== undefined &&
|
|
215
|
-
consumer === undefined &&
|
|
216
|
-
isGuess(discovered, project.configFile)) {
|
|
217
|
-
dropped(project.configFile, renderDiagnostic(unloaded, (path) => relativePath(absoluteRoot, path) ?? path));
|
|
218
|
-
return undefined;
|
|
219
|
-
}
|
|
220
|
-
if (errors.load.length > 0) {
|
|
221
|
-
failures.push(...errors.load);
|
|
222
|
-
return undefined;
|
|
223
|
-
}
|
|
224
|
-
const reading = readErrors(project, errors.check, {
|
|
225
|
-
host,
|
|
226
|
-
targetRoot: consumer === undefined
|
|
227
|
-
? absoluteRoot
|
|
228
|
-
: resolvePath(host.workingDirectory(), consumer.path),
|
|
229
|
-
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 });
|
|
230
132
|
});
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
})));
|
|
236
|
-
return undefined;
|
|
237
|
-
}
|
|
238
|
-
if (reading.missing.length > 0) {
|
|
239
|
-
setupMet(project.configFile, reading.missing);
|
|
240
|
-
return undefined;
|
|
241
|
-
}
|
|
242
|
-
const unconventional = consumer === undefined
|
|
243
|
-
? conventionFailuresFor(conventions, project.configFile, project.ownSourceFiles().map((file) => file.fileName))
|
|
244
|
-
: [];
|
|
245
|
-
if (unconventional.length > 0) {
|
|
246
|
-
setupMet(project.configFile, unconventional);
|
|
247
|
-
return undefined;
|
|
248
|
-
}
|
|
249
|
-
if (consumer !== undefined) {
|
|
250
|
-
for (const reference of consumerReferences(project, host, targetRoot, {
|
|
251
|
-
id: consumer.id,
|
|
252
|
-
root: consumer.path,
|
|
253
|
-
}, 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)) {
|
|
254
137
|
consumed.set(referenceKey(reference), reference);
|
|
255
138
|
}
|
|
256
|
-
return undefined;
|
|
257
139
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
})));
|
|
262
|
-
const configuration = ids.get(project.configFile) ?? project.configFile;
|
|
263
|
-
const read = () => {
|
|
264
|
-
const held = inventory(project, host, targetRoot);
|
|
265
|
-
const found = roots(project, held, targetRoot, options);
|
|
266
|
-
const kept = skippedRoots(project, held, reading.skips);
|
|
267
|
-
const rooted = kept.length === 0
|
|
268
|
-
? found
|
|
269
|
-
: {
|
|
270
|
-
...found,
|
|
271
|
-
liveUnderReachability: [
|
|
272
|
-
...found.liveUnderReachability,
|
|
273
|
-
...kept.map((id) => ({ id, kind: "type-error", source: "" })),
|
|
274
|
-
],
|
|
275
|
-
};
|
|
276
|
-
const own = sourceFilesOf(project, targetRoot);
|
|
277
|
-
return {
|
|
278
|
-
configuration,
|
|
279
|
-
configFile: project.configFile,
|
|
280
|
-
held,
|
|
281
|
-
rooted,
|
|
282
|
-
typeErrorSkips: reading.skips.map((one) => one.record),
|
|
283
|
-
skipped: skippedUnits(reading.skips, absoluteRoot),
|
|
284
|
-
referenceOnly: project
|
|
285
|
-
.ownSourceFiles()
|
|
286
|
-
.filter((file) => referenceOnly(file.fileName))
|
|
287
|
-
.flatMap((file) => relativePath(absoluteRoot, file.fileName) ?? []),
|
|
288
|
-
generated: generatedFilesOf(own, generatedFiles(conventions, own)),
|
|
289
|
-
testFileNames: conventions.testFiles,
|
|
290
|
-
};
|
|
291
|
-
};
|
|
292
|
-
for (const file of project.ownSourceFiles()) {
|
|
293
|
-
heldFiles.add(relativePath(absoluteRoot, file.fileName) ?? file.fileName);
|
|
294
|
-
}
|
|
295
|
-
return stage(project, { configuration, read });
|
|
296
|
-
}, discovered.derived ? "record" : "refuse", joins.size === 0
|
|
297
|
-
? workspace?.programs
|
|
298
|
-
: withJoinedTests(engine, host, workspace?.programs ?? new Map(), joins), () => {
|
|
299
|
-
outsideTests = testFilesAt(host, targetRoot, sourcePaths(host, targetRoot).filter((path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path))), parse);
|
|
300
|
-
}, readManifests);
|
|
301
|
-
for (const configFile of session.unopened) {
|
|
302
|
-
if (consumerOf.has(configFile) || !isGuess(discovered, configFile)) {
|
|
303
|
-
throw new DiscoveryError(`${configFile} opened no project`, []);
|
|
304
|
-
}
|
|
305
|
-
dropped(configFile, "the compiler opened no project for the configuration");
|
|
306
|
-
}
|
|
307
|
-
if (unbuildable.length > 0) {
|
|
308
|
-
throw new SetupError(unbuildable);
|
|
309
|
-
}
|
|
310
|
-
if (failures.length > 0) {
|
|
311
|
-
throw new DiscoveryError(`${String(failures.length)} error(s), so no answer was produced`, failures);
|
|
312
|
-
}
|
|
313
|
-
const answers = session.projects.filter((answer) => answer !== undefined);
|
|
314
|
-
const [first] = notBuilt;
|
|
315
|
-
if (answers.length === 0 && setupDropped.length > 0) {
|
|
316
|
-
throw new SetupError(setupDropped);
|
|
317
|
-
}
|
|
318
|
-
if (answers.length === 0 && first !== undefined) {
|
|
319
|
-
throw new DiscoveryError(`no configuration discovery derived could be built; ${first.id}: ${first.error}`, []);
|
|
320
|
-
}
|
|
321
|
-
return {
|
|
322
|
-
answers,
|
|
323
|
-
consumers: {
|
|
324
|
-
loaded: loads.map((load) => load.consumer),
|
|
325
|
-
references: [...consumed.values()],
|
|
326
|
-
},
|
|
327
|
-
notBuilt,
|
|
328
|
-
unanswered: session.unanswered,
|
|
329
|
-
componentsUnread: workspace?.componentsUnread ?? [],
|
|
330
|
-
librariesUnfound,
|
|
331
|
-
conventionsApplied: conventions.applied,
|
|
332
|
-
conventionUses: conventions.uses,
|
|
333
|
-
memberDirs,
|
|
334
|
-
nestedDirs,
|
|
335
|
-
outsideTests,
|
|
336
|
-
};
|
|
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
|
+
});
|
|
337
143
|
}
|
|
338
144
|
/**
|
|
339
145
|
* The projects the run the scope and the configuration describe analyzes, each read
|
|
@@ -342,7 +148,11 @@ function readProjects(engine, host, scope, config, stage) {
|
|
|
342
148
|
*/
|
|
343
149
|
export function runProjects(engine, host, scope, config) {
|
|
344
150
|
const read = readProjects(engine, host, scope, config, (_project, opened) => opened.configuration);
|
|
345
|
-
return {
|
|
151
|
+
return {
|
|
152
|
+
configurations: read.result.answers,
|
|
153
|
+
notBuilt: read.classified.notBuilt,
|
|
154
|
+
unanswered: read.unanswered,
|
|
155
|
+
};
|
|
346
156
|
}
|
|
347
157
|
/**
|
|
348
158
|
* The root set of the run the scope and the configuration describe.
|
|
@@ -353,7 +163,7 @@ export function runProjects(engine, host, scope, config) {
|
|
|
353
163
|
export function runRoots(engine, host, scope, config, provenance) {
|
|
354
164
|
const targetRoot = scope.target.path;
|
|
355
165
|
const read = readProjects(engine, host, scope, config, (_project, opened) => opened.read());
|
|
356
|
-
const projects = read.answers;
|
|
166
|
+
const projects = read.result.answers;
|
|
357
167
|
const configurations = [];
|
|
358
168
|
const merged = new Map();
|
|
359
169
|
for (const answer of projects) {
|
|
@@ -381,13 +191,15 @@ export function runRoots(engine, host, scope, config, provenance) {
|
|
|
381
191
|
}
|
|
382
192
|
}
|
|
383
193
|
}
|
|
384
|
-
const ordered = [...merged.values()].sort((a, b) => byPosition(a.position, b.position) ||
|
|
385
|
-
|
|
194
|
+
const ordered = [...merged.values()].sort((a, b) => byPosition(a.position, b.position) ||
|
|
195
|
+
bytewise(a.kind, b.kind) ||
|
|
196
|
+
bytewise(a.source, b.source));
|
|
197
|
+
const unmatched = unmatchedEverywhere(config.roots.patterns, projects.map((answer) => answer.rooted));
|
|
386
198
|
return {
|
|
387
199
|
configurations,
|
|
388
200
|
roots: ordered,
|
|
389
201
|
findings: unmatchedRootFindings(unmatched, documentOf(host, provenance, ROOTS_SETTING, targetRoot)),
|
|
390
|
-
notBuilt: read.notBuilt,
|
|
202
|
+
notBuilt: read.classified.notBuilt,
|
|
391
203
|
unanswered: read.unanswered,
|
|
392
204
|
};
|
|
393
205
|
}
|
|
@@ -403,6 +215,44 @@ export const DETECTORS = new Map([
|
|
|
403
215
|
["framework-lifecycle", frameworkLifecycle],
|
|
404
216
|
["serialization-contract", serializationContract],
|
|
405
217
|
]);
|
|
218
|
+
/** The manifest section of a package test evidence counts, and the sections that keep one out of it. */
|
|
219
|
+
const DEV_SECTION = "devDependencies";
|
|
220
|
+
const OTHER_SECTIONS = ["dependencies", "peerDependencies", "optionalDependencies"];
|
|
221
|
+
/**
|
|
222
|
+
* The imports of a run's own files and the manifests below the target root that test
|
|
223
|
+
* evidence reads: a package is a devDependency of a file where the nearest manifest at or
|
|
224
|
+
* above it that declares the package declares it under `devDependencies` alone.
|
|
225
|
+
*/
|
|
226
|
+
function testEvidence(host, targetRoot, projects) {
|
|
227
|
+
const imports = new Map();
|
|
228
|
+
for (const one of projects) {
|
|
229
|
+
for (const [path, specifiers] of one.imports) {
|
|
230
|
+
imports.set(path, specifiers);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const manifests = new Map();
|
|
234
|
+
const manifestIn = (dir) => {
|
|
235
|
+
if (!manifests.has(dir)) {
|
|
236
|
+
manifests.set(dir, manifestAt(host, dir));
|
|
237
|
+
}
|
|
238
|
+
return manifests.get(dir);
|
|
239
|
+
};
|
|
240
|
+
const declares = (section, name) => typeof section === "object" && section !== null && Object.hasOwn(section, name);
|
|
241
|
+
const root = resolvePath(host.workingDirectory(), targetRoot);
|
|
242
|
+
return {
|
|
243
|
+
imports,
|
|
244
|
+
devDependency: (path, name) => {
|
|
245
|
+
for (const dir of ancestors(dirnamePath(joinPath(root, path)), root)) {
|
|
246
|
+
const manifest = manifestIn(dir);
|
|
247
|
+
const other = OTHER_SECTIONS.some((one) => declares(manifest?.[one], name));
|
|
248
|
+
if (declares(manifest?.[DEV_SECTION], name) || other) {
|
|
249
|
+
return !other;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return false;
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
406
256
|
/**
|
|
407
257
|
* Reads every project of the run, its references and exemptions, and `extra`'s answer,
|
|
408
258
|
* while the project's view is open, and merges the projects into one matrix in the run's
|
|
@@ -413,13 +263,13 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
413
263
|
const targetRoot = scope.target.path;
|
|
414
264
|
const disabled = disabledClasses(config);
|
|
415
265
|
const templates = disabled.has("template-field")
|
|
416
|
-
? { delimiters: config.analysis.
|
|
266
|
+
? { delimiters: config.analysis.template_delimiters, files: [] }
|
|
417
267
|
: readTemplates(host, targetRoot, config.analysis);
|
|
418
268
|
const consumers = scope.consumers.map((consumer) => consumer.path);
|
|
419
269
|
const read = readProjects(engine, host, scope, config, (project, opened) => {
|
|
420
270
|
const projectRead = opened.read();
|
|
421
271
|
const resolved = references(project, projectRead.held, targetRoot, {
|
|
422
|
-
testFiles: config.ts.
|
|
272
|
+
testFiles: config.ts.test_files,
|
|
423
273
|
testFileNames: projectRead.testFileNames,
|
|
424
274
|
});
|
|
425
275
|
const evidence = evidenceRecords({
|
|
@@ -429,11 +279,14 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
429
279
|
templates,
|
|
430
280
|
ts: config.ts,
|
|
431
281
|
consumers,
|
|
432
|
-
...(config.analysis.
|
|
282
|
+
...(config.analysis.generated_files === "include"
|
|
433
283
|
? {}
|
|
434
284
|
: { generated: projectRead.generated }),
|
|
435
285
|
}, detectors, disabled);
|
|
436
286
|
const components = project.ownSourceFiles().filter(isComponentFile);
|
|
287
|
+
const injected = project.program
|
|
288
|
+
.getSourceFileNames()
|
|
289
|
+
.some((name) => name.endsWith(`/node_modules/${GLOBALS_RUNNER}/globals.d.ts`));
|
|
437
290
|
const pathOf = (file) => relativePath(targetRoot, file.fileName) ?? file.fileName;
|
|
438
291
|
return {
|
|
439
292
|
projectRead,
|
|
@@ -441,45 +294,81 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
441
294
|
testFiles: resolved.testFilePaths,
|
|
442
295
|
evidence,
|
|
443
296
|
componentFiles: components.map(pathOf),
|
|
297
|
+
augmented: mergedGlobalInterfaces(project, projectRead.held, sourceFilesOf(project, targetRoot)).map((id) => ({ id, kind: "global-augmentation", source: "" })),
|
|
298
|
+
imports: new Map(project.ownSourceFiles().flatMap((file) => {
|
|
299
|
+
const path = relativePath(targetRoot, file.fileName);
|
|
300
|
+
if (path === undefined) {
|
|
301
|
+
return [];
|
|
302
|
+
}
|
|
303
|
+
const specifiers = file.imports.filter(isStringLiteralLikeNode).map((one) => one.text);
|
|
304
|
+
// A file calling the globals a program declares is written for their runner.
|
|
305
|
+
return [
|
|
306
|
+
[
|
|
307
|
+
path,
|
|
308
|
+
injected && namesTestGlobals(project, file)
|
|
309
|
+
? [...specifiers, GLOBALS_RUNNER]
|
|
310
|
+
: specifiers,
|
|
311
|
+
],
|
|
312
|
+
];
|
|
313
|
+
})),
|
|
444
314
|
componentWarnings: components.flatMap((file) => readComponent(file.originalText, extensionOf(file.fileName)).warnings.map((warning) => ({
|
|
445
315
|
path: pathOf(file),
|
|
446
316
|
line: lineOf(file.originalText, warning.offset),
|
|
447
317
|
reason: warning.reason,
|
|
448
318
|
}))),
|
|
319
|
+
decoded: decodedMembers(project, projectRead.held, productionFiles(project, targetRoot, resolved.testFilePaths), consumers),
|
|
449
320
|
extra: extra(project, projectRead, resolved.references, resolved.testFilePaths),
|
|
450
321
|
};
|
|
451
322
|
});
|
|
452
|
-
const outsidePaths = read.outsideTests.map((one) => one.path);
|
|
453
|
-
const withOutside = read.answers.map((one) => ({
|
|
323
|
+
const outsidePaths = read.result.outsideTests.map((one) => one.path);
|
|
324
|
+
const withOutside = read.result.answers.map((one) => ({
|
|
454
325
|
...one,
|
|
455
326
|
references: [
|
|
456
327
|
...one.references,
|
|
457
|
-
...outsideTestReferences(read.outsideTests, one.projectRead.held, targetRoot),
|
|
328
|
+
...outsideTestReferences(read.result.outsideTests, one.projectRead.held, targetRoot),
|
|
458
329
|
],
|
|
459
330
|
testFiles: [...one.testFiles, ...outsidePaths],
|
|
460
331
|
}));
|
|
461
332
|
// Test-support code is code only test code imports in any configuration of the run: a
|
|
462
333
|
// configuration that holds no test file says nothing about what the tests import.
|
|
463
|
-
const support = 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));
|
|
464
|
-
|
|
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));
|
|
335
|
+
// A member a decode fills or a copy carries is written: a value decoded and sent again carries it on.
|
|
336
|
+
const written = new Set([
|
|
337
|
+
...countedWrites([...withOutside.flatMap((one) => one.references), ...read.result.references], support, mode),
|
|
338
|
+
...withOutside.flatMap((one) => [
|
|
339
|
+
...one.decoded.filled,
|
|
340
|
+
...one.decoded.parsed,
|
|
341
|
+
...one.decoded.copied,
|
|
342
|
+
]),
|
|
343
|
+
]);
|
|
344
|
+
const evidence = withOutside.map((one) => writtenRecords(one.evidence, written));
|
|
345
|
+
const settled = settledSatisfaction(withOutside.map((one, index) => ({
|
|
346
|
+
evidence: evidence[index] ?? [],
|
|
347
|
+
held: one.projectRead.held,
|
|
348
|
+
})), [...withOutside.flatMap((one) => one.references), ...read.result.references]);
|
|
465
349
|
const answers = withOutside.map((one, index) => {
|
|
466
350
|
const { projectRead } = one;
|
|
467
351
|
const satisfied = settled[index];
|
|
468
|
-
const detected = heldRecords(satisfied?.evidence ??
|
|
352
|
+
const detected = heldRecords(satisfied?.evidence ?? evidence[index] ?? [], {
|
|
469
353
|
mode,
|
|
470
354
|
testFiles: new Set([...one.testFiles, ...support]),
|
|
471
355
|
});
|
|
472
356
|
const exempt = detected.records;
|
|
473
357
|
const made = supportReferences([...one.references, ...(satisfied?.references ?? [])], support);
|
|
474
358
|
const held = new Set(projectRead.held.symbols.map((symbol) => symbol.position.path));
|
|
475
|
-
const supportFiles = [...support].filter((path) => held.has(path)).sort();
|
|
359
|
+
const supportFiles = [...support].filter((path) => held.has(path)).sort(bytewise);
|
|
360
|
+
const testUsedFiles = [...testUsed].filter((path) => held.has(path)).sort(bytewise);
|
|
476
361
|
const configured = {
|
|
477
362
|
configuration: projectRead.configuration,
|
|
478
363
|
symbols: projectRead.held.symbols,
|
|
479
364
|
references: [...made, ...evidenceReferences(projectRead.held.symbols, detected.inTestFiles)],
|
|
480
|
-
|
|
481
|
-
|
|
365
|
+
// The augmentations are rooted after test support is read: an outside declaration
|
|
366
|
+
// naming one calls nothing of its file.
|
|
367
|
+
roots: [...projectRead.rooted.liveUnderReachability, ...one.augmented],
|
|
368
|
+
testFiles: [...one.testFiles, ...supportFiles],
|
|
482
369
|
...(supportFiles.length === 0 ? {} : { supportFiles }),
|
|
370
|
+
...(testUsedFiles.length === 0 ? {} : { testUsedFiles }),
|
|
371
|
+
...(projectRead.held.ambient.size === 0 ? {} : { ambient: projectRead.held.ambient }),
|
|
483
372
|
...(projectRead.referenceOnly.length === 0
|
|
484
373
|
? {}
|
|
485
374
|
: { referenceOnly: projectRead.referenceOnly }),
|
|
@@ -498,15 +387,19 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
498
387
|
.filter((reference) => reference.resolution === "by-name")
|
|
499
388
|
.map((reference) => reference.to),
|
|
500
389
|
...exempt.filter(isUnansweredRecord).map((record) => record.id),
|
|
390
|
+
...one.decoded.unanswered,
|
|
501
391
|
],
|
|
392
|
+
filledOutside: one.decoded.filled,
|
|
502
393
|
typeErrorSkips: projectRead.typeErrorSkips,
|
|
394
|
+
unmappedEntries: projectRead.rooted.unmappedEntries,
|
|
395
|
+
heldScripts: projectRead.rooted.heldScripts,
|
|
503
396
|
skipped: projectRead.skipped,
|
|
504
397
|
componentFiles: one.componentFiles,
|
|
505
398
|
componentWarnings: one.componentWarnings,
|
|
506
399
|
extra: one.extra,
|
|
507
400
|
};
|
|
508
401
|
});
|
|
509
|
-
const consumed = read.
|
|
402
|
+
const consumed = read.result.references;
|
|
510
403
|
const projects = answers.map((one) => consumed.length === 0
|
|
511
404
|
? one
|
|
512
405
|
: {
|
|
@@ -526,15 +419,17 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
526
419
|
]),
|
|
527
420
|
],
|
|
528
421
|
projects,
|
|
529
|
-
consumers: read.consumers
|
|
530
|
-
notBuilt: read.notBuilt,
|
|
422
|
+
consumers: read.plan.discovery.consumers,
|
|
423
|
+
notBuilt: read.classified.notBuilt,
|
|
531
424
|
unanswered: read.unanswered,
|
|
532
|
-
componentsUnread: read.componentsUnread,
|
|
533
|
-
librariesUnfound: read.librariesUnfound,
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
425
|
+
componentsUnread: read.plan.workspace?.componentsUnread ?? [],
|
|
426
|
+
librariesUnfound: read.classified.librariesUnfound,
|
|
427
|
+
unresolvedSpecifiers: read.classified.unresolvedSpecifiers,
|
|
428
|
+
unread: read.plan.unread,
|
|
429
|
+
conventionsApplied: read.plan.conventions.applied,
|
|
430
|
+
conventionUses: read.plan.conventions.uses,
|
|
431
|
+
memberDirs: read.plan.packages.members,
|
|
432
|
+
nestedDirs: read.plan.packages.nested,
|
|
538
433
|
};
|
|
539
434
|
}
|
|
540
435
|
/**
|
|
@@ -587,6 +482,13 @@ function evidenceReferences(symbols, inTestFiles) {
|
|
|
587
482
|
];
|
|
588
483
|
});
|
|
589
484
|
}
|
|
485
|
+
/**
|
|
486
|
+
* The declarations a write the mode counts stores into, a write a test-support file
|
|
487
|
+
* makes being a test's.
|
|
488
|
+
*/
|
|
489
|
+
function countedWrites(references, support, mode) {
|
|
490
|
+
return new Set(supportReferences(references, support).flatMap((reference) => reference.use === "write" && !(mode.production && reference.test) ? [reference.to] : []));
|
|
491
|
+
}
|
|
590
492
|
/**
|
|
591
493
|
* The declarations every reference the mode counts stores into, a loaded consumer's
|
|
592
494
|
* reference counting as a read: what the write-only kind would report but for a record.
|
|
@@ -657,7 +559,7 @@ function sweptOf(read, input) {
|
|
|
657
559
|
unanswered: read.unanswered,
|
|
658
560
|
heldByUnanswered: [...held],
|
|
659
561
|
skipped: read.projects.flatMap((one) => one.skipped),
|
|
660
|
-
componentFiles: [...new Set(read.projects.flatMap((one) => one.componentFiles))].sort(
|
|
562
|
+
componentFiles: [...new Set(read.projects.flatMap((one) => one.componentFiles))].sort(bytewise),
|
|
661
563
|
};
|
|
662
564
|
}
|
|
663
565
|
/**
|
|
@@ -671,6 +573,11 @@ function sweptOf(read, input) {
|
|
|
671
573
|
export function runSweep(engine, host, scope, config, input, detectors = DETECTORS) {
|
|
672
574
|
return sweptOf(readRun(engine, host, scope, config, input.mode, detectors, () => undefined), input);
|
|
673
575
|
}
|
|
576
|
+
/** The project's own files below the target root that are no test file. */
|
|
577
|
+
function productionFiles(project, targetRoot, testFiles) {
|
|
578
|
+
const tests = new Set(testFiles);
|
|
579
|
+
return [...sourceFilesOf(project, targetRoot).byPath].flatMap(([path, file]) => tests.has(path) ? [] : [file]);
|
|
580
|
+
}
|
|
674
581
|
/** Reads a run's projects with every per-project fact an emitter reads. */
|
|
675
582
|
export function readEmitterRun(engine, host, scope, config, mode, detectors) {
|
|
676
583
|
const targetRoot = scope.target.path;
|
|
@@ -686,8 +593,9 @@ export function readEmitterRun(engine, host, scope, config, mode, detectors) {
|
|
|
686
593
|
directives: inlineDirectives(project, read.held, targetRoot).filter((directive) => !read.referenceOnly.includes(directive.site.path)),
|
|
687
594
|
declarationsNamed: declarationsNamed(project, read.held, configuredDeclarations(config)),
|
|
688
595
|
parts: projectParts(project, read.held, references, targetRoot),
|
|
596
|
+
unseenLoads: unseenLoadsOf(project, read.configuration, targetRoot, testFiles),
|
|
689
597
|
}));
|
|
690
|
-
// Whether a declaration carries the marker decides its code, so one whose
|
|
598
|
+
// Whether a declaration carries the marker decides its code, so one whose answer went
|
|
691
599
|
// unread is reported by nothing.
|
|
692
600
|
const unread = run.projects.flatMap((one) => one.extra.deprecation.unanswered);
|
|
693
601
|
return unread.length === 0
|
|
@@ -698,7 +606,8 @@ export function readEmitterRun(engine, host, scope, config, mode, detectors) {
|
|
|
698
606
|
* The workspace members whose dependencies the run judges: `read` holds those a built
|
|
699
607
|
* project holds a file below, `unbuilt` the others whose own directory, the nearest
|
|
700
608
|
* manifest's above the configuration, holds a configuration the run could not build. A
|
|
701
|
-
* member no configuration holds a file of is in neither.
|
|
609
|
+
* member no configuration holds a file of is in neither. A nested package no built project
|
|
610
|
+
* holds a file below joins `unbuilt` the same way.
|
|
702
611
|
*/
|
|
703
612
|
function judgedMembers(host, targetRoot, read) {
|
|
704
613
|
const root = resolvePath(host.workingDirectory(), targetRoot);
|
|
@@ -717,20 +626,23 @@ function judgedMembers(host, targetRoot, read) {
|
|
|
717
626
|
judged.unbuilt.push(dir);
|
|
718
627
|
}
|
|
719
628
|
}
|
|
629
|
+
for (const dir of read.nestedDirs) {
|
|
630
|
+
const below = relativePath(root, dir);
|
|
631
|
+
if (below !== undefined &&
|
|
632
|
+
owners.has(dir) &&
|
|
633
|
+
![...held].some((path) => path.startsWith(`${below}/`))) {
|
|
634
|
+
judged.unbuilt.push(dir);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
720
637
|
return judged;
|
|
721
638
|
}
|
|
722
639
|
/** The directory of the nearest `package.json` at or above a file, inside `root`, else `root`. */
|
|
723
640
|
function nearestManifestDir(host, root, file) {
|
|
724
|
-
|
|
725
|
-
if (host.kindOf(joinPath(dir, "package.json")) === "file") {
|
|
726
|
-
return dir;
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
return root;
|
|
641
|
+
return ancestors(dirnamePath(file), root).find((dir) => holdsManifest(host, dir)) ?? root;
|
|
730
642
|
}
|
|
731
643
|
/**
|
|
732
644
|
* The input every emitter reads over one sweep of a read run: the facts beside the sweep
|
|
733
|
-
* each
|
|
645
|
+
* each emitter reads, every per-project one read in the same session as the sweep.
|
|
734
646
|
*/
|
|
735
647
|
export function emitterInputOver(host, scope, config, read, input, selfCheck) {
|
|
736
648
|
const targetRoot = scope.target.path;
|
|
@@ -752,6 +664,7 @@ export function emitterInputOver(host, scope, config, read, input, selfCheck) {
|
|
|
752
664
|
heldByInclusion: new Set(projects.flatMap((one) => one.extra.heldByInclusion)),
|
|
753
665
|
generated: new Set(projects.flatMap((one) => one.extra.generated)),
|
|
754
666
|
inOperands: new Set(projects.flatMap((one) => one.extra.inOperands)),
|
|
667
|
+
unseenLoads: projects.flatMap((one) => one.extra.unseenLoads),
|
|
755
668
|
},
|
|
756
669
|
boundary: {
|
|
757
670
|
consumers: {
|
|
@@ -760,6 +673,7 @@ export function emitterInputOver(host, scope, config, read, input, selfCheck) {
|
|
|
760
673
|
},
|
|
761
674
|
encapsulated: readManifest(host, targetRoot).declaresExports,
|
|
762
675
|
edges: readEdgeSides(host, targetRoot),
|
|
676
|
+
filledOutside: new Set(projects.flatMap((one) => one.filledOutside)),
|
|
763
677
|
},
|
|
764
678
|
selfCheck,
|
|
765
679
|
intraFunction: intraFunctionFacts(projects.map((one) => one.extra.parts), projects.flatMap((one) => one.configured.references), new Set([...swept.exempt.map((one) => one.id), ...swept.heldByUnanswered])),
|
|
@@ -770,7 +684,7 @@ export function emitterInputOver(host, scope, config, read, input, selfCheck) {
|
|
|
770
684
|
* directives, the ignore file's entries and the baseline's rows are bound before any
|
|
771
685
|
* sweep, and the run is swept once under every bound record's mark and once under none,
|
|
772
686
|
* so a record is decided against the finding its code would have produced. The
|
|
773
|
-
*
|
|
687
|
+
* configuration family reports the refused suppressions and the roots that named nothing.
|
|
774
688
|
* Beside the inputs it answers the projects and test-file rules a report names.
|
|
775
689
|
*/
|
|
776
690
|
function readAnalysis(engine, host, scope, config, provenance, mode, detectors) {
|
|
@@ -788,7 +702,7 @@ function readAnalysis(engine, host, scope, config, provenance, mode, detectors)
|
|
|
788
702
|
id: one.configured.configuration,
|
|
789
703
|
configFile: one.configFile,
|
|
790
704
|
})),
|
|
791
|
-
testFileRules: testFileRulesOf(config.ts.
|
|
705
|
+
testFileRules: testFileRulesOf(config.ts.test_files, read.projects.flatMap((one) => one.configured.testFiles), read.projects.flatMap((one) => one.configured.supportFiles ?? [])),
|
|
792
706
|
typeErrorSkips: read.projects.flatMap((one) => one.typeErrorSkips),
|
|
793
707
|
componentWarnings: [
|
|
794
708
|
...new Map(read.projects
|
|
@@ -800,7 +714,12 @@ function readAnalysis(engine, host, scope, config, provenance, mode, detectors)
|
|
|
800
714
|
unanswered: read.unanswered,
|
|
801
715
|
componentsUnread: read.componentsUnread,
|
|
802
716
|
librariesUnfound: read.librariesUnfound,
|
|
717
|
+
unresolvedSpecifiers: read.unresolvedSpecifiers,
|
|
718
|
+
unread: read.unread,
|
|
803
719
|
conventionsApplied: read.conventionsApplied,
|
|
720
|
+
unmappedEntries: unmappedEverywhere(read.projects),
|
|
721
|
+
heldScripts: read.projects.flatMap((one) => one.heldScripts.map((held) => ({ ...held, configFile: one.configFile }))),
|
|
722
|
+
unseenLoads: read.projects.flatMap((one) => one.extra.unseenLoads),
|
|
804
723
|
},
|
|
805
724
|
configured: read.projects.map((one) => one.configured),
|
|
806
725
|
symbols,
|
|
@@ -816,7 +735,7 @@ function inputsOver(host, scope, config, provenance, mode, read, documents) {
|
|
|
816
735
|
};
|
|
817
736
|
const facts = {
|
|
818
737
|
refusals: suppressions.refusals,
|
|
819
|
-
unmatchedRoots: unmatchedEverywhere(config.
|
|
738
|
+
unmatchedRoots: unmatchedEverywhere(config.roots.patterns, read.projects.map((one) => one.extra.rooted)),
|
|
820
739
|
rootsDocument: documentOf(host, provenance, ROOTS_SETTING, targetRoot),
|
|
821
740
|
unmatchedDeclarations: configuredDeclarations(config)
|
|
822
741
|
.filter((_, at) => !read.projects.some((one) => one.extra.declarationsNamed[at] === true))
|
|
@@ -837,9 +756,22 @@ function inputsOver(host, scope, config, provenance, mode, read, documents) {
|
|
|
837
756
|
suppressions,
|
|
838
757
|
};
|
|
839
758
|
}
|
|
759
|
+
/** The manifest entries every project of the run reads back to no file, in the first project's order. */
|
|
760
|
+
function unmappedEverywhere(projects) {
|
|
761
|
+
const key = (entry) => `${entry.dir}\u0000${entry.member}`;
|
|
762
|
+
const [first, ...rest] = projects;
|
|
763
|
+
const others = rest.map((one) => new Set(one.unmappedEntries.map(key)));
|
|
764
|
+
const found = new Map();
|
|
765
|
+
for (const entry of first?.unmappedEntries ?? []) {
|
|
766
|
+
if (others.every((one) => one.has(key(entry)))) {
|
|
767
|
+
found.set(key(entry), entry);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
return [...found.values()];
|
|
771
|
+
}
|
|
840
772
|
/**
|
|
841
773
|
* The analysis of the run the scope and the configuration describe: the run read with its
|
|
842
|
-
* suppressions bound, every
|
|
774
|
+
* suppressions bound, every emitter's findings with the suppressions applied and the
|
|
843
775
|
* declared edges evaluated, the projects and test-file rules the report names, and the sweep
|
|
844
776
|
* an explanation reads.
|
|
845
777
|
*/
|
|
@@ -850,12 +782,16 @@ export function runAnalysis(engine, host, scope, config, provenance, mode, detec
|
|
|
850
782
|
}
|
|
851
783
|
/**
|
|
852
784
|
* One count per configuration of the run in which the checker left a question unanswered:
|
|
853
|
-
* the questions asked in its project,
|
|
785
|
+
* the questions asked in its project, a formed program's manifest that does not parse or cannot
|
|
786
|
+
* be read and a package whose command strings name files the project holds each counted as one, and the
|
|
787
|
+
* declarations of its own the run holds for them.
|
|
854
788
|
*/
|
|
855
789
|
export function unansweredCounts(analysis) {
|
|
856
790
|
const held = new Set(analysis.swept.heldByUnanswered);
|
|
857
791
|
return analysis.run.projects.flatMap((project) => {
|
|
858
|
-
const questions = analysis.run.unanswered.filter((one) => one.configFile === project.configFile).length
|
|
792
|
+
const questions = analysis.run.unanswered.filter((one) => one.configFile === project.configFile).length +
|
|
793
|
+
analysis.run.unread.filter((one) => one.kind === "manifest" && one.configFile === project.configFile).length +
|
|
794
|
+
analysis.run.heldScripts.filter((one) => one.configFile === project.configFile).length;
|
|
859
795
|
if (questions === 0) {
|
|
860
796
|
return [];
|
|
861
797
|
}
|