knip 6.0.1 → 6.0.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/ProjectPrincipal.d.ts +2 -0
- package/dist/ProjectPrincipal.js +10 -2
- package/dist/graph/build.js +2 -0
- package/dist/types/project.d.ts +1 -0
- package/dist/typescript/get-imports-and-exports.js +2 -3
- package/dist/typescript/resolve-module-names.d.ts +1 -0
- package/dist/typescript/resolve-module-names.js +17 -0
- package/dist/typescript/visitors/exports.js +4 -2
- package/dist/typescript/visitors/members.d.ts +1 -1
- package/dist/typescript/visitors/members.js +54 -48
- package/dist/typescript/visitors/walk.d.ts +9 -2
- package/dist/typescript/visitors/walk.js +320 -24
- package/dist/util/load-tsconfig.js +17 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/dist/typescript/visitors/local-refs.d.ts +0 -7
- package/dist/typescript/visitors/local-refs.js +0 -243
|
@@ -18,6 +18,7 @@ export declare class ProjectPrincipal {
|
|
|
18
18
|
syncCompilers: SyncCompilers;
|
|
19
19
|
asyncCompilers: AsyncCompilers;
|
|
20
20
|
private paths;
|
|
21
|
+
private rootDirs;
|
|
21
22
|
private extensions;
|
|
22
23
|
cache: CacheConsultant<FileNode>;
|
|
23
24
|
toSourceFilePath: ToSourceFilePath;
|
|
@@ -28,6 +29,7 @@ export declare class ProjectPrincipal {
|
|
|
28
29
|
constructor(options: MainOptions, toSourceFilePath: ToSourceFilePath);
|
|
29
30
|
addCompilers(compilers: [SyncCompilers, AsyncCompilers]): void;
|
|
30
31
|
addPaths(paths: Paths, basePath: string): void;
|
|
32
|
+
addRootDirs(rootDirs: string[]): void;
|
|
31
33
|
init(): void;
|
|
32
34
|
readFile(filePath: string): string;
|
|
33
35
|
private hasAcceptedExtension;
|
package/dist/ProjectPrincipal.js
CHANGED
|
@@ -27,6 +27,7 @@ export class ProjectPrincipal {
|
|
|
27
27
|
syncCompilers = new Map();
|
|
28
28
|
asyncCompilers = new Map();
|
|
29
29
|
paths = {};
|
|
30
|
+
rootDirs = [];
|
|
30
31
|
extensions = new Set(DEFAULT_EXTENSIONS);
|
|
31
32
|
cache;
|
|
32
33
|
toSourceFilePath;
|
|
@@ -69,6 +70,12 @@ export class ProjectPrincipal {
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
}
|
|
73
|
+
addRootDirs(rootDirs) {
|
|
74
|
+
for (const dir of rootDirs) {
|
|
75
|
+
if (!this.rootDirs.includes(dir))
|
|
76
|
+
this.rootDirs.push(dir);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
72
79
|
init() {
|
|
73
80
|
this.extensions = new Set([
|
|
74
81
|
...DEFAULT_EXTENSIONS,
|
|
@@ -76,7 +83,8 @@ export class ProjectPrincipal {
|
|
|
76
83
|
]);
|
|
77
84
|
const customCompilerExtensions = getCompilerExtensions([this.syncCompilers, this.asyncCompilers]);
|
|
78
85
|
const pathsOrUndefined = Object.keys(this.paths).length > 0 ? this.paths : undefined;
|
|
79
|
-
|
|
86
|
+
const rootDirsOrUndefined = this.rootDirs.length > 1 ? this.rootDirs : undefined;
|
|
87
|
+
this.resolveModule = createCustomModuleResolver({ paths: pathsOrUndefined, rootDirs: rootDirsOrUndefined }, customCompilerExtensions, this.toSourceFilePath);
|
|
80
88
|
}
|
|
81
89
|
readFile(filePath) {
|
|
82
90
|
return this.fileManager.readFile(filePath);
|
|
@@ -222,7 +230,7 @@ export class ProjectPrincipal {
|
|
|
222
230
|
}
|
|
223
231
|
}
|
|
224
232
|
if (!this._visitor)
|
|
225
|
-
this._visitor = buildVisitor(this.pluginVisitorObjects);
|
|
233
|
+
this._visitor = buildVisitor(this.pluginVisitorObjects, !!ignoreExportsUsedInFile);
|
|
226
234
|
return _getImportsAndExports(filePath, sourceText, this.resolveModule, options, ignoreExportsUsedInFile, skipExports, this._visitor, this.pluginVisitorObjects.length > 0 ? this.pluginCtx : undefined, parseResult);
|
|
227
235
|
}
|
|
228
236
|
invalidateFile(filePath) {
|
package/dist/graph/build.js
CHANGED
|
@@ -116,6 +116,8 @@ export async function build({ chief, collector, counselor, deputy, principal, is
|
|
|
116
116
|
for (const dep of getManifestImportDependencies(manifest))
|
|
117
117
|
deputy.addReferencedDependency(name, dep);
|
|
118
118
|
principal.addPaths(config.paths, dir);
|
|
119
|
+
if (compilerOptions.rootDirs)
|
|
120
|
+
principal.addRootDirs(compilerOptions.rootDirs);
|
|
119
121
|
const inputsFromPlugins = await worker.runPlugins();
|
|
120
122
|
for (const id of inputsFromPlugins)
|
|
121
123
|
inputs.add(Object.assign(id, { skipExportsAnalysis: !id.allowIncludeExports }));
|
package/dist/types/project.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ import { dirname, isInNodeModules, resolve } from "../util/path.js";
|
|
|
7
7
|
import { shouldIgnore } from "../util/tag.js";
|
|
8
8
|
import { buildLineStarts, getLineAndCol, parseFile, shouldCountRefs, stripQuotes, } from "./visitors/helpers.js";
|
|
9
9
|
import { buildJSDocTagLookup } from "./visitors/jsdoc.js";
|
|
10
|
-
import { collectLocalRefs } from "./visitors/local-refs.js";
|
|
11
10
|
import { walkAST } from "./visitors/walk.js";
|
|
12
11
|
const jsDocImportRe = /import\(\s*['"]([^'"]+)['"]\s*\)(?:\.(\w+))?/g;
|
|
13
12
|
const jsDocImportTagRe = /@import\s+(?:\{[^}]*\}|\*\s+as\s+\w+)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -244,7 +243,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
244
243
|
pluginCtx.addScript = (s) => scripts.add(s);
|
|
245
244
|
pluginCtx.addImport = (spec, pos, mod) => addImport(spec, undefined, undefined, undefined, pos, mod);
|
|
246
245
|
}
|
|
247
|
-
walkAST(result.program, sourceText, filePath, {
|
|
246
|
+
const localRefs = walkAST(result.program, sourceText, filePath, {
|
|
248
247
|
lineStarts,
|
|
249
248
|
skipExports,
|
|
250
249
|
options,
|
|
@@ -261,6 +260,7 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
261
260
|
importAliases,
|
|
262
261
|
referencedInExport,
|
|
263
262
|
skipBareExprRefs: !!ignoreExportsUsedInFile,
|
|
263
|
+
localRefs: ignoreExportsUsedInFile ? new Set() : undefined,
|
|
264
264
|
destructuredExports,
|
|
265
265
|
hasNodeModuleImport,
|
|
266
266
|
resolveModule,
|
|
@@ -309,7 +309,6 @@ const getImportsAndExports = (filePath, sourceText, resolveModule, options, igno
|
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
|
-
const localRefs = ignoreExportsUsedInFile ? collectLocalRefs(result.program, localImportMap, exports) : undefined;
|
|
313
312
|
for (const [id, item] of exports) {
|
|
314
313
|
item.referencedIn = referencedInExport.get(id);
|
|
315
314
|
if (localRefs && shouldCountRefs(ignoreExportsUsedInFile, item.type) && (localRefs.has(id) || item.isReExport)) {
|
|
@@ -2,4 +2,5 @@ import type { ToSourceFilePath } from '../util/to-source-path.ts';
|
|
|
2
2
|
import type { ResolveModule } from './visitors/helpers.ts';
|
|
3
3
|
export declare function createCustomModuleResolver(compilerOptions: {
|
|
4
4
|
paths?: Record<string, string[]>;
|
|
5
|
+
rootDirs?: string[];
|
|
5
6
|
}, customCompilerExtensions: string[], toSourceFilePath: ToSourceFilePath): ResolveModule;
|
|
@@ -12,6 +12,7 @@ export function createCustomModuleResolver(compilerOptions, customCompilerExtens
|
|
|
12
12
|
const alias = convertPathsToAlias(compilerOptions.paths);
|
|
13
13
|
const resolveSync = hasCustomExts ? _createSyncModuleResolver(extensions) : _resolveModuleSync;
|
|
14
14
|
const resolveWithAlias = alias ? _createSyncModuleResolver(extensions, alias) : undefined;
|
|
15
|
+
const rootDirs = compilerOptions.rootDirs;
|
|
15
16
|
function toSourcePath(resolvedFileName) {
|
|
16
17
|
if (!hasCustomExts || !customCompilerExtensionsSet.has(extname(resolvedFileName))) {
|
|
17
18
|
return toSourceFilePath(resolvedFileName) || resolvedFileName;
|
|
@@ -43,6 +44,22 @@ export function createCustomModuleResolver(compilerOptions, customCompilerExtens
|
|
|
43
44
|
if (existsSync(candidate)) {
|
|
44
45
|
return { resolvedFileName: candidate, isExternalLibraryImport: false };
|
|
45
46
|
}
|
|
47
|
+
if (rootDirs && !isAbsolute(sanitizedSpecifier)) {
|
|
48
|
+
const containingDir = dirname(containingFile);
|
|
49
|
+
for (const srcRoot of rootDirs) {
|
|
50
|
+
if (!containingDir.startsWith(srcRoot))
|
|
51
|
+
continue;
|
|
52
|
+
const relPath = containingDir.slice(srcRoot.length);
|
|
53
|
+
for (const targetRoot of rootDirs) {
|
|
54
|
+
if (targetRoot === srcRoot)
|
|
55
|
+
continue;
|
|
56
|
+
const mapped = join(targetRoot, relPath, sanitizedSpecifier);
|
|
57
|
+
const resolved = resolveSync(mapped, containingFile);
|
|
58
|
+
if (resolved)
|
|
59
|
+
return toResult(resolved);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
46
63
|
}
|
|
47
64
|
return timerify(resolveModuleName);
|
|
48
65
|
}
|
|
@@ -133,7 +133,6 @@ export function handleExportNamed(node, s) {
|
|
|
133
133
|
else if ((decl.type === 'FunctionDeclaration' || decl.type === 'TSDeclareFunction') && decl.id) {
|
|
134
134
|
const fix = s.getFix(exportStart, exportStart + 7);
|
|
135
135
|
s.addExport(decl.id.name, SYMBOL_TYPE.FUNCTION, decl.id.start, [], fix, false, s.getJSDocTags(exportStart));
|
|
136
|
-
s.collectRefsInType(decl, decl.id.name, true);
|
|
137
136
|
}
|
|
138
137
|
else if (decl.type === 'ClassDeclaration' && decl.id) {
|
|
139
138
|
const fix = s.getFix(exportStart, exportStart + 7);
|
|
@@ -148,6 +147,10 @@ export function handleExportNamed(node, s) {
|
|
|
148
147
|
const fix = s.getTypeFix(exportStart, exportStart + 7);
|
|
149
148
|
s.addExport(decl.id.name, SYMBOL_TYPE.INTERFACE, decl.id.start, [], fix, false, s.getJSDocTags(exportStart));
|
|
150
149
|
s.collectRefsInType(decl.body, decl.id.name, false);
|
|
150
|
+
for (const ext of decl.extends ?? []) {
|
|
151
|
+
if (ext.expression?.type === 'Identifier')
|
|
152
|
+
s.addRefInExport(ext.expression.name, decl.id.name);
|
|
153
|
+
}
|
|
151
154
|
}
|
|
152
155
|
else if (decl.type === 'TSEnumDeclaration') {
|
|
153
156
|
const members = extractEnumMembers(decl, s.options, s.lineStarts, s.getJSDocTags);
|
|
@@ -207,7 +210,6 @@ export function handleExportDefault(node, s) {
|
|
|
207
210
|
if (decl.type === 'FunctionDeclaration') {
|
|
208
211
|
type = SYMBOL_TYPE.FUNCTION;
|
|
209
212
|
pos = decl.id?.start ?? decl.start;
|
|
210
|
-
s.collectRefsInType(decl, 'default', false);
|
|
211
213
|
}
|
|
212
214
|
else if (decl.type === 'ClassDeclaration') {
|
|
213
215
|
type = SYMBOL_TYPE.CLASS;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { MemberExpression, JSXMemberExpression } from 'oxc-parser';
|
|
2
|
-
import type
|
|
2
|
+
import { type WalkState } from './walk.ts';
|
|
3
3
|
export declare function handleMemberExpression(node: MemberExpression, s: WalkState): void;
|
|
4
4
|
export declare function handleJSXMemberExpression(node: JSXMemberExpression, s: WalkState): void;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { OPAQUE } from "../../constants.js";
|
|
2
2
|
import { addValue } from "../../util/module-graph.js";
|
|
3
3
|
import { getStringValue, isStringLiteral } from "./helpers.js";
|
|
4
|
+
import { isShadowed } from "./walk.js";
|
|
4
5
|
export function handleMemberExpression(node, s) {
|
|
5
6
|
if (node.object.type === 'MemberExpression' && node.object.object.type === 'MemberExpression') {
|
|
6
7
|
s.chainedMemberExprs.add(node.object);
|
|
7
8
|
}
|
|
8
9
|
if (node.object.type === 'Identifier') {
|
|
9
10
|
const localName = node.object.name;
|
|
10
|
-
const
|
|
11
|
+
const shadowed = isShadowed(localName, node.object.start);
|
|
12
|
+
const _import = !shadowed ? s.localImportMap.get(localName) : undefined;
|
|
11
13
|
if (_import) {
|
|
12
14
|
const internalImport = s.internal.get(_import.filePath);
|
|
13
15
|
if (internalImport) {
|
|
@@ -32,7 +34,7 @@ export function handleMemberExpression(node, s) {
|
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
|
-
else {
|
|
37
|
+
else if (!shadowed) {
|
|
36
38
|
const memberName = node.computed === false && node.property.type === 'Identifier' ? node.property.name : undefined;
|
|
37
39
|
if (memberName) {
|
|
38
40
|
const exp = s.exports.get(localName);
|
|
@@ -71,34 +73,36 @@ export function handleMemberExpression(node, s) {
|
|
|
71
73
|
!node.computed &&
|
|
72
74
|
node.property.type === 'Identifier') {
|
|
73
75
|
const rootName = node.object.object.name;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
s.
|
|
76
|
+
if (!isShadowed(rootName, node.object.object.start)) {
|
|
77
|
+
const _import = s.localImportMap.get(rootName);
|
|
78
|
+
if (_import) {
|
|
79
|
+
const internalImport = s.internal.get(_import.filePath);
|
|
80
|
+
if (internalImport) {
|
|
81
|
+
const mid = node.object.property.name;
|
|
82
|
+
s.addNsMemberRefs(internalImport, rootName, mid);
|
|
83
|
+
if (!s.chainedMemberExprs.has(node)) {
|
|
84
|
+
s.addNsMemberRefs(internalImport, rootName, `${mid}.${node.property.name}`);
|
|
85
|
+
}
|
|
82
86
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
if (!_import.isNamespace) {
|
|
88
|
+
const mid = node.object.property.name;
|
|
89
|
+
const _import = s.localImportMap.get(mid);
|
|
90
|
+
if (_import) {
|
|
91
|
+
const midImport = s.internal.get(_import.filePath);
|
|
92
|
+
if (midImport)
|
|
93
|
+
s.addNsMemberRefs(midImport, mid, node.property.name);
|
|
94
|
+
}
|
|
91
95
|
}
|
|
92
96
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
else {
|
|
98
|
+
const exp = s.exports.get(rootName);
|
|
99
|
+
if (exp && exp.members.length > 0) {
|
|
100
|
+
const mid = node.object.property.name;
|
|
101
|
+
const dottedName = `${mid}.${node.property.name}`;
|
|
102
|
+
for (const member of exp.members) {
|
|
103
|
+
if (member.identifier === mid || member.identifier === dottedName)
|
|
104
|
+
member.hasRefsInFile = true;
|
|
105
|
+
}
|
|
102
106
|
}
|
|
103
107
|
}
|
|
104
108
|
}
|
|
@@ -113,28 +117,30 @@ export function handleMemberExpression(node, s) {
|
|
|
113
117
|
!node.computed &&
|
|
114
118
|
node.property.type === 'Identifier') {
|
|
115
119
|
const rootName = node.object.object.object.name;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
if (!isShadowed(rootName, node.object.object.object.start)) {
|
|
121
|
+
const _import = s.localImportMap.get(rootName);
|
|
122
|
+
if (_import) {
|
|
123
|
+
const internalImport = s.internal.get(_import.filePath);
|
|
124
|
+
if (internalImport) {
|
|
125
|
+
const a = node.object.object.property.name;
|
|
126
|
+
const b = node.object.property.name;
|
|
127
|
+
const c = node.property.name;
|
|
128
|
+
s.addNsMemberRefs(internalImport, rootName, a);
|
|
129
|
+
s.addNsMemberRefs(internalImport, rootName, `${a}.${b}`);
|
|
130
|
+
s.addNsMemberRefs(internalImport, rootName, `${a}.${b}.${c}`);
|
|
131
|
+
}
|
|
126
132
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
else {
|
|
134
|
+
const exp = s.exports.get(rootName);
|
|
135
|
+
if (exp && exp.members.length > 0) {
|
|
136
|
+
const a = node.object.object.property.name;
|
|
137
|
+
const b = node.object.property.name;
|
|
138
|
+
const c = node.property.name;
|
|
139
|
+
const dottedName = `${a}.${b}.${c}`;
|
|
140
|
+
for (const member of exp.members) {
|
|
141
|
+
if (member.identifier === a || member.identifier === `${a}.${b}` || member.identifier === dottedName)
|
|
142
|
+
member.hasRefsInFile = true;
|
|
143
|
+
}
|
|
138
144
|
}
|
|
139
145
|
}
|
|
140
146
|
}
|
|
@@ -30,6 +30,7 @@ interface WalkContext {
|
|
|
30
30
|
}>>;
|
|
31
31
|
referencedInExport: Map<string, Set<string>>;
|
|
32
32
|
skipBareExprRefs: boolean;
|
|
33
|
+
localRefs: Set<string> | undefined;
|
|
33
34
|
destructuredExports: Set<string>;
|
|
34
35
|
hasNodeModuleImport: boolean;
|
|
35
36
|
resolveModule: ResolveModule;
|
|
@@ -50,12 +51,18 @@ export interface WalkState extends WalkContext {
|
|
|
50
51
|
chainedMemberExprs: WeakSet<object>;
|
|
51
52
|
currentVarDeclStart: number;
|
|
52
53
|
nsRanges: [number, number][];
|
|
54
|
+
scopeDepth: number;
|
|
55
|
+
scopeStarts: number[];
|
|
56
|
+
scopeEnds: number[];
|
|
57
|
+
shadowScopes: Map<string, [number, number][]>;
|
|
53
58
|
addExport: (identifier: string, type: SymbolType, pos: number, members: ExportMember[], fix: Fix, isReExport: boolean, jsDocTags: Set<string>) => void;
|
|
54
59
|
getFix: (start: number, end: number, flags?: number) => Fix;
|
|
55
60
|
getTypeFix: (start: number, end: number) => Fix;
|
|
56
61
|
collectRefsInType: (node: any, exportName: string, signatureOnly: boolean) => void;
|
|
62
|
+
addRefInExport: (name: string, exportName: string) => void;
|
|
57
63
|
isInNamespace: (node: Span) => boolean;
|
|
58
64
|
}
|
|
59
|
-
export declare
|
|
60
|
-
export declare function
|
|
65
|
+
export declare const isShadowed: (name: string, pos: number) => boolean;
|
|
66
|
+
export declare function buildVisitor(pluginVisitorObjects: PluginVisitorObject[], includeLocalRefs?: boolean): Visitor;
|
|
67
|
+
export declare function walkAST(program: Program, sourceText: string, filePath: string, ctx: WalkContext): Set<string> | undefined;
|
|
61
68
|
export {};
|
|
@@ -86,8 +86,50 @@ const _collectRefsInType = (node, exportName, signatureOnly) => {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
};
|
|
89
|
+
const _addRefInExport = (name, exportName) => {
|
|
90
|
+
const refs = state.referencedInExport.get(name);
|
|
91
|
+
if (refs)
|
|
92
|
+
refs.add(exportName);
|
|
93
|
+
else
|
|
94
|
+
state.referencedInExport.set(name, new Set([exportName]));
|
|
95
|
+
};
|
|
89
96
|
const _isInNamespace = (node) => state.nsRanges.length > 0 && state.nsRanges.some(([start, end]) => node.start >= start && node.end <= end);
|
|
97
|
+
export const isShadowed = (name, pos) => {
|
|
98
|
+
if (state.shadowScopes.size === 0)
|
|
99
|
+
return false;
|
|
100
|
+
const ranges = state.shadowScopes.get(name);
|
|
101
|
+
if (!ranges)
|
|
102
|
+
return false;
|
|
103
|
+
if (state.localImportMap.get(name)?.isDynamicImport)
|
|
104
|
+
return false;
|
|
105
|
+
for (const range of ranges) {
|
|
106
|
+
if (pos >= range[0] && pos <= range[1])
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
};
|
|
111
|
+
const _addLocalRef = (name, pos) => {
|
|
112
|
+
if (!state.localImportMap.has(name) && !isShadowed(name, pos))
|
|
113
|
+
state.localRefs.add(name);
|
|
114
|
+
};
|
|
115
|
+
const _addShadow = (name) => {
|
|
116
|
+
const i = state.scopeDepth - 1;
|
|
117
|
+
const range = [state.scopeStarts[i], state.scopeEnds[i]];
|
|
118
|
+
const ranges = state.shadowScopes.get(name);
|
|
119
|
+
if (ranges)
|
|
120
|
+
ranges.push(range);
|
|
121
|
+
else
|
|
122
|
+
state.shadowScopes.set(name, [range]);
|
|
123
|
+
};
|
|
90
124
|
const coreVisitorObject = {
|
|
125
|
+
BlockStatement(node) {
|
|
126
|
+
state.scopeStarts[state.scopeDepth] = node.start;
|
|
127
|
+
state.scopeEnds[state.scopeDepth] = node.end;
|
|
128
|
+
state.scopeDepth++;
|
|
129
|
+
},
|
|
130
|
+
'BlockStatement:exit'() {
|
|
131
|
+
state.scopeDepth--;
|
|
132
|
+
},
|
|
91
133
|
TSModuleDeclaration(node) {
|
|
92
134
|
state.nsRanges.push([node.start, node.end]);
|
|
93
135
|
},
|
|
@@ -96,14 +138,27 @@ const coreVisitorObject = {
|
|
|
96
138
|
state.localDeclarationTypes.set(node.id.name, SYMBOL_TYPE.CLASS);
|
|
97
139
|
},
|
|
98
140
|
FunctionDeclaration(node) {
|
|
99
|
-
if (node.id?.name)
|
|
141
|
+
if (node.id?.name) {
|
|
100
142
|
state.localDeclarationTypes.set(node.id.name, SYMBOL_TYPE.FUNCTION);
|
|
143
|
+
if (state.scopeDepth > 0)
|
|
144
|
+
_addShadow(node.id.name);
|
|
145
|
+
}
|
|
101
146
|
},
|
|
102
147
|
VariableDeclaration(node) {
|
|
103
148
|
state.currentVarDeclStart = node.start;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
149
|
+
if (state.scopeDepth > 0) {
|
|
150
|
+
for (const decl of node.declarations) {
|
|
151
|
+
if (decl.id.type === 'Identifier') {
|
|
152
|
+
state.localDeclarationTypes.set(decl.id.name, SYMBOL_TYPE.VARIABLE);
|
|
153
|
+
_addShadow(decl.id.name);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
for (const decl of node.declarations) {
|
|
159
|
+
if (decl.id.type === 'Identifier')
|
|
160
|
+
state.localDeclarationTypes.set(decl.id.name, SYMBOL_TYPE.VARIABLE);
|
|
161
|
+
}
|
|
107
162
|
}
|
|
108
163
|
},
|
|
109
164
|
TSEnumDeclaration(node) {
|
|
@@ -141,7 +196,7 @@ const coreVisitorObject = {
|
|
|
141
196
|
handleJSXMemberExpression(node, state);
|
|
142
197
|
},
|
|
143
198
|
ForInStatement(node) {
|
|
144
|
-
if (node.right.type === 'Identifier') {
|
|
199
|
+
if (node.right.type === 'Identifier' && !isShadowed(node.right.name, node.right.start)) {
|
|
145
200
|
const _import = state.localImportMap.get(node.right.name);
|
|
146
201
|
if (_import?.isNamespace) {
|
|
147
202
|
const internalImport = state.internal.get(_import.filePath);
|
|
@@ -151,7 +206,7 @@ const coreVisitorObject = {
|
|
|
151
206
|
}
|
|
152
207
|
},
|
|
153
208
|
ForOfStatement(node) {
|
|
154
|
-
if (node.right.type === 'Identifier') {
|
|
209
|
+
if (node.right.type === 'Identifier' && !isShadowed(node.right.name, node.right.start)) {
|
|
155
210
|
const _import = state.localImportMap.get(node.right.name);
|
|
156
211
|
if (_import?.isNamespace) {
|
|
157
212
|
const internalImport = state.internal.get(_import.filePath);
|
|
@@ -168,7 +223,7 @@ const coreVisitorObject = {
|
|
|
168
223
|
parts.unshift(left.right.name);
|
|
169
224
|
left = left.left;
|
|
170
225
|
}
|
|
171
|
-
if (left.type === 'Identifier') {
|
|
226
|
+
if (left.type === 'Identifier' && !isShadowed(left.name, left.start)) {
|
|
172
227
|
const rootName = left.name;
|
|
173
228
|
const _import = state.localImportMap.get(rootName);
|
|
174
229
|
if (_import) {
|
|
@@ -204,22 +259,26 @@ const coreVisitorObject = {
|
|
|
204
259
|
TSTypeReference(node) {
|
|
205
260
|
if (node.typeName.type === 'Identifier') {
|
|
206
261
|
const name = node.typeName.name;
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
internalImport
|
|
262
|
+
if (!isShadowed(name, node.typeName.start)) {
|
|
263
|
+
const _import = state.localImportMap.get(name);
|
|
264
|
+
if (_import) {
|
|
265
|
+
const internalImport = state.internal.get(_import.filePath);
|
|
266
|
+
if (internalImport)
|
|
267
|
+
internalImport.refs.add(name);
|
|
268
|
+
}
|
|
212
269
|
}
|
|
213
270
|
}
|
|
214
271
|
},
|
|
215
272
|
TSTypeQuery(node) {
|
|
216
273
|
if (node.exprName.type === 'Identifier') {
|
|
217
274
|
const name = node.exprName.name;
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
internalImport
|
|
275
|
+
if (!isShadowed(name, node.exprName.start)) {
|
|
276
|
+
const _import = state.localImportMap.get(name);
|
|
277
|
+
if (_import) {
|
|
278
|
+
const internalImport = state.internal.get(_import.filePath);
|
|
279
|
+
if (internalImport)
|
|
280
|
+
internalImport.refs.add(name);
|
|
281
|
+
}
|
|
223
282
|
}
|
|
224
283
|
}
|
|
225
284
|
},
|
|
@@ -264,9 +323,235 @@ const coreVisitorObject = {
|
|
|
264
323
|
}
|
|
265
324
|
},
|
|
266
325
|
};
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
326
|
+
const localRefsVisitorObject = {
|
|
327
|
+
ClassDeclaration(node) {
|
|
328
|
+
if (node.superClass?.type === 'Identifier')
|
|
329
|
+
_addLocalRef(node.superClass.name, node.superClass.start);
|
|
330
|
+
for (const impl of node.implements ?? []) {
|
|
331
|
+
if (impl.expression?.type === 'Identifier')
|
|
332
|
+
_addLocalRef(impl.expression.name, impl.expression.start);
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
TSInterfaceDeclaration(node) {
|
|
336
|
+
for (const ext of node.extends ?? []) {
|
|
337
|
+
if (ext.expression?.type === 'Identifier')
|
|
338
|
+
_addLocalRef(ext.expression.name, ext.expression.start);
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
Property(node) {
|
|
342
|
+
if (node.value?.type === 'Identifier')
|
|
343
|
+
_addLocalRef(node.value.name, node.value.start);
|
|
344
|
+
},
|
|
345
|
+
ReturnStatement(node) {
|
|
346
|
+
if (node.argument?.type === 'Identifier')
|
|
347
|
+
_addLocalRef(node.argument.name, node.argument.start);
|
|
348
|
+
},
|
|
349
|
+
AssignmentExpression(node) {
|
|
350
|
+
if (node.right?.type === 'Identifier')
|
|
351
|
+
_addLocalRef(node.right.name, node.right.start);
|
|
352
|
+
},
|
|
353
|
+
SpreadElement(node) {
|
|
354
|
+
if (node.argument?.type === 'Identifier')
|
|
355
|
+
_addLocalRef(node.argument.name, node.argument.start);
|
|
356
|
+
},
|
|
357
|
+
ConditionalExpression(node) {
|
|
358
|
+
if (node.test?.type === 'Identifier')
|
|
359
|
+
_addLocalRef(node.test.name, node.test.start);
|
|
360
|
+
if (node.consequent?.type === 'Identifier')
|
|
361
|
+
_addLocalRef(node.consequent.name, node.consequent.start);
|
|
362
|
+
if (node.alternate?.type === 'Identifier')
|
|
363
|
+
_addLocalRef(node.alternate.name, node.alternate.start);
|
|
364
|
+
},
|
|
365
|
+
ArrayExpression(node) {
|
|
366
|
+
for (const el of node.elements ?? []) {
|
|
367
|
+
if (el?.type === 'Identifier')
|
|
368
|
+
_addLocalRef(el.name, el.start);
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
TemplateLiteral(node) {
|
|
372
|
+
for (const expr of node.expressions ?? []) {
|
|
373
|
+
if (expr.type === 'Identifier')
|
|
374
|
+
_addLocalRef(expr.name, expr.start);
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
BinaryExpression(node) {
|
|
378
|
+
if (node.left?.type === 'Identifier')
|
|
379
|
+
_addLocalRef(node.left.name, node.left.start);
|
|
380
|
+
if (node.right?.type === 'Identifier')
|
|
381
|
+
_addLocalRef(node.right.name, node.right.start);
|
|
382
|
+
},
|
|
383
|
+
LogicalExpression(node) {
|
|
384
|
+
if (node.left?.type === 'Identifier')
|
|
385
|
+
_addLocalRef(node.left.name, node.left.start);
|
|
386
|
+
if (node.right?.type === 'Identifier')
|
|
387
|
+
_addLocalRef(node.right.name, node.right.start);
|
|
388
|
+
},
|
|
389
|
+
UnaryExpression(node) {
|
|
390
|
+
if (node.argument?.type === 'Identifier')
|
|
391
|
+
_addLocalRef(node.argument.name, node.argument.start);
|
|
392
|
+
},
|
|
393
|
+
SwitchStatement(node) {
|
|
394
|
+
if (node.discriminant?.type === 'Identifier')
|
|
395
|
+
_addLocalRef(node.discriminant.name, node.discriminant.start);
|
|
396
|
+
for (const c of node.cases ?? []) {
|
|
397
|
+
if (c.test?.type === 'Identifier')
|
|
398
|
+
_addLocalRef(c.test.name, c.test.start);
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
IfStatement(node) {
|
|
402
|
+
if (node.test?.type === 'Identifier')
|
|
403
|
+
_addLocalRef(node.test.name, node.test.start);
|
|
404
|
+
},
|
|
405
|
+
ThrowStatement(node) {
|
|
406
|
+
if (node.argument?.type === 'Identifier')
|
|
407
|
+
_addLocalRef(node.argument.name, node.argument.start);
|
|
408
|
+
},
|
|
409
|
+
WhileStatement(node) {
|
|
410
|
+
if (node.test?.type === 'Identifier')
|
|
411
|
+
_addLocalRef(node.test.name, node.test.start);
|
|
412
|
+
},
|
|
413
|
+
DoWhileStatement(node) {
|
|
414
|
+
if (node.test?.type === 'Identifier')
|
|
415
|
+
_addLocalRef(node.test.name, node.test.start);
|
|
416
|
+
},
|
|
417
|
+
YieldExpression(node) {
|
|
418
|
+
if (node.argument?.type === 'Identifier')
|
|
419
|
+
_addLocalRef(node.argument.name, node.argument.start);
|
|
420
|
+
},
|
|
421
|
+
AwaitExpression(node) {
|
|
422
|
+
if (node.argument?.type === 'Identifier')
|
|
423
|
+
_addLocalRef(node.argument.name, node.argument.start);
|
|
424
|
+
},
|
|
425
|
+
ArrowFunctionExpression(node) {
|
|
426
|
+
if (node.body?.type === 'Identifier')
|
|
427
|
+
_addLocalRef(node.body.name, node.body.start);
|
|
428
|
+
},
|
|
429
|
+
AssignmentPattern(node) {
|
|
430
|
+
if (node.right?.type === 'Identifier')
|
|
431
|
+
_addLocalRef(node.right.name, node.right.start);
|
|
432
|
+
},
|
|
433
|
+
SequenceExpression(node) {
|
|
434
|
+
for (const expr of node.expressions ?? []) {
|
|
435
|
+
if (expr.type === 'Identifier')
|
|
436
|
+
_addLocalRef(expr.name, expr.start);
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
TSAsExpression(node) {
|
|
440
|
+
if (node.expression?.type === 'Identifier')
|
|
441
|
+
_addLocalRef(node.expression.name, node.expression.start);
|
|
442
|
+
},
|
|
443
|
+
TSSatisfiesExpression(node) {
|
|
444
|
+
if (node.expression?.type === 'Identifier')
|
|
445
|
+
_addLocalRef(node.expression.name, node.expression.start);
|
|
446
|
+
},
|
|
447
|
+
TSNonNullExpression(node) {
|
|
448
|
+
if (node.expression?.type === 'Identifier')
|
|
449
|
+
_addLocalRef(node.expression.name, node.expression.start);
|
|
450
|
+
},
|
|
451
|
+
TSTypeAssertion(node) {
|
|
452
|
+
if (node.expression?.type === 'Identifier')
|
|
453
|
+
_addLocalRef(node.expression.name, node.expression.start);
|
|
454
|
+
},
|
|
455
|
+
ParenthesizedExpression(node) {
|
|
456
|
+
if (node.expression?.type === 'Identifier')
|
|
457
|
+
_addLocalRef(node.expression.name, node.expression.start);
|
|
458
|
+
},
|
|
459
|
+
PropertyDefinition(node) {
|
|
460
|
+
if (node.value?.type === 'Identifier')
|
|
461
|
+
_addLocalRef(node.value.name, node.value.start);
|
|
462
|
+
},
|
|
463
|
+
ForInStatement(node) {
|
|
464
|
+
if (node.right?.type === 'Identifier')
|
|
465
|
+
_addLocalRef(node.right.name, node.right.start);
|
|
466
|
+
},
|
|
467
|
+
ForOfStatement(node) {
|
|
468
|
+
if (node.right?.type === 'Identifier')
|
|
469
|
+
_addLocalRef(node.right.name, node.right.start);
|
|
470
|
+
},
|
|
471
|
+
JSXOpeningElement(node) {
|
|
472
|
+
if (node.name?.type === 'JSXIdentifier')
|
|
473
|
+
_addLocalRef(node.name.name, node.name.start);
|
|
474
|
+
for (const attr of node.attributes ?? []) {
|
|
475
|
+
if (attr.type === 'JSXSpreadAttribute' && attr.argument?.type === 'Identifier')
|
|
476
|
+
_addLocalRef(attr.argument.name, attr.argument.start);
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
JSXExpressionContainer(node) {
|
|
480
|
+
if (node.expression?.type === 'Identifier')
|
|
481
|
+
_addLocalRef(node.expression.name, node.expression.start);
|
|
482
|
+
},
|
|
483
|
+
VariableDeclarator(node) {
|
|
484
|
+
if (node.init?.type === 'Identifier')
|
|
485
|
+
_addLocalRef(node.init.name, node.init.start);
|
|
486
|
+
},
|
|
487
|
+
ExpressionStatement(node) {
|
|
488
|
+
if (node.expression?.type === 'Identifier')
|
|
489
|
+
_addLocalRef(node.expression.name, node.expression.start);
|
|
490
|
+
},
|
|
491
|
+
CallExpression(node) {
|
|
492
|
+
if (node.callee?.type === 'Identifier')
|
|
493
|
+
_addLocalRef(node.callee.name, node.callee.start);
|
|
494
|
+
for (const arg of node.arguments ?? []) {
|
|
495
|
+
if (arg.type === 'Identifier')
|
|
496
|
+
_addLocalRef(arg.name, arg.start);
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
NewExpression(node) {
|
|
500
|
+
if (node.callee?.type === 'Identifier')
|
|
501
|
+
_addLocalRef(node.callee.name, node.callee.start);
|
|
502
|
+
for (const arg of node.arguments ?? []) {
|
|
503
|
+
if (arg.type === 'Identifier')
|
|
504
|
+
_addLocalRef(arg.name, arg.start);
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
MemberExpression(node) {
|
|
508
|
+
if (node.object?.type === 'Identifier')
|
|
509
|
+
_addLocalRef(node.object.name, node.object.start);
|
|
510
|
+
if (node.computed && node.property?.type === 'Identifier')
|
|
511
|
+
_addLocalRef(node.property.name, node.property.start);
|
|
512
|
+
},
|
|
513
|
+
TaggedTemplateExpression(node) {
|
|
514
|
+
if (node.tag?.type === 'Identifier')
|
|
515
|
+
_addLocalRef(node.tag.name, node.tag.start);
|
|
516
|
+
},
|
|
517
|
+
TSQualifiedName(node) {
|
|
518
|
+
let left = node;
|
|
519
|
+
const parts = [];
|
|
520
|
+
while (left.type === 'TSQualifiedName') {
|
|
521
|
+
if (left.right.type === 'Identifier')
|
|
522
|
+
parts.unshift(left.right.name);
|
|
523
|
+
left = left.left;
|
|
524
|
+
}
|
|
525
|
+
if (left.type === 'Identifier') {
|
|
526
|
+
const rootName = left.name;
|
|
527
|
+
if (!state.localImportMap.has(rootName) && !isShadowed(rootName, left.start) && parts.length > 0) {
|
|
528
|
+
const exp = state.exports.get(rootName);
|
|
529
|
+
if (exp) {
|
|
530
|
+
state.localRefs.add(rootName);
|
|
531
|
+
for (const member of exp.members) {
|
|
532
|
+
if (member.identifier === parts[0])
|
|
533
|
+
member.hasRefsInFile = true;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
},
|
|
539
|
+
TSTypeReference(node) {
|
|
540
|
+
if (node.typeName?.type === 'Identifier') {
|
|
541
|
+
const name = node.typeName.name;
|
|
542
|
+
if (!state.localImportMap.has(name))
|
|
543
|
+
_addLocalRef(name, node.typeName.start);
|
|
544
|
+
}
|
|
545
|
+
},
|
|
546
|
+
TSTypeQuery(node) {
|
|
547
|
+
if (node.exprName?.type === 'Identifier') {
|
|
548
|
+
const name = node.exprName.name;
|
|
549
|
+
if (!state.localImportMap.has(name))
|
|
550
|
+
_addLocalRef(name, node.exprName.start);
|
|
551
|
+
}
|
|
552
|
+
},
|
|
553
|
+
};
|
|
554
|
+
export function buildVisitor(pluginVisitorObjects, includeLocalRefs) {
|
|
270
555
|
const handlerLists = new Map();
|
|
271
556
|
const coreHandlers = coreVisitorObject;
|
|
272
557
|
for (const key in coreHandlers) {
|
|
@@ -274,10 +559,12 @@ export function buildVisitor(pluginVisitorObjects) {
|
|
|
274
559
|
if (fn)
|
|
275
560
|
handlerLists.set(key, [fn]);
|
|
276
561
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
562
|
+
const extras = includeLocalRefs
|
|
563
|
+
? [localRefsVisitorObject, ...pluginVisitorObjects]
|
|
564
|
+
: pluginVisitorObjects;
|
|
565
|
+
for (const obj of extras) {
|
|
566
|
+
for (const key in obj) {
|
|
567
|
+
const fn = obj[key];
|
|
281
568
|
if (!fn)
|
|
282
569
|
continue;
|
|
283
570
|
const list = handlerLists.get(key);
|
|
@@ -287,6 +574,8 @@ export function buildVisitor(pluginVisitorObjects) {
|
|
|
287
574
|
handlerLists.set(key, [fn]);
|
|
288
575
|
}
|
|
289
576
|
}
|
|
577
|
+
if (extras.length === 0)
|
|
578
|
+
return new Visitor(coreVisitorObject);
|
|
290
579
|
const merged = {};
|
|
291
580
|
for (const [key, list] of handlerLists) {
|
|
292
581
|
if (list.length === 1) {
|
|
@@ -317,10 +606,15 @@ export function walkAST(program, sourceText, filePath, ctx) {
|
|
|
317
606
|
chainedMemberExprs: new WeakSet(),
|
|
318
607
|
currentVarDeclStart: -1,
|
|
319
608
|
nsRanges: [],
|
|
609
|
+
scopeDepth: 0,
|
|
610
|
+
scopeStarts: [],
|
|
611
|
+
scopeEnds: [],
|
|
612
|
+
shadowScopes: new Map(),
|
|
320
613
|
addExport: _addExport,
|
|
321
614
|
getFix: _getFix,
|
|
322
615
|
getTypeFix: _getTypeFix,
|
|
323
616
|
collectRefsInType: _collectRefsInType,
|
|
617
|
+
addRefInExport: _addRefInExport,
|
|
324
618
|
isInNamespace: _isInNamespace,
|
|
325
619
|
};
|
|
326
620
|
ctx.visitor.visit(program);
|
|
@@ -357,5 +651,7 @@ export function walkAST(program, sourceText, filePath, ctx) {
|
|
|
357
651
|
item.hasRefsInFile = true;
|
|
358
652
|
}
|
|
359
653
|
}
|
|
654
|
+
const localRefs = state.localRefs;
|
|
360
655
|
state = undefined;
|
|
656
|
+
return localRefs;
|
|
361
657
|
}
|
|
@@ -47,6 +47,19 @@ const expandFileNames = (dir, compilerOptions, include, exclude, files) => {
|
|
|
47
47
|
}
|
|
48
48
|
return result;
|
|
49
49
|
};
|
|
50
|
+
const findRootDirsBase = (tsConfigFilePath) => {
|
|
51
|
+
try {
|
|
52
|
+
const raw = JSON.parse(stripJsonComments(readFileSync(tsConfigFilePath, 'utf8')));
|
|
53
|
+
if (raw.compilerOptions?.rootDirs)
|
|
54
|
+
return dirname(tsConfigFilePath);
|
|
55
|
+
if (raw.extends) {
|
|
56
|
+
const extPath = join(dirname(tsConfigFilePath), raw.extends);
|
|
57
|
+
return findRootDirsBase(extPath);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch { }
|
|
61
|
+
return undefined;
|
|
62
|
+
};
|
|
50
63
|
const resolveConfig = (tsConfigFilePath) => {
|
|
51
64
|
try {
|
|
52
65
|
return parseTsconfig(tsConfigFilePath);
|
|
@@ -77,6 +90,10 @@ export const loadTSConfig = async (tsConfigFilePath) => {
|
|
|
77
90
|
if (compilerOptions.paths) {
|
|
78
91
|
compilerOptions.pathsBasePath ??= dir;
|
|
79
92
|
}
|
|
93
|
+
if (compilerOptions.rootDirs) {
|
|
94
|
+
const rootDirsBase = findRootDirsBase(tsConfigFilePath) ?? dir;
|
|
95
|
+
compilerOptions.rootDirs = compilerOptions.rootDirs.map((d) => isAbsolute(d) ? d : join(rootDirsBase, d));
|
|
96
|
+
}
|
|
80
97
|
const include = resolvePatterns(config.include, dir, true);
|
|
81
98
|
const exclude = resolvePatterns(config.exclude, dir, true);
|
|
82
99
|
const files = resolvePatterns(config.files, dir);
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "6.0.
|
|
1
|
+
export declare const version = "6.0.2";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '6.0.
|
|
1
|
+
export const version = '6.0.2';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knip",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
4
4
|
"description": "Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"analysis",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"@nodelib/fs.walk": "^1.2.3",
|
|
81
81
|
"fast-glob": "^3.3.3",
|
|
82
82
|
"formatly": "^0.3.0",
|
|
83
|
-
"get-tsconfig": "4.13.
|
|
83
|
+
"get-tsconfig": "4.13.7",
|
|
84
84
|
"jiti": "^2.6.0",
|
|
85
85
|
"minimist": "^1.2.8",
|
|
86
86
|
"oxc-parser": "^0.120.0",
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { type Program } from 'oxc-parser';
|
|
2
|
-
import type { Export } from '../../types/module-graph.ts';
|
|
3
|
-
export declare function collectLocalRefs(program: Program, localImportMap: Map<string, {
|
|
4
|
-
importedName: string;
|
|
5
|
-
filePath: string;
|
|
6
|
-
isNamespace: boolean;
|
|
7
|
-
}>, fileExports: Map<string, Export>): Set<string>;
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { Visitor } from 'oxc-parser';
|
|
2
|
-
let refs;
|
|
3
|
-
let importNames;
|
|
4
|
-
let exportsMap;
|
|
5
|
-
const add = (name) => {
|
|
6
|
-
if (!importNames.has(name))
|
|
7
|
-
refs.add(name);
|
|
8
|
-
};
|
|
9
|
-
const visitor = new Visitor({
|
|
10
|
-
ClassDeclaration(node) {
|
|
11
|
-
if (node.superClass?.type === 'Identifier')
|
|
12
|
-
add(node.superClass.name);
|
|
13
|
-
for (const impl of node.implements ?? []) {
|
|
14
|
-
if (impl.expression?.type === 'Identifier')
|
|
15
|
-
add(impl.expression.name);
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
TSInterfaceDeclaration(node) {
|
|
19
|
-
for (const ext of node.extends ?? []) {
|
|
20
|
-
if (ext.expression?.type === 'Identifier')
|
|
21
|
-
add(ext.expression.name);
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
Property(node) {
|
|
25
|
-
if (node.value?.type === 'Identifier')
|
|
26
|
-
add(node.value.name);
|
|
27
|
-
},
|
|
28
|
-
ReturnStatement(node) {
|
|
29
|
-
if (node.argument?.type === 'Identifier')
|
|
30
|
-
add(node.argument.name);
|
|
31
|
-
},
|
|
32
|
-
AssignmentExpression(node) {
|
|
33
|
-
if (node.right?.type === 'Identifier')
|
|
34
|
-
add(node.right.name);
|
|
35
|
-
},
|
|
36
|
-
SpreadElement(node) {
|
|
37
|
-
if (node.argument?.type === 'Identifier')
|
|
38
|
-
add(node.argument.name);
|
|
39
|
-
},
|
|
40
|
-
ConditionalExpression(node) {
|
|
41
|
-
if (node.test?.type === 'Identifier')
|
|
42
|
-
add(node.test.name);
|
|
43
|
-
if (node.consequent?.type === 'Identifier')
|
|
44
|
-
add(node.consequent.name);
|
|
45
|
-
if (node.alternate?.type === 'Identifier')
|
|
46
|
-
add(node.alternate.name);
|
|
47
|
-
},
|
|
48
|
-
ArrayExpression(node) {
|
|
49
|
-
for (const el of node.elements ?? []) {
|
|
50
|
-
if (el?.type === 'Identifier')
|
|
51
|
-
add(el.name);
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
TemplateLiteral(node) {
|
|
55
|
-
for (const expr of node.expressions ?? []) {
|
|
56
|
-
if (expr.type === 'Identifier')
|
|
57
|
-
add(expr.name);
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
BinaryExpression(node) {
|
|
61
|
-
if (node.left?.type === 'Identifier')
|
|
62
|
-
add(node.left.name);
|
|
63
|
-
if (node.right?.type === 'Identifier')
|
|
64
|
-
add(node.right.name);
|
|
65
|
-
},
|
|
66
|
-
LogicalExpression(node) {
|
|
67
|
-
if (node.left?.type === 'Identifier')
|
|
68
|
-
add(node.left.name);
|
|
69
|
-
if (node.right?.type === 'Identifier')
|
|
70
|
-
add(node.right.name);
|
|
71
|
-
},
|
|
72
|
-
UnaryExpression(node) {
|
|
73
|
-
if (node.argument?.type === 'Identifier')
|
|
74
|
-
add(node.argument.name);
|
|
75
|
-
},
|
|
76
|
-
SwitchStatement(node) {
|
|
77
|
-
if (node.discriminant?.type === 'Identifier')
|
|
78
|
-
add(node.discriminant.name);
|
|
79
|
-
for (const c of node.cases ?? []) {
|
|
80
|
-
if (c.test?.type === 'Identifier')
|
|
81
|
-
add(c.test.name);
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
IfStatement(node) {
|
|
85
|
-
if (node.test?.type === 'Identifier')
|
|
86
|
-
add(node.test.name);
|
|
87
|
-
},
|
|
88
|
-
ThrowStatement(node) {
|
|
89
|
-
if (node.argument?.type === 'Identifier')
|
|
90
|
-
add(node.argument.name);
|
|
91
|
-
},
|
|
92
|
-
WhileStatement(node) {
|
|
93
|
-
if (node.test?.type === 'Identifier')
|
|
94
|
-
add(node.test.name);
|
|
95
|
-
},
|
|
96
|
-
DoWhileStatement(node) {
|
|
97
|
-
if (node.test?.type === 'Identifier')
|
|
98
|
-
add(node.test.name);
|
|
99
|
-
},
|
|
100
|
-
YieldExpression(node) {
|
|
101
|
-
if (node.argument?.type === 'Identifier')
|
|
102
|
-
add(node.argument.name);
|
|
103
|
-
},
|
|
104
|
-
AwaitExpression(node) {
|
|
105
|
-
if (node.argument?.type === 'Identifier')
|
|
106
|
-
add(node.argument.name);
|
|
107
|
-
},
|
|
108
|
-
ArrowFunctionExpression(node) {
|
|
109
|
-
if (node.body?.type === 'Identifier')
|
|
110
|
-
add(node.body.name);
|
|
111
|
-
},
|
|
112
|
-
AssignmentPattern(node) {
|
|
113
|
-
if (node.right?.type === 'Identifier')
|
|
114
|
-
add(node.right.name);
|
|
115
|
-
},
|
|
116
|
-
SequenceExpression(node) {
|
|
117
|
-
for (const expr of node.expressions ?? []) {
|
|
118
|
-
if (expr.type === 'Identifier')
|
|
119
|
-
add(expr.name);
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
TSAsExpression(node) {
|
|
123
|
-
if (node.expression?.type === 'Identifier')
|
|
124
|
-
add(node.expression.name);
|
|
125
|
-
},
|
|
126
|
-
TSSatisfiesExpression(node) {
|
|
127
|
-
if (node.expression?.type === 'Identifier')
|
|
128
|
-
add(node.expression.name);
|
|
129
|
-
},
|
|
130
|
-
TSNonNullExpression(node) {
|
|
131
|
-
if (node.expression?.type === 'Identifier')
|
|
132
|
-
add(node.expression.name);
|
|
133
|
-
},
|
|
134
|
-
TSTypeAssertion(node) {
|
|
135
|
-
if (node.expression?.type === 'Identifier')
|
|
136
|
-
add(node.expression.name);
|
|
137
|
-
},
|
|
138
|
-
ParenthesizedExpression(node) {
|
|
139
|
-
if (node.expression?.type === 'Identifier')
|
|
140
|
-
add(node.expression.name);
|
|
141
|
-
},
|
|
142
|
-
PropertyDefinition(node) {
|
|
143
|
-
if (node.value?.type === 'Identifier')
|
|
144
|
-
add(node.value.name);
|
|
145
|
-
},
|
|
146
|
-
ForInStatement(node) {
|
|
147
|
-
if (node.right?.type === 'Identifier')
|
|
148
|
-
add(node.right.name);
|
|
149
|
-
},
|
|
150
|
-
ForOfStatement(node) {
|
|
151
|
-
if (node.right?.type === 'Identifier')
|
|
152
|
-
add(node.right.name);
|
|
153
|
-
},
|
|
154
|
-
JSXOpeningElement(node) {
|
|
155
|
-
if (node.name?.type === 'JSXIdentifier')
|
|
156
|
-
add(node.name.name);
|
|
157
|
-
for (const attr of node.attributes ?? []) {
|
|
158
|
-
if (attr.type === 'JSXSpreadAttribute' && attr.argument?.type === 'Identifier')
|
|
159
|
-
add(attr.argument.name);
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
JSXExpressionContainer(node) {
|
|
163
|
-
if (node.expression?.type === 'Identifier')
|
|
164
|
-
add(node.expression.name);
|
|
165
|
-
},
|
|
166
|
-
VariableDeclarator(node) {
|
|
167
|
-
if (node.init?.type === 'Identifier')
|
|
168
|
-
add(node.init.name);
|
|
169
|
-
},
|
|
170
|
-
ExpressionStatement(node) {
|
|
171
|
-
if (node.expression?.type === 'Identifier')
|
|
172
|
-
add(node.expression.name);
|
|
173
|
-
},
|
|
174
|
-
CallExpression(node) {
|
|
175
|
-
if (node.callee?.type === 'Identifier')
|
|
176
|
-
add(node.callee.name);
|
|
177
|
-
for (const arg of node.arguments ?? []) {
|
|
178
|
-
if (arg.type === 'Identifier')
|
|
179
|
-
add(arg.name);
|
|
180
|
-
}
|
|
181
|
-
},
|
|
182
|
-
NewExpression(node) {
|
|
183
|
-
if (node.callee?.type === 'Identifier')
|
|
184
|
-
add(node.callee.name);
|
|
185
|
-
for (const arg of node.arguments ?? []) {
|
|
186
|
-
if (arg.type === 'Identifier')
|
|
187
|
-
add(arg.name);
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
MemberExpression(node) {
|
|
191
|
-
if (node.object?.type === 'Identifier')
|
|
192
|
-
add(node.object.name);
|
|
193
|
-
if (node.computed && node.property?.type === 'Identifier')
|
|
194
|
-
add(node.property.name);
|
|
195
|
-
},
|
|
196
|
-
TaggedTemplateExpression(node) {
|
|
197
|
-
if (node.tag?.type === 'Identifier')
|
|
198
|
-
add(node.tag.name);
|
|
199
|
-
},
|
|
200
|
-
TSQualifiedName(node) {
|
|
201
|
-
let left = node;
|
|
202
|
-
const parts = [];
|
|
203
|
-
while (left.type === 'TSQualifiedName') {
|
|
204
|
-
if (left.right.type === 'Identifier')
|
|
205
|
-
parts.unshift(left.right.name);
|
|
206
|
-
left = left.left;
|
|
207
|
-
}
|
|
208
|
-
if (left.type === 'Identifier') {
|
|
209
|
-
const rootName = left.name;
|
|
210
|
-
if (!importNames.has(rootName) && parts.length > 0) {
|
|
211
|
-
const exp = exportsMap.get(rootName);
|
|
212
|
-
if (exp) {
|
|
213
|
-
refs.add(rootName);
|
|
214
|
-
for (const member of exp.members) {
|
|
215
|
-
if (member.identifier === parts[0])
|
|
216
|
-
member.hasRefsInFile = true;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
},
|
|
222
|
-
TSTypeReference(node) {
|
|
223
|
-
if (node.typeName?.type === 'Identifier') {
|
|
224
|
-
const name = node.typeName.name;
|
|
225
|
-
if (!importNames.has(name))
|
|
226
|
-
refs.add(name);
|
|
227
|
-
}
|
|
228
|
-
},
|
|
229
|
-
TSTypeQuery(node) {
|
|
230
|
-
if (node.exprName?.type === 'Identifier') {
|
|
231
|
-
const name = node.exprName.name;
|
|
232
|
-
if (!importNames.has(name))
|
|
233
|
-
refs.add(name);
|
|
234
|
-
}
|
|
235
|
-
},
|
|
236
|
-
});
|
|
237
|
-
export function collectLocalRefs(program, localImportMap, fileExports) {
|
|
238
|
-
refs = new Set();
|
|
239
|
-
importNames = localImportMap;
|
|
240
|
-
exportsMap = fileExports;
|
|
241
|
-
visitor.visit(program);
|
|
242
|
-
return refs;
|
|
243
|
-
}
|