knip 5.70.1 → 5.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DependencyDeputy.js +2 -2
- package/dist/ProjectPrincipal.js +1 -1
- package/dist/WorkspaceWorker.js +32 -35
- package/dist/binaries/bash-parser.js +14 -1
- package/dist/compilers/index.js +1 -1
- package/dist/constants.js +1 -0
- package/dist/graph/analyze.js +21 -16
- package/dist/graph/build.js +71 -87
- package/dist/graph-explorer/constants.d.ts +2 -0
- package/dist/graph-explorer/constants.js +2 -0
- package/dist/graph-explorer/explorer.d.ts +11 -0
- package/dist/graph-explorer/explorer.js +10 -0
- package/dist/graph-explorer/operations/build-trace-tree.d.ts +12 -0
- package/dist/graph-explorer/operations/build-trace-tree.js +51 -0
- package/dist/graph-explorer/operations/has-strictly-ns-references.d.ts +2 -0
- package/dist/graph-explorer/operations/has-strictly-ns-references.js +98 -0
- package/dist/graph-explorer/operations/is-referenced.d.ts +4 -0
- package/dist/graph-explorer/operations/is-referenced.js +89 -0
- package/dist/graph-explorer/utils.d.ts +4 -0
- package/dist/graph-explorer/utils.js +28 -0
- package/dist/graph-explorer/visitors.d.ts +12 -0
- package/dist/graph-explorer/visitors.js +30 -0
- package/dist/graph-explorer/walk-down.d.ts +4 -0
- package/dist/graph-explorer/walk-down.js +119 -0
- package/dist/index.js +2 -98
- package/dist/plugins/angular/index.js +3 -3
- package/dist/plugins/astro/index.js +0 -2
- package/dist/plugins/next/index.js +4 -3
- package/dist/plugins/next/resolveFromAST.d.ts +1 -0
- package/dist/plugins/next/resolveFromAST.js +42 -1
- package/dist/plugins/vite/helpers.js +1 -1
- package/dist/reporters/codeclimate.js +3 -7
- package/dist/reporters/util/util.d.ts +2 -1
- package/dist/reporters/util/util.js +1 -0
- package/dist/reporters/watch.js +1 -1
- package/dist/run.d.ts +25 -0
- package/dist/run.js +107 -0
- package/dist/types/issues.d.ts +4 -4
- package/dist/types/module-graph.d.ts +14 -12
- package/dist/typescript/ast-helpers.d.ts +4 -0
- package/dist/typescript/ast-helpers.js +48 -0
- package/dist/typescript/get-imports-and-exports.js +18 -3
- package/dist/typescript/visitors/dynamic-imports/importCall.js +5 -19
- package/dist/typescript/visitors/dynamic-imports/jsDocType.js +7 -5
- package/dist/typescript/visitors/imports/importDeclaration.js +5 -4
- package/dist/util/create-options.js +1 -1
- package/dist/util/file-entry-cache.js +1 -1
- package/dist/util/graph-sequencer.js +1 -1
- package/dist/util/input.d.ts +1 -0
- package/dist/util/module-graph.js +7 -7
- package/dist/util/plugin.d.ts +1 -1
- package/dist/util/plugin.js +4 -3
- package/dist/util/trace.d.ts +3 -13
- package/dist/util/trace.js +10 -41
- package/dist/util/watch.d.ts +19 -3
- package/dist/util/watch.js +28 -17
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/vendor/bash-parser/index.d.ts +6 -1
- package/dist/util/has-strictly-ns-references.d.ts +0 -4
- package/dist/util/has-strictly-ns-references.js +0 -103
- package/dist/util/is-identifier-referenced.d.ts +0 -9
- package/dist/util/is-identifier-referenced.js +0 -145
|
@@ -4,7 +4,7 @@ export const getReactBabelPlugins = (sourceFile) => {
|
|
|
4
4
|
const babelPlugins = [];
|
|
5
5
|
const importMap = getImportMap(sourceFile);
|
|
6
6
|
const reactPluginNames = new Set();
|
|
7
|
-
for (const [importName, importPath] of importMap
|
|
7
|
+
for (const [importName, importPath] of importMap) {
|
|
8
8
|
if (importPath.includes('@vitejs/plugin-react')) {
|
|
9
9
|
reactPluginNames.add(importName);
|
|
10
10
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { ISSUE_TYPE_TITLE } from '../constants.js';
|
|
3
2
|
import { toRelative } from '../util/path.js';
|
|
4
|
-
import { getIssueTypeTitle } from './util/util.js';
|
|
3
|
+
import { getIssuePrefix, getIssueTypeTitle } from './util/util.js';
|
|
5
4
|
export default async ({ report, issues, cwd }) => {
|
|
6
5
|
const entries = [];
|
|
7
6
|
for (const [type, isReportType] of Object.entries(report)) {
|
|
@@ -52,15 +51,12 @@ function convertSeverity(severity) {
|
|
|
52
51
|
return 'info';
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
|
-
function getPrefix(type) {
|
|
56
|
-
return ISSUE_TYPE_TITLE[type].replace(/ies$/, 'y').replace(/s$/, '');
|
|
57
|
-
}
|
|
58
54
|
function getIssueDescription({ type, symbol, symbols, parentSymbol }) {
|
|
59
55
|
const symbolDescription = symbols ? `${symbols.map(s => s.symbol).join(', ')}` : symbol;
|
|
60
|
-
return `${
|
|
56
|
+
return `${getIssuePrefix(type)}: ${symbolDescription}${parentSymbol ? ` (${parentSymbol})` : ''}`;
|
|
61
57
|
}
|
|
62
58
|
function getSymbolDescription({ type, symbol, parentSymbol, }) {
|
|
63
|
-
return `${
|
|
59
|
+
return `${getIssuePrefix(type)}: ${symbol.symbol}${parentSymbol ? ` (${parentSymbol})` : ''}`;
|
|
64
60
|
}
|
|
65
61
|
function createLocation(filePath, cwd, line, col) {
|
|
66
62
|
if (col !== undefined) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ISSUE_TYPE_TITLE } from '../../constants.js';
|
|
2
|
-
import type { Issue, IssueSeverity, IssueSymbol } from '../../types/issues.js';
|
|
2
|
+
import type { Issue, IssueSeverity, IssueSymbol, IssueType } from '../../types/issues.js';
|
|
3
3
|
import { Table } from '../../util/table.js';
|
|
4
4
|
export declare const dim: import("picocolors/types.js").Formatter;
|
|
5
5
|
export declare const bright: import("picocolors/types.js").Formatter;
|
|
@@ -23,4 +23,5 @@ export declare const convert: (issue: Issue | IssueSymbol) => {
|
|
|
23
23
|
export declare const getTableForType: (issues: Issue[], cwd: string, options?: {
|
|
24
24
|
isUseColors?: boolean;
|
|
25
25
|
}) => Table;
|
|
26
|
+
export declare const getIssuePrefix: (type: IssueType) => string;
|
|
26
27
|
export {};
|
package/dist/reporters/watch.js
CHANGED
|
@@ -23,7 +23,7 @@ export default (options, { issues, streamer, duration, size }) => {
|
|
|
23
23
|
}
|
|
24
24
|
const mem = perfObserver.getCurrentMemUsageInMb();
|
|
25
25
|
const ms = duration ?? perfObserver.getCurrentDurationInMs();
|
|
26
|
-
const summary = `${size} files
|
|
26
|
+
const summary = `${size} files (${prettyMilliseconds(ms)} • ${mem}MB)`;
|
|
27
27
|
const messages = totalIssues === 0
|
|
28
28
|
? ['✂️ Excellent, Knip found no issues.', '', picocolors.gray(summary)]
|
|
29
29
|
: [...lines, '', picocolors.gray(summary)];
|
package/dist/run.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ConsoleStreamer } from './ConsoleStreamer.js';
|
|
2
|
+
import type { MainOptions } from './util/create-options.js';
|
|
3
|
+
export declare const run: (options: MainOptions) => Promise<{
|
|
4
|
+
results: {
|
|
5
|
+
issues: import("./types/issues.js").Issues;
|
|
6
|
+
counters: import("./types/issues.js").Counters;
|
|
7
|
+
tagHints: Set<import("./types/issues.js").TagHint>;
|
|
8
|
+
configurationHints: Set<import("./types/issues.js").ConfigurationHint>;
|
|
9
|
+
includedWorkspaceDirs: string[];
|
|
10
|
+
};
|
|
11
|
+
watchHandler: {
|
|
12
|
+
listener: import("fs").WatchListener<string | Buffer<ArrayBufferLike>>;
|
|
13
|
+
handleFileChanges: (changes: {
|
|
14
|
+
type: "added" | "deleted" | "modified";
|
|
15
|
+
filePath: string;
|
|
16
|
+
}[]) => Promise<{
|
|
17
|
+
duration: number;
|
|
18
|
+
mem: number;
|
|
19
|
+
}>;
|
|
20
|
+
getEntryPaths: () => Set<string>;
|
|
21
|
+
getGraph: () => import("./types/module-graph.js").ModuleGraph;
|
|
22
|
+
getIssues: () => import("./types/issues.js").Issues;
|
|
23
|
+
} | undefined;
|
|
24
|
+
streamer: ConsoleStreamer;
|
|
25
|
+
}>;
|
package/dist/run.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { watch } from 'node:fs';
|
|
2
|
+
import { formatly } from 'formatly';
|
|
3
|
+
import { CatalogCounselor } from './CatalogCounselor.js';
|
|
4
|
+
import { ConfigurationChief } from './ConfigurationChief.js';
|
|
5
|
+
import { ConsoleStreamer } from './ConsoleStreamer.js';
|
|
6
|
+
import { DependencyDeputy } from './DependencyDeputy.js';
|
|
7
|
+
import { analyze } from './graph/analyze.js';
|
|
8
|
+
import { build } from './graph/build.js';
|
|
9
|
+
import { IssueCollector } from './IssueCollector.js';
|
|
10
|
+
import { IssueFixer } from './IssueFixer.js';
|
|
11
|
+
import { PrincipalFactory } from './PrincipalFactory.js';
|
|
12
|
+
import watchReporter from './reporters/watch.js';
|
|
13
|
+
import { debugLogArray, debugLogObject } from './util/debug.js';
|
|
14
|
+
import { getGitIgnoredHandler } from './util/glob-core.js';
|
|
15
|
+
import { getWatchHandler } from './util/watch.js';
|
|
16
|
+
export const run = async (options) => {
|
|
17
|
+
debugLogObject('*', 'Unresolved configuration', options);
|
|
18
|
+
debugLogObject('*', 'Included issue types', options.includedIssueTypes);
|
|
19
|
+
const chief = new ConfigurationChief(options);
|
|
20
|
+
const deputy = new DependencyDeputy(options);
|
|
21
|
+
const factory = new PrincipalFactory();
|
|
22
|
+
const streamer = new ConsoleStreamer(options);
|
|
23
|
+
const fixer = new IssueFixer(options);
|
|
24
|
+
const collector = new IssueCollector(options);
|
|
25
|
+
const counselor = new CatalogCounselor(options);
|
|
26
|
+
streamer.cast('Reading workspace configuration');
|
|
27
|
+
const workspaces = await chief.getWorkspaces();
|
|
28
|
+
const isGitIgnored = await getGitIgnoredHandler(options);
|
|
29
|
+
collector.setIgnoreIssues(chief.config.ignoreIssues);
|
|
30
|
+
debugLogObject('*', 'Included workspaces', () => workspaces.map(w => w.pkgName));
|
|
31
|
+
debugLogObject('*', 'Included workspace configs', () => workspaces.map(w => ({ pkgName: w.pkgName, name: w.name, config: w.config, ancestors: w.ancestors })));
|
|
32
|
+
const { graph, entryPaths, analyzedFiles, unreferencedFiles, analyzeSourceFile } = await build({
|
|
33
|
+
chief,
|
|
34
|
+
collector,
|
|
35
|
+
counselor,
|
|
36
|
+
deputy,
|
|
37
|
+
factory,
|
|
38
|
+
isGitIgnored,
|
|
39
|
+
streamer,
|
|
40
|
+
workspaces,
|
|
41
|
+
options,
|
|
42
|
+
});
|
|
43
|
+
const reAnalyze = await analyze({
|
|
44
|
+
analyzedFiles,
|
|
45
|
+
counselor,
|
|
46
|
+
chief,
|
|
47
|
+
collector,
|
|
48
|
+
deputy,
|
|
49
|
+
entryPaths,
|
|
50
|
+
factory,
|
|
51
|
+
fixer,
|
|
52
|
+
graph,
|
|
53
|
+
streamer,
|
|
54
|
+
unreferencedFiles,
|
|
55
|
+
options,
|
|
56
|
+
});
|
|
57
|
+
let watchHandler;
|
|
58
|
+
if (options.isWatch) {
|
|
59
|
+
const isIgnored = (filePath) => (!!options.cacheLocation && filePath.startsWith(options.cacheLocation)) ||
|
|
60
|
+
filePath.includes('/.git/') ||
|
|
61
|
+
isGitIgnored(filePath);
|
|
62
|
+
const onFileChange = options.isWatch
|
|
63
|
+
? ({ issues, duration }) => watchReporter(options, { issues, streamer, size: analyzedFiles.size, duration })
|
|
64
|
+
: undefined;
|
|
65
|
+
watchHandler = await getWatchHandler(options, {
|
|
66
|
+
analyzedFiles,
|
|
67
|
+
analyzeSourceFile,
|
|
68
|
+
chief,
|
|
69
|
+
collector,
|
|
70
|
+
analyze: reAnalyze,
|
|
71
|
+
factory,
|
|
72
|
+
graph,
|
|
73
|
+
isIgnored,
|
|
74
|
+
onFileChange,
|
|
75
|
+
unreferencedFiles,
|
|
76
|
+
entryPaths,
|
|
77
|
+
});
|
|
78
|
+
if (options.isWatch)
|
|
79
|
+
watch('.', { recursive: true }, watchHandler.listener);
|
|
80
|
+
}
|
|
81
|
+
const { issues, counters, tagHints, configurationHints } = collector.getIssues();
|
|
82
|
+
if (options.isFix) {
|
|
83
|
+
const touchedFiles = await fixer.fixIssues(issues);
|
|
84
|
+
if (options.isFormat) {
|
|
85
|
+
const report = await formatly(Array.from(touchedFiles));
|
|
86
|
+
if (report.ran && report.result && (report.result.runner === 'virtual' || report.result.code === 0)) {
|
|
87
|
+
debugLogArray('*', `Formatted files using ${report.formatter.name} (${report.formatter.runner})`, touchedFiles);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
debugLogObject('*', 'Formatting files failed', report);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (!options.isWatch)
|
|
95
|
+
streamer.clear();
|
|
96
|
+
return {
|
|
97
|
+
results: {
|
|
98
|
+
issues,
|
|
99
|
+
counters,
|
|
100
|
+
tagHints,
|
|
101
|
+
configurationHints,
|
|
102
|
+
includedWorkspaceDirs: chief.includedWorkspaces.map(w => w.dir),
|
|
103
|
+
},
|
|
104
|
+
watchHandler,
|
|
105
|
+
streamer,
|
|
106
|
+
};
|
|
107
|
+
};
|
package/dist/types/issues.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { SYMBOL_TYPE } from '../constants.js';
|
|
2
2
|
import type { Fixes } from './exports.js';
|
|
3
3
|
export type SymbolType = (typeof SYMBOL_TYPE)[keyof typeof SYMBOL_TYPE];
|
|
4
|
-
export
|
|
4
|
+
export interface IssueSymbol {
|
|
5
5
|
symbol: string;
|
|
6
6
|
pos?: number;
|
|
7
7
|
line?: number;
|
|
8
8
|
col?: number;
|
|
9
|
-
}
|
|
10
|
-
export
|
|
9
|
+
}
|
|
10
|
+
export interface Issue {
|
|
11
11
|
type: SymbolIssueType;
|
|
12
12
|
filePath: string;
|
|
13
13
|
workspace: string;
|
|
@@ -22,7 +22,7 @@ export type Issue = {
|
|
|
22
22
|
col?: number;
|
|
23
23
|
fixes: Fixes;
|
|
24
24
|
isFixed?: boolean;
|
|
25
|
-
}
|
|
25
|
+
}
|
|
26
26
|
export type IssueSet = Set<string>;
|
|
27
27
|
export type IssueRecords = Record<string, Record<string, Issue>>;
|
|
28
28
|
export type Issues = {
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import type ts from 'typescript';
|
|
2
2
|
import type { Fix, Fixes } from './exports.js';
|
|
3
3
|
import type { IssueSymbol, SymbolType } from './issues.js';
|
|
4
|
-
type Identifier = string;
|
|
4
|
+
export type Identifier = string;
|
|
5
5
|
type FilePath = string;
|
|
6
6
|
type NamespaceOrAlias = string;
|
|
7
7
|
type Reference = string;
|
|
8
8
|
type References = Set<Reference>;
|
|
9
9
|
type Tags = Set<string>;
|
|
10
|
+
interface SourceLocation {
|
|
11
|
+
pos: number;
|
|
12
|
+
line: number;
|
|
13
|
+
col: number;
|
|
14
|
+
}
|
|
10
15
|
export type IdToFileMap = Map<Identifier, Set<FilePath>>;
|
|
11
16
|
export type IdToNsToFileMap = Map<Identifier, Map<NamespaceOrAlias, Set<FilePath>>>;
|
|
12
17
|
export type ImportMaps = {
|
|
@@ -19,24 +24,21 @@ export type ImportMaps = {
|
|
|
19
24
|
reExportedNs: IdToFileMap;
|
|
20
25
|
};
|
|
21
26
|
export type ImportMap = Map<FilePath, ImportMaps>;
|
|
22
|
-
export
|
|
27
|
+
export interface Import extends SourceLocation {
|
|
23
28
|
specifier: string;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
export interface Export {
|
|
29
|
+
filePath: string | undefined;
|
|
30
|
+
identifier: string | undefined;
|
|
31
|
+
isTypeOnly: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface Export extends SourceLocation {
|
|
30
34
|
identifier: Identifier;
|
|
31
|
-
pos: number;
|
|
32
|
-
line: number;
|
|
33
|
-
col: number;
|
|
34
35
|
type: SymbolType;
|
|
35
36
|
members: ExportMember[];
|
|
36
37
|
jsDocTags: Tags;
|
|
37
38
|
refs: [number, boolean];
|
|
38
39
|
fixes: Fixes;
|
|
39
40
|
symbol?: ts.Symbol;
|
|
41
|
+
isReExport?: boolean;
|
|
40
42
|
}
|
|
41
43
|
export type ExportMember = {
|
|
42
44
|
identifier: Identifier;
|
|
@@ -50,7 +52,7 @@ export type ExportMember = {
|
|
|
50
52
|
jsDocTags: Tags;
|
|
51
53
|
};
|
|
52
54
|
export type ExportMap = Map<Identifier, Export>;
|
|
53
|
-
export type Imports = Set<
|
|
55
|
+
export type Imports = Set<Import>;
|
|
54
56
|
export type FileNode = {
|
|
55
57
|
imports: {
|
|
56
58
|
internal: ImportMap;
|
|
@@ -58,6 +58,10 @@ export declare const isModuleExportsAccess: (node: ts.PropertyAccessExpression)
|
|
|
58
58
|
export declare const getImportMap: (sourceFile: ts.SourceFile) => Map<string, string>;
|
|
59
59
|
export declare const getDefaultImportName: (importMap: ReturnType<typeof getImportMap>, specifier: string) => string | undefined;
|
|
60
60
|
export declare const getPropertyValues: (node: ts.ObjectLiteralExpression, propertyName: string) => Set<string>;
|
|
61
|
+
export declare function getThenBindings(callExpression: ts.CallExpression): {
|
|
62
|
+
identifier: string;
|
|
63
|
+
pos: number;
|
|
64
|
+
}[] | undefined;
|
|
61
65
|
export declare const getAccessedIdentifiers: (identifier: string, scope: ts.Node) => {
|
|
62
66
|
identifier: string;
|
|
63
67
|
pos: number;
|
|
@@ -203,6 +203,7 @@ export const isConsiderReferencedNS = (node) => ts.isPropertyAssignment(node.par
|
|
|
203
203
|
ts.isSpreadAssignment(node.parent) ||
|
|
204
204
|
ts.isArrayLiteralExpression(node.parent) ||
|
|
205
205
|
ts.isExportAssignment(node.parent) ||
|
|
206
|
+
ts.isConditionalExpression(node.parent) ||
|
|
206
207
|
(ts.isVariableDeclaration(node.parent) && node.parent.initializer === node) ||
|
|
207
208
|
ts.isTypeQueryNode(node.parent.parent);
|
|
208
209
|
export const isInOpaqueExpression = (node) => ts.isAwaitExpression(node.parent)
|
|
@@ -263,6 +264,18 @@ export const getImportMap = (sourceFile) => {
|
|
|
263
264
|
importMap.set(element.name.text, importPath);
|
|
264
265
|
}
|
|
265
266
|
}
|
|
267
|
+
if (ts.isVariableStatement(statement)) {
|
|
268
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
269
|
+
if (declaration.initializer &&
|
|
270
|
+
isRequireCall(declaration.initializer) &&
|
|
271
|
+
ts.isIdentifier(declaration.name) &&
|
|
272
|
+
ts.isStringLiteral(declaration.initializer.arguments[0])) {
|
|
273
|
+
const importName = declaration.name.text;
|
|
274
|
+
const importPath = stripQuotes(declaration.initializer.arguments[0].text);
|
|
275
|
+
importMap.set(importName, importPath);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
266
279
|
}
|
|
267
280
|
return importMap;
|
|
268
281
|
};
|
|
@@ -304,6 +317,32 @@ const isMatchAlias = (expression, identifier) => {
|
|
|
304
317
|
expression = expression.expression;
|
|
305
318
|
return expression && ts.isIdentifier(expression) && expression.escapedText === identifier;
|
|
306
319
|
};
|
|
320
|
+
export function getThenBindings(callExpression) {
|
|
321
|
+
if (!ts.isFunctionLike(callExpression.arguments[0]))
|
|
322
|
+
return;
|
|
323
|
+
const fn = callExpression.arguments[0];
|
|
324
|
+
const param = fn.parameters[0];
|
|
325
|
+
if (!param)
|
|
326
|
+
return;
|
|
327
|
+
if (ts.isIdentifier(param.name)) {
|
|
328
|
+
const paramName = param.name.escapedText;
|
|
329
|
+
const identifiers = [];
|
|
330
|
+
for (const node of findDescendants(fn.body, ts.isPropertyAccessExpression)) {
|
|
331
|
+
if (ts.isIdentifier(node.expression) && node.expression.escapedText === paramName) {
|
|
332
|
+
identifiers.push({ identifier: String(node.name.escapedText), pos: node.name.pos });
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (identifiers.length > 0)
|
|
336
|
+
return identifiers;
|
|
337
|
+
}
|
|
338
|
+
else if (ts.isObjectBindingPattern(param.name)) {
|
|
339
|
+
return param.name.elements.map(element => {
|
|
340
|
+
const identifier = (element.propertyName ?? element.name).getText();
|
|
341
|
+
const alias = element.propertyName ? element.name.getText() : undefined;
|
|
342
|
+
return { identifier, alias, pos: element.pos };
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
307
346
|
export const getAccessedIdentifiers = (identifier, scope) => {
|
|
308
347
|
const identifiers = [];
|
|
309
348
|
function visit(node) {
|
|
@@ -328,6 +367,15 @@ export const getAccessedIdentifiers = (identifier, scope) => {
|
|
|
328
367
|
}
|
|
329
368
|
}
|
|
330
369
|
}
|
|
370
|
+
else if (ts.isCallExpression(node) &&
|
|
371
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
372
|
+
isMatchAlias(node.expression.expression, identifier) &&
|
|
373
|
+
node.expression.name.escapedText === 'then') {
|
|
374
|
+
const accessed = getThenBindings(node);
|
|
375
|
+
if (accessed)
|
|
376
|
+
for (const acc of accessed)
|
|
377
|
+
identifiers.push(acc);
|
|
378
|
+
}
|
|
331
379
|
ts.forEachChild(node, visit);
|
|
332
380
|
}
|
|
333
381
|
visit(scope);
|
|
@@ -79,7 +79,15 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
|
|
|
79
79
|
const { symbol, filePath, namespace, specifier, modifiers } = options;
|
|
80
80
|
const identifier = options.identifier ?? (modifiers & IMPORT_MODIFIERS.OPAQUE ? OPAQUE : SIDE_EFFECTS);
|
|
81
81
|
const isStar = identifier === IMPORT_STAR;
|
|
82
|
-
imports.add(
|
|
82
|
+
imports.add({
|
|
83
|
+
filePath,
|
|
84
|
+
specifier,
|
|
85
|
+
identifier: namespace ?? options.identifier,
|
|
86
|
+
pos: options.pos,
|
|
87
|
+
line: options.line,
|
|
88
|
+
col: options.col,
|
|
89
|
+
isTypeOnly: !!(modifiers & IMPORT_MODIFIERS.TYPE_ONLY),
|
|
90
|
+
});
|
|
83
91
|
const file = internal.get(filePath);
|
|
84
92
|
const importMaps = file ?? createImports();
|
|
85
93
|
if (!file)
|
|
@@ -105,7 +113,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
|
|
|
105
113
|
addNsValue(importMaps.importedAs, identifier, nsOrAlias, sourceFile.fileName);
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
|
-
else if (identifier !==
|
|
116
|
+
else if (identifier !== IMPORT_STAR) {
|
|
109
117
|
addValue(importMaps.imported, identifier, sourceFile.fileName);
|
|
110
118
|
}
|
|
111
119
|
if (symbol)
|
|
@@ -144,11 +152,13 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
|
|
|
144
152
|
const pos = node.moduleSpecifier?.getStart() ?? opts.pos;
|
|
145
153
|
const { line, character } = sourceFile.getLineAndCharacterOfPosition(pos);
|
|
146
154
|
external.add({
|
|
155
|
+
filePath,
|
|
147
156
|
specifier: sanitizedSpecifier,
|
|
148
157
|
identifier: opts.identifier ?? SIDE_EFFECTS,
|
|
149
158
|
pos: opts.pos,
|
|
150
159
|
line: line + 1,
|
|
151
160
|
col: character + 2,
|
|
161
|
+
isTypeOnly: !!(opts.modifiers & IMPORT_MODIFIERS.TYPE_ONLY),
|
|
152
162
|
});
|
|
153
163
|
}
|
|
154
164
|
}
|
|
@@ -167,20 +177,24 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
|
|
|
167
177
|
const pos = 'moduleSpecifier' in node ? node.moduleSpecifier.pos : node.pos;
|
|
168
178
|
const { line, character } = sourceFile.getLineAndCharacterOfPosition(pos);
|
|
169
179
|
unresolved.add({
|
|
180
|
+
filePath: undefined,
|
|
170
181
|
specifier: opts.specifier,
|
|
171
182
|
identifier: opts.identifier ?? SIDE_EFFECTS,
|
|
172
183
|
pos,
|
|
173
184
|
line: line + 1,
|
|
174
185
|
col: character + 2,
|
|
186
|
+
isTypeOnly: !!(opts.modifiers & IMPORT_MODIFIERS.TYPE_ONLY),
|
|
175
187
|
});
|
|
176
188
|
}
|
|
177
189
|
};
|
|
178
190
|
const addExport = ({ node, symbol, identifier, type, pos, members = [], fix }) => {
|
|
179
191
|
if (skipExports)
|
|
180
192
|
return;
|
|
193
|
+
let isReExport = Boolean(node.parent?.parent && ts.isExportDeclaration(node.parent.parent) && node.parent.parent.moduleSpecifier);
|
|
181
194
|
if (symbol) {
|
|
182
195
|
const importedSymbolFilePath = importedInternalSymbols.get(symbol);
|
|
183
196
|
if (importedSymbolFilePath) {
|
|
197
|
+
isReExport = true;
|
|
184
198
|
const importId = String(symbol.escapedName);
|
|
185
199
|
const internalImport = internal.get(importedSymbolFilePath);
|
|
186
200
|
if (internalImport) {
|
|
@@ -203,7 +217,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
|
|
|
203
217
|
const members = [...(item.members ?? []), ...exportMembers];
|
|
204
218
|
const tags = new Set([...(item.jsDocTags ?? []), ...jsDocTags]);
|
|
205
219
|
const fixes = fix ? [...(item.fixes ?? []), fix] : item.fixes;
|
|
206
|
-
exports.set(identifier, { ...item, members, jsDocTags: tags, fixes });
|
|
220
|
+
exports.set(identifier, { ...item, members, jsDocTags: tags, fixes, isReExport });
|
|
207
221
|
}
|
|
208
222
|
else {
|
|
209
223
|
const { line, character } = node.getSourceFile().getLineAndCharacterOfPosition(pos);
|
|
@@ -218,6 +232,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
|
|
|
218
232
|
col: character + 1,
|
|
219
233
|
fixes: fix ? [fix] : [],
|
|
220
234
|
refs: [0, false],
|
|
235
|
+
isReExport,
|
|
221
236
|
});
|
|
222
237
|
}
|
|
223
238
|
if (!jsDocTags.has(ALIAS_TAG)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { IMPORT_MODIFIERS } from '../../../constants.js';
|
|
3
|
-
import { findAncestor, findDescendants, getAccessedIdentifiers, isAccessExpression, isImportCall, isInOpaqueExpression, isTopLevel, stripQuotes, } from '../../ast-helpers.js';
|
|
3
|
+
import { findAncestor, findDescendants, getAccessedIdentifiers, getThenBindings, isAccessExpression, isImportCall, isInOpaqueExpression, isTopLevel, stripQuotes, } from '../../ast-helpers.js';
|
|
4
4
|
import { importVisitor as visit } from '../index.js';
|
|
5
5
|
const getSymbol = (node, isTopLevel) => (isTopLevel ? node.symbol : undefined);
|
|
6
6
|
export default visit(() => true, node => {
|
|
@@ -20,24 +20,10 @@ export default visit(() => true, node => {
|
|
|
20
20
|
const pos = accessExpression.name.pos;
|
|
21
21
|
if (identifier === 'then') {
|
|
22
22
|
const callExpression = node.parent.parent;
|
|
23
|
-
if (ts.isCallExpression(callExpression)
|
|
24
|
-
const
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
const accessExpressions = findDescendants(callExpression.arguments[0].body, ts.isPropertyAccessExpression).filter(binding => binding.expression.getText() === argName);
|
|
28
|
-
if (accessExpressions.length > 0) {
|
|
29
|
-
return accessExpressions.map(binding => {
|
|
30
|
-
const identifier = String(binding.name.escapedText);
|
|
31
|
-
return { identifier, specifier, pos, modifiers };
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
else if (arg && ts.isObjectBindingPattern(arg.name)) {
|
|
36
|
-
return arg.name.elements.map(element => {
|
|
37
|
-
const identifier = (element.propertyName ?? element.name).getText();
|
|
38
|
-
const alias = element.propertyName ? element.name.getText() : undefined;
|
|
39
|
-
return { identifier, alias, specifier, pos: element.pos, modifiers };
|
|
40
|
-
});
|
|
23
|
+
if (ts.isCallExpression(callExpression)) {
|
|
24
|
+
const accessed = getThenBindings(callExpression);
|
|
25
|
+
if (accessed && accessed.length > 0) {
|
|
26
|
+
return accessed.map(acc => ({ ...acc, specifier, modifiers }));
|
|
41
27
|
}
|
|
42
28
|
}
|
|
43
29
|
return { identifier: 'default', specifier, pos, modifiers };
|
|
@@ -13,16 +13,18 @@ const getImportSpecifiers = (node) => {
|
|
|
13
13
|
specifier: importClause.literal.text,
|
|
14
14
|
identifier,
|
|
15
15
|
pos: node.qualifier?.getStart() ?? importClause.literal.pos,
|
|
16
|
-
modifiers: IMPORT_MODIFIERS.
|
|
16
|
+
modifiers: IMPORT_MODIFIERS.TYPE_ONLY,
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
if (supportsJSDocImportTag && ts.isJSDocImportTag(node) && ts.isStringLiteralLike(node.moduleSpecifier)) {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const moduleSpecifier = node.moduleSpecifier;
|
|
22
|
+
const importClause = node.importClause;
|
|
23
|
+
if (moduleSpecifier && importClause?.namedBindings && ts.isNamedImportBindings(importClause.namedBindings)) {
|
|
24
|
+
const bindings = importClause.namedBindings;
|
|
23
25
|
if (ts.isNamespaceImport(bindings)) {
|
|
24
26
|
imports.push({
|
|
25
|
-
specifier:
|
|
27
|
+
specifier: moduleSpecifier.text,
|
|
26
28
|
identifier: IMPORT_STAR,
|
|
27
29
|
pos: bindings.name.getStart(),
|
|
28
30
|
modifiers: IMPORT_MODIFIERS.TYPE_ONLY,
|
|
@@ -31,7 +33,7 @@ const getImportSpecifiers = (node) => {
|
|
|
31
33
|
else {
|
|
32
34
|
for (const element of bindings.elements) {
|
|
33
35
|
imports.push({
|
|
34
|
-
specifier:
|
|
36
|
+
specifier: moduleSpecifier.text,
|
|
35
37
|
identifier: String((element.propertyName ?? element.name).escapedText),
|
|
36
38
|
pos: element.name.getStart(),
|
|
37
39
|
modifiers: IMPORT_MODIFIERS.TYPE_ONLY,
|
|
@@ -9,6 +9,7 @@ export default visit(() => true, node => {
|
|
|
9
9
|
return { specifier, identifier: undefined, pos: node.pos, modifiers: IMPORT_MODIFIERS.SIDE_EFFECTS };
|
|
10
10
|
}
|
|
11
11
|
const imports = [];
|
|
12
|
+
const modifiers = node.importClause.isTypeOnly ? IMPORT_MODIFIERS.TYPE_ONLY : IMPORT_MODIFIERS.NONE;
|
|
12
13
|
if (isDefaultImport(node)) {
|
|
13
14
|
imports.push({
|
|
14
15
|
identifier: 'default',
|
|
@@ -16,7 +17,7 @@ export default visit(() => true, node => {
|
|
|
16
17
|
specifier,
|
|
17
18
|
symbol: node.importClause.symbol,
|
|
18
19
|
pos: node.importClause.name?.getStart() ?? node.getStart(),
|
|
19
|
-
modifiers
|
|
20
|
+
modifiers,
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
23
|
if (node.importClause?.namedBindings) {
|
|
@@ -27,7 +28,7 @@ export default visit(() => true, node => {
|
|
|
27
28
|
specifier,
|
|
28
29
|
identifier: IMPORT_STAR,
|
|
29
30
|
pos: node.importClause.namedBindings.name.getStart(),
|
|
30
|
-
modifiers
|
|
31
|
+
modifiers,
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
34
|
if (ts.isNamedImports(node.importClause.namedBindings)) {
|
|
@@ -38,7 +39,7 @@ export default visit(() => true, node => {
|
|
|
38
39
|
specifier,
|
|
39
40
|
symbol: element.symbol,
|
|
40
41
|
pos: element.name.getStart(),
|
|
41
|
-
modifiers
|
|
42
|
+
modifiers,
|
|
42
43
|
});
|
|
43
44
|
}
|
|
44
45
|
}
|
|
@@ -47,7 +48,7 @@ export default visit(() => true, node => {
|
|
|
47
48
|
specifier,
|
|
48
49
|
identifier: undefined,
|
|
49
50
|
pos: node.importClause.namedBindings.pos,
|
|
50
|
-
modifiers
|
|
51
|
+
modifiers,
|
|
51
52
|
});
|
|
52
53
|
}
|
|
53
54
|
}
|
|
@@ -115,7 +115,7 @@ export const createOptions = async (options) => {
|
|
|
115
115
|
rules,
|
|
116
116
|
tags,
|
|
117
117
|
traceExport: parsedCLIArgs['trace-export'],
|
|
118
|
-
traceFile: parsedCLIArgs['trace-file'],
|
|
118
|
+
traceFile: parsedCLIArgs['trace-file'] ? toAbsolute(parsedCLIArgs['trace-file'], cwd) : undefined,
|
|
119
119
|
tsConfigFile: parsedCLIArgs.tsConfig,
|
|
120
120
|
workspace: options.workspace ?? parsedCLIArgs.workspace,
|
|
121
121
|
workspaces,
|
|
@@ -86,7 +86,7 @@ export class FileEntryCache {
|
|
|
86
86
|
}
|
|
87
87
|
reconcile() {
|
|
88
88
|
this.removeNotFoundFiles();
|
|
89
|
-
for (const [entryName, cacheEntry] of this.normalizedEntries
|
|
89
|
+
for (const [entryName, cacheEntry] of this.normalizedEntries) {
|
|
90
90
|
try {
|
|
91
91
|
const meta = this._getMetaForFileUsingMtimeAndSize(cacheEntry);
|
|
92
92
|
this.cache.set(entryName, meta);
|
|
@@ -6,7 +6,7 @@ export function graphSequencer(graph, includedNodes = [...graph.keys()]) {
|
|
|
6
6
|
const nodes = new Set(includedNodes);
|
|
7
7
|
const visited = new Set();
|
|
8
8
|
const outDegree = new Map();
|
|
9
|
-
for (const [from, edges] of graph
|
|
9
|
+
for (const [from, edges] of graph) {
|
|
10
10
|
outDegree.set(from, 0);
|
|
11
11
|
for (const to of edges) {
|
|
12
12
|
if (nodes.has(from) && nodes.has(to)) {
|
package/dist/util/input.d.ts
CHANGED
|
@@ -2,21 +2,21 @@ export const getOrCreateFileNode = (graph, filePath) => graph.get(filePath) ?? c
|
|
|
2
2
|
const updateImportMaps = (fromImportMaps, toImportMaps) => {
|
|
3
3
|
for (const id of fromImportMaps.refs)
|
|
4
4
|
toImportMaps.refs.add(id);
|
|
5
|
-
for (const [id, v] of fromImportMaps.imported
|
|
5
|
+
for (const [id, v] of fromImportMaps.imported)
|
|
6
6
|
addValues(toImportMaps.imported, id, v);
|
|
7
|
-
for (const [id, v] of fromImportMaps.importedAs
|
|
7
|
+
for (const [id, v] of fromImportMaps.importedAs)
|
|
8
8
|
addNsValues(toImportMaps.importedAs, id, v);
|
|
9
|
-
for (const [id, v] of fromImportMaps.importedNs
|
|
9
|
+
for (const [id, v] of fromImportMaps.importedNs)
|
|
10
10
|
addValues(toImportMaps.importedNs, id, v);
|
|
11
|
-
for (const [id, v] of fromImportMaps.reExported
|
|
11
|
+
for (const [id, v] of fromImportMaps.reExported)
|
|
12
12
|
addValues(toImportMaps.reExported, id, v);
|
|
13
|
-
for (const [id, v] of fromImportMaps.reExportedAs
|
|
13
|
+
for (const [id, v] of fromImportMaps.reExportedAs)
|
|
14
14
|
addNsValues(toImportMaps.reExportedAs, id, v);
|
|
15
|
-
for (const [id, v] of fromImportMaps.reExportedNs
|
|
15
|
+
for (const [id, v] of fromImportMaps.reExportedNs)
|
|
16
16
|
addValues(toImportMaps.reExportedNs, id, v);
|
|
17
17
|
};
|
|
18
18
|
export const updateImportMap = (file, importMap, graph) => {
|
|
19
|
-
for (const [importedFilePath, fileImportMaps] of importMap
|
|
19
|
+
for (const [importedFilePath, fileImportMaps] of importMap) {
|
|
20
20
|
const importMaps = file.imports.internal.get(importedFilePath);
|
|
21
21
|
if (!importMaps)
|
|
22
22
|
file.imports.internal.set(importedFilePath, fileImportMaps);
|
package/dist/util/plugin.d.ts
CHANGED
|
@@ -4,6 +4,6 @@ export declare const hasDependency: (dependencies: Set<string>, values: (string
|
|
|
4
4
|
export declare const normalizePluginConfig: (pluginConfig: RawPluginConfiguration) => boolean | {
|
|
5
5
|
config: string[] | null;
|
|
6
6
|
entry: string[] | null;
|
|
7
|
-
project: string[]
|
|
7
|
+
project: string[];
|
|
8
8
|
};
|
|
9
9
|
export declare const loadConfigForPlugin: (configFilePath: string, plugin: Plugin, options: PluginOptions, pluginName: string) => Promise<any>;
|