@cplieger/deadset-ts 8.0.0-dev.15 → 8.0.0-dev.17
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/dist/src/alias-chain.js +0 -5
- package/dist/src/amd.js +81 -0
- package/dist/src/analysis.js +94 -54
- package/dist/src/augmentations.js +23 -24
- package/dist/src/bindings.js +382 -0
- package/dist/src/calls.js +25 -8
- package/dist/src/commands/read.js +6 -7
- package/dist/src/commands/tools.js +5 -9
- package/dist/src/component-files.js +3 -2
- package/dist/src/conformance-record.js +1 -1
- package/dist/src/consumers.js +9 -10
- package/dist/src/contextual-uses.js +1 -17
- package/dist/src/contract/config.generated.js +5 -2
- package/dist/src/contract/contract.generated.js +119 -2
- package/dist/src/contract/report.generated.js +6 -2
- package/dist/src/dependencies.js +98 -71
- package/dist/src/destructuring.js +1 -19
- package/dist/src/element-access.js +179 -164
- package/dist/src/entries/build-scripts.js +222 -0
- package/dist/src/{configuration-files.js → entries/configuration-files.js} +22 -64
- package/dist/src/{convention-rows.js → entries/convention-rows.js} +120 -27
- package/dist/src/entries/conventions.js +739 -0
- package/dist/src/{html-entries.js → entries/html-entries.js} +9 -12
- package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +3 -3
- package/dist/src/entries/run-directories.js +77 -0
- package/dist/src/entries/sources.js +144 -0
- package/dist/src/entries/static-module.js +670 -0
- package/dist/src/entries/test-runners.js +684 -0
- package/dist/src/{workflow-steps.js → entries/workflow-steps.js} +18 -8
- package/dist/src/extensions.js +37 -0
- package/dist/src/facts.js +38 -0
- package/dist/src/findings/completion.js +40 -4
- package/dist/src/findings/emitters.js +5 -8
- package/dist/src/{implementations.js → findings/implementations.js} +3 -3
- package/dist/src/{in-operands.js → findings/in-operands.js} +2 -2
- package/dist/src/findings/self-check.js +36 -20
- package/dist/src/findings-pass.js +5 -6
- package/dist/src/framework-lifecycle.js +42 -15
- package/dist/src/fs/manifest.js +15 -20
- package/dist/src/generated-file.js +172 -29
- package/dist/src/graph.js +14 -8
- package/dist/src/import-bindings.js +73 -28
- package/dist/src/index/sites.js +557 -0
- package/dist/src/index.js +1 -1
- package/dist/src/indexed-access.js +523 -478
- package/dist/src/injection-container.js +1 -1
- package/dist/src/interface-satisfaction.js +1 -1
- package/dist/src/inventory/commonjs.js +62 -17
- package/dist/src/inventory/enumerate.js +2 -1
- package/dist/src/javascript-file.js +26 -11
- package/dist/src/keyof-comparisons.js +124 -103
- package/dist/src/load/classify.js +28 -9
- package/dist/src/load/diagnostics.js +8 -1
- package/dist/src/load/discover.js +15 -7
- package/dist/src/load/expected-module.js +2 -2
- package/dist/src/load/plan.js +2 -2
- package/dist/src/load/specifiers.js +2 -4
- package/dist/src/load/synthesize.js +10 -5
- package/dist/src/load/workspace-manifests.js +1 -1
- package/dist/src/load/workspace-resolution.js +2 -2
- package/dist/src/matrix.js +12 -17
- package/dist/src/module-declarations.js +70 -85
- package/dist/src/overrides.js +134 -112
- package/dist/src/paths.js +56 -1
- package/dist/src/platform-calls.js +78 -0
- package/dist/src/platform-symbols.js +134 -0
- package/dist/src/references/read-rule.js +1 -0
- package/dist/src/references/read-rules.js +48 -0
- package/dist/src/references/sink.js +151 -0
- package/dist/src/references/sources.js +450 -0
- package/dist/src/references.js +111 -1116
- package/dist/src/resolve.js +1 -1
- package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +7 -4
- package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +5 -8
- package/dist/src/{manifest.js → roots/manifest.js} +4 -4
- package/dist/src/roots/published-reach.js +412 -0
- package/dist/src/roots/root-set.js +489 -0
- package/dist/src/roots/unseen-loads.js +236 -0
- package/dist/src/serialization-contract.js +9 -4
- package/dist/src/source-files.js +5 -9
- package/dist/src/stores.js +4 -2
- package/dist/src/suppress.js +30 -32
- package/dist/src/sweep.js +25 -13
- package/dist/src/symbol-keys.js +89 -83
- package/dist/src/tests/file-class.js +76 -0
- package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
- package/dist/src/{test-support.js → tests/support.js} +5 -12
- package/dist/src/type-parameter-reads.js +178 -139
- package/dist/src/unimplemented-callees.js +262 -242
- package/dist/src/verbs/analyze.js +15 -3
- package/dist/src/verbs/describe.js +5 -3
- package/dist/src/verbs/explain.js +50 -28
- package/dist/src/verbs/print-retained.js +2 -2
- package/jsr.json +1 -1
- package/package.json +3 -3
- package/src/alias-chain.ts +0 -7
- package/src/amd.ts +130 -0
- package/src/analysis.ts +156 -70
- package/src/augmentations.ts +41 -27
- package/src/automatic-types.ts +1 -1
- package/src/bindings.ts +460 -0
- package/src/calls.ts +25 -7
- package/src/commands/read.ts +6 -8
- package/src/commands/tools.ts +5 -11
- package/src/component-files.ts +4 -2
- package/src/conformance-record.ts +1 -1
- package/src/consumers.ts +12 -11
- package/src/contextual-uses.ts +2 -22
- package/src/contract/config.generated.ts +5 -2
- package/src/contract/contract.generated.ts +138 -2
- package/src/contract/report.generated.ts +6 -2
- package/src/dependencies.ts +117 -71
- package/src/destructuring.ts +1 -31
- package/src/element-access.ts +188 -182
- package/src/entries/build-scripts.ts +292 -0
- package/src/{configuration-files.ts → entries/configuration-files.ts} +33 -82
- package/src/{convention-rows.ts → entries/convention-rows.ts} +167 -28
- package/src/{conventions.ts → entries/conventions.ts} +349 -523
- package/src/{html-entries.ts → entries/html-entries.ts} +19 -18
- package/src/{mdx-entries.ts → entries/mdx-entries.ts} +5 -5
- package/src/entries/run-directories.ts +108 -0
- package/src/entries/sources.ts +266 -0
- package/src/entries/static-module.ts +858 -0
- package/src/entries/test-runners.ts +868 -0
- package/src/{workflow-steps.ts → entries/workflow-steps.ts} +29 -11
- package/src/exempt.ts +3 -2
- package/src/extensions.ts +45 -0
- package/src/facts.ts +46 -0
- package/src/file-facts.ts +1 -1
- package/src/findings/boundary.ts +2 -0
- package/src/findings/completion.ts +43 -4
- package/src/findings/emitter.ts +1 -1
- package/src/findings/emitters.ts +14 -10
- package/src/{implementations.ts → findings/implementations.ts} +4 -4
- package/src/{in-operands.ts → findings/in-operands.ts} +3 -3
- package/src/findings/self-check.ts +41 -22
- package/src/findings/visibility-narrowing.ts +1 -1
- package/src/findings-pass.ts +5 -12
- package/src/framework-lifecycle.ts +43 -15
- package/src/fs/manifest.ts +25 -21
- package/src/generated-file.ts +240 -36
- package/src/graph.ts +27 -11
- package/src/import-bindings.ts +98 -29
- package/src/index/sites.ts +781 -0
- package/src/index.ts +1 -1
- package/src/indexed-access.ts +570 -527
- package/src/injection-container.ts +1 -1
- package/src/interface-satisfaction.ts +1 -1
- package/src/inventory/commonjs.ts +102 -17
- package/src/inventory/enumerate.ts +2 -1
- package/src/javascript-file.ts +29 -12
- package/src/keyof-comparisons.ts +131 -116
- package/src/load/classify.ts +49 -13
- package/src/load/diagnostics.ts +11 -1
- package/src/load/discover.ts +27 -11
- package/src/load/expected-module.ts +8 -2
- package/src/load/plan.ts +11 -2
- package/src/load/specifiers.ts +8 -5
- package/src/load/synthesize.ts +12 -6
- package/src/load/test-globals.ts +1 -1
- package/src/load/workspace-manifests.ts +1 -1
- package/src/load/workspace-resolution.ts +9 -2
- package/src/load/workspace-run.ts +1 -1
- package/src/matrix.ts +13 -17
- package/src/module-declarations.ts +74 -98
- package/src/overrides.ts +162 -134
- package/src/paths.ts +65 -1
- package/src/platform-calls.ts +119 -0
- package/src/platform-symbols.ts +189 -0
- package/src/references/read-rule.ts +60 -0
- package/src/references/read-rules.ts +55 -0
- package/src/references/sink.ts +213 -0
- package/src/references/sources.ts +632 -0
- package/src/references.ts +174 -1492
- package/src/report.ts +2 -2
- package/src/resolve.ts +1 -1
- package/src/{configured-declarations.ts → roots/configured-declarations.ts} +10 -7
- package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +5 -8
- package/src/{manifest.ts → roots/manifest.ts} +5 -5
- package/src/roots/published-reach.ts +481 -0
- package/src/{roots.ts → roots/root-set.ts} +203 -630
- package/src/roots/unseen-loads.ts +345 -0
- package/src/serialization-contract.ts +9 -4
- package/src/source-files.ts +5 -10
- package/src/stores.ts +13 -2
- package/src/suppress.ts +48 -33
- package/src/sweep.ts +37 -14
- package/src/symbol-keys.ts +102 -102
- package/src/tests/file-class.ts +118 -0
- package/src/{outside-tests.ts → tests/outside.ts} +16 -10
- package/src/{test-support.ts → tests/support.ts} +15 -21
- package/src/type-parameter-reads.ts +187 -158
- package/src/unimplemented-callees.ts +297 -280
- package/src/verbs/analyze.ts +19 -5
- package/src/verbs/describe.ts +5 -2
- package/src/verbs/explain.ts +75 -32
- package/src/verbs/print-retained.ts +2 -2
- package/dist/src/build-scripts.js +0 -418
- package/dist/src/conventions.js +0 -907
- package/dist/src/entry-points.js +0 -444
- package/dist/src/own-body.js +0 -28
- package/dist/src/roots.js +0 -865
- package/dist/src/unseen-loads.js +0 -189
- package/src/build-scripts.ts +0 -536
- package/src/entry-points.ts +0 -584
- package/src/own-body.ts +0 -42
- package/src/unseen-loads.ts +0 -282
|
@@ -63,9 +63,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
63
63
|
const privateNames = new Set(held.symbols
|
|
64
64
|
.filter((symbol) => symbol.visibility === "private-name")
|
|
65
65
|
.map((symbol) => symbol.id));
|
|
66
|
-
let batches = 0;
|
|
67
|
-
let lookups = 0;
|
|
68
|
-
const batchesOf = (count) => Math.ceil(count / cap);
|
|
69
66
|
const parts = new Map();
|
|
70
67
|
/** The object types one type is: itself, or its constituents at any depth. */
|
|
71
68
|
const partsOf = (type) => {
|
|
@@ -75,7 +72,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
75
72
|
}
|
|
76
73
|
let found = [];
|
|
77
74
|
if (type.isUnionType() || type.isIntersectionType()) {
|
|
78
|
-
lookups += 1;
|
|
79
75
|
const constituents = queries.constituents(type);
|
|
80
76
|
found = isAnswered(constituents) ? constituents.flatMap(partsOf) : [];
|
|
81
77
|
}
|
|
@@ -94,7 +90,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
94
90
|
}
|
|
95
91
|
const table = new Map();
|
|
96
92
|
const read = properties.of(type);
|
|
97
|
-
lookups += read.asked ? 1 : 0;
|
|
98
93
|
for (const property of isAnswered(read.properties) ? read.properties : []) {
|
|
99
94
|
table.set(property.name, {
|
|
100
95
|
ids: chains
|
|
@@ -112,7 +107,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
112
107
|
return table;
|
|
113
108
|
};
|
|
114
109
|
const writes = [];
|
|
115
|
-
batches += batchesOf(literals.length);
|
|
116
110
|
const contexts = queries.contextualTypes(literals.map((one) => one.literal), cap);
|
|
117
111
|
// A computed name that is not literal text names the property the literal declares
|
|
118
112
|
// under the checker's own key, which is how a type declares a member a unique symbol
|
|
@@ -123,7 +117,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
123
117
|
const name = propertyName(property);
|
|
124
118
|
return name !== undefined && name.text === undefined ? [name.node] : [];
|
|
125
119
|
}));
|
|
126
|
-
batches += batchesOf(computed.length);
|
|
127
120
|
const keys = new Map();
|
|
128
121
|
(computed.length === 0
|
|
129
122
|
? []
|
|
@@ -152,7 +145,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
152
145
|
}
|
|
153
146
|
});
|
|
154
147
|
const carried = flows.filter((flow) => !isObjectLiteralExpression(flow.value));
|
|
155
|
-
batches += batchesOf(carried.length);
|
|
156
148
|
const types = queries.typesAt(carried.map((flow) => flow.value), cap);
|
|
157
149
|
/** The members a position may read structurally: those of object types, not of classes. */
|
|
158
150
|
const readable = (member) => [
|
|
@@ -198,11 +190,9 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
198
190
|
if (elements.has(type.id)) {
|
|
199
191
|
return elements.get(type.id);
|
|
200
192
|
}
|
|
201
|
-
lookups += 1;
|
|
202
193
|
const isArray = queries.isArray(type);
|
|
203
194
|
let element;
|
|
204
195
|
if (isAnswered(isArray) && isArray) {
|
|
205
|
-
lookups += 1;
|
|
206
196
|
const held = queries.typeArguments(type);
|
|
207
197
|
element = isAnswered(held) ? held[0] : undefined;
|
|
208
198
|
}
|
|
@@ -216,7 +206,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
216
206
|
if (known !== undefined) {
|
|
217
207
|
return known;
|
|
218
208
|
}
|
|
219
|
-
lookups += type.isTypeReference() ? 1 : 0;
|
|
220
209
|
const held = queries.typeArguments(type);
|
|
221
210
|
const found = isAnswered(held) ? held : [];
|
|
222
211
|
argumentsOf.set(type.id, found);
|
|
@@ -232,18 +221,15 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
232
221
|
if (known !== undefined) {
|
|
233
222
|
return known;
|
|
234
223
|
}
|
|
235
|
-
lookups += 1;
|
|
236
224
|
let kind = SignatureKind.Call;
|
|
237
225
|
let signatures = queries.signaturesOf(type, kind);
|
|
238
226
|
if (isAnswered(signatures) && signatures.length === 0) {
|
|
239
|
-
lookups += 1;
|
|
240
227
|
kind = SignatureKind.Construct;
|
|
241
228
|
signatures = queries.signaturesOf(type, kind);
|
|
242
229
|
}
|
|
243
230
|
const called = (isAnswered(signatures) ? signatures : []).map((signature) => {
|
|
244
231
|
const parameters = signature.parameters.map((_parameter, index) => queries.parameterType(signature, index));
|
|
245
232
|
const result = queries.returnTypeOf(signature);
|
|
246
|
-
lookups += parameters.length + 1;
|
|
247
233
|
return {
|
|
248
234
|
kind,
|
|
249
235
|
parameters: parameters.map((one) => (isAnswered(one) ? one : undefined)),
|
|
@@ -335,7 +321,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
335
321
|
const type = types[index];
|
|
336
322
|
return type === undefined || !isAnswered(type) || !mayCarry(type) ? [] : [{ flow, type }];
|
|
337
323
|
});
|
|
338
|
-
batches += batchesOf(sourced.length);
|
|
339
324
|
const positions = queries.contextualTypes(sourced.map((one) => one.flow.value), cap);
|
|
340
325
|
const reads = [];
|
|
341
326
|
// A literal property writes a position's members once, however many values carry it there.
|
|
@@ -408,7 +393,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
408
393
|
return known;
|
|
409
394
|
};
|
|
410
395
|
const spreads = literals.flatMap(({ literal, from }) => literal.properties.flatMap((property) => isSpreadAssignment(property) ? [{ value: property.expression, from }] : []));
|
|
411
|
-
batches += batchesOf(spreads.length);
|
|
412
396
|
const spreadTypes = queries.typesAt(spreads.map((one) => one.value), cap);
|
|
413
397
|
spreads.forEach(({ value, from }, index) => {
|
|
414
398
|
const type = spreadTypes[index];
|
|
@@ -426,5 +410,5 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
|
|
|
426
410
|
reads.push({ at: value, from, ids });
|
|
427
411
|
}
|
|
428
412
|
});
|
|
429
|
-
return { writes, reads
|
|
413
|
+
return { writes, reads };
|
|
430
414
|
}
|
|
@@ -273,7 +273,7 @@ export const SETTINGS = [
|
|
|
273
273
|
role: "setting",
|
|
274
274
|
read: true,
|
|
275
275
|
default: [
|
|
276
|
-
"**/*.test.{ts,tsx,mts,cts}",
|
|
276
|
+
"**/*.test.{ts,tsx,mts,cts,js,jsx,mjs,cjs}",
|
|
277
277
|
"**/*.test-d.{ts,tsx,mts,cts}",
|
|
278
278
|
"**/*.spec-d.{ts,tsx,mts,cts}",
|
|
279
279
|
"**/*.spec.*",
|
|
@@ -483,7 +483,10 @@ export const SETTINGS = [
|
|
|
483
483
|
key: "provenance",
|
|
484
484
|
role: "ignored",
|
|
485
485
|
read: true,
|
|
486
|
-
value: {
|
|
486
|
+
value: {
|
|
487
|
+
type: "string",
|
|
488
|
+
pattern: "^(default|(repository|central|flag): ([^\\r\\n]|[\\r\\n])+)$",
|
|
489
|
+
},
|
|
487
490
|
keyPattern: "^[a-z][a-z_]*(\\.[A-Za-z0-9_]+)*$",
|
|
488
491
|
},
|
|
489
492
|
];
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export const CONTRACT_VERSION = "8.0.0";
|
|
3
3
|
export const SCHEMA_VERSIONS = ["9.0.0"];
|
|
4
4
|
export const SCHEMA_VERSION = "9.0.0";
|
|
5
|
+
export const FACTS_VERSION = "1.0.0";
|
|
5
6
|
export const CORPUS_VERSION = "6.0.0";
|
|
6
7
|
export const CODE_PREFIX = "DS";
|
|
7
8
|
export const FAMILY_KEY_LENGTH = 4;
|
|
@@ -25,16 +26,19 @@ export const LANGUAGE_ROWS = {
|
|
|
25
26
|
analyzer: "deadset-go",
|
|
26
27
|
markers: ["go.mod"],
|
|
27
28
|
skippedDirectories: ["node_modules", "testdata", "vendor", ".*", "_*"],
|
|
29
|
+
skippedFiles: ["_*", ".*"],
|
|
28
30
|
},
|
|
29
31
|
ts: {
|
|
30
32
|
analyzer: "deadset-ts",
|
|
31
33
|
markers: ["tsconfig*.json", "jsconfig*.json"],
|
|
32
34
|
skippedDirectories: ["node_modules", ".git"],
|
|
35
|
+
skippedFiles: ["*.min.js", "*.min.cjs", "*.min.mjs"],
|
|
33
36
|
},
|
|
34
37
|
proto: {
|
|
35
38
|
analyzer: "deadset-proto",
|
|
36
39
|
markers: ["buf.yaml", "buf.work.yaml"],
|
|
37
40
|
skippedDirectories: ["node_modules", "vendor", ".*"],
|
|
41
|
+
skippedFiles: [],
|
|
38
42
|
},
|
|
39
43
|
};
|
|
40
44
|
export const EXIT_CLEAN = 0;
|
|
@@ -441,8 +445,8 @@ export const KIND_ROWS = [
|
|
|
441
445
|
languages: ["go", "ts"],
|
|
442
446
|
subject: "dependency",
|
|
443
447
|
holdsLive: false,
|
|
444
|
-
rule: "A directly declared dependency that no import in the target needs. On the Go side, a direct require whose module provides no package any target package or test variant imports. On the TypeScript side, a manifest dependency, development dependency or peer dependency the project's import closure does not need. A deletion finding whose fix would remove the last use of a dependency names that dependency. On the TypeScript side, a needed dependency whose every use is written inside declarations that are members of the run's dead components, or at the top level of a file reported under DS1602, that no command runs and that no needed dependency used otherwise names as a peer, is reported as well, dead only through that code: at the reachability class possible where one of those declarations belongs to a library's published API, and found under reachability alone where one of those declarations or files is, so at probable unless ts.roots_complete is true. A use the configuration makes, a use an unanswered specifier may make and an import none of whose bindings is used are uses by live code.",
|
|
445
|
-
precondition: "On the Go side the rule is the semantics of `go mod tidy -diff` exactly: a requirement marked indirect is never reported, because it exists to pin a transitive version and removing it changes the build list. On the TypeScript side the import closure is the files of the run's projects, and a call of `import.meta.resolve` or of `
|
|
448
|
+
rule: "A directly declared dependency that no import in the target needs. On the Go side, a direct require whose module provides no package any target package or test variant imports. On the TypeScript side, a manifest dependency, development dependency or peer dependency the project's import closure does not need. A deletion finding whose fix would remove the last use of a dependency names that dependency. On the TypeScript side, a needed dependency whose every use is written inside declarations that are members of the run's dead components, or at the top level of a file reported under DS1602, that no command runs and that no needed dependency used otherwise names as a peer, is reported as well, dead only through that code: at the reachability class possible where one of those declarations belongs to a library's published API, and found under reachability alone where one of those declarations or files is, so at probable unless ts.roots_complete is true. A use the configuration makes, a use an unanswered specifier or callee may make and an import none of whose bindings is used are uses by live code.",
|
|
449
|
+
precondition: "On the Go side the rule is the semantics of `go mod tidy -diff` exactly: a requirement marked indirect is never reported, because it exists to pin a transitive version and removing it changes the build list. On the TypeScript side the import closure is the files of the run's projects, and a `require()` call as `roots.23` reads one, or a call of `import.meta.resolve`, of `require.resolve`, whatever `require` names, or of `resolve` on another name that is such a `require`, in them, whose first argument is a string literal or a template literal with no substitution needs each dependency an import of that specifier needs. A `@types/<name>` package in a type root of a compiler configuration that lists no `types`, a `node_modules/@types` directory at or above the configuration's directory or a `typeRoots` entry naming one, is needed by a use, in a file of that configuration, of a global name or an ambient module that one of the package's declaration files declares, which resolves to no declaration of the program: a compiler before version 6 includes every package of the type roots where `types` is not listed, and version 6 and later include none, so the program the analysis builds holds none of those declarations. A package's declaration files are the file its `types` or `typings` names, else its `index.d.ts`, and each file a `/// <reference path>` of one of them reaches inside the package. A global is a top-level declaration of such a file that is no module, or a declaration of a `declare global` block of one that is, and an ambient module is a `declare module` with a string name of a file that is no module. A name that names a member, a property or a label is no use of a global. Four more dependencies are needed: one whose command a script entry, a workflow step or a git hook runs, one that a string of a configuration file names, and one that a string names under a manifest key or a package key of an applied convention row, each as grammar/analysis/conventions.md states, and one that a needed dependency names as a peer, as stated below. A command no script entry, workflow step or git hook runs needs nothing. A declared dependency that the installed manifest of a needed declared dependency names in its peerDependencies is needed, and so on until no further dependency joins. A peer dependency is a package the needed dependency expects beside it at a version its manifest states, whether or not it imports the package, and the project's declaration is what keeps that package present at a version the project chooses, so removing the declaration can break the needed dependency where nothing the analysis reads imports the peer. A peer that peerDependenciesMeta marks optional is needed in the same way, because the needed dependency's manifest still names it as a package it works with, and a package manager may leave an optional peer out where the project does not declare it, so the project's declaration is what keeps it present for the needed dependency. A declared dependency that only dependencies nothing needs name as a peer is needed by nothing. A dependency of a manifest whose directory holds source only in configurations the run lists in configurations_not_built is reported at the reachability class possible, because the source that may import it was not analyzed. An installed manifest is the package's manifest in the nearest node_modules directory at or above the directory of the manifest that declares the dependency, and a dependency with none is decided by the import closure alone. On the TypeScript side, the dependencies judged are those of every manifest grammar/analysis/program.md says the analysis reads, a nested package's among them, each read against its own directory: a dependency is needed by a use written in a file at or below the directory of the manifest that declares it where no manifest between them declares a dependency of the same name, so a use below a nested manifest that declares the same dependency needs that nested manifest's declaration only, by a use no one file holds, and as a peer of a needed dependency of the same manifest or of a manifest below it. A dependency a nested package's manifest declares whose installed manifest the analysis cannot find is not judged, because no run requires a nested package to be installed and its commands and peers cannot be read, while a workspace member's and the target's own are judged as above.",
|
|
446
450
|
details: { dependency_class: "required" },
|
|
447
451
|
defaultEnabled: true,
|
|
448
452
|
defaultSeverity: "deny",
|
|
@@ -708,6 +712,38 @@ export const SYMBOL_SUBJECTS = {
|
|
|
708
712
|
"configured-declaration": "record",
|
|
709
713
|
edge: "record",
|
|
710
714
|
};
|
|
715
|
+
export const REMEDIES = {
|
|
716
|
+
declaration: {
|
|
717
|
+
names: "a declaration",
|
|
718
|
+
suppressions: ["inline", "ignore", "baseline"],
|
|
719
|
+
remedy: "delete the symbol, or wire it up so the program uses it",
|
|
720
|
+
},
|
|
721
|
+
binding: {
|
|
722
|
+
names: "an import binding",
|
|
723
|
+
suppressions: ["inline", "ignore", "baseline"],
|
|
724
|
+
remedy: "delete the import, or use what it binds",
|
|
725
|
+
},
|
|
726
|
+
part: {
|
|
727
|
+
names: "a part of a declaration",
|
|
728
|
+
suppressions: ["inline", "ignore", "baseline"],
|
|
729
|
+
remedy: "remove the part, or use it",
|
|
730
|
+
},
|
|
731
|
+
file: {
|
|
732
|
+
names: "a file",
|
|
733
|
+
suppressions: [],
|
|
734
|
+
remedy: "delete the file, name it as a root, or build it in a configuration of the build matrix",
|
|
735
|
+
},
|
|
736
|
+
dependency: {
|
|
737
|
+
names: "a dependency row",
|
|
738
|
+
suppressions: ["ignore", "baseline"],
|
|
739
|
+
remedy: "remove the dependency",
|
|
740
|
+
},
|
|
741
|
+
record: {
|
|
742
|
+
names: "a record of deadset's own configuration",
|
|
743
|
+
suppressions: [],
|
|
744
|
+
remedy: "correct or remove the record the finding names",
|
|
745
|
+
},
|
|
746
|
+
};
|
|
711
747
|
export const EXEMPTION_CLASSES = [
|
|
712
748
|
{
|
|
713
749
|
class: "interface-satisfaction",
|
|
@@ -1220,6 +1256,86 @@ export const EVIDENCE = [
|
|
|
1220
1256
|
codes: ["DS1801", "DS1802", "DS1803", "DS1804", "DS1805"],
|
|
1221
1257
|
},
|
|
1222
1258
|
];
|
|
1259
|
+
/** The generators whose TypeScript output a generated file is matched against, in the document's order. */
|
|
1260
|
+
export const GENERATORS = [
|
|
1261
|
+
{
|
|
1262
|
+
id: "protoc-gen-es-2",
|
|
1263
|
+
plugin: "protoc-gen-es",
|
|
1264
|
+
header: "^// @generated by protoc-gen-es v2\\.",
|
|
1265
|
+
versions: { min: "v2.10.0", max: "v2.16.0" },
|
|
1266
|
+
cell: "exact",
|
|
1267
|
+
},
|
|
1268
|
+
{
|
|
1269
|
+
id: "protoc-gen-es-2-fallback",
|
|
1270
|
+
plugin: "protoc-gen-es",
|
|
1271
|
+
header: "^// @generated by protoc-gen-es v2\\.",
|
|
1272
|
+
cell: "fallback",
|
|
1273
|
+
},
|
|
1274
|
+
{
|
|
1275
|
+
id: "protoc-gen-es-1",
|
|
1276
|
+
plugin: "protoc-gen-es",
|
|
1277
|
+
header: "^// @generated by protoc-gen-es v1\\.",
|
|
1278
|
+
cell: "exact",
|
|
1279
|
+
},
|
|
1280
|
+
{
|
|
1281
|
+
id: "protoc-gen-connect-es-1",
|
|
1282
|
+
plugin: "protoc-gen-connect-es",
|
|
1283
|
+
header: "^// @generated by protoc-gen-connect-es v1\\.",
|
|
1284
|
+
cell: "exact",
|
|
1285
|
+
},
|
|
1286
|
+
{
|
|
1287
|
+
id: "ts-proto-2-output-schema",
|
|
1288
|
+
plugin: "ts-proto",
|
|
1289
|
+
header: "^// Code generated by protoc-gen-ts_proto\\. DO NOT EDIT\\.$",
|
|
1290
|
+
versions: { min: "v2.11.4", max: "v2.15.0" },
|
|
1291
|
+
cell: "exact",
|
|
1292
|
+
},
|
|
1293
|
+
{
|
|
1294
|
+
id: "ts-proto-2",
|
|
1295
|
+
plugin: "ts-proto",
|
|
1296
|
+
header: "^// Code generated by protoc-gen-ts_proto\\. DO NOT EDIT\\.$",
|
|
1297
|
+
versions: { min: "v2.11.4", max: "v2.15.0" },
|
|
1298
|
+
cell: "rpc-types-fallback",
|
|
1299
|
+
},
|
|
1300
|
+
{
|
|
1301
|
+
id: "ts-proto-2-types",
|
|
1302
|
+
plugin: "ts-proto",
|
|
1303
|
+
header: "^// Code generated by protoc-gen-ts_proto\\. DO NOT EDIT\\.$",
|
|
1304
|
+
versions: { min: "v2.11.4", max: "v2.15.0" },
|
|
1305
|
+
cell: "fallback",
|
|
1306
|
+
},
|
|
1307
|
+
{
|
|
1308
|
+
id: "ts-proto-2-fallback",
|
|
1309
|
+
plugin: "ts-proto",
|
|
1310
|
+
header: "^// Code generated by protoc-gen-ts_proto\\. DO NOT EDIT\\.$",
|
|
1311
|
+
cell: "fallback",
|
|
1312
|
+
},
|
|
1313
|
+
{
|
|
1314
|
+
id: "protoc-gen-js",
|
|
1315
|
+
plugin: "protoc-gen-js",
|
|
1316
|
+
header: "^// GENERATED CODE -- DO NOT EDIT!$",
|
|
1317
|
+
cell: "fallback",
|
|
1318
|
+
},
|
|
1319
|
+
{
|
|
1320
|
+
id: "protoc-gen-grpc-web",
|
|
1321
|
+
plugin: "protoc-gen-grpc-web",
|
|
1322
|
+
header: "^// Code generated by protoc-gen-grpc-web\\. DO NOT EDIT\\.$",
|
|
1323
|
+
cell: "fallback",
|
|
1324
|
+
},
|
|
1325
|
+
{
|
|
1326
|
+
id: "protobuf-ts",
|
|
1327
|
+
plugin: "protobuf-ts",
|
|
1328
|
+
header: "^// @generated by protobuf-ts ",
|
|
1329
|
+
cell: "fallback",
|
|
1330
|
+
},
|
|
1331
|
+
{ id: "ts-protoc-gen", plugin: "ts-protoc-gen", header: "^// package: ", cell: "fallback" },
|
|
1332
|
+
{
|
|
1333
|
+
id: "protoc-gen-es-unsupported",
|
|
1334
|
+
plugin: "protoc-gen-es",
|
|
1335
|
+
header: "^// @generated by protoc-gen-es v(?:0|[3-9]|[1-9][0-9]+)\\.",
|
|
1336
|
+
cell: "unsupported",
|
|
1337
|
+
},
|
|
1338
|
+
];
|
|
1223
1339
|
/** Each group of failure classes, and the text opening the line that names one of its failures. */
|
|
1224
1340
|
export const FAILURE_PREFIXES = { setup: "setup failure: ", run: "run failure: " };
|
|
1225
1341
|
/** Each failure class the Contract names, and its group. */
|
|
@@ -1230,6 +1346,7 @@ export const FAILURE_CLASSES = {
|
|
|
1230
1346
|
"workspace-member-without-source": "setup",
|
|
1231
1347
|
"convention-not-literal": "setup",
|
|
1232
1348
|
"no-program": "setup",
|
|
1349
|
+
"unreadable-configuration": "setup",
|
|
1233
1350
|
"unreadable-document": "setup",
|
|
1234
1351
|
"missing-import-path": "setup",
|
|
1235
1352
|
"binding-undecodable": "setup",
|
|
@@ -43,6 +43,11 @@ export const REPORT_SCHEMAS = {
|
|
|
43
43
|
},
|
|
44
44
|
else: { properties: { configurations: { minItems: 1 }, target: { required: ["kind"] } } },
|
|
45
45
|
},
|
|
46
|
+
{
|
|
47
|
+
if: { required: ["merged_from"], properties: { merged_from: { maxItems: 0 } } },
|
|
48
|
+
then: { properties: { analyzer: { properties: { languages: { maxItems: 0 } } } } },
|
|
49
|
+
else: { properties: { analyzer: { properties: { languages: { minItems: 1 } } } } },
|
|
50
|
+
},
|
|
46
51
|
],
|
|
47
52
|
properties: {
|
|
48
53
|
schema_version: { type: "string", pattern: "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
|
|
@@ -59,7 +64,6 @@ export const REPORT_SCHEMAS = {
|
|
|
59
64
|
},
|
|
60
65
|
languages: {
|
|
61
66
|
type: "array",
|
|
62
|
-
minItems: 1,
|
|
63
67
|
uniqueItems: true,
|
|
64
68
|
items: { type: "string", enum: ["go", "ts", "proto"] },
|
|
65
69
|
},
|
|
@@ -95,7 +99,7 @@ export const REPORT_SCHEMAS = {
|
|
|
95
99
|
pattern: "^[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z.-]+)?(\\+[0-9A-Za-z.-]+)?$",
|
|
96
100
|
},
|
|
97
101
|
digest: { type: "string", pattern: "^sha256:[0-9a-f]{64}$" },
|
|
98
|
-
languages: { $ref: "#/properties/analyzer/properties/languages" },
|
|
102
|
+
languages: { $ref: "#/properties/analyzer/properties/languages", minItems: 1 },
|
|
99
103
|
totals: { $ref: "#/properties/totals" },
|
|
100
104
|
},
|
|
101
105
|
},
|
package/dist/src/dependencies.js
CHANGED
|
@@ -7,15 +7,19 @@
|
|
|
7
7
|
* itself is that dependency's need, not the target's.
|
|
8
8
|
*/
|
|
9
9
|
import { isArrayLiteralExpression, isCallExpression, isExportDeclaration, isExpressionStatement, isExternalModuleReference, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isMetaProperty, isNamespaceExport, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isStringLiteral, isNoSubstitutionTemplateLiteral, SyntaxKind, } from "@typescript/native/ast";
|
|
10
|
+
import { amdLoadOf, amdPlatform } from "./amd.js";
|
|
10
11
|
import { automaticTypes } from "./automatic-types.js";
|
|
11
|
-
import {
|
|
12
|
+
import { declaredIn as declaredBeside, dependenciesNamed, moduleStrings, outsideChain, } from "./entries/configuration-files.js";
|
|
13
|
+
import { declarationBindings } from "./import-bindings.js";
|
|
12
14
|
import { nodeKey } from "./inventory.js";
|
|
13
15
|
import { packageScope } from "./load/package-scope.js";
|
|
14
|
-
import { ancestors,
|
|
16
|
+
import { ancestors, cannotStartPackageName, dirnamePath, joinPath, relativePath, resolvePath, } from "./paths.js";
|
|
15
17
|
import { UNANSWERED } from "./query.js";
|
|
16
18
|
import { sourceFilesOf } from "./source-files.js";
|
|
17
|
-
import { manifestCommands, nodemonTexts } from "./manifest.js";
|
|
18
|
-
import {
|
|
19
|
+
import { manifestCommands, nodemonTexts } from "./roots/manifest.js";
|
|
20
|
+
import { writtenName } from "./platform-calls.js";
|
|
21
|
+
import { callsPlatform } from "./platform-symbols.js";
|
|
22
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
19
23
|
import { pathsNamed, preloadedPackages, readCommands, } from "./commands/read.js";
|
|
20
24
|
import { heldNames } from "./text/named-files.js";
|
|
21
25
|
import { bytewise } from "./text/compare.js";
|
|
@@ -151,7 +155,7 @@ function configurationPackages(host, configFile, options, programPackages, parse
|
|
|
151
155
|
}
|
|
152
156
|
seen.add(file);
|
|
153
157
|
for (const entry of extendsOf(host, file, parse)) {
|
|
154
|
-
if (
|
|
158
|
+
if (cannotStartPackageName(entry)) {
|
|
155
159
|
const local = resolvePath(dirnamePath(file), entry);
|
|
156
160
|
pending.push(local.endsWith(".json") ? local : `${local}.json`);
|
|
157
161
|
}
|
|
@@ -176,36 +180,19 @@ function importOf(specifier) {
|
|
|
176
180
|
}
|
|
177
181
|
/** The local names one import declaration binds. */
|
|
178
182
|
function bindingsOf(node) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (isImportEqualsDeclaration(node)) {
|
|
183
|
-
return [node.name];
|
|
184
|
-
}
|
|
185
|
-
if (!isImportDeclaration(node) || node.importClause === undefined) {
|
|
186
|
-
return [];
|
|
187
|
-
}
|
|
188
|
-
const clause = node.importClause;
|
|
189
|
-
const names = clause.name === undefined ? [] : [clause.name];
|
|
190
|
-
const bindings = clause.namedBindings;
|
|
191
|
-
if (bindings !== undefined) {
|
|
192
|
-
if (bindings.kind === SyntaxKind.NamespaceImport) {
|
|
193
|
-
names.push(bindings.name);
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
names.push(...bindings.elements.map((element) => element.name));
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return names;
|
|
183
|
+
return node !== undefined && (isImportDeclaration(node) || isImportEqualsDeclaration(node))
|
|
184
|
+
? declarationBindings(node).map((binding) => binding.name)
|
|
185
|
+
: [];
|
|
200
186
|
}
|
|
201
187
|
/**
|
|
202
188
|
* Every package one project needs, and which declaration each use is written in.
|
|
203
189
|
* One local walk and one batched resolution per file: a use of an import binding is
|
|
204
190
|
* an identifier resolving to the binding's own symbol, so a local declaration that
|
|
205
|
-
* shadows the name is not one. A string of a configuration file
|
|
206
|
-
* the manifest beside the file
|
|
191
|
+
* shadows the name is not one. A string of a configuration file, as the entry sources
|
|
192
|
+
* read them in `configuration`, uses each dependency the manifest beside the file
|
|
193
|
+
* declares that it spells.
|
|
207
194
|
*/
|
|
208
|
-
export function projectNeeds(project, held, host, targetRoot, parse) {
|
|
195
|
+
export function projectNeeds(project, held, host, targetRoot, parse, configuration, workflows) {
|
|
209
196
|
const programPackages = new Set();
|
|
210
197
|
for (const name of project.program.getSourceFileNames()) {
|
|
211
198
|
const named = packageOfPath(name);
|
|
@@ -256,7 +243,6 @@ export function projectNeeds(project, held, host, targetRoot, parse) {
|
|
|
256
243
|
return names;
|
|
257
244
|
};
|
|
258
245
|
const files = sourceFilesOf(project, targetRoot);
|
|
259
|
-
const configuration = configurationFiles(host, targetRoot, files, parse);
|
|
260
246
|
for (const { file, manifestDir } of configuration.modules) {
|
|
261
247
|
const names = declaredAt(joinPath(manifestDir, MANIFEST));
|
|
262
248
|
for (const { node, text } of moduleStrings(file)) {
|
|
@@ -271,7 +257,7 @@ export function projectNeeds(project, held, host, targetRoot, parse) {
|
|
|
271
257
|
}
|
|
272
258
|
}
|
|
273
259
|
}
|
|
274
|
-
const ranFiles = outsideChain(host, targetRoot, files, parse, scriptRunFiles(host, targetRoot, files));
|
|
260
|
+
const ranFiles = outsideChain(host, targetRoot, files, parse, scriptRunFiles(host, targetRoot, files, workflows));
|
|
275
261
|
for (const { file, manifestDirs } of [...configuration.outside, ...ranFiles]) {
|
|
276
262
|
for (const manifestDir of manifestDirs) {
|
|
277
263
|
const names = declaredAt(joinPath(manifestDir, MANIFEST));
|
|
@@ -288,7 +274,7 @@ export function projectNeeds(project, held, host, targetRoot, parse) {
|
|
|
288
274
|
* workflow step or git hook names, with the target root's: a path `pathsNamed` reads, below the
|
|
289
275
|
* target root and in no `node_modules`.
|
|
290
276
|
*/
|
|
291
|
-
function scriptRunFiles(host, targetRoot, files) {
|
|
277
|
+
function scriptRunFiles(host, targetRoot, files, workflows) {
|
|
292
278
|
const root = resolvePath(host.workingDirectory(), targetRoot);
|
|
293
279
|
const dirs = new Set([root]);
|
|
294
280
|
for (const name of files.byName.keys()) {
|
|
@@ -300,12 +286,7 @@ function scriptRunFiles(host, targetRoot, files) {
|
|
|
300
286
|
}
|
|
301
287
|
}
|
|
302
288
|
const named = new Map([
|
|
303
|
-
[
|
|
304
|
-
root,
|
|
305
|
-
workflowReadings(host, root)
|
|
306
|
-
.flatMap(pathsNamed)
|
|
307
|
-
.map((one) => one.path),
|
|
308
|
-
],
|
|
289
|
+
[root, workflows.readings.flatMap(pathsNamed).map((one) => one.path)],
|
|
309
290
|
]);
|
|
310
291
|
for (const dir of dirs) {
|
|
311
292
|
const read = readDocument(host, joinPath(dir, MANIFEST));
|
|
@@ -341,19 +322,9 @@ function manifestUses(host, dir, manifest) {
|
|
|
341
322
|
return { ...uses, held: [uses.held, ...texts].join("\n") };
|
|
342
323
|
}
|
|
343
324
|
/** What the target root's workflow steps, git hooks and recipes use, held with their files' whole text. */
|
|
344
|
-
function workflowUses(
|
|
345
|
-
const uses = usesOf(
|
|
346
|
-
return { ...uses, held: [uses.held, ...
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* What the target root's workflow steps, git hooks, hook managers and recipes run, each held
|
|
350
|
-
* with the directory the file writes for it.
|
|
351
|
-
*/
|
|
352
|
-
function workflowReadings(host, targetRoot) {
|
|
353
|
-
return workflowCommands(host, targetRoot).map(({ text, dir, writtenDirectory }) => {
|
|
354
|
-
const reading = readCommands(text, dir);
|
|
355
|
-
return { ...reading, held: [reading.held, writtenDirectory ?? ""].join("\n") };
|
|
356
|
-
});
|
|
325
|
+
function workflowUses(workflows) {
|
|
326
|
+
const uses = usesOf(workflows.readings);
|
|
327
|
+
return { ...uses, held: [uses.held, ...workflows.texts].join("\n") };
|
|
357
328
|
}
|
|
358
329
|
function usesOf(readings) {
|
|
359
330
|
return {
|
|
@@ -439,7 +410,16 @@ function fileNeeds(project, held, file, { programPackages, automatic }, use) {
|
|
|
439
410
|
if (names.size > 0 || automatic.globals.size > 0) {
|
|
440
411
|
visit(file);
|
|
441
412
|
}
|
|
442
|
-
const
|
|
413
|
+
const loads = runtimeLoads(file);
|
|
414
|
+
const callees = loads.flatMap((load) => load.callees);
|
|
415
|
+
const amdCallees = new Set(loads.flatMap((load) => (load.amd ? load.callees : [])));
|
|
416
|
+
const asked = [
|
|
417
|
+
...specifiers,
|
|
418
|
+
...bindings.map(({ node }) => node),
|
|
419
|
+
...candidates,
|
|
420
|
+
...globals,
|
|
421
|
+
...callees,
|
|
422
|
+
];
|
|
443
423
|
const handles = asked.map((node) => project.handle(node));
|
|
444
424
|
const resolved = project.symbolsAt(handles);
|
|
445
425
|
const packagesOf = new Map();
|
|
@@ -510,33 +490,80 @@ function fileNeeds(project, held, file, { programPackages, automatic }, use) {
|
|
|
510
490
|
for (const reference of file.typeReferenceDirectives) {
|
|
511
491
|
use(ownersOf(file, held, file), typePackages(reference.fileName, programPackages));
|
|
512
492
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
493
|
+
// A callee the checker leaves unanswered may be a require, so its call holds the
|
|
494
|
+
// dependency it names by live code, as program.33 holds one.
|
|
495
|
+
const calleesAt = unresolvedAt + globals.length;
|
|
496
|
+
const decided = new Map();
|
|
497
|
+
const requires = new Set();
|
|
498
|
+
const unansweredCallees = new Set();
|
|
499
|
+
callees.forEach((callee, index) => {
|
|
500
|
+
const symbol = resolved[calleesAt + index];
|
|
501
|
+
if (symbol === UNANSWERED) {
|
|
502
|
+
unansweredCallees.add(callee);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
// The decision reads the callee's symbol, its written name and its platform name, and nothing else.
|
|
506
|
+
const platform = amdCallees.has(callee) ? amdPlatform(callee) : "require";
|
|
507
|
+
const key = symbol === undefined ? undefined : `${symbol.id}\u0000${platform}\u0000${callee.text}`;
|
|
508
|
+
const answer = (key === undefined ? undefined : decided.get(key)) ??
|
|
509
|
+
callsPlatform(project, platform, callee, symbol);
|
|
510
|
+
if (key !== undefined) {
|
|
511
|
+
decided.set(key, answer);
|
|
512
|
+
}
|
|
513
|
+
if (answer) {
|
|
514
|
+
requires.add(callee);
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
for (const { specifier, named, callees: through } of loads) {
|
|
518
|
+
if (through.length === 0 || through.some((one) => requires.has(one))) {
|
|
516
519
|
use(ownersOf(file, held, specifier), [named]);
|
|
517
520
|
}
|
|
521
|
+
else if (through.some((one) => unansweredCallees.has(one))) {
|
|
522
|
+
use([PROJECT_OWNER], [named]);
|
|
523
|
+
}
|
|
518
524
|
}
|
|
519
525
|
return resolved.slice(0, specifiers.length).includes(UNANSWERED);
|
|
520
526
|
}
|
|
521
527
|
/**
|
|
522
|
-
* The
|
|
523
|
-
*
|
|
528
|
+
* The calls one file may load or resolve a package with at run time, each of whose first
|
|
529
|
+
* argument is literal text naming a package: a `require()` call, which the compiler lists among
|
|
530
|
+
* a file's imports only in a JavaScript file and only through the bare name; a `.resolve` of
|
|
531
|
+
* another name, which needs it where that name is a `require`; and `import.meta.resolve` or
|
|
532
|
+
* a `.resolve` of the name `require`, whatever it names, a use where it stands; and each id of
|
|
533
|
+
* an AMD dependency list (references-ts.37), which needs it where the call is AMD's.
|
|
524
534
|
*/
|
|
525
|
-
function
|
|
535
|
+
function runtimeLoads(file) {
|
|
526
536
|
const found = [];
|
|
527
|
-
if (!file.text.includes(".resolve(")) {
|
|
528
|
-
return found;
|
|
529
|
-
}
|
|
530
537
|
const visit = (node) => {
|
|
531
|
-
|
|
532
|
-
|
|
538
|
+
const amd = amdLoadOf(node);
|
|
539
|
+
if (amd !== undefined) {
|
|
540
|
+
for (const { id } of amd.ids) {
|
|
541
|
+
const named = packageOfSpecifier(id.text);
|
|
542
|
+
if (named !== undefined) {
|
|
543
|
+
found.push({ specifier: id, named, callees: [amd.callee], amd: true });
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
else if (isCallExpression(node)) {
|
|
533
548
|
const [argument] = node.arguments;
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
549
|
+
if (argument !== undefined && isLiteralText(argument)) {
|
|
550
|
+
const named = packageOfSpecifier(argument.text);
|
|
551
|
+
const callee = parenthesesRemoved(node.expression);
|
|
552
|
+
const receiver = isPropertyAccessExpression(callee) && callee.name.text === "resolve"
|
|
553
|
+
? parenthesesRemoved(callee.expression)
|
|
554
|
+
: undefined;
|
|
555
|
+
const stands = receiver !== undefined &&
|
|
556
|
+
((isMetaProperty(receiver) && receiver.name.text === "meta") ||
|
|
557
|
+
(isIdentifier(receiver) && receiver.text === "require"));
|
|
558
|
+
const callees = stands
|
|
559
|
+
? []
|
|
560
|
+
: [
|
|
561
|
+
writtenName(callee),
|
|
562
|
+
receiver === undefined ? undefined : writtenName(receiver),
|
|
563
|
+
].filter((one) => one !== undefined);
|
|
564
|
+
if (named !== undefined && (stands || callees.length > 0)) {
|
|
565
|
+
found.push({ specifier: argument, named, callees, amd: false });
|
|
566
|
+
}
|
|
540
567
|
}
|
|
541
568
|
}
|
|
542
569
|
node.forEachChild(visit);
|
|
@@ -727,7 +754,7 @@ function addNeededPeers(declared, peers, needed, ran) {
|
|
|
727
754
|
* manifest declares nothing, nor does a nested package's uninstalled dependency, because
|
|
728
755
|
* no run requires a nested package to be installed.
|
|
729
756
|
*/
|
|
730
|
-
export function dependenciesOf(host, targetRoot, perProject, candidates, members = [], unbuiltMembers = [], nested = []) {
|
|
757
|
+
export function dependenciesOf(host, targetRoot, workflows, perProject, candidates, members = [], unbuiltMembers = [], nested = []) {
|
|
731
758
|
const root = resolvePath(host.workingDirectory(), targetRoot);
|
|
732
759
|
const scopeOf = packageScope(host, targetRoot);
|
|
733
760
|
const manifests = new Map([[root, MANIFEST]]);
|
|
@@ -744,7 +771,7 @@ export function dependenciesOf(host, targetRoot, perProject, candidates, members
|
|
|
744
771
|
unbuilt.add(path);
|
|
745
772
|
}
|
|
746
773
|
}
|
|
747
|
-
const workflow = workflowUses(
|
|
774
|
+
const workflow = workflowUses(workflows);
|
|
748
775
|
const declared = [];
|
|
749
776
|
const ran = new Set();
|
|
750
777
|
const peers = new Map();
|