@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/conventions.ts
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
10
|
isArrayLiteralExpression,
|
|
11
|
-
isAsExpression,
|
|
12
11
|
isBinaryExpression,
|
|
13
12
|
isCallExpression,
|
|
14
13
|
isClassDeclaration,
|
|
@@ -22,27 +21,20 @@ import {
|
|
|
22
21
|
isNamedExports,
|
|
23
22
|
isNamespaceImport,
|
|
24
23
|
isNoSubstitutionTemplateLiteral,
|
|
25
|
-
isNonNullExpression,
|
|
26
24
|
isNumericLiteral,
|
|
27
25
|
isObjectBindingPattern,
|
|
28
26
|
isObjectLiteralExpression,
|
|
29
|
-
isParenthesizedExpression,
|
|
30
27
|
isPropertyAccessExpression,
|
|
31
28
|
isPropertyAssignment,
|
|
32
|
-
isSatisfiesExpression,
|
|
33
29
|
isShorthandPropertyAssignment,
|
|
34
30
|
isSpreadAssignment,
|
|
35
31
|
isStringLiteral,
|
|
36
32
|
isVariableStatement,
|
|
37
33
|
SyntaxKind,
|
|
38
|
-
type AsExpression,
|
|
39
34
|
type Identifier,
|
|
40
35
|
type Node,
|
|
41
36
|
type ObjectBindingPattern,
|
|
42
|
-
type NonNullExpression,
|
|
43
37
|
type ObjectLiteralExpression,
|
|
44
|
-
type ParenthesizedExpression,
|
|
45
|
-
type SatisfiesExpression,
|
|
46
38
|
type SourceFile,
|
|
47
39
|
} from "@typescript/native/ast";
|
|
48
40
|
import { lineOf } from "./component-files.ts";
|
|
@@ -51,19 +43,34 @@ import {
|
|
|
51
43
|
type ConventionRow,
|
|
52
44
|
type DirectoryMove,
|
|
53
45
|
type HelperReading,
|
|
46
|
+
type ManifestEntryKey,
|
|
54
47
|
type MoveReading,
|
|
55
48
|
type OptionsCall,
|
|
56
49
|
type PackageKey,
|
|
50
|
+
type PrefixedNameReading,
|
|
57
51
|
type ShortNameReading,
|
|
58
52
|
type TestFileReading,
|
|
59
53
|
} from "./convention-rows.ts";
|
|
60
54
|
import { documentStrings } from "./configuration-files.ts";
|
|
61
|
-
import { globExpression } from "./glob.ts";
|
|
62
55
|
import type { Host } from "./host.ts";
|
|
63
|
-
import {
|
|
64
|
-
|
|
56
|
+
import {
|
|
57
|
+
ancestors,
|
|
58
|
+
dirnamePath,
|
|
59
|
+
joinPath,
|
|
60
|
+
normalizePath,
|
|
61
|
+
relativePath,
|
|
62
|
+
resolvePath,
|
|
63
|
+
} from "./paths.ts";
|
|
64
|
+
import type { Failure } from "./failure.ts";
|
|
65
65
|
import type { SourceFiles } from "./source-files.ts";
|
|
66
66
|
import { satisfies } from "./version-range.ts";
|
|
67
|
+
import { bytewise } from "./text/compare.ts";
|
|
68
|
+
import { isRecord } from "./json-document.ts";
|
|
69
|
+
import { unwrapped } from "./unwrap.ts";
|
|
70
|
+
import { filesIn } from "./fs/tree.ts";
|
|
71
|
+
import { DEPENDENCY_SECTIONS, INSTALLED_PACKAGES, MANIFEST, readJSON } from "./fs/manifest.ts";
|
|
72
|
+
import { globExpression } from "./text/glob.ts";
|
|
73
|
+
import { yamlDocument } from "./text/yaml.ts";
|
|
67
74
|
|
|
68
75
|
/** One manifest the analysis reads. */
|
|
69
76
|
export interface ConventionManifest {
|
|
@@ -108,7 +115,7 @@ interface GeneratedDirectory {
|
|
|
108
115
|
/** A setup failure a row met, at the directory of the manifest that declared it. */
|
|
109
116
|
interface ConventionFailure {
|
|
110
117
|
readonly dir: string;
|
|
111
|
-
readonly failure:
|
|
118
|
+
readonly failure: Failure;
|
|
112
119
|
}
|
|
113
120
|
|
|
114
121
|
/** What the rows decided for one run. */
|
|
@@ -149,30 +156,19 @@ type ParseSource = (fileName: string, text: string) => SourceFile;
|
|
|
149
156
|
|
|
150
157
|
const JSON_EXTENSION = ".json";
|
|
151
158
|
|
|
159
|
+
/**
|
|
160
|
+
* A configuration file its tool reads as a YAML document, read as the JSON document it
|
|
161
|
+
* denotes. Its nodes' offsets are that JSON text's, so no move may read one: a failure's
|
|
162
|
+
* line would name the wrong line.
|
|
163
|
+
*/
|
|
164
|
+
const YAML_NAME = /\.ya?ml$/u;
|
|
165
|
+
|
|
152
166
|
/** A configuration file with no extension that its tool reads as a JSON document. */
|
|
153
167
|
const JSON_RC = /^\.[\w-]+rc$/u;
|
|
154
168
|
|
|
155
169
|
/** The sections an installed package is required by, so its absence fails the run. */
|
|
156
170
|
const REQUIRED_SECTIONS = ["dependencies", "devDependencies"] as const;
|
|
157
171
|
|
|
158
|
-
const DEPENDENCY_SECTIONS = [
|
|
159
|
-
...REQUIRED_SECTIONS,
|
|
160
|
-
"peerDependencies",
|
|
161
|
-
"optionalDependencies",
|
|
162
|
-
] as const;
|
|
163
|
-
|
|
164
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
165
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function readJSON(host: Host, path: string): unknown {
|
|
169
|
-
try {
|
|
170
|
-
return JSON.parse(host.readFile(path));
|
|
171
|
-
} catch {
|
|
172
|
-
return undefined;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
172
|
function declares(
|
|
177
173
|
manifest: unknown,
|
|
178
174
|
name: string,
|
|
@@ -193,38 +189,15 @@ function declares(
|
|
|
193
189
|
* none, or `undefined` where no `node_modules` holds it.
|
|
194
190
|
*/
|
|
195
191
|
function installedVersion(host: Host, dir: string, name: string): string | undefined {
|
|
196
|
-
for (
|
|
197
|
-
const path = joinPath(at,
|
|
192
|
+
for (const at of ancestors(dir)) {
|
|
193
|
+
const path = joinPath(at, INSTALLED_PACKAGES, name, MANIFEST);
|
|
198
194
|
if (host.kindOf(path) === "file") {
|
|
199
195
|
const manifest = readJSON(host, path);
|
|
200
196
|
const version = isRecord(manifest) ? manifest["version"] : undefined;
|
|
201
197
|
return typeof version === "string" ? version : "";
|
|
202
198
|
}
|
|
203
|
-
if (dirnamePath(at) === at) {
|
|
204
|
-
return undefined;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/** Whether one node wraps an expression without changing its value. */
|
|
210
|
-
function isWrapper(
|
|
211
|
-
node: Node,
|
|
212
|
-
): node is ParenthesizedExpression | AsExpression | SatisfiesExpression | NonNullExpression {
|
|
213
|
-
return (
|
|
214
|
-
isParenthesizedExpression(node) ||
|
|
215
|
-
isAsExpression(node) ||
|
|
216
|
-
isSatisfiesExpression(node) ||
|
|
217
|
-
isNonNullExpression(node)
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/** The expression a wrapper that changes no value holds. */
|
|
222
|
-
function unwrapped(node: Node): Node {
|
|
223
|
-
let at = node;
|
|
224
|
-
while (isWrapper(at)) {
|
|
225
|
-
at = at.expression;
|
|
226
199
|
}
|
|
227
|
-
return
|
|
200
|
+
return undefined;
|
|
228
201
|
}
|
|
229
202
|
|
|
230
203
|
/** The key one property is written with, where it is written as a name or as literal text. */
|
|
@@ -692,6 +665,47 @@ function manifestKeyUses(manifest: unknown, keys: readonly string[]): readonly s
|
|
|
692
665
|
);
|
|
693
666
|
}
|
|
694
667
|
|
|
668
|
+
/** The extensions an entry a manifest entry key names without one may carry. */
|
|
669
|
+
const ENTRY_EXTENSIONS = "{js,jsx,mjs,cjs,ts,tsx,mts,cts}";
|
|
670
|
+
|
|
671
|
+
/** The characters that make a manifest string a pattern rather than a directory's name. */
|
|
672
|
+
const PATTERN = /[*?{}[\]]/u;
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* The entry globs one applied row's manifest entry keys write, below the manifest's
|
|
676
|
+
* directory: a directory's every module, or a file with or without an extension. A string
|
|
677
|
+
* that leaves the directory names nothing.
|
|
678
|
+
*/
|
|
679
|
+
function manifestEntryGlobs(manifest: unknown, keys: readonly ManifestEntryKey[]): string[] {
|
|
680
|
+
const at = (value: unknown, path: readonly string[]): unknown[] => {
|
|
681
|
+
const [key, ...rest] = path;
|
|
682
|
+
if (key === undefined) {
|
|
683
|
+
return [value];
|
|
684
|
+
}
|
|
685
|
+
if (!isRecord(value)) {
|
|
686
|
+
return [];
|
|
687
|
+
}
|
|
688
|
+
const next = key === "*" ? Object.values(value) : Object.hasOwn(value, key) ? [value[key]] : [];
|
|
689
|
+
return next.flatMap((one) => at(one, rest));
|
|
690
|
+
};
|
|
691
|
+
return keys.flatMap(({ key, directory }) =>
|
|
692
|
+
at(manifest, key.split(".")).flatMap((value) =>
|
|
693
|
+
documentStrings(value).flatMap((text) => {
|
|
694
|
+
const path = normalizePath(text)
|
|
695
|
+
.replace(/^(?:\.\/)+/u, "")
|
|
696
|
+
.replace(/\/+$/u, "");
|
|
697
|
+
if (path === "" || path === ".." || path.startsWith("../") || path.startsWith("/")) {
|
|
698
|
+
return [];
|
|
699
|
+
}
|
|
700
|
+
if (!directory) {
|
|
701
|
+
return [path, `${path}.${ENTRY_EXTENSIONS}`];
|
|
702
|
+
}
|
|
703
|
+
return PATTERN.test(path) ? [] : [`${path}/**/*.${ENTRY_EXTENSIONS}`];
|
|
704
|
+
}),
|
|
705
|
+
),
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
|
|
695
709
|
/** What one configuration file states about one property. */
|
|
696
710
|
interface PropertyReading {
|
|
697
711
|
/** The literal values the file sets the property to. */
|
|
@@ -772,16 +786,7 @@ function expand(
|
|
|
772
786
|
/** The configuration files in one directory that one glob names, by name. */
|
|
773
787
|
function configurationFiles(host: Host, dir: string, glob: string): readonly string[] {
|
|
774
788
|
const expression = globExpression(glob);
|
|
775
|
-
|
|
776
|
-
try {
|
|
777
|
-
entries = host.readDirectory(dir);
|
|
778
|
-
} catch {
|
|
779
|
-
return [];
|
|
780
|
-
}
|
|
781
|
-
return entries
|
|
782
|
-
.filter((entry) => !entry.directory && expression.test(entry.name))
|
|
783
|
-
.map((entry) => entry.name)
|
|
784
|
-
.sort();
|
|
789
|
+
return filesIn(host, dir, (name) => expression.test(name));
|
|
785
790
|
}
|
|
786
791
|
|
|
787
792
|
/** What one move resolved to: its directories, or the failure its property met. */
|
|
@@ -840,6 +845,14 @@ function readingFiles(
|
|
|
840
845
|
} catch {
|
|
841
846
|
continue;
|
|
842
847
|
}
|
|
848
|
+
if (YAML_NAME.test(name)) {
|
|
849
|
+
const value = yamlDocument(text);
|
|
850
|
+
if (value !== undefined) {
|
|
851
|
+
const json = JSON.stringify(value);
|
|
852
|
+
found.push({ name, text: json, file: parse(`${path}${JSON_EXTENSION}`, json) });
|
|
853
|
+
}
|
|
854
|
+
continue;
|
|
855
|
+
}
|
|
843
856
|
found.push({
|
|
844
857
|
name,
|
|
845
858
|
text,
|
|
@@ -889,7 +902,67 @@ function shortNameUses(
|
|
|
889
902
|
}
|
|
890
903
|
}
|
|
891
904
|
}
|
|
892
|
-
return [...used].filter((name) => declared.has(name)).sort(
|
|
905
|
+
return [...used].filter((name) => declared.has(name)).sort(bytewise);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* The package one value of a prefixed-name reading names, or none: ESLint's own naming,
|
|
910
|
+
* https://github.com/eslint/eslintrc/blob/main/lib/shared/naming.js
|
|
911
|
+
*/
|
|
912
|
+
function prefixedPackage(value: string, reading: PrefixedNameReading): string | undefined {
|
|
913
|
+
const { prefix, marker } = reading;
|
|
914
|
+
let name: string;
|
|
915
|
+
if (marker === undefined) {
|
|
916
|
+
if (value.includes(":") || value.startsWith(".") || value.startsWith("/")) {
|
|
917
|
+
return undefined;
|
|
918
|
+
}
|
|
919
|
+
const parts = value.split("/");
|
|
920
|
+
name = (value.startsWith("@") ? parts.slice(0, 2) : parts.slice(0, 1)).join("/");
|
|
921
|
+
} else {
|
|
922
|
+
if (!value.startsWith(marker) || !value.includes("/", marker.length)) {
|
|
923
|
+
return undefined;
|
|
924
|
+
}
|
|
925
|
+
name = value.slice(marker.length, value.lastIndexOf("/"));
|
|
926
|
+
}
|
|
927
|
+
if (name === "") {
|
|
928
|
+
return undefined;
|
|
929
|
+
}
|
|
930
|
+
if (!name.startsWith("@")) {
|
|
931
|
+
return name.startsWith(`${prefix}-`) ? name : `${prefix}-${name}`;
|
|
932
|
+
}
|
|
933
|
+
const [scope, rest] = name.split("/");
|
|
934
|
+
if (rest === undefined || rest === "" || rest === prefix) {
|
|
935
|
+
return `${scope ?? name}/${prefix}`;
|
|
936
|
+
}
|
|
937
|
+
return rest.startsWith(`${prefix}-`) ? name : `${scope ?? name}/${prefix}-${rest}`;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/** The declared dependencies an applied row's prefixed names use. */
|
|
941
|
+
function prefixedNameUses(
|
|
942
|
+
host: Host,
|
|
943
|
+
parse: ParseSource,
|
|
944
|
+
dir: string,
|
|
945
|
+
manifest: unknown,
|
|
946
|
+
readings: readonly PrefixedNameReading[],
|
|
947
|
+
): readonly string[] {
|
|
948
|
+
const declared = new Set(
|
|
949
|
+
DEPENDENCY_SECTIONS.flatMap((section) => {
|
|
950
|
+
const held = isRecord(manifest) ? manifest[section] : undefined;
|
|
951
|
+
return isRecord(held) ? Object.keys(held) : [];
|
|
952
|
+
}),
|
|
953
|
+
);
|
|
954
|
+
const used = new Set<string>();
|
|
955
|
+
for (const reading of readings) {
|
|
956
|
+
for (const { file } of readingFiles(host, parse, dir, reading.files)) {
|
|
957
|
+
for (const value of readProperty(file, reading.property, reading.call, true).values) {
|
|
958
|
+
const named = prefixedPackage(value, reading);
|
|
959
|
+
if (named !== undefined && declared.has(named)) {
|
|
960
|
+
used.add(named);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
return [...used].sort(bytewise);
|
|
893
966
|
}
|
|
894
967
|
|
|
895
968
|
/** The declared dependencies an applied row's helper settings use. */
|
|
@@ -973,14 +1046,6 @@ function packageKeyUses(
|
|
|
973
1046
|
);
|
|
974
1047
|
}
|
|
975
1048
|
|
|
976
|
-
/** Two strings ordered bytewise. */
|
|
977
|
-
function compare(a: string, b: string): number {
|
|
978
|
-
if (a === b) {
|
|
979
|
-
return 0;
|
|
980
|
-
}
|
|
981
|
-
return a < b ? -1 : 1;
|
|
982
|
-
}
|
|
983
|
-
|
|
984
1049
|
/**
|
|
985
1050
|
* What the rows decide over the manifests the analysis reads. A row `disabled` names
|
|
986
1051
|
* is skipped before anything is read for it.
|
|
@@ -1000,7 +1065,7 @@ export function readConventions(
|
|
|
1000
1065
|
const selected = new Map<string, { starts: Set<number>; texts: string[] }>();
|
|
1001
1066
|
const testFiles = new Set<string>();
|
|
1002
1067
|
for (const manifest of manifests) {
|
|
1003
|
-
const declared = readJSON(host, joinPath(manifest.dir,
|
|
1068
|
+
const declared = readJSON(host, joinPath(manifest.dir, MANIFEST));
|
|
1004
1069
|
const versions = new Map<string, string | undefined>();
|
|
1005
1070
|
const missing = new Set<string>();
|
|
1006
1071
|
for (const row of rows) {
|
|
@@ -1023,7 +1088,7 @@ export function readConventions(
|
|
|
1023
1088
|
failures.push({
|
|
1024
1089
|
dir: manifest.dir,
|
|
1025
1090
|
failure: {
|
|
1026
|
-
|
|
1091
|
+
failureClass: "missing-module",
|
|
1027
1092
|
detail:
|
|
1028
1093
|
`${manifest.path} declares ${row.package}, which no node_modules at or ` +
|
|
1029
1094
|
`above its directory holds: run the package manager's install`,
|
|
@@ -1049,7 +1114,7 @@ export function readConventions(
|
|
|
1049
1114
|
failures.push({
|
|
1050
1115
|
dir: manifest.dir,
|
|
1051
1116
|
failure: {
|
|
1052
|
-
|
|
1117
|
+
failureClass: "convention-not-literal",
|
|
1053
1118
|
detail: where === "." ? failed : `${where}/${failed}`,
|
|
1054
1119
|
},
|
|
1055
1120
|
});
|
|
@@ -1064,6 +1129,10 @@ export function readConventions(
|
|
|
1064
1129
|
for (const name of shortNameUses(host, parse, manifest.dir, declared, row.shortNames ?? [])) {
|
|
1065
1130
|
uses.add(name);
|
|
1066
1131
|
}
|
|
1132
|
+
const prefixed = row.prefixedNames ?? [];
|
|
1133
|
+
for (const name of prefixedNameUses(host, parse, manifest.dir, declared, prefixed)) {
|
|
1134
|
+
uses.add(name);
|
|
1135
|
+
}
|
|
1067
1136
|
const keys = row.packageKeys ?? [];
|
|
1068
1137
|
for (const name of packageKeyUses(host, parse, manifest.dir, declared, keys)) {
|
|
1069
1138
|
uses.add(name);
|
|
@@ -1082,7 +1151,11 @@ export function readConventions(
|
|
|
1082
1151
|
for (const below of new Set((row.generated ?? []).flatMap((one) => expand(one, resolved)))) {
|
|
1083
1152
|
generated.push({ dir: manifest.dir, row: row.name, below });
|
|
1084
1153
|
}
|
|
1085
|
-
|
|
1154
|
+
const written = [
|
|
1155
|
+
...row.entries.flatMap((entry) => expand(entry, resolved)),
|
|
1156
|
+
...manifestEntryGlobs(declared, row.manifestEntries ?? []),
|
|
1157
|
+
];
|
|
1158
|
+
for (const glob of new Set(written)) {
|
|
1086
1159
|
globs.push({
|
|
1087
1160
|
dir: manifest.dir,
|
|
1088
1161
|
row: row.name,
|
|
@@ -1095,16 +1168,16 @@ export function readConventions(
|
|
|
1095
1168
|
const unique = [...new Map(applied.map((one) => [JSON.stringify(one), one])).values()];
|
|
1096
1169
|
unique.sort(
|
|
1097
1170
|
(a, b) =>
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1171
|
+
bytewise(a.name, b.name) ||
|
|
1172
|
+
bytewise(a.manifest, b.manifest) ||
|
|
1173
|
+
bytewise(JSON.stringify(a), JSON.stringify(b)),
|
|
1101
1174
|
);
|
|
1102
1175
|
return {
|
|
1103
1176
|
applied: unique,
|
|
1104
1177
|
globs,
|
|
1105
1178
|
generated,
|
|
1106
1179
|
failures,
|
|
1107
|
-
uses: [...uses].sort(
|
|
1180
|
+
uses: [...uses].sort(bytewise),
|
|
1108
1181
|
selected,
|
|
1109
1182
|
testFiles,
|
|
1110
1183
|
};
|
|
@@ -1138,12 +1211,15 @@ export function conventionEntries(
|
|
|
1138
1211
|
const found = new Map<string, ConventionEntry>();
|
|
1139
1212
|
for (const glob of conventions.globs) {
|
|
1140
1213
|
for (const file of files.byName.values()) {
|
|
1141
|
-
const
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1214
|
+
const matched = [file.fileName, ...files.writtenAs(file)].some((name) => {
|
|
1215
|
+
const path = relativePath(glob.dir, name);
|
|
1216
|
+
return (
|
|
1217
|
+
path !== undefined &&
|
|
1218
|
+
glob.expression.test(path) &&
|
|
1219
|
+
!glob.excludes.some((one) => one.test(path))
|
|
1220
|
+
);
|
|
1221
|
+
});
|
|
1222
|
+
if (matched) {
|
|
1147
1223
|
found.set(`${file.fileName}\u0000${glob.row}`, { file, row: glob.row });
|
|
1148
1224
|
}
|
|
1149
1225
|
}
|
|
@@ -1159,7 +1235,7 @@ export function conventionFailuresFor(
|
|
|
1159
1235
|
conventions: Conventions,
|
|
1160
1236
|
configFile: string,
|
|
1161
1237
|
ownFiles: readonly string[],
|
|
1162
|
-
): readonly
|
|
1238
|
+
): readonly Failure[] {
|
|
1163
1239
|
return conventions.failures
|
|
1164
1240
|
.filter(
|
|
1165
1241
|
({ dir }) =>
|
package/src/decorator.ts
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The decorator class: a member a decorator expression is attached to, and every
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* the
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* The use the decorator itself makes of what it decorates is the reference pass's,
|
|
9
|
-
* which records it as a `decorator` reference; this class records only that the
|
|
10
|
-
* declaration is held back, and the member set of a decorated class is every member
|
|
11
|
-
* the inventory holds for the class, static members included.
|
|
2
|
+
* The decorator class: a member a decorator expression is attached to, and every member
|
|
3
|
+
* of a class one is attached to but the member a parameter property declares, is held
|
|
4
|
+
* back, because the decorator may reach the member by its name. The rule is read from
|
|
5
|
+
* the tree alone. The decorator's own use of what it decorates is the reference pass's
|
|
6
|
+
* `decorator` reference; this class records only that the declaration is held back,
|
|
7
|
+
* static members of a decorated class included.
|
|
12
8
|
*/
|
|
13
9
|
|
|
14
10
|
import type { Node } from "@typescript/native/ast";
|
|
@@ -44,25 +40,39 @@ export function decorator<Brand>(input: DetectorInput<Brand>): readonly Evidence
|
|
|
44
40
|
}
|
|
45
41
|
}
|
|
46
42
|
|
|
47
|
-
const
|
|
43
|
+
const decorated: {
|
|
44
|
+
readonly symbol: InventorySymbol;
|
|
45
|
+
readonly detail: string;
|
|
46
|
+
readonly site: Evidence["site"];
|
|
47
|
+
}[] = [];
|
|
48
|
+
// A decorated class's container passes each constructor argument, which keeps the
|
|
49
|
+
// parameter, not the member a parameter property stores it in.
|
|
50
|
+
const parameterMembers = new Set<string>();
|
|
48
51
|
for (const file of project.ownSourceFiles()) {
|
|
49
52
|
const visit = (node: Node): void => {
|
|
50
53
|
const id = held.declarations.get(nodeKey(file, node));
|
|
51
54
|
const symbol = id === undefined ? undefined : byId.get(id);
|
|
55
|
+
if (id !== undefined && isParameterProperty(node)) {
|
|
56
|
+
parameterMembers.add(id);
|
|
57
|
+
}
|
|
52
58
|
// A parameter property's decorator is attached to its parameter, and to no member.
|
|
53
59
|
if (symbol !== undefined && DECORATED.has(symbol.kind) && !isParameterProperty(node)) {
|
|
54
60
|
for (const attached of decoratorsOf(node)) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
+
decorated.push({
|
|
62
|
+
symbol,
|
|
63
|
+
detail: `decorated by ${spelledDecorator(attached)}`,
|
|
64
|
+
site: renderPosition(file, targetRoot, attached.getStart()),
|
|
65
|
+
});
|
|
61
66
|
}
|
|
62
67
|
}
|
|
63
68
|
node.forEachChild(visit);
|
|
64
69
|
};
|
|
65
70
|
file.forEachChild(visit);
|
|
66
71
|
}
|
|
67
|
-
return
|
|
72
|
+
return decorated.flatMap(({ symbol, detail, site }) =>
|
|
73
|
+
(symbol.kind === "class"
|
|
74
|
+
? (membersOf.get(symbol.id) ?? []).filter((member) => !parameterMembers.has(member.id))
|
|
75
|
+
: [symbol]
|
|
76
|
+
).map((member) => ({ id: member.id, detail, site })),
|
|
77
|
+
);
|
|
68
78
|
}
|