knip 6.14.1 → 6.15.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/README.md +1 -1
- package/dist/CacheConsultant.d.ts +1 -0
- package/dist/CacheConsultant.js +2 -0
- package/dist/ConfigurationChief.d.ts +12 -0
- package/dist/ConfigurationChief.js +7 -10
- package/dist/DependencyDeputy.d.ts +0 -4
- package/dist/DependencyDeputy.js +6 -18
- package/dist/IssueCollector.d.ts +1 -0
- package/dist/IssueCollector.js +10 -20
- package/dist/IssueFixer.js +10 -15
- package/dist/ProjectPrincipal.d.ts +0 -2
- package/dist/ProjectPrincipal.js +1 -9
- package/dist/WorkspaceWorker.js +6 -1
- package/dist/binaries/resolvers/bun.js +9 -8
- package/dist/cli.js +3 -1
- package/dist/compilers/compilers.d.ts +3 -0
- package/dist/compilers/compilers.js +9 -13
- package/dist/compilers/index.d.ts +21 -0
- package/dist/compilers/scss.js +9 -3
- package/dist/graph/analyze.js +7 -1
- package/dist/graph/build.js +0 -2
- package/dist/manifest/index.js +11 -14
- package/dist/plugins/astro/index.js +1 -0
- package/dist/plugins/graphql-codegen/index.js +4 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/nano-spawn/index.d.ts +3 -0
- package/dist/plugins/nano-spawn/index.js +15 -0
- package/dist/plugins/nano-spawn/visitors/nano-spawn.d.ts +2 -0
- package/dist/plugins/nano-spawn/visitors/nano-spawn.js +25 -0
- package/dist/plugins/orval/index.d.ts +3 -0
- package/dist/plugins/orval/index.js +16 -0
- package/dist/plugins/orval/resolveFromAST.d.ts +2 -0
- package/dist/plugins/orval/resolveFromAST.js +11 -0
- package/dist/plugins/orval/types.d.ts +9 -0
- package/dist/plugins/orval/types.js +1 -0
- package/dist/plugins/serverless-framework/index.js +11 -6
- package/dist/plugins/serverless-framework/types.d.ts +7 -0
- package/dist/plugins/typescript/index.js +1 -1
- package/dist/plugins/vite/helpers.d.ts +1 -1
- package/dist/plugins/vite/helpers.js +43 -36
- package/dist/plugins/vite/index.js +2 -6
- package/dist/plugins/webdriver-io/index.js +3 -3
- package/dist/plugins/webdriver-io/types.d.ts +5 -1
- package/dist/reporters/github-actions.d.ts +1 -1
- package/dist/reporters/github-actions.js +19 -1
- package/dist/reporters/index.d.ts +1 -1
- package/dist/reporters/symbols.js +2 -1
- package/dist/reporters/trace.d.ts +3 -1
- package/dist/reporters/trace.js +48 -16
- package/dist/reporters/util/configuration-hints.d.ts +1 -1
- package/dist/reporters/util/configuration-hints.js +3 -2
- package/dist/schema/configuration.d.ts +32 -1
- package/dist/schema/configuration.js +1 -0
- package/dist/schema/plugins.d.ts +10 -0
- package/dist/schema/plugins.js +2 -0
- package/dist/types/PluginNames.d.ts +2 -2
- package/dist/types/PluginNames.js +2 -0
- package/dist/types/issues.d.ts +1 -0
- package/dist/types/project.d.ts +0 -1
- package/dist/typescript/resolve-module-names.d.ts +0 -1
- package/dist/typescript/resolve-module-names.js +0 -17
- package/dist/typescript/visitors/walk.js +7 -0
- package/dist/util/Performance.d.ts +13 -28
- package/dist/util/Performance.js +41 -72
- package/dist/util/cli-arguments.d.ts +3 -1
- package/dist/util/cli-arguments.js +4 -0
- package/dist/util/create-input-handler.js +3 -1
- package/dist/util/create-options.d.ts +22 -0
- package/dist/util/create-options.js +2 -1
- package/dist/util/disk-cache.d.ts +1 -0
- package/dist/util/disk-cache.js +8 -0
- package/dist/util/gitignore-cache.js +5 -11
- package/dist/util/glob-cache.js +2 -8
- package/dist/util/glob-core.js +4 -7
- package/dist/util/jiti.js +1 -0
- package/dist/util/load-tsconfig.js +0 -3
- package/dist/util/trace.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -4
- package/schema.json +12 -0
- package/dist/util/math.d.ts +0 -6
- package/dist/util/math.js +0 -11
package/dist/plugins/index.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ export declare const Plugins: {
|
|
|
59
59
|
mocha: import("../types/config.ts").Plugin;
|
|
60
60
|
moonrepo: import("../types/config.ts").Plugin;
|
|
61
61
|
msw: import("../types/config.ts").Plugin;
|
|
62
|
+
'nano-spawn': import("../types/config.ts").Plugin;
|
|
62
63
|
'nano-staged': import("../types/config.ts").Plugin;
|
|
63
64
|
nest: import("../types/config.ts").Plugin;
|
|
64
65
|
netlify: import("../types/config.ts").Plugin;
|
|
@@ -75,6 +76,7 @@ export declare const Plugins: {
|
|
|
75
76
|
nyc: import("../types/config.ts").Plugin;
|
|
76
77
|
oclif: import("../types/config.ts").Plugin;
|
|
77
78
|
'openapi-ts': import("../types/config.ts").Plugin;
|
|
79
|
+
orval: import("../types/config.ts").Plugin;
|
|
78
80
|
oxfmt: import("../types/config.ts").Plugin;
|
|
79
81
|
oxlint: import("../types/config.ts").Plugin;
|
|
80
82
|
'panda-css': import("../types/config.ts").Plugin;
|
package/dist/plugins/index.js
CHANGED
|
@@ -53,6 +53,7 @@ import { default as metro } from './metro/index.js';
|
|
|
53
53
|
import { default as mocha } from './mocha/index.js';
|
|
54
54
|
import { default as moonrepo } from './moonrepo/index.js';
|
|
55
55
|
import { default as msw } from './msw/index.js';
|
|
56
|
+
import { default as nanoSpawn } from './nano-spawn/index.js';
|
|
56
57
|
import { default as nanoStaged } from './nano-staged/index.js';
|
|
57
58
|
import { default as nest } from './nest/index.js';
|
|
58
59
|
import { default as netlify } from './netlify/index.js';
|
|
@@ -69,6 +70,7 @@ import { default as nx } from './nx/index.js';
|
|
|
69
70
|
import { default as nyc } from './nyc/index.js';
|
|
70
71
|
import { default as oclif } from './oclif/index.js';
|
|
71
72
|
import { default as openapiTs } from './openapi-ts/index.js';
|
|
73
|
+
import { default as orval } from './orval/index.js';
|
|
72
74
|
import { default as oxfmt } from './oxfmt/index.js';
|
|
73
75
|
import { default as oxlint } from './oxlint/index.js';
|
|
74
76
|
import { default as pandaCss } from './panda-css/index.js';
|
|
@@ -204,6 +206,7 @@ export const Plugins = {
|
|
|
204
206
|
mocha,
|
|
205
207
|
moonrepo,
|
|
206
208
|
msw,
|
|
209
|
+
'nano-spawn': nanoSpawn,
|
|
207
210
|
'nano-staged': nanoStaged,
|
|
208
211
|
nest,
|
|
209
212
|
netlify,
|
|
@@ -220,6 +223,7 @@ export const Plugins = {
|
|
|
220
223
|
nyc,
|
|
221
224
|
oclif,
|
|
222
225
|
'openapi-ts': openapiTs,
|
|
226
|
+
orval,
|
|
223
227
|
oxfmt,
|
|
224
228
|
oxlint,
|
|
225
229
|
'panda-css': pandaCss,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { hasDependency } from '../../util/plugin.js';
|
|
2
|
+
import { createNanoSpawnVisitor } from './visitors/nano-spawn.js';
|
|
3
|
+
const title = 'nano-spawn';
|
|
4
|
+
const enablers = ['nano-spawn'];
|
|
5
|
+
const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
|
|
6
|
+
const registerVisitors = ({ ctx, registerVisitor }) => {
|
|
7
|
+
registerVisitor(createNanoSpawnVisitor(ctx));
|
|
8
|
+
};
|
|
9
|
+
const plugin = {
|
|
10
|
+
title,
|
|
11
|
+
enablers,
|
|
12
|
+
isEnabled,
|
|
13
|
+
registerVisitors,
|
|
14
|
+
};
|
|
15
|
+
export default plugin;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getStringValue, isStringLiteral } from '../../../typescript/ast-nodes.js';
|
|
2
|
+
export function createNanoSpawnVisitor(ctx) {
|
|
3
|
+
return {
|
|
4
|
+
CallExpression(node) {
|
|
5
|
+
if (node.callee.type !== 'Identifier' || node.callee.name !== 'spawn')
|
|
6
|
+
return;
|
|
7
|
+
const executable = node.arguments[0];
|
|
8
|
+
if (!executable || !isStringLiteral(executable))
|
|
9
|
+
return;
|
|
10
|
+
const executableStr = getStringValue(executable);
|
|
11
|
+
const args = node.arguments[1];
|
|
12
|
+
if (args?.type === 'ArrayExpression') {
|
|
13
|
+
const argStrings = [];
|
|
14
|
+
for (const a of args.elements) {
|
|
15
|
+
if (a && isStringLiteral(a))
|
|
16
|
+
argStrings.push(getStringValue(a));
|
|
17
|
+
}
|
|
18
|
+
ctx.addScript([executableStr, ...argStrings].join(' '));
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
ctx.addScript(executableStr);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { toEntry } from '../../util/input.js';
|
|
2
|
+
import { hasDependency } from '../../util/plugin.js';
|
|
3
|
+
import { getInputsFromAST } from './resolveFromAST.js';
|
|
4
|
+
const title = 'orval';
|
|
5
|
+
const enablers = ['orval'];
|
|
6
|
+
const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
|
|
7
|
+
const config = ['orval.config.{js,mjs,ts,mts}'];
|
|
8
|
+
const resolveFromAST = program => [...getInputsFromAST(program)].map(id => toEntry(id));
|
|
9
|
+
const plugin = {
|
|
10
|
+
title,
|
|
11
|
+
enablers,
|
|
12
|
+
isEnabled,
|
|
13
|
+
config,
|
|
14
|
+
resolveFromAST,
|
|
15
|
+
};
|
|
16
|
+
export default plugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { collectPropertyValues } from '../../typescript/ast-helpers.js';
|
|
2
|
+
const PATH_KEY = 'path';
|
|
3
|
+
const TRANSFORMER_KEY = 'transformer';
|
|
4
|
+
export const getInputsFromAST = (program) => {
|
|
5
|
+
const values = new Set();
|
|
6
|
+
for (const v of collectPropertyValues(program, PATH_KEY))
|
|
7
|
+
values.add(v);
|
|
8
|
+
for (const v of collectPropertyValues(program, TRANSFORMER_KEY))
|
|
9
|
+
values.add(v);
|
|
10
|
+
return values;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
import { toProductionEntry } from '../../util/input.js';
|
|
1
|
+
import { toDependency, toProductionEntry } from '../../util/input.js';
|
|
2
|
+
import { isInternal, join } from '../../util/path.js';
|
|
2
3
|
import { hasDependency } from '../../util/plugin.js';
|
|
3
4
|
const title = 'Serverless Framework';
|
|
4
5
|
const enablers = ['serverless'];
|
|
5
6
|
const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
|
|
6
|
-
const config = ['serverless.{yml,yaml}'];
|
|
7
|
+
const config = ['serverless.{js,cjs,mjs,ts,cts,mts,yml,yaml}'];
|
|
7
8
|
const handlerToEntry = (handler) => {
|
|
8
9
|
const dot = handler.lastIndexOf('.');
|
|
9
10
|
return toProductionEntry(`${handler.slice(0, dot)}.{js,ts}`);
|
|
10
11
|
};
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
const pluginToInput = (plugin, dir) => isInternal(plugin) ? toProductionEntry(join(dir, plugin)) : toDependency(plugin);
|
|
13
|
+
const resolveConfig = async (config, options) => {
|
|
14
|
+
const functions = config.functions
|
|
15
|
+
? Object.values(config.functions).flatMap(fn => (fn.handler ? [handlerToEntry(fn.handler)] : []))
|
|
16
|
+
: [];
|
|
17
|
+
const plugins = config.plugins?.filter((plugin) => typeof plugin === 'string') ?? [];
|
|
18
|
+
const esbuild = config.custom?.esbuild || config.build?.esbuild ? [toDependency('esbuild', { optional: true })] : [];
|
|
19
|
+
return [...functions, ...plugins.map(plugin => pluginToInput(plugin, options.configFileDir)), ...esbuild];
|
|
15
20
|
};
|
|
16
21
|
const plugin = {
|
|
17
22
|
title,
|
|
@@ -32,7 +32,7 @@ const resolveConfig = async (localConfig, options) => {
|
|
|
32
32
|
return compact([
|
|
33
33
|
...extend,
|
|
34
34
|
...references,
|
|
35
|
-
...types.map(id => toDeferResolve(id, { isTypeOnly: true })),
|
|
35
|
+
...types.map(id => toDeferResolve(id, { isTypeOnly: true, dir: options.cwd })),
|
|
36
36
|
...[...plugins, ...importHelpers].map(id => toDeferResolve(id)),
|
|
37
37
|
...jsx,
|
|
38
38
|
...aliases,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Program } from 'oxc-parser';
|
|
2
2
|
import { type Input } from '../../util/input.ts';
|
|
3
|
-
export declare const
|
|
3
|
+
export declare const getBabelInputs: (program: Program) => Input[];
|
|
4
4
|
export declare const getIndexHtmlEntries: (rootDir: string) => Promise<Input[]>;
|
|
@@ -1,56 +1,63 @@
|
|
|
1
1
|
import { Visitor } from 'oxc-parser';
|
|
2
|
-
import {
|
|
2
|
+
import { blockCommentMatcher, lineCommentMatcher, scriptExtractor } from '../../compilers/compilers.js';
|
|
3
|
+
import { findProperty, getImportMap, getStringValues } from '../../typescript/ast-helpers.js';
|
|
3
4
|
import { isFile, loadFile } from '../../util/fs.js';
|
|
4
5
|
import { toProductionEntry } from '../../util/input.js';
|
|
5
6
|
import { join } from '../../util/path.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if (reactPluginNames.size === 0) {
|
|
15
|
-
const defaultImportName = getDefaultImportName(importMap, '@vitejs/plugin-react');
|
|
16
|
-
if (defaultImportName)
|
|
17
|
-
reactPluginNames.add(defaultImportName);
|
|
18
|
-
else
|
|
19
|
-
reactPluginNames.add('react');
|
|
7
|
+
import { getDependenciesFromConfig } from '../babel/index.js';
|
|
8
|
+
const babelPluginSources = ['@rolldown/plugin-babel', '@vitejs/plugin-react', 'vite-plugin-babel'];
|
|
9
|
+
const isBabelWrappingPlugin = (path) => babelPluginSources.some(source => path === source || path.startsWith(`${source}/`));
|
|
10
|
+
export const getBabelInputs = (program) => {
|
|
11
|
+
const pluginNames = new Set();
|
|
12
|
+
for (const [name, path] of getImportMap(program)) {
|
|
13
|
+
if (isBabelWrappingPlugin(path))
|
|
14
|
+
pluginNames.add(name);
|
|
20
15
|
}
|
|
16
|
+
if (pluginNames.size === 0)
|
|
17
|
+
return [];
|
|
18
|
+
const inputs = [];
|
|
21
19
|
const visitor = new Visitor({
|
|
22
20
|
CallExpression(node) {
|
|
23
|
-
if (node.callee?.type !== 'Identifier' || node.callee.name
|
|
24
|
-
return;
|
|
25
|
-
const config = resolveObjectArg(node.arguments?.[0]);
|
|
26
|
-
const plugins = findProperty(config, 'plugins');
|
|
27
|
-
if (plugins?.type !== 'ArrayExpression')
|
|
21
|
+
if (node.callee?.type !== 'Identifier' || !pluginNames.has(node.callee.name))
|
|
28
22
|
return;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
for (const key of ['plugins', 'presets']) {
|
|
36
|
-
for (const v of getStringValues(findProperty(babel, key)))
|
|
37
|
-
inputs.push(v);
|
|
38
|
-
}
|
|
23
|
+
const options = node.arguments?.[0];
|
|
24
|
+
const plugins = [];
|
|
25
|
+
const presets = [];
|
|
26
|
+
for (const config of [options, findProperty(options, 'babel'), findProperty(options, 'babelConfig')]) {
|
|
27
|
+
plugins.push(...getStringValues(findProperty(config, 'plugins')));
|
|
28
|
+
presets.push(...getStringValues(findProperty(config, 'presets')));
|
|
39
29
|
}
|
|
30
|
+
inputs.push(...getDependenciesFromConfig({ plugins, presets }));
|
|
40
31
|
},
|
|
41
32
|
});
|
|
42
33
|
visitor.visit(program);
|
|
43
34
|
return inputs;
|
|
44
35
|
};
|
|
45
|
-
const
|
|
36
|
+
const moduleTypePattern = /\btype\s*=\s*["']?module["']?/i;
|
|
37
|
+
const srcAttrPattern = /\bsrc\s*=\s*["']([^"']+)["']/i;
|
|
38
|
+
const importSpecPattern = /\bimport\b(?:\s*\(\s*|(?:[\w$*,{}\s]*\bfrom\b)?\s*)(['"])([^'"]+)\1/g;
|
|
39
|
+
const isFilePath = (specifier) => specifier.startsWith('/') || specifier.startsWith('./') || specifier.startsWith('../');
|
|
46
40
|
const normalizeModuleScriptSrc = (value) => value.trim().replace(/^\//, '');
|
|
47
41
|
const getModuleScriptSources = (html) => {
|
|
48
|
-
const matches = html.matchAll(moduleScriptPattern);
|
|
49
42
|
const sources = [];
|
|
50
|
-
for (const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
43
|
+
for (const [, attrs, body] of html.matchAll(scriptExtractor)) {
|
|
44
|
+
if (!moduleTypePattern.test(attrs))
|
|
45
|
+
continue;
|
|
46
|
+
const srcMatch = attrs.match(srcAttrPattern);
|
|
47
|
+
if (srcMatch) {
|
|
48
|
+
const src = normalizeModuleScriptSrc(srcMatch[1]);
|
|
49
|
+
if (src)
|
|
50
|
+
sources.push(src);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (body) {
|
|
54
|
+
const code = body.replace(blockCommentMatcher, '').replace(lineCommentMatcher, '');
|
|
55
|
+
for (const importMatch of code.matchAll(importSpecPattern)) {
|
|
56
|
+
const specifier = importMatch[2];
|
|
57
|
+
if (isFilePath(specifier))
|
|
58
|
+
sources.push(normalizeModuleScriptSrc(specifier));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
54
61
|
}
|
|
55
62
|
return sources;
|
|
56
63
|
};
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import { toDependency } from '../../util/input.js';
|
|
2
1
|
import { hasDependency } from '../../util/plugin.js';
|
|
3
2
|
import { resolveConfig } from '../vitest/index.js';
|
|
4
|
-
import {
|
|
3
|
+
import { getBabelInputs, getIndexHtmlEntries } from './helpers.js';
|
|
5
4
|
import { createImportMetaGlobVisitor } from './visitors/importMetaGlob.js';
|
|
6
5
|
const title = 'Vite';
|
|
7
6
|
const enablers = ['vite', 'vitest'];
|
|
8
7
|
const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
|
|
9
8
|
export const config = ['vite.config.{js,mjs,ts,cjs,mts,cts}'];
|
|
10
|
-
const resolveFromAST = program =>
|
|
11
|
-
const inputs = getReactBabelInputs(program);
|
|
12
|
-
return inputs.map(id => toDependency(id));
|
|
13
|
-
};
|
|
9
|
+
const resolveFromAST = program => getBabelInputs(program);
|
|
14
10
|
const registerVisitors = ({ ctx, registerVisitor }) => {
|
|
15
11
|
registerVisitor(createImportMetaGlobVisitor(ctx));
|
|
16
12
|
};
|
|
@@ -8,11 +8,11 @@ const resolveConfig = async (config) => {
|
|
|
8
8
|
const cfg = config?.config;
|
|
9
9
|
if (!cfg)
|
|
10
10
|
return [];
|
|
11
|
-
const frameworks = cfg
|
|
12
|
-
const runners = cfg
|
|
11
|
+
const frameworks = cfg.framework ? [`@wdio/${cfg.framework}-framework`] : [];
|
|
12
|
+
const runners = cfg.runner && cfg.runner !== 'local'
|
|
13
13
|
? [`@wdio/${Array.isArray(cfg.runner) ? cfg.runner[0] : cfg.runner}-runner`]
|
|
14
14
|
: [];
|
|
15
|
-
const reporters = cfg
|
|
15
|
+
const reporters = cfg.reporters
|
|
16
16
|
? cfg.reporters
|
|
17
17
|
.flatMap(reporter => {
|
|
18
18
|
if (typeof reporter === 'string')
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ReporterOptions } from '../types/issues.ts';
|
|
2
|
-
declare const _default: ({ report, issues, cwd, configurationHints, isDisableConfigHints, isTreatConfigHintsAsErrors, configFilePath, }: ReporterOptions) => void;
|
|
2
|
+
declare const _default: ({ report, issues, cwd, configurationHints, tagHints, isDisableConfigHints, isDisableTagHints, isTreatConfigHintsAsErrors, isTreatTagHintsAsErrors, configFilePath, }: ReporterOptions) => void;
|
|
3
3
|
export default _default;
|
|
@@ -24,7 +24,7 @@ const createGitHubActionsLogger = () => {
|
|
|
24
24
|
notice: (message, options) => formatAnnotation('notice', message, options),
|
|
25
25
|
};
|
|
26
26
|
};
|
|
27
|
-
export default ({ report, issues, cwd, configurationHints, isDisableConfigHints, isTreatConfigHintsAsErrors, configFilePath, }) => {
|
|
27
|
+
export default ({ report, issues, cwd, configurationHints, tagHints, isDisableConfigHints, isDisableTagHints, isTreatConfigHintsAsErrors, isTreatTagHintsAsErrors, configFilePath, }) => {
|
|
28
28
|
const core = createGitHubActionsLogger();
|
|
29
29
|
const reportMultipleGroups = Object.values(report).filter(Boolean).length > 1;
|
|
30
30
|
for (const [reportType, isReportType] of Object.entries(report)) {
|
|
@@ -91,4 +91,22 @@ export default ({ report, issues, cwd, configurationHints, isDisableConfigHints,
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
+
if (!isDisableTagHints && tagHints.size > 0) {
|
|
95
|
+
const TAG_HINTS_TITLE = 'Tag hints';
|
|
96
|
+
core.info(`${TAG_HINTS_TITLE} (${tagHints.size})`);
|
|
97
|
+
const sortedHints = [...tagHints].sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
98
|
+
for (const hint of sortedHints) {
|
|
99
|
+
const file = relative(cwd, hint.filePath);
|
|
100
|
+
const hintMessage = `Unused tag in ${file}: ${hint.identifier} → ${hint.tagName}`;
|
|
101
|
+
const log = isTreatTagHintsAsErrors ? core.error : core.notice;
|
|
102
|
+
log(hintMessage, {
|
|
103
|
+
file,
|
|
104
|
+
startLine: 1,
|
|
105
|
+
endLine: 1,
|
|
106
|
+
startColumn: 1,
|
|
107
|
+
endColumn: 1,
|
|
108
|
+
title: TAG_HINTS_TITLE,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
94
112
|
};
|
|
@@ -6,6 +6,6 @@ declare const _default: {
|
|
|
6
6
|
codeclimate: ({ report, issues, cwd }: import("../types.ts").ReporterOptions) => Promise<void>;
|
|
7
7
|
json: ({ report, issues, options, cwd }: import("../types.ts").ReporterOptions) => Promise<void>;
|
|
8
8
|
markdown: ({ report, issues, cwd }: import("../types.ts").ReporterOptions) => void;
|
|
9
|
-
'github-actions': ({ report, issues, cwd, configurationHints, isDisableConfigHints, isTreatConfigHintsAsErrors, configFilePath, }: import("../types.ts").ReporterOptions) => void;
|
|
9
|
+
'github-actions': ({ report, issues, cwd, configurationHints, tagHints, isDisableConfigHints, isDisableTagHints, isTreatConfigHintsAsErrors, isTreatTagHintsAsErrors, configFilePath, }: import("../types.ts").ReporterOptions) => void;
|
|
10
10
|
};
|
|
11
11
|
export default _default;
|
|
@@ -29,7 +29,8 @@ export default (options) => {
|
|
|
29
29
|
}
|
|
30
30
|
if (totalIssues === 0 &&
|
|
31
31
|
isShowProgress &&
|
|
32
|
-
(!options.isTreatConfigHintsAsErrors || options.configurationHints.length === 0)
|
|
32
|
+
(!options.isTreatConfigHintsAsErrors || options.configurationHints.length === 0) &&
|
|
33
|
+
(!options.isTreatTagHintsAsErrors || options.tagHints.size === 0)) {
|
|
33
34
|
console.log('✂️ Excellent, Knip found no issues.');
|
|
34
35
|
}
|
|
35
36
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { GraphExplorer } from '../graph-explorer/explorer.ts';
|
|
2
|
+
import type { Issues } from '../types/issues.ts';
|
|
2
3
|
import type { ModuleGraph } from '../types/module-graph.ts';
|
|
3
4
|
import type { MainOptions } from '../util/create-options.ts';
|
|
4
5
|
import type { WorkspaceFilePathFilter } from '../util/workspace-file-filter.ts';
|
|
@@ -7,6 +8,7 @@ interface TraceReporterOptions {
|
|
|
7
8
|
explorer: GraphExplorer;
|
|
8
9
|
options: MainOptions;
|
|
9
10
|
workspaceFilePathFilter: WorkspaceFilePathFilter;
|
|
11
|
+
issues: Issues;
|
|
10
12
|
}
|
|
11
|
-
declare const _default: ({ graph, explorer, options, workspaceFilePathFilter }: TraceReporterOptions) => void;
|
|
13
|
+
declare const _default: ({ graph, explorer, options, workspaceFilePathFilter, issues }: TraceReporterOptions) => void;
|
|
12
14
|
export default _default;
|
package/dist/reporters/trace.js
CHANGED
|
@@ -3,7 +3,7 @@ import { toRelative } from '../util/path.js';
|
|
|
3
3
|
import { toRegexOrString } from '../util/regex.js';
|
|
4
4
|
import { Table } from '../util/table.js';
|
|
5
5
|
import { formatTrace } from '../util/trace.js';
|
|
6
|
-
export default ({ graph, explorer, options, workspaceFilePathFilter }) => {
|
|
6
|
+
export default ({ graph, explorer, options, workspaceFilePathFilter, issues }) => {
|
|
7
7
|
if (options.traceDependency) {
|
|
8
8
|
const pattern = toRegexOrString(options.traceDependency);
|
|
9
9
|
const toRel = (path) => toRelative(path, options.cwd);
|
|
@@ -23,8 +23,12 @@ export default ({ graph, explorer, options, workspaceFilePathFilter }) => {
|
|
|
23
23
|
table.cell('package', st.cyanBright(packageName));
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const rows = table.toRows();
|
|
27
|
+
if (rows.length === 0)
|
|
28
|
+
console.log(`No imports found matching ${st.cyanBright(options.traceDependency)}`);
|
|
29
|
+
else
|
|
30
|
+
for (const line of rows)
|
|
31
|
+
console.log(line);
|
|
28
32
|
}
|
|
29
33
|
else {
|
|
30
34
|
let nodes = explorer.buildExportsTree({ filePath: options.traceFile, identifier: options.traceExport });
|
|
@@ -32,27 +36,55 @@ export default ({ graph, explorer, options, workspaceFilePathFilter }) => {
|
|
|
32
36
|
const nsName = options.traceExport.substring(0, options.traceExport.indexOf('.'));
|
|
33
37
|
nodes = explorer.buildExportsTree({ filePath: options.traceFile, identifier: nsName });
|
|
34
38
|
}
|
|
39
|
+
if (nodes.length === 0 && options.traceExport) {
|
|
40
|
+
const query = options.traceExport;
|
|
41
|
+
const member = query.slice(query.lastIndexOf('.') + 1);
|
|
42
|
+
const seen = new Set();
|
|
43
|
+
for (const [filePath, file] of graph) {
|
|
44
|
+
if (options.traceFile && filePath !== options.traceFile)
|
|
45
|
+
continue;
|
|
46
|
+
for (const [exportId, exp] of file.exports) {
|
|
47
|
+
const key = `${filePath}:${exportId}`;
|
|
48
|
+
if (seen.has(key))
|
|
49
|
+
continue;
|
|
50
|
+
if (exp.members.some(m => m.identifier === query || m.identifier === member || m.identifier.endsWith(`.${member}`))) {
|
|
51
|
+
seen.add(key);
|
|
52
|
+
nodes.push(...explorer.buildExportsTree({ filePath, identifier: exportId }));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
35
57
|
nodes.sort((a, b) => a.filePath.localeCompare(b.filePath) || a.identifier.localeCompare(b.identifier));
|
|
36
58
|
const toRel = (path) => toRelative(path, options.cwd);
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
59
|
+
if (nodes.length === 0) {
|
|
60
|
+
if (options.traceFile && !graph.has(options.traceFile)) {
|
|
61
|
+
console.log(`File not found in module graph: ${toRel(options.traceFile)}`);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const what = options.traceExport ? `export ${st.cyanBright(options.traceExport)}` : 'exports';
|
|
65
|
+
const where = options.traceFile ? ` in ${toRel(options.traceFile)}` : '';
|
|
66
|
+
console.log(`No ${what} found${where}`);
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const reportedExports = new Set();
|
|
71
|
+
for (const type of ['exports', 'types', 'nsExports', 'nsTypes'])
|
|
72
|
+
for (const byFile of Object.values(issues[type]))
|
|
73
|
+
for (const issue of Object.values(byFile))
|
|
74
|
+
reportedExports.add(`${issue.filePath}:${issue.symbol}`);
|
|
75
|
+
const reportedMembers = new Set();
|
|
76
|
+
for (const type of ['enumMembers', 'namespaceMembers'])
|
|
77
|
+
for (const byFile of Object.values(issues[type]))
|
|
78
|
+
for (const issue of Object.values(byFile))
|
|
79
|
+
reportedMembers.add(`${issue.filePath}:${issue.parentSymbol}.${issue.symbol}`);
|
|
80
|
+
const isReferenced = (node) => !reportedExports.has(`${node.filePath}:${node.identifier}`);
|
|
44
81
|
for (const node of nodes) {
|
|
45
82
|
const exp = graph.get(node.filePath)?.exports.get(node.identifier);
|
|
46
83
|
let memberStatuses;
|
|
47
84
|
if (exp && exp.members.length > 0) {
|
|
48
85
|
memberStatuses = [];
|
|
49
86
|
for (const m of exp.members) {
|
|
50
|
-
const
|
|
51
|
-
const referenced = m.hasRefsInFile ||
|
|
52
|
-
explorer.isReferenced(node.filePath, id, {
|
|
53
|
-
traverseEntries: true,
|
|
54
|
-
treatStarAtEntryAsReferenced: true,
|
|
55
|
-
})[0];
|
|
87
|
+
const referenced = !reportedMembers.has(`${node.filePath}:${node.identifier}.${m.identifier}`);
|
|
56
88
|
memberStatuses.push({ identifier: m.identifier, referenced });
|
|
57
89
|
}
|
|
58
90
|
}
|
|
@@ -19,5 +19,5 @@ export declare const finalizeConfigurationHints: (results: Results, options: {
|
|
|
19
19
|
configFilePath?: string;
|
|
20
20
|
}) => ProcessedHint[];
|
|
21
21
|
export declare const printConfigurationHints: ({ cwd, counters, issues, tagHints, configurationHints, enabledPlugins, isTreatConfigHintsAsErrors, includedWorkspaceDirs, selectedWorkspaces, configFilePath, }: ReporterOptions) => void;
|
|
22
|
-
export declare const printTagHints: ({ cwd, tagHints }: ReporterOptions) => void;
|
|
22
|
+
export declare const printTagHints: ({ cwd, tagHints, isTreatTagHintsAsErrors }: ReporterOptions) => void;
|
|
23
23
|
export {};
|
|
@@ -128,9 +128,10 @@ export const printConfigurationHints = ({ cwd, counters, issues, tagHints, confi
|
|
|
128
128
|
console.warn(getTableForHints(rows).toString());
|
|
129
129
|
}
|
|
130
130
|
};
|
|
131
|
-
export const printTagHints = ({ cwd, tagHints }) => {
|
|
131
|
+
export const printTagHints = ({ cwd, tagHints, isTreatTagHintsAsErrors }) => {
|
|
132
132
|
if (tagHints.size > 0) {
|
|
133
|
-
|
|
133
|
+
const getTitle = isTreatTagHintsAsErrors ? getColoredTitle : getDimmedTitle;
|
|
134
|
+
console.warn(getTitle('Tag hints', tagHints.size));
|
|
134
135
|
for (const hint of tagHints) {
|
|
135
136
|
const { filePath, identifier, tagName } = hint;
|
|
136
137
|
const message = `Unused tag in ${toRelative(filePath, cwd)}:`;
|