@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
|
@@ -7,18 +7,34 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { ModuleKind, ModuleResolutionKind } from "@typescript/native/sync";
|
|
9
9
|
import { isStringLiteralLikeNode } from "@typescript/native/ast";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import { JAVASCRIPT_FILE } from "../javascript-file.js";
|
|
11
|
+
import { isRecord } from "../json-document.js";
|
|
12
|
+
import { dirnamePath, resolvePath } from "../paths.js";
|
|
13
|
+
import { batched } from "../session.js";
|
|
14
|
+
import { bytewise } from "../text/compare.js";
|
|
15
|
+
import { PRODUCT } from "../product.js";
|
|
13
16
|
/**
|
|
14
|
-
* The options a configuration's program is built with:
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
17
|
+
* The options a configuration's program is built with: the plan's, less the ones that lay
|
|
18
|
+
* out an emitted program's inputs and outputs. The analysis emits nothing, and a member's
|
|
19
|
+
* source is outside the importer's root directory by construction, which the compiler
|
|
20
|
+
* refuses under such a layout.
|
|
18
21
|
*/
|
|
19
|
-
function analysisOptions(
|
|
20
|
-
const { composite, rootDir: _rootDir, outDir: _outDir, declarationDir: _declarationDir, tsBuildInfoFile: _tsBuildInfoFile, ...kept } =
|
|
21
|
-
|
|
22
|
+
function analysisOptions(options, readsJavaScript) {
|
|
23
|
+
const { composite, rootDir: _rootDir, outDir: _outDir, declarationDir: _declarationDir, tsBuildInfoFile: _tsBuildInfoFile, ...kept } = options;
|
|
24
|
+
const read = readsJavaScript ? { ...kept, allowJs: true } : kept;
|
|
25
|
+
return composite === true ? { ...read, declaration: true } : read;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Whether one reading answers a member import with a JavaScript file, which its program reads
|
|
29
|
+
* as source only where it allows JavaScript, a program formed for a JavaScript member being the
|
|
30
|
+
* member's source.
|
|
31
|
+
*/
|
|
32
|
+
function readsJavaScript(reading) {
|
|
33
|
+
return (reading.options.allowJs !== true &&
|
|
34
|
+
reading.entries.some((entry) => {
|
|
35
|
+
const file = entry.result.resolvedFileName;
|
|
36
|
+
return typeof file === "string" && JAVASCRIPT_FILE.test(file);
|
|
37
|
+
}));
|
|
22
38
|
}
|
|
23
39
|
/** The conditions an `exports` lookup under one configuration and one resolution mode reads. */
|
|
24
40
|
function conditionsOf(parsed, mode) {
|
|
@@ -47,29 +63,41 @@ function unstatable(reading) {
|
|
|
47
63
|
}
|
|
48
64
|
return undefined;
|
|
49
65
|
}
|
|
50
|
-
/** The path beside `configFile` its written configuration takes, which no file has. */
|
|
51
|
-
export function writtenPath(host, configFile) {
|
|
66
|
+
/** The path beside `configFile` its written configuration takes, which no file and none of `taken` has. */
|
|
67
|
+
export function writtenPath(host, configFile, taken = new Set()) {
|
|
52
68
|
const stem = configFile.replace(/\.json$/u, "");
|
|
53
69
|
for (let counter = 0;; counter += 1) {
|
|
54
|
-
const path = `${stem}
|
|
55
|
-
if (host.kindOf(path) === "absent") {
|
|
70
|
+
const path = `${stem}.${PRODUCT}${counter === 0 ? "" : `-${String(counter)}`}.json`;
|
|
71
|
+
if (host.kindOf(path) === "absent" && !taken.has(path)) {
|
|
56
72
|
return path;
|
|
57
73
|
}
|
|
58
74
|
}
|
|
59
75
|
}
|
|
60
76
|
/**
|
|
61
|
-
* The
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
* The path the snapshot holds one configuration's written form at: a formed configuration's
|
|
78
|
+
* own path, else a free one beside it that no configuration of `formed` holds, because a formed
|
|
79
|
+
* program in a directory with a `jsconfig.json` takes the name that file's written form would.
|
|
80
|
+
*/
|
|
81
|
+
export function writtenFileOf(host, configuration, formed) {
|
|
82
|
+
return configuration.written === undefined
|
|
83
|
+
? writtenPath(host, configuration.configFile, formed)
|
|
84
|
+
: configuration.configFile;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The configuration that reads as one configuration's program: it extends it, lays out no output
|
|
88
|
+
* ({@link analysisOptions}), maps each answered specifier to its file and keeps its references.
|
|
89
|
+
* Where the file list moves, the default `exclude` the dropped output directories are named in is
|
|
90
|
+
* restated, and one that {@link readsJavaScript} lists its files outright, as `allowJs` widens its
|
|
91
|
+
* `include` to JavaScript; a list that still differs, or answers `paths` cannot state, are a
|
|
92
|
+
* reason. A formed configuration, which no file holds to extend, is its own value with `paths`.
|
|
66
93
|
*/
|
|
67
|
-
function configurationOf(engine, host, reading) {
|
|
94
|
+
function configurationOf(engine, host, reading, formed) {
|
|
68
95
|
const reason = unstatable(reading);
|
|
69
96
|
if (reason !== undefined) {
|
|
70
97
|
return { kind: "unread", reason };
|
|
71
98
|
}
|
|
72
|
-
const { options
|
|
99
|
+
const { options } = reading;
|
|
100
|
+
const references = reading.parsed.projectReferences ?? [];
|
|
73
101
|
const raw = options["pathsBasePath"];
|
|
74
102
|
const base = typeof raw === "string" ? raw : dirnamePath(reading.configFile);
|
|
75
103
|
const paths = {};
|
|
@@ -82,6 +110,17 @@ function configurationOf(engine, host, reading) {
|
|
|
82
110
|
paths[entry.moduleName] = [file];
|
|
83
111
|
}
|
|
84
112
|
}
|
|
113
|
+
if (reading.written !== undefined) {
|
|
114
|
+
const held = reading.written["compilerOptions"];
|
|
115
|
+
return {
|
|
116
|
+
kind: "configuration",
|
|
117
|
+
value: {
|
|
118
|
+
...reading.written,
|
|
119
|
+
compilerOptions: { ...(isRecord(held) ? held : {}), paths },
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const javascript = readsJavaScript(reading);
|
|
85
124
|
const json = (exclude) => ({
|
|
86
125
|
extends: reading.configFile,
|
|
87
126
|
compilerOptions: {
|
|
@@ -90,18 +129,20 @@ function configurationOf(engine, host, reading) {
|
|
|
90
129
|
declarationDir: null,
|
|
91
130
|
tsBuildInfoFile: null,
|
|
92
131
|
...(options.composite === true ? { composite: false, declaration: true } : {}),
|
|
132
|
+
...(javascript ? { allowJs: true } : {}),
|
|
93
133
|
paths,
|
|
94
134
|
},
|
|
95
135
|
...(references.length > 0
|
|
96
136
|
? { references: references.map((reference) => ({ path: reference.path })) }
|
|
97
137
|
: {}),
|
|
138
|
+
...(javascript ? { files: [...reading.parsed.fileNames], include: [] } : {}),
|
|
98
139
|
...(exclude === undefined ? {} : { exclude }),
|
|
99
140
|
});
|
|
100
|
-
const file =
|
|
101
|
-
const expected = [...reading.parsed.fileNames].sort().join("\u0000");
|
|
141
|
+
const file = writtenFileOf(host, reading, formed);
|
|
142
|
+
const expected = [...reading.parsed.fileNames].sort(bytewise).join("\u0000");
|
|
102
143
|
const listed = (value) => {
|
|
103
144
|
try {
|
|
104
|
-
return [...engine.parseConfigJson(value, file).fileNames].sort().join("\u0000");
|
|
145
|
+
return [...engine.parseConfigJson(value, file).fileNames].sort(bytewise).join("\u0000");
|
|
105
146
|
}
|
|
106
147
|
catch {
|
|
107
148
|
return undefined;
|
|
@@ -120,11 +161,11 @@ function configurationOf(engine, host, reading) {
|
|
|
120
161
|
};
|
|
121
162
|
}
|
|
122
163
|
}
|
|
123
|
-
return { kind: "configuration",
|
|
164
|
+
return { kind: "configuration", value };
|
|
124
165
|
}
|
|
125
166
|
/** The program one configuration is built as, under the answers it holds so far. */
|
|
126
167
|
function programOf(engine, reading) {
|
|
127
|
-
const compilerOptions = analysisOptions(reading.
|
|
168
|
+
const compilerOptions = analysisOptions(reading.options, readsJavaScript(reading));
|
|
128
169
|
const references = reading.parsed.projectReferences ?? [];
|
|
129
170
|
const resolver = engine.createModuleResolver(compilerOptions, reading.entries);
|
|
130
171
|
return {
|
|
@@ -140,17 +181,6 @@ function programOf(engine, reading) {
|
|
|
140
181
|
},
|
|
141
182
|
};
|
|
142
183
|
}
|
|
143
|
-
function chunks(items) {
|
|
144
|
-
const found = [];
|
|
145
|
-
for (let at = 0; at < items.length; at += BATCH) {
|
|
146
|
-
found.push(items.slice(at, at + BATCH));
|
|
147
|
-
}
|
|
148
|
-
return found;
|
|
149
|
-
}
|
|
150
|
-
/** Asks one question of every item, in round trips of at most {@link BATCH}. */
|
|
151
|
-
function batched(engine, items, question) {
|
|
152
|
-
return chunks(items).flatMap((run) => engine.batch(run.map(question)));
|
|
153
|
-
}
|
|
154
184
|
/** One round over one program: answers the member imports no earlier round asked about. */
|
|
155
185
|
function scan(engine, program, reading, resolver) {
|
|
156
186
|
const names = program.getSourceFileNames().filter((name) => !name.includes("/node_modules/"));
|
|
@@ -211,6 +241,13 @@ function scan(engine, program, reading, resolver) {
|
|
|
211
241
|
});
|
|
212
242
|
return added;
|
|
213
243
|
}
|
|
244
|
+
function configurationText(value) {
|
|
245
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
246
|
+
}
|
|
247
|
+
/** One configuration value as the snapshot holds it, at `file`, which no file on disk holds. */
|
|
248
|
+
export function writtenConfiguration(file, value) {
|
|
249
|
+
return { kind: "configuration", file, text: configurationText(value) };
|
|
250
|
+
}
|
|
214
251
|
/**
|
|
215
252
|
* Answers the member imports of every reading `build` describes, round by round, all
|
|
216
253
|
* the readings still adding answers built in one snapshot per round. A reading `build`
|
|
@@ -252,35 +289,25 @@ function readRounds(engine, readings, resolver, build) {
|
|
|
252
289
|
* the rounds go on over each reading's configuration, which reads them, for the imports
|
|
253
290
|
* only they make.
|
|
254
291
|
*/
|
|
255
|
-
export function workspacePrograms(engine, host,
|
|
256
|
-
const readings =
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
265
|
-
return [
|
|
266
|
-
{
|
|
267
|
-
configFile,
|
|
268
|
-
parsed,
|
|
269
|
-
entries: [],
|
|
270
|
-
seen: new Set(),
|
|
271
|
-
bound: new Map(),
|
|
272
|
-
unresolved: [],
|
|
273
|
-
},
|
|
274
|
-
];
|
|
275
|
-
});
|
|
292
|
+
export function workspacePrograms(engine, host, configurations, resolver) {
|
|
293
|
+
const readings = configurations.map((configuration) => ({
|
|
294
|
+
...configuration,
|
|
295
|
+
entries: [],
|
|
296
|
+
seen: new Set(),
|
|
297
|
+
bound: new Map(),
|
|
298
|
+
unresolved: [],
|
|
299
|
+
}));
|
|
300
|
+
const formed = new Set(configurations.filter((one) => one.written !== undefined).map((one) => one.configFile));
|
|
276
301
|
readRounds(engine, readings, resolver, (reading) => ({
|
|
277
302
|
kind: "program",
|
|
278
303
|
...programOf(engine, reading),
|
|
279
304
|
}));
|
|
280
305
|
if (engine.readsComponents) {
|
|
281
306
|
readRounds(engine, readings, resolver, (reading) => {
|
|
282
|
-
const one = configurationOf(engine, host, reading);
|
|
283
|
-
return one.kind === "configuration"
|
|
307
|
+
const one = configurationOf(engine, host, reading, formed);
|
|
308
|
+
return one.kind === "configuration"
|
|
309
|
+
? writtenConfiguration(writtenFileOf(host, reading, formed), one.value)
|
|
310
|
+
: undefined;
|
|
284
311
|
});
|
|
285
312
|
}
|
|
286
313
|
const programs = new Map();
|
|
@@ -289,7 +316,7 @@ export function workspacePrograms(engine, host, configFiles, resolver) {
|
|
|
289
316
|
if (reading.entries.length === 0) {
|
|
290
317
|
continue;
|
|
291
318
|
}
|
|
292
|
-
const one = engine.readsComponents ? configurationOf(engine, host, reading) : undefined;
|
|
319
|
+
const one = engine.readsComponents ? configurationOf(engine, host, reading, formed) : undefined;
|
|
293
320
|
if (one !== undefined && one.kind !== "unread") {
|
|
294
321
|
programs.set(reading.configFile, one);
|
|
295
322
|
continue;
|
|
@@ -1,43 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Which file an import of a workspace package's name is read from
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the package
|
|
7
|
-
* import nothing answers for is unresolved.
|
|
2
|
+
* Which file an import of a workspace package's name is read from: the package
|
|
3
|
+
* `node_modules` links the importer to or, with no link, the one its manifest depends on.
|
|
4
|
+
* A source file the compiler reaches stands; any other file reads back to its source or to
|
|
5
|
+
* a manifest target that is source, an ignored file to the source its path mirrors, a file
|
|
6
|
+
* the package neither compiles nor writes is read as installed, and the rest is unresolved.
|
|
8
7
|
*/
|
|
9
8
|
import { emittedFrom } from "./emit-map.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { packageOfSpecifier } from "../dependencies.js";
|
|
10
|
+
import { gitIgnored } from "../git-ignore.js";
|
|
11
|
+
import { ancestors, dirnamePath, joinPath, relativePath, resolvePath } from "../paths.js";
|
|
12
|
+
import { satisfies } from "../version-range.js";
|
|
13
|
+
import { isRecord } from "../json-document.js";
|
|
14
|
+
import { MANIFEST } from "../fs/manifest.js";
|
|
15
|
+
import { dependencySpecifiers, installedPackage, manifestsAbove, } from "./module-lookup.js";
|
|
12
16
|
/** The manifest members that name an entry point for the subpath `.` without `exports`. */
|
|
13
17
|
const LEGACY_MEMBERS = ["types", "typings", "module", "main"];
|
|
14
|
-
/** The dependency members a manifest declares other packages under. */
|
|
15
|
-
const DEPENDENCY_MEMBERS = [
|
|
16
|
-
"dependencies",
|
|
17
|
-
"devDependencies",
|
|
18
|
-
"peerDependencies",
|
|
19
|
-
"optionalDependencies",
|
|
20
|
-
];
|
|
21
18
|
const SOURCE = /(?<!\.d)\.(?:[mc]?ts|tsx)$/u;
|
|
22
19
|
const OUTPUT = /(?:\.d\.[mc]?ts|\.[mc]?js|\.jsx)$/u;
|
|
23
|
-
function isRecord(value) {
|
|
24
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25
|
-
}
|
|
26
|
-
/** The package name a bare specifier names, or `undefined` for any other specifier. */
|
|
27
|
-
export function packageNameOf(specifier) {
|
|
28
|
-
if (specifier === "" ||
|
|
29
|
-
specifier.startsWith(".") ||
|
|
30
|
-
specifier.startsWith("#") ||
|
|
31
|
-
isAbsolutePath(specifier) ||
|
|
32
|
-
specifier.includes(":")) {
|
|
33
|
-
return undefined;
|
|
34
|
-
}
|
|
35
|
-
const [first, second] = specifier.split("/");
|
|
36
|
-
if (specifier.startsWith("@")) {
|
|
37
|
-
return second === undefined || second === "" ? undefined : `${first ?? ""}/${second}`;
|
|
38
|
-
}
|
|
39
|
-
return first;
|
|
40
|
-
}
|
|
41
20
|
function inside(dir, path) {
|
|
42
21
|
return relativePath(dir, path) !== undefined;
|
|
43
22
|
}
|
|
@@ -140,28 +119,32 @@ function dependsOn(specifier, member, fromDir) {
|
|
|
140
119
|
/** The member imports of one workspace, read from the members' sources. */
|
|
141
120
|
export function workspaceResolver(host, workspace) {
|
|
142
121
|
const links = new Map();
|
|
143
|
-
/** The directory `
|
|
122
|
+
/** The directory the package `name` installed for one directory is, links followed. */
|
|
144
123
|
const linkedFrom = (name, dir) => {
|
|
145
124
|
const key = `${name}\u0000${dir}`;
|
|
146
|
-
if (links.has(key)) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const candidate = joinPath(dir, "node_modules", name);
|
|
150
|
-
let found;
|
|
151
|
-
if (host.kindOf(candidate) === "absent") {
|
|
152
|
-
const up = dirnamePath(dir);
|
|
153
|
-
found = up === dir ? undefined : linkedFrom(name, up);
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
125
|
+
if (!links.has(key)) {
|
|
126
|
+
const installed = installedPackage(host, dir, name);
|
|
127
|
+
let found;
|
|
156
128
|
try {
|
|
157
|
-
found = host.realPath(
|
|
129
|
+
found = installed === undefined ? undefined : host.realPath(installed);
|
|
158
130
|
}
|
|
159
131
|
catch {
|
|
160
132
|
found = undefined;
|
|
161
133
|
}
|
|
134
|
+
links.set(key, found);
|
|
135
|
+
}
|
|
136
|
+
return links.get(key);
|
|
137
|
+
};
|
|
138
|
+
const root = workspace.members[0]?.dir;
|
|
139
|
+
const ignored = root === undefined ? () => false : gitIgnored(host, root);
|
|
140
|
+
const manifests = new Map();
|
|
141
|
+
/** The nearest manifest at or above one directory, up to the workspace's root. */
|
|
142
|
+
const nearestManifest = (dir) => {
|
|
143
|
+
if (!manifests.has(dir)) {
|
|
144
|
+
const [nearest] = manifestsAbove(host, dir, root ?? dir);
|
|
145
|
+
manifests.set(dir, nearest);
|
|
162
146
|
}
|
|
163
|
-
|
|
164
|
-
return found;
|
|
147
|
+
return manifests.get(dir);
|
|
165
148
|
};
|
|
166
149
|
const linkOf = (candidates, fromDir) => {
|
|
167
150
|
const name = candidates[0]?.name ?? "";
|
|
@@ -170,17 +153,15 @@ export function workspaceResolver(host, workspace) {
|
|
|
170
153
|
const member = candidates.find((one) => one.dir === linked);
|
|
171
154
|
return member === undefined ? { kind: "none" } : { kind: "member", member };
|
|
172
155
|
}
|
|
173
|
-
const scope = workspace.memberOf(joinPath(fromDir,
|
|
156
|
+
const scope = workspace.memberOf(joinPath(fromDir, MANIFEST));
|
|
174
157
|
if (scope?.name === name) {
|
|
175
158
|
return { kind: "member", member: scope };
|
|
176
159
|
}
|
|
177
|
-
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
});
|
|
183
|
-
const matched = candidates.filter((member) => declared.some((specifier) => dependsOn(specifier, member, scope?.dir ?? fromDir)));
|
|
160
|
+
// A package below the root that no workspace lists depends on a member as a member does.
|
|
161
|
+
const owner = scope ?? nearestManifest(fromDir);
|
|
162
|
+
const manifest = owner?.manifest;
|
|
163
|
+
const declared = (manifest === undefined ? [] : dependencySpecifiers(manifest, name)).filter((specifier) => typeof specifier === "string");
|
|
164
|
+
const matched = candidates.filter((member) => declared.some((specifier) => dependsOn(specifier, member, owner?.dir ?? fromDir)));
|
|
184
165
|
const [one, two] = matched;
|
|
185
166
|
if (one === undefined) {
|
|
186
167
|
return { kind: "none" };
|
|
@@ -191,6 +172,21 @@ export function workspaceResolver(host, workspace) {
|
|
|
191
172
|
};
|
|
192
173
|
/** The files a member's configurations compile, which is what makes a file there source. */
|
|
193
174
|
const compiled = (member, path) => member.configurations.some((configuration) => configuration.fileNames.has(path));
|
|
175
|
+
/**
|
|
176
|
+
* The member's source an ignored output path mirrors: the path below one of its
|
|
177
|
+
* directories, the deepest first, read below the member's own directory as an output
|
|
178
|
+
* directory's tree mirrors its root directory's, which a build leaves in an ignored
|
|
179
|
+
* directory however its configuration writes it.
|
|
180
|
+
*/
|
|
181
|
+
const mirrored = (member, path) => {
|
|
182
|
+
for (const dir of ancestors(dirnamePath(path), member.dir).filter((at) => at !== member.dir)) {
|
|
183
|
+
const found = emittedFrom(path, { outDir: dir, sourceDirs: [member.dir] }).find((candidate) => SOURCE.test(candidate) && !ignored(candidate) && host.kindOf(candidate) === "file");
|
|
184
|
+
if (found !== undefined) {
|
|
185
|
+
return found;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return undefined;
|
|
189
|
+
};
|
|
194
190
|
/**
|
|
195
191
|
* The member's source one of its paths is, or is compiled from: a TypeScript source
|
|
196
192
|
* file, the source an output path maps back to, or a file one of the member's
|
|
@@ -212,6 +208,9 @@ export function workspaceResolver(host, workspace) {
|
|
|
212
208
|
if (found !== undefined) {
|
|
213
209
|
return found;
|
|
214
210
|
}
|
|
211
|
+
if (ignored(path)) {
|
|
212
|
+
return mirrored(member, path);
|
|
213
|
+
}
|
|
215
214
|
return compiled(member, path) && host.kindOf(path) === "file" ? path : undefined;
|
|
216
215
|
};
|
|
217
216
|
/** The targets a member's manifest names for one subpath, the selected one first. */
|
|
@@ -247,11 +246,11 @@ export function workspaceResolver(host, workspace) {
|
|
|
247
246
|
workspace,
|
|
248
247
|
sourceOf,
|
|
249
248
|
names: (specifier) => {
|
|
250
|
-
const name =
|
|
249
|
+
const name = packageOfSpecifier(specifier);
|
|
251
250
|
return name !== undefined && workspace.named.has(name);
|
|
252
251
|
},
|
|
253
252
|
resolve(specifier, fromDir, conditions, answered) {
|
|
254
|
-
const name =
|
|
253
|
+
const name = packageOfSpecifier(specifier);
|
|
255
254
|
const candidates = name === undefined ? undefined : workspace.named.get(name);
|
|
256
255
|
if (name === undefined || candidates === undefined) {
|
|
257
256
|
return { kind: "default" };
|
|
@@ -270,9 +269,11 @@ export function workspaceResolver(host, workspace) {
|
|
|
270
269
|
}
|
|
271
270
|
const { member } = linked;
|
|
272
271
|
// A member no compiler configuration builds is read as the package manager
|
|
273
|
-
// installed it, wherever the compiler's resolution found it
|
|
272
|
+
// installed it, wherever the compiler's resolution found it, unless what it found is
|
|
273
|
+
// a file the tree ignores, which no install wrote.
|
|
274
274
|
if (answered !== undefined &&
|
|
275
|
-
(member.configurations.length === 0
|
|
275
|
+
((member.configurations.length === 0 && !ignored(answered.resolvedFileName)) ||
|
|
276
|
+
!inside(member.dir, answered.resolvedFileName))) {
|
|
276
277
|
return { kind: "default" };
|
|
277
278
|
}
|
|
278
279
|
if (answered !== undefined) {
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
* the files each configuration holds only for their references, and the entry points
|
|
5
5
|
* the members' manifests name. A target in no workspace reads none of it.
|
|
6
6
|
*/
|
|
7
|
-
import { relativePath } from "
|
|
8
|
-
import {
|
|
7
|
+
import { relativePath } from "../paths.js";
|
|
8
|
+
import { referenceOnlyIn } from "./workspace.js";
|
|
9
9
|
import { memberEntries, targetManifestIn } from "./workspace-manifests.js";
|
|
10
10
|
import { workspacePrograms, } from "./workspace-programs.js";
|
|
11
11
|
import { workspaceResolver } from "./workspace-resolution.js";
|
|
12
|
-
|
|
12
|
+
/** What one member's configuration file says of its layout, or `undefined` where it does not parse. */
|
|
13
|
+
export function layoutOf(engine, configFile) {
|
|
13
14
|
try {
|
|
14
15
|
const parsed = engine.parseConfigFile(configFile);
|
|
15
16
|
return {
|
|
@@ -42,16 +43,16 @@ function unbuildableReason(reading, referenceOnly, targetRoot) {
|
|
|
42
43
|
* The workspace the target at `targetRoot` sits in, read for the configurations named,
|
|
43
44
|
* or `undefined` where the target sits in none.
|
|
44
45
|
*/
|
|
45
|
-
export function workspaceRun(engine, host, targetRoot,
|
|
46
|
-
const workspace = findWorkspace(host, targetRoot, (configFile) => layoutOf(engine, configFile));
|
|
46
|
+
export function workspaceRun(engine, host, targetRoot, configurations, manifest, workspace) {
|
|
47
47
|
if (workspace === undefined) {
|
|
48
48
|
return undefined;
|
|
49
49
|
}
|
|
50
50
|
const resolver = workspaceResolver(host, workspace);
|
|
51
|
-
const read = workspacePrograms(engine, host,
|
|
51
|
+
const read = workspacePrograms(engine, host, configurations, resolver);
|
|
52
52
|
const readings = new Map(read.readings.map((reading) => [reading.configFile, reading]));
|
|
53
53
|
const referenceOnly = (configFile, compiled = []) => referenceOnlyIn(workspace, new Set([...(readings.get(configFile)?.fileNames ?? []), ...compiled]));
|
|
54
54
|
return {
|
|
55
|
+
workspace,
|
|
55
56
|
programs: read.programs,
|
|
56
57
|
componentsUnread: read.readings.flatMap(({ configFile, componentsUnread }) => componentsUnread === undefined ? [] : [{ configFile, reason: componentsUnread }]),
|
|
57
58
|
unbuildable: (configFile) => {
|
|
@@ -66,7 +67,6 @@ export function workspaceRun(engine, host, targetRoot, configFiles, manifest) {
|
|
|
66
67
|
: !fromExternalLibrary,
|
|
67
68
|
manifest: targetManifestIn(resolver, targetRoot, manifest),
|
|
68
69
|
entries: memberEntries(host, resolver, targetRoot),
|
|
69
|
-
memberDirs: workspace.members.map((member) => member.dir),
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
72
|
/** The errors one configuration answers for: none in a file it holds only for its references. */
|