@cplieger/deadset-ts 7.2.0-dev.4 → 8.0.0-dev.2
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 +108 -10
- package/dist/src/augmentations.js +62 -18
- 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 +98 -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 +172 -40
- 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 +30 -5
- package/dist/src/findings/visibility-narrowing.js +29 -5
- 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 +57 -10
- 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 +38 -4
- 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 +8 -5
- package/dist/src/sweep.js +27 -10
- package/dist/src/symbol-keys.js +103 -2
- package/dist/src/test-support.js +119 -18
- 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 +146 -11
- package/src/augmentations.ts +76 -22
- 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 +128 -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 +15 -0
- package/src/findings/completion.ts +222 -46
- 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 +36 -5
- package/src/findings/visibility-narrowing.ts +40 -5
- 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 +104 -15
- 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 +48 -3
- 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 +10 -5
- package/src/sweep.ts +32 -11
- package/src/symbol-keys.ts +129 -2
- package/src/test-support.ts +155 -18
- 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
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// Regenerate it with `UPDATE_GOLDEN=1 npx vitest --run src/conformance.corpus.test.ts`.
|
|
3
3
|
export const RECORD = {
|
|
4
4
|
conformance: {
|
|
5
|
-
corpusVersion: "
|
|
5
|
+
corpusVersion: "6.0.0",
|
|
6
6
|
result: "pass",
|
|
7
|
-
digest: "sha256:
|
|
7
|
+
digest: "sha256:d65daae4b7c95050c07896b166d0250d233cca71f97de75a6086c1d80fe76232",
|
|
8
8
|
},
|
|
9
9
|
gaps: [],
|
|
10
10
|
};
|
|
@@ -10,6 +10,8 @@ const SCRIPT = "{js,jsx,ts,tsx}";
|
|
|
10
10
|
const MODULE = "{js,mjs,ts,mts}";
|
|
11
11
|
const ANY_MODULE = "{js,mjs,cjs,ts,mts,cts}";
|
|
12
12
|
const VITE_CONFIG = `vite.config.${ANY_MODULE}`;
|
|
13
|
+
/** The legacy configuration files of ESLint that hold JSON or a CommonJS module. */
|
|
14
|
+
const ESLINTRC = [".eslintrc", ".eslintrc.json", ".eslintrc.{js,cjs}"];
|
|
13
15
|
const SVELTEKIT_ROUTE_FILES = "+{page,layout,server,page.server,layout.server,error}";
|
|
14
16
|
/** SvelteKit's entries other than its parameter matchers. */
|
|
15
17
|
const SVELTEKIT_ENTRIES = [
|
|
@@ -59,6 +61,29 @@ const ANGULAR_PACKAGE_KEYS = [
|
|
|
59
61
|
"styles",
|
|
60
62
|
"scripts",
|
|
61
63
|
].map((key) => ({ key, files: ["angular.json"] }));
|
|
64
|
+
/**
|
|
65
|
+
* The test runners and the assertion, mock and runner libraries whose import is test
|
|
66
|
+
* evidence beside each runner a row reads test files for. Each applies whether or not a
|
|
67
|
+
* manifest declares it, so none is a row.
|
|
68
|
+
*/
|
|
69
|
+
export const TEST_LIBRARIES = [
|
|
70
|
+
"@jest/globals",
|
|
71
|
+
"@playwright/test",
|
|
72
|
+
"ava",
|
|
73
|
+
"chai",
|
|
74
|
+
"expect",
|
|
75
|
+
"jasmine",
|
|
76
|
+
"jest",
|
|
77
|
+
"mocha",
|
|
78
|
+
"msw",
|
|
79
|
+
"nock",
|
|
80
|
+
"node:test",
|
|
81
|
+
"sinon",
|
|
82
|
+
"tap",
|
|
83
|
+
"uvu",
|
|
84
|
+
];
|
|
85
|
+
/** The scopes every package of which is a test library. */
|
|
86
|
+
export const TEST_LIBRARY_SCOPES = ["@testing-library/"];
|
|
62
87
|
/** Every row, ordered by name and then by range. */
|
|
63
88
|
export const CONVENTION_ROWS = [
|
|
64
89
|
{
|
|
@@ -111,6 +136,25 @@ export const CONVENTION_ROWS = [
|
|
|
111
136
|
package: "@babel/runtime",
|
|
112
137
|
})),
|
|
113
138
|
},
|
|
139
|
+
{
|
|
140
|
+
name: "docusaurus",
|
|
141
|
+
package: "@docusaurus/core",
|
|
142
|
+
range: ">=2.0.0 <4.0.0",
|
|
143
|
+
entries: [`src/pages/**/*.${SCRIPT}`, `src/theme/**/*.${SCRIPT}`],
|
|
144
|
+
moves: [],
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "eslint",
|
|
148
|
+
package: "eslint",
|
|
149
|
+
range: ">=4.0.0 <10.0.0",
|
|
150
|
+
entries: [],
|
|
151
|
+
moves: [],
|
|
152
|
+
prefixedNames: [
|
|
153
|
+
{ property: "plugins", files: ESLINTRC, prefix: "eslint-plugin" },
|
|
154
|
+
{ property: "extends", files: ESLINTRC, prefix: "eslint-plugin", marker: "plugin:" },
|
|
155
|
+
{ property: "extends", files: ESLINTRC, prefix: "eslint-config" },
|
|
156
|
+
],
|
|
157
|
+
},
|
|
114
158
|
{
|
|
115
159
|
name: "eslint",
|
|
116
160
|
package: "eslint",
|
|
@@ -118,6 +162,13 @@ export const CONVENTION_ROWS = [
|
|
|
118
162
|
entries: [`**/eslint.config.${ANY_MODULE}`],
|
|
119
163
|
moves: [],
|
|
120
164
|
},
|
|
165
|
+
{
|
|
166
|
+
name: "expo",
|
|
167
|
+
package: "expo",
|
|
168
|
+
range: ">=44.0.0 <60.0.0",
|
|
169
|
+
entries: [`{index,App}.${SCRIPT}`],
|
|
170
|
+
moves: [],
|
|
171
|
+
},
|
|
121
172
|
{
|
|
122
173
|
name: "expo-router",
|
|
123
174
|
package: "expo-router",
|
|
@@ -202,6 +253,28 @@ export const CONVENTION_ROWS = [
|
|
|
202
253
|
},
|
|
203
254
|
],
|
|
204
255
|
},
|
|
256
|
+
{
|
|
257
|
+
name: "oclif",
|
|
258
|
+
package: "@oclif/core",
|
|
259
|
+
range: ">=1.0.0 <5.0.0",
|
|
260
|
+
entries: [`src/{commands,hooks}/**/*.${SCRIPT}`],
|
|
261
|
+
moves: [],
|
|
262
|
+
manifestEntries: [
|
|
263
|
+
{ key: "oclif.commands", directory: true },
|
|
264
|
+
{ key: "oclif.hooks", directory: false },
|
|
265
|
+
],
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: "parcel",
|
|
269
|
+
package: "parcel",
|
|
270
|
+
range: ">=2.0.0 <3.0.0",
|
|
271
|
+
entries: [],
|
|
272
|
+
moves: [],
|
|
273
|
+
manifestEntries: [
|
|
274
|
+
{ key: "source", directory: false },
|
|
275
|
+
{ key: "targets.*.source", directory: false },
|
|
276
|
+
],
|
|
277
|
+
},
|
|
205
278
|
{
|
|
206
279
|
name: "prettier",
|
|
207
280
|
package: "prettier",
|
|
@@ -493,6 +566,31 @@ export const CONVENTION_ROWS = [
|
|
|
493
566
|
},
|
|
494
567
|
],
|
|
495
568
|
},
|
|
569
|
+
{
|
|
570
|
+
name: "tanstack-router",
|
|
571
|
+
package: "@tanstack/router-plugin",
|
|
572
|
+
range: ">=1.0.0 <2.0.0",
|
|
573
|
+
entries: [`<routes>/**/*.${SCRIPT}`],
|
|
574
|
+
moves: [
|
|
575
|
+
{
|
|
576
|
+
id: "routes",
|
|
577
|
+
defaults: ["src/routes"],
|
|
578
|
+
readings: [
|
|
579
|
+
{ property: "routesDirectory", files: ["tsr.config.json"] },
|
|
580
|
+
{
|
|
581
|
+
property: "routesDirectory",
|
|
582
|
+
files: [VITE_CONFIG],
|
|
583
|
+
call: { module: "@tanstack/router-plugin/vite", export: "tanstackRouter" },
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
property: "routesDirectory",
|
|
587
|
+
files: [VITE_CONFIG],
|
|
588
|
+
call: { module: "@tanstack/router-plugin/vite", export: "TanStackRouterVite" },
|
|
589
|
+
},
|
|
590
|
+
],
|
|
591
|
+
},
|
|
592
|
+
],
|
|
593
|
+
},
|
|
496
594
|
{
|
|
497
595
|
name: "vite",
|
|
498
596
|
package: "vite",
|
package/dist/src/conventions.js
CHANGED
|
@@ -471,6 +471,40 @@ function manifestKeyUses(manifest, keys) {
|
|
|
471
471
|
const strings = keys.flatMap((key) => documentStrings(manifest[key]));
|
|
472
472
|
return declared.filter((name) => strings.some((text) => text === name || text.startsWith(`${name}/`)));
|
|
473
473
|
}
|
|
474
|
+
/** The extensions an entry a manifest entry key names without one may carry. */
|
|
475
|
+
const ENTRY_EXTENSIONS = "{js,jsx,mjs,cjs,ts,tsx,mts,cts}";
|
|
476
|
+
/** The characters that make a manifest string a pattern rather than a directory's name. */
|
|
477
|
+
const PATTERN = /[*?{}[\]]/u;
|
|
478
|
+
/**
|
|
479
|
+
* The entry globs one applied row's manifest entry keys write, below the manifest's
|
|
480
|
+
* directory: a directory's every module, or a file with or without an extension. A string
|
|
481
|
+
* that leaves the directory names nothing.
|
|
482
|
+
*/
|
|
483
|
+
function manifestEntryGlobs(manifest, keys) {
|
|
484
|
+
const at = (value, path) => {
|
|
485
|
+
const [key, ...rest] = path;
|
|
486
|
+
if (key === undefined) {
|
|
487
|
+
return [value];
|
|
488
|
+
}
|
|
489
|
+
if (!isRecord(value)) {
|
|
490
|
+
return [];
|
|
491
|
+
}
|
|
492
|
+
const next = key === "*" ? Object.values(value) : Object.hasOwn(value, key) ? [value[key]] : [];
|
|
493
|
+
return next.flatMap((one) => at(one, rest));
|
|
494
|
+
};
|
|
495
|
+
return keys.flatMap(({ key, directory }) => at(manifest, key.split(".")).flatMap((value) => documentStrings(value).flatMap((text) => {
|
|
496
|
+
const path = normalizePath(text)
|
|
497
|
+
.replace(/^(?:\.\/)+/u, "")
|
|
498
|
+
.replace(/\/+$/u, "");
|
|
499
|
+
if (path === "" || path === ".." || path.startsWith("../") || path.startsWith("/")) {
|
|
500
|
+
return [];
|
|
501
|
+
}
|
|
502
|
+
if (!directory) {
|
|
503
|
+
return [path, `${path}.${ENTRY_EXTENSIONS}`];
|
|
504
|
+
}
|
|
505
|
+
return PATTERN.test(path) ? [] : [`${path}/**/*.${ENTRY_EXTENSIONS}`];
|
|
506
|
+
})));
|
|
507
|
+
}
|
|
474
508
|
/**
|
|
475
509
|
* Every value one file writes at one property's path inside the object it is read from:
|
|
476
510
|
* the options argument of every call `call` names, or the file's default export. A string
|
|
@@ -620,6 +654,57 @@ function shortNameUses(host, parse, dir, manifest, readings) {
|
|
|
620
654
|
}
|
|
621
655
|
return [...used].filter((name) => declared.has(name)).sort(compare);
|
|
622
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* The package one value of a prefixed-name reading names, or none: ESLint's own naming,
|
|
659
|
+
* https://github.com/eslint/eslintrc/blob/main/lib/shared/naming.js
|
|
660
|
+
*/
|
|
661
|
+
function prefixedPackage(value, reading) {
|
|
662
|
+
const { prefix, marker } = reading;
|
|
663
|
+
let name;
|
|
664
|
+
if (marker === undefined) {
|
|
665
|
+
if (value.includes(":") || value.startsWith(".") || value.startsWith("/")) {
|
|
666
|
+
return undefined;
|
|
667
|
+
}
|
|
668
|
+
const parts = value.split("/");
|
|
669
|
+
name = (value.startsWith("@") ? parts.slice(0, 2) : parts.slice(0, 1)).join("/");
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
if (!value.startsWith(marker) || !value.includes("/", marker.length)) {
|
|
673
|
+
return undefined;
|
|
674
|
+
}
|
|
675
|
+
name = value.slice(marker.length, value.lastIndexOf("/"));
|
|
676
|
+
}
|
|
677
|
+
if (name === "") {
|
|
678
|
+
return undefined;
|
|
679
|
+
}
|
|
680
|
+
if (!name.startsWith("@")) {
|
|
681
|
+
return name.startsWith(`${prefix}-`) ? name : `${prefix}-${name}`;
|
|
682
|
+
}
|
|
683
|
+
const [scope, rest] = name.split("/");
|
|
684
|
+
if (rest === undefined || rest === "" || rest === prefix) {
|
|
685
|
+
return `${scope ?? name}/${prefix}`;
|
|
686
|
+
}
|
|
687
|
+
return rest.startsWith(`${prefix}-`) ? name : `${scope ?? name}/${prefix}-${rest}`;
|
|
688
|
+
}
|
|
689
|
+
/** The declared dependencies an applied row's prefixed names use. */
|
|
690
|
+
function prefixedNameUses(host, parse, dir, manifest, readings) {
|
|
691
|
+
const declared = new Set(DEPENDENCY_SECTIONS.flatMap((section) => {
|
|
692
|
+
const held = isRecord(manifest) ? manifest[section] : undefined;
|
|
693
|
+
return isRecord(held) ? Object.keys(held) : [];
|
|
694
|
+
}));
|
|
695
|
+
const used = new Set();
|
|
696
|
+
for (const reading of readings) {
|
|
697
|
+
for (const { file } of readingFiles(host, parse, dir, reading.files)) {
|
|
698
|
+
for (const value of readProperty(file, reading.property, reading.call, true).values) {
|
|
699
|
+
const named = prefixedPackage(value, reading);
|
|
700
|
+
if (named !== undefined && declared.has(named)) {
|
|
701
|
+
used.add(named);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
return [...used].sort(compare);
|
|
707
|
+
}
|
|
623
708
|
/** The declared dependencies an applied row's helper settings use. */
|
|
624
709
|
function helperUses(host, parse, dir, manifest, readings) {
|
|
625
710
|
const declared = new Set(DEPENDENCY_SECTIONS.flatMap((section) => {
|
|
@@ -756,6 +841,10 @@ export function readConventions(host, parse, manifests, disabled, rows = CONVENT
|
|
|
756
841
|
for (const name of shortNameUses(host, parse, manifest.dir, declared, row.shortNames ?? [])) {
|
|
757
842
|
uses.add(name);
|
|
758
843
|
}
|
|
844
|
+
const prefixed = row.prefixedNames ?? [];
|
|
845
|
+
for (const name of prefixedNameUses(host, parse, manifest.dir, declared, prefixed)) {
|
|
846
|
+
uses.add(name);
|
|
847
|
+
}
|
|
759
848
|
const keys = row.packageKeys ?? [];
|
|
760
849
|
for (const name of packageKeyUses(host, parse, manifest.dir, declared, keys)) {
|
|
761
850
|
uses.add(name);
|
|
@@ -774,7 +863,11 @@ export function readConventions(host, parse, manifests, disabled, rows = CONVENT
|
|
|
774
863
|
for (const below of new Set((row.generated ?? []).flatMap((one) => expand(one, resolved)))) {
|
|
775
864
|
generated.push({ dir: manifest.dir, row: row.name, below });
|
|
776
865
|
}
|
|
777
|
-
|
|
866
|
+
const written = [
|
|
867
|
+
...row.entries.flatMap((entry) => expand(entry, resolved)),
|
|
868
|
+
...manifestEntryGlobs(declared, row.manifestEntries ?? []),
|
|
869
|
+
];
|
|
870
|
+
for (const glob of new Set(written)) {
|
|
778
871
|
globs.push({
|
|
779
872
|
dir: manifest.dir,
|
|
780
873
|
row: row.name,
|
|
@@ -819,10 +912,13 @@ export function conventionEntries(conventions, files) {
|
|
|
819
912
|
const found = new Map();
|
|
820
913
|
for (const glob of conventions.globs) {
|
|
821
914
|
for (const file of files.byName.values()) {
|
|
822
|
-
const
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
915
|
+
const matched = [file.fileName, ...files.writtenAs(file)].some((name) => {
|
|
916
|
+
const path = relativePath(glob.dir, name);
|
|
917
|
+
return (path !== undefined &&
|
|
918
|
+
glob.expression.test(path) &&
|
|
919
|
+
!glob.excludes.some((one) => one.test(path)));
|
|
920
|
+
});
|
|
921
|
+
if (matched) {
|
|
826
922
|
found.set(`${file.fileName}\u0000${glob.row}`, { file, row: glob.row });
|
|
827
923
|
}
|
|
828
924
|
}
|
package/dist/src/decorator.js
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
|
import { decoratorsOf, spelledDecorator } from "./calls.js";
|
|
14
10
|
import { isParameterProperty, nodeKey, } from "./inventory.js";
|
|
@@ -34,25 +30,32 @@ export function decorator(input) {
|
|
|
34
30
|
}
|
|
35
31
|
}
|
|
36
32
|
}
|
|
37
|
-
const
|
|
33
|
+
const decorated = [];
|
|
34
|
+
// A decorated class's container passes each constructor argument, which keeps the
|
|
35
|
+
// parameter, not the member a parameter property stores it in.
|
|
36
|
+
const parameterMembers = new Set();
|
|
38
37
|
for (const file of project.ownSourceFiles()) {
|
|
39
38
|
const visit = (node) => {
|
|
40
39
|
const id = held.declarations.get(nodeKey(file, node));
|
|
41
40
|
const symbol = id === undefined ? undefined : byId.get(id);
|
|
41
|
+
if (id !== undefined && isParameterProperty(node)) {
|
|
42
|
+
parameterMembers.add(id);
|
|
43
|
+
}
|
|
42
44
|
// A parameter property's decorator is attached to its parameter, and to no member.
|
|
43
45
|
if (symbol !== undefined && DECORATED.has(symbol.kind) && !isParameterProperty(node)) {
|
|
44
46
|
for (const attached of decoratorsOf(node)) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
47
|
+
decorated.push({
|
|
48
|
+
symbol,
|
|
49
|
+
detail: `decorated by ${spelledDecorator(attached)}`,
|
|
50
|
+
site: renderPosition(file, targetRoot, attached.getStart()),
|
|
51
|
+
});
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
node.forEachChild(visit);
|
|
54
55
|
};
|
|
55
56
|
file.forEachChild(visit);
|
|
56
57
|
}
|
|
57
|
-
return
|
|
58
|
+
return decorated.flatMap(({ symbol, detail, site }) => (symbol.kind === "class"
|
|
59
|
+
? (membersOf.get(symbol.id) ?? []).filter((member) => !parameterMembers.has(member.id))
|
|
60
|
+
: [symbol]).map((member) => ({ id: member.id, detail, site })));
|
|
58
61
|
}
|