@cplieger/deadset-ts 7.2.0-dev.3 → 8.0.0-dev.1
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/bin/mapper-connection.js +7 -4
- package/dist/src/analysis.js +116 -16
- package/dist/src/augmentations.js +21 -8
- package/dist/src/automatic-types.js +189 -0
- package/dist/src/base-url.js +18 -0
- package/dist/src/component-files.js +96 -31
- package/dist/src/components.js +7 -6
- package/dist/src/config.js +1 -0
- package/dist/src/configuration-files.js +54 -15
- package/dist/src/configured-declarations.js +24 -2
- package/dist/src/conformance-record.js +2 -2
- package/dist/src/contextual-uses.js +26 -26
- package/dist/src/convention-rows.js +75 -0
- package/dist/src/conventions.js +101 -5
- package/dist/src/decorator.js +21 -18
- package/dist/src/dependencies.js +185 -30
- package/dist/src/destructuring.js +77 -2
- package/dist/src/discover.js +188 -85
- package/dist/src/edges.js +1 -1
- package/dist/src/entry-point-gaps.js +7 -10
- package/dist/src/entry-points.js +112 -11
- package/dist/src/findings/completion.js +116 -21
- package/dist/src/findings/dependencies-and-module-machinery.js +71 -25
- package/dist/src/findings/emitters.js +1 -1
- package/dist/src/findings/intra-function.js +44 -13
- package/dist/src/findings/non-code-artifacts.js +66 -33
- package/dist/src/findings/unused-declarations.js +21 -1
- package/dist/src/findings/visibility-narrowing.js +22 -3
- package/dist/src/generated-file.js +11 -0
- package/dist/src/git-ignore.js +86 -0
- package/dist/src/graph.js +4 -1
- package/dist/src/import-bindings.js +97 -0
- package/dist/src/indexed-access.js +130 -28
- package/dist/src/interface-satisfaction.js +30 -12
- package/dist/src/intra-function-parts.js +313 -50
- package/dist/src/inventory.js +63 -8
- package/dist/src/json-document.js +5 -5
- package/dist/src/kinds.js +13 -13
- package/dist/src/matrix.js +18 -9
- package/dist/src/mdx-entries.js +197 -0
- package/dist/src/module-declarations.js +9 -13
- package/dist/src/namespace-objects.js +28 -18
- package/dist/src/overrides.js +45 -9
- package/dist/src/paths.js +9 -0
- package/dist/src/print.js +1 -0
- package/dist/src/ref.js +10 -0
- package/dist/src/references.js +29 -13
- package/dist/src/reflective-lookup.js +8 -6
- package/dist/src/report.js +4 -2
- package/dist/src/reporters/template.js +22 -13
- package/dist/src/resolve.js +2 -0
- package/dist/src/roots.js +110 -38
- package/dist/src/schema.js +1 -0
- package/dist/src/serialization-contract.js +97 -20
- package/dist/src/session.js +26 -1
- package/dist/src/source-files.js +39 -14
- package/dist/src/spelled-names.js +58 -0
- package/dist/src/suppress-file.js +12 -4
- package/dist/src/suppress-inline.js +21 -3
- package/dist/src/suppress.js +7 -5
- package/dist/src/sweep.js +27 -10
- package/dist/src/symbol-keys.js +103 -2
- package/dist/src/template-field.js +9 -6
- package/dist/src/test-support.js +121 -17
- package/dist/src/type-errors.js +116 -35
- package/dist/src/type-parameter-reads.js +172 -0
- package/dist/src/value-reach.js +17 -5
- package/dist/src/verbs/analyze.js +19 -1
- package/dist/src/verbs/explain.js +4 -2
- package/dist/src/version-range.js +10 -5
- package/dist/src/version.js +1 -1
- package/dist/src/workflow-steps.js +119 -22
- package/dist/src/workspace-programs.js +7 -3
- package/dist/src/workspace-resolution.js +72 -13
- package/dist/src/workspace.js +1 -1
- package/jsr.json +1 -1
- package/package.json +2 -2
- package/src/analysis.ts +175 -16
- package/src/augmentations.ts +21 -10
- package/src/automatic-types.ts +246 -0
- package/src/base-url.ts +24 -0
- package/src/component-files.ts +116 -31
- package/src/components.ts +7 -6
- package/src/config.ts +3 -0
- package/src/configuration-files.ts +80 -18
- package/src/configured-declarations.ts +33 -4
- package/src/conformance-record.ts +2 -2
- package/src/contextual-uses.ts +27 -27
- package/src/convention-rows.ts +103 -0
- package/src/conventions.ts +121 -7
- package/src/decorator.ts +28 -18
- package/src/dependencies.ts +249 -43
- package/src/destructuring.ts +93 -2
- package/src/discover.ts +234 -86
- package/src/edges.ts +1 -1
- package/src/entry-point-gaps.ts +8 -11
- package/src/entry-points.ts +133 -11
- package/src/finding.ts +10 -0
- package/src/findings/completion.ts +147 -24
- package/src/findings/dependencies-and-module-machinery.ts +90 -28
- package/src/findings/emitters.ts +1 -1
- package/src/findings/intra-function.ts +56 -14
- package/src/findings/non-code-artifacts.ts +81 -41
- package/src/findings/unused-declarations.ts +25 -1
- package/src/findings/visibility-narrowing.ts +32 -3
- package/src/generated-file.ts +16 -0
- package/src/git-ignore.ts +98 -0
- package/src/graph.ts +6 -0
- package/src/host.ts +5 -9
- package/src/import-bindings.ts +128 -0
- package/src/indexed-access.ts +152 -30
- package/src/interface-satisfaction.ts +33 -13
- package/src/intra-function-parts.ts +415 -64
- package/src/inventory.ts +83 -7
- package/src/json-document.ts +7 -7
- package/src/kinds.ts +13 -13
- package/src/matrix.ts +32 -14
- package/src/mdx-entries.ts +241 -0
- package/src/module-declarations.ts +11 -13
- package/src/namespace-objects.ts +34 -21
- package/src/overrides.ts +56 -9
- package/src/paths.ts +10 -0
- package/src/print.ts +1 -0
- package/src/ref.ts +12 -0
- package/src/references.ts +38 -17
- package/src/reflective-lookup.ts +9 -7
- package/src/report.ts +16 -3
- package/src/reporters/template.ts +21 -13
- package/src/resolve.ts +3 -0
- package/src/roots.ts +163 -45
- package/src/schema.ts +1 -0
- package/src/serialization-contract.ts +108 -17
- package/src/session.ts +29 -1
- package/src/source-files.ts +66 -16
- package/src/spelled-names.ts +102 -0
- package/src/suppress-file.ts +14 -3
- package/src/suppress-inline.ts +21 -2
- package/src/suppress.ts +9 -5
- package/src/sweep.ts +32 -11
- package/src/symbol-keys.ts +129 -2
- package/src/template-field.ts +9 -6
- package/src/test-support.ts +149 -16
- package/src/type-errors.ts +132 -41
- package/src/type-parameter-reads.ts +227 -0
- package/src/value-reach.ts +19 -6
- package/src/verbs/analyze.ts +28 -1
- package/src/verbs/explain.ts +5 -2
- package/src/version-range.ts +10 -5
- package/src/version.ts +1 -1
- package/src/workflow-steps.ts +127 -22
- package/src/workspace-programs.ts +7 -3
- package/src/workspace-resolution.ts +86 -14
- package/src/workspace.ts +1 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Module namespace objects: the binding of a namespace import, the value an `await` of a
|
|
3
3
|
* dynamic `import()` produces, the first parameter of the first callback passed to `then`
|
|
4
|
-
* on one, and a
|
|
4
|
+
* on one, and a variable binding initialized with one of these. A use reads the exports it
|
|
5
5
|
* names and no other: a property access by name or by a literal index, or a destructured
|
|
6
6
|
* property, names one export, and any other use may read every export.
|
|
7
7
|
*/
|
|
8
|
-
import { isArrowFunction, isAwaitExpression,
|
|
8
|
+
import { isArrowFunction, isAwaitExpression, isCallExpression, isClassStaticBlockDeclaration, isElementAccessExpression, isExpressionStatement, isFunctionExpression, isFunctionLikeDeclaration, isIdentifier, isImportDeclaration, isModuleBlock, isNamespaceImport, isNoSubstitutionTemplateLiteral, isObjectBindingPattern, isParenthesizedExpression, isPropertyAccessExpression, isQualifiedName, isSourceFile, isStringLiteral, isVariableDeclaration, isVariableDeclarationList, isVariableStatement, isVoidExpression, NodeFlags, SyntaxKind, } from "@typescript/native/ast";
|
|
9
|
+
import { spellsNoBinding } from "./spelled-names.js";
|
|
9
10
|
function isLiteralText(node) {
|
|
10
11
|
return isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node);
|
|
11
12
|
}
|
|
@@ -25,21 +26,30 @@ function isLiteralImport(node) {
|
|
|
25
26
|
const [argument] = node.arguments;
|
|
26
27
|
return argument !== undefined && isLiteralText(argument);
|
|
27
28
|
}
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
/**
|
|
30
|
+
* The node the binding one declaration list declares is visible below: for `let` and
|
|
31
|
+
* `const`, the loop whose head declares it, or else the block or file its statement is
|
|
32
|
+
* in; for `var`, the function, namespace body, static block or file that holds it.
|
|
33
|
+
*/
|
|
34
|
+
function scopeOf(list) {
|
|
35
|
+
if ((list.flags & (NodeFlags.Let | NodeFlags.Const | NodeFlags.Using)) !== 0) {
|
|
36
|
+
return isVariableStatement(list.parent) ? list.parent.parent : list.parent;
|
|
37
|
+
}
|
|
38
|
+
let at = list.parent;
|
|
39
|
+
while (!isSourceFile(at) &&
|
|
40
|
+
!isFunctionLikeDeclaration(at) &&
|
|
41
|
+
!isModuleBlock(at) &&
|
|
42
|
+
!isClassStaticBlockDeclaration(at)) {
|
|
43
|
+
at = at.parent;
|
|
44
|
+
}
|
|
45
|
+
return at;
|
|
32
46
|
}
|
|
33
|
-
/** Every identifier below `scope` that spells `name
|
|
47
|
+
/** Every identifier below `scope` that spells `name` as a reference, other than `declared`. */
|
|
34
48
|
function occurrences(scope, name, declared) {
|
|
35
49
|
const found = [];
|
|
36
50
|
const visit = (node) => {
|
|
37
51
|
if (isIdentifier(node)) {
|
|
38
|
-
|
|
39
|
-
const member = (isPropertyAccessExpression(parent) && parent.name === node) ||
|
|
40
|
-
(isQualifiedName(parent) && parent.right === node) ||
|
|
41
|
-
(isBindingElement(parent) && parent.propertyName === node);
|
|
42
|
-
if (node !== declared && node.text === name && !member) {
|
|
52
|
+
if (node !== declared && node.text === name && !spellsNoBinding(node)) {
|
|
43
53
|
found.push(node);
|
|
44
54
|
}
|
|
45
55
|
return;
|
|
@@ -52,8 +62,8 @@ function occurrences(scope, name, declared) {
|
|
|
52
62
|
/**
|
|
53
63
|
* Every use of the namespace objects one file holds, keyed by the node the use is written
|
|
54
64
|
* at, that reads more than a name the checker resolves: an indexed read by a literal, and
|
|
55
|
-
* any use that may read every export. A shadowing declaration of a binding's
|
|
56
|
-
* its scope is read as the binding, which can only keep an export live.
|
|
65
|
+
* any use that may read every export. A use of a shadowing declaration of a binding's
|
|
66
|
+
* name inside its scope is read as a use of the binding, which can only keep an export live.
|
|
57
67
|
*/
|
|
58
68
|
export function namespaceUses(file) {
|
|
59
69
|
const uses = new Map();
|
|
@@ -92,11 +102,11 @@ export function namespaceUses(file) {
|
|
|
92
102
|
}
|
|
93
103
|
return;
|
|
94
104
|
}
|
|
105
|
+
// A binding that is not `const` is followed too: each assignment to it is an
|
|
106
|
+
// occurrence `value` cannot narrow, so a reassigned binding still reads every export.
|
|
95
107
|
const list = parent.parent;
|
|
96
|
-
if (isIdentifier(pattern) &&
|
|
97
|
-
|
|
98
|
-
(list.flags & NodeFlags.Const) !== 0) {
|
|
99
|
-
binding(pattern, scopeOf(parent), specifier, seen);
|
|
108
|
+
if (isIdentifier(pattern) && isVariableDeclarationList(list)) {
|
|
109
|
+
binding(pattern, scopeOf(list), specifier, seen);
|
|
100
110
|
return;
|
|
101
111
|
}
|
|
102
112
|
}
|
package/dist/src/overrides.js
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
|
import { isClassDeclaration, isClassExpression, isExpressionWithTypeArguments, isPropertyAccessExpression, isQualifiedName, SyntaxKind, } from "@typescript/native/ast";
|
|
10
9
|
import { memberComponent } from "./class-members.js";
|
|
@@ -12,6 +11,10 @@ import { nodeKey } from "./inventory.js";
|
|
|
12
11
|
import { SymbolFlags } from "@typescript/native/sync";
|
|
13
12
|
import { UNANSWERED } from "./query.js";
|
|
14
13
|
import { nameComponent } from "./ref.js";
|
|
14
|
+
const CLASS_DECLARATIONS = new Set([
|
|
15
|
+
SyntaxKind.ClassDeclaration,
|
|
16
|
+
SyntaxKind.ClassExpression,
|
|
17
|
+
]);
|
|
15
18
|
/** The member kinds a subclass overrides. */
|
|
16
19
|
const OVERRIDABLE = new Set(["method", "class-member"]);
|
|
17
20
|
/** The node naming the class one `extends` entry names. */
|
|
@@ -81,9 +84,12 @@ export function overrideReferences(project, held, chains, testFiles) {
|
|
|
81
84
|
const declared = (symbol.flags & SymbolFlags.Alias) === 0 ? symbol : project.queries.aliased(symbol);
|
|
82
85
|
if (inTarget.length === 0 &&
|
|
83
86
|
declared !== UNANSWERED &&
|
|
84
|
-
(declared.flags & SymbolFlags.Class) !== 0 &&
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
(((declared.flags & SymbolFlags.Class) !== 0 &&
|
|
88
|
+
// The target's augmentation of an outside class merges an interface into it,
|
|
89
|
+
// so only a class declaration says where the class is.
|
|
90
|
+
declared.declarations.some((handle) => CLASS_DECLARATIONS.has(handle.kind) && !own.has(handle.path))) ||
|
|
91
|
+
((declared.flags & SymbolFlags.Interface) !== 0 &&
|
|
92
|
+
declared.declarations.some((handle) => handle.kind === SyntaxKind.VariableDeclaration && !own.has(handle.path))))) {
|
|
87
93
|
outsideBases.set(id, declared);
|
|
88
94
|
}
|
|
89
95
|
}
|
|
@@ -140,11 +146,13 @@ export function overrideReferences(project, held, chains, testFiles) {
|
|
|
140
146
|
*/
|
|
141
147
|
function outsideMemberNames(project, bases, outsideBases) {
|
|
142
148
|
const direct = new Map();
|
|
149
|
+
const error = errorType(project);
|
|
143
150
|
for (const [classId, base] of outsideBases) {
|
|
144
151
|
const instance = project.queries.declaredTypeOf(base);
|
|
145
152
|
const statics = project.queries.typeOfSymbol(base);
|
|
146
153
|
const components = [
|
|
147
154
|
...namesOf(project, instance === UNANSWERED ? undefined : instance).map(nameComponent),
|
|
155
|
+
...(instance !== UNANSWERED && reaches(project, instance, error) ? ["toString"] : []),
|
|
148
156
|
...namesOf(project, statics === UNANSWERED ? undefined : statics).map((name) => `${nameComponent(name)}:static`),
|
|
149
157
|
];
|
|
150
158
|
if (components.length > 0) {
|
|
@@ -170,6 +178,34 @@ function outsideMemberNames(project, bases, outsideBases) {
|
|
|
170
178
|
}
|
|
171
179
|
return names;
|
|
172
180
|
}
|
|
181
|
+
/** The global `Error` instance type's identifier, where the program's library declares one. */
|
|
182
|
+
function errorType(project) {
|
|
183
|
+
const symbol = project.queries.resolveName("Error", SymbolFlags.Type, undefined, false);
|
|
184
|
+
if (symbol === UNANSWERED || symbol === undefined) {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
const type = project.queries.declaredTypeOf(symbol);
|
|
188
|
+
return type === UNANSWERED ? undefined : type.id;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Whether one type is the `Error` instance type or extends it at any depth: the runtime
|
|
192
|
+
* prints an error through its `toString`, a member the library's `Error` interface omits.
|
|
193
|
+
*/
|
|
194
|
+
function reaches(project, type, target) {
|
|
195
|
+
const seen = new Set();
|
|
196
|
+
const pending = [type];
|
|
197
|
+
for (let next = pending.pop(); next !== undefined; next = pending.pop()) {
|
|
198
|
+
if (next.id === target) {
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
if (!seen.has(next.id)) {
|
|
202
|
+
seen.add(next.id);
|
|
203
|
+
const bases = project.queries.baseTypes(next);
|
|
204
|
+
pending.push(...(bases === UNANSWERED ? [] : bases));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
173
209
|
/** The names of a type's properties; none where the type or its properties are unanswered. */
|
|
174
210
|
function namesOf(project, type) {
|
|
175
211
|
const properties = type === undefined ? UNANSWERED : project.queries.propertiesOf(type);
|
package/dist/src/paths.js
CHANGED
|
@@ -61,6 +61,15 @@ export function dirnamePath(path) {
|
|
|
61
61
|
}
|
|
62
62
|
return cut === 0 ? SEPARATOR : normalized.slice(0, cut);
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* The extension of one path's last segment, from its last full stop, or the empty string
|
|
66
|
+
* where it has none. A segment that only starts with a full stop has none.
|
|
67
|
+
*/
|
|
68
|
+
export function extensionOf(path) {
|
|
69
|
+
const name = path.slice(path.lastIndexOf(SEPARATOR) + 1);
|
|
70
|
+
const dot = name.lastIndexOf(".");
|
|
71
|
+
return dot <= 0 ? "" : name.slice(dot);
|
|
72
|
+
}
|
|
64
73
|
/** One path resolved against a directory, absolute where that directory is. */
|
|
65
74
|
export function resolvePath(against, path) {
|
|
66
75
|
return isAbsolutePath(path) ? normalizePath(path) : joinPath(against, path);
|
package/dist/src/print.js
CHANGED
|
@@ -73,6 +73,7 @@ export function printConfig(config, provenance) {
|
|
|
73
73
|
members: entry.members,
|
|
74
74
|
})),
|
|
75
75
|
serializers: config.ts.serializers.map(declarationOf),
|
|
76
|
+
roots_complete: config.ts.rootsComplete,
|
|
76
77
|
},
|
|
77
78
|
provenance: Object.fromEntries([...provenance]
|
|
78
79
|
.sort(([a], [b]) => (a < b ? -1 : 1))
|
package/dist/src/ref.js
CHANGED
|
@@ -45,9 +45,11 @@ export const REF_EXPRESSIONS = [
|
|
|
45
45
|
`^${SCOPE}#$`,
|
|
46
46
|
`^${SCOPE}#${TS_HEAD}$`,
|
|
47
47
|
`^${SCOPE}#(?:${TS_QUOTED}\\.)?${TS_HEAD}:alias$`,
|
|
48
|
+
`^${SCOPE}#${TS_HEAD}:import$`,
|
|
48
49
|
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+$`,
|
|
49
50
|
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+:static$`,
|
|
50
51
|
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})*(?::static)?<${TS_IDENT}>$`,
|
|
52
|
+
`^${SCOPE}#(?:${TS_HEAD}(?:\\.${TS_MEMBER})*(?::static)?)?\\(${TS_IDENT}\\)$`,
|
|
51
53
|
`^${MANIFEST_SCOPE}#${TS_PACKAGE}:(?:dependency|dev-dependency|peer-dependency)$`,
|
|
52
54
|
];
|
|
53
55
|
const REF_FORMS = REF_EXPRESSIONS.map((expression) => new RegExp(expression, "u"));
|
|
@@ -86,6 +88,14 @@ function quoted(name) {
|
|
|
86
88
|
export function computedComponent(text) {
|
|
87
89
|
return `[${text.replaceAll(ASCII_WHITESPACE, "")}]`;
|
|
88
90
|
}
|
|
91
|
+
/** The reference of an import binding, read against the reference of the module that holds it. */
|
|
92
|
+
export function importRef(moduleRef, name) {
|
|
93
|
+
return `${moduleRef}${nameComponent(name)}:import`;
|
|
94
|
+
}
|
|
95
|
+
/** The reference of a parameter, read against the reference of the declaration that holds it. */
|
|
96
|
+
export function parameterRef(holderRef, name) {
|
|
97
|
+
return `${holderRef}(${name})`;
|
|
98
|
+
}
|
|
89
99
|
/** The fragment of an export alias, inside the `declare module` block named, if one is. */
|
|
90
100
|
export function aliasFragment(name, block) {
|
|
91
101
|
const head = block === undefined ? "" : `${quoted(block)}.`;
|
package/dist/src/references.js
CHANGED
|
@@ -16,8 +16,9 @@ import { overrideReferences } from "./overrides.js";
|
|
|
16
16
|
import { dirnamePath, queriedModulePath, relativePath, resolvePath } from "./paths.js";
|
|
17
17
|
import { byPosition, isComponentFile, renderPosition } from "./position.js";
|
|
18
18
|
import { DEFAULT_BATCH_CAP, propertyTables, UNANSWERED } from "./query.js";
|
|
19
|
+
import { typeParameterReads } from "./type-parameter-reads.js";
|
|
19
20
|
import { typeQueryAliases } from "./type-query-alias.js";
|
|
20
|
-
import { computedKeyNames, keyNameOf, keyedUses } from "./symbol-keys.js";
|
|
21
|
+
import { computedKeyNames, iterationReferences, keyNameOf, keyedUses, } from "./symbol-keys.js";
|
|
21
22
|
import { handedOn, valuesOf } from "./value-flow.js";
|
|
22
23
|
/**
|
|
23
24
|
* The operators whose left side one assignment stores into. A compound assignment is
|
|
@@ -661,19 +662,29 @@ export function references(project, held, targetRoot, options) {
|
|
|
661
662
|
relativePath(targetRoot, file.fileName) === undefined);
|
|
662
663
|
const ownPaths = project.ownPaths();
|
|
663
664
|
const fileIds = new Set(held.symbols.filter((symbol) => symbol.kind === "file").map((symbol) => symbol.id));
|
|
664
|
-
let
|
|
665
|
-
/**
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
665
|
+
let moduleBodies;
|
|
666
|
+
/**
|
|
667
|
+
* The declarations one module holds directly: a file's top level, or the body of a
|
|
668
|
+
* `declare module` whose name is a string. Any other declaration holds none here.
|
|
669
|
+
*/
|
|
670
|
+
const declaredIn = (moduleId) => {
|
|
671
|
+
if (moduleBodies === undefined) {
|
|
672
|
+
const byModule = new Map();
|
|
669
673
|
for (const symbol of held.symbols) {
|
|
670
|
-
if (fileIds.has(symbol.parent)) {
|
|
671
|
-
|
|
674
|
+
if (!fileIds.has(symbol.parent) && !held.modules.has(symbol.parent)) {
|
|
675
|
+
continue;
|
|
676
|
+
}
|
|
677
|
+
const siblings = byModule.get(symbol.parent);
|
|
678
|
+
if (siblings === undefined) {
|
|
679
|
+
byModule.set(symbol.parent, [symbol]);
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
siblings.push(symbol);
|
|
672
683
|
}
|
|
673
684
|
}
|
|
674
|
-
|
|
685
|
+
moduleBodies = byModule;
|
|
675
686
|
}
|
|
676
|
-
return
|
|
687
|
+
return moduleBodies.get(moduleId) ?? [];
|
|
677
688
|
};
|
|
678
689
|
const exportsCache = new Map();
|
|
679
690
|
/**
|
|
@@ -975,8 +986,11 @@ export function references(project, held, targetRoot, options) {
|
|
|
975
986
|
}
|
|
976
987
|
for (const url of urls) {
|
|
977
988
|
const constructor = url.constructor === undefined ? undefined : answered.get(url.constructor);
|
|
989
|
+
// An augmentation of the global `URL` merges into it, which keeps the
|
|
990
|
+
// library's declaration; a `URL` the target declares has no other.
|
|
978
991
|
if (typeof constructor === "object" &&
|
|
979
|
-
constructor.declarations.
|
|
992
|
+
constructor.declarations.length > 0 &&
|
|
993
|
+
constructor.declarations.every((handle) => ownPaths.has(handle.path))) {
|
|
980
994
|
continue;
|
|
981
995
|
}
|
|
982
996
|
const loaded = specifierCandidates(dirnamePath(file.fileName), url.specifier)
|
|
@@ -1133,14 +1147,16 @@ export function references(project, held, targetRoot, options) {
|
|
|
1133
1147
|
}
|
|
1134
1148
|
let typedLookups = 0;
|
|
1135
1149
|
if (consumer === undefined) {
|
|
1136
|
-
found.push(...overrideReferences(project, held, chains, new Set(tests)));
|
|
1137
1150
|
const before = options.requestCount?.() ?? 0;
|
|
1151
|
+
found.push(...overrideReferences(project, held, chains, new Set(tests)));
|
|
1138
1152
|
found.push(...indexedAccessReferences(project, held, chains, root, new Set(tests)));
|
|
1139
1153
|
found.push(...elementAccessReferences(project, held, chains, root, new Set(tests)));
|
|
1140
1154
|
found.push(...keyofComparisonReferences(project, held, chains, root, new Set(tests)));
|
|
1155
|
+
found.push(...iterationReferences(project, held, chains, root, new Set(tests)));
|
|
1156
|
+
found.push(...typeParameterReads(project, held, chains, root, new Set(tests)));
|
|
1141
1157
|
found.push(...unimplementedCalleeReads(project, held, chains, root, new Set(tests)));
|
|
1142
|
-
typedLookups = (options.requestCount?.() ?? 0) - before;
|
|
1143
1158
|
found.push(...moduleDeclarationReferences(project, held, root, new Set(tests)));
|
|
1159
|
+
typedLookups = (options.requestCount?.() ?? 0) - before;
|
|
1144
1160
|
}
|
|
1145
1161
|
const scripts = new Set(walked.filter((one) => one.file.externalModuleIndicator === undefined).map((one) => one.fileId));
|
|
1146
1162
|
found.push(...augmentationReferences(held, found, scripts));
|
|
@@ -90,8 +90,9 @@ export function reflectiveLookup(input) {
|
|
|
90
90
|
if (lookups.length === 0) {
|
|
91
91
|
return [];
|
|
92
92
|
}
|
|
93
|
-
// Whether each written `Reflect` is the global one, asked in one batch: a
|
|
94
|
-
//
|
|
93
|
+
// Whether each written `Reflect` is the global one, asked in one batch: a name
|
|
94
|
+
// declared only in the project's own files shadows it, and an augmentation of the
|
|
95
|
+
// global merges into it, which keeps the library's declaration.
|
|
95
96
|
const ownFiles = project.ownPaths();
|
|
96
97
|
const reflects = lookups.flatMap((lookup) => lookup.reflect === undefined ? [] : [lookup.reflect]);
|
|
97
98
|
const global = new Set();
|
|
@@ -99,10 +100,11 @@ export function reflectiveLookup(input) {
|
|
|
99
100
|
project.symbolsAt(reflects.map((node) => project.handle(node))).forEach((symbol, index) => {
|
|
100
101
|
const node = reflects[index];
|
|
101
102
|
// A name the checker did not answer for is read as the global, which retains.
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
const isGlobal = symbol === UNANSWERED ||
|
|
104
|
+
(symbol !== undefined &&
|
|
105
|
+
(symbol.declarations.length === 0 ||
|
|
106
|
+
symbol.declarations.some((declaration) => !ownFiles.has(declaration.path))));
|
|
107
|
+
if (node !== undefined && isGlobal) {
|
|
106
108
|
global.add(node);
|
|
107
109
|
}
|
|
108
110
|
});
|
package/dist/src/report.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* renders this document, so no two renderings disagree about which findings exist.
|
|
5
5
|
*/
|
|
6
6
|
/** The version of the report schema this analyzer writes a report to. */
|
|
7
|
-
const SCHEMA_VERSION = "
|
|
7
|
+
const SCHEMA_VERSION = "9.0.0";
|
|
8
8
|
/** Every report schema version this analyzer reads: the one the Contract it implements admits. */
|
|
9
9
|
export const SCHEMA_VERSIONS_ACCEPTED = [SCHEMA_VERSION];
|
|
10
10
|
/** The name this analyzer writes every document under and mints every identifier with. */
|
|
@@ -247,7 +247,9 @@ export function buildReport(input) {
|
|
|
247
247
|
]
|
|
248
248
|
.sort(([a, x], [b, y]) => compare(x.path, y.path) || x.line - y.line || compare(a, b))
|
|
249
249
|
.map(([, skip]) => skip),
|
|
250
|
-
notes: [],
|
|
250
|
+
notes: [...new Map((input.notes ?? []).map((one) => [JSON.stringify(one), one])).entries()]
|
|
251
|
+
.sort(([a, x], [b, y]) => compare(x.kind, y.kind) || compare(x.path, y.path) || compare(a, b))
|
|
252
|
+
.map(([, note]) => note),
|
|
251
253
|
unanswered_questions: [...input.unanswered]
|
|
252
254
|
.sort((a, b) => compare(a.configuration, b.configuration) ||
|
|
253
255
|
compare(JSON.stringify(a), JSON.stringify(b)))
|
|
@@ -793,7 +793,7 @@ class Execution {
|
|
|
793
793
|
case "lit":
|
|
794
794
|
return arg.value;
|
|
795
795
|
case "pipe":
|
|
796
|
-
return this.pipeline(arg.pipe, dot
|
|
796
|
+
return this.pipeline(arg.pipe, dot);
|
|
797
797
|
case "field":
|
|
798
798
|
return this.field(arg.recv === undefined ? dot : this.arg(arg.recv, dot), arg.names);
|
|
799
799
|
case "func":
|
|
@@ -837,19 +837,18 @@ class Execution {
|
|
|
837
837
|
}
|
|
838
838
|
return call(head.name, operands());
|
|
839
839
|
}
|
|
840
|
-
pipeline(pipe, dot
|
|
840
|
+
pipeline(pipe, dot) {
|
|
841
841
|
let value;
|
|
842
842
|
for (const command of pipe.commands) {
|
|
843
843
|
value = this.command(command, dot, value);
|
|
844
844
|
}
|
|
845
845
|
const result = value ?? null;
|
|
846
|
-
const
|
|
847
|
-
if (only !== undefined && (declares || pipe.assign)) {
|
|
846
|
+
for (const name of pipe.vars) {
|
|
848
847
|
if (pipe.assign) {
|
|
849
|
-
this.assign(
|
|
848
|
+
this.assign(name, result);
|
|
850
849
|
}
|
|
851
850
|
else {
|
|
852
|
-
this.scopes.at(-1)?.set(
|
|
851
|
+
this.scopes.at(-1)?.set(name, result);
|
|
853
852
|
}
|
|
854
853
|
}
|
|
855
854
|
return result;
|
|
@@ -861,7 +860,7 @@ class Execution {
|
|
|
861
860
|
this.write(node.text);
|
|
862
861
|
break;
|
|
863
862
|
case "action": {
|
|
864
|
-
const value = this.pipeline(node.pipe, dot
|
|
863
|
+
const value = this.pipeline(node.pipe, dot);
|
|
865
864
|
if (node.pipe.vars.length === 0) {
|
|
866
865
|
this.write(formatted(value, false));
|
|
867
866
|
}
|
|
@@ -874,7 +873,7 @@ class Execution {
|
|
|
874
873
|
case "with": {
|
|
875
874
|
this.scopes.push(new Map());
|
|
876
875
|
try {
|
|
877
|
-
const value = this.pipeline(node.pipe, dot
|
|
876
|
+
const value = this.pipeline(node.pipe, dot);
|
|
878
877
|
const taken = truthy(value);
|
|
879
878
|
this.run(taken ? node.list : node.otherwise, taken && node.k === "with" ? value : dot);
|
|
880
879
|
}
|
|
@@ -892,7 +891,9 @@ class Execution {
|
|
|
892
891
|
range(node, dot) {
|
|
893
892
|
this.scopes.push(new Map());
|
|
894
893
|
try {
|
|
895
|
-
|
|
894
|
+
// Go's `evalPipeline` gives every variable the range declares or assigns the whole value first:
|
|
895
|
+
// https://github.com/golang/go/blob/go1.27.2/src/text/template/exec.go#L525
|
|
896
|
+
const value = this.pipeline(node.pipe, dot);
|
|
896
897
|
let entries;
|
|
897
898
|
if (value === null) {
|
|
898
899
|
entries = [];
|
|
@@ -913,14 +914,22 @@ class Execution {
|
|
|
913
914
|
return;
|
|
914
915
|
}
|
|
915
916
|
const [first, second] = node.pipe.vars;
|
|
917
|
+
const scope = this.scopes.at(-1);
|
|
918
|
+
const bind = (name, held) => {
|
|
919
|
+
if (node.pipe.assign) {
|
|
920
|
+
this.assign(name, held);
|
|
921
|
+
}
|
|
922
|
+
else {
|
|
923
|
+
scope?.set(name, held);
|
|
924
|
+
}
|
|
925
|
+
};
|
|
916
926
|
for (const [key, element] of entries) {
|
|
917
|
-
const scope = this.scopes.at(-1);
|
|
918
927
|
if (second !== undefined && first !== undefined) {
|
|
919
|
-
|
|
920
|
-
|
|
928
|
+
bind(first, key);
|
|
929
|
+
bind(second, element);
|
|
921
930
|
}
|
|
922
931
|
else if (first !== undefined) {
|
|
923
|
-
|
|
932
|
+
bind(first, element);
|
|
924
933
|
}
|
|
925
934
|
try {
|
|
926
935
|
this.run(node.list, element);
|
package/dist/src/resolve.js
CHANGED
|
@@ -567,6 +567,7 @@ function readDoc(value, label) {
|
|
|
567
567
|
injectionRegistrations: readDeclarations(ts, "injection_registrations", "ts.injection_registrations", label),
|
|
568
568
|
lifecycleContracts: readLifecycleContracts(ts, label),
|
|
569
569
|
serializers: readDeclarations(ts, "serializers", "ts.serializers", label),
|
|
570
|
+
rootsComplete: readBoolean(ts, "roots_complete", "ts.roots_complete", label),
|
|
570
571
|
};
|
|
571
572
|
}
|
|
572
573
|
/** Parses one document's text and walks it against the closed key list. */
|
|
@@ -776,6 +777,7 @@ function settleAll(inputs) {
|
|
|
776
777
|
injectionRegistrations: at("ts.injection_registrations", defaults.ts.injectionRegistrations, (doc) => doc.injectionRegistrations),
|
|
777
778
|
lifecycleContracts: at("ts.lifecycle_contracts", defaults.ts.lifecycleContracts, (doc) => doc.lifecycleContracts),
|
|
778
779
|
serializers: at("ts.serializers", defaults.ts.serializers, (doc) => doc.serializers),
|
|
780
|
+
rootsComplete: at("ts.roots_complete", defaults.ts.rootsComplete, (doc) => doc.rootsComplete),
|
|
779
781
|
},
|
|
780
782
|
};
|
|
781
783
|
return { config, provenance };
|