@cplieger/deadset-ts 7.2.0-dev.4 → 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 +245 -309
- package/dist/src/augmentations.js +124 -18
- package/dist/src/automatic-types.js +170 -0
- package/dist/src/build-scripts.js +425 -0
- package/dist/src/component-layer.js +4 -2
- package/dist/src/components.js +9 -9
- package/dist/src/config.js +6 -81
- package/dist/src/configuration-files.js +78 -188
- package/dist/src/configured-declarations.js +15 -20
- package/dist/src/conformance-record.js +2 -2
- 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 +146 -1
- package/dist/src/conventions.js +136 -70
- package/dist/src/decorator.js +21 -18
- package/dist/src/dependencies.js +280 -62
- package/dist/src/edges.js +38 -122
- package/dist/src/element-access.js +4 -6
- package/dist/src/entry-point-gaps.js +9 -18
- package/dist/src/entry-points.js +106 -21
- 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 +225 -63
- package/dist/src/findings/dependencies-and-module-machinery.js +72 -27
- package/dist/src/findings/emitters.js +6 -6
- package/dist/src/findings/interfaces.js +4 -5
- package/dist/src/findings/intra-function.js +53 -19
- package/dist/src/findings/non-code-artifacts.js +71 -39
- 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 +57 -28
- package/dist/src/findings/visibility-narrowing.js +40 -18
- 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 +18 -4
- package/dist/src/git-ignore.js +99 -0
- package/dist/src/graph.js +9 -4
- package/dist/src/html-entries.js +6 -33
- package/dist/src/import-bindings.js +97 -0
- package/dist/src/in-operands.js +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/indexed-access.js +130 -28
- package/dist/src/injection-container.js +1 -1
- package/dist/src/interface-satisfaction.js +30 -12
- package/dist/src/intra-function-parts.js +341 -69
- package/dist/src/inventory.js +54 -29
- 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} +88 -61
- package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +60 -59
- 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 +94 -13
- package/dist/src/mdx-entries.js +174 -0
- package/dist/src/module-declarations.js +9 -13
- package/dist/src/outside-tests.js +1 -1
- package/dist/src/overrides.js +41 -10
- 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 -78
- package/dist/src/product.js +13 -0
- package/dist/src/query.js +1 -0
- package/dist/src/ref.js +11 -0
- package/dist/src/references.js +52 -31
- package/dist/src/report-schema.js +51 -0
- package/dist/src/report.js +59 -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 -727
- package/dist/src/roots.js +374 -116
- package/dist/src/run.js +66 -77
- package/dist/src/schema.js +320 -342
- package/dist/src/scope.js +38 -115
- package/dist/src/serialization-contract.js +649 -29
- package/dist/src/session.js +41 -29
- package/dist/src/source-files.js +40 -15
- package/dist/src/suppress-file.js +34 -29
- package/dist/src/suppress-inline.js +21 -4
- package/dist/src/suppress.js +40 -56
- package/dist/src/sweep.js +32 -17
- package/dist/src/symbol-keys.js +105 -6
- package/dist/src/template-field.js +9 -19
- package/dist/src/test-support.js +119 -18
- 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 +27 -221
- package/dist/src/type-parameter-reads.js +172 -0
- 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 +181 -125
- package/dist/src/verbs/describe.js +9 -16
- package/dist/src/verbs/explain.js +14 -9
- 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 +128 -33
- package/jsr.json +1 -1
- package/package.json +5 -4
- package/src/analysis.ts +333 -457
- package/src/augmentations.ts +152 -23
- package/src/automatic-types.ts +228 -0
- package/src/build-scripts.ts +543 -0
- package/src/component-layer.ts +4 -2
- package/src/components.ts +9 -10
- package/src/config.ts +31 -299
- package/src/configuration-files.ts +100 -191
- package/src/configured-declarations.ts +18 -23
- package/src/conformance-record.ts +2 -2
- 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 +186 -1
- package/src/conventions.ts +166 -90
- package/src/decorator.ts +28 -18
- package/src/dependencies.ts +356 -78
- package/src/edges.ts +41 -140
- package/src/element-access.ts +4 -7
- package/src/entry-point-gaps.ts +11 -20
- package/src/entry-points.ts +124 -28
- 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 +24 -9
- package/src/findings/boundary.ts +2 -0
- package/src/findings/completion.ts +297 -77
- package/src/findings/dependencies-and-module-machinery.ts +90 -31
- package/src/findings/emitter.ts +8 -9
- package/src/findings/emitters.ts +8 -8
- package/src/findings/interfaces.ts +4 -6
- package/src/findings/intra-function.ts +64 -20
- package/src/findings/non-code-artifacts.ts +88 -50
- package/src/findings/reads-and-writes.ts +20 -16
- package/src/findings/self-check.ts +11 -17
- package/src/findings/unused-declarations.ts +65 -28
- package/src/findings/visibility-narrowing.ts +51 -19
- 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 +23 -4
- package/src/git-ignore.ts +122 -0
- package/src/graph.ts +11 -3
- package/src/host.ts +17 -14
- package/src/html-entries.ts +6 -33
- package/src/import-bindings.ts +128 -0
- package/src/in-operands.ts +2 -1
- package/src/index.ts +1 -1
- package/src/indexed-access.ts +152 -30
- package/src/injection-container.ts +1 -1
- package/src/interface-satisfaction.ts +33 -13
- package/src/intra-function-parts.ts +449 -85
- package/src/inventory.ts +73 -27
- 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} +127 -80
- package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +73 -64
- 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 +154 -18
- package/src/mdx-entries.ts +218 -0
- package/src/module-declarations.ts +11 -13
- package/src/outside-tests.ts +1 -1
- package/src/overrides.ts +51 -12
- package/src/partial.ts +3 -2
- package/src/paths.ts +27 -15
- package/src/position.ts +2 -1
- package/src/print.ts +12 -91
- package/src/product.ts +18 -0
- package/src/query.ts +11 -0
- package/src/ref.ts +13 -0
- package/src/references.ts +62 -32
- package/src/report-schema.ts +68 -0
- package/src/report.ts +105 -215
- 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 -1111
- package/src/roots.ts +490 -137
- package/src/run.ts +75 -91
- package/src/schema.ts +391 -387
- package/src/scope.ts +46 -138
- package/src/serialization-contract.ts +818 -26
- package/src/session.ts +77 -54
- package/src/source-files.ts +67 -17
- package/src/suppress-file.ts +36 -34
- package/src/suppress-inline.ts +20 -3
- package/src/suppress.ts +52 -63
- package/src/sweep.ts +53 -18
- package/src/symbol-keys.ts +131 -7
- package/src/template-field.ts +15 -25
- package/src/test-support.ts +155 -18
- 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 +35 -273
- package/src/type-parameter-reads.ts +227 -0
- package/src/unseen-loads.ts +134 -0
- package/src/unwrap.ts +34 -0
- package/src/usage.ts +10 -0
- package/src/verbs/analyze.ts +245 -161
- package/src/verbs/describe.ts +14 -15
- package/src/verbs/explain.ts +15 -13
- 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 +149 -34
- package/dist/src/discover.js +0 -347
- 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/discover.ts +0 -510
- 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
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The files the import declarations of the target's Markdown and MDX documents load. A
|
|
3
|
+
* document is read as text: a line outside a fenced code block that starts with `import`
|
|
4
|
+
* is an import declaration, which an MDX compiler hoists into the module it builds.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { SourceFile } from "@typescript/native/ast";
|
|
8
|
+
import { resolveRelativeSpecifier } from "./configuration-files.ts";
|
|
9
|
+
import type { Host } from "./host.ts";
|
|
10
|
+
import { dirnamePath, joinPath, resolvePath } from "./paths.ts";
|
|
11
|
+
import type { SourceFiles } from "./source-files.ts";
|
|
12
|
+
import { filesBelow } from "./fs/tree.ts";
|
|
13
|
+
|
|
14
|
+
/** One file a document imports, the specifier that named it, and the export names it reads. */
|
|
15
|
+
interface DocumentEntry {
|
|
16
|
+
readonly file: SourceFile;
|
|
17
|
+
readonly source: string;
|
|
18
|
+
/** The export names the import reads, or undefined for a namespace import, which reads them all. */
|
|
19
|
+
readonly names: readonly string[] | undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** The extensions of a document whose imports an MDX compiler reads. */
|
|
23
|
+
const DOCUMENT = /\.mdx?$/u;
|
|
24
|
+
|
|
25
|
+
/** A fence line, its marker run and what follows it captured. */
|
|
26
|
+
const FENCE = /^ {0,3}(`{3,}|~{3,})(.*)$/u;
|
|
27
|
+
|
|
28
|
+
/** A string literal in either quote, its escapes included. */
|
|
29
|
+
const STRING = String.raw`"(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'`;
|
|
30
|
+
|
|
31
|
+
/** An import declaration at the start of a line, its clause and its specifier captured. */
|
|
32
|
+
const IMPORT_LINE = new RegExp(
|
|
33
|
+
String.raw`^import\s+(?:((?:[^"'\n]|${STRING})*?)\s+from\s*)?["']([^"'\n]+)["']`,
|
|
34
|
+
"u",
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
/** The braces of an import clause, what they hold captured. */
|
|
38
|
+
const BRACES = new RegExp(String.raw`\{((?:[^}"']|${STRING})*)\}`, "u");
|
|
39
|
+
|
|
40
|
+
/** One comma-separated part of a clause's braces. */
|
|
41
|
+
const PART = new RegExp(String.raw`(?:[^,"']|${STRING})+`, "gu");
|
|
42
|
+
|
|
43
|
+
/** A named import of a clause's braces: the exported name and an optional local alias. */
|
|
44
|
+
const NAMED_IMPORT = new RegExp(String.raw`^([\w$]+|${STRING})(?:\s+as\s+[\w$]+)?$`, "u");
|
|
45
|
+
|
|
46
|
+
/** The single-character escapes of a string literal and the character each stands for. */
|
|
47
|
+
const SINGLE_ESCAPES: ReadonlyMap<string, string> = new Map([
|
|
48
|
+
["b", "\b"],
|
|
49
|
+
["f", "\f"],
|
|
50
|
+
["n", "\n"],
|
|
51
|
+
["r", "\r"],
|
|
52
|
+
["t", "\t"],
|
|
53
|
+
["v", "\v"],
|
|
54
|
+
["0", "\0"],
|
|
55
|
+
["'", "'"],
|
|
56
|
+
['"', '"'],
|
|
57
|
+
["\\", "\\"],
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* One escape of a string literal: two hexadecimal digits, a code unit, a code point, or one
|
|
62
|
+
* character and the digit after it.
|
|
63
|
+
*/
|
|
64
|
+
const ESCAPE = /\\(?:x([\da-fA-F]{2})|u([\da-fA-F]{4})|u\{([\da-fA-F]+)\}|(.)(\d?))/gu;
|
|
65
|
+
|
|
66
|
+
/** What one escape stands for, or undefined for one a module cannot hold. */
|
|
67
|
+
function unescaped([, hex, unit, point, single, digit]: RegExpExecArray): string | undefined {
|
|
68
|
+
if (single === undefined) {
|
|
69
|
+
const code = Number.parseInt(hex ?? unit ?? point ?? "", 16);
|
|
70
|
+
return code <= 0x10ffff ? String.fromCodePoint(code) : undefined;
|
|
71
|
+
}
|
|
72
|
+
return /[1-9xu]/u.test(single) || (single === "0" && digit !== "")
|
|
73
|
+
? undefined
|
|
74
|
+
: `${SINGLE_ESCAPES.get(single) ?? single}${digit ?? ""}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The value of a quoted export name, its escapes decoded, or undefined for an escape this
|
|
79
|
+
* reading does not decode. A module is strict code, so no legacy octal escape is valid.
|
|
80
|
+
*/
|
|
81
|
+
function quotedName(literal: string): string | undefined {
|
|
82
|
+
const body = literal.slice(1, -1);
|
|
83
|
+
let value = "";
|
|
84
|
+
let from = 0;
|
|
85
|
+
for (const escape of body.matchAll(ESCAPE)) {
|
|
86
|
+
const decoded = unescaped(escape);
|
|
87
|
+
if (decoded === undefined) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
value += body.slice(from, escape.index) + decoded;
|
|
91
|
+
from = escape.index + escape[0].length;
|
|
92
|
+
}
|
|
93
|
+
return value + body.slice(from);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The export names one import clause reads: `default` for a default binding and each name
|
|
98
|
+
* its braces list, or undefined for a namespace import, which reads every export, and for
|
|
99
|
+
* a clause this reading does not parse, which may read any.
|
|
100
|
+
*/
|
|
101
|
+
function clauseNames(clause: string): readonly string[] | undefined {
|
|
102
|
+
const braces = BRACES.exec(clause);
|
|
103
|
+
const head = (braces === null ? clause : clause.slice(0, braces.index))
|
|
104
|
+
.replace(/,\s*$/u, "")
|
|
105
|
+
.trim();
|
|
106
|
+
if (head.includes("*")) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
const names = head === "" ? [] : ["default"];
|
|
110
|
+
if (head !== "" && !/^[\w$]+$/u.test(head)) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
for (const part of (braces?.[1]?.match(PART) ?? []).map((one) => one.trim())) {
|
|
114
|
+
const named = NAMED_IMPORT.exec(part);
|
|
115
|
+
if (part === "") {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (named?.[1] === undefined) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
const name = /^["']/u.test(named[1]) ? quotedName(named[1]) : named[1];
|
|
122
|
+
if (name === undefined) {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
names.push(name);
|
|
126
|
+
}
|
|
127
|
+
return names;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** The relative specifiers one document's import lines name, its fenced code blocks skipped. */
|
|
131
|
+
function importedBy(
|
|
132
|
+
text: string,
|
|
133
|
+
): readonly { readonly specifier: string; readonly names: readonly string[] | undefined }[] {
|
|
134
|
+
const found: { specifier: string; names: readonly string[] | undefined }[] = [];
|
|
135
|
+
let open: string | undefined;
|
|
136
|
+
for (const line of text.split(/\r?\n/u)) {
|
|
137
|
+
const fence = FENCE.exec(line);
|
|
138
|
+
const marker = fence?.[1];
|
|
139
|
+
if (marker !== undefined && open === undefined) {
|
|
140
|
+
open = marker;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// https://spec.commonmark.org/0.31.2/#fenced-code-blocks: only a run of the opening
|
|
144
|
+
// character, at least as long and followed by nothing, closes a fence.
|
|
145
|
+
if (
|
|
146
|
+
marker !== undefined &&
|
|
147
|
+
open !== undefined &&
|
|
148
|
+
marker.startsWith(open.slice(0, 1)) &&
|
|
149
|
+
marker.length >= open.length &&
|
|
150
|
+
fence?.[2]?.trim() === ""
|
|
151
|
+
) {
|
|
152
|
+
open = undefined;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const matched = open === undefined ? IMPORT_LINE.exec(line) : null;
|
|
156
|
+
const specifier = matched?.[2];
|
|
157
|
+
if (specifier?.startsWith("./") === true || specifier?.startsWith("../") === true) {
|
|
158
|
+
found.push({ specifier, names: clauseNames(matched?.[1] ?? "") });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return found;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** One document below a target root, by absolute path, and what its import lines name. */
|
|
165
|
+
interface DocumentImports {
|
|
166
|
+
readonly path: string;
|
|
167
|
+
readonly imports: ReturnType<typeof importedBy>;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* The documents each host's target roots hold, which every project of a run reads alike,
|
|
172
|
+
* kept for the host's life as {@link Host} allows.
|
|
173
|
+
*/
|
|
174
|
+
const documentsOf = new WeakMap<Host, Map<string, readonly DocumentImports[]>>();
|
|
175
|
+
|
|
176
|
+
/** Every readable document below `root` and the import lines it writes, read once per host. */
|
|
177
|
+
function documentImports(host: Host, root: string): readonly DocumentImports[] {
|
|
178
|
+
const byRoot = documentsOf.get(host) ?? new Map<string, readonly DocumentImports[]>();
|
|
179
|
+
documentsOf.set(host, byRoot);
|
|
180
|
+
const known = byRoot.get(root);
|
|
181
|
+
if (known !== undefined) {
|
|
182
|
+
return known;
|
|
183
|
+
}
|
|
184
|
+
const found = filesBelow(host, root, (name) => DOCUMENT.test(name)).flatMap((below) => {
|
|
185
|
+
const path = joinPath(root, below);
|
|
186
|
+
try {
|
|
187
|
+
return [{ path, imports: importedBy(host.readFile(path)) }];
|
|
188
|
+
} catch {
|
|
189
|
+
return [];
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
byRoot.set(root, found);
|
|
193
|
+
return found;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Every own file one document below the target root imports by a relative specifier,
|
|
198
|
+
* read against the document's directory, on disk or through the emit mapping.
|
|
199
|
+
*/
|
|
200
|
+
export function documentEntries(
|
|
201
|
+
host: Host,
|
|
202
|
+
targetRoot: string,
|
|
203
|
+
files: SourceFiles,
|
|
204
|
+
): readonly DocumentEntry[] {
|
|
205
|
+
const root = resolvePath(host.workingDirectory(), targetRoot);
|
|
206
|
+
const found: DocumentEntry[] = [];
|
|
207
|
+
for (const { path, imports } of documentImports(host, root)) {
|
|
208
|
+
const dir = dirnamePath(path);
|
|
209
|
+
for (const { specifier, names } of imports) {
|
|
210
|
+
const reached = resolveRelativeSpecifier(host, dir, specifier);
|
|
211
|
+
const held = reached === undefined ? undefined : files.byName.get(reached);
|
|
212
|
+
for (const file of held === undefined ? files.named(resolvePath(dir, specifier)) : [held]) {
|
|
213
|
+
found.push({ file, source: specifier, names });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return found;
|
|
218
|
+
}
|
|
@@ -104,6 +104,8 @@ function namesModule(specifier: string, name: string): boolean {
|
|
|
104
104
|
interface Named {
|
|
105
105
|
readonly id: string;
|
|
106
106
|
readonly members: readonly string[];
|
|
107
|
+
/** Whether the declaration's name is a pattern, which a specifier names by matching it. */
|
|
108
|
+
readonly wildcard: boolean;
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
/**
|
|
@@ -140,7 +142,7 @@ function namedBy(
|
|
|
140
142
|
]),
|
|
141
143
|
);
|
|
142
144
|
const members = (children.get(id) ?? []).filter((child) => wanted.has(child.ref));
|
|
143
|
-
return [{ id, members: members.map((child) => child.id) }];
|
|
145
|
+
return [{ id, members: members.map((child) => child.id), wildcard: name.includes("*") }];
|
|
144
146
|
});
|
|
145
147
|
}
|
|
146
148
|
|
|
@@ -208,28 +210,24 @@ export function moduleDeclarationReferences<Brand>(
|
|
|
208
210
|
imports.forEach((one, index) => {
|
|
209
211
|
const resolved = moduleOf(declared.length + index);
|
|
210
212
|
const position = renderPosition(one.file, root, one.specifier.getStart());
|
|
211
|
-
const read = (to: string, resolution: Reference["resolution"]): void => {
|
|
212
|
-
found.push({
|
|
213
|
-
from: one.from,
|
|
214
|
-
to,
|
|
215
|
-
position,
|
|
216
|
-
use: "read",
|
|
217
|
-
resolution,
|
|
218
|
-
test: testFiles.has(position.path),
|
|
219
|
-
});
|
|
213
|
+
const read = (to: string, resolution: Reference["resolution"], test: boolean): void => {
|
|
214
|
+
found.push({ from: one.from, to, position, use: "read", resolution, test });
|
|
220
215
|
};
|
|
216
|
+
const test = testFiles.has(position.path);
|
|
221
217
|
const same = new Set(
|
|
222
218
|
declared
|
|
223
219
|
.filter((_, at) => resolved !== undefined && resolved === moduleOf(at))
|
|
224
220
|
.map((declaration) => declaration.id),
|
|
225
221
|
);
|
|
226
222
|
for (const id of same) {
|
|
227
|
-
read(id, "batch");
|
|
223
|
+
read(id, "batch", test);
|
|
228
224
|
}
|
|
229
225
|
for (const declaration of named(one.specifier.text, one.names)) {
|
|
230
|
-
|
|
226
|
+
// A wildcard declaration is how the compiler types the file a matching specifier
|
|
227
|
+
// names, so the import uses it whoever writes it, a test included.
|
|
228
|
+
if (declaration.wildcard || !same.has(declaration.id)) {
|
|
231
229
|
for (const to of [declaration.id, ...declaration.members]) {
|
|
232
|
-
read(to, "syntax");
|
|
230
|
+
read(to, "syntax", test && !declaration.wildcard);
|
|
233
231
|
}
|
|
234
232
|
}
|
|
235
233
|
}
|
package/src/outside-tests.ts
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
type SourceFile,
|
|
21
21
|
} from "@typescript/native/ast";
|
|
22
22
|
import { RESOLVED_EXTENSIONS, type ParseFile } from "./configuration-files.ts";
|
|
23
|
-
import { emittedFrom } from "./emit-map.ts";
|
|
23
|
+
import { emittedFrom } from "./load/emit-map.ts";
|
|
24
24
|
import type { Host } from "./host.ts";
|
|
25
25
|
import type { Inventory } from "./inventory.ts";
|
|
26
26
|
import { namesImported } from "./module-declarations.ts";
|
package/src/overrides.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The overrides of the target's class members. A call through the base class
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* through that class, so its own class references it.
|
|
2
|
+
* The overrides of the target's class members. A call through the base class runs the
|
|
3
|
+
* override of whichever subclass the value is, so the base member references every
|
|
4
|
+
* override. A member, static or not, overriding one of a class declared outside the target
|
|
5
|
+
* at any depth of its `extends` chain, a library's interface-and-variable class such as
|
|
6
|
+
* `Error` included, is used by outside code holding the value, so its own class references it.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
import {
|
|
@@ -115,12 +114,16 @@ export function overrideReferences<Brand>(
|
|
|
115
114
|
if (
|
|
116
115
|
inTarget.length === 0 &&
|
|
117
116
|
declared !== UNANSWERED &&
|
|
118
|
-
(declared.flags & SymbolFlags.Class) !== 0 &&
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
(((declared.flags & SymbolFlags.Class) !== 0 &&
|
|
118
|
+
// The target's augmentation of an outside class merges an interface into it,
|
|
119
|
+
// so only a class declaration says where the class is.
|
|
120
|
+
declared.declarations.some(
|
|
121
|
+
(handle) => CLASS_DECLARATIONS.has(handle.kind) && !own.has(handle.path),
|
|
122
|
+
)) ||
|
|
123
|
+
((declared.flags & SymbolFlags.Interface) !== 0 &&
|
|
124
|
+
declared.declarations.some(
|
|
125
|
+
(handle) => handle.kind === SyntaxKind.VariableDeclaration && !own.has(handle.path),
|
|
126
|
+
)))
|
|
124
127
|
) {
|
|
125
128
|
outsideBases.set(id, declared);
|
|
126
129
|
}
|
|
@@ -185,11 +188,13 @@ function outsideMemberNames<Brand>(
|
|
|
185
188
|
outsideBases: ReadonlyMap<string, TSSymbol>,
|
|
186
189
|
): ReadonlyMap<string, ReadonlySet<string>> {
|
|
187
190
|
const direct = new Map<string, ReadonlySet<string>>();
|
|
191
|
+
const error = errorType(project);
|
|
188
192
|
for (const [classId, base] of outsideBases) {
|
|
189
193
|
const instance = project.queries.declaredTypeOf(base);
|
|
190
194
|
const statics = project.queries.typeOfSymbol(base);
|
|
191
195
|
const components = [
|
|
192
196
|
...namesOf(project, instance === UNANSWERED ? undefined : instance).map(nameComponent),
|
|
197
|
+
...(instance !== UNANSWERED && reaches(project, instance, error) ? ["toString"] : []),
|
|
193
198
|
...namesOf(project, statics === UNANSWERED ? undefined : statics).map(
|
|
194
199
|
(name) => `${nameComponent(name)}:static`,
|
|
195
200
|
),
|
|
@@ -218,6 +223,40 @@ function outsideMemberNames<Brand>(
|
|
|
218
223
|
return names;
|
|
219
224
|
}
|
|
220
225
|
|
|
226
|
+
/** The global `Error` instance type's identifier, where the program's library declares one. */
|
|
227
|
+
function errorType<Brand>(project: ProjectView<Brand>): number | undefined {
|
|
228
|
+
const symbol = project.queries.resolveName("Error", SymbolFlags.Type, undefined, false);
|
|
229
|
+
if (symbol === UNANSWERED || symbol === undefined) {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
const type = project.queries.declaredTypeOf(symbol);
|
|
233
|
+
return type === UNANSWERED ? undefined : type.id;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Whether one type is the `Error` instance type or extends it at any depth: the runtime
|
|
238
|
+
* prints an error through its `toString`, a member the library's `Error` interface omits.
|
|
239
|
+
*/
|
|
240
|
+
function reaches<Brand>(
|
|
241
|
+
project: ProjectView<Brand>,
|
|
242
|
+
type: Type,
|
|
243
|
+
target: number | undefined,
|
|
244
|
+
): boolean {
|
|
245
|
+
const seen = new Set<number>();
|
|
246
|
+
const pending = [type];
|
|
247
|
+
for (let next = pending.pop(); next !== undefined; next = pending.pop()) {
|
|
248
|
+
if (next.id === target) {
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
if (!seen.has(next.id)) {
|
|
252
|
+
seen.add(next.id);
|
|
253
|
+
const bases = project.queries.baseTypes(next);
|
|
254
|
+
pending.push(...(bases === UNANSWERED ? [] : bases));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
|
|
221
260
|
/** The names of a type's properties; none where the type or its properties are unanswered. */
|
|
222
261
|
function namesOf<Brand>(project: ProjectView<Brand>, type: Type | undefined): readonly string[] {
|
|
223
262
|
const properties = type === undefined ? UNANSWERED : project.queries.propertiesOf(type);
|
package/src/partial.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { NotBuilt } from "./discover.ts";
|
|
1
|
+
import type { NotBuilt } from "./load/discover.ts";
|
|
2
2
|
import { relativePath } from "./paths.ts";
|
|
3
3
|
import type { UnansweredQuestion } from "./query.ts";
|
|
4
|
+
import { bytewise } from "./text/compare.ts";
|
|
4
5
|
|
|
5
6
|
/** What a run read only in part. */
|
|
6
7
|
interface Partial {
|
|
@@ -24,7 +25,7 @@ function counted(n: number, one: string, many: string): string {
|
|
|
24
25
|
*/
|
|
25
26
|
export function partialNotes(partial: Partial): readonly string[] {
|
|
26
27
|
const notes = [...partial.notBuilt]
|
|
27
|
-
.sort((a, b) => (a.id
|
|
28
|
+
.sort((a, b) => bytewise(a.id, b.id))
|
|
28
29
|
.map(
|
|
29
30
|
(one) =>
|
|
30
31
|
`the derived configuration ${one.id} was not built and is not analyzed: ${one.error}`,
|
package/src/paths.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Filesystem paths
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* They are written here rather than taken from the platform's own library because
|
|
6
|
-
* every module below the command line stays free of the platform, and because the
|
|
7
|
-
* supported platform set is one, so a second spelling would be a rule nothing
|
|
8
|
-
* exercises.
|
|
2
|
+
* Filesystem paths as the supported platform spells them: a solidus between segments, a
|
|
3
|
+
* leading one for an absolute path. They are written here rather than taken from the
|
|
4
|
+
* platform's library so every module below the command line stays free of the platform.
|
|
9
5
|
*/
|
|
10
6
|
|
|
11
7
|
const SEPARATOR = "/";
|
|
@@ -67,6 +63,25 @@ export function dirnamePath(path: string): string {
|
|
|
67
63
|
return cut === 0 ? SEPARATOR : normalized.slice(0, cut);
|
|
68
64
|
}
|
|
69
65
|
|
|
66
|
+
/**
|
|
67
|
+
* `dir` and every directory above it, nearest first, normalized. With `top`, the list ends
|
|
68
|
+
* at `top` and is empty where `dir` is neither `top` nor below it; without, it ends at the
|
|
69
|
+
* root of the path.
|
|
70
|
+
*/
|
|
71
|
+
export function ancestors(dir: string, top?: string): readonly string[] {
|
|
72
|
+
const end = top === undefined ? undefined : normalizePath(top);
|
|
73
|
+
const found: string[] = [];
|
|
74
|
+
for (let at = normalizePath(dir); ; at = dirnamePath(at)) {
|
|
75
|
+
if (end !== undefined && at !== end && relativePath(end, at) === undefined) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
found.push(at);
|
|
79
|
+
if (at === end || dirnamePath(at) === at) {
|
|
80
|
+
return found;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
70
85
|
/**
|
|
71
86
|
* The extension of one path's last segment, from its last full stop, or the empty string
|
|
72
87
|
* where it has none. A segment that only starts with a full stop has none.
|
|
@@ -101,14 +116,11 @@ export function queriedModulePath(specifier: string): string | undefined {
|
|
|
101
116
|
}
|
|
102
117
|
|
|
103
118
|
/**
|
|
104
|
-
* One path as it reads below a root, or undefined when it is not below the root
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* The caller resolves both against the same directory before calling: a relative
|
|
111
|
-
* root and an absolute path are two spellings this cannot reconcile.
|
|
119
|
+
* One path as it reads below a root, or undefined when it is not strictly below the root:
|
|
120
|
+
* the root itself is not below itself. Both are normalized, then compared lexically, so a
|
|
121
|
+
* root and a path spelled through different symbolic links name nothing in common. The
|
|
122
|
+
* caller resolves both against the same directory first: a relative root and an absolute
|
|
123
|
+
* path cannot be reconciled.
|
|
112
124
|
*/
|
|
113
125
|
export function relativePath(root: string, path: string): string | undefined {
|
|
114
126
|
const at = normalizePath(root);
|
package/src/position.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SourceFile } from "@typescript/native/ast";
|
|
2
2
|
import { relativePath } from "./paths.ts";
|
|
3
|
+
import { bytewise } from "./text/compare.ts";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Where one declaration is written, as every report renders it.
|
|
@@ -87,7 +88,7 @@ export function positionKey(position: Position): string {
|
|
|
87
88
|
*/
|
|
88
89
|
export function byPosition(a: Position, b: Position): number {
|
|
89
90
|
if (a.path !== b.path) {
|
|
90
|
-
return a.path
|
|
91
|
+
return bytewise(a.path, b.path);
|
|
91
92
|
}
|
|
92
93
|
if (a.line !== b.line) {
|
|
93
94
|
return a.line - b.line;
|
package/src/print.ts
CHANGED
|
@@ -1,95 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
type Config,
|
|
4
|
-
type DeclarationEntry,
|
|
5
|
-
type Provenance,
|
|
6
|
-
type Provider,
|
|
7
|
-
} from "./config.ts";
|
|
8
|
-
|
|
9
|
-
/** One declaration entry as a document writes it: the members of its shape alone. */
|
|
10
|
-
function declarationOf(entry: DeclarationEntry): Record<string, string> {
|
|
11
|
-
switch (entry.shape) {
|
|
12
|
-
case "symbol":
|
|
13
|
-
return { symbol: entry.symbol };
|
|
14
|
-
case "module":
|
|
15
|
-
return { module: entry.module, name: entry.name };
|
|
16
|
-
case "global":
|
|
17
|
-
return { global: entry.global };
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** One provider entry as a document writes it: the members of its shape alone. */
|
|
22
|
-
function providerOf(entry: Provider): Record<string, unknown> {
|
|
23
|
-
const installed = { name: entry.name, languages: entry.languages, command: entry.command };
|
|
24
|
-
if (entry.shape === "installed") {
|
|
25
|
-
return installed;
|
|
26
|
-
}
|
|
27
|
-
return { ...installed, source: entry.source, version: entry.version, digest: entry.digest };
|
|
28
|
-
}
|
|
1
|
+
import { renderOrigin, type Provenance, type ResolvedConfig } from "./config.ts";
|
|
2
|
+
import { bytewise } from "./text/compare.ts";
|
|
29
3
|
|
|
30
4
|
/**
|
|
31
|
-
* The resolved configuration and its provenance as one JSON object, indented,
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* object is a declared key resolution ignores. Keys are written in the schema's
|
|
37
|
-
* order and the severity and provenance objects in ascending key order, so one
|
|
38
|
-
* configuration renders to one string whatever order a source named its settings
|
|
39
|
-
* in.
|
|
5
|
+
* The resolved configuration and its provenance as one JSON object, indented, ending
|
|
6
|
+
* in a newline: the configuration in the order resolution gives it, then the provenance
|
|
7
|
+
* object in ascending key order. Read back as a repository configuration it resolves to
|
|
8
|
+
* the same configuration, because resolution checks the provenance object and then
|
|
9
|
+
* ignores it.
|
|
40
10
|
*/
|
|
41
|
-
export function printConfig(config:
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
languages: config.analysis.languages,
|
|
47
|
-
min_confidence: config.analysis.minConfidence,
|
|
48
|
-
generated_files: config.analysis.generatedFiles,
|
|
49
|
-
consumer_tests: config.analysis.consumerTests,
|
|
50
|
-
configurations: config.analysis.configurations.map((entry) =>
|
|
51
|
-
entry.shape === "project"
|
|
52
|
-
? { id: entry.id, project: entry.project }
|
|
53
|
-
: { id: entry.id, os: entry.os, arch: entry.arch, tags: entry.tags },
|
|
54
|
-
),
|
|
55
|
-
matrix: { complete: config.analysis.matrixComplete },
|
|
56
|
-
template_dirs: config.analysis.templateDirs,
|
|
57
|
-
template_delimiters: {
|
|
58
|
-
left: config.analysis.templateDelimiters.left,
|
|
59
|
-
right: config.analysis.templateDelimiters.right,
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
consumers: { complete: config.consumersComplete },
|
|
63
|
-
roots: { patterns: config.rootPatterns },
|
|
64
|
-
severity: Object.fromEntries([...config.severity].sort(([a], [b]) => (a < b ? -1 : 1))),
|
|
65
|
-
exemptions: { disabled: config.exemptionsDisabled },
|
|
66
|
-
reporters: {
|
|
67
|
-
formats: config.reporters.formats,
|
|
68
|
-
sort: config.reporters.sort,
|
|
69
|
-
cascade: config.reporters.cascade,
|
|
70
|
-
max_findings: config.reporters.maxFindings,
|
|
71
|
-
fail_on: config.reporters.failOn,
|
|
72
|
-
},
|
|
73
|
-
providers: { analyzers: config.providers.analyzers.map(providerOf) },
|
|
74
|
-
go: {},
|
|
75
|
-
ts: {
|
|
76
|
-
test_files: config.ts.testFiles,
|
|
77
|
-
entry_files: config.ts.entryFiles,
|
|
78
|
-
component_extensions: config.ts.componentExtensions,
|
|
79
|
-
disabled_conventions: config.ts.disabledConventions,
|
|
80
|
-
injection_registrations: config.ts.injectionRegistrations.map(declarationOf),
|
|
81
|
-
lifecycle_contracts: config.ts.lifecycleContracts.map((entry) => ({
|
|
82
|
-
components: entry.components.map(declarationOf),
|
|
83
|
-
bases: entry.bases.map(declarationOf),
|
|
84
|
-
members: entry.members,
|
|
85
|
-
})),
|
|
86
|
-
serializers: config.ts.serializers.map(declarationOf),
|
|
87
|
-
},
|
|
88
|
-
provenance: Object.fromEntries(
|
|
89
|
-
[...provenance]
|
|
90
|
-
.sort(([a], [b]) => (a < b ? -1 : 1))
|
|
91
|
-
.map(([path, origin]) => [path, renderOrigin(origin)]),
|
|
92
|
-
),
|
|
93
|
-
};
|
|
94
|
-
return `${JSON.stringify(document, undefined, 2)}\n`;
|
|
11
|
+
export function printConfig(config: ResolvedConfig, provenance: Provenance): string {
|
|
12
|
+
const origins = [...provenance]
|
|
13
|
+
.sort(([a], [b]) => bytewise(a, b))
|
|
14
|
+
.map(([path, origin]): [string, string] => [path, renderOrigin(origin)]);
|
|
15
|
+
return `${JSON.stringify({ ...config, provenance: Object.fromEntries(origins) }, undefined, 2)}\n`;
|
|
95
16
|
}
|
package/src/product.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { LANGUAGE_ROWS } from "./contract/contract.generated.ts";
|
|
2
|
+
import type { Writer } from "./run.ts";
|
|
3
|
+
|
|
4
|
+
/** The language this analyzer reads. */
|
|
5
|
+
export const LANGUAGE = "ts";
|
|
6
|
+
|
|
7
|
+
/** The analyzer's name: the one its language's row names, which every output spells it with. */
|
|
8
|
+
export const PRODUCT = LANGUAGE_ROWS[LANGUAGE].analyzer;
|
|
9
|
+
|
|
10
|
+
/** Writes one diagnostic line to the error stream, named for the analyzer. */
|
|
11
|
+
export function diagnose(err: Writer, text: string): void {
|
|
12
|
+
err.write(`${PRODUCT}: ${text}\n`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** The text one thrown value carries. */
|
|
16
|
+
export function message(error: unknown): string {
|
|
17
|
+
return error instanceof Error ? error.message : String(error);
|
|
18
|
+
}
|
package/src/query.ts
CHANGED
|
@@ -211,6 +211,8 @@ export interface Queries {
|
|
|
211
211
|
symbolOfType(type: Type): Answer<TSSymbol | undefined>;
|
|
212
212
|
signaturesOf(type: Type, kind: SignatureKind): Answer<readonly Signature[]>;
|
|
213
213
|
resolvedSignature(node: Node): Answer<Signature | undefined>;
|
|
214
|
+
/** The signature each call-like node resolves to. */
|
|
215
|
+
resolvedSignatures(nodes: readonly Node[], cap?: number): Answer<Signature | undefined>[];
|
|
214
216
|
parameterType(signature: Signature, index: number): Answer<Type | undefined>;
|
|
215
217
|
/** The generic signature an instantiated one instantiates; none for another signature. */
|
|
216
218
|
genericOf(signature: Signature): Answer<Signature | undefined>;
|
|
@@ -544,6 +546,15 @@ export function queriesOf(
|
|
|
544
546
|
() => nodeLocation(node),
|
|
545
547
|
() => checker.getResolvedSignature(node),
|
|
546
548
|
),
|
|
549
|
+
resolvedSignatures: (nodes, cap = DEFAULT_BATCH_CAP) =>
|
|
550
|
+
each(
|
|
551
|
+
"getResolvedSignature",
|
|
552
|
+
nodes,
|
|
553
|
+
cap,
|
|
554
|
+
nodeLocation,
|
|
555
|
+
(node) => checker.getResolvedSignature.gen(node),
|
|
556
|
+
(node) => checker.getResolvedSignature(node),
|
|
557
|
+
),
|
|
547
558
|
parameterType: (signature, index) =>
|
|
548
559
|
one(
|
|
549
560
|
"getParameterType",
|
package/src/ref.ts
CHANGED
|
@@ -49,9 +49,12 @@ export const REF_EXPRESSIONS: readonly string[] = [
|
|
|
49
49
|
`^${SCOPE}#$`,
|
|
50
50
|
`^${SCOPE}#${TS_HEAD}$`,
|
|
51
51
|
`^${SCOPE}#(?:${TS_QUOTED}\\.)?${TS_HEAD}:alias$`,
|
|
52
|
+
`^${SCOPE}#${TS_HEAD}:import$`,
|
|
52
53
|
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+$`,
|
|
53
54
|
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+:static$`,
|
|
55
|
+
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+\\.${TS_QUOTED}:case$`,
|
|
54
56
|
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})*(?::static)?<${TS_IDENT}>$`,
|
|
57
|
+
`^${SCOPE}#(?:${TS_HEAD}(?:\\.${TS_MEMBER})*(?::static)?)?\\(${TS_IDENT}\\)$`,
|
|
55
58
|
`^${MANIFEST_SCOPE}#${TS_PACKAGE}:(?:dependency|dev-dependency|peer-dependency)$`,
|
|
56
59
|
];
|
|
57
60
|
|
|
@@ -151,6 +154,16 @@ export function computedComponent(text: string): string {
|
|
|
151
154
|
return `[${text.replaceAll(ASCII_WHITESPACE, "")}]`;
|
|
152
155
|
}
|
|
153
156
|
|
|
157
|
+
/** The reference of an import binding, read against the reference of the module that holds it. */
|
|
158
|
+
export function importRef(moduleRef: string, name: string): string {
|
|
159
|
+
return `${moduleRef}${nameComponent(name)}:import`;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** The reference of a parameter, read against the reference of the declaration that holds it. */
|
|
163
|
+
export function parameterRef(holderRef: string, name: string): string {
|
|
164
|
+
return `${holderRef}(${name})`;
|
|
165
|
+
}
|
|
166
|
+
|
|
154
167
|
/** The fragment of an export alias, inside the `declare module` block named, if one is. */
|
|
155
168
|
export function aliasFragment(name: string, block?: string): string {
|
|
156
169
|
const head = block === undefined ? "" : `${quoted(block)}.`;
|