knip 5.70.2 → 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 +1 -1
- 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-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/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 +9 -10
- 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 +4 -1
- package/dist/typescript/visitors/dynamic-imports/importCall.js +5 -19
- 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/module-graph.js +7 -7
- 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
package/dist/DependencyDeputy.js
CHANGED
|
@@ -174,7 +174,7 @@ export class DependencyDeputy {
|
|
|
174
174
|
const dependencyIssues = [];
|
|
175
175
|
const devDependencyIssues = [];
|
|
176
176
|
const optionalPeerDependencyIssues = [];
|
|
177
|
-
for (const [workspace, { manifestPath: filePath, manifestStr }] of this._manifests
|
|
177
|
+
for (const [workspace, { manifestPath: filePath, manifestStr }] of this._manifests) {
|
|
178
178
|
const referencedDependencies = this.referencedDependencies.get(workspace);
|
|
179
179
|
const hasTypesIncluded = this.getHasTypesIncluded(workspace);
|
|
180
180
|
const peeker = new PackagePeeker(manifestStr);
|
|
@@ -342,7 +342,7 @@ export class DependencyDeputy {
|
|
|
342
342
|
}
|
|
343
343
|
getConfigurationHints() {
|
|
344
344
|
const configurationHints = new Set();
|
|
345
|
-
for (const [workspaceName, manifest] of this._manifests
|
|
345
|
+
for (const [workspaceName, manifest] of this._manifests) {
|
|
346
346
|
for (const identifier of manifest.unusedIgnoreDependencies) {
|
|
347
347
|
configurationHints.add({ workspaceName, identifier, type: 'ignoreDependencies' });
|
|
348
348
|
}
|
package/dist/ProjectPrincipal.js
CHANGED
|
@@ -217,7 +217,7 @@ export class ProjectPrincipal {
|
|
|
217
217
|
return externalRefs.length > 0;
|
|
218
218
|
}
|
|
219
219
|
reconcileCache(graph) {
|
|
220
|
-
for (const [filePath, file] of graph
|
|
220
|
+
for (const [filePath, file] of graph) {
|
|
221
221
|
const fd = this.cache.getFileDescriptor(filePath);
|
|
222
222
|
if (!fd?.meta)
|
|
223
223
|
continue;
|
package/dist/WorkspaceWorker.js
CHANGED
|
@@ -319,7 +319,7 @@ export class WorkspaceWorker {
|
|
|
319
319
|
const configFiles = this.configFilesMap.get(wsName);
|
|
320
320
|
if (configFiles) {
|
|
321
321
|
do {
|
|
322
|
-
for (const [pluginName, dependencies] of configFiles
|
|
322
|
+
for (const [pluginName, dependencies] of configFiles) {
|
|
323
323
|
configFiles.delete(pluginName);
|
|
324
324
|
if (this.enabledPlugins.includes(pluginName)) {
|
|
325
325
|
for (const input of await runPlugin(pluginName, Array.from(dependencies)))
|
|
@@ -25,6 +25,12 @@ export const getDependenciesFromScript = (script, options) => {
|
|
|
25
25
|
knownBinsOnly: false,
|
|
26
26
|
});
|
|
27
27
|
};
|
|
28
|
+
const definedFunctions = new Set();
|
|
29
|
+
const collectFunctionNames = (nodes) => {
|
|
30
|
+
for (const node of nodes)
|
|
31
|
+
if (node.type === 'Function')
|
|
32
|
+
definedFunctions.add(node.name.text);
|
|
33
|
+
};
|
|
28
34
|
const getDependenciesFromNodes = (nodes) => nodes.flatMap(node => {
|
|
29
35
|
switch (node.type) {
|
|
30
36
|
case 'Command': {
|
|
@@ -41,6 +47,8 @@ export const getDependenciesFromScript = (script, options) => {
|
|
|
41
47
|
return [];
|
|
42
48
|
if (binary.startsWith('-') || binary.startsWith('"') || binary.startsWith('..'))
|
|
43
49
|
return [];
|
|
50
|
+
if (definedFunctions.has(binary))
|
|
51
|
+
return [];
|
|
44
52
|
const args = node.suffix?.map(arg => arg.text) ?? [];
|
|
45
53
|
if (['!', 'test'].includes(binary))
|
|
46
54
|
return fromArgs(args);
|
|
@@ -82,13 +90,18 @@ export const getDependenciesFromScript = (script, options) => {
|
|
|
82
90
|
return getDependenciesFromNodes(node.commands);
|
|
83
91
|
case 'Function':
|
|
84
92
|
return getDependenciesFromNodes(node.body.commands);
|
|
93
|
+
case 'Subshell':
|
|
94
|
+
return getDependenciesFromNodes(node.list.commands);
|
|
85
95
|
default:
|
|
86
96
|
return [];
|
|
87
97
|
}
|
|
88
98
|
});
|
|
89
99
|
try {
|
|
90
100
|
const parsed = parse(script);
|
|
91
|
-
|
|
101
|
+
if (!parsed?.commands)
|
|
102
|
+
return [];
|
|
103
|
+
collectFunctionNames(parsed.commands);
|
|
104
|
+
return getDependenciesFromNodes(parsed.commands);
|
|
92
105
|
}
|
|
93
106
|
catch (error) {
|
|
94
107
|
const msg = `Warning: failed to parse and ignoring script in ${relative(options.cwd, options.containingFilePath)} (${truncate(script, 30)})`;
|
package/dist/compilers/index.js
CHANGED
|
@@ -38,7 +38,7 @@ const compilers = new Map([
|
|
|
38
38
|
]);
|
|
39
39
|
export const getIncludedCompilers = (syncCompilers, asyncCompilers, dependencies) => {
|
|
40
40
|
const hasDependency = (packageName) => dependencies.has(packageName);
|
|
41
|
-
for (const [extension, { condition, compiler }] of compilers
|
|
41
|
+
for (const [extension, { condition, compiler }] of compilers) {
|
|
42
42
|
if (extension === '.mdx' && AstroMDX.condition(hasDependency)) {
|
|
43
43
|
syncCompilers.set(extension, AstroMDX.compiler);
|
|
44
44
|
}
|
package/dist/constants.js
CHANGED
package/dist/graph/analyze.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createGraphExplorer } from '../graph-explorer/explorer.js';
|
|
2
|
+
import { getIssueType, hasStrictlyEnumReferences } from '../graph-explorer/utils.js';
|
|
3
3
|
import { getPackageNameFromModuleSpecifier } from '../util/modules.js';
|
|
4
4
|
import { findMatch } from '../util/regex.js';
|
|
5
5
|
import { getShouldIgnoreHandler, getShouldIgnoreTagHandler } from '../util/tag.js';
|
|
6
|
-
import {
|
|
6
|
+
import { printTraceNode } from '../util/trace.js';
|
|
7
7
|
export const analyze = async ({ analyzedFiles, counselor, chief, collector, deputy, entryPaths, factory, graph, streamer, unreferencedFiles, options, }) => {
|
|
8
8
|
const shouldIgnore = getShouldIgnoreHandler(options.isProduction);
|
|
9
9
|
const shouldIgnoreTags = getShouldIgnoreTagHandler(options.tags);
|
|
10
|
-
const
|
|
10
|
+
const explorer = createGraphExplorer(graph, entryPaths);
|
|
11
11
|
const ignoreExportsUsedInFile = chief.config.ignoreExportsUsedInFile;
|
|
12
12
|
const isExportedItemReferenced = (exportedItem) => exportedItem.refs[1] ||
|
|
13
13
|
(exportedItem.refs[0] > 0 &&
|
|
@@ -17,7 +17,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
17
17
|
const analyzeGraph = async () => {
|
|
18
18
|
if (options.isReportValues || options.isReportTypes) {
|
|
19
19
|
streamer.cast('Connecting the dots');
|
|
20
|
-
for (const [filePath, file] of graph
|
|
20
|
+
for (const [filePath, file] of graph) {
|
|
21
21
|
const exportItems = file.exports;
|
|
22
22
|
if (!exportItems || exportItems.size === 0)
|
|
23
23
|
continue;
|
|
@@ -27,16 +27,17 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
27
27
|
const principal = factory.getPrincipalByPackageName(workspace.pkgName);
|
|
28
28
|
const isEntry = entryPaths.has(filePath);
|
|
29
29
|
if (!isIncludeEntryExports && isEntry) {
|
|
30
|
-
createAndPrintTrace(filePath, options, { isEntry });
|
|
31
30
|
continue;
|
|
32
31
|
}
|
|
33
32
|
const importsForExport = file.imported;
|
|
34
|
-
for (const [identifier, exportedItem] of exportItems
|
|
33
|
+
for (const [identifier, exportedItem] of exportItems) {
|
|
35
34
|
if (shouldIgnore(exportedItem.jsDocTags))
|
|
36
35
|
continue;
|
|
37
36
|
const isIgnored = shouldIgnoreTags(exportedItem.jsDocTags);
|
|
38
37
|
if (importsForExport) {
|
|
39
|
-
const
|
|
38
|
+
const [isReferenced, reExportingEntryFile] = explorer.isReferenced(filePath, identifier, {
|
|
39
|
+
includeEntryExports: isIncludeEntryExports,
|
|
40
|
+
});
|
|
40
41
|
if ((isReferenced || exportedItem.refs[1]) && isIgnored) {
|
|
41
42
|
for (const tagName of exportedItem.jsDocTags) {
|
|
42
43
|
if (options.tags[1].includes(tagName.replace(/^@/, ''))) {
|
|
@@ -48,15 +49,12 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
48
49
|
continue;
|
|
49
50
|
if (reExportingEntryFile) {
|
|
50
51
|
if (!isIncludeEntryExports) {
|
|
51
|
-
createAndPrintTrace(filePath, options, { identifier, isEntry, hasRef: isReferenced });
|
|
52
52
|
continue;
|
|
53
53
|
}
|
|
54
54
|
const reExportedItem = graph.get(reExportingEntryFile)?.exports.get(identifier);
|
|
55
55
|
if (reExportedItem && shouldIgnore(reExportedItem.jsDocTags))
|
|
56
56
|
continue;
|
|
57
57
|
}
|
|
58
|
-
if (traceNode)
|
|
59
|
-
printTrace(traceNode, filePath, options, identifier);
|
|
60
58
|
if (isReferenced) {
|
|
61
59
|
if (options.includedIssueTypes.enumMembers && exportedItem.type === 'enum') {
|
|
62
60
|
if (!options.includedIssueTypes.nsTypes && importsForExport.refs.has(identifier))
|
|
@@ -70,9 +68,11 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
70
68
|
continue;
|
|
71
69
|
if (member.refs[0] === 0) {
|
|
72
70
|
const id = `${identifier}.${member.identifier}`;
|
|
73
|
-
const
|
|
71
|
+
const [isMemberReferenced] = explorer.isReferenced(filePath, id, {
|
|
72
|
+
includeEntryExports: true,
|
|
73
|
+
});
|
|
74
74
|
const isIgnored = shouldIgnoreTags(member.jsDocTags);
|
|
75
|
-
if (!
|
|
75
|
+
if (!isMemberReferenced) {
|
|
76
76
|
if (isIgnored)
|
|
77
77
|
continue;
|
|
78
78
|
collector.addIssue({
|
|
@@ -125,7 +125,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
125
125
|
continue;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
const [hasStrictlyNsRefs, namespace] = hasStrictlyNsReferences(
|
|
128
|
+
const [hasStrictlyNsRefs, namespace] = explorer.hasStrictlyNsReferences(filePath, identifier);
|
|
129
129
|
const isType = ['enum', 'type', 'interface'].includes(exportedItem.type);
|
|
130
130
|
if (hasStrictlyNsRefs &&
|
|
131
131
|
((!options.includedIssueTypes.nsTypes && isType) || !(options.includedIssueTypes.nsExports || isType)))
|
|
@@ -135,7 +135,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
135
135
|
continue;
|
|
136
136
|
if (!options.isSkipLibs && principal?.hasExternalReferences(filePath, exportedItem))
|
|
137
137
|
continue;
|
|
138
|
-
const type =
|
|
138
|
+
const type = getIssueType(hasStrictlyNsRefs, isType);
|
|
139
139
|
collector.addIssue({
|
|
140
140
|
type,
|
|
141
141
|
filePath,
|
|
@@ -153,7 +153,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
|
-
for (const [filePath, file] of graph
|
|
156
|
+
for (const [filePath, file] of graph) {
|
|
157
157
|
const ws = chief.findWorkspaceByFilePath(filePath);
|
|
158
158
|
if (ws) {
|
|
159
159
|
if (file.duplicates && options.includedIssueTypes.duplicates) {
|
|
@@ -227,5 +227,10 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
227
227
|
collector.addConfigurationHint(hint);
|
|
228
228
|
};
|
|
229
229
|
await analyzeGraph();
|
|
230
|
+
if (options.isTrace) {
|
|
231
|
+
const nodes = explorer.buildExportsTree({ filePath: options.traceFile, identifier: options.traceExport });
|
|
232
|
+
for (const node of nodes)
|
|
233
|
+
printTraceNode(node, options);
|
|
234
|
+
}
|
|
230
235
|
return analyzeGraph;
|
|
231
236
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ModuleGraph } from '../types/module-graph.js';
|
|
2
|
+
export declare const createGraphExplorer: (graph: ModuleGraph, entryPaths: Set<string>) => {
|
|
3
|
+
isReferenced: (filePath: string, identifier: string, options: {
|
|
4
|
+
includeEntryExports: boolean;
|
|
5
|
+
}) => [boolean, string | undefined];
|
|
6
|
+
hasStrictlyNsReferences: (filePath: string, identifier: string) => [boolean, (string | undefined)?];
|
|
7
|
+
buildExportsTree: (options: {
|
|
8
|
+
filePath?: string;
|
|
9
|
+
identifier?: string;
|
|
10
|
+
}) => import("./operations/build-trace-tree.js").TreeNode[];
|
|
11
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { buildExportsTree } from './operations/build-trace-tree.js';
|
|
2
|
+
import { hasStrictlyNsReferences } from './operations/has-strictly-ns-references.js';
|
|
3
|
+
import { isReferenced } from './operations/is-referenced.js';
|
|
4
|
+
export const createGraphExplorer = (graph, entryPaths) => {
|
|
5
|
+
return {
|
|
6
|
+
isReferenced: (filePath, identifier, options) => isReferenced(graph, entryPaths, filePath, identifier, options),
|
|
7
|
+
hasStrictlyNsReferences: (filePath, identifier) => hasStrictlyNsReferences(graph, graph.get(filePath)?.imported, identifier),
|
|
8
|
+
buildExportsTree: (options) => buildExportsTree(graph, entryPaths, options),
|
|
9
|
+
};
|
|
10
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Identifier, ModuleGraph } from '../../types/module-graph.js';
|
|
2
|
+
export interface TreeNode {
|
|
3
|
+
filePath: string;
|
|
4
|
+
identifier: string;
|
|
5
|
+
hasRef: boolean;
|
|
6
|
+
isEntry: boolean;
|
|
7
|
+
children: TreeNode[];
|
|
8
|
+
}
|
|
9
|
+
export declare const buildExportsTree: (graph: ModuleGraph, entryPaths: Set<string>, options: {
|
|
10
|
+
filePath?: string;
|
|
11
|
+
identifier?: Identifier;
|
|
12
|
+
}) => TreeNode[];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { CONTINUE } from '../constants.js';
|
|
2
|
+
import { walkDown } from '../walk-down.js';
|
|
3
|
+
export const buildExportsTree = (graph, entryPaths, options) => {
|
|
4
|
+
const traces = [];
|
|
5
|
+
const processFile = (filePath, file) => {
|
|
6
|
+
for (const exportId of options.identifier ? [options.identifier] : file.exports.keys()) {
|
|
7
|
+
if (!options.identifier || file.exports.has(exportId)) {
|
|
8
|
+
const trace = buildExportTree(graph, entryPaths, filePath, exportId);
|
|
9
|
+
if (trace)
|
|
10
|
+
traces.push(trace);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
if (options.filePath) {
|
|
15
|
+
const file = graph.get(options.filePath);
|
|
16
|
+
if (file)
|
|
17
|
+
processFile(options.filePath, file);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
for (const [filePath, file] of graph)
|
|
21
|
+
processFile(filePath, file);
|
|
22
|
+
}
|
|
23
|
+
return traces;
|
|
24
|
+
};
|
|
25
|
+
const buildExportTree = (graph, entryPaths, filePath, identifier) => {
|
|
26
|
+
const rootNode = {
|
|
27
|
+
filePath,
|
|
28
|
+
identifier,
|
|
29
|
+
hasRef: false,
|
|
30
|
+
isEntry: entryPaths.has(filePath),
|
|
31
|
+
children: [],
|
|
32
|
+
};
|
|
33
|
+
const nodeMap = new Map();
|
|
34
|
+
nodeMap.set(`${filePath}:${identifier}`, rootNode);
|
|
35
|
+
walkDown(graph, filePath, identifier, (sourceFile, sourceId, importingFile, id, isEntry, isReExport) => {
|
|
36
|
+
const key = `${importingFile}:${id}`;
|
|
37
|
+
const childNode = nodeMap.get(key) ?? {
|
|
38
|
+
filePath: importingFile,
|
|
39
|
+
identifier: id,
|
|
40
|
+
hasRef: !isReExport && Boolean(graph.get(importingFile)?.traceRefs?.has(id)),
|
|
41
|
+
isEntry,
|
|
42
|
+
children: [],
|
|
43
|
+
};
|
|
44
|
+
nodeMap.set(key, childNode);
|
|
45
|
+
const parentKey = `${sourceFile}:${sourceId}`;
|
|
46
|
+
const parentNode = nodeMap.get(parentKey) ?? rootNode;
|
|
47
|
+
parentNode.children.push(childNode);
|
|
48
|
+
return CONTINUE;
|
|
49
|
+
}, entryPaths);
|
|
50
|
+
return rootNode;
|
|
51
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { forEachAliasReExport, forEachNamespaceReExport, forEachPassThroughReExport, getStarReExportSources, } from '../visitors.js';
|
|
2
|
+
export const hasStrictlyNsReferences = (graph, importsForExport, identifier) => {
|
|
3
|
+
if (!importsForExport)
|
|
4
|
+
return [false];
|
|
5
|
+
let foundNamespace;
|
|
6
|
+
const aliasByIdentifier = new Map();
|
|
7
|
+
const namespaceReExports = new Map();
|
|
8
|
+
const namespaceEdges = [];
|
|
9
|
+
const directById = new Map();
|
|
10
|
+
forEachPassThroughReExport(importsForExport, (id, sources) => {
|
|
11
|
+
directById.set(id, sources);
|
|
12
|
+
});
|
|
13
|
+
forEachAliasReExport(importsForExport, (id, alias, sources) => {
|
|
14
|
+
let arr = aliasByIdentifier.get(id);
|
|
15
|
+
if (!arr) {
|
|
16
|
+
arr = [];
|
|
17
|
+
aliasByIdentifier.set(id, arr);
|
|
18
|
+
}
|
|
19
|
+
arr.push({ alias, sources });
|
|
20
|
+
});
|
|
21
|
+
forEachNamespaceReExport(importsForExport, (namespace, sources) => {
|
|
22
|
+
namespaceEdges.push({ namespace, sources });
|
|
23
|
+
let arr = namespaceReExports.get(namespace);
|
|
24
|
+
if (!arr) {
|
|
25
|
+
arr = [];
|
|
26
|
+
namespaceReExports.set(namespace, arr);
|
|
27
|
+
}
|
|
28
|
+
arr.push(sources);
|
|
29
|
+
});
|
|
30
|
+
const starSources = getStarReExportSources(importsForExport);
|
|
31
|
+
const followReExports = (sources, nextId, propagateNamespace = true) => {
|
|
32
|
+
for (const filePath of sources) {
|
|
33
|
+
const file = graph.get(filePath);
|
|
34
|
+
if (!file?.imported)
|
|
35
|
+
continue;
|
|
36
|
+
const result = hasStrictlyNsReferences(graph, file.imported, nextId);
|
|
37
|
+
if (result[0] === false)
|
|
38
|
+
return result;
|
|
39
|
+
if (propagateNamespace && result[1])
|
|
40
|
+
foundNamespace = result[1];
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
};
|
|
44
|
+
for (const ns of importsForExport.importedNs.keys()) {
|
|
45
|
+
const hasNsRef = importsForExport.refs.has(ns);
|
|
46
|
+
if (!hasNsRef)
|
|
47
|
+
return [false, ns];
|
|
48
|
+
for (const ref of importsForExport.refs) {
|
|
49
|
+
if (ref.startsWith(`${ns}.`))
|
|
50
|
+
return [false, ns];
|
|
51
|
+
}
|
|
52
|
+
const nsReExports = namespaceReExports.get(ns);
|
|
53
|
+
if (nsReExports) {
|
|
54
|
+
for (const sources of nsReExports) {
|
|
55
|
+
const result = followReExports(sources, identifier, false);
|
|
56
|
+
if (result)
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const nsAliases = aliasByIdentifier.get(ns);
|
|
61
|
+
if (nsAliases) {
|
|
62
|
+
for (const { sources } of nsAliases) {
|
|
63
|
+
const result = followReExports(sources, identifier, false);
|
|
64
|
+
if (result)
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
foundNamespace = ns;
|
|
69
|
+
}
|
|
70
|
+
const directSources = directById.get(identifier);
|
|
71
|
+
if (directSources) {
|
|
72
|
+
const result = followReExports(directSources, identifier, true);
|
|
73
|
+
if (result)
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
if (starSources) {
|
|
77
|
+
const result = followReExports(starSources, identifier, true);
|
|
78
|
+
if (result)
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
const [id, ...rest] = identifier.split('.');
|
|
82
|
+
const aliasEntries = aliasByIdentifier.get(id);
|
|
83
|
+
if (aliasEntries) {
|
|
84
|
+
for (const { alias, sources } of aliasEntries) {
|
|
85
|
+
const result = followReExports(sources, [alias, ...rest].join('.'), true);
|
|
86
|
+
if (result)
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const { namespace: ns, sources } of namespaceEdges) {
|
|
91
|
+
const result = followReExports(sources, `${ns}.${identifier}`, true);
|
|
92
|
+
if (result)
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
if (foundNamespace)
|
|
96
|
+
return [true, foundNamespace];
|
|
97
|
+
return [false];
|
|
98
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Identifier, ModuleGraph } from '../../types/module-graph.js';
|
|
2
|
+
export declare const isReferenced: (graph: ModuleGraph, entryPaths: Set<string>, filePath: string, id: Identifier, options: {
|
|
3
|
+
includeEntryExports: boolean;
|
|
4
|
+
}) => [boolean, string | undefined];
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { OPAQUE } from '../../constants.js';
|
|
2
|
+
import { getAliasReExportMap, getNamespaceReExportSources, getPassThroughReExportSources, getStarReExportSources, } from '../visitors.js';
|
|
3
|
+
export const isReferenced = (graph, entryPaths, filePath, id, options) => {
|
|
4
|
+
const seen = new Set();
|
|
5
|
+
const check = (currentPath, currentId) => {
|
|
6
|
+
const isEntryFile = entryPaths.has(currentPath);
|
|
7
|
+
let reExportingEntryFile = isEntryFile ? currentPath : undefined;
|
|
8
|
+
if (isEntryFile && !options.includeEntryExports)
|
|
9
|
+
return [false, reExportingEntryFile];
|
|
10
|
+
if (seen.has(currentPath))
|
|
11
|
+
return [false, reExportingEntryFile];
|
|
12
|
+
seen.add(currentPath);
|
|
13
|
+
const restIds = currentId.split('.');
|
|
14
|
+
const identifier = restIds.shift();
|
|
15
|
+
const file = graph.get(currentPath)?.imported;
|
|
16
|
+
if (!identifier || !file) {
|
|
17
|
+
return [false, reExportingEntryFile];
|
|
18
|
+
}
|
|
19
|
+
const directSources = getPassThroughReExportSources(file, identifier);
|
|
20
|
+
const starSources = getStarReExportSources(file);
|
|
21
|
+
const followSources = (sources, nextId) => {
|
|
22
|
+
for (const byFilePath of sources) {
|
|
23
|
+
if (seen.has(byFilePath))
|
|
24
|
+
continue;
|
|
25
|
+
const result = check(byFilePath, nextId);
|
|
26
|
+
if (result[1])
|
|
27
|
+
reExportingEntryFile = result[1];
|
|
28
|
+
if (result[0])
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
33
|
+
if (file.imported.get(OPAQUE) ||
|
|
34
|
+
((identifier === currentId || (identifier !== currentId && file.refs.has(currentId))) &&
|
|
35
|
+
(file.imported.has(identifier) || file.importedAs.has(identifier)))) {
|
|
36
|
+
return [true, reExportingEntryFile];
|
|
37
|
+
}
|
|
38
|
+
for (const [exportId, aliases] of file.importedAs) {
|
|
39
|
+
if (identifier === exportId) {
|
|
40
|
+
for (const alias of aliases.keys()) {
|
|
41
|
+
const aliasedRef = [alias, ...restIds].join('.');
|
|
42
|
+
if (file.refs.has(aliasedRef)) {
|
|
43
|
+
return [true, reExportingEntryFile];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for (const namespace of file.importedNs.keys()) {
|
|
49
|
+
if (file.refs.has(`${namespace}.${currentId}`)) {
|
|
50
|
+
return [true, reExportingEntryFile];
|
|
51
|
+
}
|
|
52
|
+
const nsAliasMap = getAliasReExportMap(file, namespace);
|
|
53
|
+
if (nsAliasMap) {
|
|
54
|
+
for (const [alias, sources] of nsAliasMap) {
|
|
55
|
+
if (followSources(sources, `${alias}.${currentId}`))
|
|
56
|
+
return [true, reExportingEntryFile];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const nsReExportSources = getNamespaceReExportSources(file, namespace);
|
|
60
|
+
if (nsReExportSources) {
|
|
61
|
+
if (followSources(nsReExportSources, `${namespace}.${currentId}`))
|
|
62
|
+
return [true, reExportingEntryFile];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const aliasMap = getAliasReExportMap(file, identifier);
|
|
66
|
+
if (aliasMap) {
|
|
67
|
+
for (const [alias, sources] of aliasMap) {
|
|
68
|
+
const ref = [alias, ...restIds].join('.');
|
|
69
|
+
if (followSources(sources, ref))
|
|
70
|
+
return [true, reExportingEntryFile];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (directSources) {
|
|
74
|
+
if (followSources(directSources, currentId))
|
|
75
|
+
return [true, reExportingEntryFile];
|
|
76
|
+
}
|
|
77
|
+
else if (starSources) {
|
|
78
|
+
if (followSources(starSources, currentId))
|
|
79
|
+
return [true, reExportingEntryFile];
|
|
80
|
+
}
|
|
81
|
+
for (const [namespace, sources] of file.reExportedNs) {
|
|
82
|
+
if (followSources(sources, `${namespace}.${currentId}`)) {
|
|
83
|
+
return [true, reExportingEntryFile];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return [false, reExportingEntryFile];
|
|
87
|
+
};
|
|
88
|
+
return check(filePath, id);
|
|
89
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ImportMaps, ModuleGraph } from '../types/module-graph.js';
|
|
2
|
+
export declare const hasNamespaceMemberReference: (graph: ModuleGraph, importingFile: string, importedFile: string, namespace: string, member: string) => boolean | null;
|
|
3
|
+
export declare const hasStrictlyEnumReferences: (importsForExport: ImportMaps | undefined, identifier: string) => boolean;
|
|
4
|
+
export declare const getIssueType: (hasOnlyNsReference: boolean, isType: boolean) => "exports" | "nsExports" | "types" | "nsTypes";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { OPAQUE } from '../constants.js';
|
|
2
|
+
export const hasNamespaceMemberReference = (graph, importingFile, importedFile, namespace, member) => {
|
|
3
|
+
const importerNode = graph.get(importingFile);
|
|
4
|
+
if (!importerNode)
|
|
5
|
+
return null;
|
|
6
|
+
const importMap = importerNode.imports.internal.get(importedFile);
|
|
7
|
+
if (!importMap)
|
|
8
|
+
return null;
|
|
9
|
+
if (importMap.imported.get(OPAQUE))
|
|
10
|
+
return true;
|
|
11
|
+
if (importMap.refs.size === 0)
|
|
12
|
+
return false;
|
|
13
|
+
const refKey = member ? `${namespace}.${member}` : namespace;
|
|
14
|
+
return refKey ? importMap.refs.has(refKey) : null;
|
|
15
|
+
};
|
|
16
|
+
export const hasStrictlyEnumReferences = (importsForExport, identifier) => {
|
|
17
|
+
if (!importsForExport || !importsForExport.refs.has(identifier))
|
|
18
|
+
return false;
|
|
19
|
+
for (const ref of importsForExport.refs)
|
|
20
|
+
if (ref.startsWith(`${identifier}.`))
|
|
21
|
+
return false;
|
|
22
|
+
return true;
|
|
23
|
+
};
|
|
24
|
+
export const getIssueType = (hasOnlyNsReference, isType) => {
|
|
25
|
+
if (hasOnlyNsReference)
|
|
26
|
+
return isType ? 'nsTypes' : 'nsExports';
|
|
27
|
+
return isType ? 'types' : 'exports';
|
|
28
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ImportMaps } from '../types/module-graph.js';
|
|
2
|
+
type PassThroughReExportCallback = (identifier: string, sources: Set<string>) => boolean | void;
|
|
3
|
+
type AliasReExportCallback = (identifier: string, alias: string, sources: Set<string>) => boolean | void;
|
|
4
|
+
type NamespaceReExportCallback = (namespace: string, sources: Set<string>) => boolean | void;
|
|
5
|
+
export declare const forEachPassThroughReExport: (importMaps: ImportMaps, callback: PassThroughReExportCallback) => boolean;
|
|
6
|
+
export declare const forEachAliasReExport: (importMaps: ImportMaps, callback: AliasReExportCallback) => boolean;
|
|
7
|
+
export declare const forEachNamespaceReExport: (importMaps: ImportMaps, callback: NamespaceReExportCallback) => boolean;
|
|
8
|
+
export declare const getStarReExportSources: (importMaps: ImportMaps) => Set<string> | undefined;
|
|
9
|
+
export declare const getPassThroughReExportSources: (importMaps: ImportMaps, identifier: string) => Set<string> | undefined;
|
|
10
|
+
export declare const getAliasReExportMap: (importMaps: ImportMaps, identifier: string) => Map<string, Set<string>> | undefined;
|
|
11
|
+
export declare const getNamespaceReExportSources: (importMaps: ImportMaps, namespace: string) => Set<string> | undefined;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { IMPORT_STAR } from '../constants.js';
|
|
2
|
+
export const forEachPassThroughReExport = (importMaps, callback) => {
|
|
3
|
+
for (const [identifier, sources] of importMaps.reExported) {
|
|
4
|
+
if (identifier === IMPORT_STAR)
|
|
5
|
+
continue;
|
|
6
|
+
if (callback(identifier, sources ?? new Set()) === false)
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
return true;
|
|
10
|
+
};
|
|
11
|
+
export const forEachAliasReExport = (importMaps, callback) => {
|
|
12
|
+
for (const [identifier, aliasMap] of importMaps.reExportedAs) {
|
|
13
|
+
for (const [alias, sources] of aliasMap) {
|
|
14
|
+
if (callback(identifier, alias, sources ?? new Set()) === false)
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
};
|
|
20
|
+
export const forEachNamespaceReExport = (importMaps, callback) => {
|
|
21
|
+
for (const [namespace, sources] of importMaps.reExportedNs) {
|
|
22
|
+
if (callback(namespace, sources ?? new Set()) === false)
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
};
|
|
27
|
+
export const getStarReExportSources = (importMaps) => importMaps.reExported.get(IMPORT_STAR);
|
|
28
|
+
export const getPassThroughReExportSources = (importMaps, identifier) => importMaps.reExported.get(identifier);
|
|
29
|
+
export const getAliasReExportMap = (importMaps, identifier) => importMaps.reExportedAs.get(identifier);
|
|
30
|
+
export const getNamespaceReExportSources = (importMaps, namespace) => importMaps.reExportedNs.get(namespace);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ModuleGraph } from '../types/module-graph.js';
|
|
2
|
+
type Visitor = (sourceFile: string, identifier: string, importingFile: string, identifierPath: string, isEntry: boolean, isReExport: boolean) => 'continue' | 'stop' | undefined;
|
|
3
|
+
export declare const walkDown: (graph: ModuleGraph, filePath: string, identifier: string, visitor: Visitor, entryPaths: Set<string>, visited?: Set<string>) => boolean;
|
|
4
|
+
export {};
|