@cplieger/deadset-ts 8.0.0-dev.5 → 8.0.0-dev.7
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 +2 -1
- package/dist/bin/node-host.js +3 -2
- package/dist/src/analysis.js +28 -46
- package/dist/src/automatic-types.js +10 -29
- package/dist/src/build-scripts.js +17 -29
- package/dist/src/component-layer.js +4 -2
- package/dist/src/components.js +2 -3
- package/dist/src/config.js +3 -2
- package/dist/src/configuration-files.js +27 -168
- package/dist/src/conformance-record.js +1 -1
- package/dist/src/contract/contract.generated.js +1084 -0
- package/dist/src/contract/report.generated.js +796 -0
- package/dist/src/conventions.js +20 -60
- package/dist/src/dependencies.js +25 -43
- package/dist/src/discover.js +13 -39
- package/dist/src/edges.js +7 -15
- package/dist/src/element-access.js +4 -6
- package/dist/src/entry-point-gaps.js +2 -8
- package/dist/src/entry-points.js +3 -10
- package/dist/src/enum-group.js +3 -10
- package/dist/src/erased-stores.js +4 -6
- package/dist/src/exempt-classes.js +3 -63
- package/dist/src/exempt.js +13 -40
- package/dist/src/file-facts.js +2 -25
- package/dist/src/findings/completion.js +11 -20
- package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
- package/dist/src/findings/emitters.js +4 -4
- package/dist/src/findings/interfaces.js +4 -5
- package/dist/src/findings/intra-function.js +8 -7
- package/dist/src/findings/non-code-artifacts.js +5 -6
- package/dist/src/findings/reads-and-writes.js +11 -9
- package/dist/src/findings/self-check.js +10 -12
- package/dist/src/findings/unused-declarations.js +28 -27
- package/dist/src/findings/visibility-narrowing.js +9 -11
- package/dist/src/findings-pass.js +7 -14
- package/dist/src/fs/manifest.js +43 -0
- package/dist/src/fs/tree.js +88 -0
- package/dist/src/git-ignore.js +34 -25
- package/dist/src/html-entries.js +6 -33
- package/dist/src/in-operands.js +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/intra-function-parts.js +18 -26
- package/dist/src/inventory.js +2 -21
- package/dist/src/json-document.js +4 -0
- package/dist/src/keyof-comparisons.js +4 -6
- package/dist/src/kinds.js +4 -360
- package/dist/src/manifest.js +5 -43
- package/dist/src/mdx-entries.js +3 -26
- 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 +3 -2
- package/dist/src/product.js +13 -0
- package/dist/src/references.js +14 -27
- package/dist/src/report-schema.js +272 -0
- package/dist/src/report.js +39 -42
- package/dist/src/reporters/sarif.js +4 -2
- package/dist/src/reporters/template.js +4 -19
- package/dist/src/resolve.js +12 -26
- package/dist/src/roots.js +7 -17
- package/dist/src/run.js +10 -8
- package/dist/src/schema.js +4 -3
- package/dist/src/scope.js +4 -5
- package/dist/src/serialization-contract.js +4 -8
- package/dist/src/session.js +2 -1
- package/dist/src/setup-failure.js +2 -6
- package/dist/src/suppress-file.js +12 -13
- package/dist/src/suppress-inline.js +3 -2
- package/dist/src/suppress.js +29 -48
- package/dist/src/symbol-keys.js +3 -5
- package/dist/src/template-field.js +5 -15
- package/dist/src/test-globals.js +6 -28
- package/dist/src/test-joins.js +6 -6
- package/dist/src/text/compare.js +26 -0
- package/dist/src/text/glob.js +194 -0
- package/dist/src/text/shell.js +159 -0
- package/dist/src/{yaml-document.js → text/yaml.js} +38 -0
- package/dist/src/type-errors.js +14 -38
- package/dist/src/unseen-loads.js +2 -9
- package/dist/src/unwrap.js +23 -0
- package/dist/src/verbs/analyze.js +22 -15
- package/dist/src/verbs/describe.js +7 -7
- package/dist/src/verbs/explain.js +7 -4
- package/dist/src/verbs/print-config.js +2 -1
- package/dist/src/verbs/print-projects.js +4 -2
- 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 +4 -3
- package/dist/src/workflow-steps.js +9 -46
- package/dist/src/workspace-manifests.js +2 -2
- package/dist/src/workspace-programs.js +5 -3
- package/dist/src/workspace-resolution.js +13 -17
- package/dist/src/workspace.js +28 -116
- package/jsr.json +1 -1
- package/package.json +2 -1
- package/src/analysis.ts +29 -54
- package/src/automatic-types.ts +11 -29
- package/src/build-scripts.ts +17 -38
- package/src/component-layer.ts +4 -2
- package/src/components.ts +2 -4
- package/src/config.ts +11 -15
- package/src/configuration-files.ts +27 -170
- package/src/conformance-record.ts +1 -1
- package/src/contract/contract.generated.ts +1148 -0
- package/src/contract/report.generated.ts +1157 -0
- package/src/conventions.ts +26 -74
- package/src/dependencies.ts +32 -50
- package/src/discover.ts +14 -39
- package/src/edges.ts +7 -21
- package/src/element-access.ts +4 -7
- package/src/entry-point-gaps.ts +3 -9
- package/src/entry-points.ts +2 -13
- package/src/enum-group.ts +2 -11
- package/src/erased-stores.ts +3 -7
- package/src/exempt-classes.ts +5 -74
- package/src/exempt.ts +17 -47
- package/src/file-facts.ts +6 -24
- package/src/finding.ts +9 -9
- package/src/findings/completion.ts +22 -23
- package/src/findings/dependencies-and-module-machinery.ts +4 -7
- package/src/findings/emitter.ts +6 -7
- package/src/findings/emitters.ts +6 -6
- package/src/findings/interfaces.ts +4 -6
- package/src/findings/intra-function.ts +8 -8
- package/src/findings/non-code-artifacts.ts +5 -7
- package/src/findings/reads-and-writes.ts +15 -12
- package/src/findings/self-check.ts +11 -17
- package/src/findings/unused-declarations.ts +28 -27
- package/src/findings/visibility-narrowing.ts +9 -12
- package/src/findings-pass.ts +7 -16
- package/src/fs/manifest.ts +52 -0
- package/src/fs/tree.ts +110 -0
- package/src/git-ignore.ts +38 -25
- package/src/html-entries.ts +6 -33
- package/src/in-operands.ts +2 -1
- package/src/index.ts +1 -1
- package/src/intra-function-parts.ts +18 -28
- package/src/inventory.ts +2 -20
- package/src/json-document.ts +5 -0
- package/src/keyof-comparisons.ts +3 -7
- package/src/kinds.ts +6 -406
- package/src/manifest.ts +5 -46
- package/src/mdx-entries.ts +3 -26
- package/src/partial.ts +2 -1
- package/src/paths.ts +27 -15
- package/src/position.ts +2 -1
- package/src/print.ts +3 -2
- package/src/product.ts +18 -0
- package/src/references.ts +14 -29
- package/src/report-schema.ts +364 -0
- package/src/report.ts +66 -229
- package/src/reporters/annotations.ts +2 -2
- package/src/reporters/json.ts +1 -1
- package/src/reporters/reporter.ts +2 -2
- package/src/reporters/reporters.ts +1 -1
- package/src/reporters/sarif.ts +17 -12
- package/src/reporters/template.ts +4 -20
- package/src/reporters/text.ts +3 -3
- package/src/resolve.ts +31 -38
- package/src/roots.ts +7 -20
- package/src/run.ts +10 -14
- package/src/schema.ts +4 -3
- package/src/scope.ts +4 -10
- package/src/serialization-contract.ts +4 -9
- package/src/session.ts +2 -1
- package/src/setup-failure.ts +5 -7
- package/src/suppress-file.ts +11 -15
- package/src/suppress-inline.ts +2 -2
- package/src/suppress.ts +39 -55
- package/src/symbol-keys.ts +2 -5
- package/src/template-field.ts +5 -18
- package/src/test-globals.ts +9 -27
- package/src/test-joins.ts +6 -8
- package/src/text/compare.ts +27 -0
- package/src/text/glob.ts +210 -0
- package/src/text/shell.ts +161 -0
- package/src/{yaml-document.ts → text/yaml.ts} +46 -0
- package/src/type-errors.ts +25 -36
- package/src/unseen-loads.ts +1 -12
- package/src/unwrap.ts +34 -0
- package/src/verbs/analyze.ts +38 -25
- package/src/verbs/describe.ts +13 -7
- package/src/verbs/explain.ts +7 -4
- package/src/verbs/print-config.ts +2 -1
- package/src/verbs/print-projects.ts +4 -2
- package/src/verbs/print-retained.ts +4 -2
- package/src/verbs/print-roots.ts +4 -2
- package/src/verbs/verb.ts +0 -6
- package/src/verbs/version.ts +4 -3
- package/src/workflow-steps.ts +9 -44
- package/src/workspace-manifests.ts +2 -2
- package/src/workspace-programs.ts +5 -3
- package/src/workspace-resolution.ts +21 -17
- package/src/workspace.ts +35 -121
- package/dist/src/glob.js +0 -65
- package/dist/src/pnpm-workspace.js +0 -120
- package/dist/src/version.js +0 -7
- package/src/glob.ts +0 -67
- package/src/pnpm-workspace.ts +0 -135
- package/src/version.ts +0 -7
|
@@ -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,5 @@ 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
|
-
/**
|
|
73
|
-
export
|
|
74
|
-
return EXEMPTION_CLASSES.some((row) => row.class === name);
|
|
75
|
-
}
|
|
14
|
+
/** Every class of the vocabulary, whichever language it runs on, in the vocabulary's order. */
|
|
15
|
+
export const EXEMPTION_CLASS_NAMES = EXEMPTION_CLASSES.map((row) => row.class);
|
package/dist/src/exempt.js
CHANGED
|
@@ -6,26 +6,18 @@
|
|
|
6
6
|
* which records held something back. It names no class's detector: the composition
|
|
7
7
|
* hands it the table of the classes it has.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { EXEMPTION_CLASSES } from "./contract/contract.generated.js";
|
|
10
|
+
import { TS_EXEMPTION_CLASSES, typescriptVisibilityOf, } from "./exempt-classes.js";
|
|
11
11
|
import { byPosition, positionKey } from "./position.js";
|
|
12
12
|
import { Unanswerable } from "./query.js";
|
|
13
13
|
import { sweep } from "./sweep.js";
|
|
14
|
+
import { bytewise } from "./text/compare.js";
|
|
14
15
|
/**
|
|
15
|
-
* The classes `exemptions.disabled` switches off. A
|
|
16
|
-
*
|
|
17
|
-
* switches nothing off here, so one configuration serves every analyzer.
|
|
16
|
+
* The classes `exemptions.disabled` switches off. A class that runs on another language
|
|
17
|
+
* only switches nothing off here, so one configuration serves every analyzer.
|
|
18
18
|
*/
|
|
19
19
|
export function disabledClasses(config) {
|
|
20
|
-
|
|
21
|
-
for (const name of config.exemptionsDisabled) {
|
|
22
|
-
if (!isExemptionClass(name)) {
|
|
23
|
-
const known = EXEMPTION_CLASSES.map((row) => row.class).join(", ");
|
|
24
|
-
throw new ConfigError("malformed", "exemptions.disabled", `exemptions.disabled: ${JSON.stringify(name)} is not an exemption class: the classes are ${known}`);
|
|
25
|
-
}
|
|
26
|
-
disabled.add(name);
|
|
27
|
-
}
|
|
28
|
-
return disabled;
|
|
20
|
+
return new Set(config.exemptionsDisabled);
|
|
29
21
|
}
|
|
30
22
|
/**
|
|
31
23
|
* Whether a class whose row states `allowed` may retain a member of one visibility. A
|
|
@@ -40,20 +32,8 @@ function retainable(allowed, visibility) {
|
|
|
40
32
|
}
|
|
41
33
|
return true;
|
|
42
34
|
}
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
* back whole. A class with no row here holds back every declaration but a file.
|
|
46
|
-
*/
|
|
47
|
-
const RETAINABLE = new Map([
|
|
48
|
-
["interface-satisfaction", new Set(["method", "class-member"])],
|
|
49
|
-
["enum-group", new Set(["enum-member"])],
|
|
50
|
-
["injection-container", new Set(["method", "class-member"])],
|
|
51
|
-
["framework-lifecycle", new Set(["method", "class-member"])],
|
|
52
|
-
[
|
|
53
|
-
"serialization-contract",
|
|
54
|
-
new Set(["method", "class-member", "interface-method", "type-member"]),
|
|
55
|
-
],
|
|
56
|
-
]);
|
|
35
|
+
/** The kinds of declaration each class can hold back, which a detector that stops holds back whole. */
|
|
36
|
+
const RETAINABLE = new Map(EXEMPTION_CLASSES.flatMap((row) => "ts" in row.retainsKinds ? [[row.class, new Set(row.retainsKinds.ts)]] : []));
|
|
57
37
|
/** The detail of a record a detector that could not finish holds. */
|
|
58
38
|
const UNANSWERED_DETAIL = "kept live by a question the checker did not answer";
|
|
59
39
|
/** Whether one record is held by a detector that could not finish. */
|
|
@@ -76,7 +56,7 @@ function detected(exemptionClass, detect, input) {
|
|
|
76
56
|
}
|
|
77
57
|
const kinds = RETAINABLE.get(exemptionClass);
|
|
78
58
|
return input.held.symbols
|
|
79
|
-
.filter((symbol) =>
|
|
59
|
+
.filter((symbol) => kinds?.has(symbol.kind) === true)
|
|
80
60
|
.map((symbol) => ({ id: symbol.id, detail: UNANSWERED_DETAIL, site: symbol.position }));
|
|
81
61
|
}
|
|
82
62
|
}
|
|
@@ -133,20 +113,13 @@ export function heldRecords(records, holding) {
|
|
|
133
113
|
}
|
|
134
114
|
return { records: exemptionsOf(found), inTestFiles };
|
|
135
115
|
}
|
|
136
|
-
/** Two strings ordered bytewise. */
|
|
137
|
-
function compare(a, b) {
|
|
138
|
-
if (a === b) {
|
|
139
|
-
return 0;
|
|
140
|
-
}
|
|
141
|
-
return a < b ? -1 : 1;
|
|
142
|
-
}
|
|
143
116
|
/**
|
|
144
117
|
* Records as a run holds them: ordered by site, then class, then declaration, and one
|
|
145
118
|
* per declaration, class, detail and file it holds while live, the one at the first
|
|
146
119
|
* site. A fact found at many sites, or by several projects, is one record.
|
|
147
120
|
*/
|
|
148
121
|
export function exemptionsOf(found) {
|
|
149
|
-
const ordered = [...found].sort((a, b) => byPosition(a.site, b.site) ||
|
|
122
|
+
const ordered = [...found].sort((a, b) => byPosition(a.site, b.site) || bytewise(a.class, b.class) || bytewise(a.id, b.id));
|
|
150
123
|
const seen = new Set();
|
|
151
124
|
return ordered.filter((record) => {
|
|
152
125
|
const fact = [record.id, record.class, record.detail, record.whileLive ?? ""].join("\u0000");
|
|
@@ -197,8 +170,8 @@ export function retainedIn(matrix, input, writeOnly = new Set()) {
|
|
|
197
170
|
return matrix.union.symbols.flatMap((symbol) => held.get(symbol.id) ?? []);
|
|
198
171
|
}
|
|
199
172
|
/**
|
|
200
|
-
* One line per held-back declaration, in site order: its reference, then
|
|
201
|
-
* class, site and detail, all separated by tabs.
|
|
173
|
+
* One line per held-back declaration, in site order: its reference and position, then
|
|
174
|
+
* each record's class, site and detail, all separated by tabs.
|
|
202
175
|
*/
|
|
203
176
|
export function retainedLines(symbols, retained) {
|
|
204
177
|
const held = byDeclaration(retained);
|
|
@@ -212,6 +185,6 @@ export function retainedLines(symbols, retained) {
|
|
|
212
185
|
positionKey(record.site),
|
|
213
186
|
record.detail,
|
|
214
187
|
]);
|
|
215
|
-
return [[symbol.ref, ...fields].join("\t")];
|
|
188
|
+
return [[symbol.ref, positionKey(symbol.position), ...fields].join("\t")];
|
|
216
189
|
});
|
|
217
190
|
}
|
package/dist/src/file-facts.js
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* file below the target root, whether or not a project includes it, and the files a
|
|
4
4
|
* program holds by inclusion rather than by an import.
|
|
5
5
|
*/
|
|
6
|
-
import { IGNORED_DIRECTORIES } from "./discover.js";
|
|
7
6
|
import { packageScope } from "./inventory.js";
|
|
8
7
|
import { dirnamePath, joinPath, relativePath, resolvePath } from "./paths.js";
|
|
9
8
|
import { renderRef } from "./ref.js";
|
|
9
|
+
import { filesBelow } from "./fs/tree.js";
|
|
10
10
|
/** A file name the compiler reads as a source file. */
|
|
11
11
|
const SOURCE_FILE = /\.(?:ts|tsx|mts|cts)$/u;
|
|
12
12
|
/** A file name the compiler reads as a declaration file, which no build emits code from. */
|
|
@@ -30,30 +30,7 @@ function lastLine(text) {
|
|
|
30
30
|
* that cannot be read is skipped, as discovery skips it.
|
|
31
31
|
*/
|
|
32
32
|
export function sourcePaths(host, targetRoot) {
|
|
33
|
-
|
|
34
|
-
const pending = [""];
|
|
35
|
-
for (let dir = pending.pop(); dir !== undefined; dir = pending.pop()) {
|
|
36
|
-
let entries;
|
|
37
|
-
try {
|
|
38
|
-
entries = host.readDirectory(joinPath(targetRoot, dir));
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
for (const entry of entries) {
|
|
44
|
-
const path = dir === "" ? entry.name : `${dir}/${entry.name}`;
|
|
45
|
-
if (entry.directory) {
|
|
46
|
-
if (!IGNORED_DIRECTORIES.has(entry.name)) {
|
|
47
|
-
pending.push(path);
|
|
48
|
-
}
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (SOURCE_FILE.test(entry.name) && !DECLARATION_FILE.test(entry.name)) {
|
|
52
|
-
found.push(path);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return found.sort((a, b) => (a < b ? -1 : 1));
|
|
33
|
+
return filesBelow(host, targetRoot, (name) => SOURCE_FILE.test(name) && !DECLARATION_FILE.test(name));
|
|
57
34
|
}
|
|
58
35
|
/**
|
|
59
36
|
* Every source file below the target root, in path order. A file that cannot be read is
|
|
@@ -3,29 +3,20 @@
|
|
|
3
3
|
* the code's row of the issue-kind vocabulary, and the dials that withhold a finding
|
|
4
4
|
* together with every finding that falls with a root they withhold.
|
|
5
5
|
*/
|
|
6
|
+
import { CODE, FAMILY_KEY_LENGTH, KIND_ROWS, } from "../contract/contract.generated.js";
|
|
6
7
|
import { componentId } from "../components.js";
|
|
7
8
|
import { deadComponents } from "../matrix.js";
|
|
8
9
|
import { OUTSIDE } from "../graph.js";
|
|
9
10
|
import { KINDS } from "../kinds.js";
|
|
10
11
|
import { byPosition, positionKey } from "../position.js";
|
|
11
12
|
import { declarationKey } from "../ref.js";
|
|
12
|
-
import { FAMILY_KEY_LENGTH } from "../resolve.js";
|
|
13
13
|
import { isPartSubject, isRowSubject } from "../suppress.js";
|
|
14
|
-
/** The unused-file code, whose deletion removes every use its file writes. */
|
|
15
|
-
const FILE_NEVER_IMPORTED = "DS1502";
|
|
16
14
|
/**
|
|
17
|
-
* The codes whose subject the run that counts test references holds live,
|
|
18
|
-
*
|
|
19
|
-
* none of a dead declaration's sweep facts.
|
|
15
|
+
* The codes whose subject the run that counts test references holds live, so a test
|
|
16
|
+
* file's candidate reported under one carries none of a dead declaration's sweep facts.
|
|
20
17
|
*/
|
|
21
|
-
const LIVE_SUBJECT = new Set(
|
|
22
|
-
|
|
23
|
-
"DS1102",
|
|
24
|
-
"DS1104",
|
|
25
|
-
"DS1204",
|
|
26
|
-
"DS1301",
|
|
27
|
-
]);
|
|
28
|
-
/** The fixability grammar/analysis.md "Fixability" gives a finding about a held declaration. */
|
|
18
|
+
const LIVE_SUBJECT = new Set(KIND_ROWS.filter((row) => row.holdsLive).map((row) => row.code));
|
|
19
|
+
/** The fixability grammar/analysis/fixability.md gives a finding about a held declaration. */
|
|
29
20
|
const MANUAL = "manual";
|
|
30
21
|
/** The member kinds an object property can declare, which an `in` expression tests by name. */
|
|
31
22
|
const IN_TESTED = new Set([
|
|
@@ -147,7 +138,7 @@ function testCeilings(input, classOf) {
|
|
|
147
138
|
}
|
|
148
139
|
/**
|
|
149
140
|
* The subjects dead only because production code only tests use is: each declaration the
|
|
150
|
-
* sweep marks test-used, each `
|
|
141
|
+
* sweep marks test-used, each `DS1602` file of such code, and each test of dead code every
|
|
151
142
|
* target of which is one. Nothing they hold references a dead declaration outside them, so
|
|
152
143
|
* the rest of a component they share is reported without them.
|
|
153
144
|
*/
|
|
@@ -224,13 +215,13 @@ function membersListed(swept) {
|
|
|
224
215
|
.sort((a, b) => byPosition(a.position, b.position));
|
|
225
216
|
}
|
|
226
217
|
/**
|
|
227
|
-
* The run's dead components with each file a `
|
|
218
|
+
* The run's dead components with each file a `DS1602` finding reports dead among them, so
|
|
228
219
|
* the file's declarations fall with it, and with the components each subject that is no
|
|
229
220
|
* declaration falls with joined into one.
|
|
230
221
|
*/
|
|
231
222
|
function runComponents(swept, findings) {
|
|
232
223
|
const union = swept.matrix.union;
|
|
233
|
-
const reported = new Set(findings.filter((one) => one.code ===
|
|
224
|
+
const reported = new Set(findings.filter((one) => one.code === CODE.fileNeverImported).map((one) => one.position.path));
|
|
234
225
|
const files = new Map(union.symbols.flatMap((symbol, at) => symbol.kind === "file" && reported.has(symbol.position.path) ? [[at, symbol]] : []));
|
|
235
226
|
const computed = files.size === 0
|
|
236
227
|
? swept.sweep.components
|
|
@@ -330,7 +321,7 @@ export function completed(input, findings, kinds = KINDS) {
|
|
|
330
321
|
: candidates.get(judged.id);
|
|
331
322
|
const fallsWith = finding.fallsWith?.[0];
|
|
332
323
|
const joined = fallsWith === undefined ? undefined : componentOf(fallsWith);
|
|
333
|
-
const file = finding.code ===
|
|
324
|
+
const file = finding.code === CODE.fileNeverImported ? files.get(finding.position.path) : undefined;
|
|
334
325
|
const found = joined !== undefined
|
|
335
326
|
? { ...joined, root: false }
|
|
336
327
|
: file !== undefined
|
|
@@ -376,7 +367,7 @@ export function completed(input, findings, kinds = KINDS) {
|
|
|
376
367
|
const ownClass = judged === undefined ? (finding.reachabilityClass ?? "certain") : classOf(judged.id);
|
|
377
368
|
const used = judged !== undefined
|
|
378
369
|
? candidate !== undefined && testUsed.declarations.has(judged.id)
|
|
379
|
-
: finding.code ===
|
|
370
|
+
: finding.code === CODE.fileNeverImported && testUsed.files.has(finding.position.path);
|
|
380
371
|
const reachabilityClass = used && candidate?.testOfDeadCode !== true ? "possible" : ownClass;
|
|
381
372
|
const configurations = candidate?.configurations ??
|
|
382
373
|
(judged === undefined && !part
|
|
@@ -396,7 +387,7 @@ export function completed(input, findings, kinds = KINDS) {
|
|
|
396
387
|
? undefined
|
|
397
388
|
: candidate !== undefined
|
|
398
389
|
? input.dependencies.lastUses.get(candidate.id)
|
|
399
|
-
: finding.code ===
|
|
390
|
+
: finding.code === CODE.fileNeverImported
|
|
400
391
|
? input.dependencies.fileLastUses.get(finding.position.path)
|
|
401
392
|
: undefined;
|
|
402
393
|
return {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { CODE } from "../contract/contract.generated.js";
|
|
1
2
|
import { declarationKey } from "../dependencies.js";
|
|
2
3
|
import { renderRef } from "../ref.js";
|
|
3
4
|
import { nonCodeArtifacts } from "./non-code-artifacts.js";
|
|
4
|
-
const UNUSED_DEPENDENCY = "DS1601";
|
|
5
|
-
const FILE_NEVER_IMPORTED = "DS1502";
|
|
6
5
|
const MESSAGES = {
|
|
7
6
|
dependency: "no import in the target needs the declared dependency",
|
|
8
7
|
"dev-dependency": "no import in the target needs the declared development dependency",
|
|
@@ -25,7 +24,7 @@ function deadCode(input) {
|
|
|
25
24
|
const reachedOnly = new Set(swept.sweep.candidates.filter((one) => one.relation === "reachability").map((one) => one.id));
|
|
26
25
|
for (const finding of nonCodeArtifacts(input)) {
|
|
27
26
|
const id = files.get(finding.position.path);
|
|
28
|
-
if (finding.code ===
|
|
27
|
+
if (finding.code === CODE.fileNeverImported && id !== undefined) {
|
|
29
28
|
dead.add(id);
|
|
30
29
|
if (finding.unreachableOnly === true) {
|
|
31
30
|
reachedOnly.add(id);
|
|
@@ -57,7 +56,7 @@ function unusedDependencies(input, dependencies) {
|
|
|
57
56
|
const atPossible = unbuilt || users?.some((id) => published.has(id)) === true;
|
|
58
57
|
return [
|
|
59
58
|
{
|
|
60
|
-
code:
|
|
59
|
+
code: CODE.unusedDependency,
|
|
61
60
|
position: dependency.position,
|
|
62
61
|
symbol: {
|
|
63
62
|
ref: renderRef(dependency.manifest, {
|
|
@@ -80,5 +79,5 @@ function unusedDependencies(input, dependencies) {
|
|
|
80
79
|
];
|
|
81
80
|
});
|
|
82
81
|
}
|
|
83
|
-
/** The findings of the dependencies
|
|
82
|
+
/** The findings of the dependencies family, `DS1700` to `DS1799`. */
|
|
84
83
|
export const dependenciesAndModuleMachinery = (input) => unusedDependencies(input, input.dependencies);
|
|
@@ -12,7 +12,7 @@ import { readsAndWrites } from "./reads-and-writes.js";
|
|
|
12
12
|
import { selfCheck } from "./self-check.js";
|
|
13
13
|
import { fallenMembers, unusedDeclarations } from "./unused-declarations.js";
|
|
14
14
|
import { visibilityNarrowing } from "./visibility-narrowing.js";
|
|
15
|
-
/** Every
|
|
15
|
+
/** Every emitter this analyzer runs, by the name its tests select it by. */
|
|
16
16
|
export const EMITTERS = new Map([
|
|
17
17
|
["unused-declarations", unusedDeclarations],
|
|
18
18
|
["visibility-narrowing", visibilityNarrowing],
|
|
@@ -51,7 +51,7 @@ function markupKeys(input) {
|
|
|
51
51
|
.filter((symbol) => live.has(symbol.parent))
|
|
52
52
|
.map((symbol) => declarationKey(symbol.ref, symbol.position.path)));
|
|
53
53
|
}
|
|
54
|
-
/** Every
|
|
54
|
+
/** Every emitter's findings over one sweep, and those of any further emitter, completed by one step. */
|
|
55
55
|
function completedOver(input, ...more) {
|
|
56
56
|
return completed(input, [...EMITTERS.values(), ...more].flatMap((emit) => emit(input)));
|
|
57
57
|
}
|
|
@@ -70,8 +70,8 @@ function dialsOver(input, found, suppressed, unmarked) {
|
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
72
|
* Every finding of one run swept under its suppressions' marks, decided in one pass: each
|
|
73
|
-
*
|
|
74
|
-
* finding each record claims withheld, the rest withheld by the dials, so a root one
|
|
73
|
+
* emitter's findings completed by one step, so every component number is minted once, the
|
|
74
|
+
* finding each record claims withheld, the rest withheld by the dials, so a root one emitter
|
|
75
75
|
* reports withholds what another reports in its component, and every declared edge
|
|
76
76
|
* evaluated over what remains, so a pending finding is in its evaluation alone.
|
|
77
77
|
*/
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
+
import { CODE } from "../contract/contract.generated.js";
|
|
1
2
|
import { byPosition } from "../position.js";
|
|
2
|
-
const UNUSED_INTERFACE = "DS1201";
|
|
3
|
-
const UNCALLED_INTERFACE_METHOD = "DS1203";
|
|
4
3
|
/** What each finding says, by what the sweep found about the subject's references. */
|
|
5
4
|
const UNUSED_MESSAGE = "nothing in the target names the interface as a type";
|
|
6
5
|
const UNUSED_DEAD_MESSAGE = "the interface is named as a type only from declarations that are themselves dead";
|
|
@@ -45,7 +44,7 @@ function findingOf(code, symbol, message, implementations) {
|
|
|
45
44
|
}
|
|
46
45
|
/**
|
|
47
46
|
* The findings of the interfaces family, `DS1200` to `DS1299`: `DS1201`, a dead
|
|
48
|
-
* interface, whose members fall with it unreported; and `
|
|
47
|
+
* interface, whose members fall with it unreported; and `DS1202`, a method of a live
|
|
49
48
|
* interface no reference names, unless it is a marker, a method whose every
|
|
50
49
|
* implementation has an empty body. A test file's declaration is neither kind's subject,
|
|
51
50
|
* because a production sweep counts none of the references it can have, save an interface
|
|
@@ -60,7 +59,7 @@ export const interfaces = (input) => {
|
|
|
60
59
|
continue;
|
|
61
60
|
}
|
|
62
61
|
if (symbol.kind === "interface") {
|
|
63
|
-
found.push(findingOf(
|
|
62
|
+
found.push(findingOf(CODE.unusedInterface, symbol, unusedMessage(candidate), run.implementationsOf(candidate.id)));
|
|
64
63
|
continue;
|
|
65
64
|
}
|
|
66
65
|
if (symbol.kind !== "interface-method" ||
|
|
@@ -69,7 +68,7 @@ export const interfaces = (input) => {
|
|
|
69
68
|
marker(input, candidate.id)) {
|
|
70
69
|
continue;
|
|
71
70
|
}
|
|
72
|
-
found.push(findingOf(
|
|
71
|
+
found.push(findingOf(CODE.uncalledInterfaceMethod, symbol, UNCALLED_MESSAGE, run.implementationsOf(symbol.parent)));
|
|
73
72
|
}
|
|
74
73
|
return found;
|
|
75
74
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { CODE } from "../contract/contract.generated.js";
|
|
1
2
|
import { KINDS } from "../kinds.js";
|
|
2
3
|
import { parameterRef } from "../ref.js";
|
|
3
|
-
import {
|
|
4
|
+
import {} from "../intra-function-parts.js";
|
|
4
5
|
import { reachedWithTheTests } from "../sweep.js";
|
|
5
6
|
/** A list of rules as a sentence names them. */
|
|
6
7
|
function spelled(rules) {
|
|
@@ -62,9 +63,9 @@ function reported(input, part, callersUnknown) {
|
|
|
62
63
|
}
|
|
63
64
|
const { free, freeButValued, discardedEverywhere } = input.intraFunction;
|
|
64
65
|
switch (part.code) {
|
|
65
|
-
case
|
|
66
|
+
case CODE.unusedParameter:
|
|
66
67
|
return parameterVerdict(part, free, freeButValued) !== undefined;
|
|
67
|
-
case
|
|
68
|
+
case CODE.unusedResult:
|
|
68
69
|
return (free.has(part.declaration) &&
|
|
69
70
|
discardedEverywhere.has(part.declaration) &&
|
|
70
71
|
!callersUnknown.has(part.declaration));
|
|
@@ -73,7 +74,7 @@ function reported(input, part, callersUnknown) {
|
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
/**
|
|
76
|
-
* The findings of the
|
|
77
|
+
* The findings of the inside-functions family, `DS1401` to `DS1406`, each about a part of
|
|
77
78
|
* the declaration its reference names, at the part's own position, whatever the sweep
|
|
78
79
|
* decided about a production declaration. A part of test code is reported only where the
|
|
79
80
|
* run that counts test references reaches its declaration and that is no test of dead
|
|
@@ -114,11 +115,11 @@ export const intraFunction = (input) => {
|
|
|
114
115
|
const found = [];
|
|
115
116
|
for (const part of input.intraFunction.parts) {
|
|
116
117
|
const declaration = byId.get(part.declaration);
|
|
117
|
-
const overlap = KINDS.get(part.code)?.overlap ?? [];
|
|
118
|
+
const overlap = KINDS.get(part.code)?.overlap?.ts ?? [];
|
|
118
119
|
if (declaration === undefined || !judged(declaration.id) || !reported(input, part, unknown)) {
|
|
119
120
|
continue;
|
|
120
121
|
}
|
|
121
|
-
const verdict = part.code ===
|
|
122
|
+
const verdict = part.code === CODE.unusedParameter
|
|
122
123
|
? parameterVerdict(part, input.intraFunction.free, input.intraFunction.freeButValued)
|
|
123
124
|
: undefined;
|
|
124
125
|
const message = verdict?.fix === "rename"
|
|
@@ -128,7 +129,7 @@ export const intraFunction = (input) => {
|
|
|
128
129
|
code: part.code,
|
|
129
130
|
position: part.position,
|
|
130
131
|
symbol: {
|
|
131
|
-
...(part.code ===
|
|
132
|
+
...(part.code === CODE.unusedParameter
|
|
132
133
|
? { ref: parameterRef(declaration.ref, part.name), holder: declaration.ref }
|
|
133
134
|
: { ref: declaration.ref }),
|
|
134
135
|
kind: part.kind,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const FILE_NEVER_IMPORTED = "DS1502";
|
|
1
|
+
import { CODE } from "../contract/contract.generated.js";
|
|
3
2
|
/** The subject kind of a finding about a source file, from the finding schema's vocabulary. */
|
|
4
3
|
const FILE_SUBJECT = "file";
|
|
5
4
|
/** A file's subject starts at its first character. */
|
|
@@ -40,7 +39,7 @@ function fileNeverBuilt({ config, swept, files }) {
|
|
|
40
39
|
const message = `no project of the build matrix includes this file (${swept.matrix.configurations.join(", ")})`;
|
|
41
40
|
return files.tree
|
|
42
41
|
.filter((file) => !built.has(file.path))
|
|
43
|
-
.map((file) => fileFinding(
|
|
42
|
+
.map((file) => fileFinding(CODE.fileNeverBuilt, file, message));
|
|
44
43
|
}
|
|
45
44
|
/**
|
|
46
45
|
* The paths of the files a reference from a live declaration of another file reaches, a
|
|
@@ -125,13 +124,13 @@ function fileNeverImported(input) {
|
|
|
125
124
|
const file = { path: symbol.position.path, ref: symbol.ref, endLine: symbol.endLine };
|
|
126
125
|
return referenced.has(symbol.position.path)
|
|
127
126
|
? {
|
|
128
|
-
...fileFinding(
|
|
127
|
+
...fileFinding(CODE.fileNeverImported, file, "only code that is itself dead imports this file, and no root names it or a declaration in it"),
|
|
129
128
|
unreachableOnly: true,
|
|
130
129
|
}
|
|
131
|
-
: fileFinding(
|
|
130
|
+
: fileFinding(CODE.fileNeverImported, file, "no import reaches this file and no root names it or a declaration in it");
|
|
132
131
|
});
|
|
133
132
|
}
|
|
134
|
-
/** The findings of the
|
|
133
|
+
/** The findings of the files family, `DS1600` to `DS1699`. */
|
|
135
134
|
export const nonCodeArtifacts = (input) => [
|
|
136
135
|
...fileNeverBuilt(input),
|
|
137
136
|
...fileNeverImported(input),
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { CODE } from "../contract/contract.generated.js";
|
|
1
2
|
import { positionKey } from "../position.js";
|
|
2
3
|
import { declarationKey } from "../ref.js";
|
|
3
|
-
|
|
4
|
+
import { bytewise } from "../text/compare.js";
|
|
5
|
+
/** The containers whose type parameters `DS1006` reports: a function, a class method and a type alias. */
|
|
4
6
|
const SIGNATURES = new Set(["function", "method", "type"]);
|
|
5
7
|
function indexed(input) {
|
|
6
8
|
const { matrix, sweep } = input.swept;
|
|
@@ -75,7 +77,7 @@ function writeOnlyMessage(run, namedBy, symbol, held) {
|
|
|
75
77
|
: "never read";
|
|
76
78
|
const cascade = [
|
|
77
79
|
...parametersOnlyNamedBy(run, namedBy, symbol).map((name) => `type parameter ${name}`),
|
|
78
|
-
...[...held.alone].sort().map((name) => `import ${name}`),
|
|
80
|
+
...[...held.alone].sort(bytewise).map((name) => `import ${name}`),
|
|
79
81
|
];
|
|
80
82
|
const word = SUBJECT_WORDS[symbol.kind] ?? "member";
|
|
81
83
|
const message = `${word} ${symbol.name} is written ${writes} and ${read}`;
|
|
@@ -133,7 +135,7 @@ function writeOnlySymbols(run) {
|
|
|
133
135
|
run.candidates.has(symbol.id)) {
|
|
134
136
|
continue;
|
|
135
137
|
}
|
|
136
|
-
found.push(findingAbout(symbol,
|
|
138
|
+
found.push(findingAbout(symbol, CODE.writeOnlySymbol, writeOnlyMessage(run, namedBy, symbol, held), {
|
|
137
139
|
writePositions: held.writes,
|
|
138
140
|
}));
|
|
139
141
|
}
|
|
@@ -157,15 +159,15 @@ function unnamed(run, kind) {
|
|
|
157
159
|
});
|
|
158
160
|
}
|
|
159
161
|
/**
|
|
160
|
-
* `
|
|
162
|
+
* `DS1005`: a member of an enum declaration that nothing names. A member an enum-group
|
|
161
163
|
* record holds back is no candidate, so a member a conversion can produce never reaches
|
|
162
164
|
* this kind.
|
|
163
165
|
*/
|
|
164
166
|
function unusedEnumMembers(run) {
|
|
165
|
-
return unnamed(run, "enum-member").map((symbol) => findingAbout(symbol,
|
|
167
|
+
return unnamed(run, "enum-member").map((symbol) => findingAbout(symbol, CODE.unusedEnumMember, `enum member ${symbol.name} is named nowhere`));
|
|
166
168
|
}
|
|
167
169
|
/**
|
|
168
|
-
* `
|
|
170
|
+
* `DS1006`: a type parameter of a function, a class method or a type alias that neither
|
|
169
171
|
* the declaration's signature nor its body names. An alias names no type of its own, so
|
|
170
172
|
* a parameter its type never names makes no two instantiations distinct. One of a class,
|
|
171
173
|
* an interface or a method signature is never reported: a class or an interface merges
|
|
@@ -174,7 +176,7 @@ function unusedEnumMembers(run) {
|
|
|
174
176
|
function unusedTypeParameters(run) {
|
|
175
177
|
return unnamed(run, "type-parameter")
|
|
176
178
|
.filter((symbol) => SIGNATURES.has(run.symbols.get(symbol.parent)?.kind ?? ""))
|
|
177
|
-
.map((symbol) => findingAbout(symbol,
|
|
179
|
+
.map((symbol) => findingAbout(symbol, CODE.unusedTypeParameter, `type parameter ${symbol.name} is named in neither its signature nor its body`));
|
|
178
180
|
}
|
|
179
181
|
/**
|
|
180
182
|
* The keys of the declarations the write-only kind reports, whatever the
|
|
@@ -185,8 +187,8 @@ export function writeOnlyDeclarations(input) {
|
|
|
185
187
|
return new Set(writeOnlySymbols(indexed(input)).map((finding) => declarationKey(finding.symbol.ref, finding.position.path)));
|
|
186
188
|
}
|
|
187
189
|
/**
|
|
188
|
-
* The findings of the reads-and-writes
|
|
189
|
-
* each code's in site order.
|
|
190
|
+
* The findings of the reads-and-writes kinds, `DS1301`, `DS1005` and `DS1006`, in that
|
|
191
|
+
* order and each code's in site order.
|
|
190
192
|
*/
|
|
191
193
|
export const readsAndWrites = (input) => {
|
|
192
194
|
const run = indexed(input);
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
+
import { CODE } from "../contract/contract.generated.js";
|
|
1
2
|
import { REPOSITORY_DOCUMENT } from "../config.js";
|
|
2
3
|
import { FIXED_SEVERITY_CODES } from "../kinds.js";
|
|
3
|
-
import { isDependencyCode, isUnsuppressibleCode,
|
|
4
|
-
|
|
5
|
-
const UNMATCHED_ROOT = "DS1704";
|
|
6
|
-
/** The code a configured declaration that names nothing is reported under. */
|
|
7
|
-
const UNMATCHED_DECLARATION = "DS1706";
|
|
4
|
+
import { isDependencyCode, isUnsuppressibleCode, } from "../suppress.js";
|
|
5
|
+
import { bytewise } from "../text/compare.js";
|
|
8
6
|
/** The subject kind of a finding about a configured declaration. */
|
|
9
7
|
const DECLARATION_SUBJECT = "configured-declaration";
|
|
10
8
|
/** The subject kind of a finding about a suppression record. */
|
|
@@ -63,7 +61,7 @@ function suppressionRef(symbol, path, files) {
|
|
|
63
61
|
}
|
|
64
62
|
/** One finding per refused suppression: the grammar's reason refusal and its scope refusal. */
|
|
65
63
|
function refusedSuppressions(refusals, files) {
|
|
66
|
-
return refusals.map((refused) => aboutSuppression(refused.reported, suppressionRef(refused.symbol, refused.path, files), refused.site, `${WRITTEN[refused.mechanism]} for ${refused.code} ${refused.reported ===
|
|
64
|
+
return refusals.map((refused) => aboutSuppression(refused.reported, suppressionRef(refused.symbol, refused.path, files), refused.site, `${WRITTEN[refused.mechanism]} for ${refused.code} ${refused.reported === CODE.suppressionWithoutReason
|
|
67
65
|
? "carries no reason"
|
|
68
66
|
: "names a symbol and no path"}`, { mechanism: refused.mechanism, entry: writtenEntry(refused) }));
|
|
69
67
|
}
|
|
@@ -83,10 +81,10 @@ export function staleSuppressions(stale, files) {
|
|
|
83
81
|
bySite.set(key, held);
|
|
84
82
|
}
|
|
85
83
|
return [...bySite.values()].map(({ first, records }) => {
|
|
86
|
-
const codes = [...new Set(records.map((one) => one.record.code))].sort();
|
|
84
|
+
const codes = [...new Set(records.map((one) => one.record.code))].sort(bytewise);
|
|
87
85
|
const reports = [...new Set(records.flatMap((one) => one.reports))]
|
|
88
86
|
.filter((code) => !codes.includes(code))
|
|
89
|
-
.sort();
|
|
87
|
+
.sort(bytewise);
|
|
90
88
|
const rows = codes.filter(isUnsuppressibleCode);
|
|
91
89
|
const dependencies = first.mechanism === "inline" ? codes.filter(isDependencyCode) : [];
|
|
92
90
|
const settable = rows.filter((code) => !FIXED_SEVERITY_CODES.includes(code));
|
|
@@ -112,7 +110,7 @@ export function staleSuppressions(stale, files) {
|
|
|
112
110
|
? ""
|
|
113
111
|
: `, and ${declared}`;
|
|
114
112
|
return {
|
|
115
|
-
code:
|
|
113
|
+
code: CODE.staleSuppression,
|
|
116
114
|
mechanism: first.mechanism,
|
|
117
115
|
entry: {
|
|
118
116
|
code: first.code,
|
|
@@ -141,7 +139,7 @@ function documentPosition(document) {
|
|
|
141
139
|
*/
|
|
142
140
|
function unmatchedDeclarationFindings(unmatched) {
|
|
143
141
|
return unmatched.map((one) => ({
|
|
144
|
-
code:
|
|
142
|
+
code: CODE.unmatchedConfiguredDeclaration,
|
|
145
143
|
position: documentPosition(one.document),
|
|
146
144
|
symbol: { ref: one.ref, kind: DECLARATION_SUBJECT, name: one.ref, sizeLines: 1 },
|
|
147
145
|
message: `${one.key} entry names no declaration in any project`,
|
|
@@ -157,7 +155,7 @@ function unmatchedDeclarationFindings(unmatched) {
|
|
|
157
155
|
export function unmatchedRootFindings(sources, document) {
|
|
158
156
|
const position = documentPosition(document);
|
|
159
157
|
return sources.map((source) => ({
|
|
160
|
-
code:
|
|
158
|
+
code: CODE.unmatchedRoot,
|
|
161
159
|
position,
|
|
162
160
|
symbol: { ref: source, kind: ROOT_SUBJECT, name: source, sizeLines: 1 },
|
|
163
161
|
message: source.includes("*") || source.includes("?")
|
|
@@ -166,7 +164,7 @@ export function unmatchedRootFindings(sources, document) {
|
|
|
166
164
|
}));
|
|
167
165
|
}
|
|
168
166
|
/**
|
|
169
|
-
* The findings of the
|
|
167
|
+
* The findings of the configuration family, `DS9000` to `DS9099`: a suppression refused for
|
|
170
168
|
* carrying no reason or naming no path, and a configured root or declaration that named
|
|
171
169
|
* nothing. A
|
|
172
170
|
* suppression that matched nothing is a record of the report's stale suppressions, which
|