@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/src/erased-stores.ts
CHANGED
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
isNoSubstitutionTemplateLiteral,
|
|
17
17
|
isNumericLiteral,
|
|
18
18
|
isObjectLiteralExpression,
|
|
19
|
-
isParenthesizedExpression,
|
|
20
19
|
isPropertyAccessExpression,
|
|
21
20
|
isPropertyAssignment,
|
|
22
21
|
isShorthandPropertyAssignment,
|
|
@@ -31,6 +30,7 @@ import { SymbolFlags, TypeFlags, type Type } from "@typescript/native/sync";
|
|
|
31
30
|
import { must } from "./query.ts";
|
|
32
31
|
import type { ProjectView } from "./session.ts";
|
|
33
32
|
import { checkedTypes } from "./value-reach.ts";
|
|
33
|
+
import { parenthesesRemoved } from "./unwrap.ts";
|
|
34
34
|
|
|
35
35
|
/** The types that keep nothing of the value they are given. */
|
|
36
36
|
const ERASED = TypeFlags.Any | TypeFlags.Unknown;
|
|
@@ -81,10 +81,6 @@ function literalKey(node: Expression): string | undefined {
|
|
|
81
81
|
: undefined;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
function unwrapped(node: Expression): Expression {
|
|
85
|
-
return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
84
|
/**
|
|
89
85
|
* Whether a variable declaration's type can differ from what is stored in it: it carries an
|
|
90
86
|
* annotation, or it has neither an annotation nor an initializer, so its type evolves.
|
|
@@ -150,8 +146,8 @@ function propertyAt(source: Expression, name: string): Expression | undefined {
|
|
|
150
146
|
* here, and a default value is stored in its target too.
|
|
151
147
|
*/
|
|
152
148
|
function patternTargets(pattern: Expression, from: Stored, out: Target[]): void {
|
|
153
|
-
const target =
|
|
154
|
-
const source = from.path.length === 0 ?
|
|
149
|
+
const target = parenthesesRemoved(pattern);
|
|
150
|
+
const source = from.path.length === 0 ? parenthesesRemoved(from.value) : from.value;
|
|
155
151
|
const into = (element: Expression, step: Step, literal: Expression | undefined): void => {
|
|
156
152
|
patternTargets(
|
|
157
153
|
element,
|
package/src/exempt-classes.ts
CHANGED
|
@@ -1,12 +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
|
-
|
|
9
|
-
import type { Language } from "./config.ts";
|
|
1
|
+
import { EXEMPTION_CLASSES, type Language } from "./contract/contract.generated.ts";
|
|
10
2
|
|
|
11
3
|
/**
|
|
12
4
|
* Whether a class may retain a member declared with the `private` modifier, and one
|
|
@@ -19,67 +11,6 @@ export interface TypeScriptVisibility {
|
|
|
19
11
|
readonly privateName: boolean;
|
|
20
12
|
}
|
|
21
13
|
|
|
22
|
-
/** One class of the vocabulary. */
|
|
23
|
-
interface ExemptionClassRow {
|
|
24
|
-
readonly class: string;
|
|
25
|
-
readonly languages: readonly Language[];
|
|
26
|
-
/** Present exactly on a class that runs on TypeScript. */
|
|
27
|
-
readonly typescriptVisibility?: TypeScriptVisibility;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Every class of the vocabulary, in the order the Contract lists them. */
|
|
31
|
-
export const EXEMPTION_CLASSES = [
|
|
32
|
-
{
|
|
33
|
-
class: "interface-satisfaction",
|
|
34
|
-
languages: ["go", "ts"],
|
|
35
|
-
typescriptVisibility: { private: false, privateName: false },
|
|
36
|
-
},
|
|
37
|
-
{ class: "encoding-reflection", languages: ["go"] },
|
|
38
|
-
{ class: "format-verb-contract", languages: ["go"] },
|
|
39
|
-
{ class: "errors-duck-typing", languages: ["go"] },
|
|
40
|
-
{
|
|
41
|
-
class: "enum-group",
|
|
42
|
-
languages: ["go", "ts"],
|
|
43
|
-
typescriptVisibility: { private: false, privateName: false },
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
class: "generated-file",
|
|
47
|
-
languages: ["go", "ts"],
|
|
48
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
49
|
-
},
|
|
50
|
-
{ class: "linkname-cgo-asm-plugin", languages: ["go"] },
|
|
51
|
-
{
|
|
52
|
-
class: "template-field",
|
|
53
|
-
languages: ["go", "ts"],
|
|
54
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
class: "reflective-lookup",
|
|
58
|
-
languages: ["go", "ts"],
|
|
59
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
class: "decorator",
|
|
63
|
-
languages: ["ts"],
|
|
64
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
class: "injection-container",
|
|
68
|
-
languages: ["ts"],
|
|
69
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
class: "framework-lifecycle",
|
|
73
|
-
languages: ["ts"],
|
|
74
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
class: "serialization-contract",
|
|
78
|
-
languages: ["ts"],
|
|
79
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
80
|
-
},
|
|
81
|
-
] as const satisfies readonly ExemptionClassRow[];
|
|
82
|
-
|
|
83
14
|
type Row = (typeof EXEMPTION_CLASSES)[number];
|
|
84
15
|
|
|
85
16
|
/** The name of a class of the vocabulary. */
|
|
@@ -116,8 +47,3 @@ const VISIBILITY: ReadonlyMap<TSExemptionClass, TypeScriptVisibility> = new Map(
|
|
|
116
47
|
export function typescriptVisibilityOf(exemptionClass: TSExemptionClass): TypeScriptVisibility {
|
|
117
48
|
return VISIBILITY.get(exemptionClass) ?? { private: false, privateName: false };
|
|
118
49
|
}
|
|
119
|
-
|
|
120
|
-
/** Whether one name is a class of the vocabulary, whichever language it runs on. */
|
|
121
|
-
export function isExemptionClass(name: string): name is ExemptionClass {
|
|
122
|
-
return EXEMPTION_CLASSES.some((row) => row.class === name);
|
|
123
|
-
}
|
package/src/exempt.ts
CHANGED
|
@@ -7,24 +7,23 @@
|
|
|
7
7
|
* hands it the table of the classes it has.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
10
|
+
import { EXEMPTION_CLASSES } from "./contract/contract.generated.ts";
|
|
11
|
+
import type { ResolvedConfig } from "./config.ts";
|
|
12
12
|
import {
|
|
13
|
-
EXEMPTION_CLASSES,
|
|
14
|
-
isExemptionClass,
|
|
15
13
|
TS_EXEMPTION_CLASSES,
|
|
16
14
|
typescriptVisibilityOf,
|
|
17
15
|
type ExemptionClass,
|
|
18
16
|
type TSExemptionClass,
|
|
19
17
|
type TypeScriptVisibility,
|
|
20
18
|
} from "./exempt-classes.ts";
|
|
21
|
-
import type { Inventory, InventorySymbol,
|
|
19
|
+
import type { Inventory, InventorySymbol, Visibility } from "./inventory.ts";
|
|
22
20
|
import type { Matrix } from "./matrix.ts";
|
|
23
21
|
import { byPosition, positionKey, type Position } from "./position.ts";
|
|
24
22
|
import { Unanswerable } from "./query.ts";
|
|
25
23
|
import type { ProjectView } from "./session.ts";
|
|
26
24
|
import type { Templates } from "./template-field.ts";
|
|
27
25
|
import { sweep, type Exemption, type Implementing, type Mode, type SweepInput } from "./sweep.ts";
|
|
26
|
+
import { bytewise } from "./text/compare.ts";
|
|
28
27
|
|
|
29
28
|
/** One declaration a detector holds back, and where and why. */
|
|
30
29
|
export interface Evidence {
|
|
@@ -37,6 +36,8 @@ export interface Evidence {
|
|
|
37
36
|
readonly whileLive?: string;
|
|
38
37
|
/** Where the evidence is an implementation of interface methods, which and how. */
|
|
39
38
|
readonly implementing?: Implementing;
|
|
39
|
+
/** Whether the evidence holds only where a write the mode counts stores into the declaration. */
|
|
40
|
+
readonly whileWritten?: true;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
/** What a detector reads of one project, while the project's view is open. */
|
|
@@ -47,7 +48,7 @@ export interface DetectorInput<Brand> {
|
|
|
47
48
|
/** The configured templates, read once for the run. */
|
|
48
49
|
readonly templates: Templates;
|
|
49
50
|
/** The `ts` section, whose declarations the configured classes read. */
|
|
50
|
-
readonly ts:
|
|
51
|
+
readonly ts: ResolvedConfig["ts"];
|
|
51
52
|
/** The absolute path of each declared consumer, whose modules are part of the analysis. */
|
|
52
53
|
readonly consumers: readonly string[];
|
|
53
54
|
/** The project's generated files, by path below the target root, each with the detail its retentions name. */
|
|
@@ -71,24 +72,11 @@ interface Holding {
|
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
/**
|
|
74
|
-
* The classes `exemptions.disabled` switches off. A
|
|
75
|
-
*
|
|
76
|
-
* switches nothing off here, so one configuration serves every analyzer.
|
|
75
|
+
* The classes `exemptions.disabled` switches off. A class that runs on another language
|
|
76
|
+
* only switches nothing off here, so one configuration serves every analyzer.
|
|
77
77
|
*/
|
|
78
|
-
export function disabledClasses(config:
|
|
79
|
-
|
|
80
|
-
for (const name of config.exemptionsDisabled) {
|
|
81
|
-
if (!isExemptionClass(name)) {
|
|
82
|
-
const known = EXEMPTION_CLASSES.map((row) => row.class).join(", ");
|
|
83
|
-
throw new ConfigError(
|
|
84
|
-
"malformed",
|
|
85
|
-
"exemptions.disabled",
|
|
86
|
-
`exemptions.disabled: ${JSON.stringify(name)} is not an exemption class: the classes are ${known}`,
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
disabled.add(name);
|
|
90
|
-
}
|
|
91
|
-
return disabled;
|
|
78
|
+
export function disabledClasses(config: ResolvedConfig): ReadonlySet<ExemptionClass> {
|
|
79
|
+
return new Set(config.exemptions.disabled);
|
|
92
80
|
}
|
|
93
81
|
|
|
94
82
|
/**
|
|
@@ -105,20 +93,12 @@ function retainable(allowed: TypeScriptVisibility, visibility: Visibility | unde
|
|
|
105
93
|
return true;
|
|
106
94
|
}
|
|
107
95
|
|
|
108
|
-
/**
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
["enum-group", new Set<SymbolKind>(["enum-member"])],
|
|
115
|
-
["injection-container", new Set<SymbolKind>(["method", "class-member"])],
|
|
116
|
-
["framework-lifecycle", new Set<SymbolKind>(["method", "class-member"])],
|
|
117
|
-
[
|
|
118
|
-
"serialization-contract",
|
|
119
|
-
new Set<SymbolKind>(["method", "class-member", "interface-method", "type-member"]),
|
|
120
|
-
],
|
|
121
|
-
]);
|
|
96
|
+
/** The kinds of declaration each class can hold back, which a detector that stops holds back whole. */
|
|
97
|
+
const RETAINABLE: ReadonlyMap<string, ReadonlySet<string>> = new Map(
|
|
98
|
+
EXEMPTION_CLASSES.flatMap((row) =>
|
|
99
|
+
"ts" in row.retainsKinds ? [[row.class, new Set<string>(row.retainsKinds.ts)] as const] : [],
|
|
100
|
+
),
|
|
101
|
+
);
|
|
122
102
|
|
|
123
103
|
/** The detail of a record a detector that could not finish holds. */
|
|
124
104
|
const UNANSWERED_DETAIL = "kept live by a question the checker did not answer";
|
|
@@ -147,7 +127,7 @@ function detected<Brand>(
|
|
|
147
127
|
}
|
|
148
128
|
const kinds = RETAINABLE.get(exemptionClass);
|
|
149
129
|
return input.held.symbols
|
|
150
|
-
.filter((symbol) =>
|
|
130
|
+
.filter((symbol) => kinds?.has(symbol.kind) === true)
|
|
151
131
|
.map((symbol) => ({ id: symbol.id, detail: UNANSWERED_DETAIL, site: symbol.position }));
|
|
152
132
|
}
|
|
153
133
|
}
|
|
@@ -193,12 +173,26 @@ export function evidenceRecords<Brand>(
|
|
|
193
173
|
site: evidence.site,
|
|
194
174
|
...(evidence.whileLive === undefined ? {} : { whileLive: evidence.whileLive }),
|
|
195
175
|
...(evidence.implementing === undefined ? {} : { implementing: evidence.implementing }),
|
|
176
|
+
...(evidence.whileWritten === undefined ? {} : { whileWritten: evidence.whileWritten }),
|
|
196
177
|
});
|
|
197
178
|
}
|
|
198
179
|
}
|
|
199
180
|
return found;
|
|
200
181
|
}
|
|
201
182
|
|
|
183
|
+
/**
|
|
184
|
+
* The records that hold given the declarations a write the mode counts stores into: one
|
|
185
|
+
* that holds only while written holds where its declaration is among them.
|
|
186
|
+
*/
|
|
187
|
+
export function writtenRecords(
|
|
188
|
+
records: readonly Exemption[],
|
|
189
|
+
written: ReadonlySet<string>,
|
|
190
|
+
): readonly Exemption[] {
|
|
191
|
+
return records.flatMap(({ whileWritten, ...record }) =>
|
|
192
|
+
whileWritten === undefined || written.has(record.id) ? [record] : [],
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
202
196
|
/** The records that hold under one mode, beside the evidence a production mode found in a test file. */
|
|
203
197
|
export function heldRecords(records: readonly Exemption[], holding: Holding): Detected {
|
|
204
198
|
const found: Exemption[] = [];
|
|
@@ -213,14 +207,6 @@ export function heldRecords(records: readonly Exemption[], holding: Holding): De
|
|
|
213
207
|
return { records: exemptionsOf(found), inTestFiles };
|
|
214
208
|
}
|
|
215
209
|
|
|
216
|
-
/** Two strings ordered bytewise. */
|
|
217
|
-
function compare(a: string, b: string): number {
|
|
218
|
-
if (a === b) {
|
|
219
|
-
return 0;
|
|
220
|
-
}
|
|
221
|
-
return a < b ? -1 : 1;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
210
|
/**
|
|
225
211
|
* Records as a run holds them: ordered by site, then class, then declaration, and one
|
|
226
212
|
* per declaration, class, detail and file it holds while live, the one at the first
|
|
@@ -228,7 +214,7 @@ function compare(a: string, b: string): number {
|
|
|
228
214
|
*/
|
|
229
215
|
export function exemptionsOf(found: readonly Exemption[]): readonly Exemption[] {
|
|
230
216
|
const ordered = [...found].sort(
|
|
231
|
-
(a, b) => byPosition(a.site, b.site) ||
|
|
217
|
+
(a, b) => byPosition(a.site, b.site) || bytewise(a.class, b.class) || bytewise(a.id, b.id),
|
|
232
218
|
);
|
|
233
219
|
const seen = new Set<string>();
|
|
234
220
|
return ordered.filter((record) => {
|
|
@@ -300,8 +286,8 @@ export function retainedIn(
|
|
|
300
286
|
}
|
|
301
287
|
|
|
302
288
|
/**
|
|
303
|
-
* One line per held-back declaration, in site order: its reference, then
|
|
304
|
-
* class, site and detail, all separated by tabs.
|
|
289
|
+
* One line per held-back declaration, in site order: its reference and position, then
|
|
290
|
+
* each record's class, site and detail, all separated by tabs.
|
|
305
291
|
*/
|
|
306
292
|
export function retainedLines(
|
|
307
293
|
symbols: readonly InventorySymbol[],
|
|
@@ -318,6 +304,6 @@ export function retainedLines(
|
|
|
318
304
|
positionKey(record.site),
|
|
319
305
|
record.detail,
|
|
320
306
|
]);
|
|
321
|
-
return [[symbol.ref, ...fields].join("\t")];
|
|
307
|
+
return [[symbol.ref, positionKey(symbol.position), ...fields].join("\t")];
|
|
322
308
|
});
|
|
323
309
|
}
|
package/src/failure.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { FAILURE_CLASSES, FAILURE_PREFIXES } from "./contract/contract.generated.ts";
|
|
2
|
+
import type { LocatedDiagnostic } from "./load/diagnostics.ts";
|
|
3
|
+
import { PRODUCT } from "./product.ts";
|
|
4
|
+
|
|
5
|
+
/** A class of failure the Contract's exit-code table names, of either group. */
|
|
6
|
+
type FailureClass = keyof typeof FAILURE_CLASSES;
|
|
7
|
+
|
|
8
|
+
/** One cause the run ends with the failure code for. */
|
|
9
|
+
export interface Failure {
|
|
10
|
+
readonly failureClass: FailureClass;
|
|
11
|
+
/** What fails and the fix, on one line. */
|
|
12
|
+
readonly detail: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** The failure as a class line of the error stream, opened by its group's prefix. */
|
|
16
|
+
export function failureLine(failure: Failure): string {
|
|
17
|
+
return `${FAILURE_PREFIXES[FAILURE_CLASSES[failure.failureClass]]}${failure.failureClass}: ${failure.detail}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The lines of the error stream that name the failures: the first one's class line, the run's
|
|
22
|
+
* only one, then each further failure as its class and detail with no group prefix.
|
|
23
|
+
*/
|
|
24
|
+
export function failureLines([first, ...further]: readonly [Failure, ...Failure[]]): string[] {
|
|
25
|
+
return [failureLine(first), ...further.map((one) => `${one.failureClass}: ${one.detail}`)];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A run the analysis cannot answer. It ends the run with the failure code and no finding
|
|
30
|
+
* list, printing the compiler's located errors and then the failures' lines.
|
|
31
|
+
*/
|
|
32
|
+
export class FailureExit extends Error {
|
|
33
|
+
readonly failures: readonly [Failure, ...Failure[]];
|
|
34
|
+
/** The compiler's errors behind the failures, in the order it reported them. */
|
|
35
|
+
readonly diagnostics: readonly LocatedDiagnostic[];
|
|
36
|
+
|
|
37
|
+
constructor(
|
|
38
|
+
failures: readonly [Failure, ...Failure[]],
|
|
39
|
+
diagnostics: readonly LocatedDiagnostic[] = [],
|
|
40
|
+
) {
|
|
41
|
+
super(failureLines(failures).join("\n"));
|
|
42
|
+
this.name = "FailureExit";
|
|
43
|
+
this.failures = failures;
|
|
44
|
+
this.diagnostics = diagnostics;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** A failure exit of one failure. */
|
|
49
|
+
export function failureExit(
|
|
50
|
+
failureClass: FailureClass,
|
|
51
|
+
detail: string,
|
|
52
|
+
diagnostics: readonly LocatedDiagnostic[] = [],
|
|
53
|
+
): FailureExit {
|
|
54
|
+
return new FailureExit([{ failureClass, detail }], diagnostics);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** A fault of this analyzer itself, `fault` saying what it cannot do. */
|
|
58
|
+
export function productFault(fault: string): FailureExit {
|
|
59
|
+
return failureExit(
|
|
60
|
+
"product-fault",
|
|
61
|
+
`${PRODUCT} ${fault}: reinstall ${PRODUCT}, and report the fault to its maintainers if a reinstalled ${PRODUCT} fails the same way`,
|
|
62
|
+
);
|
|
63
|
+
}
|
package/src/file-facts.ts
CHANGED
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { SourceFile } from "@typescript/native/ast";
|
|
8
|
-
import { IGNORED_DIRECTORIES } from "./discover.ts";
|
|
9
8
|
import type { Host } from "./host.ts";
|
|
10
9
|
import { packageScope } from "./inventory.ts";
|
|
11
10
|
import { dirnamePath, joinPath, relativePath, resolvePath } from "./paths.ts";
|
|
12
11
|
import { renderRef } from "./ref.ts";
|
|
13
12
|
import type { ProjectView } from "./session.ts";
|
|
13
|
+
import type { UnseenLoad } from "./unseen-loads.ts";
|
|
14
|
+
import { filesBelow } from "./fs/tree.ts";
|
|
14
15
|
|
|
15
16
|
/** A file name the compiler reads as a source file. */
|
|
16
17
|
const SOURCE_FILE = /\.(?:ts|tsx|mts|cts)$/u;
|
|
@@ -51,6 +52,8 @@ export interface FileFacts {
|
|
|
51
52
|
readonly generated?: ReadonlySet<string>;
|
|
52
53
|
/** The property names an `in` expression of a production file tests by a literal. */
|
|
53
54
|
readonly inOperands?: ReadonlySet<string>;
|
|
55
|
+
/** The loads of production files whose target the analysis cannot resolve. */
|
|
56
|
+
readonly unseenLoads?: readonly UnseenLoad[];
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
/** The line of the last character of one text, counted from one; an empty text is one line. */
|
|
@@ -71,29 +74,11 @@ function lastLine(text: string): number {
|
|
|
71
74
|
* that cannot be read is skipped, as discovery skips it.
|
|
72
75
|
*/
|
|
73
76
|
export function sourcePaths(host: Host, targetRoot: string): readonly string[] {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
entries = host.readDirectory(joinPath(targetRoot, dir));
|
|
80
|
-
} catch {
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
for (const entry of entries) {
|
|
84
|
-
const path = dir === "" ? entry.name : `${dir}/${entry.name}`;
|
|
85
|
-
if (entry.directory) {
|
|
86
|
-
if (!IGNORED_DIRECTORIES.has(entry.name)) {
|
|
87
|
-
pending.push(path);
|
|
88
|
-
}
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
if (SOURCE_FILE.test(entry.name) && !DECLARATION_FILE.test(entry.name)) {
|
|
92
|
-
found.push(path);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return found.sort((a, b) => (a < b ? -1 : 1));
|
|
77
|
+
return filesBelow(
|
|
78
|
+
host,
|
|
79
|
+
targetRoot,
|
|
80
|
+
(name) => SOURCE_FILE.test(name) && !DECLARATION_FILE.test(name),
|
|
81
|
+
);
|
|
97
82
|
}
|
|
98
83
|
|
|
99
84
|
/**
|
package/src/finding.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Confidence, Severity } from "./
|
|
2
|
-
import type { Fixability } from "./kinds.ts";
|
|
1
|
+
import type { Fixability, Confidence, Severity } from "./contract/contract.generated.ts";
|
|
3
2
|
import type { DependencySection } from "./ref.ts";
|
|
4
3
|
import type { Mechanism } from "./suppress.ts";
|
|
5
4
|
import type { Relation } from "./sweep.ts";
|
|
5
|
+
import type { FindingSymbol } from "./contract/report.generated.ts";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* The finding: what an emitter decides about one subject, and every member the
|
|
@@ -29,11 +29,17 @@ interface FindingSubject {
|
|
|
29
29
|
/** The stable symbol reference, or for a configured root the root as written. */
|
|
30
30
|
readonly ref: string;
|
|
31
31
|
/** The subject kind, from the closed vocabulary of the finding schema. */
|
|
32
|
-
readonly kind:
|
|
32
|
+
readonly kind: FindingSymbol["kind"];
|
|
33
33
|
/** The display name a text line renders. */
|
|
34
34
|
readonly name: string;
|
|
35
35
|
/** The number of source lines the subject spans. */
|
|
36
36
|
readonly sizeLines: number;
|
|
37
|
+
/**
|
|
38
|
+
* Where the subject is a part whose reference is its own, a parameter's, the reference
|
|
39
|
+
* of the declaration that holds it, which a record binding that declaration matches.
|
|
40
|
+
* No report carries it.
|
|
41
|
+
*/
|
|
42
|
+
readonly holder?: string;
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
/** A declaration a finding names beside the subject, with where it is written. */
|
|
@@ -49,19 +55,19 @@ export interface PositionedSymbol {
|
|
|
49
55
|
*/
|
|
50
56
|
export interface FindingDetails {
|
|
51
57
|
/**
|
|
52
|
-
* On `
|
|
58
|
+
* On `DS1501` and `DS1503`: the widest scope that holds every reference to the
|
|
53
59
|
* subject, which is the visibility its references support.
|
|
54
60
|
*/
|
|
55
61
|
readonly narrowerVisibility?: "file" | "package";
|
|
56
|
-
/** On `DS1201` and `
|
|
62
|
+
/** On `DS1201` and `DS1202`: the classes implementing the interface, in site order. */
|
|
57
63
|
readonly implementations?: readonly PositionedSymbol[];
|
|
58
|
-
/** On `DS1301` and `
|
|
64
|
+
/** On `DS1301` and `DS1404`: every position the subject is written at, in site order. */
|
|
59
65
|
readonly writePositions?: readonly FindingPosition[];
|
|
60
|
-
/** On `
|
|
66
|
+
/** On `DS1701`: the manifest section that declares the dependency. */
|
|
61
67
|
readonly dependencyClass?: DependencySection;
|
|
62
|
-
/** On `
|
|
68
|
+
/** On `DS9001` and `DS9002`: the document that holds the refused suppression. */
|
|
63
69
|
readonly mechanism?: Mechanism;
|
|
64
|
-
/** On `
|
|
70
|
+
/** On `DS9001` and `DS9002`: the refused suppression as written, a member absent where it lacks one. */
|
|
65
71
|
readonly entry?: SuppressionEntry;
|
|
66
72
|
/** On the intra-function kinds: the external rules that report the same kind, as the vocabulary lists them. */
|
|
67
73
|
readonly overlap?: readonly string[];
|
|
@@ -87,6 +93,10 @@ export interface Finding {
|
|
|
87
93
|
readonly details?: FindingDetails;
|
|
88
94
|
/** The reachability class of a subject that is no declaration, where it is not `certain`. */
|
|
89
95
|
readonly reachabilityClass?: Confidence;
|
|
96
|
+
/** Whether references to a subject that is no declaration exist, all from dead code. */
|
|
97
|
+
readonly unreachableOnly?: true;
|
|
98
|
+
/** The dead declarations and files whose component a subject that is no declaration falls with. */
|
|
99
|
+
readonly fallsWith?: readonly string[];
|
|
90
100
|
}
|
|
91
101
|
|
|
92
102
|
/** The dead component a finding names, as the finding schema spells its members. */
|
|
@@ -109,6 +119,11 @@ export interface CompletedFinding extends Finding {
|
|
|
109
119
|
readonly reachabilityClass: Confidence;
|
|
110
120
|
/** The reachability class capped by the code's ceiling. */
|
|
111
121
|
readonly confidence: Confidence;
|
|
122
|
+
/**
|
|
123
|
+
* Where test-used code alone lowers the confidence, the one the finding would carry
|
|
124
|
+
* otherwise, which its component's cap and the dials read.
|
|
125
|
+
*/
|
|
126
|
+
readonly componentConfidence?: Confidence;
|
|
112
127
|
/**
|
|
113
128
|
* The relation that decided the subject: present on a declaration the sweep judged
|
|
114
129
|
* dead, absent on a live one and on a subject that is no declaration.
|
package/src/findings/boundary.ts
CHANGED
|
@@ -25,4 +25,6 @@ export interface Boundary {
|
|
|
25
25
|
readonly encapsulated: boolean;
|
|
26
26
|
/** Every side of a declared cross-language edge that names a symbol of this language. */
|
|
27
27
|
readonly edges: readonly EdgeSide[];
|
|
28
|
+
/** The members a function outside the analysis fills, which it may read unseen. */
|
|
29
|
+
readonly filledOutside?: ReadonlySet<string>;
|
|
28
30
|
}
|