@cplieger/deadset-ts 8.0.0-dev.16 → 8.0.0-dev.18
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 +82 -91
- package/dist/src/augmentations.js +24 -25
- package/dist/src/bindings.js +382 -0
- package/dist/src/calls.js +279 -43
- 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/contract.generated.js +2 -2
- 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/exempt.js +0 -26
- package/dist/src/exposure.js +400 -0
- package/dist/src/facts.js +4 -4
- package/dist/src/findings/completion.js +44 -21
- package/dist/src/findings/emitters.js +22 -33
- 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/intra-function.js +3 -3
- package/dist/src/findings/reads-and-writes.js +71 -15
- package/dist/src/findings/unused-declarations.js +2 -22
- package/dist/src/findings/visibility-narrowing.js +14 -20
- package/dist/src/framework-lifecycle.js +41 -14
- 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/inventory.js +18 -0
- package/dist/src/keyof-comparisons.js +124 -103
- package/dist/src/{components.js → liveness/components.js} +1 -1
- package/dist/src/{graph.js → liveness/graph.js} +45 -20
- package/dist/src/liveness/matrix.js +99 -0
- package/dist/src/liveness/sweep.js +558 -0
- 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/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/query.js +46 -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 +237 -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/published-reach.js +4 -4
- 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/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 +75 -132
- package/dist/src/verbs/print-retained.js +3 -3
- 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 +125 -128
- package/src/augmentations.ts +42 -28
- package/src/bindings.ts +460 -0
- package/src/calls.ts +338 -46
- 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/contract.generated.ts +2 -2
- 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/exempt.ts +31 -46
- package/src/exposure.ts +492 -0
- package/src/facts.ts +5 -3
- package/src/finding.ts +1 -1
- package/src/findings/boundary.ts +9 -0
- package/src/findings/completion.ts +48 -23
- package/src/findings/emitter.ts +1 -1
- package/src/findings/emitters.ts +23 -41
- package/src/{implementations.ts → findings/implementations.ts} +4 -4
- package/src/{in-operands.ts → findings/in-operands.ts} +3 -3
- package/src/findings/interfaces.ts +3 -3
- package/src/findings/intra-function.ts +3 -3
- package/src/findings/reads-and-writes.ts +99 -26
- package/src/findings/unused-declarations.ts +4 -28
- package/src/findings/visibility-narrowing.ts +25 -26
- package/src/framework-lifecycle.ts +42 -14
- 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 +2 -2
- package/src/inventory.ts +19 -0
- package/src/keyof-comparisons.ts +131 -116
- package/src/{components.ts → liveness/components.ts} +3 -3
- package/src/{graph.ts → liveness/graph.ts} +93 -27
- package/src/liveness/matrix.ts +162 -0
- package/src/liveness/sweep.ts +855 -0
- 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/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/query.ts +81 -0
- package/src/references/read-rule.ts +60 -0
- package/src/references/read-rules.ts +55 -0
- package/src/references/sink.ts +314 -0
- package/src/references/sources.ts +632 -0
- package/src/references.ts +175 -1733
- package/src/report.ts +1 -1
- package/src/roots/configured-declarations.ts +3 -0
- package/src/roots/published-reach.ts +9 -4
- 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 +15 -3
- package/src/symbol-keys.ts +102 -102
- package/src/tests/file-class.ts +135 -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 +83 -158
- package/src/verbs/print-retained.ts +3 -3
- package/dist/src/matrix.js +0 -273
- package/dist/src/sweep.js +0 -222
- package/src/matrix.ts +0 -463
- package/src/sweep.ts +0 -361
package/src/paths.ts
CHANGED
|
@@ -11,6 +11,58 @@ export function isAbsolutePath(path: string): boolean {
|
|
|
11
11
|
return path.startsWith(SEPARATOR);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
/** Whether a specifier starts a path relative to the file that writes it: `./` or `../`. */
|
|
15
|
+
export function startsRelativePath(specifier: string): boolean {
|
|
16
|
+
return specifier.startsWith("./") || specifier.startsWith("../");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Whether a specifier names a path relative to the file that writes it: `.`, `..`, `./` or `../` first. */
|
|
20
|
+
export function isRelativeSpecifier(specifier: string): boolean {
|
|
21
|
+
return specifier === "." || specifier === ".." || startsRelativePath(specifier);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Whether a module specifier names a path rather than a package, as the compiler reads one:
|
|
26
|
+
* a relative specifier or an absolute path.
|
|
27
|
+
*/
|
|
28
|
+
export function isPathSpecifier(specifier: string): boolean {
|
|
29
|
+
return isRelativeSpecifier(specifier) || isAbsolutePath(specifier);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Whether a string starts with `./`, `../` or `/`, the specifiers a browser reads as a URL
|
|
34
|
+
* rather than a bare name, so a bare `.` or `..` stays a request:
|
|
35
|
+
* https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-url-like-module-specifier
|
|
36
|
+
*/
|
|
37
|
+
export function isExplicitPath(text: string): boolean {
|
|
38
|
+
return startsRelativePath(text) || isAbsolutePath(text);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Whether a string starts with `.` or `/`, which no npm package name does, so a reader that
|
|
43
|
+
* takes any other string as a package's takes it as a path:
|
|
44
|
+
* https://docs.npmjs.com/cli/v11/configuring-npm/package-json#name
|
|
45
|
+
*/
|
|
46
|
+
export function cannotStartPackageName(text: string): boolean {
|
|
47
|
+
return text.startsWith(".") || isAbsolutePath(text);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** A URL scheme, `file:` and `node:` among them: https://url.spec.whatwg.org/#url-scheme-string */
|
|
51
|
+
const URL_SCHEME = /^[a-z][a-z\d+.-]*:/iu;
|
|
52
|
+
|
|
53
|
+
/** Whether a string starts with a URL scheme. */
|
|
54
|
+
export function hasURLScheme(text: string): boolean {
|
|
55
|
+
return URL_SCHEME.test(text);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Whether a URL reference is a relative one that does not start with a solidus, the bare
|
|
60
|
+
* name included: https://url.spec.whatwg.org/#relative-url-string
|
|
61
|
+
*/
|
|
62
|
+
export function isPathRelativeURL(reference: string): boolean {
|
|
63
|
+
return reference !== "" && !reference.startsWith(SEPARATOR) && !hasURLScheme(reference);
|
|
64
|
+
}
|
|
65
|
+
|
|
14
66
|
/**
|
|
15
67
|
* One path with `.` removed, `..` applied to the segment before it, and repeated
|
|
16
68
|
* separators collapsed. A `..` that walks past the root of an absolute path is
|
|
@@ -97,18 +149,12 @@ export function resolvePath(against: string, path: string): string {
|
|
|
97
149
|
return isAbsolutePath(path) ? normalizePath(path) : joinPath(against, path);
|
|
98
150
|
}
|
|
99
151
|
|
|
100
|
-
/**
|
|
101
|
-
* A URL reference's scheme. A reference with none that does not start with a solidus is
|
|
102
|
-
* relative, the bare name included: https://url.spec.whatwg.org/#relative-url-string
|
|
103
|
-
*/
|
|
104
|
-
const URL_SCHEME = /^[a-z][a-z\d+.-]*:/iu;
|
|
105
|
-
|
|
106
152
|
/**
|
|
107
153
|
* The path a relative URL reference names against `dir`, its query and its fragment
|
|
108
154
|
* removed, which name no part of the file; undefined where the reference is not relative.
|
|
109
155
|
*/
|
|
110
156
|
export function relativeURLPath(dir: string, reference: string): string | undefined {
|
|
111
|
-
if (
|
|
157
|
+
if (!isPathRelativeURL(reference)) {
|
|
112
158
|
return undefined;
|
|
113
159
|
}
|
|
114
160
|
const cut = reference.search(/[?#]/u);
|
|
@@ -123,7 +169,7 @@ export function relativeURLPath(dir: string, reference: string): string | undefi
|
|
|
123
169
|
*/
|
|
124
170
|
export function queriedModulePath(specifier: string): string | undefined {
|
|
125
171
|
const query = specifier.indexOf("?");
|
|
126
|
-
if (query < 0 || !(specifier
|
|
172
|
+
if (query < 0 || !startsRelativePath(specifier)) {
|
|
127
173
|
return undefined;
|
|
128
174
|
}
|
|
129
175
|
const raw = specifier
|
package/src/platform-calls.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Which calls are the platform's `require` and which constructions its `URL`
|
|
3
|
-
* references-ts.1), decided once over the bindings of the names a callee is written with: the
|
|
2
|
+
* Which calls are the platform's `require` or AMD's `define` and which constructions its `URL`
|
|
3
|
+
* (roots.23, references-ts.37, references-ts.1), decided once over the bindings of the names a callee is written with: the
|
|
4
4
|
* checker's in a program, the file's own scopes in a module read outside every program.
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import { parenthesesRemoved, unwrapped } from "./unwrap.ts";
|
|
20
20
|
|
|
21
21
|
/** A name of the platform the analysis reads calls of. */
|
|
22
|
-
type PlatformName = "require" | "createRequire" | "URL";
|
|
22
|
+
type PlatformName = "require" | "createRequire" | "define" | "URL";
|
|
23
23
|
|
|
24
24
|
/** What one written name is bound to, as far as its reader can tell. */
|
|
25
25
|
export interface Bound {
|
package/src/platform-symbols.ts
CHANGED
|
@@ -28,19 +28,11 @@ import { isAmbient } from "./inventory.ts";
|
|
|
28
28
|
import { callsPlatformBy, carriedNames, type BindingOf, type Bound } from "./platform-calls.ts";
|
|
29
29
|
import { unwrapped } from "./unwrap.ts";
|
|
30
30
|
|
|
31
|
-
/** Counts one request a platform decision puts to the checker. */
|
|
32
|
-
type Asked = () => void;
|
|
33
|
-
|
|
34
31
|
/** The symbol one symbol names through its aliases, or the symbol itself where it is none. */
|
|
35
|
-
function dealiased<Brand>(
|
|
36
|
-
project: ProjectView<Brand>,
|
|
37
|
-
symbol: TSSymbol,
|
|
38
|
-
asked: Asked,
|
|
39
|
-
): Answer<TSSymbol> {
|
|
32
|
+
function dealiased<Brand>(project: ProjectView<Brand>, symbol: TSSymbol): Answer<TSSymbol> {
|
|
40
33
|
if ((symbol.flags & SymbolFlags.Alias) === 0) {
|
|
41
34
|
return symbol;
|
|
42
35
|
}
|
|
43
|
-
asked();
|
|
44
36
|
return project.queries.aliased(symbol);
|
|
45
37
|
}
|
|
46
38
|
|
|
@@ -84,7 +76,6 @@ function writesBody(node: Node): boolean {
|
|
|
84
76
|
function boundBy<Brand>(
|
|
85
77
|
project: ProjectView<Brand>,
|
|
86
78
|
symbol: Answer<TSSymbol> | undefined,
|
|
87
|
-
asked: Asked,
|
|
88
79
|
): Bound | undefined {
|
|
89
80
|
if (typeof symbol !== "object") {
|
|
90
81
|
return undefined;
|
|
@@ -101,7 +92,6 @@ function boundBy<Brand>(
|
|
|
101
92
|
if ((at.flags & SymbolFlags.Alias) === 0) {
|
|
102
93
|
return { names, own, provenOwn: own.some(writesBody) };
|
|
103
94
|
}
|
|
104
|
-
asked();
|
|
105
95
|
const next = project.aliasStepOf(at);
|
|
106
96
|
at = typeof next === "object" ? next : undefined;
|
|
107
97
|
}
|
|
@@ -109,29 +99,24 @@ function boundBy<Brand>(
|
|
|
109
99
|
}
|
|
110
100
|
|
|
111
101
|
/** Each written name's binding, as this project's checker answers it. */
|
|
112
|
-
function checkerBinding<Brand>(project: ProjectView<Brand
|
|
113
|
-
return (written) =>
|
|
114
|
-
asked();
|
|
115
|
-
return boundBy(project, project.symbolsAt([project.handle(written)])[0], asked);
|
|
116
|
-
};
|
|
102
|
+
function checkerBinding<Brand>(project: ProjectView<Brand>): BindingOf {
|
|
103
|
+
return (written) => boundBy(project, project.symbolsAt([project.handle(written)])[0]);
|
|
117
104
|
}
|
|
118
105
|
|
|
119
106
|
/**
|
|
120
107
|
* Whether a call or construction through `callee`, the batch's answer for which is `symbol`,
|
|
121
|
-
* is one of the platform's `require` or `URL` (roots.23, references-ts.
|
|
122
|
-
* {@link callsPlatformBy} decides it over this project's checker
|
|
123
|
-
* counted by `asked`.
|
|
108
|
+
* is one of the platform's `require`, AMD's `define` or `URL` (roots.23, references-ts.37,
|
|
109
|
+
* references-ts.1), as {@link callsPlatformBy} decides it over this project's checker.
|
|
124
110
|
*/
|
|
125
111
|
export function callsPlatform<Brand>(
|
|
126
112
|
project: ProjectView<Brand>,
|
|
127
|
-
name: "require" | "URL",
|
|
113
|
+
name: "require" | "define" | "URL",
|
|
128
114
|
callee: Identifier,
|
|
129
115
|
symbol: Answer<TSSymbol> | undefined,
|
|
130
|
-
asked: Asked,
|
|
131
116
|
): boolean {
|
|
132
|
-
const others = checkerBinding(project
|
|
117
|
+
const others = checkerBinding(project);
|
|
133
118
|
return callsPlatformBy(name, callee, (written) =>
|
|
134
|
-
written === callee ? boundBy(project, symbol
|
|
119
|
+
written === callee ? boundBy(project, symbol) : others(written),
|
|
135
120
|
);
|
|
136
121
|
}
|
|
137
122
|
|
|
@@ -177,15 +162,14 @@ function inThreadsModule(node: Node): boolean {
|
|
|
177
162
|
* (references-ts.2): its symbol resolves to a declaration of `worker_threads`, or one of its
|
|
178
163
|
* own declarations binds the module's `Worker`, or `holder`, the namespace it is read
|
|
179
164
|
* through, binds the module, each binding read as {@link boundExports} reads one, which
|
|
180
|
-
* decides where the module has no declaration.
|
|
165
|
+
* decides where the module has no declaration.
|
|
181
166
|
*/
|
|
182
167
|
export function startsThread<Brand>(
|
|
183
168
|
project: ProjectView<Brand>,
|
|
184
169
|
symbol: Answer<TSSymbol> | undefined,
|
|
185
170
|
holder: Answer<TSSymbol> | undefined,
|
|
186
|
-
asked: Asked,
|
|
187
171
|
): boolean {
|
|
188
|
-
const bindingOf = checkerBinding(project
|
|
172
|
+
const bindingOf = checkerBinding(project);
|
|
189
173
|
const declared = (one: Answer<TSSymbol> | undefined, member: string): boolean =>
|
|
190
174
|
typeof one === "object" &&
|
|
191
175
|
ownDeclarations(project, one).some((node) =>
|
|
@@ -194,7 +178,7 @@ export function startsThread<Brand>(
|
|
|
194
178
|
if (declared(symbol, "Worker") || declared(holder, NAMESPACE)) {
|
|
195
179
|
return true;
|
|
196
180
|
}
|
|
197
|
-
const named = typeof symbol === "object" ? dealiased(project, symbol
|
|
181
|
+
const named = typeof symbol === "object" ? dealiased(project, symbol) : undefined;
|
|
198
182
|
return (
|
|
199
183
|
typeof named === "object" &&
|
|
200
184
|
named.declarations.some((handle) => {
|
package/src/query.ts
CHANGED
|
@@ -207,8 +207,22 @@ export interface Queries {
|
|
|
207
207
|
constraintOf(type: Type): Answer<Type | undefined>;
|
|
208
208
|
/** The object and the index of an indexed-access type; none for another type. */
|
|
209
209
|
indexedAccessOf(type: Type): Answer<{ readonly object: Type; readonly index: Type } | undefined>;
|
|
210
|
+
/**
|
|
211
|
+
* The types one type is spelled from besides its constituents, type arguments and members:
|
|
212
|
+
* a type parameter's constraint and default, a conditional's check, extends, true
|
|
213
|
+
* and false types, a mapped type's constraint, name and template, an indexed access's
|
|
214
|
+
* object and index, the operand of `keyof` or of a string mapping, a template literal's
|
|
215
|
+
* spans and a substitution's base and constraint. None for another type.
|
|
216
|
+
*/
|
|
217
|
+
partsOf(type: Type): Answer<readonly Type[]>;
|
|
218
|
+
/** The type parameters of a signature, its `this` parameter's type and its predicate's type. */
|
|
219
|
+
signaturePartsOf(signature: Signature): Answer<readonly Type[]>;
|
|
210
220
|
/** The symbol a type is declared by. */
|
|
211
221
|
symbolOfType(type: Type): Answer<TSSymbol | undefined>;
|
|
222
|
+
/** The type alias a type was instantiated from, where it was. */
|
|
223
|
+
aliasSymbolOf(type: Type): Answer<TSSymbol | undefined>;
|
|
224
|
+
/** The type arguments the alias a type was instantiated from was given. */
|
|
225
|
+
aliasArgumentsOf(type: Type): Answer<readonly Type[]>;
|
|
212
226
|
signaturesOf(type: Type, kind: SignatureKind): Answer<readonly Signature[]>;
|
|
213
227
|
resolvedSignature(node: Node): Answer<Signature | undefined>;
|
|
214
228
|
/** The signature each call-like node resolves to. */
|
|
@@ -223,6 +237,37 @@ export interface Queries {
|
|
|
223
237
|
typeToString(type: Type): Answer<string>;
|
|
224
238
|
}
|
|
225
239
|
|
|
240
|
+
/** How to read the types one type is spelled from, as {@link Queries.partsOf} names them. */
|
|
241
|
+
function partQuestion(type: Type): (() => readonly (Type | undefined)[]) | undefined {
|
|
242
|
+
if (type.isTypeParameter()) {
|
|
243
|
+
return () => [type.getConstraint(), type.getDefault()];
|
|
244
|
+
}
|
|
245
|
+
if (type.isConditionalType()) {
|
|
246
|
+
return () => [
|
|
247
|
+
type.getCheckType(),
|
|
248
|
+
type.getExtendsType(),
|
|
249
|
+
type.getTrueType(),
|
|
250
|
+
type.getFalseType(),
|
|
251
|
+
];
|
|
252
|
+
}
|
|
253
|
+
if (type.isMappedType()) {
|
|
254
|
+
return () => [type.getConstraintType(), type.getNameType(), type.getTemplateType()];
|
|
255
|
+
}
|
|
256
|
+
if (type.isIndexedAccessType()) {
|
|
257
|
+
return () => [type.getObjectType(), type.getIndexType()];
|
|
258
|
+
}
|
|
259
|
+
if (type.isIndexType() || type.isStringMappingType()) {
|
|
260
|
+
return () => [type.getTarget()];
|
|
261
|
+
}
|
|
262
|
+
if (type.isTemplateLiteralType()) {
|
|
263
|
+
return () => type.getTypes();
|
|
264
|
+
}
|
|
265
|
+
if (type.isSubstitutionType()) {
|
|
266
|
+
return () => [type.getBaseType(), type.getConstraint()];
|
|
267
|
+
}
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
|
|
226
271
|
/**
|
|
227
272
|
* The guarded questions over one project's checker. `configFile` names the project
|
|
228
273
|
* in the log, `batch` sends many questions in one round trip, `log` is the run's,
|
|
@@ -528,12 +573,48 @@ export function queriesOf(
|
|
|
528
573
|
() => ({ object: type.getObjectType(), index: type.getIndexType() }),
|
|
529
574
|
)
|
|
530
575
|
: undefined,
|
|
576
|
+
partsOf: (type) => {
|
|
577
|
+
const parts = partQuestion(type);
|
|
578
|
+
return parts === undefined
|
|
579
|
+
? []
|
|
580
|
+
: one(
|
|
581
|
+
"getParts",
|
|
582
|
+
() => typeLocation(type),
|
|
583
|
+
() => parts().filter((part) => part !== undefined),
|
|
584
|
+
);
|
|
585
|
+
},
|
|
586
|
+
signaturePartsOf: (signature) =>
|
|
587
|
+
one(
|
|
588
|
+
"getSignatureParts",
|
|
589
|
+
() => `signature ${String(signature.id)}`,
|
|
590
|
+
() => {
|
|
591
|
+
const self =
|
|
592
|
+
signature.thisParameter === undefined ? undefined : signature.getThisParameter();
|
|
593
|
+
return [
|
|
594
|
+
...((signature.typeParameters ?? []).length === 0 ? [] : signature.getTypeParameters()),
|
|
595
|
+
self === undefined ? undefined : checker.getTypeOfSymbol(self),
|
|
596
|
+
checker.getTypePredicateOfSignature(signature)?.type,
|
|
597
|
+
].filter((part) => part !== undefined);
|
|
598
|
+
},
|
|
599
|
+
),
|
|
531
600
|
symbolOfType: (type) =>
|
|
532
601
|
one(
|
|
533
602
|
"getSymbol",
|
|
534
603
|
() => typeLocation(type),
|
|
535
604
|
() => type.getSymbol(),
|
|
536
605
|
),
|
|
606
|
+
aliasSymbolOf: (type) =>
|
|
607
|
+
one(
|
|
608
|
+
"getAliasSymbol",
|
|
609
|
+
() => typeLocation(type),
|
|
610
|
+
() => type.getAliasSymbol(),
|
|
611
|
+
),
|
|
612
|
+
aliasArgumentsOf: (type) =>
|
|
613
|
+
one(
|
|
614
|
+
"getAliasTypeArguments",
|
|
615
|
+
() => typeLocation(type),
|
|
616
|
+
() => type.getAliasTypeArguments(),
|
|
617
|
+
),
|
|
537
618
|
signaturesOf: (type, kind) =>
|
|
538
619
|
one(
|
|
539
620
|
"getSignaturesOfType",
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Node, SourceFile } from "@typescript/native/ast";
|
|
2
|
+
import type { Type } from "@typescript/native/sync";
|
|
3
|
+
import type { AliasChains } from "../alias-chain.ts";
|
|
4
|
+
import type { Inventory } from "../inventory.ts";
|
|
5
|
+
import type { Position } from "../position.ts";
|
|
6
|
+
import type { Resolution } from "../references.ts";
|
|
7
|
+
import type { ProjectView } from "../session.ts";
|
|
8
|
+
|
|
9
|
+
/** Where the walk offered a read rule one node: the file, and the declaration enclosing the node. */
|
|
10
|
+
interface ReadSite {
|
|
11
|
+
readonly file: SourceFile;
|
|
12
|
+
readonly from: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** What a read rule reads its answers through, after the walk of every file of the side. */
|
|
16
|
+
export interface ReadContext<Brand> {
|
|
17
|
+
readonly project: ProjectView<Brand>;
|
|
18
|
+
readonly held: Inventory;
|
|
19
|
+
readonly chains: AliasChains;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* One read a rule makes: a use of the declaration `to` by `from` at a node of a walked file,
|
|
24
|
+
* or, where a question the read needed went unanswered, a hold. A hold names what the answer
|
|
25
|
+
* could have made live (program.33): the declarations `ids`, each declaration bearing one of
|
|
26
|
+
* `names`, each member of one of `types`, or with `members` every member the inventory holds;
|
|
27
|
+
* the declaration making the read is held as well. A named read sits at a node of `file`, or
|
|
28
|
+
* at a declaration's own position in it.
|
|
29
|
+
*/
|
|
30
|
+
export type Read =
|
|
31
|
+
| {
|
|
32
|
+
readonly kind: "named";
|
|
33
|
+
readonly from: string;
|
|
34
|
+
readonly to: string;
|
|
35
|
+
readonly file: SourceFile;
|
|
36
|
+
readonly at: Node | Position;
|
|
37
|
+
readonly use: "read" | "write";
|
|
38
|
+
readonly via: Resolution;
|
|
39
|
+
/** A read a rule counts as production code's whoever writes it. */
|
|
40
|
+
readonly production?: true;
|
|
41
|
+
}
|
|
42
|
+
| {
|
|
43
|
+
readonly kind: "held";
|
|
44
|
+
readonly from: string;
|
|
45
|
+
readonly ids?: readonly string[];
|
|
46
|
+
readonly names?: readonly string[];
|
|
47
|
+
readonly types?: readonly Type[];
|
|
48
|
+
readonly members?: true;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** One pass of one read rule over the files of one side: it collects while the walk offers nodes, then reads. */
|
|
52
|
+
interface ReadRuleRun {
|
|
53
|
+
visit(node: Node, site: ReadSite): void;
|
|
54
|
+
reads<Brand>(context: ReadContext<Brand>): readonly Read[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** One rule of the references pages that reads declarations no name node names. */
|
|
58
|
+
export interface ReadRule {
|
|
59
|
+
start(): ReadRuleRun;
|
|
60
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { elementAccess } from "../element-access.ts";
|
|
2
|
+
import { indexedAccess } from "../indexed-access.ts";
|
|
3
|
+
import { keyofComparisons } from "../keyof-comparisons.ts";
|
|
4
|
+
import { moduleDeclarations } from "../module-declarations.ts";
|
|
5
|
+
import { overrides } from "../overrides.ts";
|
|
6
|
+
import { isAnswered } from "../query.ts";
|
|
7
|
+
import { iteration } from "../symbol-keys.ts";
|
|
8
|
+
import { typeParameterReads } from "../type-parameter-reads.ts";
|
|
9
|
+
import { unimplementedCallees } from "../unimplemented-callees.ts";
|
|
10
|
+
import type { Read, ReadContext, ReadRule } from "./read-rule.ts";
|
|
11
|
+
|
|
12
|
+
/** The member kinds a hold of every member names. */
|
|
13
|
+
const MEMBER_KINDS: ReadonlySet<string> = new Set([
|
|
14
|
+
"method",
|
|
15
|
+
"class-member",
|
|
16
|
+
"interface-method",
|
|
17
|
+
"type-member",
|
|
18
|
+
"enum-member",
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Every read rule, each run over every side's walked files with the reference sources:
|
|
23
|
+
* a consumer's read of a target member is a reference as the target's own is.
|
|
24
|
+
*/
|
|
25
|
+
export const READ_RULES: readonly ReadRule[] = [
|
|
26
|
+
overrides,
|
|
27
|
+
indexedAccess,
|
|
28
|
+
elementAccess,
|
|
29
|
+
keyofComparisons,
|
|
30
|
+
iteration,
|
|
31
|
+
typeParameterReads,
|
|
32
|
+
unimplementedCallees,
|
|
33
|
+
moduleDeclarations,
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/** The declarations one hold names, with the declaration whose read it is. */
|
|
37
|
+
export function heldBy<Brand>(
|
|
38
|
+
read: Extract<Read, { kind: "held" }>,
|
|
39
|
+
{ project, held, chains }: ReadContext<Brand>,
|
|
40
|
+
): readonly string[] {
|
|
41
|
+
const ids = [...(read.from === "" ? [] : [read.from]), ...(read.ids ?? [])];
|
|
42
|
+
for (const name of read.names ?? []) {
|
|
43
|
+
ids.push(...(held.byName.get(name) ?? []));
|
|
44
|
+
}
|
|
45
|
+
for (const type of read.types ?? []) {
|
|
46
|
+
const properties = project.queries.propertiesOf(type);
|
|
47
|
+
for (const property of isAnswered(properties) ? properties : []) {
|
|
48
|
+
ids.push(...chains.declarationsOf(property));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (read.members === true) {
|
|
52
|
+
ids.push(...held.symbols.filter((one) => MEMBER_KINDS.has(one.kind)).map((one) => one.id));
|
|
53
|
+
}
|
|
54
|
+
return ids;
|
|
55
|
+
}
|