@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
package/dist/src/alias-chain.js
CHANGED
|
@@ -19,7 +19,6 @@ export function aliasChains(project, held) {
|
|
|
19
19
|
const ownFiles = project.ownPaths();
|
|
20
20
|
const steps = new Map();
|
|
21
21
|
const chains = new Map();
|
|
22
|
-
let asked = 0;
|
|
23
22
|
const declarationsOf = (symbol) => {
|
|
24
23
|
const ids = [];
|
|
25
24
|
for (const handle of symbol.declarations) {
|
|
@@ -52,7 +51,6 @@ export function aliasChains(project, held) {
|
|
|
52
51
|
return steps.get(symbol.id);
|
|
53
52
|
}
|
|
54
53
|
const next = project.aliasStepOf(symbol);
|
|
55
|
-
asked += 1;
|
|
56
54
|
steps.set(symbol.id, next);
|
|
57
55
|
return next;
|
|
58
56
|
};
|
|
@@ -145,8 +143,5 @@ export function aliasChains(project, held) {
|
|
|
145
143
|
declarationsOf,
|
|
146
144
|
chainOf,
|
|
147
145
|
nextDeclared,
|
|
148
|
-
get steps() {
|
|
149
|
-
return asked;
|
|
150
|
-
},
|
|
151
146
|
};
|
|
152
147
|
}
|
package/dist/src/amd.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AMD's module forms (references-ts.37), read from the syntax because the binder declares
|
|
3
|
+
* none of them: `define([<ids>], factory)`, `define("<name>", [<ids>], factory)` and
|
|
4
|
+
* `require([<ids>], callback)` (https://github.com/amdjs/amdjs-api/blob/master/AMD.md).
|
|
5
|
+
*/
|
|
6
|
+
import { isArrayLiteralExpression, isArrowFunction, isFunctionExpression, isCallExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isStringLiteral, } from "@typescript/native/ast";
|
|
7
|
+
import { hasURLScheme, isAbsolutePath, resolvePath, startsRelativePath } from "./paths.js";
|
|
8
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
9
|
+
/** The ids AMD binds to the factory's CommonJS parameters, which load no module. */
|
|
10
|
+
const FREE_VARIABLES = new Set(["require", "exports", "module"]);
|
|
11
|
+
/** The platform function `callee` is written as. */
|
|
12
|
+
export function amdPlatform(callee) {
|
|
13
|
+
return callee.text === "define" ? "define" : "require";
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The dependency list one call writes, where it is a call of a bare `define` or `require` in
|
|
17
|
+
* one of AMD's forms. A `define` with no list, of a factory or a value alone, loads nothing;
|
|
18
|
+
* a `require` whose first argument is no array literal is CommonJS's.
|
|
19
|
+
*/
|
|
20
|
+
export function amdLoadOf(node) {
|
|
21
|
+
if (!isCallExpression(node)) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
const callee = parenthesesRemoved(node.expression);
|
|
25
|
+
if (!isIdentifier(callee) || (callee.text !== "define" && callee.text !== "require")) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const written = node.arguments.map((one) => parenthesesRemoved(one));
|
|
29
|
+
const [first] = written;
|
|
30
|
+
if (first === undefined) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const define = callee.text === "define";
|
|
34
|
+
const named = define && isLiteralText(first);
|
|
35
|
+
const list = written[named ? 1 : 0];
|
|
36
|
+
if (list !== undefined && isArrayLiteralExpression(list)) {
|
|
37
|
+
const elements = list.elements.map((one) => parenthesesRemoved(one));
|
|
38
|
+
const factory = written[named ? 2 : 1];
|
|
39
|
+
const ids = elements.flatMap((one, at) => isLiteralText(one) && !FREE_VARIABLES.has(one.text)
|
|
40
|
+
? [{ id: one, received: receives(factory, at) }]
|
|
41
|
+
: []);
|
|
42
|
+
return { callee, ids, computed: elements.some((one) => !isLiteralText(one)) };
|
|
43
|
+
}
|
|
44
|
+
if (!define) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
// A factory after the list's place makes what stands there a list, here a computed one.
|
|
48
|
+
return { callee, ids: [], computed: written.length > (named ? 2 : 1) };
|
|
49
|
+
}
|
|
50
|
+
function isLiteralText(node) {
|
|
51
|
+
return isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node);
|
|
52
|
+
}
|
|
53
|
+
/** Whether a factory may receive the dependency at place `at` of its list. */
|
|
54
|
+
function receives(factory, at) {
|
|
55
|
+
if (factory === undefined) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
if (!isFunctionExpression(factory) && !isArrowFunction(factory)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
const { parameters } = factory;
|
|
62
|
+
return at < parameters.length || parameters.some((one) => one.dotDotDotToken !== undefined);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The path a dependency id names against the calling file's directory: a relative module id,
|
|
66
|
+
* `./` or `../` with no `.js` ending, with `.js` appended. RequireJS reads any other id
|
|
67
|
+
* through its configuration or as a URL against the page, which the analysis does not know.
|
|
68
|
+
*/
|
|
69
|
+
export function amdPath(dir, id) {
|
|
70
|
+
return startsRelativePath(id) && !id.endsWith(".js") ? resolvePath(dir, `${id}.js`) : undefined;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Whether one call may load a file the analysis cannot name: a computed list, or an id that
|
|
74
|
+
* RequireJS reads as a URL, one ending in `.js`, starting with `/` or carrying a scheme. Any
|
|
75
|
+
* other id {@link amdPath} reads no path from is a package's.
|
|
76
|
+
*/
|
|
77
|
+
export function amdUnresolved(load) {
|
|
78
|
+
return (load.computed ||
|
|
79
|
+
load.ids.some(({ id }) => amdPath("/", id.text) === undefined &&
|
|
80
|
+
(id.text.endsWith(".js") || isAbsolutePath(id.text) || hasURLScheme(id.text))));
|
|
81
|
+
}
|
package/dist/src/analysis.js
CHANGED
|
@@ -9,43 +9,45 @@ import { isStringLiteralLikeNode } from "@typescript/native/ast";
|
|
|
9
9
|
import { lineOf, readComponent } from "./component-files.js";
|
|
10
10
|
import { kindOf } from "./config.js";
|
|
11
11
|
import { consumerReferences } from "./consumers.js";
|
|
12
|
-
import { configuredDeclarations, configuredRef, declarationsNamed, } from "./configured-declarations.js";
|
|
12
|
+
import { configuredDeclarations, configuredRef, declarationsNamed, } from "./roots/configured-declarations.js";
|
|
13
13
|
import { decorator } from "./decorator.js";
|
|
14
14
|
import { configurationNeeds, dependenciesOf, projectNeeds } from "./dependencies.js";
|
|
15
15
|
import { deprecatedDeclarations } from "./deprecation.js";
|
|
16
16
|
import { moduleIdentity } from "./load/discover.js";
|
|
17
17
|
import { loadRun } from "./load/load.js";
|
|
18
|
-
import {
|
|
18
|
+
import { readSources } from "./entries/sources.js";
|
|
19
|
+
import { readWorkflows } from "./entries/workflow-steps.js";
|
|
19
20
|
import { readEdgeSides } from "./edges.js";
|
|
20
21
|
import { enumGroup } from "./enum-group.js";
|
|
22
|
+
import { bindingsOf, distinctBindings } from "./bindings.js";
|
|
21
23
|
import { generatedFile, generatedFilesOf } from "./generated-file.js";
|
|
22
|
-
import { inOperandNames } from "./in-operands.js";
|
|
24
|
+
import { inOperandNames } from "./findings/in-operands.js";
|
|
23
25
|
import { sourceFilesOf } from "./source-files.js";
|
|
24
26
|
import { evidenceRecords, heldRecords, disabledClasses, exemptionsOf, holdingWhile, isUnansweredRecord, retainedIn, writtenRecords, } from "./exempt.js";
|
|
25
27
|
import { heldByInclusion, sourcePaths, sourceTree } from "./file-facts.js";
|
|
26
28
|
import { findingsPass, recordedFindings, rowKey } from "./findings-pass.js";
|
|
27
29
|
import { unmatchedRootFindings } from "./findings/self-check.js";
|
|
28
30
|
import { frameworkLifecycle } from "./framework-lifecycle.js";
|
|
29
|
-
import { implementations, mergeImplementations } from "./implementations.js";
|
|
31
|
+
import { implementations, mergeImplementations } from "./findings/implementations.js";
|
|
30
32
|
import { injectionContainer } from "./injection-container.js";
|
|
31
33
|
import { interfaceSatisfaction, settledSatisfaction } from "./interface-satisfaction.js";
|
|
32
34
|
import { intraFunctionFacts, projectParts } from "./intra-function-parts.js";
|
|
33
35
|
import {} from "./inventory.js";
|
|
34
36
|
import { inventory } from "./inventory/enumerate.js";
|
|
35
|
-
import { readManifest } from "./manifest.js";
|
|
37
|
+
import { readManifest } from "./roots/manifest.js";
|
|
36
38
|
import { liveFilesAt, matrixOf, referenceKey, sweepMatrix, } from "./matrix.js";
|
|
37
39
|
import { ancestors, dirnamePath, extensionOf, joinPath, relativePath, resolvePath, } from "./paths.js";
|
|
38
40
|
import { byPosition, isComponentFile } from "./position.js";
|
|
39
|
-
import {
|
|
41
|
+
import { skippedUnits } from "./type-errors.js";
|
|
40
42
|
import { reflectiveLookup } from "./reflective-lookup.js";
|
|
41
|
-
import { references
|
|
42
|
-
import {
|
|
43
|
+
import { references } from "./references.js";
|
|
44
|
+
import { rootSet, unmatchedEverywhere, } from "./roots/root-set.js";
|
|
43
45
|
import { decodedMembers, serializationContract } from "./serialization-contract.js";
|
|
44
|
-
import { outsideTestReferences, testFilesAt } from "./outside
|
|
45
|
-
import {
|
|
46
|
-
import { unseenLoadsOf } from "./unseen-loads.js";
|
|
46
|
+
import { outsideTestReferences, testFilesAt } from "./tests/outside.js";
|
|
47
|
+
import { formedForNode } from "./load/synthesize.js";
|
|
47
48
|
import { GLOBALS_RUNNER, namesTestGlobals } from "./load/test-globals.js";
|
|
48
|
-
import {
|
|
49
|
+
import { targetTestFile, testFilePaths, testFileRulesOf, withheldBy, } from "./tests/file-class.js";
|
|
50
|
+
import { testSupportFiles } from "./tests/support.js";
|
|
49
51
|
import { accessorsOf, storesOf } from "./stores.js";
|
|
50
52
|
import { isPartKind } from "./suppress.js";
|
|
51
53
|
import { bindRows, readBaseline, readIgnoreFile } from "./suppress-file.js";
|
|
@@ -53,6 +55,7 @@ import { inlineDirectives, inlineSuppressions } from "./suppress-inline.js";
|
|
|
53
55
|
import { readTemplates, templateField } from "./template-field.js";
|
|
54
56
|
import { bytewise } from "./text/compare.js";
|
|
55
57
|
import { holdsManifest, manifestAt } from "./fs/manifest.js";
|
|
58
|
+
import { runDirectories } from "./entries/run-directories.js";
|
|
56
59
|
import { globExpression } from "./text/glob.js";
|
|
57
60
|
/** The setting whose source decides where a finding about a configured root sits. */
|
|
58
61
|
const ROOTS_SETTING = "roots.patterns";
|
|
@@ -82,14 +85,13 @@ function readProjects(engine, host, scope, config, stage) {
|
|
|
82
85
|
const parse = (fileName, text) => engine.parseSourceFile(fileName, text);
|
|
83
86
|
return loadRun(engine, host, scope, config, ({ plan, classified, runFiles }) => {
|
|
84
87
|
const { packages, conventions } = plan;
|
|
88
|
+
const workflows = readWorkflows(host, targetRoot);
|
|
85
89
|
const options = {
|
|
86
90
|
host,
|
|
87
91
|
manifest: packages.manifest,
|
|
88
92
|
otherPackages: packages.entries,
|
|
89
93
|
patterns: config.roots.patterns,
|
|
90
94
|
entryFiles: config.ts.entry_files,
|
|
91
|
-
conventions,
|
|
92
|
-
testFiles: config.ts.test_files,
|
|
93
95
|
parse,
|
|
94
96
|
publishedAPI: config.target.kind !== undefined && kindOf(config.target.kind) === "library",
|
|
95
97
|
publishedMembers: packages.published,
|
|
@@ -99,18 +101,18 @@ function readProjects(engine, host, scope, config, stage) {
|
|
|
99
101
|
const answers = classified.analyzed.map(({ plan: planned, project, skips, referenceOnly }) => {
|
|
100
102
|
const read = () => {
|
|
101
103
|
const held = inventory(project, host, targetRoot);
|
|
102
|
-
const found = roots(project, held, targetRoot, options);
|
|
103
|
-
const kept = skippedRoots(project, held, skips);
|
|
104
|
-
const rooted = kept.length === 0
|
|
105
|
-
? found
|
|
106
|
-
: {
|
|
107
|
-
...found,
|
|
108
|
-
liveUnderReachability: [
|
|
109
|
-
...found.liveUnderReachability,
|
|
110
|
-
...kept.map((id) => ({ id, kind: "type-error", source: "" })),
|
|
111
|
-
],
|
|
112
|
-
};
|
|
113
104
|
const own = sourceFilesOf(project, targetRoot);
|
|
105
|
+
const sources = readSources({
|
|
106
|
+
host,
|
|
107
|
+
targetRoot,
|
|
108
|
+
files: own,
|
|
109
|
+
parse,
|
|
110
|
+
testFiles: config.ts.test_files,
|
|
111
|
+
conventions,
|
|
112
|
+
workflows,
|
|
113
|
+
});
|
|
114
|
+
const rooted = rootSet(project, held, targetRoot, { ...options, sources, skips });
|
|
115
|
+
const generated = generatedFilesOf(own, sources.generated);
|
|
114
116
|
return {
|
|
115
117
|
configuration: planned.id,
|
|
116
118
|
configFile: project.configFile,
|
|
@@ -122,8 +124,12 @@ function readProjects(engine, host, scope, config, stage) {
|
|
|
122
124
|
.ownSourceFiles()
|
|
123
125
|
.filter((file) => referenceOnly(file.fileName))
|
|
124
126
|
.flatMap((file) => relativePath(absoluteRoot, file.fileName) ?? []),
|
|
125
|
-
generated
|
|
126
|
-
|
|
127
|
+
generated,
|
|
128
|
+
bindings: bindingsOf(own.byPath, generated, new Map(held.symbols
|
|
129
|
+
.filter((one) => one.kind === "file")
|
|
130
|
+
.map((one) => [one.position.path, one.ref]))),
|
|
131
|
+
sources,
|
|
132
|
+
formedForNode: formedForNode(planned),
|
|
127
133
|
};
|
|
128
134
|
};
|
|
129
135
|
for (const file of project.ownSourceFiles()) {
|
|
@@ -132,14 +138,25 @@ function readProjects(engine, host, scope, config, stage) {
|
|
|
132
138
|
return stage(project, { configuration: planned.id, read });
|
|
133
139
|
});
|
|
134
140
|
const consumed = new Map();
|
|
141
|
+
const consumerHeld = new Set();
|
|
135
142
|
for (const { project, consumer } of classified.consumed) {
|
|
136
143
|
const side = { id: consumer.id, root: consumer.path };
|
|
137
|
-
|
|
144
|
+
const read = consumerReferences(project, host, targetRoot, side, config, parse);
|
|
145
|
+
for (const reference of read.references) {
|
|
138
146
|
consumed.set(referenceKey(reference), reference);
|
|
139
147
|
}
|
|
148
|
+
for (const id of read.held) {
|
|
149
|
+
consumerHeld.add(id);
|
|
150
|
+
}
|
|
140
151
|
}
|
|
141
152
|
const outsideTests = testFilesAt(host, targetRoot, sourcePaths(host, targetRoot).filter((path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path))), parse);
|
|
142
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
answers,
|
|
155
|
+
references: [...consumed.values()],
|
|
156
|
+
consumerHeld: [...consumerHeld],
|
|
157
|
+
outsideTests,
|
|
158
|
+
workflows,
|
|
159
|
+
};
|
|
143
160
|
});
|
|
144
161
|
}
|
|
145
162
|
/**
|
|
@@ -204,6 +221,13 @@ export function runRoots(engine, host, scope, config, provenance) {
|
|
|
204
221
|
unanswered: read.unanswered,
|
|
205
222
|
};
|
|
206
223
|
}
|
|
224
|
+
/** The production mode a configuration sets: a consumer's test reference is classed as `analysis.consumer_tests` says. */
|
|
225
|
+
export function productionMode(config) {
|
|
226
|
+
return {
|
|
227
|
+
production: true,
|
|
228
|
+
consumerTestsProduction: config.analysis.consumer_tests === "production",
|
|
229
|
+
};
|
|
230
|
+
}
|
|
207
231
|
/** The exemption classes this analyzer detects, each by its detector; any other retains nothing. */
|
|
208
232
|
export const DETECTORS = new Map([
|
|
209
233
|
["interface-satisfaction", interfaceSatisfaction],
|
|
@@ -267,12 +291,16 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
267
291
|
? { delimiters: config.analysis.template_delimiters, files: [] }
|
|
268
292
|
: readTemplates(host, targetRoot, config.analysis);
|
|
269
293
|
const consumers = scope.consumers.map((consumer) => consumer.path);
|
|
294
|
+
const directories = runDirectories(host, targetRoot, (fileName, text) => engine.parseSourceFile(fileName, text));
|
|
270
295
|
const read = readProjects(engine, host, scope, config, (project, opened) => {
|
|
271
296
|
const projectRead = opened.read();
|
|
297
|
+
const testFile = targetTestFile(projectRead.sources.testFiles);
|
|
272
298
|
const resolved = references(project, projectRead.held, targetRoot, {
|
|
273
|
-
|
|
274
|
-
|
|
299
|
+
testFile,
|
|
300
|
+
directories,
|
|
301
|
+
formedForNode: projectRead.formedForNode,
|
|
275
302
|
});
|
|
303
|
+
const testFiles = testFilePaths(project, targetRoot, testFile);
|
|
276
304
|
const evidence = evidenceRecords({
|
|
277
305
|
project,
|
|
278
306
|
held: projectRead.held,
|
|
@@ -292,10 +320,11 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
292
320
|
return {
|
|
293
321
|
projectRead,
|
|
294
322
|
references: resolved.references,
|
|
295
|
-
|
|
323
|
+
held: resolved.held,
|
|
324
|
+
possiblyLoaded: resolved.possiblyLoaded,
|
|
325
|
+
testFiles,
|
|
296
326
|
evidence,
|
|
297
327
|
componentFiles: components.map(pathOf),
|
|
298
|
-
augmented: mergedGlobalInterfaces(project, projectRead.held, sourceFilesOf(project, targetRoot)).map((id) => ({ id, kind: "global-augmentation", source: "" })),
|
|
299
328
|
imports: new Map(project.ownSourceFiles().flatMap((file) => {
|
|
300
329
|
const path = relativePath(targetRoot, file.fileName);
|
|
301
330
|
if (path === undefined) {
|
|
@@ -317,8 +346,11 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
317
346
|
line: lineOf(file.originalText, warning.offset),
|
|
318
347
|
reason: warning.reason,
|
|
319
348
|
}))),
|
|
320
|
-
decoded: decodedMembers(project, projectRead.held, productionFiles(project, targetRoot,
|
|
321
|
-
extra: extra(project, projectRead, resolved.references, resolved.
|
|
349
|
+
decoded: decodedMembers(project, projectRead.held, productionFiles(project, targetRoot, testFiles), consumers),
|
|
350
|
+
extra: extra(project, projectRead, resolved.references, testFiles, resolved.unseenLoads.map((position) => ({
|
|
351
|
+
configuration: projectRead.configuration,
|
|
352
|
+
position,
|
|
353
|
+
}))),
|
|
322
354
|
};
|
|
323
355
|
});
|
|
324
356
|
const outsidePaths = read.result.outsideTests.map((one) => one.path);
|
|
@@ -332,7 +364,9 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
332
364
|
}));
|
|
333
365
|
// Test-support code is code only test code imports in any configuration of the run: a
|
|
334
366
|
// configuration that holds no test file says nothing about what the tests import.
|
|
335
|
-
const { support, testUsed } = testSupportFiles(withOutside.flatMap((one) => one.projectRead.held.symbols), withOutside.flatMap((one) => one.references),
|
|
367
|
+
const { support, testUsed } = testSupportFiles(withOutside.flatMap((one) => one.projectRead.held.symbols), withOutside.flatMap((one) => one.references),
|
|
368
|
+
// An outside declaration naming a global augmentation calls nothing of its file.
|
|
369
|
+
withOutside.flatMap((one) => one.projectRead.rooted.liveUnderReachability.filter((root) => root.kind !== "global-augmentation")), withOutside.flatMap((one) => one.testFiles), testEvidence(host, targetRoot, withOutside));
|
|
336
370
|
// A member a decode fills or a copy carries is written: a value decoded and sent again carries it on.
|
|
337
371
|
const written = new Set([
|
|
338
372
|
...countedWrites([...withOutside.flatMap((one) => one.references), ...read.result.references], support, mode),
|
|
@@ -355,7 +389,7 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
355
389
|
testFiles: new Set([...one.testFiles, ...support]),
|
|
356
390
|
});
|
|
357
391
|
const exempt = detected.records;
|
|
358
|
-
const made =
|
|
392
|
+
const made = [...one.references, ...(satisfied?.references ?? [])];
|
|
359
393
|
const held = new Set(projectRead.held.symbols.map((symbol) => symbol.position.path));
|
|
360
394
|
const supportFiles = [...support].filter((path) => held.has(path)).sort(bytewise);
|
|
361
395
|
const testUsedFiles = [...testUsed].filter((path) => held.has(path)).sort(bytewise);
|
|
@@ -363,9 +397,7 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
363
397
|
configuration: projectRead.configuration,
|
|
364
398
|
symbols: projectRead.held.symbols,
|
|
365
399
|
references: [...made, ...evidenceReferences(projectRead.held.symbols, detected.inTestFiles)],
|
|
366
|
-
|
|
367
|
-
// naming one calls nothing of its file.
|
|
368
|
-
roots: [...projectRead.rooted.liveUnderReachability, ...one.augmented],
|
|
400
|
+
roots: projectRead.rooted.liveUnderReachability,
|
|
369
401
|
testFiles: [...one.testFiles, ...supportFiles],
|
|
370
402
|
...(supportFiles.length === 0 ? {} : { supportFiles }),
|
|
371
403
|
...(testUsedFiles.length === 0 ? {} : { testUsedFiles }),
|
|
@@ -384,13 +416,13 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
384
416
|
unanswered: [
|
|
385
417
|
...projectRead.held.unanswered,
|
|
386
418
|
...projectRead.rooted.unanswered,
|
|
387
|
-
...made
|
|
388
|
-
|
|
389
|
-
.map((reference) => reference.to),
|
|
419
|
+
...made.filter((reference) => reference.guessed === true).map((reference) => reference.to),
|
|
420
|
+
...one.held,
|
|
390
421
|
...exempt.filter(isUnansweredRecord).map((record) => record.id),
|
|
391
422
|
...one.decoded.unanswered,
|
|
392
423
|
],
|
|
393
424
|
filledOutside: one.decoded.filled,
|
|
425
|
+
possiblyLoaded: one.possiblyLoaded,
|
|
394
426
|
typeErrorSkips: projectRead.typeErrorSkips,
|
|
395
427
|
unmappedEntries: projectRead.rooted.unmappedEntries,
|
|
396
428
|
heldScripts: projectRead.rooted.heldScripts,
|
|
@@ -416,7 +448,8 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
416
448
|
unansweredHeld: [
|
|
417
449
|
...new Set([
|
|
418
450
|
...answers.flatMap((one) => one.unanswered),
|
|
419
|
-
...consumed.filter((one) => one.
|
|
451
|
+
...consumed.filter((one) => one.guessed === true).map((one) => one.to),
|
|
452
|
+
...read.result.consumerHeld,
|
|
420
453
|
]),
|
|
421
454
|
],
|
|
422
455
|
projects,
|
|
@@ -431,6 +464,7 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
431
464
|
conventionUses: read.plan.conventions.uses,
|
|
432
465
|
memberDirs: read.plan.packages.members,
|
|
433
466
|
nestedDirs: read.plan.packages.nested,
|
|
467
|
+
workflows: read.result.workflows,
|
|
434
468
|
};
|
|
435
469
|
}
|
|
436
470
|
/**
|
|
@@ -488,7 +522,7 @@ function evidenceReferences(symbols, inTestFiles) {
|
|
|
488
522
|
* makes being a test's.
|
|
489
523
|
*/
|
|
490
524
|
function countedWrites(references, support, mode) {
|
|
491
|
-
return new Set(
|
|
525
|
+
return new Set(references.flatMap((reference) => reference.use === "write" && !withheldBy(mode, reference, support) ? [reference.to] : []));
|
|
492
526
|
}
|
|
493
527
|
/**
|
|
494
528
|
* The declarations every reference the mode counts stores into, a loaded consumer's
|
|
@@ -498,8 +532,9 @@ function writtenOnly(read, mode) {
|
|
|
498
532
|
const written = new Set();
|
|
499
533
|
const readSome = new Set();
|
|
500
534
|
for (const { configured } of read.projects) {
|
|
535
|
+
const support = new Set(configured.supportFiles ?? []);
|
|
501
536
|
for (const reference of configured.references) {
|
|
502
|
-
if (mode
|
|
537
|
+
if (withheldBy(mode, reference, support)) {
|
|
503
538
|
continue;
|
|
504
539
|
}
|
|
505
540
|
if (reference.use === "write" && reference.consumer === undefined) {
|
|
@@ -528,7 +563,7 @@ function sweptOf(read, input) {
|
|
|
528
563
|
// over what it reads, the test of dead code among them, cannot judge it.
|
|
529
564
|
for (const { configured } of read.projects) {
|
|
530
565
|
for (const reference of configured.references) {
|
|
531
|
-
if (reference.
|
|
566
|
+
if (reference.guessed === true) {
|
|
532
567
|
held.add(reference.from);
|
|
533
568
|
}
|
|
534
569
|
}
|
|
@@ -536,7 +571,7 @@ function sweptOf(read, input) {
|
|
|
536
571
|
const dead = new Map(result.candidates.map((candidate) => [candidate.id, candidate]));
|
|
537
572
|
const answered = matrixOf(read.projects.map(({ configured }) => ({
|
|
538
573
|
...configured,
|
|
539
|
-
references: configured.references.filter((one) => one.
|
|
574
|
+
references: configured.references.filter((one) => one.guessed !== true),
|
|
540
575
|
})));
|
|
541
576
|
const bare = {
|
|
542
577
|
...swept,
|
|
@@ -582,19 +617,20 @@ function productionFiles(project, targetRoot, testFiles) {
|
|
|
582
617
|
/** Reads a run's projects with every per-project fact an emitter reads. */
|
|
583
618
|
export function readEmitterRun(engine, host, scope, config, mode, detectors) {
|
|
584
619
|
const targetRoot = scope.target.path;
|
|
585
|
-
const run = readRun(engine, host, scope, config, mode, detectors, (project, read, references, testFiles) => ({
|
|
620
|
+
const run = readRun(engine, host, scope, config, mode, detectors, (project, read, references, testFiles, unseenLoads) => ({
|
|
586
621
|
deprecation: deprecatedDeclarations(project, read.held),
|
|
587
622
|
accessors: accessorsOf(project, read.held),
|
|
588
|
-
needs: projectNeeds(project, read.held, host, targetRoot, (fileName, text) => engine.parseSourceFile(fileName, text)),
|
|
623
|
+
needs: projectNeeds(project, read.held, host, targetRoot, (fileName, text) => engine.parseSourceFile(fileName, text), read.sources.configuration, read.sources.workflows),
|
|
589
624
|
implementations: implementations(project, read.held),
|
|
590
625
|
heldByInclusion: heldByInclusion(project, targetRoot),
|
|
591
|
-
generated:
|
|
626
|
+
generated: read.generated,
|
|
627
|
+
bindings: read.bindings,
|
|
592
628
|
inOperands: inOperandNames(project, targetRoot, testFiles),
|
|
593
629
|
rooted: read.rooted,
|
|
594
630
|
directives: inlineDirectives(project, read.held, targetRoot).filter((directive) => !read.referenceOnly.includes(directive.site.path)),
|
|
595
631
|
declarationsNamed: declarationsNamed(project, read.held, configuredDeclarations(config)),
|
|
596
632
|
parts: projectParts(project, read.held, references, targetRoot),
|
|
597
|
-
unseenLoads
|
|
633
|
+
unseenLoads,
|
|
598
634
|
}));
|
|
599
635
|
// Whether a declaration carries the marker decides its code, so one whose answer went
|
|
600
636
|
// unread is reported by nothing.
|
|
@@ -656,14 +692,15 @@ export function emitterInputOver(host, scope, config, read, input, selfCheck) {
|
|
|
656
692
|
deprecated: new Set(projects.flatMap((one) => one.extra.deprecation.deprecated)),
|
|
657
693
|
stores: storesOf(projects.map((one) => ({
|
|
658
694
|
references: one.configured.references,
|
|
695
|
+
support: new Set(one.configured.supportFiles ?? []),
|
|
659
696
|
accessors: one.extra.accessors,
|
|
660
697
|
})), swept.exempt, input.mode),
|
|
661
|
-
dependencies: dependenciesOf(host, targetRoot, [...projects.map((one) => one.extra.needs), configurationNeeds(read.conventionUses)], swept.sweep.candidates.map((candidate) => candidate.id), members.read, members.unbuilt, read.nestedDirs),
|
|
698
|
+
dependencies: dependenciesOf(host, targetRoot, read.workflows, [...projects.map((one) => one.extra.needs), configurationNeeds(read.conventionUses)], swept.sweep.candidates.map((candidate) => candidate.id), members.read, members.unbuilt, read.nestedDirs),
|
|
662
699
|
implementations: mergeImplementations(projects.map((one) => one.extra.implementations)),
|
|
663
700
|
files: {
|
|
664
701
|
tree: sourceTree(host, targetRoot),
|
|
665
702
|
heldByInclusion: new Set(projects.flatMap((one) => one.extra.heldByInclusion)),
|
|
666
|
-
generated: new Set(projects.flatMap((one) => one.extra.generated)),
|
|
703
|
+
generated: new Set(projects.flatMap((one) => [...one.extra.generated.keys()])),
|
|
667
704
|
inOperands: new Set(projects.flatMap((one) => one.extra.inOperands)),
|
|
668
705
|
unseenLoads: projects.flatMap((one) => one.extra.unseenLoads),
|
|
669
706
|
},
|
|
@@ -675,6 +712,7 @@ export function emitterInputOver(host, scope, config, read, input, selfCheck) {
|
|
|
675
712
|
encapsulated: readManifest(host, targetRoot).declaresExports,
|
|
676
713
|
edges: readEdgeSides(host, targetRoot),
|
|
677
714
|
filledOutside: new Set(projects.flatMap((one) => one.filledOutside)),
|
|
715
|
+
possiblyLoaded: new Set(projects.flatMap((one) => one.possiblyLoaded)),
|
|
678
716
|
},
|
|
679
717
|
selfCheck,
|
|
680
718
|
intraFunction: intraFunctionFacts(projects.map((one) => one.extra.parts), projects.flatMap((one) => one.configured.references), new Set([...swept.exempt.map((one) => one.id), ...swept.heldByUnanswered])),
|
|
@@ -721,6 +759,8 @@ function readAnalysis(engine, host, scope, config, provenance, mode, detectors)
|
|
|
721
759
|
unmappedEntries: unmappedEverywhere(read.projects),
|
|
722
760
|
heldScripts: read.projects.flatMap((one) => one.heldScripts.map((held) => ({ ...held, configFile: one.configFile }))),
|
|
723
761
|
unseenLoads: read.projects.flatMap((one) => one.extra.unseenLoads),
|
|
762
|
+
generated: new Map(read.projects.flatMap((one) => [...one.extra.generated])),
|
|
763
|
+
bindings: distinctBindings(read.projects.flatMap((one) => one.extra.bindings)),
|
|
724
764
|
},
|
|
725
765
|
configured: read.projects.map((one) => one.configured),
|
|
726
766
|
symbols,
|
|
@@ -50,19 +50,15 @@ function holdersOf(held, scripts) {
|
|
|
50
50
|
* file or a `declare` holds that a `declare global` block, or the top level of a file in
|
|
51
51
|
* `scripts`, declares, directly or inside a namespace there.
|
|
52
52
|
*/
|
|
53
|
-
|
|
53
|
+
function ambientGlobalInterfaces(held, interfaces, scripts) {
|
|
54
54
|
const holders = holdersOf(held, scripts);
|
|
55
55
|
return holders === undefined
|
|
56
56
|
? []
|
|
57
57
|
: interfaces.filter((id) => held.ambient.has(id) && holders(id).global);
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
61
|
-
* declared outside them,
|
|
62
|
-
* global scope: the outside declaration names it wherever a value is typed by it. Where
|
|
63
|
-
* every outside declaration is a package's, not the compiler's library, and declares no
|
|
64
|
-
* member, each member it declares as well: such an interface is a slot the package reads
|
|
65
|
-
* by type, as `keyof` does, in declarations the analysis does not walk.
|
|
60
|
+
* Which ambient global interfaces of the project's own files, `files`, merge into an interface
|
|
61
|
+
* declared outside them, and what each merge keeps.
|
|
66
62
|
*/
|
|
67
63
|
export function mergedGlobalInterfaces(project, held, files) {
|
|
68
64
|
const scripts = new Set();
|
|
@@ -88,7 +84,7 @@ export function mergedGlobalInterfaces(project, held, files) {
|
|
|
88
84
|
const global = new Set(ambientGlobalInterfaces(held, [...names.keys()], scripts));
|
|
89
85
|
const asked = [...names].filter(([id]) => global.has(id));
|
|
90
86
|
if (asked.length === 0) {
|
|
91
|
-
return [];
|
|
87
|
+
return { scripts, interfaces: new Set(), kept: [] };
|
|
92
88
|
}
|
|
93
89
|
const answers = project.symbolsAt(asked.map(([, name]) => project.handle(name)));
|
|
94
90
|
const holders = holdersOf(held, scripts);
|
|
@@ -99,22 +95,25 @@ export function mergedGlobalInterfaces(project, held, files) {
|
|
|
99
95
|
const node = project.declarationAt(handle)?.node;
|
|
100
96
|
return node !== undefined && isInterfaceDeclaration(node) && node.members.length === 0;
|
|
101
97
|
};
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
98
|
+
const interfaces = new Set();
|
|
99
|
+
const kept = new Set();
|
|
100
|
+
asked.forEach(([id], at) => {
|
|
101
|
+
const symbol = answers[at];
|
|
102
|
+
const outside = typeof symbol === "object"
|
|
103
|
+
? symbol.declarations.filter((handle) => !files.byName.has(handle.path))
|
|
104
|
+
: [];
|
|
105
|
+
if (outside.length === 0) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
interfaces.add(id);
|
|
109
|
+
const members = outside.every(empty)
|
|
110
|
+
? held.symbols.filter((one) => one.parent === id).map((one) => one.id)
|
|
111
|
+
: [];
|
|
112
|
+
for (const one of [id, ...(holders?.(id).ids ?? []), ...members]) {
|
|
113
|
+
kept.add(one);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return { scripts, interfaces, kept: [...kept] };
|
|
118
117
|
}
|
|
119
118
|
/**
|
|
120
119
|
* For each reference to a declaration an augmentation block, or the global scope of a
|