@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/src/analysis.ts
CHANGED
|
@@ -6,14 +6,10 @@
|
|
|
6
6
|
* another project's checker, which holds only for views the session hands out.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { isStringLiteralLikeNode, type SourceFile } from "@typescript/native/ast";
|
|
9
10
|
import { lineOf, readComponent } from "./component-files.ts";
|
|
10
|
-
import { kindOf, type
|
|
11
|
-
import {
|
|
12
|
-
consumerLoads,
|
|
13
|
-
consumerReferences,
|
|
14
|
-
moduleIdentity,
|
|
15
|
-
type LoadedConsumer,
|
|
16
|
-
} from "./consumers.ts";
|
|
11
|
+
import { kindOf, type PartialConfig, type Provenance, type ResolvedConfig } from "./config.ts";
|
|
12
|
+
import { consumerReferences } from "./consumers.ts";
|
|
17
13
|
import {
|
|
18
14
|
configuredDeclarations,
|
|
19
15
|
configuredRef,
|
|
@@ -22,24 +18,10 @@ import {
|
|
|
22
18
|
import { decorator } from "./decorator.ts";
|
|
23
19
|
import { configurationNeeds, dependenciesOf, projectNeeds } from "./dependencies.ts";
|
|
24
20
|
import { deprecatedDeclarations, type Deprecation } from "./deprecation.ts";
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
projectErrors,
|
|
30
|
-
renderDiagnostic,
|
|
31
|
-
targetRelative,
|
|
32
|
-
type LocatedDiagnostic,
|
|
33
|
-
type NotBuilt,
|
|
34
|
-
} from "./discover.ts";
|
|
35
|
-
import {
|
|
36
|
-
conventionFailuresFor,
|
|
37
|
-
generatedFiles,
|
|
38
|
-
readConventions,
|
|
39
|
-
type AppliedConvention,
|
|
40
|
-
type ConventionManifest,
|
|
41
|
-
type Conventions,
|
|
42
|
-
} from "./conventions.ts";
|
|
21
|
+
import { moduleIdentity, type LoadedConsumer, type NotBuilt } from "./load/discover.ts";
|
|
22
|
+
import type { LibraryUnfound } from "./load/classify.ts";
|
|
23
|
+
import { loadRun, type LoadedRun } from "./load/load.ts";
|
|
24
|
+
import { generatedFiles, type AppliedConvention } from "./conventions.ts";
|
|
43
25
|
import { readEdgeSides } from "./edges.ts";
|
|
44
26
|
import { enumGroup } from "./enum-group.ts";
|
|
45
27
|
import { generatedFile, generatedFilesOf } from "./generated-file.ts";
|
|
@@ -53,12 +35,12 @@ import {
|
|
|
53
35
|
holdingWhile,
|
|
54
36
|
isUnansweredRecord,
|
|
55
37
|
retainedIn,
|
|
38
|
+
writtenRecords,
|
|
56
39
|
type Detector,
|
|
57
40
|
type Detectors,
|
|
58
41
|
} from "./exempt.ts";
|
|
59
42
|
import type { TSExemptionClass } from "./exempt-classes.ts";
|
|
60
43
|
import { heldByInclusion, sourcePaths, sourceTree } from "./file-facts.ts";
|
|
61
|
-
import { globExpression } from "./glob.ts";
|
|
62
44
|
import type { Finding } from "./finding.ts";
|
|
63
45
|
import { findingsPass, recordedFindings, rowKey, type PassResult } from "./findings-pass.ts";
|
|
64
46
|
import type { EmitterInput } from "./findings/emitter.ts";
|
|
@@ -70,7 +52,7 @@ import { injectionContainer } from "./injection-container.ts";
|
|
|
70
52
|
import { interfaceSatisfaction, settledSatisfaction } from "./interface-satisfaction.ts";
|
|
71
53
|
import { intraFunctionFacts, projectParts, type ProjectParts } from "./intra-function-parts.ts";
|
|
72
54
|
import { inventory, type Inventory, type InventorySymbol } from "./inventory.ts";
|
|
73
|
-
import {
|
|
55
|
+
import { readManifest, type ManifestEntry } from "./manifest.ts";
|
|
74
56
|
import {
|
|
75
57
|
liveFilesAt,
|
|
76
58
|
matrixOf,
|
|
@@ -81,53 +63,46 @@ import {
|
|
|
81
63
|
type SweepResult,
|
|
82
64
|
} from "./matrix.ts";
|
|
83
65
|
import {
|
|
66
|
+
ancestors,
|
|
84
67
|
dirnamePath,
|
|
85
68
|
extensionOf,
|
|
86
69
|
joinPath,
|
|
87
|
-
normalizePath,
|
|
88
70
|
relativePath,
|
|
89
71
|
resolvePath,
|
|
90
72
|
} from "./paths.ts";
|
|
91
73
|
import type { UnansweredQuestion } from "./query.ts";
|
|
92
74
|
import { byPosition, isComponentFile, type Position } from "./position.ts";
|
|
93
|
-
import {
|
|
94
|
-
import {
|
|
95
|
-
import {
|
|
96
|
-
pathsOf,
|
|
97
|
-
readErrors,
|
|
98
|
-
skippedRoots,
|
|
99
|
-
skippedUnits,
|
|
100
|
-
type SkippedUnit,
|
|
101
|
-
} from "./type-errors.ts";
|
|
75
|
+
import type { TypeErrorSkip, UnansweredCount } from "./report.ts";
|
|
76
|
+
import { skippedRoots, skippedUnits, type SkippedUnit } from "./type-errors.ts";
|
|
102
77
|
import { reflectiveLookup } from "./reflective-lookup.ts";
|
|
103
78
|
import { references, testFileRulesOf, type Reference, type TestFileRule } from "./references.ts";
|
|
104
79
|
import {
|
|
105
80
|
roots,
|
|
106
81
|
unmatchedEverywhere,
|
|
82
|
+
type Root,
|
|
107
83
|
type RootKind,
|
|
108
|
-
type RootOptions,
|
|
109
84
|
type Roots,
|
|
85
|
+
type HeldScripts,
|
|
110
86
|
} from "./roots.ts";
|
|
111
87
|
import type { Scope } from "./scope.ts";
|
|
112
|
-
import { serializationContract } from "./serialization-contract.ts";
|
|
88
|
+
import { decodedMembers, serializationContract, type Decoded } from "./serialization-contract.ts";
|
|
113
89
|
import { outsideTestReferences, testFilesAt, type OutsideTest } from "./outside-tests.ts";
|
|
114
|
-
import {
|
|
115
|
-
import {
|
|
116
|
-
import {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
type OpenedFiles,
|
|
122
|
-
type ProjectView,
|
|
123
|
-
} from "./session.ts";
|
|
90
|
+
import { mergedGlobalInterfaces } from "./augmentations.ts";
|
|
91
|
+
import { unseenLoadsOf, type UnseenLoad } from "./unseen-loads.ts";
|
|
92
|
+
import type { UnresolvedSpecifier } from "./load/specifiers.ts";
|
|
93
|
+
import type { UnreadInput } from "./load/plan.ts";
|
|
94
|
+
import { GLOBALS_RUNNER, namesTestGlobals } from "./load/test-globals.ts";
|
|
95
|
+
import { supportReferences, testSupportFiles, type TestEvidence } from "./test-support.ts";
|
|
96
|
+
import type { Engine, ProjectView } from "./session.ts";
|
|
124
97
|
import { accessorsOf, storesOf } from "./stores.ts";
|
|
125
98
|
import { isPartKind, type SuppressionRecord, type Suppressions, type Verdict } from "./suppress.ts";
|
|
126
99
|
import { bindRows, readBaseline, readIgnoreFile, type Recorded } from "./suppress-file.ts";
|
|
127
100
|
import { inlineDirectives, inlineSuppressions, type InlineDirective } from "./suppress-inline.ts";
|
|
128
101
|
import type { Exemption, Mode, SweepInput } from "./sweep.ts";
|
|
129
102
|
import { readTemplates, templateField } from "./template-field.ts";
|
|
130
|
-
import {
|
|
103
|
+
import { bytewise } from "./text/compare.ts";
|
|
104
|
+
import { holdsManifest, manifestAt } from "./fs/manifest.ts";
|
|
105
|
+
import { globExpression } from "./text/glob.ts";
|
|
131
106
|
|
|
132
107
|
/** The setting whose source decides where a finding about a configured root sits. */
|
|
133
108
|
const ROOTS_SETTING = "roots.patterns";
|
|
@@ -184,14 +159,6 @@ function documentOf(
|
|
|
184
159
|
return relativePath(resolvePath(host.workingDirectory(), targetRoot), document) ?? "";
|
|
185
160
|
}
|
|
186
161
|
|
|
187
|
-
/** Two strings ordered bytewise. */
|
|
188
|
-
function compare(a: string, b: string): number {
|
|
189
|
-
if (a === b) {
|
|
190
|
-
return 0;
|
|
191
|
-
}
|
|
192
|
-
return a < b ? -1 : 1;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
162
|
/** What every stage after the root set reads of one project. */
|
|
196
163
|
interface ProjectRead {
|
|
197
164
|
readonly configuration: string;
|
|
@@ -221,304 +188,52 @@ interface OpenedProject {
|
|
|
221
188
|
readonly read: () => ProjectRead;
|
|
222
189
|
}
|
|
223
190
|
|
|
224
|
-
/** What a run
|
|
225
|
-
interface
|
|
226
|
-
|
|
227
|
-
readonly loaded: readonly LoadedConsumer[];
|
|
191
|
+
/** What reading a loaded run's projects answered. */
|
|
192
|
+
interface ProjectsRead<Answer> {
|
|
193
|
+
readonly answers: readonly Answer[];
|
|
228
194
|
/** Every reference a consumer makes to a declaration of the target, each once. */
|
|
229
195
|
readonly references: readonly Reference[];
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/** What a run read of its projects: each target project's answer, and its consumers. */
|
|
233
|
-
interface ReadProjects<Answer> {
|
|
234
|
-
readonly answers: readonly Answer[];
|
|
235
|
-
readonly consumers: ConsumerReads;
|
|
236
|
-
/** The derived configurations the run dropped, in the order it met them. */
|
|
237
|
-
readonly notBuilt: readonly NotBuilt[];
|
|
238
|
-
/** Every question the checker could not answer, each once. */
|
|
239
|
-
readonly unanswered: readonly UnansweredQuestion[];
|
|
240
|
-
/** Per configuration whose component files the run cannot read, the reason. */
|
|
241
|
-
readonly componentsUnread: readonly ComponentsUnread[];
|
|
242
|
-
/** Per analyzed configuration, each library it names that the compiler cannot find. */
|
|
243
|
-
readonly librariesUnfound: readonly LibraryUnfound[];
|
|
244
|
-
/** The convention rows the run applied. */
|
|
245
|
-
readonly conventionsApplied: readonly AppliedConvention[];
|
|
246
|
-
/** The dependencies the applied rows' short names use. */
|
|
247
|
-
readonly conventionUses: readonly string[];
|
|
248
|
-
/** The directory of every workspace member, absolute. */
|
|
249
|
-
readonly memberDirs: readonly string[];
|
|
250
|
-
/** The directory of every nested package, absolute. */
|
|
251
|
-
readonly nestedDirs: readonly string[];
|
|
252
196
|
/** The test files below the target root no project the run reads holds, parsed. */
|
|
253
197
|
readonly outsideTests: readonly OutsideTest[];
|
|
254
198
|
}
|
|
255
199
|
|
|
256
200
|
/**
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
|
|
260
|
-
function conventionManifests(
|
|
261
|
-
host: Host,
|
|
262
|
-
targetRoot: string,
|
|
263
|
-
memberDirs: readonly string[],
|
|
264
|
-
nestedDirs: readonly string[],
|
|
265
|
-
): readonly ConventionManifest[] {
|
|
266
|
-
const found = new Map<string, ConventionManifest>();
|
|
267
|
-
if (host.kindOf(joinPath(targetRoot, "package.json")) === "file") {
|
|
268
|
-
found.set(targetRoot, { dir: targetRoot, path: "package.json" });
|
|
269
|
-
}
|
|
270
|
-
for (const [dirs, nested] of [
|
|
271
|
-
[memberDirs, false],
|
|
272
|
-
[nestedDirs, true],
|
|
273
|
-
] as const) {
|
|
274
|
-
for (const dir of dirs) {
|
|
275
|
-
const below = relativePath(targetRoot, dir);
|
|
276
|
-
if (below !== undefined && !found.has(dir)) {
|
|
277
|
-
found.set(dir, { dir, path: `${below}/package.json`, nested });
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return [...found.values()];
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* The nested packages of a run: each directory below the target root, in no `node_modules`
|
|
286
|
-
* directory and none of `known`, that holds a `package.json` and lies at or above one of
|
|
287
|
-
* `files`, the program's source files and the compiler configuration files, in path order.
|
|
288
|
-
*/
|
|
289
|
-
function nestedPackageDirs(
|
|
290
|
-
host: Host,
|
|
291
|
-
targetRoot: string,
|
|
292
|
-
files: Iterable<string>,
|
|
293
|
-
known: ReadonlySet<string>,
|
|
294
|
-
): readonly string[] {
|
|
295
|
-
const seen = new Set<string>();
|
|
296
|
-
const found: string[] = [];
|
|
297
|
-
for (const file of files) {
|
|
298
|
-
for (
|
|
299
|
-
let dir = dirnamePath(file);
|
|
300
|
-
dir !== targetRoot && !seen.has(dir) && relativePath(targetRoot, dir) !== undefined;
|
|
301
|
-
dir = dirnamePath(dir)
|
|
302
|
-
) {
|
|
303
|
-
seen.add(dir);
|
|
304
|
-
const below = relativePath(targetRoot, dir) ?? "";
|
|
305
|
-
if (
|
|
306
|
-
!below.split("/").includes("node_modules") &&
|
|
307
|
-
!known.has(dir) &&
|
|
308
|
-
host.kindOf(joinPath(dir, "package.json")) === "file"
|
|
309
|
-
) {
|
|
310
|
-
found.push(dir);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
return found.sort(compare);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Reads every project the scope discovers, and each declared consumer's, in one snapshot,
|
|
319
|
-
* each checked for errors first. `stage` is handed a target project and enumerates and roots
|
|
320
|
-
* it if it reads it; a consumer project is read for its references to the target. A type error
|
|
321
|
-
* in an own file skips the unit holding it. A guess that does not load or meets a setup failure
|
|
322
|
-
* is dropped into `notBuilt` (see {@link isGuess}); any other such project fails the run, as
|
|
323
|
-
* does a run whose every guess was dropped.
|
|
201
|
+
* Reads every project the load phase analyzes through `stage`, which enumerates and roots one
|
|
202
|
+
* if it reads it, and each declared consumer's project for its references to the target,
|
|
203
|
+
* in the same snapshot. A type error in an own file skips the unit holding it.
|
|
324
204
|
*/
|
|
325
205
|
function readProjects<Answer>(
|
|
326
206
|
engine: Engine,
|
|
327
207
|
host: Host,
|
|
328
208
|
scope: Scope,
|
|
329
|
-
config:
|
|
209
|
+
config: PartialConfig,
|
|
330
210
|
stage: <Brand>(project: ProjectView<Brand>, opened: OpenedProject) => Answer,
|
|
331
|
-
):
|
|
211
|
+
): LoadedRun<ProjectsRead<Answer>> {
|
|
332
212
|
const targetRoot = scope.target.path;
|
|
333
|
-
const discovered = discoverProjects(engine, host, scope, config.analysis.configurations);
|
|
334
|
-
if (discovered.configFiles.length === 0 && discovered.notBuilt.length === 0) {
|
|
335
|
-
throw new DiscoveryError(
|
|
336
|
-
`${targetRoot} holds no compiler configuration, so the run holds no program`,
|
|
337
|
-
[],
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
const ids = new Map(discovered.projects.map((project) => [project.configFile, project.id]));
|
|
341
|
-
const loads = consumerLoads(engine, host, scope, discovered.configFiles);
|
|
342
|
-
const consumerOf = new Map(
|
|
343
|
-
loads.flatMap((load) =>
|
|
344
|
-
load.configFiles.map((configFile) => [configFile, load.consumer] as const),
|
|
345
|
-
),
|
|
346
|
-
);
|
|
347
213
|
const absoluteRoot = resolvePath(host.workingDirectory(), targetRoot);
|
|
348
|
-
const
|
|
349
|
-
engine,
|
|
350
|
-
host,
|
|
351
|
-
absoluteRoot,
|
|
352
|
-
discovered.configFiles,
|
|
353
|
-
readManifest(host, targetRoot),
|
|
354
|
-
);
|
|
214
|
+
const testPatterns = config.ts.test_files.map(globExpression);
|
|
355
215
|
const parse = (fileName: string, text: string) => engine.parseSourceFile(fileName, text);
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
let nestedDirs: readonly string[] = [];
|
|
360
|
-
let conventions = readConventions(host, parse, [], config.ts.disabledConventions);
|
|
361
|
-
let options: RootOptions & { readonly parse: typeof parse; readonly conventions: Conventions };
|
|
362
|
-
const readManifests = (opened: readonly OpenedFiles[]): void => {
|
|
363
|
-
nestedDirs = nestedPackageDirs(
|
|
364
|
-
host,
|
|
365
|
-
normalizePath(absoluteRoot),
|
|
366
|
-
opened
|
|
367
|
-
.filter((one) => !consumerOf.has(one.configFile))
|
|
368
|
-
.flatMap((one) => [one.configFile, ...one.fileNames()]),
|
|
369
|
-
new Set(memberDirs),
|
|
370
|
-
);
|
|
371
|
-
conventions = readConventions(
|
|
372
|
-
host,
|
|
373
|
-
parse,
|
|
374
|
-
conventionManifests(host, absoluteRoot, memberDirs, nestedDirs),
|
|
375
|
-
config.ts.disabledConventions,
|
|
376
|
-
);
|
|
377
|
-
options = {
|
|
216
|
+
return loadRun(engine, host, scope, config, ({ plan, classified, runFiles }) => {
|
|
217
|
+
const { packages, conventions } = plan;
|
|
218
|
+
const options = {
|
|
378
219
|
host,
|
|
379
|
-
manifest:
|
|
380
|
-
otherPackages:
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
],
|
|
384
|
-
patterns: config.rootPatterns,
|
|
385
|
-
entryFiles: config.ts.entryFiles,
|
|
220
|
+
manifest: packages.manifest,
|
|
221
|
+
otherPackages: packages.entries,
|
|
222
|
+
patterns: config.roots.patterns,
|
|
223
|
+
entryFiles: config.ts.entry_files,
|
|
386
224
|
conventions,
|
|
387
|
-
testFiles: config.ts.
|
|
225
|
+
testFiles: config.ts.test_files,
|
|
388
226
|
parse,
|
|
389
|
-
publishedAPI: config.
|
|
390
|
-
publishedMembers:
|
|
391
|
-
|
|
392
|
-
),
|
|
227
|
+
publishedAPI: config.target.kind !== undefined && kindOf(config.target.kind) === "library",
|
|
228
|
+
publishedMembers: packages.published,
|
|
229
|
+
runFiles,
|
|
393
230
|
};
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const dropped = (configFile: string, error: string): void => {
|
|
397
|
-
notBuilt.push({
|
|
398
|
-
id: ids.get(configFile) ?? configFile,
|
|
399
|
-
configFile,
|
|
400
|
-
error: targetRelative(error, absoluteRoot),
|
|
401
|
-
});
|
|
402
|
-
};
|
|
403
|
-
const failures: LocatedDiagnostic[] = [];
|
|
404
|
-
const unbuildable: SetupFailure[] = [];
|
|
405
|
-
const setupDropped: SetupFailure[] = [];
|
|
406
|
-
const librariesUnfound: LibraryUnfound[] = [];
|
|
407
|
-
const consumed = new Map<string, Reference>();
|
|
408
|
-
const heldFiles = new Set<string>();
|
|
409
|
-
let outsideTests: readonly OutsideTest[] = [];
|
|
410
|
-
const setupMet = (configFile: string, met: readonly SetupFailure[]): void => {
|
|
411
|
-
const [first] = met;
|
|
412
|
-
if (first !== undefined && isGuess(discovered, configFile)) {
|
|
413
|
-
dropped(configFile, setupLine(first));
|
|
414
|
-
setupDropped.push(...met);
|
|
415
|
-
} else {
|
|
416
|
-
unbuildable.push(...met);
|
|
417
|
-
}
|
|
418
|
-
};
|
|
419
|
-
const testPatterns = config.ts.testFiles.map(globExpression);
|
|
420
|
-
const joins = discovered.derived
|
|
421
|
-
? joinedTestFiles(engine, host, absoluteRoot, discovered.configFiles, testPatterns)
|
|
422
|
-
: new Map<string, readonly string[]>();
|
|
423
|
-
const session = runSession(
|
|
424
|
-
engine,
|
|
425
|
-
[...discovered.configFiles, ...consumerOf.keys()],
|
|
426
|
-
(opened) => {
|
|
427
|
-
const consumer = consumerOf.get(opened.configFile);
|
|
428
|
-
const setup = consumer === undefined ? workspace?.unbuildable(opened.configFile) : undefined;
|
|
429
|
-
if (setup !== undefined) {
|
|
430
|
-
setupMet(opened.configFile, [
|
|
431
|
-
{ setupClass: "workspace-member-without-source", detail: setup },
|
|
432
|
-
]);
|
|
433
|
-
return undefined;
|
|
434
|
-
}
|
|
435
|
-
const referenceOnly =
|
|
436
|
-
workspace === undefined || consumer !== undefined
|
|
437
|
-
? () => false
|
|
438
|
-
: workspace.referenceOnly(opened.configFile, opened.rootFiles);
|
|
439
|
-
const project =
|
|
440
|
-
workspace === undefined || consumer !== undefined
|
|
441
|
-
? opened
|
|
442
|
-
: ownedAs(opened, (file, fromExternalLibrary) =>
|
|
443
|
-
workspace.ownFile(file, fromExternalLibrary),
|
|
444
|
-
);
|
|
445
|
-
const raw = projectErrors(diagnosticsOf(project));
|
|
446
|
-
const errors = { load: raw.load, check: ownErrors(raw.check, referenceOnly) };
|
|
447
|
-
const [unloaded] = errors.load;
|
|
448
|
-
if (
|
|
449
|
-
unloaded !== undefined &&
|
|
450
|
-
consumer === undefined &&
|
|
451
|
-
isGuess(discovered, project.configFile)
|
|
452
|
-
) {
|
|
453
|
-
dropped(
|
|
454
|
-
project.configFile,
|
|
455
|
-
renderDiagnostic(unloaded, (path) => relativePath(absoluteRoot, path) ?? path),
|
|
456
|
-
);
|
|
457
|
-
return undefined;
|
|
458
|
-
}
|
|
459
|
-
if (errors.load.length > 0) {
|
|
460
|
-
failures.push(...errors.load);
|
|
461
|
-
return undefined;
|
|
462
|
-
}
|
|
463
|
-
const reading = readErrors(project, errors.check, {
|
|
464
|
-
host,
|
|
465
|
-
targetRoot:
|
|
466
|
-
consumer === undefined
|
|
467
|
-
? absoluteRoot
|
|
468
|
-
: resolvePath(host.workingDirectory(), consumer.path),
|
|
469
|
-
paths: pathsOf(engine, project.configFile),
|
|
470
|
-
});
|
|
471
|
-
if (consumer !== undefined && reading.missing.length > 0) {
|
|
472
|
-
unbuildable.push(
|
|
473
|
-
...reading.missing.map((one) => ({
|
|
474
|
-
setupClass: "missing-consumer" as const,
|
|
475
|
-
detail: `the consumer ${consumer.path} does not build, its dependencies not installed: ${one.detail}`,
|
|
476
|
-
})),
|
|
477
|
-
);
|
|
478
|
-
return undefined;
|
|
479
|
-
}
|
|
480
|
-
if (reading.missing.length > 0) {
|
|
481
|
-
setupMet(project.configFile, reading.missing);
|
|
482
|
-
return undefined;
|
|
483
|
-
}
|
|
484
|
-
const unconventional =
|
|
485
|
-
consumer === undefined
|
|
486
|
-
? conventionFailuresFor(
|
|
487
|
-
conventions,
|
|
488
|
-
project.configFile,
|
|
489
|
-
project.ownSourceFiles().map((file) => file.fileName),
|
|
490
|
-
)
|
|
491
|
-
: [];
|
|
492
|
-
if (unconventional.length > 0) {
|
|
493
|
-
setupMet(project.configFile, unconventional);
|
|
494
|
-
return undefined;
|
|
495
|
-
}
|
|
496
|
-
if (consumer !== undefined) {
|
|
497
|
-
for (const reference of consumerReferences(
|
|
498
|
-
project,
|
|
499
|
-
host,
|
|
500
|
-
targetRoot,
|
|
501
|
-
{
|
|
502
|
-
id: consumer.id,
|
|
503
|
-
root: consumer.path,
|
|
504
|
-
},
|
|
505
|
-
config,
|
|
506
|
-
)) {
|
|
507
|
-
consumed.set(referenceKey(reference), reference);
|
|
508
|
-
}
|
|
509
|
-
return undefined;
|
|
510
|
-
}
|
|
511
|
-
librariesUnfound.push(
|
|
512
|
-
...raw.unfound.map((one) => ({
|
|
513
|
-
configFile: project.configFile,
|
|
514
|
-
error: renderDiagnostic(one, (path) => relativePath(absoluteRoot, path) ?? path),
|
|
515
|
-
})),
|
|
516
|
-
);
|
|
517
|
-
const configuration = ids.get(project.configFile) ?? project.configFile;
|
|
231
|
+
const heldFiles = new Set<string>();
|
|
232
|
+
const answers = classified.analyzed.map(({ plan: planned, project, skips, referenceOnly }) => {
|
|
518
233
|
const read = (): ProjectRead => {
|
|
519
234
|
const held = inventory(project, host, targetRoot);
|
|
520
235
|
const found = roots(project, held, targetRoot, options);
|
|
521
|
-
const kept = skippedRoots(project, held,
|
|
236
|
+
const kept = skippedRoots(project, held, skips);
|
|
522
237
|
const rooted =
|
|
523
238
|
kept.length === 0
|
|
524
239
|
? found
|
|
@@ -531,12 +246,12 @@ function readProjects<Answer>(
|
|
|
531
246
|
};
|
|
532
247
|
const own = sourceFilesOf(project, targetRoot);
|
|
533
248
|
return {
|
|
534
|
-
configuration,
|
|
249
|
+
configuration: planned.id,
|
|
535
250
|
configFile: project.configFile,
|
|
536
251
|
held,
|
|
537
252
|
rooted,
|
|
538
|
-
typeErrorSkips:
|
|
539
|
-
skipped: skippedUnits(
|
|
253
|
+
typeErrorSkips: skips.map((one) => one.record),
|
|
254
|
+
skipped: skippedUnits(skips, absoluteRoot),
|
|
540
255
|
referenceOnly: project
|
|
541
256
|
.ownSourceFiles()
|
|
542
257
|
.filter((file) => referenceOnly(file.fileName))
|
|
@@ -548,66 +263,25 @@ function readProjects<Answer>(
|
|
|
548
263
|
for (const file of project.ownSourceFiles()) {
|
|
549
264
|
heldFiles.add(relativePath(absoluteRoot, file.fileName) ?? file.fileName);
|
|
550
265
|
}
|
|
551
|
-
return stage(project, { configuration, read });
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
host,
|
|
560
|
-
targetRoot,
|
|
561
|
-
sourcePaths(host, targetRoot).filter(
|
|
562
|
-
(path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path)),
|
|
563
|
-
),
|
|
564
|
-
parse,
|
|
565
|
-
);
|
|
566
|
-
},
|
|
567
|
-
readManifests,
|
|
568
|
-
);
|
|
569
|
-
for (const configFile of session.unopened) {
|
|
570
|
-
if (consumerOf.has(configFile) || !isGuess(discovered, configFile)) {
|
|
571
|
-
throw new DiscoveryError(`${configFile} opened no project`, []);
|
|
266
|
+
return stage(project, { configuration: planned.id, read });
|
|
267
|
+
});
|
|
268
|
+
const consumed = new Map<string, Reference>();
|
|
269
|
+
for (const { project, consumer } of classified.consumed) {
|
|
270
|
+
const side = { id: consumer.id, root: consumer.path };
|
|
271
|
+
for (const reference of consumerReferences(project, host, targetRoot, side, config)) {
|
|
272
|
+
consumed.set(referenceKey(reference), reference);
|
|
273
|
+
}
|
|
572
274
|
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
`${String(failures.length)} error(s), so no answer was produced`,
|
|
581
|
-
failures,
|
|
582
|
-
);
|
|
583
|
-
}
|
|
584
|
-
const answers = session.projects.filter((answer): answer is Answer => answer !== undefined);
|
|
585
|
-
const [first] = notBuilt;
|
|
586
|
-
if (answers.length === 0 && setupDropped.length > 0) {
|
|
587
|
-
throw new SetupError(setupDropped);
|
|
588
|
-
}
|
|
589
|
-
if (answers.length === 0 && first !== undefined) {
|
|
590
|
-
throw new DiscoveryError(
|
|
591
|
-
`no configuration discovery derived could be built; ${first.id}: ${first.error}`,
|
|
592
|
-
[],
|
|
275
|
+
const outsideTests = testFilesAt(
|
|
276
|
+
host,
|
|
277
|
+
targetRoot,
|
|
278
|
+
sourcePaths(host, targetRoot).filter(
|
|
279
|
+
(path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path)),
|
|
280
|
+
),
|
|
281
|
+
parse,
|
|
593
282
|
);
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
answers,
|
|
597
|
-
consumers: {
|
|
598
|
-
loaded: loads.map((load) => load.consumer),
|
|
599
|
-
references: [...consumed.values()],
|
|
600
|
-
},
|
|
601
|
-
notBuilt,
|
|
602
|
-
unanswered: session.unanswered,
|
|
603
|
-
componentsUnread: workspace?.componentsUnread ?? [],
|
|
604
|
-
librariesUnfound,
|
|
605
|
-
conventionsApplied: conventions.applied,
|
|
606
|
-
conventionUses: conventions.uses,
|
|
607
|
-
memberDirs,
|
|
608
|
-
nestedDirs,
|
|
609
|
-
outsideTests,
|
|
610
|
-
};
|
|
283
|
+
return { answers, references: [...consumed.values()], outsideTests };
|
|
284
|
+
});
|
|
611
285
|
}
|
|
612
286
|
|
|
613
287
|
/** The projects one run analyzes, and what reading them left out. */
|
|
@@ -625,7 +299,12 @@ interface RunProjects {
|
|
|
625
299
|
* for the errors and setup failures that decide whether it is analyzed, dropped or
|
|
626
300
|
* fails the run, exactly as the analysis reads them.
|
|
627
301
|
*/
|
|
628
|
-
export function runProjects(
|
|
302
|
+
export function runProjects(
|
|
303
|
+
engine: Engine,
|
|
304
|
+
host: Host,
|
|
305
|
+
scope: Scope,
|
|
306
|
+
config: PartialConfig,
|
|
307
|
+
): RunProjects {
|
|
629
308
|
const read = readProjects(
|
|
630
309
|
engine,
|
|
631
310
|
host,
|
|
@@ -633,7 +312,11 @@ export function runProjects(engine: Engine, host: Host, scope: Scope, config: Co
|
|
|
633
312
|
config,
|
|
634
313
|
(_project, opened) => opened.configuration,
|
|
635
314
|
);
|
|
636
|
-
return {
|
|
315
|
+
return {
|
|
316
|
+
configurations: read.result.answers,
|
|
317
|
+
notBuilt: read.classified.notBuilt,
|
|
318
|
+
unanswered: read.unanswered,
|
|
319
|
+
};
|
|
637
320
|
}
|
|
638
321
|
|
|
639
322
|
/**
|
|
@@ -646,12 +329,12 @@ export function runRoots(
|
|
|
646
329
|
engine: Engine,
|
|
647
330
|
host: Host,
|
|
648
331
|
scope: Scope,
|
|
649
|
-
config:
|
|
332
|
+
config: ResolvedConfig,
|
|
650
333
|
provenance: Provenance,
|
|
651
334
|
): RunRoots {
|
|
652
335
|
const targetRoot = scope.target.path;
|
|
653
336
|
const read = readProjects(engine, host, scope, config, (_project, opened) => opened.read());
|
|
654
|
-
const projects = read.answers;
|
|
337
|
+
const projects = read.result.answers;
|
|
655
338
|
|
|
656
339
|
const configurations: string[] = [];
|
|
657
340
|
const merged = new Map<string, Omit<RunRoot, "configurations"> & { configurations: string[] }>();
|
|
@@ -682,10 +365,12 @@ export function runRoots(
|
|
|
682
365
|
|
|
683
366
|
const ordered = [...merged.values()].sort(
|
|
684
367
|
(a, b) =>
|
|
685
|
-
byPosition(a.position, b.position) ||
|
|
368
|
+
byPosition(a.position, b.position) ||
|
|
369
|
+
bytewise(a.kind, b.kind) ||
|
|
370
|
+
bytewise(a.source, b.source),
|
|
686
371
|
);
|
|
687
372
|
const unmatched = unmatchedEverywhere(
|
|
688
|
-
config.
|
|
373
|
+
config.roots.patterns,
|
|
689
374
|
projects.map((answer) => answer.rooted),
|
|
690
375
|
);
|
|
691
376
|
return {
|
|
@@ -695,7 +380,7 @@ export function runRoots(
|
|
|
695
380
|
unmatched,
|
|
696
381
|
documentOf(host, provenance, ROOTS_SETTING, targetRoot),
|
|
697
382
|
),
|
|
698
|
-
notBuilt: read.notBuilt,
|
|
383
|
+
notBuilt: read.classified.notBuilt,
|
|
699
384
|
unanswered: read.unanswered,
|
|
700
385
|
};
|
|
701
386
|
}
|
|
@@ -727,7 +412,7 @@ export interface RunSweep {
|
|
|
727
412
|
}
|
|
728
413
|
|
|
729
414
|
/** One `<script` start tag of a component file the run read no block for. */
|
|
730
|
-
|
|
415
|
+
interface ComponentWarning {
|
|
731
416
|
/** The file, below the target root. */
|
|
732
417
|
readonly path: string;
|
|
733
418
|
readonly line: number;
|
|
@@ -754,11 +439,16 @@ interface SweptProject<Extra> {
|
|
|
754
439
|
readonly exempt: readonly Exemption[];
|
|
755
440
|
/** The declarations of the project an unanswered question could have kept live. */
|
|
756
441
|
readonly unanswered: readonly string[];
|
|
442
|
+
/** The data members a generic declared outside the analysis fills, which it may read. */
|
|
443
|
+
readonly filledOutside: readonly string[];
|
|
757
444
|
readonly typeErrorSkips: readonly TypeErrorSkip[];
|
|
758
445
|
readonly skipped: readonly SkippedUnit[];
|
|
759
446
|
/** The component files the project holds of its own, by path below the target root. */
|
|
760
447
|
readonly componentFiles: readonly string[];
|
|
761
448
|
readonly componentWarnings: readonly ComponentWarning[];
|
|
449
|
+
/** The manifest entries the project reads back to no file of its own. */
|
|
450
|
+
readonly unmappedEntries: readonly ManifestEntry[];
|
|
451
|
+
readonly heldScripts: readonly HeldScripts[];
|
|
762
452
|
readonly extra: Extra;
|
|
763
453
|
}
|
|
764
454
|
|
|
@@ -770,6 +460,12 @@ interface ReadProject<Extra> {
|
|
|
770
460
|
readonly evidence: readonly Exemption[];
|
|
771
461
|
readonly componentFiles: readonly string[];
|
|
772
462
|
readonly componentWarnings: readonly ComponentWarning[];
|
|
463
|
+
/** Per own file below the target root, the module specifiers its imports write. */
|
|
464
|
+
readonly imports: ReadonlyMap<string, readonly string[]>;
|
|
465
|
+
/** The global augmentations a declaration outside the project names. */
|
|
466
|
+
readonly augmented: readonly Root[];
|
|
467
|
+
/** The data members its production code decodes into. */
|
|
468
|
+
readonly decoded: Decoded;
|
|
773
469
|
readonly extra: Extra;
|
|
774
470
|
}
|
|
775
471
|
|
|
@@ -790,6 +486,10 @@ interface ReadRun<Extra> {
|
|
|
790
486
|
readonly componentsUnread: readonly ComponentsUnread[];
|
|
791
487
|
/** Per analyzed configuration, each library it names that the compiler cannot find. */
|
|
792
488
|
readonly librariesUnfound: readonly LibraryUnfound[];
|
|
489
|
+
/** The relative specifiers of the run's unchecked JavaScript files that resolve to no file. */
|
|
490
|
+
readonly unresolvedSpecifiers: readonly UnresolvedSpecifier[];
|
|
491
|
+
/** The inputs the run could not read. */
|
|
492
|
+
readonly unread: readonly UnreadInput[];
|
|
793
493
|
/** The convention rows the run applied. */
|
|
794
494
|
readonly conventionsApplied: readonly AppliedConvention[];
|
|
795
495
|
/** The dependencies the applied rows' short names use. */
|
|
@@ -800,6 +500,51 @@ interface ReadRun<Extra> {
|
|
|
800
500
|
readonly nestedDirs: readonly string[];
|
|
801
501
|
}
|
|
802
502
|
|
|
503
|
+
/** The manifest section of a package test evidence counts, and the sections that keep one out of it. */
|
|
504
|
+
const DEV_SECTION = "devDependencies";
|
|
505
|
+
const OTHER_SECTIONS = ["dependencies", "peerDependencies", "optionalDependencies"] as const;
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* The imports of a run's own files and the manifests below the target root that test
|
|
509
|
+
* evidence reads: a package is a devDependency of a file where the nearest manifest at or
|
|
510
|
+
* above it that declares the package declares it under `devDependencies` alone.
|
|
511
|
+
*/
|
|
512
|
+
function testEvidence(
|
|
513
|
+
host: Host,
|
|
514
|
+
targetRoot: string,
|
|
515
|
+
projects: readonly { readonly imports: ReadonlyMap<string, readonly string[]> }[],
|
|
516
|
+
): TestEvidence {
|
|
517
|
+
const imports = new Map<string, readonly string[]>();
|
|
518
|
+
for (const one of projects) {
|
|
519
|
+
for (const [path, specifiers] of one.imports) {
|
|
520
|
+
imports.set(path, specifiers);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
const manifests = new Map<string, Readonly<Record<string, unknown>> | undefined>();
|
|
524
|
+
const manifestIn = (dir: string): Readonly<Record<string, unknown>> | undefined => {
|
|
525
|
+
if (!manifests.has(dir)) {
|
|
526
|
+
manifests.set(dir, manifestAt(host, dir));
|
|
527
|
+
}
|
|
528
|
+
return manifests.get(dir);
|
|
529
|
+
};
|
|
530
|
+
const declares = (section: unknown, name: string): boolean =>
|
|
531
|
+
typeof section === "object" && section !== null && Object.hasOwn(section, name);
|
|
532
|
+
const root = resolvePath(host.workingDirectory(), targetRoot);
|
|
533
|
+
return {
|
|
534
|
+
imports,
|
|
535
|
+
devDependency: (path, name) => {
|
|
536
|
+
for (const dir of ancestors(dirnamePath(joinPath(root, path)), root)) {
|
|
537
|
+
const manifest = manifestIn(dir);
|
|
538
|
+
const other = OTHER_SECTIONS.some((one) => declares(manifest?.[one], name));
|
|
539
|
+
if (declares(manifest?.[DEV_SECTION], name) || other) {
|
|
540
|
+
return !other;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return false;
|
|
544
|
+
},
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
|
|
803
548
|
/**
|
|
804
549
|
* Reads every project of the run, its references and exemptions, and `extra`'s answer,
|
|
805
550
|
* while the project's view is open, and merges the projects into one matrix in the run's
|
|
@@ -810,7 +555,7 @@ function readRun<Extra>(
|
|
|
810
555
|
engine: Engine,
|
|
811
556
|
host: Host,
|
|
812
557
|
scope: Scope,
|
|
813
|
-
config:
|
|
558
|
+
config: ResolvedConfig,
|
|
814
559
|
mode: Mode,
|
|
815
560
|
detectors: Detectors,
|
|
816
561
|
extra: <Brand>(
|
|
@@ -823,13 +568,13 @@ function readRun<Extra>(
|
|
|
823
568
|
const targetRoot = scope.target.path;
|
|
824
569
|
const disabled = disabledClasses(config);
|
|
825
570
|
const templates = disabled.has("template-field")
|
|
826
|
-
? { delimiters: config.analysis.
|
|
571
|
+
? { delimiters: config.analysis.template_delimiters, files: [] }
|
|
827
572
|
: readTemplates(host, targetRoot, config.analysis);
|
|
828
573
|
const consumers = scope.consumers.map((consumer) => consumer.path);
|
|
829
574
|
const read = readProjects<ReadProject<Extra>>(engine, host, scope, config, (project, opened) => {
|
|
830
575
|
const projectRead = opened.read();
|
|
831
576
|
const resolved = references(project, projectRead.held, targetRoot, {
|
|
832
|
-
testFiles: config.ts.
|
|
577
|
+
testFiles: config.ts.test_files,
|
|
833
578
|
testFileNames: projectRead.testFileNames,
|
|
834
579
|
});
|
|
835
580
|
const evidence = evidenceRecords(
|
|
@@ -840,7 +585,7 @@ function readRun<Extra>(
|
|
|
840
585
|
templates,
|
|
841
586
|
ts: config.ts,
|
|
842
587
|
consumers,
|
|
843
|
-
...(config.analysis.
|
|
588
|
+
...(config.analysis.generated_files === "include"
|
|
844
589
|
? {}
|
|
845
590
|
: { generated: projectRead.generated }),
|
|
846
591
|
},
|
|
@@ -848,6 +593,9 @@ function readRun<Extra>(
|
|
|
848
593
|
disabled,
|
|
849
594
|
);
|
|
850
595
|
const components = project.ownSourceFiles().filter(isComponentFile);
|
|
596
|
+
const injected = project.program
|
|
597
|
+
.getSourceFileNames()
|
|
598
|
+
.some((name) => name.endsWith(`/node_modules/${GLOBALS_RUNNER}/globals.d.ts`));
|
|
851
599
|
const pathOf = (file: (typeof components)[number]): string =>
|
|
852
600
|
relativePath(targetRoot, file.fileName) ?? file.fileName;
|
|
853
601
|
return {
|
|
@@ -856,6 +604,29 @@ function readRun<Extra>(
|
|
|
856
604
|
testFiles: resolved.testFilePaths,
|
|
857
605
|
evidence,
|
|
858
606
|
componentFiles: components.map(pathOf),
|
|
607
|
+
augmented: mergedGlobalInterfaces(
|
|
608
|
+
project,
|
|
609
|
+
projectRead.held,
|
|
610
|
+
sourceFilesOf(project, targetRoot),
|
|
611
|
+
).map((id): Root => ({ id, kind: "global-augmentation", source: "" })),
|
|
612
|
+
imports: new Map(
|
|
613
|
+
project.ownSourceFiles().flatMap((file) => {
|
|
614
|
+
const path = relativePath(targetRoot, file.fileName);
|
|
615
|
+
if (path === undefined) {
|
|
616
|
+
return [];
|
|
617
|
+
}
|
|
618
|
+
const specifiers = file.imports.filter(isStringLiteralLikeNode).map((one) => one.text);
|
|
619
|
+
// A file calling the globals a program declares is written for their runner.
|
|
620
|
+
return [
|
|
621
|
+
[
|
|
622
|
+
path,
|
|
623
|
+
injected && namesTestGlobals(project, file)
|
|
624
|
+
? [...specifiers, GLOBALS_RUNNER]
|
|
625
|
+
: specifiers,
|
|
626
|
+
],
|
|
627
|
+
];
|
|
628
|
+
}),
|
|
629
|
+
),
|
|
859
630
|
componentWarnings: components.flatMap((file) =>
|
|
860
631
|
readComponent(file.originalText, extensionOf(file.fileName)).warnings.map((warning) => ({
|
|
861
632
|
path: pathOf(file),
|
|
@@ -863,48 +634,77 @@ function readRun<Extra>(
|
|
|
863
634
|
reason: warning.reason,
|
|
864
635
|
})),
|
|
865
636
|
),
|
|
637
|
+
decoded: decodedMembers(
|
|
638
|
+
project,
|
|
639
|
+
projectRead.held,
|
|
640
|
+
productionFiles(project, targetRoot, resolved.testFilePaths),
|
|
641
|
+
consumers,
|
|
642
|
+
),
|
|
866
643
|
extra: extra(project, projectRead, resolved.references, resolved.testFilePaths),
|
|
867
644
|
};
|
|
868
645
|
});
|
|
869
|
-
const outsidePaths = read.outsideTests.map((one) => one.path);
|
|
870
|
-
const withOutside = read.answers.map((one) => ({
|
|
646
|
+
const outsidePaths = read.result.outsideTests.map((one) => one.path);
|
|
647
|
+
const withOutside = read.result.answers.map((one) => ({
|
|
871
648
|
...one,
|
|
872
649
|
references: [
|
|
873
650
|
...one.references,
|
|
874
|
-
...outsideTestReferences(read.outsideTests, one.projectRead.held, targetRoot),
|
|
651
|
+
...outsideTestReferences(read.result.outsideTests, one.projectRead.held, targetRoot),
|
|
875
652
|
],
|
|
876
653
|
testFiles: [...one.testFiles, ...outsidePaths],
|
|
877
654
|
}));
|
|
878
655
|
// Test-support code is code only test code imports in any configuration of the run: a
|
|
879
656
|
// configuration that holds no test file says nothing about what the tests import.
|
|
880
|
-
const support = testSupportFiles(
|
|
657
|
+
const { support, testUsed } = testSupportFiles(
|
|
881
658
|
withOutside.flatMap((one) => one.projectRead.held.symbols),
|
|
882
659
|
withOutside.flatMap((one) => one.references),
|
|
883
660
|
withOutside.flatMap((one) => one.projectRead.rooted.liveUnderReachability),
|
|
884
661
|
withOutside.flatMap((one) => one.testFiles),
|
|
662
|
+
testEvidence(host, targetRoot, withOutside),
|
|
885
663
|
);
|
|
664
|
+
// A member a decode fills or a copy carries is written: a value decoded and sent again carries it on.
|
|
665
|
+
const written = new Set([
|
|
666
|
+
...countedWrites(
|
|
667
|
+
[...withOutside.flatMap((one) => one.references), ...read.result.references],
|
|
668
|
+
support,
|
|
669
|
+
mode,
|
|
670
|
+
),
|
|
671
|
+
...withOutside.flatMap((one) => [
|
|
672
|
+
...one.decoded.filled,
|
|
673
|
+
...one.decoded.parsed,
|
|
674
|
+
...one.decoded.copied,
|
|
675
|
+
]),
|
|
676
|
+
]);
|
|
677
|
+
const evidence = withOutside.map((one) => writtenRecords(one.evidence, written));
|
|
886
678
|
const settled = settledSatisfaction(
|
|
887
|
-
withOutside.map((one) => ({
|
|
888
|
-
|
|
679
|
+
withOutside.map((one, index) => ({
|
|
680
|
+
evidence: evidence[index] ?? [],
|
|
681
|
+
held: one.projectRead.held,
|
|
682
|
+
})),
|
|
683
|
+
[...withOutside.flatMap((one) => one.references), ...read.result.references],
|
|
889
684
|
);
|
|
890
685
|
const answers = withOutside.map((one, index): SweptProject<Extra> => {
|
|
891
686
|
const { projectRead } = one;
|
|
892
687
|
const satisfied = settled[index];
|
|
893
|
-
const detected = heldRecords(satisfied?.evidence ??
|
|
688
|
+
const detected = heldRecords(satisfied?.evidence ?? evidence[index] ?? [], {
|
|
894
689
|
mode,
|
|
895
690
|
testFiles: new Set([...one.testFiles, ...support]),
|
|
896
691
|
});
|
|
897
692
|
const exempt = detected.records;
|
|
898
693
|
const made = supportReferences([...one.references, ...(satisfied?.references ?? [])], support);
|
|
899
694
|
const held = new Set(projectRead.held.symbols.map((symbol) => symbol.position.path));
|
|
900
|
-
const supportFiles = [...support].filter((path) => held.has(path)).sort();
|
|
695
|
+
const supportFiles = [...support].filter((path) => held.has(path)).sort(bytewise);
|
|
696
|
+
const testUsedFiles = [...testUsed].filter((path) => held.has(path)).sort(bytewise);
|
|
901
697
|
const configured: Configured = {
|
|
902
698
|
configuration: projectRead.configuration,
|
|
903
699
|
symbols: projectRead.held.symbols,
|
|
904
700
|
references: [...made, ...evidenceReferences(projectRead.held.symbols, detected.inTestFiles)],
|
|
905
|
-
|
|
906
|
-
|
|
701
|
+
// The augmentations are rooted after test support is read: an outside declaration
|
|
702
|
+
// naming one calls nothing of its file.
|
|
703
|
+
roots: [...projectRead.rooted.liveUnderReachability, ...one.augmented],
|
|
704
|
+
testFiles: [...one.testFiles, ...supportFiles],
|
|
907
705
|
...(supportFiles.length === 0 ? {} : { supportFiles }),
|
|
706
|
+
...(testUsedFiles.length === 0 ? {} : { testUsedFiles }),
|
|
707
|
+
...(projectRead.held.ambient.size === 0 ? {} : { ambient: projectRead.held.ambient }),
|
|
908
708
|
...(projectRead.referenceOnly.length === 0
|
|
909
709
|
? {}
|
|
910
710
|
: { referenceOnly: projectRead.referenceOnly }),
|
|
@@ -923,15 +723,19 @@ function readRun<Extra>(
|
|
|
923
723
|
.filter((reference) => reference.resolution === "by-name")
|
|
924
724
|
.map((reference) => reference.to),
|
|
925
725
|
...exempt.filter(isUnansweredRecord).map((record) => record.id),
|
|
726
|
+
...one.decoded.unanswered,
|
|
926
727
|
],
|
|
728
|
+
filledOutside: one.decoded.filled,
|
|
927
729
|
typeErrorSkips: projectRead.typeErrorSkips,
|
|
730
|
+
unmappedEntries: projectRead.rooted.unmappedEntries,
|
|
731
|
+
heldScripts: projectRead.rooted.heldScripts,
|
|
928
732
|
skipped: projectRead.skipped,
|
|
929
733
|
componentFiles: one.componentFiles,
|
|
930
734
|
componentWarnings: one.componentWarnings,
|
|
931
735
|
extra: one.extra,
|
|
932
736
|
};
|
|
933
737
|
});
|
|
934
|
-
const consumed = read.
|
|
738
|
+
const consumed = read.result.references;
|
|
935
739
|
const projects = answers.map((one) =>
|
|
936
740
|
consumed.length === 0
|
|
937
741
|
? one
|
|
@@ -953,15 +757,17 @@ function readRun<Extra>(
|
|
|
953
757
|
]),
|
|
954
758
|
],
|
|
955
759
|
projects,
|
|
956
|
-
consumers: read.consumers
|
|
957
|
-
notBuilt: read.notBuilt,
|
|
760
|
+
consumers: read.plan.discovery.consumers,
|
|
761
|
+
notBuilt: read.classified.notBuilt,
|
|
958
762
|
unanswered: read.unanswered,
|
|
959
|
-
componentsUnread: read.componentsUnread,
|
|
960
|
-
librariesUnfound: read.librariesUnfound,
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
763
|
+
componentsUnread: read.plan.workspace?.componentsUnread ?? [],
|
|
764
|
+
librariesUnfound: read.classified.librariesUnfound,
|
|
765
|
+
unresolvedSpecifiers: read.classified.unresolvedSpecifiers,
|
|
766
|
+
unread: read.plan.unread,
|
|
767
|
+
conventionsApplied: read.plan.conventions.applied,
|
|
768
|
+
conventionUses: read.plan.conventions.uses,
|
|
769
|
+
memberDirs: read.plan.packages.members,
|
|
770
|
+
nestedDirs: read.plan.packages.nested,
|
|
965
771
|
};
|
|
966
772
|
}
|
|
967
773
|
|
|
@@ -1025,6 +831,22 @@ function evidenceReferences(
|
|
|
1025
831
|
});
|
|
1026
832
|
}
|
|
1027
833
|
|
|
834
|
+
/**
|
|
835
|
+
* The declarations a write the mode counts stores into, a write a test-support file
|
|
836
|
+
* makes being a test's.
|
|
837
|
+
*/
|
|
838
|
+
function countedWrites(
|
|
839
|
+
references: readonly Reference[],
|
|
840
|
+
support: ReadonlySet<string>,
|
|
841
|
+
mode: Mode,
|
|
842
|
+
): ReadonlySet<string> {
|
|
843
|
+
return new Set(
|
|
844
|
+
supportReferences(references, support).flatMap((reference) =>
|
|
845
|
+
reference.use === "write" && !(mode.production && reference.test) ? [reference.to] : [],
|
|
846
|
+
),
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
|
|
1028
850
|
/**
|
|
1029
851
|
* The declarations every reference the mode counts stores into, a loaded consumer's
|
|
1030
852
|
* reference counting as a read: what the write-only kind would report but for a record.
|
|
@@ -1102,7 +924,7 @@ function sweptOf<Extra>(
|
|
|
1102
924
|
unanswered: read.unanswered,
|
|
1103
925
|
heldByUnanswered: [...held],
|
|
1104
926
|
skipped: read.projects.flatMap((one) => one.skipped),
|
|
1105
|
-
componentFiles: [...new Set(read.projects.flatMap((one) => one.componentFiles))].sort(
|
|
927
|
+
componentFiles: [...new Set(read.projects.flatMap((one) => one.componentFiles))].sort(bytewise),
|
|
1106
928
|
};
|
|
1107
929
|
}
|
|
1108
930
|
|
|
@@ -1118,7 +940,7 @@ export function runSweep(
|
|
|
1118
940
|
engine: Engine,
|
|
1119
941
|
host: Host,
|
|
1120
942
|
scope: Scope,
|
|
1121
|
-
config:
|
|
943
|
+
config: ResolvedConfig,
|
|
1122
944
|
input: Pick<SweepInput, "marked" | "mode">,
|
|
1123
945
|
detectors: Detectors = DETECTORS,
|
|
1124
946
|
): RunSweep {
|
|
@@ -1141,6 +963,19 @@ interface EmitterExtra {
|
|
|
1141
963
|
readonly directives: readonly InlineDirective[];
|
|
1142
964
|
readonly declarationsNamed: readonly boolean[];
|
|
1143
965
|
readonly parts: ProjectParts;
|
|
966
|
+
readonly unseenLoads: readonly UnseenLoad[];
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
/** The project's own files below the target root that are no test file. */
|
|
970
|
+
function productionFiles<Brand>(
|
|
971
|
+
project: ProjectView<Brand>,
|
|
972
|
+
targetRoot: string,
|
|
973
|
+
testFiles: readonly string[],
|
|
974
|
+
): readonly SourceFile[] {
|
|
975
|
+
const tests = new Set(testFiles);
|
|
976
|
+
return [...sourceFilesOf(project, targetRoot).byPath].flatMap(([path, file]) =>
|
|
977
|
+
tests.has(path) ? [] : [file],
|
|
978
|
+
);
|
|
1144
979
|
}
|
|
1145
980
|
|
|
1146
981
|
/** Reads a run's projects with every per-project fact an emitter reads. */
|
|
@@ -1148,7 +983,7 @@ export function readEmitterRun(
|
|
|
1148
983
|
engine: Engine,
|
|
1149
984
|
host: Host,
|
|
1150
985
|
scope: Scope,
|
|
1151
|
-
config:
|
|
986
|
+
config: ResolvedConfig,
|
|
1152
987
|
mode: Mode,
|
|
1153
988
|
detectors: Detectors,
|
|
1154
989
|
): ReadRun<EmitterExtra> {
|
|
@@ -1176,9 +1011,10 @@ export function readEmitterRun(
|
|
|
1176
1011
|
),
|
|
1177
1012
|
declarationsNamed: declarationsNamed(project, read.held, configuredDeclarations(config)),
|
|
1178
1013
|
parts: projectParts(project, read.held, references, targetRoot),
|
|
1014
|
+
unseenLoads: unseenLoadsOf(project, read.configuration, targetRoot, testFiles),
|
|
1179
1015
|
}),
|
|
1180
1016
|
);
|
|
1181
|
-
// Whether a declaration carries the marker decides its code, so one whose
|
|
1017
|
+
// Whether a declaration carries the marker decides its code, so one whose answer went
|
|
1182
1018
|
// unread is reported by nothing.
|
|
1183
1019
|
const unread = run.projects.flatMap((one) => one.extra.deprecation.unanswered);
|
|
1184
1020
|
return unread.length === 0
|
|
@@ -1190,7 +1026,8 @@ export function readEmitterRun(
|
|
|
1190
1026
|
* The workspace members whose dependencies the run judges: `read` holds those a built
|
|
1191
1027
|
* project holds a file below, `unbuilt` the others whose own directory, the nearest
|
|
1192
1028
|
* manifest's above the configuration, holds a configuration the run could not build. A
|
|
1193
|
-
* member no configuration holds a file of is in neither.
|
|
1029
|
+
* member no configuration holds a file of is in neither. A nested package no built project
|
|
1030
|
+
* holds a file below joins `unbuilt` the same way.
|
|
1194
1031
|
*/
|
|
1195
1032
|
function judgedMembers(
|
|
1196
1033
|
host: Host,
|
|
@@ -1214,27 +1051,32 @@ function judgedMembers(
|
|
|
1214
1051
|
judged.unbuilt.push(dir);
|
|
1215
1052
|
}
|
|
1216
1053
|
}
|
|
1054
|
+
for (const dir of read.nestedDirs) {
|
|
1055
|
+
const below = relativePath(root, dir);
|
|
1056
|
+
if (
|
|
1057
|
+
below !== undefined &&
|
|
1058
|
+
owners.has(dir) &&
|
|
1059
|
+
![...held].some((path) => path.startsWith(`${below}/`))
|
|
1060
|
+
) {
|
|
1061
|
+
judged.unbuilt.push(dir);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1217
1064
|
return judged;
|
|
1218
1065
|
}
|
|
1219
1066
|
|
|
1220
1067
|
/** The directory of the nearest `package.json` at or above a file, inside `root`, else `root`. */
|
|
1221
1068
|
function nearestManifestDir(host: Host, root: string, file: string): string {
|
|
1222
|
-
|
|
1223
|
-
if (host.kindOf(joinPath(dir, "package.json")) === "file") {
|
|
1224
|
-
return dir;
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
return root;
|
|
1069
|
+
return ancestors(dirnamePath(file), root).find((dir) => holdsManifest(host, dir)) ?? root;
|
|
1228
1070
|
}
|
|
1229
1071
|
|
|
1230
1072
|
/**
|
|
1231
1073
|
* The input every emitter reads over one sweep of a read run: the facts beside the sweep
|
|
1232
|
-
* each
|
|
1074
|
+
* each emitter reads, every per-project one read in the same session as the sweep.
|
|
1233
1075
|
*/
|
|
1234
1076
|
export function emitterInputOver(
|
|
1235
1077
|
host: Host,
|
|
1236
1078
|
scope: Scope,
|
|
1237
|
-
config:
|
|
1079
|
+
config: ResolvedConfig,
|
|
1238
1080
|
read: ReadRun<EmitterExtra>,
|
|
1239
1081
|
input: Pick<SweepInput, "marked" | "mode">,
|
|
1240
1082
|
selfCheck: SelfCheckFacts,
|
|
@@ -1270,6 +1112,7 @@ export function emitterInputOver(
|
|
|
1270
1112
|
heldByInclusion: new Set(projects.flatMap((one) => one.extra.heldByInclusion)),
|
|
1271
1113
|
generated: new Set(projects.flatMap((one) => one.extra.generated)),
|
|
1272
1114
|
inOperands: new Set(projects.flatMap((one) => one.extra.inOperands)),
|
|
1115
|
+
unseenLoads: projects.flatMap((one) => one.extra.unseenLoads),
|
|
1273
1116
|
},
|
|
1274
1117
|
boundary: {
|
|
1275
1118
|
consumers: {
|
|
@@ -1278,6 +1121,7 @@ export function emitterInputOver(
|
|
|
1278
1121
|
},
|
|
1279
1122
|
encapsulated: readManifest(host, targetRoot).declaresExports,
|
|
1280
1123
|
edges: readEdgeSides(host, targetRoot),
|
|
1124
|
+
filledOutside: new Set(projects.flatMap((one) => one.filledOutside)),
|
|
1281
1125
|
},
|
|
1282
1126
|
selfCheck,
|
|
1283
1127
|
intraFunction: intraFunctionFacts(
|
|
@@ -1313,14 +1157,14 @@ interface AnalysisReader {
|
|
|
1313
1157
|
* directives, the ignore file's entries and the baseline's rows are bound before any
|
|
1314
1158
|
* sweep, and the run is swept once under every bound record's mark and once under none,
|
|
1315
1159
|
* so a record is decided against the finding its code would have produced. The
|
|
1316
|
-
*
|
|
1160
|
+
* configuration family reports the refused suppressions and the roots that named nothing.
|
|
1317
1161
|
* Beside the inputs it answers the projects and test-file rules a report names.
|
|
1318
1162
|
*/
|
|
1319
1163
|
function readAnalysis(
|
|
1320
1164
|
engine: Engine,
|
|
1321
1165
|
host: Host,
|
|
1322
1166
|
scope: Scope,
|
|
1323
|
-
config:
|
|
1167
|
+
config: ResolvedConfig,
|
|
1324
1168
|
provenance: Provenance,
|
|
1325
1169
|
mode: Mode,
|
|
1326
1170
|
detectors: Detectors,
|
|
@@ -1341,7 +1185,7 @@ function readAnalysis(
|
|
|
1341
1185
|
configFile: one.configFile,
|
|
1342
1186
|
})),
|
|
1343
1187
|
testFileRules: testFileRulesOf(
|
|
1344
|
-
config.ts.
|
|
1188
|
+
config.ts.test_files,
|
|
1345
1189
|
read.projects.flatMap((one) => one.configured.testFiles),
|
|
1346
1190
|
read.projects.flatMap((one) => one.configured.supportFiles ?? []),
|
|
1347
1191
|
),
|
|
@@ -1358,7 +1202,14 @@ function readAnalysis(
|
|
|
1358
1202
|
unanswered: read.unanswered,
|
|
1359
1203
|
componentsUnread: read.componentsUnread,
|
|
1360
1204
|
librariesUnfound: read.librariesUnfound,
|
|
1205
|
+
unresolvedSpecifiers: read.unresolvedSpecifiers,
|
|
1206
|
+
unread: read.unread,
|
|
1361
1207
|
conventionsApplied: read.conventionsApplied,
|
|
1208
|
+
unmappedEntries: unmappedEverywhere(read.projects),
|
|
1209
|
+
heldScripts: read.projects.flatMap((one) =>
|
|
1210
|
+
one.heldScripts.map((held) => ({ ...held, configFile: one.configFile })),
|
|
1211
|
+
),
|
|
1212
|
+
unseenLoads: read.projects.flatMap((one) => one.extra.unseenLoads),
|
|
1362
1213
|
},
|
|
1363
1214
|
configured: read.projects.map((one) => one.configured),
|
|
1364
1215
|
symbols,
|
|
@@ -1370,7 +1221,7 @@ function readAnalysis(
|
|
|
1370
1221
|
function inputsOver(
|
|
1371
1222
|
host: Host,
|
|
1372
1223
|
scope: Scope,
|
|
1373
|
-
config:
|
|
1224
|
+
config: ResolvedConfig,
|
|
1374
1225
|
provenance: Provenance,
|
|
1375
1226
|
mode: Mode,
|
|
1376
1227
|
read: ReadRun<EmitterExtra>,
|
|
@@ -1384,7 +1235,7 @@ function inputsOver(
|
|
|
1384
1235
|
const facts: SelfCheckFacts = {
|
|
1385
1236
|
refusals: suppressions.refusals,
|
|
1386
1237
|
unmatchedRoots: unmatchedEverywhere(
|
|
1387
|
-
config.
|
|
1238
|
+
config.roots.patterns,
|
|
1388
1239
|
read.projects.map((one) => one.extra.rooted),
|
|
1389
1240
|
),
|
|
1390
1241
|
rootsDocument: documentOf(host, provenance, ROOTS_SETTING, targetRoot),
|
|
@@ -1410,6 +1261,22 @@ function inputsOver(
|
|
|
1410
1261
|
};
|
|
1411
1262
|
}
|
|
1412
1263
|
|
|
1264
|
+
/** The manifest entries every project of the run reads back to no file, in the first project's order. */
|
|
1265
|
+
function unmappedEverywhere(
|
|
1266
|
+
projects: readonly { readonly unmappedEntries: readonly ManifestEntry[] }[],
|
|
1267
|
+
): readonly ManifestEntry[] {
|
|
1268
|
+
const key = (entry: ManifestEntry): string => `${entry.dir}\u0000${entry.member}`;
|
|
1269
|
+
const [first, ...rest] = projects;
|
|
1270
|
+
const others = rest.map((one) => new Set(one.unmappedEntries.map(key)));
|
|
1271
|
+
const found = new Map<string, ManifestEntry>();
|
|
1272
|
+
for (const entry of first?.unmappedEntries ?? []) {
|
|
1273
|
+
if (others.every((one) => one.has(key(entry)))) {
|
|
1274
|
+
found.set(key(entry), entry);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
return [...found.values()];
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1413
1280
|
/** One project of a run: the name the run gives it and the file it was opened from. */
|
|
1414
1281
|
export interface RunProject {
|
|
1415
1282
|
readonly id: string;
|
|
@@ -1437,8 +1304,18 @@ interface RunFacts {
|
|
|
1437
1304
|
readonly componentsUnread: readonly ComponentsUnread[];
|
|
1438
1305
|
/** Per analyzed configuration, each library it names that the compiler cannot find. */
|
|
1439
1306
|
readonly librariesUnfound: readonly LibraryUnfound[];
|
|
1307
|
+
/** The relative specifiers of the run's unchecked JavaScript files that resolve to no file. */
|
|
1308
|
+
readonly unresolvedSpecifiers: readonly UnresolvedSpecifier[];
|
|
1309
|
+
/** The inputs the run could not read. */
|
|
1310
|
+
readonly unread: readonly UnreadInput[];
|
|
1440
1311
|
/** The convention rows the run applied. */
|
|
1441
1312
|
readonly conventionsApplied: readonly AppliedConvention[];
|
|
1313
|
+
/** The manifest entries no project of the run reads back to a file, each once. */
|
|
1314
|
+
readonly unmappedEntries: readonly ManifestEntry[];
|
|
1315
|
+
/** Per project, by its compiler configuration file, each package whose command strings name files it holds. */
|
|
1316
|
+
readonly heldScripts: readonly (HeldScripts & { readonly configFile: string })[];
|
|
1317
|
+
/** The loads of production files whose target the run cannot resolve, per configuration. */
|
|
1318
|
+
readonly unseenLoads: readonly UnseenLoad[];
|
|
1442
1319
|
}
|
|
1443
1320
|
|
|
1444
1321
|
/** One configuration whose component files a run cannot read. */
|
|
@@ -1447,13 +1324,6 @@ interface ComponentsUnread {
|
|
|
1447
1324
|
readonly reason: string;
|
|
1448
1325
|
}
|
|
1449
1326
|
|
|
1450
|
-
/** One library an analyzed configuration names that the compiler cannot find. */
|
|
1451
|
-
interface LibraryUnfound {
|
|
1452
|
-
readonly configFile: string;
|
|
1453
|
-
/** The compiler's error, rendered as a dropped configuration's is. */
|
|
1454
|
-
readonly error: string;
|
|
1455
|
-
}
|
|
1456
|
-
|
|
1457
1327
|
/** The findings of one run, beside what a report states about the run itself. */
|
|
1458
1328
|
export interface RunAnalysis {
|
|
1459
1329
|
readonly result: PassResult;
|
|
@@ -1466,7 +1336,7 @@ export interface RunAnalysis {
|
|
|
1466
1336
|
|
|
1467
1337
|
/**
|
|
1468
1338
|
* The analysis of the run the scope and the configuration describe: the run read with its
|
|
1469
|
-
* suppressions bound, every
|
|
1339
|
+
* suppressions bound, every emitter's findings with the suppressions applied and the
|
|
1470
1340
|
* declared edges evaluated, the projects and test-file rules the report names, and the sweep
|
|
1471
1341
|
* an explanation reads.
|
|
1472
1342
|
*/
|
|
@@ -1474,7 +1344,7 @@ export function runAnalysis(
|
|
|
1474
1344
|
engine: Engine,
|
|
1475
1345
|
host: Host,
|
|
1476
1346
|
scope: Scope,
|
|
1477
|
-
config:
|
|
1347
|
+
config: ResolvedConfig,
|
|
1478
1348
|
provenance: Provenance,
|
|
1479
1349
|
mode: Mode,
|
|
1480
1350
|
detectors: Detectors = DETECTORS,
|
|
@@ -1486,14 +1356,20 @@ export function runAnalysis(
|
|
|
1486
1356
|
|
|
1487
1357
|
/**
|
|
1488
1358
|
* One count per configuration of the run in which the checker left a question unanswered:
|
|
1489
|
-
* the questions asked in its project,
|
|
1359
|
+
* the questions asked in its project, a formed program's manifest that does not parse or cannot
|
|
1360
|
+
* be read and a package whose command strings name files the project holds each counted as one, and the
|
|
1361
|
+
* declarations of its own the run holds for them.
|
|
1490
1362
|
*/
|
|
1491
1363
|
export function unansweredCounts(analysis: RunAnalysis): readonly UnansweredCount[] {
|
|
1492
1364
|
const held = new Set(analysis.swept.heldByUnanswered);
|
|
1493
1365
|
return analysis.run.projects.flatMap((project) => {
|
|
1494
|
-
const questions =
|
|
1495
|
-
(one) => one.configFile === project.configFile
|
|
1496
|
-
|
|
1366
|
+
const questions =
|
|
1367
|
+
analysis.run.unanswered.filter((one) => one.configFile === project.configFile).length +
|
|
1368
|
+
analysis.run.unread.filter(
|
|
1369
|
+
(one) => one.kind === "manifest" && one.configFile === project.configFile,
|
|
1370
|
+
).length +
|
|
1371
|
+
analysis.run.heldScripts.filter((one) => one.configFile === project.configFile).length;
|
|
1372
|
+
|
|
1497
1373
|
if (questions === 0) {
|
|
1498
1374
|
return [];
|
|
1499
1375
|
}
|
|
@@ -1530,7 +1406,7 @@ export function runBaselineWrite(
|
|
|
1530
1406
|
engine: Engine,
|
|
1531
1407
|
host: Host,
|
|
1532
1408
|
scope: Scope,
|
|
1533
|
-
config:
|
|
1409
|
+
config: ResolvedConfig,
|
|
1534
1410
|
provenance: Provenance,
|
|
1535
1411
|
mode: Mode,
|
|
1536
1412
|
reason: string,
|