@cplieger/deadset-ts 7.2.0-dev.4 → 8.0.0-dev.1
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/src/analysis.js +106 -10
- package/dist/src/augmentations.js +21 -8
- package/dist/src/automatic-types.js +189 -0
- package/dist/src/base-url.js +18 -0
- package/dist/src/components.js +7 -6
- package/dist/src/config.js +1 -0
- package/dist/src/configuration-files.js +50 -12
- package/dist/src/conformance-record.js +2 -2
- package/dist/src/convention-rows.js +75 -0
- package/dist/src/conventions.js +101 -5
- package/dist/src/decorator.js +21 -18
- package/dist/src/dependencies.js +183 -28
- package/dist/src/discover.js +132 -11
- package/dist/src/entry-point-gaps.js +7 -10
- package/dist/src/entry-points.js +112 -11
- package/dist/src/findings/completion.js +116 -21
- package/dist/src/findings/dependencies-and-module-machinery.js +71 -25
- package/dist/src/findings/emitters.js +1 -1
- package/dist/src/findings/intra-function.js +44 -13
- package/dist/src/findings/non-code-artifacts.js +66 -33
- package/dist/src/findings/unused-declarations.js +21 -1
- package/dist/src/findings/visibility-narrowing.js +22 -3
- package/dist/src/generated-file.js +11 -0
- package/dist/src/git-ignore.js +86 -0
- package/dist/src/graph.js +4 -1
- package/dist/src/import-bindings.js +97 -0
- package/dist/src/indexed-access.js +130 -28
- package/dist/src/interface-satisfaction.js +30 -12
- package/dist/src/intra-function-parts.js +297 -45
- package/dist/src/inventory.js +52 -8
- package/dist/src/kinds.js +13 -13
- package/dist/src/matrix.js +18 -9
- package/dist/src/mdx-entries.js +197 -0
- package/dist/src/module-declarations.js +9 -13
- package/dist/src/overrides.js +41 -10
- package/dist/src/print.js +1 -0
- package/dist/src/ref.js +10 -0
- package/dist/src/references.js +4 -1
- package/dist/src/report.js +4 -2
- package/dist/src/resolve.js +2 -0
- package/dist/src/roots.js +110 -38
- package/dist/src/schema.js +1 -0
- package/dist/src/serialization-contract.js +54 -8
- package/dist/src/session.js +7 -0
- package/dist/src/source-files.js +39 -14
- package/dist/src/suppress-file.js +10 -2
- package/dist/src/suppress-inline.js +18 -2
- package/dist/src/suppress.js +7 -5
- package/dist/src/sweep.js +27 -10
- package/dist/src/symbol-keys.js +103 -2
- package/dist/src/test-support.js +121 -17
- package/dist/src/type-errors.js +34 -7
- package/dist/src/type-parameter-reads.js +172 -0
- package/dist/src/verbs/analyze.js +16 -0
- package/dist/src/verbs/explain.js +4 -2
- package/dist/src/version.js +1 -1
- package/dist/src/workflow-steps.js +119 -22
- package/dist/src/workspace-programs.js +7 -3
- package/dist/src/workspace-resolution.js +53 -10
- package/jsr.json +1 -1
- package/package.json +2 -2
- package/src/analysis.ts +143 -10
- package/src/augmentations.ts +21 -10
- package/src/automatic-types.ts +246 -0
- package/src/base-url.ts +24 -0
- package/src/components.ts +7 -6
- package/src/config.ts +3 -0
- package/src/configuration-files.ts +66 -12
- package/src/conformance-record.ts +2 -2
- package/src/convention-rows.ts +103 -0
- package/src/conventions.ts +121 -7
- package/src/decorator.ts +28 -18
- package/src/dependencies.ts +247 -41
- package/src/discover.ts +156 -13
- package/src/entry-point-gaps.ts +8 -11
- package/src/entry-points.ts +133 -11
- package/src/finding.ts +10 -0
- package/src/findings/completion.ts +147 -24
- package/src/findings/dependencies-and-module-machinery.ts +90 -28
- package/src/findings/emitters.ts +1 -1
- package/src/findings/intra-function.ts +56 -14
- package/src/findings/non-code-artifacts.ts +81 -41
- package/src/findings/unused-declarations.ts +25 -1
- package/src/findings/visibility-narrowing.ts +32 -3
- package/src/generated-file.ts +16 -0
- package/src/git-ignore.ts +98 -0
- package/src/graph.ts +6 -0
- package/src/host.ts +5 -9
- package/src/import-bindings.ts +128 -0
- package/src/indexed-access.ts +152 -30
- package/src/interface-satisfaction.ts +33 -13
- package/src/intra-function-parts.ts +394 -59
- package/src/inventory.ts +71 -7
- package/src/kinds.ts +13 -13
- package/src/matrix.ts +32 -14
- package/src/mdx-entries.ts +241 -0
- package/src/module-declarations.ts +11 -13
- package/src/overrides.ts +51 -12
- package/src/print.ts +1 -0
- package/src/ref.ts +12 -0
- package/src/references.ts +10 -1
- package/src/report.ts +16 -3
- package/src/resolve.ts +3 -0
- package/src/roots.ts +163 -45
- package/src/schema.ts +1 -0
- package/src/serialization-contract.ts +55 -4
- package/src/session.ts +7 -0
- package/src/source-files.ts +66 -16
- package/src/suppress-file.ts +12 -1
- package/src/suppress-inline.ts +18 -1
- package/src/suppress.ts +9 -5
- package/src/sweep.ts +32 -11
- package/src/symbol-keys.ts +129 -2
- package/src/test-support.ts +149 -16
- package/src/type-errors.ts +38 -6
- package/src/type-parameter-reads.ts +227 -0
- package/src/verbs/analyze.ts +22 -0
- package/src/verbs/explain.ts +5 -2
- package/src/version.ts +1 -1
- package/src/workflow-steps.ts +127 -22
- package/src/workspace-programs.ts +7 -3
- package/src/workspace-resolution.ts +62 -10
package/src/conventions.ts
CHANGED
|
@@ -51,9 +51,11 @@ import {
|
|
|
51
51
|
type ConventionRow,
|
|
52
52
|
type DirectoryMove,
|
|
53
53
|
type HelperReading,
|
|
54
|
+
type ManifestEntryKey,
|
|
54
55
|
type MoveReading,
|
|
55
56
|
type OptionsCall,
|
|
56
57
|
type PackageKey,
|
|
58
|
+
type PrefixedNameReading,
|
|
57
59
|
type ShortNameReading,
|
|
58
60
|
type TestFileReading,
|
|
59
61
|
} from "./convention-rows.ts";
|
|
@@ -692,6 +694,47 @@ function manifestKeyUses(manifest: unknown, keys: readonly string[]): readonly s
|
|
|
692
694
|
);
|
|
693
695
|
}
|
|
694
696
|
|
|
697
|
+
/** The extensions an entry a manifest entry key names without one may carry. */
|
|
698
|
+
const ENTRY_EXTENSIONS = "{js,jsx,mjs,cjs,ts,tsx,mts,cts}";
|
|
699
|
+
|
|
700
|
+
/** The characters that make a manifest string a pattern rather than a directory's name. */
|
|
701
|
+
const PATTERN = /[*?{}[\]]/u;
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* The entry globs one applied row's manifest entry keys write, below the manifest's
|
|
705
|
+
* directory: a directory's every module, or a file with or without an extension. A string
|
|
706
|
+
* that leaves the directory names nothing.
|
|
707
|
+
*/
|
|
708
|
+
function manifestEntryGlobs(manifest: unknown, keys: readonly ManifestEntryKey[]): string[] {
|
|
709
|
+
const at = (value: unknown, path: readonly string[]): unknown[] => {
|
|
710
|
+
const [key, ...rest] = path;
|
|
711
|
+
if (key === undefined) {
|
|
712
|
+
return [value];
|
|
713
|
+
}
|
|
714
|
+
if (!isRecord(value)) {
|
|
715
|
+
return [];
|
|
716
|
+
}
|
|
717
|
+
const next = key === "*" ? Object.values(value) : Object.hasOwn(value, key) ? [value[key]] : [];
|
|
718
|
+
return next.flatMap((one) => at(one, rest));
|
|
719
|
+
};
|
|
720
|
+
return keys.flatMap(({ key, directory }) =>
|
|
721
|
+
at(manifest, key.split(".")).flatMap((value) =>
|
|
722
|
+
documentStrings(value).flatMap((text) => {
|
|
723
|
+
const path = normalizePath(text)
|
|
724
|
+
.replace(/^(?:\.\/)+/u, "")
|
|
725
|
+
.replace(/\/+$/u, "");
|
|
726
|
+
if (path === "" || path === ".." || path.startsWith("../") || path.startsWith("/")) {
|
|
727
|
+
return [];
|
|
728
|
+
}
|
|
729
|
+
if (!directory) {
|
|
730
|
+
return [path, `${path}.${ENTRY_EXTENSIONS}`];
|
|
731
|
+
}
|
|
732
|
+
return PATTERN.test(path) ? [] : [`${path}/**/*.${ENTRY_EXTENSIONS}`];
|
|
733
|
+
}),
|
|
734
|
+
),
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
|
|
695
738
|
/** What one configuration file states about one property. */
|
|
696
739
|
interface PropertyReading {
|
|
697
740
|
/** The literal values the file sets the property to. */
|
|
@@ -892,6 +935,66 @@ function shortNameUses(
|
|
|
892
935
|
return [...used].filter((name) => declared.has(name)).sort(compare);
|
|
893
936
|
}
|
|
894
937
|
|
|
938
|
+
/**
|
|
939
|
+
* The package one value of a prefixed-name reading names, or none: ESLint's own naming,
|
|
940
|
+
* https://github.com/eslint/eslintrc/blob/main/lib/shared/naming.js
|
|
941
|
+
*/
|
|
942
|
+
function prefixedPackage(value: string, reading: PrefixedNameReading): string | undefined {
|
|
943
|
+
const { prefix, marker } = reading;
|
|
944
|
+
let name: string;
|
|
945
|
+
if (marker === undefined) {
|
|
946
|
+
if (value.includes(":") || value.startsWith(".") || value.startsWith("/")) {
|
|
947
|
+
return undefined;
|
|
948
|
+
}
|
|
949
|
+
const parts = value.split("/");
|
|
950
|
+
name = (value.startsWith("@") ? parts.slice(0, 2) : parts.slice(0, 1)).join("/");
|
|
951
|
+
} else {
|
|
952
|
+
if (!value.startsWith(marker) || !value.includes("/", marker.length)) {
|
|
953
|
+
return undefined;
|
|
954
|
+
}
|
|
955
|
+
name = value.slice(marker.length, value.lastIndexOf("/"));
|
|
956
|
+
}
|
|
957
|
+
if (name === "") {
|
|
958
|
+
return undefined;
|
|
959
|
+
}
|
|
960
|
+
if (!name.startsWith("@")) {
|
|
961
|
+
return name.startsWith(`${prefix}-`) ? name : `${prefix}-${name}`;
|
|
962
|
+
}
|
|
963
|
+
const [scope, rest] = name.split("/");
|
|
964
|
+
if (rest === undefined || rest === "" || rest === prefix) {
|
|
965
|
+
return `${scope ?? name}/${prefix}`;
|
|
966
|
+
}
|
|
967
|
+
return rest.startsWith(`${prefix}-`) ? name : `${scope ?? name}/${prefix}-${rest}`;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/** The declared dependencies an applied row's prefixed names use. */
|
|
971
|
+
function prefixedNameUses(
|
|
972
|
+
host: Host,
|
|
973
|
+
parse: ParseSource,
|
|
974
|
+
dir: string,
|
|
975
|
+
manifest: unknown,
|
|
976
|
+
readings: readonly PrefixedNameReading[],
|
|
977
|
+
): readonly string[] {
|
|
978
|
+
const declared = new Set(
|
|
979
|
+
DEPENDENCY_SECTIONS.flatMap((section) => {
|
|
980
|
+
const held = isRecord(manifest) ? manifest[section] : undefined;
|
|
981
|
+
return isRecord(held) ? Object.keys(held) : [];
|
|
982
|
+
}),
|
|
983
|
+
);
|
|
984
|
+
const used = new Set<string>();
|
|
985
|
+
for (const reading of readings) {
|
|
986
|
+
for (const { file } of readingFiles(host, parse, dir, reading.files)) {
|
|
987
|
+
for (const value of readProperty(file, reading.property, reading.call, true).values) {
|
|
988
|
+
const named = prefixedPackage(value, reading);
|
|
989
|
+
if (named !== undefined && declared.has(named)) {
|
|
990
|
+
used.add(named);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
return [...used].sort(compare);
|
|
996
|
+
}
|
|
997
|
+
|
|
895
998
|
/** The declared dependencies an applied row's helper settings use. */
|
|
896
999
|
function helperUses(
|
|
897
1000
|
host: Host,
|
|
@@ -1064,6 +1167,10 @@ export function readConventions(
|
|
|
1064
1167
|
for (const name of shortNameUses(host, parse, manifest.dir, declared, row.shortNames ?? [])) {
|
|
1065
1168
|
uses.add(name);
|
|
1066
1169
|
}
|
|
1170
|
+
const prefixed = row.prefixedNames ?? [];
|
|
1171
|
+
for (const name of prefixedNameUses(host, parse, manifest.dir, declared, prefixed)) {
|
|
1172
|
+
uses.add(name);
|
|
1173
|
+
}
|
|
1067
1174
|
const keys = row.packageKeys ?? [];
|
|
1068
1175
|
for (const name of packageKeyUses(host, parse, manifest.dir, declared, keys)) {
|
|
1069
1176
|
uses.add(name);
|
|
@@ -1082,7 +1189,11 @@ export function readConventions(
|
|
|
1082
1189
|
for (const below of new Set((row.generated ?? []).flatMap((one) => expand(one, resolved)))) {
|
|
1083
1190
|
generated.push({ dir: manifest.dir, row: row.name, below });
|
|
1084
1191
|
}
|
|
1085
|
-
|
|
1192
|
+
const written = [
|
|
1193
|
+
...row.entries.flatMap((entry) => expand(entry, resolved)),
|
|
1194
|
+
...manifestEntryGlobs(declared, row.manifestEntries ?? []),
|
|
1195
|
+
];
|
|
1196
|
+
for (const glob of new Set(written)) {
|
|
1086
1197
|
globs.push({
|
|
1087
1198
|
dir: manifest.dir,
|
|
1088
1199
|
row: row.name,
|
|
@@ -1138,12 +1249,15 @@ export function conventionEntries(
|
|
|
1138
1249
|
const found = new Map<string, ConventionEntry>();
|
|
1139
1250
|
for (const glob of conventions.globs) {
|
|
1140
1251
|
for (const file of files.byName.values()) {
|
|
1141
|
-
const
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1252
|
+
const matched = [file.fileName, ...files.writtenAs(file)].some((name) => {
|
|
1253
|
+
const path = relativePath(glob.dir, name);
|
|
1254
|
+
return (
|
|
1255
|
+
path !== undefined &&
|
|
1256
|
+
glob.expression.test(path) &&
|
|
1257
|
+
!glob.excludes.some((one) => one.test(path))
|
|
1258
|
+
);
|
|
1259
|
+
});
|
|
1260
|
+
if (matched) {
|
|
1147
1261
|
found.set(`${file.fileName}\u0000${glob.row}`, { file, row: glob.row });
|
|
1148
1262
|
}
|
|
1149
1263
|
}
|
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
|
}
|