@cplieger/deadset-ts 2.2.0 → 2.3.0
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 +5 -3
- package/dist/src/analysis.js +109 -0
- package/dist/src/config.js +6 -0
- package/dist/src/entry-point-gaps.js +278 -0
- package/dist/src/entry-points.js +385 -0
- package/dist/src/finding.js +12 -0
- package/dist/src/glob.js +65 -0
- package/dist/src/index.js +1 -0
- package/dist/src/manifest.js +120 -0
- package/dist/src/references.js +15 -79
- package/dist/src/roots.js +345 -0
- package/dist/src/run.js +48 -3
- package/dist/src/session.js +6 -1
- package/dist/src/source-files.js +122 -0
- package/jsr.json +1 -1
- package/package.json +3 -3
- package/src/analysis.ts +169 -0
- package/src/config.ts +7 -0
- package/src/entry-point-gaps.ts +304 -0
- package/src/entry-points.ts +496 -0
- package/src/finding.ts +43 -0
- package/src/glob.ts +67 -0
- package/src/index.ts +1 -0
- package/src/manifest.ts +174 -0
- package/src/references.ts +15 -83
- package/src/roots.ts +467 -0
- package/src/run.ts +55 -4
- package/src/session.ts +6 -1
- package/src/source-files.ts +157 -0
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ deadset-ts is a command-line analyzer for TypeScript and JavaScript projects. It
|
|
|
8
8
|
|
|
9
9
|
deadset-ts is report-only. It never edits source, and it refuses any `--fix` flag.
|
|
10
10
|
|
|
11
|
-
**Status: pre-release.** This version implements contract 2.1.0 and ships the analyzer's foundation: one compiler session per run over every `tsconfig` project discovered under the target (the explicit scope, every `tsconfig*.json`, each project's `references`), a fail-closed read of every project's diagnostics, configuration decoding against the contract's closed key list with `print-config` and its provenance, `print-projects`, the report-only guard, the symbol inventory of every declaration a project's own files hold down to its class and type members,
|
|
11
|
+
**Status: pre-release.** This version implements contract 2.1.0 and ships the analyzer's foundation: one compiler session per run over every `tsconfig` project discovered under the target (the explicit scope, every `tsconfig*.json`, each project's `references`), a fail-closed read of every project's diagnostics, configuration decoding against the contract's closed key list with `print-config` and its provenance, `print-projects`, the report-only guard, the symbol inventory of every declaration a project's own files hold down to its class and type members, the one-pass reference resolution over that inventory, and the root set `print-roots` prints. A root is a declaration the analysis keeps live without a reference: what a file exports when the manifest names it through `main`, `module`, `types`, `bin` or `exports`, or when `ts.entry_files` matches it; a library target's published API; the configuration, setup and test files of Vitest, Stryker and Playwright, the flat configuration of ESLint, and a worker or service worker a call addresses by a string literal; and every declaration a `roots.patterns` entry names. An entry that names nothing is reported as `DS1704` and fails the run. The entry-point conventions of other tools are not read, and `DECLINED_CONVENTIONS` lists each one with the reason. The inventory and the reference pass are library functions the package exports; no other verb reports findings yet, so `analyze`, `explain`, `print-retained` and `describe` exit with a usage message. The one runtime dependency is the `typescript` package at exactly 7.0.2, installed under the `@typescript/native` name until TypeScript 7.1 ships a compiler API the tooling can share.
|
|
12
12
|
|
|
13
13
|
## Install
|
|
14
14
|
|
|
@@ -28,14 +28,15 @@ The npm package carries the command and the library as JavaScript that the compi
|
|
|
28
28
|
npx deadset-ts version
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
`version` prints the analyzer version and the Contract version it implements, and exits 0.
|
|
31
|
+
`version` prints the analyzer version and the Contract version it implements, and exits 0. `print-config`, `print-projects` and `print-roots` print what their row of the table says and exit 0, or 1 when `print-roots` reports a `DS1704`. `analyze`, `explain`, `print-retained`, `describe`, any other invocation and no arguments print the usage line and exit 2.
|
|
32
32
|
|
|
33
33
|
| Verb | Job |
|
|
34
34
|
| ---------------- | ------------------------------------------------------------------------------- |
|
|
35
35
|
| `analyze` | Analyze a project and print the findings |
|
|
36
36
|
| `explain` | Explain one finding: the relation, the roots and the references that decided it |
|
|
37
37
|
| `print-config` | Print the resolved configuration and where each setting came from |
|
|
38
|
-
| `print-
|
|
38
|
+
| `print-projects` | Print the compiler configuration of every project a run analyzes |
|
|
39
|
+
| `print-roots` | Print every declaration the analysis keeps live without a reference, and why |
|
|
39
40
|
| `print-retained` | Print every symbol an exemption class held back, with the class |
|
|
40
41
|
| `describe` | Describe the analyzer: version, Contract version, supported issue kinds |
|
|
41
42
|
| `version` | Print the analyzer and Contract versions |
|
|
@@ -90,6 +91,7 @@ Stable symbol references:
|
|
|
90
91
|
|
|
91
92
|
Versions:
|
|
92
93
|
|
|
94
|
+
- `DECLINED_CONVENTIONS`, `DeclinedConvention`: the entry-point conventions of other tools the analysis does not read, one row per tool or convention with the reason.
|
|
93
95
|
- `CONTRACT_VERSION`: the contract version this analyzer implements.
|
|
94
96
|
|
|
95
97
|
## Contributing
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One run's passes, composed: the projects discovery names, opened in one snapshot
|
|
3
|
+
* of one client, each read through the stages in the order they depend on each
|
|
4
|
+
* other, and the per-project answers merged into the answer for the run.
|
|
5
|
+
*
|
|
6
|
+
* The stages take a project's view, which only this composition makes: a view
|
|
7
|
+
* carries a project's identity in its type so a handle cannot cross to another
|
|
8
|
+
* project's checker, and that holds only for views the session itself hands out.
|
|
9
|
+
*/
|
|
10
|
+
import { diagnosticErrors, discoverProjects, DiscoveryError } from "./discover.js";
|
|
11
|
+
import { inventory } from "./inventory.js";
|
|
12
|
+
import { readManifest } from "./manifest.js";
|
|
13
|
+
import { relativePath, resolvePath } from "./paths.js";
|
|
14
|
+
import { byPosition } from "./position.js";
|
|
15
|
+
import { roots, unmatchedEverywhere, unmatchedRoots } from "./roots.js";
|
|
16
|
+
import { diagnosticsOf, runSession } from "./session.js";
|
|
17
|
+
/** The setting whose source decides where a finding about a configured root sits. */
|
|
18
|
+
const ROOTS_SETTING = "roots.patterns";
|
|
19
|
+
/**
|
|
20
|
+
* The document that supplied one setting, below the target root, or the empty
|
|
21
|
+
* string where the setting came from no document of the target. Both paths are
|
|
22
|
+
* resolved against the working directory before one is read below the other, so a
|
|
23
|
+
* relative target and a relative document name the same place.
|
|
24
|
+
*/
|
|
25
|
+
function documentOf(host, provenance, setting, targetRoot) {
|
|
26
|
+
const origin = provenance.get(setting);
|
|
27
|
+
if (origin === undefined || origin.source === "default" || origin.source === "flag") {
|
|
28
|
+
return "";
|
|
29
|
+
}
|
|
30
|
+
const document = resolvePath(host.workingDirectory(), origin.label);
|
|
31
|
+
return relativePath(resolvePath(host.workingDirectory(), targetRoot), document) ?? "";
|
|
32
|
+
}
|
|
33
|
+
/** Two strings ordered bytewise. */
|
|
34
|
+
function compare(a, b) {
|
|
35
|
+
if (a === b) {
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
return a < b ? -1 : 1;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The root set of the run the scope and the configuration describe.
|
|
42
|
+
*
|
|
43
|
+
* Every project is read for errors before anything else, and a project carrying one
|
|
44
|
+
* fails the run with no root set, as every verb that reads declarations does. A
|
|
45
|
+
* configured string is a finding when it names nothing in every project, and the
|
|
46
|
+
* finding sits in the document that declared the roots.
|
|
47
|
+
*/
|
|
48
|
+
export function runRoots(engine, host, scope, config, provenance) {
|
|
49
|
+
const targetRoot = scope.target.path;
|
|
50
|
+
const discovered = discoverProjects(engine, host, scope);
|
|
51
|
+
const manifest = readManifest(host, targetRoot);
|
|
52
|
+
const options = {
|
|
53
|
+
manifest,
|
|
54
|
+
patterns: config.rootPatterns,
|
|
55
|
+
entryFiles: config.ts.entryFiles,
|
|
56
|
+
testFiles: config.ts.testFiles,
|
|
57
|
+
publishedAPI: config.targetKind === "library",
|
|
58
|
+
};
|
|
59
|
+
const failures = [];
|
|
60
|
+
const { projects } = runSession(engine, discovered.configFiles, (project) => {
|
|
61
|
+
const errors = diagnosticErrors(diagnosticsOf(project));
|
|
62
|
+
if (errors.length > 0) {
|
|
63
|
+
failures.push(...errors);
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const held = inventory(project, host, targetRoot);
|
|
67
|
+
return { held, rooted: roots(project, held, targetRoot, options) };
|
|
68
|
+
});
|
|
69
|
+
if (failures.length > 0) {
|
|
70
|
+
throw new DiscoveryError(`${String(failures.length)} error(s); no answer was produced`, failures);
|
|
71
|
+
}
|
|
72
|
+
const configurations = [];
|
|
73
|
+
const merged = new Map();
|
|
74
|
+
for (const answer of projects) {
|
|
75
|
+
if (answer === undefined) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const configuration = relativePath(targetRoot, answer.rooted.configFile) ?? answer.rooted.configFile;
|
|
79
|
+
configurations.push(configuration);
|
|
80
|
+
const symbols = new Map(answer.held.symbols.map((symbol) => [symbol.id, symbol]));
|
|
81
|
+
for (const root of answer.rooted.liveUnderReachability) {
|
|
82
|
+
const symbol = symbols.get(root.id);
|
|
83
|
+
if (symbol === undefined) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const key = [root.id, root.kind, root.source].join("\u0000");
|
|
87
|
+
const held = merged.get(key);
|
|
88
|
+
if (held === undefined) {
|
|
89
|
+
merged.set(key, {
|
|
90
|
+
ref: symbol.ref,
|
|
91
|
+
position: symbol.position,
|
|
92
|
+
kind: root.kind,
|
|
93
|
+
source: root.source,
|
|
94
|
+
configurations: [configuration],
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else if (!held.configurations.includes(configuration)) {
|
|
98
|
+
held.configurations.push(configuration);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const ordered = [...merged.values()].sort((a, b) => byPosition(a.position, b.position) || compare(a.kind, b.kind) || compare(a.source, b.source));
|
|
103
|
+
const unmatched = unmatchedEverywhere(config.rootPatterns, projects.flatMap((answer) => (answer === undefined ? [] : [answer.rooted])));
|
|
104
|
+
return {
|
|
105
|
+
configurations,
|
|
106
|
+
roots: ordered,
|
|
107
|
+
findings: unmatchedRoots(unmatched, documentOf(host, provenance, ROOTS_SETTING, targetRoot)),
|
|
108
|
+
};
|
|
109
|
+
}
|
package/dist/src/config.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { CONTRACT_VERSION } from "./version.js";
|
|
2
|
+
/**
|
|
3
|
+
* The name of the repository configuration at the target root, which is also the
|
|
4
|
+
* document a finding about the configuration names where no document of the
|
|
5
|
+
* target supplied the setting it is about.
|
|
6
|
+
*/
|
|
7
|
+
export const REPOSITORY_DOCUMENT = "deadset.json";
|
|
2
8
|
/**
|
|
3
9
|
* The configuration every documented default states. `targetKind` is empty: the
|
|
4
10
|
* field has no default and is never inferred.
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every entry-point convention this analyzer declines, each with the tool it belongs
|
|
3
|
+
* to and why. A file only a declined convention enters is reported as never
|
|
4
|
+
* imported, so a project that relies on one names the file in `ts.entry_files` or
|
|
5
|
+
* `roots.patterns`, and this list is what tells it to.
|
|
6
|
+
*
|
|
7
|
+
* Every row carries a reason, because the list is read where the rows are shown
|
|
8
|
+
* one at a time: beside a finding, or in a report's declared gaps.
|
|
9
|
+
*/
|
|
10
|
+
/** What is declined for a tool none of whose conventions is entered. */
|
|
11
|
+
const EVERY_CONVENTION = "its configuration and every file it loads by its own convention";
|
|
12
|
+
/** Why a tool none of whose conventions is entered declines them. */
|
|
13
|
+
const UNREAD = "No rule reads it, so a file only it loads is reported as never imported unless " +
|
|
14
|
+
"ts.entry_files or roots.patterns names it.";
|
|
15
|
+
/** The tools none of whose conventions is entered. */
|
|
16
|
+
const UNREAD_TOOLS = [
|
|
17
|
+
"angular",
|
|
18
|
+
"astro",
|
|
19
|
+
"astro-db",
|
|
20
|
+
"astro-markdoc",
|
|
21
|
+
"astro-og-canvas",
|
|
22
|
+
"ava",
|
|
23
|
+
"babel",
|
|
24
|
+
"biome",
|
|
25
|
+
"borp",
|
|
26
|
+
"bumpp",
|
|
27
|
+
"bun",
|
|
28
|
+
"c8",
|
|
29
|
+
"capacitor",
|
|
30
|
+
"catalyst",
|
|
31
|
+
"changelogen",
|
|
32
|
+
"changelogithub",
|
|
33
|
+
"changesets",
|
|
34
|
+
"commitizen",
|
|
35
|
+
"commitlint",
|
|
36
|
+
"convex",
|
|
37
|
+
"create-typescript-app",
|
|
38
|
+
"cspell",
|
|
39
|
+
"cucumber",
|
|
40
|
+
"cypress",
|
|
41
|
+
"danger",
|
|
42
|
+
"dependency-cruiser",
|
|
43
|
+
"docusaurus",
|
|
44
|
+
"dotenv",
|
|
45
|
+
"drizzle",
|
|
46
|
+
"electron-vite",
|
|
47
|
+
"eleventy",
|
|
48
|
+
"esbuild",
|
|
49
|
+
"eve",
|
|
50
|
+
"execa",
|
|
51
|
+
"expo",
|
|
52
|
+
"expressive-code",
|
|
53
|
+
"fast",
|
|
54
|
+
"fumadocs",
|
|
55
|
+
"gatsby",
|
|
56
|
+
"github-action",
|
|
57
|
+
"github-actions",
|
|
58
|
+
"glob",
|
|
59
|
+
"graphql-codegen",
|
|
60
|
+
"hardhat",
|
|
61
|
+
"husky",
|
|
62
|
+
"i18next-parser",
|
|
63
|
+
"jest",
|
|
64
|
+
"karma",
|
|
65
|
+
"knex",
|
|
66
|
+
"ladle",
|
|
67
|
+
"laravel-vite-plugin",
|
|
68
|
+
"lefthook",
|
|
69
|
+
"lint-staged",
|
|
70
|
+
"linthtml",
|
|
71
|
+
"lit",
|
|
72
|
+
"lockfile-lint",
|
|
73
|
+
"lost-pixel",
|
|
74
|
+
"lunaria",
|
|
75
|
+
"markdownlint",
|
|
76
|
+
"marko",
|
|
77
|
+
"mdx",
|
|
78
|
+
"mdxlint",
|
|
79
|
+
"metro",
|
|
80
|
+
"mise",
|
|
81
|
+
"mocha",
|
|
82
|
+
"moonrepo",
|
|
83
|
+
"msw",
|
|
84
|
+
"nano-spawn",
|
|
85
|
+
"nano-staged",
|
|
86
|
+
"nest",
|
|
87
|
+
"netlify",
|
|
88
|
+
"next",
|
|
89
|
+
"next-intl",
|
|
90
|
+
"next-mdx",
|
|
91
|
+
"nitro",
|
|
92
|
+
"node",
|
|
93
|
+
"node-modules-inspector",
|
|
94
|
+
"nodemon",
|
|
95
|
+
"npm-package-json-lint",
|
|
96
|
+
"nuxt",
|
|
97
|
+
"nuxtjs-i18n",
|
|
98
|
+
"nx",
|
|
99
|
+
"nyc",
|
|
100
|
+
"oclif",
|
|
101
|
+
"openapi-ts",
|
|
102
|
+
"openclaw",
|
|
103
|
+
"orval",
|
|
104
|
+
"oxfmt",
|
|
105
|
+
"oxlint",
|
|
106
|
+
"panda-css",
|
|
107
|
+
"parcel",
|
|
108
|
+
"payload",
|
|
109
|
+
"pino",
|
|
110
|
+
"playwright-ct",
|
|
111
|
+
"playwright-test",
|
|
112
|
+
"plop",
|
|
113
|
+
"pm2",
|
|
114
|
+
"pnpm",
|
|
115
|
+
"postcss",
|
|
116
|
+
"pre-commit",
|
|
117
|
+
"preconstruct",
|
|
118
|
+
"prettier",
|
|
119
|
+
"prisma",
|
|
120
|
+
"quasar",
|
|
121
|
+
"qwik",
|
|
122
|
+
"railway",
|
|
123
|
+
"raycast",
|
|
124
|
+
"react-cosmos",
|
|
125
|
+
"react-email",
|
|
126
|
+
"react-native",
|
|
127
|
+
"react-router",
|
|
128
|
+
"relay",
|
|
129
|
+
"release-it",
|
|
130
|
+
"remark",
|
|
131
|
+
"remix",
|
|
132
|
+
"rolldown",
|
|
133
|
+
"rollup",
|
|
134
|
+
"rsbuild",
|
|
135
|
+
"rslib",
|
|
136
|
+
"rspack",
|
|
137
|
+
"rstest",
|
|
138
|
+
"sanity",
|
|
139
|
+
"semantic-release",
|
|
140
|
+
"sentry",
|
|
141
|
+
"serverless-framework",
|
|
142
|
+
"simple-git-hooks",
|
|
143
|
+
"size-limit",
|
|
144
|
+
"sst",
|
|
145
|
+
"starlight",
|
|
146
|
+
"stencil",
|
|
147
|
+
"storybook",
|
|
148
|
+
"stylelint",
|
|
149
|
+
"svelte",
|
|
150
|
+
"sveltejs-package",
|
|
151
|
+
"sveltekit",
|
|
152
|
+
"svgo",
|
|
153
|
+
"svgr",
|
|
154
|
+
"swc",
|
|
155
|
+
"syncpack",
|
|
156
|
+
"tailwind",
|
|
157
|
+
"tanstack-router",
|
|
158
|
+
"taskfile",
|
|
159
|
+
"tauri",
|
|
160
|
+
"temporal",
|
|
161
|
+
"textlint",
|
|
162
|
+
"travis",
|
|
163
|
+
"ts-node",
|
|
164
|
+
"tsd",
|
|
165
|
+
"tsdown",
|
|
166
|
+
"tsup",
|
|
167
|
+
"tsx",
|
|
168
|
+
"turbo",
|
|
169
|
+
"typedoc",
|
|
170
|
+
"typescript",
|
|
171
|
+
"typescript-content-mapper",
|
|
172
|
+
"unbuild",
|
|
173
|
+
"unocss",
|
|
174
|
+
"unplugin-auto-import",
|
|
175
|
+
"unplugin-icons",
|
|
176
|
+
"unplugin-vue-components",
|
|
177
|
+
"unplugin-vue-i18n",
|
|
178
|
+
"unplugin-vue-markdown",
|
|
179
|
+
"unplugin-vue-router",
|
|
180
|
+
"varlock",
|
|
181
|
+
"vercel",
|
|
182
|
+
"vercel-og",
|
|
183
|
+
"vike",
|
|
184
|
+
"vite-plugin-pages",
|
|
185
|
+
"vite-plugin-pwa",
|
|
186
|
+
"vite-plugin-vue-layouts-next",
|
|
187
|
+
"vite-plus",
|
|
188
|
+
"vite-pwa-assets-generator",
|
|
189
|
+
"vitepress",
|
|
190
|
+
"vue",
|
|
191
|
+
"webdriver-io",
|
|
192
|
+
"wireit",
|
|
193
|
+
"wrangler",
|
|
194
|
+
"wxt",
|
|
195
|
+
"xo",
|
|
196
|
+
"yarn",
|
|
197
|
+
"yorkie",
|
|
198
|
+
"zx",
|
|
199
|
+
];
|
|
200
|
+
/** The conventions declined for a tool some of whose conventions are entered. */
|
|
201
|
+
const PARTLY_ENTERED = [
|
|
202
|
+
{
|
|
203
|
+
tool: "eslint",
|
|
204
|
+
convention: "the legacy .eslintrc configuration files",
|
|
205
|
+
reason: "Only the flat configuration's file names are entered, so a legacy configuration " +
|
|
206
|
+
"file the program holds is reported as never imported.",
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
tool: "playwright",
|
|
210
|
+
convention: "a testMatch written as a regular expression",
|
|
211
|
+
reason: "A testMatch that is not a string literal leaves the test-file set unknown, and an " +
|
|
212
|
+
"unknown set enters nothing.",
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
tool: "playwright",
|
|
216
|
+
convention: "the globalSetup and globalTeardown files",
|
|
217
|
+
reason: "No rule enters them, so a setup file only the runner loads is reported as never imported.",
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
tool: "playwright",
|
|
221
|
+
convention: "the testDir and testMatch of an entry in projects",
|
|
222
|
+
reason: "Only the configuration object's own testDir and testMatch are read, so a test " +
|
|
223
|
+
"directory a project entry moves is not entered.",
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
tool: "stryker",
|
|
227
|
+
convention: "a configuration file named on the command line",
|
|
228
|
+
reason: "Only the file names the tool looks for by default are entered.",
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
tool: "vite",
|
|
232
|
+
convention: "its configuration and every entry point it names",
|
|
233
|
+
reason: "Only a worker a call addresses by a literal is entered; no rule reads the " +
|
|
234
|
+
"configuration, so a file only it names is reported as never imported.",
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
tool: "vitest",
|
|
238
|
+
convention: "the benchmark and type-test files",
|
|
239
|
+
reason: "A test file is one ts.test_files classifies, so a *.bench.* or *.test-d.* file is " +
|
|
240
|
+
"entered only where a configured pattern names it.",
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
tool: "vitest",
|
|
244
|
+
convention: "the mock files below a __mocks__ directory",
|
|
245
|
+
reason: "No rule enters a file by its directory, so a mock only the runner's module mocking " +
|
|
246
|
+
"loads is reported as never imported.",
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
tool: "vitest",
|
|
250
|
+
convention: "the setup files of a configuration that moves its root",
|
|
251
|
+
reason: "A configuration writing root reads its setup files against a directory its text " +
|
|
252
|
+
"may not state, so none of them is entered.",
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
tool: "vitest",
|
|
256
|
+
convention: "the test files a configuration's include member names",
|
|
257
|
+
reason: "A test file is one ts.test_files classifies rather than one the runner's include " +
|
|
258
|
+
"reads, so the two are kept equal by configuration.",
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
tool: "webpack",
|
|
262
|
+
convention: "its configuration and every entry point it names",
|
|
263
|
+
reason: "Only a worker a call addresses by a literal is entered; no rule reads the " +
|
|
264
|
+
"configuration, so a file only it names is reported as never imported.",
|
|
265
|
+
},
|
|
266
|
+
];
|
|
267
|
+
/** Two strings ordered bytewise. */
|
|
268
|
+
function compare(a, b) {
|
|
269
|
+
if (a === b) {
|
|
270
|
+
return 0;
|
|
271
|
+
}
|
|
272
|
+
return a < b ? -1 : 1;
|
|
273
|
+
}
|
|
274
|
+
/** Every declined entry-point convention, ordered by tool and then by convention. */
|
|
275
|
+
export const DECLINED_CONVENTIONS = [
|
|
276
|
+
...UNREAD_TOOLS.map((tool) => ({ tool, convention: EVERY_CONVENTION, reason: UNREAD })),
|
|
277
|
+
...PARTLY_ENTERED,
|
|
278
|
+
].sort((a, b) => compare(a.tool, b.tool) || compare(a.convention, b.convention));
|