@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
package/dist/src/edges.js
CHANGED
|
@@ -4,153 +4,69 @@
|
|
|
4
4
|
* never resolves the paired symbol: the other language's analyzer decides whether the
|
|
5
5
|
* pairing is a use, and the merge reads the two evaluations together.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { EDGES_SCHEMA } from "./contract/config.generated.js";
|
|
8
|
+
import { readTargetDocument } from "./fs/document.js";
|
|
9
|
+
import { dotted, placeIn, positionAt, readStrict, StrictJSONError } from "./json-document.js";
|
|
10
10
|
import { positionKey } from "./position.js";
|
|
11
|
+
import { firstRefusal } from "./schema.js";
|
|
11
12
|
import { isPartSubject } from "./suppress.js";
|
|
13
|
+
import { bytewise } from "./text/compare.js";
|
|
14
|
+
import { UsageError } from "./usage.js";
|
|
12
15
|
/** The name and the location the Contract fixes for the edges document. */
|
|
13
16
|
export const EDGES_FILE = "deadset-edges.json";
|
|
14
17
|
/** The language prefix of every reference this analyzer evaluates. */
|
|
15
18
|
const OWN_PREFIX = "ts://";
|
|
16
|
-
/** The closed key list of the document and of one edge. */
|
|
17
|
-
const DOCUMENT_KEYS = new Set(["description", "edges"]);
|
|
18
|
-
const EDGE_KEYS = new Set(["id", "because", "provides", "used_by"]);
|
|
19
|
-
/** An edge identifier: solidus-separated segments of ASCII letters, digits, `_`, `.` and `-`. */
|
|
20
|
-
const ID_FORM = /^[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)*$/u;
|
|
21
|
-
/** A reference naming one symbol of some language: `<language>://<scope>#<fragment>`. */
|
|
22
|
-
const REFERENCE_FORM = /^[a-z][a-z0-9]*:\/\/[^ \t\r\n#]+#[^ \t\r\n]*$/u;
|
|
23
|
-
const DOCUMENT_WANT = "an object carrying the edges array, and an optional description";
|
|
24
|
-
const EDGE_WANT = "an edge naming id, provides and used_by, each a string, and an optional because";
|
|
25
|
-
const ID_WANT = "one or more solidus-separated segments of ASCII letters, digits, underscore, full stop and hyphen";
|
|
26
|
-
const REFERENCE_WANT = "a stable symbol reference naming one symbol exactly, <language>://<scope>#<fragment>";
|
|
27
19
|
/** An edges document the Contract refuses: a malformed input, answered with the usage code. */
|
|
28
|
-
class EdgesError extends
|
|
29
|
-
constructor(at,
|
|
30
|
-
super(
|
|
20
|
+
class EdgesError extends UsageError {
|
|
21
|
+
constructor(at, reason) {
|
|
22
|
+
super(`${at}: ${reason}`);
|
|
31
23
|
this.name = "EdgesError";
|
|
32
24
|
}
|
|
33
25
|
}
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
* would name a set of symbols rather than one.
|
|
37
|
-
*/
|
|
38
|
-
function carriesWildcard(ref) {
|
|
39
|
-
let quoted = false;
|
|
40
|
-
let computed = false;
|
|
41
|
-
let escaped = false;
|
|
42
|
-
for (const char of ref) {
|
|
43
|
-
if (escaped) {
|
|
44
|
-
escaped = false;
|
|
45
|
-
}
|
|
46
|
-
else if (quoted && char === "\\") {
|
|
47
|
-
escaped = true;
|
|
48
|
-
}
|
|
49
|
-
else if (quoted) {
|
|
50
|
-
quoted = char !== "'";
|
|
51
|
-
}
|
|
52
|
-
else if (computed) {
|
|
53
|
-
computed = char !== "]";
|
|
54
|
-
}
|
|
55
|
-
else if (char === "'") {
|
|
56
|
-
quoted = true;
|
|
57
|
-
}
|
|
58
|
-
else if (char === "[") {
|
|
59
|
-
computed = true;
|
|
60
|
-
}
|
|
61
|
-
else if (char === "*") {
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
function isObject(value) {
|
|
68
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
69
|
-
}
|
|
70
|
-
/** One edge, checked: the closed key list, the value types and the value forms. */
|
|
71
|
-
function readEdge(value, at) {
|
|
72
|
-
const refuse = (text, want) => {
|
|
73
|
-
throw new EdgesError(at, text, want);
|
|
74
|
-
};
|
|
75
|
-
if (!isObject(value)) {
|
|
76
|
-
return refuse(JSON.stringify(value), EDGE_WANT);
|
|
77
|
-
}
|
|
78
|
-
for (const [key, held] of Object.entries(value)) {
|
|
79
|
-
if (!EDGE_KEYS.has(key) || typeof held !== "string") {
|
|
80
|
-
refuse(`the member ${JSON.stringify(key)} holding ${JSON.stringify(held)}`, EDGE_WANT);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
const edge = value;
|
|
84
|
-
const id = edge["id"] ?? refuse("an edge naming no id", EDGE_WANT);
|
|
85
|
-
const provides = edge["provides"] ?? refuse("an edge naming no provides side", EDGE_WANT);
|
|
86
|
-
const usedBy = edge["used_by"] ?? refuse("an edge naming no used_by side", EDGE_WANT);
|
|
87
|
-
if (!ID_FORM.test(id)) {
|
|
88
|
-
refuse(JSON.stringify(id), ID_WANT);
|
|
89
|
-
}
|
|
90
|
-
for (const ref of [provides, usedBy]) {
|
|
91
|
-
if (!REFERENCE_FORM.test(ref) || carriesWildcard(ref)) {
|
|
92
|
-
refuse(JSON.stringify(ref), REFERENCE_WANT);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return { id, provides, usedBy };
|
|
96
|
-
}
|
|
26
|
+
/** The sides of one edge, in the order a reader yields them. */
|
|
27
|
+
const SIDE_NAMES = ["provides", "used_by"];
|
|
97
28
|
/**
|
|
98
29
|
* Every side of a declared edge that names a symbol of this language, in document order,
|
|
99
30
|
* `provides` before `used_by` within an edge. An absent document declares no edge. The
|
|
100
|
-
* document is strict JSON
|
|
101
|
-
* {@link EdgesError}.
|
|
31
|
+
* document is strict JSON held to the Contract's edges schema, and a defect in it is an
|
|
32
|
+
* {@link EdgesError} at the line and column of the edge it is in, where it is in one.
|
|
102
33
|
*/
|
|
103
34
|
export function readEdgeSides(host, targetRoot) {
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
35
|
+
const text = readTargetDocument(host, targetRoot, EDGES_FILE);
|
|
36
|
+
if (text === undefined) {
|
|
106
37
|
return [];
|
|
107
38
|
}
|
|
108
|
-
|
|
109
|
-
let parsed;
|
|
39
|
+
let read;
|
|
110
40
|
try {
|
|
111
|
-
|
|
41
|
+
read = readStrict(text, "edges");
|
|
112
42
|
}
|
|
113
43
|
catch (error) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
throw new EdgesError(EDGES_FILE,
|
|
118
|
-
}
|
|
119
|
-
const walk = walkDocument(text, "edges");
|
|
120
|
-
if (walk.twice !== undefined) {
|
|
121
|
-
throw new EdgesError(positionKey(positionAt(text, EDGES_FILE, walk.twice.offset)), `the member ${JSON.stringify(walk.twice.name)} is written twice, so neither value is chosen`, DOCUMENT_WANT);
|
|
44
|
+
if (!(error instanceof StrictJSONError)) {
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
throw new EdgesError(positionKey(positionAt(text, EDGES_FILE, error.offset)), error.message);
|
|
122
48
|
}
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
49
|
+
const value = read.value;
|
|
50
|
+
const refused = firstRefusal(EDGES_SCHEMA, value);
|
|
51
|
+
if (refused !== undefined) {
|
|
52
|
+
const place = placeIn(value, refused.pointer, refused.member);
|
|
53
|
+
const offset = place.length > 1 ? read.starts.get(place[1] ?? "") : undefined;
|
|
54
|
+
const at = offset === undefined ? EDGES_FILE : positionKey(positionAt(text, EDGES_FILE, offset));
|
|
55
|
+
const where = dotted(place);
|
|
56
|
+
throw new EdgesError(at, where === "" ? refused.reason : `${where}: ${refused.reason}`);
|
|
130
57
|
}
|
|
58
|
+
const edges = value.edges;
|
|
131
59
|
const sides = [];
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
["used_by", edge.usedBy],
|
|
139
|
-
];
|
|
140
|
-
for (const [side, symbol] of named) {
|
|
141
|
-
if (symbol.startsWith(OWN_PREFIX)) {
|
|
142
|
-
sides.push({ edge: edge.id, side, symbol });
|
|
60
|
+
for (const id of read.starts.keys()) {
|
|
61
|
+
const edge = String(id);
|
|
62
|
+
for (const side of SIDE_NAMES) {
|
|
63
|
+
const symbol = edges[edge]?.[side];
|
|
64
|
+
if (symbol?.startsWith(OWN_PREFIX) === true) {
|
|
65
|
+
sides.push({ edge, side, symbol });
|
|
143
66
|
}
|
|
144
67
|
}
|
|
145
|
-
});
|
|
146
|
-
return sides;
|
|
147
|
-
}
|
|
148
|
-
/** Two strings ordered bytewise. */
|
|
149
|
-
function compare(a, b) {
|
|
150
|
-
if (a === b) {
|
|
151
|
-
return 0;
|
|
152
68
|
}
|
|
153
|
-
return
|
|
69
|
+
return sides;
|
|
154
70
|
}
|
|
155
71
|
/**
|
|
156
72
|
* Evaluates every declared side of this language over the run's findings. A side naming a
|
|
@@ -191,6 +107,6 @@ export function evaluateEdges(findings, sides, symbols) {
|
|
|
191
107
|
return { ...side, state: "dead", finding };
|
|
192
108
|
});
|
|
193
109
|
});
|
|
194
|
-
evaluations.sort((a, b) =>
|
|
110
|
+
evaluations.sort((a, b) => bytewise(a.edge, b.edge) || bytewise(a.side, b.side));
|
|
195
111
|
return { findings: findings.filter((_finding, at) => !pending.has(at)), evaluations };
|
|
196
112
|
}
|
|
@@ -8,6 +8,7 @@ import { isArrayLiteralExpression, isArrowFunction, isBinaryExpression, isCallEx
|
|
|
8
8
|
import { nodeKey } from "./inventory.js";
|
|
9
9
|
import { renderPosition } from "./position.js";
|
|
10
10
|
import { UNANSWERED } from "./query.js";
|
|
11
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
11
12
|
/** The assignment operators that read their target before they write it. */
|
|
12
13
|
const COMPOUND = new Set([
|
|
13
14
|
SyntaxKind.PlusEqualsToken,
|
|
@@ -47,12 +48,9 @@ function useOf(node) {
|
|
|
47
48
|
}
|
|
48
49
|
return "read";
|
|
49
50
|
}
|
|
50
|
-
function unwrapped(node) {
|
|
51
|
-
return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
|
|
52
|
-
}
|
|
53
51
|
/** Whether an index is a literal the checker resolves to a member by its own text. */
|
|
54
52
|
function isLiteralIndex(node) {
|
|
55
|
-
const at =
|
|
53
|
+
const at = parenthesesRemoved(node);
|
|
56
54
|
return isStringLiteral(at) || isNumericLiteral(at) || isNoSubstitutionTemplateLiteral(at);
|
|
57
55
|
}
|
|
58
56
|
/**
|
|
@@ -195,7 +193,7 @@ export function elementAccessReferences(project, held, chains, root, testFiles)
|
|
|
195
193
|
const parameterOf = new Map();
|
|
196
194
|
const byCallable = new Map();
|
|
197
195
|
for (const candidate of candidates) {
|
|
198
|
-
const index =
|
|
196
|
+
const index = parenthesesRemoved(candidate.access.argumentExpression);
|
|
199
197
|
const fn = isIdentifier(index) ? enclosingFunction(candidate.access) : undefined;
|
|
200
198
|
const callable = fn === undefined ? undefined : callableOf(fn);
|
|
201
199
|
if (callable === undefined || !isIdentifier(index)) {
|
|
@@ -252,7 +250,7 @@ export function elementAccessReferences(project, held, chains, root, testFiles)
|
|
|
252
250
|
continue;
|
|
253
251
|
}
|
|
254
252
|
// An object that is a parameter too is read as the argument each call passes there.
|
|
255
|
-
const object =
|
|
253
|
+
const object = parenthesesRemoved(candidate.access.expression);
|
|
256
254
|
const objectAt = isIdentifier(object)
|
|
257
255
|
? deferred.callable.parameters.findIndex((parameter) => isIdentifier(parameter.name) && parameter.name.text === object.text)
|
|
258
256
|
: -1;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* Every row carries a reason, because the list is read where the rows are shown
|
|
8
8
|
* one at a time: beside a finding, or in a report's declared gaps.
|
|
9
9
|
*/
|
|
10
|
+
import { bytewise } from "./text/compare.js";
|
|
10
11
|
/** What is declined for a tool whose own conventions are entered only through its configuration files. */
|
|
11
12
|
const EVERY_CONVENTION = "every file it loads by its own convention beyond its configuration files";
|
|
12
13
|
/** Why a tool whose own conventions are not read declines them. */
|
|
@@ -43,7 +44,6 @@ const UNREAD_TOOLS = [
|
|
|
43
44
|
"cypress",
|
|
44
45
|
"danger",
|
|
45
46
|
"dependency-cruiser",
|
|
46
|
-
"docusaurus",
|
|
47
47
|
"dotenv",
|
|
48
48
|
"drizzle",
|
|
49
49
|
"electron-vite",
|
|
@@ -97,14 +97,12 @@ const UNREAD_TOOLS = [
|
|
|
97
97
|
"nuxtjs-i18n",
|
|
98
98
|
"nx",
|
|
99
99
|
"nyc",
|
|
100
|
-
"oclif",
|
|
101
100
|
"openapi-ts",
|
|
102
101
|
"openclaw",
|
|
103
102
|
"orval",
|
|
104
103
|
"oxfmt",
|
|
105
104
|
"oxlint",
|
|
106
105
|
"panda-css",
|
|
107
|
-
"parcel",
|
|
108
106
|
"payload",
|
|
109
107
|
"pino",
|
|
110
108
|
"playwright-ct",
|
|
@@ -149,7 +147,6 @@ const UNREAD_TOOLS = [
|
|
|
149
147
|
"swc",
|
|
150
148
|
"syncpack",
|
|
151
149
|
"tailwind",
|
|
152
|
-
"tanstack-router",
|
|
153
150
|
"taskfile",
|
|
154
151
|
"tauri",
|
|
155
152
|
"temporal",
|
|
@@ -193,18 +190,19 @@ const UNREAD_TOOLS = [
|
|
|
193
190
|
];
|
|
194
191
|
/** The conventions declined for a tool some of whose conventions are entered. */
|
|
195
192
|
const PARTLY_ENTERED = [
|
|
193
|
+
{
|
|
194
|
+
tool: "docusaurus",
|
|
195
|
+
convention: "a page or theme directory a plugin's configuration moves, and the docs",
|
|
196
|
+
reason: "The convention row reads src/pages and src/theme only, and a document's imports are " +
|
|
197
|
+
"read from every Markdown and MDX file, so a module only a moved directory holds is " +
|
|
198
|
+
"reported as never imported unless ts.entry_files names it.",
|
|
199
|
+
},
|
|
196
200
|
{
|
|
197
201
|
tool: "eslint",
|
|
198
202
|
convention: "a legacy configuration written in YAML or in JSON with comments",
|
|
199
203
|
reason: "Only a configuration module and a strict JSON configuration file are read, so a " +
|
|
200
204
|
"dependency only such a file names is reported as unused.",
|
|
201
205
|
},
|
|
202
|
-
{
|
|
203
|
-
tool: "eslint",
|
|
204
|
-
convention: "a plugin or shareable configuration named without its package's prefix",
|
|
205
|
-
reason: "A string uses a dependency only where it spells the dependency's name, so a " +
|
|
206
|
-
"dependency only a shortened name loads is reported as unused.",
|
|
207
|
-
},
|
|
208
206
|
{
|
|
209
207
|
tool: "playwright",
|
|
210
208
|
convention: "a testMatch written as a regular expression",
|
|
@@ -294,15 +292,8 @@ const PARTLY_ENTERED = [
|
|
|
294
292
|
reason: NOT_LITERAL,
|
|
295
293
|
},
|
|
296
294
|
];
|
|
297
|
-
/** Two strings ordered bytewise. */
|
|
298
|
-
function compare(a, b) {
|
|
299
|
-
if (a === b) {
|
|
300
|
-
return 0;
|
|
301
|
-
}
|
|
302
|
-
return a < b ? -1 : 1;
|
|
303
|
-
}
|
|
304
295
|
/** Every declined entry-point convention, ordered by tool and then by convention. */
|
|
305
296
|
export const DECLINED_CONVENTIONS = [
|
|
306
297
|
...UNREAD_TOOLS.map((tool) => ({ tool, convention: EVERY_CONVENTION, reason: UNREAD })),
|
|
307
298
|
...PARTLY_ENTERED,
|
|
308
|
-
].sort((a, b) =>
|
|
299
|
+
].sort((a, b) => bytewise(a.tool, b.tool) || bytewise(a.convention, b.convention));
|
package/dist/src/entry-points.js
CHANGED
|
@@ -10,14 +10,18 @@
|
|
|
10
10
|
* value that is not a literal is not evaluated and not guessed, so a file it would
|
|
11
11
|
* have named is entered by nothing here.
|
|
12
12
|
*/
|
|
13
|
-
import { isArrayLiteralExpression,
|
|
13
|
+
import { isArrayLiteralExpression, isCallExpression, isExportAssignment, isIdentifier, isMetaProperty, isNewExpression, isNoSubstitutionTemplateLiteral, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isStringLiteral, SyntaxKind, } from "@typescript/native/ast";
|
|
14
14
|
import { SymbolFlags } from "@typescript/native/sync";
|
|
15
15
|
import { configurationFiles, filesNamedBy, moduleStrings, } from "./configuration-files.js";
|
|
16
|
-
import {
|
|
16
|
+
import { buildScriptEntries } from "./build-scripts.js";
|
|
17
17
|
import { htmlEntries } from "./html-entries.js";
|
|
18
|
+
import { documentEntries } from "./mdx-entries.js";
|
|
18
19
|
import { dirnamePath, relativePath, resolvePath } from "./paths.js";
|
|
19
20
|
import { UNANSWERED } from "./query.js";
|
|
21
|
+
import { computedLoadDirectory, leadingLiteral } from "./unseen-loads.js";
|
|
20
22
|
import { workflowEntries } from "./workflow-steps.js";
|
|
23
|
+
import { unwrapped } from "./unwrap.js";
|
|
24
|
+
import { globExpression } from "./text/glob.js";
|
|
21
25
|
/** The extensions the test runner and the browser-test runner load a configuration from. */
|
|
22
26
|
const MODULE_EXTENSIONS = ["js", "mjs", "cjs", "ts", "mts", "cts"];
|
|
23
27
|
/** The tool file names the configuration form does not cover. */
|
|
@@ -37,8 +41,11 @@ const BROWSER_TEST_MATCH = "**/*.{spec,test}.{js,ts,jsx,tsx,cjs,cts,cjsx,ctsx,mj
|
|
|
37
41
|
const SETUP_MEMBERS = ["setupFiles", "globalSetup"];
|
|
38
42
|
/** A member that moves the directory every path of a test-runner configuration is read from. */
|
|
39
43
|
const ROOT_MEMBER = "root";
|
|
40
|
-
/**
|
|
41
|
-
|
|
44
|
+
/**
|
|
45
|
+
* A URL reference's scheme. A reference with none that does not start with a solidus is
|
|
46
|
+
* relative, the bare name included: https://url.spec.whatwg.org/#relative-url-string
|
|
47
|
+
*/
|
|
48
|
+
const URL_SCHEME = /^[a-z][a-z\d+.-]*:/iu;
|
|
42
49
|
/** The constructors whose first argument addresses a worker script. */
|
|
43
50
|
const WORKER_CONSTRUCTORS = new Set(["Worker", "SharedWorker"]);
|
|
44
51
|
/** The file's name, the last segment of its path. */
|
|
@@ -63,14 +70,6 @@ function literalOf(node) {
|
|
|
63
70
|
}
|
|
64
71
|
return undefined;
|
|
65
72
|
}
|
|
66
|
-
/** The expression a wrapper that changes no value holds: parentheses and type assertions. */
|
|
67
|
-
function unwrapped(node) {
|
|
68
|
-
let at = node;
|
|
69
|
-
while (isParenthesizedExpression(at) || isAsExpression(at) || isSatisfiesExpression(at)) {
|
|
70
|
-
at = at.expression;
|
|
71
|
-
}
|
|
72
|
-
return at;
|
|
73
|
-
}
|
|
74
73
|
/**
|
|
75
74
|
* The object literals one configuration file's default export is written as: the
|
|
76
75
|
* literal itself, or each literal argument of the call it is, at any depth of calls.
|
|
@@ -138,9 +137,16 @@ function literalsOf(value) {
|
|
|
138
137
|
}
|
|
139
138
|
return found;
|
|
140
139
|
}
|
|
141
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* Whether a literal is a relative URL reference, which is also how the test runner reads a
|
|
142
|
+
* setup file's path against its root.
|
|
143
|
+
*/
|
|
142
144
|
function isRelative(text) {
|
|
143
|
-
return
|
|
145
|
+
return text !== "" && !text.startsWith("/") && !URL_SCHEME.test(text);
|
|
146
|
+
}
|
|
147
|
+
/** Whether a module specifier is relative, which a bare name is not: it names a package. */
|
|
148
|
+
function isModuleRelative(text) {
|
|
149
|
+
return text.startsWith("./") || text.startsWith("../");
|
|
144
150
|
}
|
|
145
151
|
/** A URL reference with its query and its fragment removed, which name no part of the file. */
|
|
146
152
|
function pathPart(text) {
|
|
@@ -199,7 +205,7 @@ function configurationEntries(host, targetRoot, files, parse, selected) {
|
|
|
199
205
|
strings(dirnamePath(document.path), unselectedIn(document.path, document.strings));
|
|
200
206
|
}
|
|
201
207
|
for (const { file } of outside) {
|
|
202
|
-
strings(dirnamePath(file.fileName),
|
|
208
|
+
strings(dirnamePath(file.fileName), unselected(file));
|
|
203
209
|
}
|
|
204
210
|
return found;
|
|
205
211
|
}
|
|
@@ -348,10 +354,10 @@ function workerSitesOf(file) {
|
|
|
348
354
|
return found;
|
|
349
355
|
}
|
|
350
356
|
/**
|
|
351
|
-
* The workers one file addresses. A call's names must resolve to the platform
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
357
|
+
* The workers one file addresses. A call's names must resolve to a symbol the platform
|
|
358
|
+
* declares, which a file of the target may augment and no import brings in; a name only
|
|
359
|
+
* the target declares is the target's own constructor or object, which addresses no
|
|
360
|
+
* worker this rule knows. One batch per file that writes such a call.
|
|
355
361
|
*/
|
|
356
362
|
function workersOf(project, file, files) {
|
|
357
363
|
const sites = workerSitesOf(file);
|
|
@@ -371,8 +377,7 @@ function workersOf(project, file, files) {
|
|
|
371
377
|
}
|
|
372
378
|
if (symbol !== undefined &&
|
|
373
379
|
(symbol.flags & SymbolFlags.Alias) === 0 &&
|
|
374
|
-
symbol.declarations.
|
|
375
|
-
symbol.declarations.every((handle) => !files.byName.has(handle.path))) {
|
|
380
|
+
symbol.declarations.some((handle) => !files.byName.has(handle.path))) {
|
|
376
381
|
platform.add(name);
|
|
377
382
|
}
|
|
378
383
|
});
|
|
@@ -388,6 +393,73 @@ function workersOf(project, file, files) {
|
|
|
388
393
|
}
|
|
389
394
|
return found;
|
|
390
395
|
}
|
|
396
|
+
/** Whether one call is `import.meta.glob(...)`. */
|
|
397
|
+
function isMetaGlob(node) {
|
|
398
|
+
if (!isCallExpression(node) || !isPropertyAccessExpression(node.expression)) {
|
|
399
|
+
return false;
|
|
400
|
+
}
|
|
401
|
+
const { expression, name } = node.expression;
|
|
402
|
+
return (isIdentifier(name) &&
|
|
403
|
+
name.text === "glob" &&
|
|
404
|
+
isMetaProperty(expression) &&
|
|
405
|
+
expression.keywordToken === SyntaxKind.ImportKeyword);
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* The files one file loads by a computed path, each with what exports: every own file
|
|
409
|
+
* below the directory a relative literal start of an `import()` or `require()` argument
|
|
410
|
+
* names, other than the calling file's own directory or one holding it, which would name
|
|
411
|
+
* every sibling, and
|
|
412
|
+
* every own file a relative literal glob of `import.meta.glob` matches, both read against
|
|
413
|
+
* the calling file's directory, as a bundler's context module reads them.
|
|
414
|
+
*/
|
|
415
|
+
function computedImportsOf(file, files) {
|
|
416
|
+
const dir = dirnamePath(file.fileName);
|
|
417
|
+
const found = [];
|
|
418
|
+
const below = (prefix) => {
|
|
419
|
+
const target = computedLoadDirectory(dir, prefix);
|
|
420
|
+
if (target === undefined) {
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
for (const candidate of files.byName.values()) {
|
|
424
|
+
if (candidate !== file && relativePath(target, candidate.fileName) !== undefined) {
|
|
425
|
+
found.push({ file: candidate, rule: "computed-import", source: prefix, exports: true });
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
const globbed = (pattern) => {
|
|
430
|
+
if (!isModuleRelative(pattern)) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const expression = globExpression(resolvePath(dir, pattern));
|
|
434
|
+
for (const candidate of files.byName.values()) {
|
|
435
|
+
if (candidate !== file && expression.test(candidate.fileName)) {
|
|
436
|
+
found.push({ file: candidate, rule: "computed-import", source: pattern, exports: true });
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
const visit = (node) => {
|
|
441
|
+
if (isCallExpression(node)) {
|
|
442
|
+
const [first] = node.arguments;
|
|
443
|
+
const callee = node.expression;
|
|
444
|
+
const loads = callee.kind === SyntaxKind.ImportKeyword ||
|
|
445
|
+
(isIdentifier(callee) && callee.text === "require");
|
|
446
|
+
if (loads && first !== undefined) {
|
|
447
|
+
const prefix = leadingLiteral(first);
|
|
448
|
+
if (prefix !== undefined) {
|
|
449
|
+
below(prefix);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
else if (isMetaGlob(node) && first !== undefined) {
|
|
453
|
+
for (const pattern of literalsOf(first) ?? []) {
|
|
454
|
+
globbed(pattern);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
node.forEachChild(visit);
|
|
459
|
+
};
|
|
460
|
+
file.forEachChild(visit);
|
|
461
|
+
return found;
|
|
462
|
+
}
|
|
391
463
|
/**
|
|
392
464
|
* Every file of one project the rules enter, in no particular order and possibly more
|
|
393
465
|
* than once: a file two rules enter appears once per rule.
|
|
@@ -417,10 +489,23 @@ export function entryPoints(project, files, testFiles, host, targetRoot, parse,
|
|
|
417
489
|
}
|
|
418
490
|
}
|
|
419
491
|
found.push(...workersOf(project, file, files));
|
|
492
|
+
found.push(...computedImportsOf(file, files));
|
|
420
493
|
}
|
|
421
494
|
for (const { file, source } of htmlEntries(host, targetRoot, files, parse)) {
|
|
422
495
|
found.push({ file, rule: "html-entry", source, exports: true });
|
|
423
496
|
}
|
|
497
|
+
for (const { file, source, names } of documentEntries(host, targetRoot, files)) {
|
|
498
|
+
found.push({
|
|
499
|
+
file,
|
|
500
|
+
rule: "document-import",
|
|
501
|
+
source,
|
|
502
|
+
exports: true,
|
|
503
|
+
...(names === undefined ? {} : { names }),
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
for (const { file, source } of buildScriptEntries(host, targetRoot, files, parse)) {
|
|
507
|
+
found.push({ file, rule: "bundler-entry", source, exports: true });
|
|
508
|
+
}
|
|
424
509
|
for (const { file, source } of workflowEntries(host, targetRoot, files)) {
|
|
425
510
|
found.push({ file, rule: "workflow-step", source, exports: true });
|
|
426
511
|
}
|
package/dist/src/enum-group.js
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* or `unknown` expression asserted to it, or bound to a variable or returned from a
|
|
7
7
|
* function it annotates, where a number counts too. An enum's own value converts nothing.
|
|
8
8
|
*/
|
|
9
|
-
import { isArrowFunction, isAsExpression, isElementAccessExpression, isEnumDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isIdentifier, isMethodDeclaration, isNoSubstitutionTemplateLiteral,
|
|
9
|
+
import { isArrowFunction, isAsExpression, isElementAccessExpression, isEnumDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isIdentifier, isMethodDeclaration, isNoSubstitutionTemplateLiteral, isParenthesizedTypeNode, isPropertyAccessExpression, isReturnStatement, isStringLiteral, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
|
|
10
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
10
11
|
import { TypeFlags } from "@typescript/native/sync";
|
|
11
12
|
import { aliasChains } from "./alias-chain.js";
|
|
12
13
|
import { nodeKey } from "./inventory.js";
|
|
@@ -16,14 +17,6 @@ import { isAnswered, UNANSWERED } from "./query.js";
|
|
|
16
17
|
const NUMBER = TypeFlags.NumberLike;
|
|
17
18
|
const STRING = TypeFlags.StringLike;
|
|
18
19
|
const DECODED = TypeFlags.Any | TypeFlags.Unknown;
|
|
19
|
-
/** The expression one node is, through however many parentheses are written around it. */
|
|
20
|
-
function unparenthesized(node) {
|
|
21
|
-
let held = node;
|
|
22
|
-
while (isParenthesizedExpression(held)) {
|
|
23
|
-
held = held.expression;
|
|
24
|
-
}
|
|
25
|
-
return held;
|
|
26
|
-
}
|
|
27
20
|
/**
|
|
28
21
|
* The name node a type node names its declaration by: the identifier of a type
|
|
29
22
|
* reference, the right side of a qualified one, through parentheses. A type that is no
|
|
@@ -45,7 +38,7 @@ function typeName(type) {
|
|
|
45
38
|
}
|
|
46
39
|
/** The name node an expression names an object by: an identifier, or a property access's name. */
|
|
47
40
|
function objectName(expression) {
|
|
48
|
-
const held =
|
|
41
|
+
const held = parenthesesRemoved(expression);
|
|
49
42
|
if (isIdentifier(held)) {
|
|
50
43
|
return held;
|
|
51
44
|
}
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
* either stores. A store into an erased property of a type the analyzed program does not
|
|
7
7
|
* declare hands the value to the code that declares it.
|
|
8
8
|
*/
|
|
9
|
-
import { isArrayLiteralExpression, isBinaryExpression, isCallExpression, isElementAccessExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectLiteralExpression,
|
|
9
|
+
import { isArrayLiteralExpression, isBinaryExpression, isCallExpression, isElementAccessExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadElement, isStringLiteral, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
|
|
10
10
|
import { SymbolFlags, TypeFlags } from "@typescript/native/sync";
|
|
11
11
|
import { must } from "./query.js";
|
|
12
12
|
import { checkedTypes } from "./value-reach.js";
|
|
13
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
13
14
|
/** The types that keep nothing of the value they are given. */
|
|
14
15
|
const ERASED = TypeFlags.Any | TypeFlags.Unknown;
|
|
15
16
|
/** The array methods whose arguments become elements of the array they are called on. */
|
|
@@ -20,9 +21,6 @@ function literalKey(node) {
|
|
|
20
21
|
? node.text
|
|
21
22
|
: undefined;
|
|
22
23
|
}
|
|
23
|
-
function unwrapped(node) {
|
|
24
|
-
return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
|
|
25
|
-
}
|
|
26
24
|
/**
|
|
27
25
|
* Whether a variable declaration's type can differ from what is stored in it: it carries an
|
|
28
26
|
* annotation, or it has neither an annotation nor an initializer, so its type evolves.
|
|
@@ -76,8 +74,8 @@ function propertyAt(source, name) {
|
|
|
76
74
|
* here, and a default value is stored in its target too.
|
|
77
75
|
*/
|
|
78
76
|
function patternTargets(pattern, from, out) {
|
|
79
|
-
const target =
|
|
80
|
-
const source = from.path.length === 0 ?
|
|
77
|
+
const target = parenthesesRemoved(pattern);
|
|
78
|
+
const source = from.path.length === 0 ? parenthesesRemoved(from.value) : from.value;
|
|
81
79
|
const into = (element, step, literal) => {
|
|
82
80
|
patternTargets(element, literal === undefined
|
|
83
81
|
? { value: from.value, path: [...from.path, step] }
|
|
@@ -1,62 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* The exemption classes of the Contract's vocabulary, in its order: each class's name, its
|
|
3
|
-
* languages and, for a TypeScript class, which private members it may retain. The rows are
|
|
4
|
-
* written out, as the fixed severity codes are, and a test holds them equal to the Contract.
|
|
5
|
-
* A class name is a type, so a table or a record naming a class outside the vocabulary, or
|
|
6
|
-
* one of another language only, does not compile.
|
|
7
|
-
*/
|
|
8
|
-
/** Every class of the vocabulary, in the order the Contract lists them. */
|
|
9
|
-
export const EXEMPTION_CLASSES = [
|
|
10
|
-
{
|
|
11
|
-
class: "interface-satisfaction",
|
|
12
|
-
languages: ["go", "ts"],
|
|
13
|
-
typescriptVisibility: { private: false, privateName: false },
|
|
14
|
-
},
|
|
15
|
-
{ class: "encoding-reflection", languages: ["go"] },
|
|
16
|
-
{ class: "format-verb-contract", languages: ["go"] },
|
|
17
|
-
{ class: "errors-duck-typing", languages: ["go"] },
|
|
18
|
-
{
|
|
19
|
-
class: "enum-group",
|
|
20
|
-
languages: ["go", "ts"],
|
|
21
|
-
typescriptVisibility: { private: false, privateName: false },
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
class: "generated-file",
|
|
25
|
-
languages: ["go", "ts"],
|
|
26
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
27
|
-
},
|
|
28
|
-
{ class: "linkname-cgo-asm-plugin", languages: ["go"] },
|
|
29
|
-
{
|
|
30
|
-
class: "template-field",
|
|
31
|
-
languages: ["go", "ts"],
|
|
32
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
class: "reflective-lookup",
|
|
36
|
-
languages: ["go", "ts"],
|
|
37
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
class: "decorator",
|
|
41
|
-
languages: ["ts"],
|
|
42
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
class: "injection-container",
|
|
46
|
-
languages: ["ts"],
|
|
47
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
class: "framework-lifecycle",
|
|
51
|
-
languages: ["ts"],
|
|
52
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
class: "serialization-contract",
|
|
56
|
-
languages: ["ts"],
|
|
57
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
58
|
-
},
|
|
59
|
-
];
|
|
1
|
+
import { EXEMPTION_CLASSES } from "./contract/contract.generated.js";
|
|
60
2
|
function runsOnTS(row) {
|
|
61
3
|
const languages = row.languages;
|
|
62
4
|
return languages.includes("ts");
|
|
@@ -69,7 +11,3 @@ const VISIBILITY = new Map(TS_ROWS.map((row) => [row.class, row.typescriptVisibi
|
|
|
69
11
|
export function typescriptVisibilityOf(exemptionClass) {
|
|
70
12
|
return VISIBILITY.get(exemptionClass) ?? { private: false, privateName: false };
|
|
71
13
|
}
|
|
72
|
-
/** Whether one name is a class of the vocabulary, whichever language it runs on. */
|
|
73
|
-
export function isExemptionClass(name) {
|
|
74
|
-
return EXEMPTION_CLASSES.some((row) => row.class === name);
|
|
75
|
-
}
|