@cplieger/deadset-ts 8.0.0-dev.1 → 8.0.0-dev.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/bin/mapper-connection.js +2 -1
- package/dist/bin/node-host.js +24 -5
- package/dist/src/analysis.js +181 -341
- package/dist/src/augmentations.js +106 -13
- package/dist/src/automatic-types.js +10 -29
- package/dist/src/build-scripts.js +425 -0
- package/dist/src/component-layer.js +4 -2
- package/dist/src/components.js +2 -3
- package/dist/src/config.js +6 -82
- package/dist/src/configuration-files.js +28 -176
- package/dist/src/configured-declarations.js +15 -20
- package/dist/src/conformance-record.js +1 -1
- package/dist/src/consumers.js +3 -30
- package/dist/src/contextual-uses.js +56 -9
- package/dist/src/contract/config.generated.js +558 -0
- package/dist/src/contract/contract.generated.js +1244 -0
- package/dist/src/contract/report.generated.js +862 -0
- package/dist/src/convention-rows.js +73 -3
- package/dist/src/conventions.js +36 -66
- package/dist/src/dependencies.js +103 -40
- package/dist/src/edges.js +38 -122
- package/dist/src/element-access.js +4 -6
- package/dist/src/entry-point-gaps.js +2 -8
- package/dist/src/entry-points.js +11 -27
- package/dist/src/enum-group.js +3 -10
- package/dist/src/erased-stores.js +4 -6
- package/dist/src/exempt-classes.js +1 -63
- package/dist/src/exempt.js +21 -40
- package/dist/src/failure.js +36 -0
- package/dist/src/file-facts.js +2 -25
- package/dist/src/findings/completion.js +139 -72
- package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
- package/dist/src/findings/emitters.js +5 -5
- package/dist/src/findings/interfaces.js +4 -5
- package/dist/src/findings/intra-function.js +13 -10
- package/dist/src/findings/non-code-artifacts.js +7 -8
- package/dist/src/findings/reads-and-writes.js +16 -13
- package/dist/src/findings/self-check.js +10 -12
- package/dist/src/findings/unused-declarations.js +41 -32
- package/dist/src/findings/visibility-narrowing.js +19 -16
- package/dist/src/findings-pass.js +8 -15
- package/dist/src/framework-lifecycle.js +7 -7
- package/dist/src/fs/document.js +52 -0
- package/dist/src/fs/manifest.js +72 -0
- package/dist/src/fs/tree.js +88 -0
- package/dist/src/generated-file.js +7 -4
- package/dist/src/git-ignore.js +39 -26
- package/dist/src/graph.js +5 -3
- package/dist/src/html-entries.js +6 -33
- package/dist/src/in-operands.js +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/injection-container.js +1 -1
- package/dist/src/intra-function-parts.js +63 -43
- package/dist/src/inventory.js +2 -21
- package/dist/src/javascript-file.js +33 -0
- package/dist/src/json-document.js +198 -67
- package/dist/src/keyof-comparisons.js +4 -6
- package/dist/src/kinds.js +3 -366
- package/dist/src/load/classify.js +270 -0
- package/dist/src/load/diagnostics.js +80 -0
- package/dist/src/load/discover.js +277 -0
- package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
- package/dist/src/load/expected-module.js +136 -0
- package/dist/src/load/load.js +27 -0
- package/dist/src/load/module-lookup.js +37 -0
- package/dist/src/load/plan.js +313 -0
- package/dist/src/load/specifiers.js +115 -0
- package/dist/src/load/synthesize.js +140 -0
- package/dist/src/load/test-globals.js +207 -0
- package/dist/src/load/test-joins.js +82 -0
- package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
- package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
- package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +23 -65
- package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
- package/dist/src/{workspace.js → load/workspace.js} +62 -124
- package/dist/src/manifest.js +49 -54
- package/dist/src/matrix.js +76 -4
- package/dist/src/mdx-entries.js +3 -26
- package/dist/src/outside-tests.js +1 -1
- package/dist/src/partial.js +2 -1
- package/dist/src/paths.js +26 -15
- package/dist/src/position.js +2 -1
- package/dist/src/print.js +11 -79
- package/dist/src/product.js +13 -0
- package/dist/src/query.js +1 -0
- package/dist/src/ref.js +1 -0
- package/dist/src/references.js +48 -30
- package/dist/src/report-schema.js +51 -0
- package/dist/src/report.js +57 -41
- package/dist/src/reporters/annotations.js +15 -8
- package/dist/src/reporters/sarif.js +16 -10
- package/dist/src/reporters/template.js +4 -19
- package/dist/src/resolve.js +245 -729
- package/dist/src/roots.js +273 -87
- package/dist/src/run.js +66 -77
- package/dist/src/schema.js +320 -343
- package/dist/src/scope.js +38 -115
- package/dist/src/serialization-contract.js +595 -21
- package/dist/src/session.js +34 -29
- package/dist/src/source-files.js +1 -1
- package/dist/src/suppress-file.js +25 -28
- package/dist/src/suppress-inline.js +3 -2
- package/dist/src/suppress.js +33 -51
- package/dist/src/sweep.js +7 -9
- package/dist/src/symbol-keys.js +3 -5
- package/dist/src/template-field.js +9 -19
- package/dist/src/test-support.js +8 -11
- package/dist/src/text/compare.js +26 -0
- package/dist/src/text/glob.js +194 -0
- package/dist/src/text/named-files.js +54 -0
- package/dist/src/text/shell.js +159 -0
- package/dist/src/text/yaml.js +393 -0
- package/dist/src/type-errors.js +11 -232
- package/dist/src/unseen-loads.js +100 -0
- package/dist/src/unwrap.js +23 -0
- package/dist/src/usage.js +10 -0
- package/dist/src/verbs/analyze.js +166 -126
- package/dist/src/verbs/describe.js +9 -16
- package/dist/src/verbs/explain.js +10 -7
- package/dist/src/verbs/print-config.js +2 -1
- package/dist/src/verbs/print-projects.js +6 -4
- package/dist/src/verbs/print-retained.js +4 -2
- package/dist/src/verbs/print-roots.js +4 -2
- package/dist/src/verbs/verb.js +1 -5
- package/dist/src/verbs/version.js +14 -3
- package/dist/src/workflow-steps.js +62 -64
- package/jsr.json +1 -1
- package/package.json +4 -3
- package/src/analysis.ts +245 -502
- package/src/augmentations.ts +135 -17
- package/src/automatic-types.ts +11 -29
- package/src/build-scripts.ts +543 -0
- package/src/component-layer.ts +4 -2
- package/src/components.ts +2 -4
- package/src/config.ts +31 -302
- package/src/configuration-files.ts +34 -179
- package/src/configured-declarations.ts +18 -23
- package/src/conformance-record.ts +1 -1
- package/src/consumers.ts +6 -57
- package/src/contextual-uses.ts +64 -12
- package/src/contract/config.generated.ts +818 -0
- package/src/contract/contract.generated.ts +1308 -0
- package/src/contract/report.generated.ts +1237 -0
- package/src/convention-rows.ts +85 -3
- package/src/conventions.ts +46 -84
- package/src/dependencies.ts +118 -46
- package/src/edges.ts +41 -140
- package/src/element-access.ts +4 -7
- package/src/entry-point-gaps.ts +3 -9
- package/src/entry-points.ts +12 -38
- package/src/enum-group.ts +2 -11
- package/src/erased-stores.ts +3 -7
- package/src/exempt-classes.ts +1 -75
- package/src/exempt.ts +36 -50
- package/src/failure.ts +63 -0
- package/src/file-facts.ts +9 -24
- package/src/finding.ts +14 -9
- package/src/findings/boundary.ts +2 -0
- package/src/findings/completion.ts +181 -84
- package/src/findings/dependencies-and-module-machinery.ts +4 -7
- package/src/findings/emitter.ts +8 -9
- package/src/findings/emitters.ts +7 -7
- package/src/findings/interfaces.ts +4 -6
- package/src/findings/intra-function.ts +13 -11
- package/src/findings/non-code-artifacts.ts +9 -11
- package/src/findings/reads-and-writes.ts +20 -16
- package/src/findings/self-check.ts +11 -17
- package/src/findings/unused-declarations.ts +45 -32
- package/src/findings/visibility-narrowing.ts +20 -17
- package/src/findings-pass.ts +10 -19
- package/src/framework-lifecycle.ts +7 -7
- package/src/fs/document.ts +70 -0
- package/src/fs/manifest.ts +92 -0
- package/src/fs/tree.ts +110 -0
- package/src/generated-file.ts +7 -4
- package/src/git-ignore.ts +50 -26
- package/src/graph.ts +5 -3
- package/src/host.ts +12 -5
- package/src/html-entries.ts +6 -33
- package/src/in-operands.ts +2 -1
- package/src/index.ts +1 -1
- package/src/injection-container.ts +1 -1
- package/src/intra-function-parts.ts +73 -44
- package/src/inventory.ts +2 -20
- package/src/javascript-file.ts +37 -0
- package/src/json-document.ts +241 -76
- package/src/keyof-comparisons.ts +3 -7
- package/src/kinds.ts +5 -413
- package/src/load/classify.ts +397 -0
- package/src/load/diagnostics.ts +144 -0
- package/src/load/discover.ts +455 -0
- package/src/{emit-map.ts → load/emit-map.ts} +1 -1
- package/src/load/expected-module.ts +188 -0
- package/src/load/load.ts +73 -0
- package/src/load/module-lookup.ts +50 -0
- package/src/load/plan.ts +504 -0
- package/src/load/specifiers.ts +168 -0
- package/src/load/synthesize.ts +211 -0
- package/src/load/test-globals.ts +251 -0
- package/src/load/test-joins.ts +98 -0
- package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
- package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
- package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +33 -76
- package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
- package/src/{workspace.ts → load/workspace.ts} +90 -134
- package/src/manifest.ts +81 -75
- package/src/matrix.ts +122 -4
- package/src/mdx-entries.ts +3 -26
- package/src/outside-tests.ts +1 -1
- package/src/partial.ts +3 -2
- package/src/paths.ts +27 -15
- package/src/position.ts +2 -1
- package/src/print.ts +12 -92
- package/src/product.ts +18 -0
- package/src/query.ts +11 -0
- package/src/ref.ts +1 -0
- package/src/references.ts +52 -31
- package/src/report-schema.ts +68 -0
- package/src/report.ts +101 -224
- package/src/reporters/annotations.ts +22 -11
- package/src/reporters/json.ts +1 -1
- package/src/reporters/reporter.ts +2 -4
- package/src/reporters/reporters.ts +1 -1
- package/src/reporters/sarif.ts +29 -16
- package/src/reporters/template.ts +4 -20
- package/src/reporters/text.ts +3 -3
- package/src/resolve.ts +283 -1114
- package/src/roots.ts +339 -104
- package/src/run.ts +75 -91
- package/src/schema.ts +391 -388
- package/src/scope.ts +46 -138
- package/src/serialization-contract.ts +763 -22
- package/src/session.ts +70 -54
- package/src/source-files.ts +1 -1
- package/src/suppress-file.ts +24 -33
- package/src/suppress-inline.ts +2 -2
- package/src/suppress.ts +43 -58
- package/src/sweep.ts +23 -9
- package/src/symbol-keys.ts +2 -5
- package/src/template-field.ts +15 -25
- package/src/test-support.ts +17 -13
- package/src/text/compare.ts +27 -0
- package/src/text/glob.ts +210 -0
- package/src/text/named-files.inputs.json +1522 -0
- package/src/text/named-files.ts +68 -0
- package/src/text/shell.ts +161 -0
- package/src/text/yaml.ts +423 -0
- package/src/type-errors.ts +18 -288
- package/src/unseen-loads.ts +134 -0
- package/src/unwrap.ts +34 -0
- package/src/usage.ts +10 -0
- package/src/verbs/analyze.ts +224 -162
- package/src/verbs/describe.ts +14 -15
- package/src/verbs/explain.ts +10 -11
- package/src/verbs/print-config.ts +2 -1
- package/src/verbs/print-projects.ts +6 -4
- package/src/verbs/print-retained.ts +4 -2
- package/src/verbs/print-roots.ts +4 -2
- package/src/verbs/verb.ts +2 -8
- package/src/verbs/version.ts +15 -3
- package/src/workflow-steps.ts +74 -64
- package/dist/src/base-url.js +0 -18
- package/dist/src/discover.js +0 -468
- package/dist/src/glob.js +0 -65
- package/dist/src/pnpm-workspace.js +0 -120
- package/dist/src/setup-failure.js +0 -23
- package/dist/src/test-joins.js +0 -101
- package/dist/src/version.js +0 -7
- package/src/base-url.ts +0 -24
- package/src/discover.ts +0 -653
- package/src/glob.ts +0 -67
- package/src/pnpm-workspace.ts +0 -135
- package/src/setup-failure.ts +0 -39
- package/src/test-joins.ts +0 -120
- package/src/version.ts +0 -7
package/dist/src/roots.js
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The root set of one project: every declaration
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* that names a caller is live under reference counting as well, which the sweep
|
|
7
|
-
* decides; the published API only supposes a consumer, so a published export is live
|
|
8
|
-
* under reachability and still a candidate under reference counting.
|
|
2
|
+
* The root set of one project: every declaration kept live without a reference, and why.
|
|
3
|
+
* Every root seeds reachability and none counts as a reference; a root of a kind that
|
|
4
|
+
* names a caller is live under reference counting too, which the sweep decides, so a
|
|
5
|
+
* published export, which only supposes a consumer, stays a reference-counting candidate.
|
|
9
6
|
*/
|
|
10
|
-
import { isExpressionWithTypeArguments, isFunctionLikeDeclaration, isPropertyAccessExpression, isQualifiedName, isTypeQueryNode, isTypeReferenceNode, isPropertyDeclaration, isVariableDeclaration, isVariableStatement, } from "@typescript/native/ast";
|
|
7
|
+
import { isArrowFunction, isAssertionExpression, isExpressionWithTypeArguments, isFunctionLikeDeclaration, isIdentifier, isMethodDeclaration, isObjectLiteralExpression, isParenthesizedExpression, isPropertyAssignment, isReturnStatement, isSatisfiesExpression, isPropertyAccessExpression, isQualifiedName, isTypeQueryNode, isTypeReferenceNode, isPropertyDeclaration, isVariableDeclaration, isVariableStatement, SyntaxKind, } from "@typescript/native/ast";
|
|
11
8
|
import { aliasChains } from "./alias-chain.js";
|
|
9
|
+
import { isGlobalBlock } from "./augmentations.js";
|
|
12
10
|
import { filesNamedBy, outsideChain, relativeSpecifiers, } from "./configuration-files.js";
|
|
13
11
|
import { conventionEntries } from "./conventions.js";
|
|
14
12
|
import { entryPoints } from "./entry-points.js";
|
|
15
|
-
import { globExpression } from "./glob.js";
|
|
16
13
|
import { nodeKey } from "./inventory.js";
|
|
17
|
-
import {
|
|
14
|
+
import { ancestors, dirnamePath, relativePath, resolvePath } from "./paths.js";
|
|
18
15
|
import { byPosition } from "./position.js";
|
|
19
16
|
import { UNANSWERED } from "./query.js";
|
|
20
17
|
import { sourceFilesOf } from "./source-files.js";
|
|
21
18
|
import { typeQueryAliases } from "./type-query-alias.js";
|
|
19
|
+
import { bytewise } from "./text/compare.js";
|
|
20
|
+
import { holdsManifest } from "./fs/manifest.js";
|
|
21
|
+
import { globExpression } from "./text/glob.js";
|
|
22
|
+
import { spelledFiles } from "./text/named-files.js";
|
|
23
|
+
import { commandDirectories, workflowCommands } from "./workflow-steps.js";
|
|
22
24
|
/** Whether one declaration is written below the directory of a published workspace member. */
|
|
23
25
|
function inPublishedMember(held, id, root, members) {
|
|
24
26
|
const path = held.symbols.find((symbol) => symbol.id === id)?.position.path;
|
|
@@ -46,13 +48,8 @@ const OUTPUT_EXTENSION = /\.(?:d\.ts|d\.mts|d\.cts|js|mjs|cjs|jsx)$/u;
|
|
|
46
48
|
const SOURCE_EXTENSION = /\.(?:d\.)?[cm]?[jt]sx?$/u;
|
|
47
49
|
/** Whether no `package.json` sits between one file and the manifest's directory, which holds it. */
|
|
48
50
|
function ofPackage(host, dir, file) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
host.kindOf(joinPath(at, "package.json")) === "file") {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return true;
|
|
51
|
+
const between = ancestors(dirnamePath(file), dir);
|
|
52
|
+
return between.length > 0 && !between.slice(0, -1).some((at) => holdsManifest(host, at));
|
|
56
53
|
}
|
|
57
54
|
/**
|
|
58
55
|
* The rooted files one manifest target reads back to by name: its path below the
|
|
@@ -162,13 +159,6 @@ export function matchRef(pattern, ref) {
|
|
|
162
159
|
}
|
|
163
160
|
return matchGlob(Array.from(pattern), Array.from(ref));
|
|
164
161
|
}
|
|
165
|
-
/** Two strings ordered bytewise, which is the order every set of a run is read in. */
|
|
166
|
-
function compare(a, b) {
|
|
167
|
-
if (a === b) {
|
|
168
|
-
return 0;
|
|
169
|
-
}
|
|
170
|
-
return a < b ? -1 : 1;
|
|
171
|
-
}
|
|
172
162
|
/** The members of one declaration, indexed by the container that holds them. */
|
|
173
163
|
function childrenOf(held) {
|
|
174
164
|
const byParent = new Map();
|
|
@@ -184,15 +174,47 @@ function childrenOf(held) {
|
|
|
184
174
|
return byParent;
|
|
185
175
|
}
|
|
186
176
|
/**
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
177
|
+
* Per package, the own files its command strings name as plain text, but those a root enters
|
|
178
|
+
* with all they export: a command can use no more of such a file than the root keeps live. A
|
|
179
|
+
* manifest's are its entries' whole command strings, and the target root's package has the
|
|
180
|
+
* workflow steps, git hooks and makefile recipes beside its own, with the directories its
|
|
181
|
+
* workflow steps and lefthook commands run in, where a `.` names that directory's index file.
|
|
182
|
+
*/
|
|
183
|
+
function scriptHolds(entries, files, entered, host, targetRoot) {
|
|
184
|
+
const rooted = new Set(entered.filter((one) => one.exports && one.names === undefined).map((one) => one.file.fileName));
|
|
185
|
+
const spelled = [...files.byName.values()]
|
|
186
|
+
.filter((file) => !rooted.has(file.fileName))
|
|
187
|
+
.map((file) => ({ file, paths: [file.fileName, ...files.writtenAs(file)] }));
|
|
188
|
+
const cwd = host.workingDirectory();
|
|
189
|
+
const commands = new Map([
|
|
190
|
+
[
|
|
191
|
+
resolvePath(cwd, targetRoot),
|
|
192
|
+
[...workflowCommands(host, targetRoot), ...commandDirectories(host, targetRoot)],
|
|
193
|
+
],
|
|
194
|
+
]);
|
|
195
|
+
for (const entry of entries) {
|
|
196
|
+
if (entry.command !== undefined) {
|
|
197
|
+
const dir = resolvePath(cwd, entry.dir);
|
|
198
|
+
commands.set(dir, [...(commands.get(dir) ?? []), entry.command]);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const held = [];
|
|
202
|
+
for (const [dir, texts] of commands) {
|
|
203
|
+
const named = spelledFiles(texts.join("\n"), dir, spelled);
|
|
204
|
+
if (named.length > 0) {
|
|
205
|
+
const paths = named.map((file) => relativePath(targetRoot, file.fileName) ?? file.fileName);
|
|
206
|
+
held.push({ dir, files: paths });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return held;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* The roots one project holds, and every configured string that named nothing in it. A
|
|
213
|
+
* file a manifest member, an entry-file pattern or a tool's configuration names is a root
|
|
214
|
+
* with each name of its export table and every link of a re-export chain to the
|
|
215
|
+
* declaration it carries; in a library, the published API alone roots what a published
|
|
216
|
+
* file exports. A file a runtime executes without reading its exports, a test file or a
|
|
217
|
+
* worker, is a root by itself.
|
|
196
218
|
*/
|
|
197
219
|
export function roots(project, held, targetRoot, options) {
|
|
198
220
|
const files = sourceFilesOf(project, targetRoot);
|
|
@@ -227,7 +249,7 @@ export function roots(project, held, targetRoot, options) {
|
|
|
227
249
|
(options.publishedAPI || options.publishedMembers?.has(entry.dir) === true),
|
|
228
250
|
})),
|
|
229
251
|
];
|
|
230
|
-
const scripted = entries.flatMap(({ entry }) => entry.role === "script" ? files.named(entry.path) : []);
|
|
252
|
+
const scripted = entries.flatMap(({ entry }) => entry.role === "script" && entry.command === undefined ? files.named(entry.path) : []);
|
|
231
253
|
const readBackTo = [
|
|
232
254
|
...scripted,
|
|
233
255
|
...points.filter((point) => READ_BACK_RULES.has(point.rule)).map((point) => point.file),
|
|
@@ -260,6 +282,10 @@ export function roots(project, held, targetRoot, options) {
|
|
|
260
282
|
published.push(...entryFiles(entry));
|
|
261
283
|
}
|
|
262
284
|
}
|
|
285
|
+
if (options.publishedAPI) {
|
|
286
|
+
// A library's bundle hands what its entry exports to every program that loads it.
|
|
287
|
+
published.push(...points.filter((point) => point.rule === "bundler-entry").map((point) => point.file));
|
|
288
|
+
}
|
|
263
289
|
const publishedNames = new Set(published.map((file) => file.fileName));
|
|
264
290
|
const patterned = [];
|
|
265
291
|
for (const pattern of options.entryFiles) {
|
|
@@ -273,6 +299,9 @@ export function roots(project, held, targetRoot, options) {
|
|
|
273
299
|
const unmapped = [];
|
|
274
300
|
const mapped = patterned.map(({ file }) => file);
|
|
275
301
|
for (const { entry } of entries) {
|
|
302
|
+
if (entry.command !== undefined) {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
276
305
|
const named = entryFiles(entry);
|
|
277
306
|
if (named.length === 0 && entry.role !== "script") {
|
|
278
307
|
unmapped.push(entry);
|
|
@@ -295,6 +324,8 @@ export function roots(project, held, targetRoot, options) {
|
|
|
295
324
|
for (const point of points) {
|
|
296
325
|
enter(point.file, point.rule, point.source, point.exports, point.names);
|
|
297
326
|
}
|
|
327
|
+
const heldScripts = scriptHolds(entries.map(({ entry }) => entry), files, entered, options.host, targetRoot);
|
|
328
|
+
const heldFiles = [...new Set(heldScripts.flatMap((one) => one.files))].flatMap((path) => files.byPath.get(path) ?? []);
|
|
298
329
|
for (const file of files.byPath.values()) {
|
|
299
330
|
for (const alias of typeQueryAliases(file)) {
|
|
300
331
|
const source = alias.type.getText().replace(/\s+/gu, " ");
|
|
@@ -309,6 +340,7 @@ export function roots(project, held, targetRoot, options) {
|
|
|
309
340
|
const { tables: exportsOf, named, answered, } = exportTables(project, held, [
|
|
310
341
|
...entered.filter((entry) => entry.exports).map((entry) => entry.file),
|
|
311
342
|
...published,
|
|
343
|
+
...heldFiles,
|
|
312
344
|
]);
|
|
313
345
|
for (const entry of entered) {
|
|
314
346
|
const id = fileIds.get(entry.file.fileName);
|
|
@@ -339,13 +371,22 @@ export function roots(project, held, targetRoot, options) {
|
|
|
339
371
|
const left = sites.get(a.id);
|
|
340
372
|
const right = sites.get(b.id);
|
|
341
373
|
const site = left === undefined || right === undefined ? 0 : byPosition(left, right);
|
|
342
|
-
return site ||
|
|
374
|
+
return site || bytewise(a.kind, b.kind) || bytewise(a.source, b.source);
|
|
343
375
|
});
|
|
344
376
|
return {
|
|
345
377
|
liveUnderReachability: ordered,
|
|
346
378
|
unmatched,
|
|
347
|
-
unanswered:
|
|
379
|
+
unanswered: [
|
|
380
|
+
...(answered ? api.guessed : held.symbols.map((symbol) => symbol.id)),
|
|
381
|
+
// A command runs a held file and may read any export of it, so the file, which reaches its
|
|
382
|
+
// top level, and its exports are held; a declaration neither reaches is still dead.
|
|
383
|
+
...heldFiles.flatMap((file) => {
|
|
384
|
+
const id = fileIds.get(file.fileName);
|
|
385
|
+
return [...(id === undefined ? [] : [id]), ...(exportsOf.get(file.fileName) ?? [])];
|
|
386
|
+
}),
|
|
387
|
+
],
|
|
348
388
|
unmappedEntries,
|
|
389
|
+
heldScripts,
|
|
349
390
|
};
|
|
350
391
|
}
|
|
351
392
|
/**
|
|
@@ -436,12 +477,12 @@ function releaseTagged(held, files) {
|
|
|
436
477
|
/** The kinds of container whose export table, not its members' visibility, says what it publishes. */
|
|
437
478
|
const EXPORTING_CONTAINERS = new Set(["file", "namespace"]);
|
|
438
479
|
/**
|
|
439
|
-
* Every declaration a consumer of the library can name
|
|
440
|
-
*
|
|
441
|
-
* declaration's public and protected ones
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
*
|
|
480
|
+
* Every declaration a consumer of the library can name, a published file itself excluded:
|
|
481
|
+
* what the published files export, with a namespace's exported members and any other
|
|
482
|
+
* declaration's public and protected ones; a declaration a published one's type names; an
|
|
483
|
+
* exported declaration a release tag marks; each declaration a `declare global` block holds
|
|
484
|
+
* in a published file or one holding a published declaration; and, as `guessed`, each
|
|
485
|
+
* declaration spelled as a type name the checker leaves unanswered.
|
|
445
486
|
*/
|
|
446
487
|
function publishedAPI(project, published, exportsOf, held, byPath, tagged) {
|
|
447
488
|
const byId = new Map(held.symbols.map((symbol) => [symbol.id, symbol]));
|
|
@@ -467,46 +508,80 @@ function publishedAPI(project, published, exportsOf, held, byPath, tagged) {
|
|
|
467
508
|
reach(id);
|
|
468
509
|
}
|
|
469
510
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
511
|
+
const files = new Set(held.symbols.filter((one) => one.kind === "file").map((one) => one.id));
|
|
512
|
+
const blocks = held.symbols.filter((one) => isGlobalBlock(one, held, files));
|
|
513
|
+
const fileOf = (id) => {
|
|
514
|
+
let at = byId.get(id);
|
|
515
|
+
while (at !== undefined && at.kind !== "file") {
|
|
516
|
+
at = byId.get(at.parent);
|
|
517
|
+
}
|
|
518
|
+
return at?.id;
|
|
519
|
+
};
|
|
520
|
+
const publishedFiles = published.flatMap((file) => held.declarations.get(nodeKey(file, file)) ?? []);
|
|
521
|
+
const globalsReached = () => {
|
|
522
|
+
const typed = new Set([...publishedFiles, ...[...reached].flatMap((id) => fileOf(id) ?? [])]);
|
|
523
|
+
const before = pending.length;
|
|
524
|
+
for (const block of blocks.filter((one) => typed.has(one.parent))) {
|
|
525
|
+
reach(block.id);
|
|
526
|
+
for (const member of children.get(block.id) ?? []) {
|
|
527
|
+
if (member.kind !== "type-parameter") {
|
|
480
528
|
reach(member.id);
|
|
481
529
|
}
|
|
482
530
|
}
|
|
483
531
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
guessed.add(id);
|
|
500
|
-
reach(id);
|
|
532
|
+
return pending.length > before;
|
|
533
|
+
};
|
|
534
|
+
do {
|
|
535
|
+
while (pending.length > 0) {
|
|
536
|
+
const round = [];
|
|
537
|
+
for (let next = pending.shift(); next !== undefined; next = pending.shift()) {
|
|
538
|
+
round.push(next);
|
|
539
|
+
const exporting = EXPORTING_CONTAINERS.has(byId.get(next)?.kind ?? "");
|
|
540
|
+
for (const member of children.get(next) ?? []) {
|
|
541
|
+
const reachable = exporting
|
|
542
|
+
? member.exported
|
|
543
|
+
: member.visibility !== "private" && member.visibility !== "private-name";
|
|
544
|
+
if (member.kind !== "type-parameter" && reachable) {
|
|
545
|
+
reach(member.id);
|
|
546
|
+
}
|
|
501
547
|
}
|
|
502
548
|
}
|
|
503
|
-
|
|
549
|
+
const named = round.flatMap((id) => {
|
|
550
|
+
const symbol = byId.get(id);
|
|
551
|
+
return symbol === undefined || symbol.kind === "file" ? [] : nodes.typeNamesOf(symbol);
|
|
552
|
+
});
|
|
553
|
+
const inferred = inferredTypeSymbols(project, round.flatMap((id) => {
|
|
554
|
+
const symbol = byId.get(id);
|
|
555
|
+
return symbol === undefined ? [] : nodes.nodesOf(symbol);
|
|
556
|
+
}));
|
|
557
|
+
for (const symbol of inferred.types) {
|
|
504
558
|
for (const target of chains.chainOf(symbol)) {
|
|
505
559
|
reach(target.id);
|
|
506
560
|
}
|
|
507
561
|
}
|
|
508
|
-
|
|
509
|
-
|
|
562
|
+
for (const symbol of inferred.members) {
|
|
563
|
+
for (const target of chains.chainOf(symbol)) {
|
|
564
|
+
const member = byId.get(target.id);
|
|
565
|
+
if (member?.visibility === "public" || member?.visibility === "protected") {
|
|
566
|
+
reach(target.id);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
project.symbolsAt(named.map((node) => project.handle(node))).forEach((symbol, index) => {
|
|
571
|
+
if (symbol === UNANSWERED) {
|
|
572
|
+
for (const id of held.byName.get(named[index]?.getText() ?? "") ?? []) {
|
|
573
|
+
guessed.add(id);
|
|
574
|
+
reach(id);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
else if (symbol !== undefined) {
|
|
578
|
+
for (const target of chains.chainOf(symbol)) {
|
|
579
|
+
reach(target.id);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
} while (globalsReached());
|
|
510
585
|
return { ids: [...reached], guessed: [...guessed] };
|
|
511
586
|
}
|
|
512
587
|
/** The type names declarations of the inventory write, each file walked once, when first asked. */
|
|
@@ -544,11 +619,101 @@ function declarationNodes(held, byPath) {
|
|
|
544
619
|
/** How deep the type arguments and constituents of an inferred type are followed. */
|
|
545
620
|
const INFERRED_DEPTH = 4;
|
|
546
621
|
/**
|
|
547
|
-
* The
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
|
|
551
|
-
|
|
622
|
+
* The values one function body returns, each through the type assertions around it: the
|
|
623
|
+
* value a caller receives carries the operand's type whatever type the assertion or the
|
|
624
|
+
* signature names. A nested function's returns are its own.
|
|
625
|
+
*/
|
|
626
|
+
function returnedValues(body) {
|
|
627
|
+
const found = [];
|
|
628
|
+
const add = (value) => {
|
|
629
|
+
for (let at = value; at !== undefined;) {
|
|
630
|
+
found.push(at);
|
|
631
|
+
at =
|
|
632
|
+
isAssertionExpression(at) || isSatisfiesExpression(at) || isParenthesizedExpression(at)
|
|
633
|
+
? at.expression
|
|
634
|
+
: undefined;
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
if (!isFunctionLikeDeclaration(body.parent) || body.parent.body !== body) {
|
|
638
|
+
return found;
|
|
639
|
+
}
|
|
640
|
+
if (isArrowFunction(body.parent) && body.kind !== SyntaxKind.Block) {
|
|
641
|
+
add(body);
|
|
642
|
+
return found;
|
|
643
|
+
}
|
|
644
|
+
const visit = (node) => {
|
|
645
|
+
if (isFunctionLikeDeclaration(node)) {
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
if (isReturnStatement(node) && node.expression !== undefined) {
|
|
649
|
+
add(node.expression);
|
|
650
|
+
}
|
|
651
|
+
node.forEachChild(visit);
|
|
652
|
+
};
|
|
653
|
+
body.forEachChild(visit);
|
|
654
|
+
return found;
|
|
655
|
+
}
|
|
656
|
+
/** The object literal one returned value is, written there or as the initializer of a variable `body` declares. */
|
|
657
|
+
function returnedLiteral(value, body) {
|
|
658
|
+
if (isObjectLiteralExpression(value)) {
|
|
659
|
+
return value;
|
|
660
|
+
}
|
|
661
|
+
if (!isIdentifier(value)) {
|
|
662
|
+
return undefined;
|
|
663
|
+
}
|
|
664
|
+
let found;
|
|
665
|
+
const visit = (node) => {
|
|
666
|
+
if (isVariableDeclaration(node) &&
|
|
667
|
+
isIdentifier(node.name) &&
|
|
668
|
+
node.name.text === value.text &&
|
|
669
|
+
node.initializer !== undefined) {
|
|
670
|
+
let at = node.initializer;
|
|
671
|
+
while (isAssertionExpression(at) ||
|
|
672
|
+
isSatisfiesExpression(at) ||
|
|
673
|
+
isParenthesizedExpression(at)) {
|
|
674
|
+
at = at.expression;
|
|
675
|
+
}
|
|
676
|
+
found = isObjectLiteralExpression(at) ? at : found;
|
|
677
|
+
}
|
|
678
|
+
if (!isFunctionLikeDeclaration(node)) {
|
|
679
|
+
node.forEachChild(visit);
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
body.forEachChild(visit);
|
|
683
|
+
return found;
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* The values one function body returns, and those each method of an object literal it
|
|
687
|
+
* returns returns, to a fixed depth: a caller holding the literal calls its methods, and
|
|
688
|
+
* receives what they return.
|
|
689
|
+
*/
|
|
690
|
+
function returnedThroughLiterals(body, depth = 0) {
|
|
691
|
+
const values = returnedValues(body);
|
|
692
|
+
if (depth >= INFERRED_DEPTH) {
|
|
693
|
+
return values;
|
|
694
|
+
}
|
|
695
|
+
const found = [...values];
|
|
696
|
+
for (const value of values) {
|
|
697
|
+
for (const property of returnedLiteral(value, body)?.properties ?? []) {
|
|
698
|
+
const fn = isMethodDeclaration(property)
|
|
699
|
+
? property
|
|
700
|
+
: isPropertyAssignment(property) && isFunctionLikeDeclaration(property.initializer)
|
|
701
|
+
? property.initializer
|
|
702
|
+
: undefined;
|
|
703
|
+
if (fn?.body !== undefined) {
|
|
704
|
+
found.push(...returnedThroughLiterals(fn.body, depth + 1));
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
return found;
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* The declarations of the types the compiler infers where a declaration writes none, and
|
|
712
|
+
* of the values a function returns: the type of a variable or a property with no
|
|
713
|
+
* annotation, the result of a function or a method with no result annotation, and the type
|
|
714
|
+
* of each value its body returns, each with the types its type arguments and its union or
|
|
715
|
+
* intersection constituents name, to a fixed depth; and as `members` the properties of each
|
|
716
|
+
* returned value's type. A question the checker leaves unanswered names nothing.
|
|
552
717
|
*/
|
|
553
718
|
function inferredTypeSymbols(project, declarations) {
|
|
554
719
|
const { queries } = project;
|
|
@@ -557,12 +722,24 @@ function inferredTypeSymbols(project, declarations) {
|
|
|
557
722
|
!isFunctionLikeDeclaration(node.initializer ?? node)
|
|
558
723
|
? [node.name]
|
|
559
724
|
: []);
|
|
725
|
+
const returned = declarations.flatMap((node) => {
|
|
726
|
+
const signature = isFunctionLikeDeclaration(node)
|
|
727
|
+
? node
|
|
728
|
+
: isVariableDeclaration(node) &&
|
|
729
|
+
node.initializer !== undefined &&
|
|
730
|
+
isFunctionLikeDeclaration(node.initializer)
|
|
731
|
+
? node.initializer
|
|
732
|
+
: undefined;
|
|
733
|
+
return signature?.body === undefined ? [] : returnedThroughLiterals(signature.body);
|
|
734
|
+
});
|
|
560
735
|
const types = [];
|
|
561
|
-
|
|
736
|
+
const returnedTypes = [];
|
|
737
|
+
queries.typesAt([...valued, ...returned]).forEach((type, at) => {
|
|
562
738
|
if (type !== UNANSWERED && type !== undefined) {
|
|
563
|
-
types.push(type);
|
|
739
|
+
(at < valued.length ? types : returnedTypes).push(type);
|
|
564
740
|
}
|
|
565
741
|
});
|
|
742
|
+
types.push(...returnedTypes);
|
|
566
743
|
for (const node of declarations) {
|
|
567
744
|
const signature = isFunctionLikeDeclaration(node)
|
|
568
745
|
? node
|
|
@@ -604,7 +781,19 @@ function inferredTypeSymbols(project, declarations) {
|
|
|
604
781
|
types.forEach((type) => {
|
|
605
782
|
visit(type, 0);
|
|
606
783
|
});
|
|
607
|
-
|
|
784
|
+
// A returned value carries each property of its type, one an anonymous type declares or
|
|
785
|
+
// an intersection merges included, which no type name reaches.
|
|
786
|
+
const members = new Map();
|
|
787
|
+
for (const type of returnedTypes) {
|
|
788
|
+
const parts = queries.constituents(type);
|
|
789
|
+
for (const one of [type, ...(parts === UNANSWERED ? [] : parts)]) {
|
|
790
|
+
const properties = queries.propertiesOf(one);
|
|
791
|
+
for (const property of properties === UNANSWERED ? [] : properties) {
|
|
792
|
+
members.set(property.id, property);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
return { types: [...found.values()], members: [...members.values()] };
|
|
608
797
|
}
|
|
609
798
|
/**
|
|
610
799
|
* The names of types one declaration's own syntax writes: in a type reference, a
|
|
@@ -659,13 +848,10 @@ function configured(held, patterns, add) {
|
|
|
659
848
|
return unmatched;
|
|
660
849
|
}
|
|
661
850
|
/**
|
|
662
|
-
* Every configured string that named no declaration in
|
|
663
|
-
* configuration order and each once.
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
* declaration, so there is one per run: a string that names a declaration of one
|
|
667
|
-
* project has named something, and the projects it named nothing in are not a
|
|
668
|
-
* finding. A run with no project names nothing with any of them.
|
|
851
|
+
* Every configured string that named no declaration in any project of the run, in
|
|
852
|
+
* configuration order and each once. The finding is about the configuration, so a string
|
|
853
|
+
* naming a declaration of one project has named something, and a run with no project
|
|
854
|
+
* names nothing with any of them.
|
|
669
855
|
*/
|
|
670
856
|
export function unmatchedEverywhere(patterns, perProject) {
|
|
671
857
|
return [...new Set(patterns)].filter((pattern) => perProject.every((project) => project.unmatched.includes(pattern)));
|