@cplieger/deadset-ts 8.0.0-dev.16 → 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 +58 -22
- 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/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 +6 -9
- package/dist/src/contextual-uses.js +1 -17
- package/dist/src/contract/config.generated.js +4 -1
- package/dist/src/contract/report.generated.js +6 -2
- package/dist/src/dependencies.js +25 -29
- package/dist/src/destructuring.js +1 -19
- package/dist/src/element-access.js +179 -164
- package/dist/src/entries/build-scripts.js +2 -2
- package/dist/src/entries/configuration-files.js +3 -7
- package/dist/src/entries/conventions.js +2 -2
- package/dist/src/entries/html-entries.js +7 -10
- package/dist/src/entries/mdx-entries.js +2 -2
- package/dist/src/entries/static-module.js +2 -1
- package/dist/src/facts.js +4 -4
- package/dist/src/findings/completion.js +40 -4
- 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/framework-lifecycle.js +41 -14
- package/dist/src/graph.js +12 -4
- package/dist/src/import-bindings.js +73 -28
- package/dist/src/index/sites.js +557 -0
- package/dist/src/indexed-access.js +523 -478
- package/dist/src/interface-satisfaction.js +1 -1
- package/dist/src/keyof-comparisons.js +124 -103
- package/dist/src/load/expected-module.js +2 -2
- package/dist/src/load/specifiers.js +2 -4
- package/dist/src/load/synthesize.js +5 -0
- package/dist/src/load/workspace-resolution.js +2 -2
- package/dist/src/matrix.js +6 -4
- package/dist/src/module-declarations.js +70 -85
- package/dist/src/overrides.js +134 -112
- package/dist/src/paths.js +46 -7
- package/dist/src/platform-calls.js +2 -2
- package/dist/src/platform-symbols.js +13 -19
- 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 +110 -1285
- package/dist/src/roots/configured-declarations.js +3 -0
- package/dist/src/roots/root-set.js +1 -1
- package/dist/src/roots/unseen-loads.js +38 -10
- package/dist/src/serialization-contract.js +8 -3
- package/dist/src/stores.js +4 -2
- 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} +2 -11
- package/dist/src/type-parameter-reads.js +178 -139
- package/dist/src/unimplemented-callees.js +262 -242
- package/dist/src/verbs/analyze.js +3 -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 +2 -2
- package/src/alias-chain.ts +0 -7
- package/src/amd.ts +130 -0
- package/src/analysis.ts +86 -23
- package/src/augmentations.ts +41 -27
- package/src/bindings.ts +460 -0
- package/src/calls.ts +25 -7
- 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 +8 -11
- package/src/contextual-uses.ts +2 -22
- package/src/contract/config.generated.ts +4 -1
- package/src/contract/report.generated.ts +6 -2
- package/src/dependencies.ts +27 -28
- package/src/destructuring.ts +1 -31
- package/src/element-access.ts +188 -182
- package/src/entries/build-scripts.ts +2 -2
- package/src/entries/configuration-files.ts +11 -8
- package/src/entries/conventions.ts +2 -1
- package/src/entries/html-entries.ts +15 -14
- package/src/entries/mdx-entries.ts +2 -2
- package/src/entries/static-module.ts +2 -1
- package/src/facts.ts +5 -3
- package/src/findings/boundary.ts +2 -0
- package/src/findings/completion.ts +43 -4
- package/src/findings/emitter.ts +1 -1
- package/src/{implementations.ts → findings/implementations.ts} +4 -4
- package/src/{in-operands.ts → findings/in-operands.ts} +3 -3
- package/src/framework-lifecycle.ts +42 -14
- package/src/graph.ts +24 -6
- package/src/import-bindings.ts +98 -29
- package/src/index/sites.ts +781 -0
- package/src/indexed-access.ts +570 -527
- package/src/interface-satisfaction.ts +1 -1
- package/src/keyof-comparisons.ts +131 -116
- package/src/load/expected-module.ts +8 -2
- package/src/load/specifiers.ts +8 -5
- package/src/load/synthesize.ts +6 -0
- package/src/load/workspace-resolution.ts +9 -2
- package/src/matrix.ts +6 -3
- package/src/module-declarations.ts +74 -98
- package/src/overrides.ts +162 -134
- package/src/paths.ts +54 -8
- package/src/platform-calls.ts +3 -3
- package/src/platform-symbols.ts +11 -27
- 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 +168 -1733
- package/src/report.ts +1 -1
- package/src/roots/configured-declarations.ts +3 -0
- package/src/roots/root-set.ts +1 -1
- package/src/roots/unseen-loads.ts +49 -11
- package/src/serialization-contract.ts +8 -3
- package/src/stores.ts +13 -2
- 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} +9 -20
- package/src/type-parameter-reads.ts +187 -158
- package/src/unimplemented-callees.ts +297 -280
- package/src/verbs/analyze.ts +3 -2
- package/src/verbs/explain.ts +74 -31
- package/src/verbs/print-retained.ts +2 -2
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
|
@@ -19,15 +19,16 @@ import { readSources } from "./entries/sources.js";
|
|
|
19
19
|
import { readWorkflows } from "./entries/workflow-steps.js";
|
|
20
20
|
import { readEdgeSides } from "./edges.js";
|
|
21
21
|
import { enumGroup } from "./enum-group.js";
|
|
22
|
+
import { bindingsOf, distinctBindings } from "./bindings.js";
|
|
22
23
|
import { generatedFile, generatedFilesOf } from "./generated-file.js";
|
|
23
|
-
import { inOperandNames } from "./in-operands.js";
|
|
24
|
+
import { inOperandNames } from "./findings/in-operands.js";
|
|
24
25
|
import { sourceFilesOf } from "./source-files.js";
|
|
25
26
|
import { evidenceRecords, heldRecords, disabledClasses, exemptionsOf, holdingWhile, isUnansweredRecord, retainedIn, writtenRecords, } from "./exempt.js";
|
|
26
27
|
import { heldByInclusion, sourcePaths, sourceTree } from "./file-facts.js";
|
|
27
28
|
import { findingsPass, recordedFindings, rowKey } from "./findings-pass.js";
|
|
28
29
|
import { unmatchedRootFindings } from "./findings/self-check.js";
|
|
29
30
|
import { frameworkLifecycle } from "./framework-lifecycle.js";
|
|
30
|
-
import { implementations, mergeImplementations } from "./implementations.js";
|
|
31
|
+
import { implementations, mergeImplementations } from "./findings/implementations.js";
|
|
31
32
|
import { injectionContainer } from "./injection-container.js";
|
|
32
33
|
import { interfaceSatisfaction, settledSatisfaction } from "./interface-satisfaction.js";
|
|
33
34
|
import { intraFunctionFacts, projectParts } from "./intra-function-parts.js";
|
|
@@ -39,12 +40,14 @@ import { ancestors, dirnamePath, extensionOf, joinPath, relativePath, resolvePat
|
|
|
39
40
|
import { byPosition, isComponentFile } from "./position.js";
|
|
40
41
|
import { skippedUnits } from "./type-errors.js";
|
|
41
42
|
import { reflectiveLookup } from "./reflective-lookup.js";
|
|
42
|
-
import { references
|
|
43
|
+
import { references } from "./references.js";
|
|
43
44
|
import { rootSet, unmatchedEverywhere, } from "./roots/root-set.js";
|
|
44
45
|
import { decodedMembers, serializationContract } from "./serialization-contract.js";
|
|
45
|
-
import { outsideTestReferences, testFilesAt } from "./outside
|
|
46
|
+
import { outsideTestReferences, testFilesAt } from "./tests/outside.js";
|
|
47
|
+
import { formedForNode } from "./load/synthesize.js";
|
|
46
48
|
import { GLOBALS_RUNNER, namesTestGlobals } from "./load/test-globals.js";
|
|
47
|
-
import {
|
|
49
|
+
import { targetTestFile, testFilePaths, testFileRulesOf, withheldBy, } from "./tests/file-class.js";
|
|
50
|
+
import { testSupportFiles } from "./tests/support.js";
|
|
48
51
|
import { accessorsOf, storesOf } from "./stores.js";
|
|
49
52
|
import { isPartKind } from "./suppress.js";
|
|
50
53
|
import { bindRows, readBaseline, readIgnoreFile } from "./suppress-file.js";
|
|
@@ -109,6 +112,7 @@ function readProjects(engine, host, scope, config, stage) {
|
|
|
109
112
|
workflows,
|
|
110
113
|
});
|
|
111
114
|
const rooted = rootSet(project, held, targetRoot, { ...options, sources, skips });
|
|
115
|
+
const generated = generatedFilesOf(own, sources.generated);
|
|
112
116
|
return {
|
|
113
117
|
configuration: planned.id,
|
|
114
118
|
configFile: project.configFile,
|
|
@@ -120,8 +124,12 @@ function readProjects(engine, host, scope, config, stage) {
|
|
|
120
124
|
.ownSourceFiles()
|
|
121
125
|
.filter((file) => referenceOnly(file.fileName))
|
|
122
126
|
.flatMap((file) => relativePath(absoluteRoot, file.fileName) ?? []),
|
|
123
|
-
generated
|
|
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]))),
|
|
124
131
|
sources,
|
|
132
|
+
formedForNode: formedForNode(planned),
|
|
125
133
|
};
|
|
126
134
|
};
|
|
127
135
|
for (const file of project.ownSourceFiles()) {
|
|
@@ -130,14 +138,25 @@ function readProjects(engine, host, scope, config, stage) {
|
|
|
130
138
|
return stage(project, { configuration: planned.id, read });
|
|
131
139
|
});
|
|
132
140
|
const consumed = new Map();
|
|
141
|
+
const consumerHeld = new Set();
|
|
133
142
|
for (const { project, consumer } of classified.consumed) {
|
|
134
143
|
const side = { id: consumer.id, root: consumer.path };
|
|
135
|
-
|
|
144
|
+
const read = consumerReferences(project, host, targetRoot, side, config, parse);
|
|
145
|
+
for (const reference of read.references) {
|
|
136
146
|
consumed.set(referenceKey(reference), reference);
|
|
137
147
|
}
|
|
148
|
+
for (const id of read.held) {
|
|
149
|
+
consumerHeld.add(id);
|
|
150
|
+
}
|
|
138
151
|
}
|
|
139
152
|
const outsideTests = testFilesAt(host, targetRoot, sourcePaths(host, targetRoot).filter((path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path))), parse);
|
|
140
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
answers,
|
|
155
|
+
references: [...consumed.values()],
|
|
156
|
+
consumerHeld: [...consumerHeld],
|
|
157
|
+
outsideTests,
|
|
158
|
+
workflows,
|
|
159
|
+
};
|
|
141
160
|
});
|
|
142
161
|
}
|
|
143
162
|
/**
|
|
@@ -202,6 +221,13 @@ export function runRoots(engine, host, scope, config, provenance) {
|
|
|
202
221
|
unanswered: read.unanswered,
|
|
203
222
|
};
|
|
204
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
|
+
}
|
|
205
231
|
/** The exemption classes this analyzer detects, each by its detector; any other retains nothing. */
|
|
206
232
|
export const DETECTORS = new Map([
|
|
207
233
|
["interface-satisfaction", interfaceSatisfaction],
|
|
@@ -268,11 +294,13 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
268
294
|
const directories = runDirectories(host, targetRoot, (fileName, text) => engine.parseSourceFile(fileName, text));
|
|
269
295
|
const read = readProjects(engine, host, scope, config, (project, opened) => {
|
|
270
296
|
const projectRead = opened.read();
|
|
297
|
+
const testFile = targetTestFile(projectRead.sources.testFiles);
|
|
271
298
|
const resolved = references(project, projectRead.held, targetRoot, {
|
|
272
|
-
|
|
273
|
-
testFileNames: projectRead.sources.testFiles,
|
|
299
|
+
testFile,
|
|
274
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,7 +320,9 @@ 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
328
|
imports: new Map(project.ownSourceFiles().flatMap((file) => {
|
|
@@ -316,8 +346,8 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
316
346
|
line: lineOf(file.originalText, warning.offset),
|
|
317
347
|
reason: warning.reason,
|
|
318
348
|
}))),
|
|
319
|
-
decoded: decodedMembers(project, projectRead.held, productionFiles(project, targetRoot,
|
|
320
|
-
extra: extra(project, projectRead, resolved.references,
|
|
349
|
+
decoded: decodedMembers(project, projectRead.held, productionFiles(project, targetRoot, testFiles), consumers),
|
|
350
|
+
extra: extra(project, projectRead, resolved.references, testFiles, resolved.unseenLoads.map((position) => ({
|
|
321
351
|
configuration: projectRead.configuration,
|
|
322
352
|
position,
|
|
323
353
|
}))),
|
|
@@ -359,7 +389,7 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
359
389
|
testFiles: new Set([...one.testFiles, ...support]),
|
|
360
390
|
});
|
|
361
391
|
const exempt = detected.records;
|
|
362
|
-
const made =
|
|
392
|
+
const made = [...one.references, ...(satisfied?.references ?? [])];
|
|
363
393
|
const held = new Set(projectRead.held.symbols.map((symbol) => symbol.position.path));
|
|
364
394
|
const supportFiles = [...support].filter((path) => held.has(path)).sort(bytewise);
|
|
365
395
|
const testUsedFiles = [...testUsed].filter((path) => held.has(path)).sort(bytewise);
|
|
@@ -386,13 +416,13 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
386
416
|
unanswered: [
|
|
387
417
|
...projectRead.held.unanswered,
|
|
388
418
|
...projectRead.rooted.unanswered,
|
|
389
|
-
...made
|
|
390
|
-
|
|
391
|
-
.map((reference) => reference.to),
|
|
419
|
+
...made.filter((reference) => reference.guessed === true).map((reference) => reference.to),
|
|
420
|
+
...one.held,
|
|
392
421
|
...exempt.filter(isUnansweredRecord).map((record) => record.id),
|
|
393
422
|
...one.decoded.unanswered,
|
|
394
423
|
],
|
|
395
424
|
filledOutside: one.decoded.filled,
|
|
425
|
+
possiblyLoaded: one.possiblyLoaded,
|
|
396
426
|
typeErrorSkips: projectRead.typeErrorSkips,
|
|
397
427
|
unmappedEntries: projectRead.rooted.unmappedEntries,
|
|
398
428
|
heldScripts: projectRead.rooted.heldScripts,
|
|
@@ -418,7 +448,8 @@ function readRun(engine, host, scope, config, mode, detectors, extra) {
|
|
|
418
448
|
unansweredHeld: [
|
|
419
449
|
...new Set([
|
|
420
450
|
...answers.flatMap((one) => one.unanswered),
|
|
421
|
-
...consumed.filter((one) => one.
|
|
451
|
+
...consumed.filter((one) => one.guessed === true).map((one) => one.to),
|
|
452
|
+
...read.result.consumerHeld,
|
|
422
453
|
]),
|
|
423
454
|
],
|
|
424
455
|
projects,
|
|
@@ -491,7 +522,7 @@ function evidenceReferences(symbols, inTestFiles) {
|
|
|
491
522
|
* makes being a test's.
|
|
492
523
|
*/
|
|
493
524
|
function countedWrites(references, support, mode) {
|
|
494
|
-
return new Set(
|
|
525
|
+
return new Set(references.flatMap((reference) => reference.use === "write" && !withheldBy(mode, reference, support) ? [reference.to] : []));
|
|
495
526
|
}
|
|
496
527
|
/**
|
|
497
528
|
* The declarations every reference the mode counts stores into, a loaded consumer's
|
|
@@ -501,8 +532,9 @@ function writtenOnly(read, mode) {
|
|
|
501
532
|
const written = new Set();
|
|
502
533
|
const readSome = new Set();
|
|
503
534
|
for (const { configured } of read.projects) {
|
|
535
|
+
const support = new Set(configured.supportFiles ?? []);
|
|
504
536
|
for (const reference of configured.references) {
|
|
505
|
-
if (mode
|
|
537
|
+
if (withheldBy(mode, reference, support)) {
|
|
506
538
|
continue;
|
|
507
539
|
}
|
|
508
540
|
if (reference.use === "write" && reference.consumer === undefined) {
|
|
@@ -531,7 +563,7 @@ function sweptOf(read, input) {
|
|
|
531
563
|
// over what it reads, the test of dead code among them, cannot judge it.
|
|
532
564
|
for (const { configured } of read.projects) {
|
|
533
565
|
for (const reference of configured.references) {
|
|
534
|
-
if (reference.
|
|
566
|
+
if (reference.guessed === true) {
|
|
535
567
|
held.add(reference.from);
|
|
536
568
|
}
|
|
537
569
|
}
|
|
@@ -539,7 +571,7 @@ function sweptOf(read, input) {
|
|
|
539
571
|
const dead = new Map(result.candidates.map((candidate) => [candidate.id, candidate]));
|
|
540
572
|
const answered = matrixOf(read.projects.map(({ configured }) => ({
|
|
541
573
|
...configured,
|
|
542
|
-
references: configured.references.filter((one) => one.
|
|
574
|
+
references: configured.references.filter((one) => one.guessed !== true),
|
|
543
575
|
})));
|
|
544
576
|
const bare = {
|
|
545
577
|
...swept,
|
|
@@ -592,6 +624,7 @@ export function readEmitterRun(engine, host, scope, config, mode, detectors) {
|
|
|
592
624
|
implementations: implementations(project, read.held),
|
|
593
625
|
heldByInclusion: heldByInclusion(project, targetRoot),
|
|
594
626
|
generated: read.generated,
|
|
627
|
+
bindings: read.bindings,
|
|
595
628
|
inOperands: inOperandNames(project, targetRoot, testFiles),
|
|
596
629
|
rooted: read.rooted,
|
|
597
630
|
directives: inlineDirectives(project, read.held, targetRoot).filter((directive) => !read.referenceOnly.includes(directive.site.path)),
|
|
@@ -659,6 +692,7 @@ export function emitterInputOver(host, scope, config, read, input, selfCheck) {
|
|
|
659
692
|
deprecated: new Set(projects.flatMap((one) => one.extra.deprecation.deprecated)),
|
|
660
693
|
stores: storesOf(projects.map((one) => ({
|
|
661
694
|
references: one.configured.references,
|
|
695
|
+
support: new Set(one.configured.supportFiles ?? []),
|
|
662
696
|
accessors: one.extra.accessors,
|
|
663
697
|
})), swept.exempt, input.mode),
|
|
664
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),
|
|
@@ -678,6 +712,7 @@ export function emitterInputOver(host, scope, config, read, input, selfCheck) {
|
|
|
678
712
|
encapsulated: readManifest(host, targetRoot).declaresExports,
|
|
679
713
|
edges: readEdgeSides(host, targetRoot),
|
|
680
714
|
filledOutside: new Set(projects.flatMap((one) => one.filledOutside)),
|
|
715
|
+
possiblyLoaded: new Set(projects.flatMap((one) => one.possiblyLoaded)),
|
|
681
716
|
},
|
|
682
717
|
selfCheck,
|
|
683
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])),
|
|
@@ -725,6 +760,7 @@ function readAnalysis(engine, host, scope, config, provenance, mode, detectors)
|
|
|
725
760
|
heldScripts: read.projects.flatMap((one) => one.heldScripts.map((held) => ({ ...held, configFile: one.configFile }))),
|
|
726
761
|
unseenLoads: read.projects.flatMap((one) => one.extra.unseenLoads),
|
|
727
762
|
generated: new Map(read.projects.flatMap((one) => [...one.extra.generated])),
|
|
763
|
+
bindings: distinctBindings(read.projects.flatMap((one) => one.extra.bindings)),
|
|
728
764
|
},
|
|
729
765
|
configured: read.projects.map((one) => one.configured),
|
|
730
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
|