Skip to content

Commit eca123b

Browse files
committedOct 28, 2024·
Highlight package name in specifier in symbols reporter
1 parent c881d78 commit eca123b

15 files changed

+49
-25
lines changed
 

‎packages/knip/src/IssueCollector.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,10 @@ export class IssueCollector {
7575
if (this.isMatch(issue.filePath)) return;
7676
const key = relative(this.cwd, issue.filePath);
7777
issue.severity = this.rules[issue.type];
78-
this.issues[issue.type][key] = this.issues[issue.type][key] ?? {};
79-
if (!this.issues[issue.type][key][issue.symbol]) {
80-
this.issues[issue.type][key][issue.symbol] = issue;
78+
const issues = this.issues[issue.type];
79+
issues[key] = issues[key] ?? {};
80+
if (!issues[key][issue.symbol]) {
81+
issues[key][issue.symbol] = issue;
8182
this.counters[issue.type]++;
8283
}
8384
return issue;

‎packages/knip/src/index.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,14 @@ export const main = async (unresolvedConfiguration: CommandLineOptions) => {
582582
for (const specifier of file.imports.external) {
583583
const packageName = getPackageNameFromModuleSpecifier(specifier);
584584
const isHandled = packageName && deputy.maybeAddReferencedExternalDependency(ws, packageName);
585-
if (!isHandled) collector.addIssue({ type: 'unlisted', filePath, workspace: ws.name, symbol: specifier });
585+
if (!isHandled)
586+
collector.addIssue({
587+
type: 'unlisted',
588+
filePath,
589+
workspace: ws.name,
590+
symbol: packageName ?? specifier,
591+
specifier,
592+
});
586593
}
587594
}
588595

‎packages/knip/src/reporters/symbols.ts

+18-6
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,26 @@ import type { Issue, ReporterOptions } from '../types/issues.js';
66
import { relative, toRelative } from '../util/path.js';
77
import { getTitle, identity, logTitle } from './util.js';
88

9+
const dim = picocolors.gray;
10+
const bright = picocolors.whiteBright;
11+
912
const TRUNCATE_WIDTH = 40;
1013
const truncate = (text: string) => (text.length > TRUNCATE_WIDTH ? `${text.slice(0, TRUNCATE_WIDTH - 3)}...` : text);
1114

15+
const hl = (issue: Issue) => {
16+
if (issue.specifier && issue.specifier !== issue.symbol && issue.specifier.includes(issue.symbol)) {
17+
const parts = issue.specifier.split(issue.symbol);
18+
const rest = parts.slice(1).join('');
19+
return [dim(parts[0]), bright(issue.symbol), dim(rest)].join('');
20+
}
21+
return issue.symbol;
22+
};
23+
1224
const logIssueRecord = (issues: Issue[]) => {
1325
const table = new EasyTable();
1426
for (const issue of issues) {
15-
const print = issue.isFixed || issue.severity === 'warn' ? picocolors.gray : identity;
16-
table.cell('symbol', print(issue.symbols ? truncate(issue.symbols.map(s => s.symbol).join(', ')) : issue.symbol));
27+
const print = issue.isFixed || issue.severity === 'warn' ? dim : identity;
28+
table.cell('symbol', print(issue.symbols ? truncate(issue.symbols.map(s => s.symbol).join(', ')) : hl(issue)));
1729
issue.parentSymbol && table.cell('parentSymbol', print(issue.parentSymbol));
1830
issue.symbolType && table.cell('symbolType', print(issue.symbolType));
1931
const pos = issue.line === undefined ? '' : `:${issue.line}${issue.col === undefined ? '' : `:${issue.col}`}`;
@@ -41,8 +53,8 @@ export default ({ report, issues, tagHints, configurationHints, noConfigHints, i
4153
title && logTitle(title, issuesForType.length);
4254
for (const issue of issuesForType) {
4355
const relPath = toRelative(issue.filePath);
44-
if (issue.isFixed) console.log(picocolors.gray(`${relPath} (removed)`));
45-
else if (issue.severity === 'warn') console.log(picocolors.gray(relPath));
56+
if (issue.isFixed) console.log(dim(`${relPath} (removed)`));
57+
else if (issue.severity === 'warn') console.log(dim(relPath));
4658
else console.log(relPath);
4759
}
4860
totalIssues = totalIssues + issuesForType.length;
@@ -66,15 +78,15 @@ export default ({ report, issues, tagHints, configurationHints, noConfigHints, i
6678
const message = `Unused item in ${type}`;
6779
const workspace =
6880
workspaceName && workspaceName !== ROOT_WORKSPACE_NAME ? ` (workspace: ${workspaceName})` : '';
69-
console.warn(picocolors.gray(`${message}${workspace}:`), identifier);
81+
console.warn(dim(`${message}${workspace}:`), identifier);
7082
}
7183
}
7284
if (tagHints.size > 0) {
7385
logTitle('Tag issues', tagHints.size);
7486
for (const hint of tagHints) {
7587
const { filePath, identifier, tagName } = hint;
7688
const message = `Unused tag in ${toRelative(filePath)}:`;
77-
console.warn(picocolors.gray(message), `${identifier}${tagName}`);
89+
console.warn(dim(message), `${identifier}${tagName}`);
7890
}
7991
}
8092
}

‎packages/knip/src/types/issues.ts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export type Issue = {
1818
symbols?: IssueSymbol[];
1919
symbolType?: SymbolType;
2020
parentSymbol?: string;
21+
specifier?: string;
2122
severity?: IssueSeverity;
2223
pos?: number;
2324
line?: number;

‎packages/knip/src/util/get-referenced-inputs.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const getReferencedInputsHandler =
3737
filePath: containingFilePath,
3838
workspace: workspace.name,
3939
symbol: binaryName,
40+
specifier,
4041
});
4142
return;
4243
}
@@ -59,7 +60,8 @@ export const getReferencedInputsHandler =
5960
type: 'unlisted',
6061
filePath: containingFilePath,
6162
workspace: specifierWorkspace.name,
62-
symbol: specifier,
63+
symbol: packageName ?? specifier,
64+
specifier,
6365
});
6466
}
6567
return;
@@ -92,6 +94,7 @@ export const getReferencedInputsHandler =
9294
filePath: containingFilePath,
9395
workspace: workspace.name,
9496
symbol: packageName ?? specifier,
97+
specifier,
9598
});
9699
} else if (!isGitIgnored(filePath)) {
97100
// Let's start out conservatively

‎packages/knip/test/module-resolution-tsconfig-paths.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ test('Resolve modules properly using tsconfig paths and globs', async () => {
1616
assert.equal(issues.dependencies['package.json']['internal'].symbol, 'internal');
1717

1818
assert.equal(issues.unlisted['index.ts']['@unknown'].symbol, '@unknown');
19-
assert.equal(issues.unlisted['index.ts']['unresolved/dir'].symbol, 'unresolved/dir');
19+
assert.equal(issues.unlisted['index.ts']['unresolved'].symbol, 'unresolved');
2020

2121
assert.equal(issues.exports['internal-package/index.ts']['unused'].symbol, 'unused');
2222
assert.equal(issues.exports['unprefixed/module.ts']['unused'].symbol, 'unused');

‎packages/knip/test/plugins/cypress-multi-reporter.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ test('Find dependencies with the cypress-multi-reporter plugin', async () => {
1313
cwd,
1414
});
1515

16-
assert(issues.unlisted['cypress.config.ts']['@nrwl/cypress/plugins/cypress-preset']);
16+
assert(issues.unlisted['cypress.config.ts']['@nrwl/cypress']);
1717
assert(issues.unlisted['cypress/support/commands.ts']['@faker-js/faker']);
18-
assert(issues.unlisted['cypress/support/e2e.ts']['@testing-library/cypress/add-commands']);
18+
assert(issues.unlisted['cypress/support/e2e.ts']['@testing-library/cypress']);
1919
assert(issues.unresolved['cypress.config.ts']['@testing-library/my-fake-reporter']);
2020

2121
assert.deepEqual(counters, {

‎packages/knip/test/plugins/cypress.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ test('Find dependencies with the Cypress plugin', async () => {
1313
cwd,
1414
});
1515

16-
assert(issues.unlisted['cypress.config.ts']['@nrwl/cypress/plugins/cypress-preset']);
16+
assert(issues.unlisted['cypress.config.ts']['@nrwl/cypress']);
1717
assert(issues.unlisted['cypress/support/commands.ts']['@faker-js/faker']);
18-
assert(issues.unlisted['cypress/support/e2e.ts']['@testing-library/cypress/add-commands']);
18+
assert(issues.unlisted['cypress/support/e2e.ts']['@testing-library/cypress']);
1919

2020
assert.deepEqual(counters, {
2121
...baseCounters,

‎packages/knip/test/plugins/jest.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ test('Find dependencies with the Jest plugin', async () => {
1414
});
1515

1616
assert(issues.unlisted['jest.config.shared.js']['@jest/types']);
17-
assert(issues.unlisted['jest.setup.js']['@testing-library/jest-dom/extend-expect']);
17+
assert(issues.unlisted['jest.setup.js']['@testing-library/jest-dom']);
1818
assert(issues.unlisted['jest.config.js']['@jest/types']);
1919
assert(issues.unresolved['jest.config.js']['@nrwl/react/plugins/jest']);
2020
assert(issues.unresolved['jest.config.js']['babel-jest']);

‎packages/knip/test/plugins/nx-crystal.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ test('Find dependencies with the Nx plugin', async () => {
1515

1616
assert(issues.devDependencies['package.json']['@nx/cypress']);
1717
assert(issues.devDependencies['package.json']['@nrwl/workspace']);
18-
assert(issues.unlisted['nx.json']['@nx/nuxt/plugin']);
18+
assert(issues.unlisted['nx.json']['@nx/nuxt']);
1919
assert(issues.binaries['package.json']['nx']);
2020

2121
assert.deepEqual(counters, {

‎packages/knip/test/plugins/remix.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ test('Find dependencies with the Remix plugin', async () => {
2626

2727
assert(issues.unlisted['app/entry.client.tsx']['@remix-run/react']);
2828
assert(issues.unlisted['app/entry.client.tsx']['react']);
29-
assert(issues.unlisted['app/entry.client.tsx']['react-dom/client']);
29+
assert(issues.unlisted['app/entry.client.tsx']['react-dom']);
3030

3131
assert(issues.unlisted['app/entry.server.tsx']['@remix-run/node']);
3232
assert(issues.unlisted['app/entry.server.tsx']['@remix-run/react']);
33-
assert(issues.unlisted['app/entry.server.tsx']['react-dom/server']);
33+
assert(issues.unlisted['app/entry.server.tsx']['react-dom']);
3434

3535
assert(issues.unlisted['app/root.tsx']['@remix-run/node']);
3636
assert(issues.unlisted['app/root.tsx']['@remix-run/react']);

‎packages/knip/test/plugins/storybook.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ test('Find dependencies with Storybook plugin', async () => {
1717
assert(issues.unlisted['main.js']['@storybook/builder-webpack5']);
1818
assert(issues.unlisted['main.js']['@storybook/manager-webpack5']);
1919
assert(issues.unlisted['main.js']['@storybook/react-webpack5']);
20-
assert(issues.unlisted['preview.js']['cypress-storybook/react']);
20+
assert(issues.unlisted['preview.js']['cypress-storybook']);
2121
assert(issues.unresolved['main.js']['@storybook/addon-knobs/preset']);
2222
assert(issues.unresolved['main.js']['storybook-addon-export-to-codesandbox']);
2323
assert(issues.binaries['package.json']['storybook']);

‎packages/knip/test/plugins/typescript.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test('Find dependencies with the TypeScript plugin', async () => {
1919
assert(issues.unlisted['tsconfig.jsx-import-source-preact.json']['preact']);
2020
assert(issues.unresolved['tsconfig.jsx-import-source-preact.json']['preact']);
2121
assert(issues.unresolved['tsconfig.jsx-import-source-react.json']['vitest/globals']);
22-
assert(issues.unlisted['tsconfig.jsx-import-source-react.json']['hastscript/svg']);
22+
assert(issues.unlisted['tsconfig.jsx-import-source-react.json']['hastscript']);
2323

2424
assert.deepEqual(counters, {
2525
...baseCounters,
@@ -39,7 +39,7 @@ test('Find dependencies with the TypeScript plugin (production)', async () => {
3939
});
4040

4141
assert(issues.unlisted['tsconfig.jsx-import-source-preact.json']['preact']);
42-
assert(issues.unlisted['tsconfig.jsx-import-source-react.json']['hastscript/svg']);
42+
assert(issues.unlisted['tsconfig.jsx-import-source-react.json']['hastscript']);
4343

4444
assert.deepEqual(counters, {
4545
...baseCounters,

‎packages/knip/test/workspaces-paths.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ test('Find unused files, dependencies and exports in workspaces (w/ paths)', asy
1313
});
1414

1515
assert.equal(Object.keys(issues.unlisted).length, 1);
16-
assert(issues.unlisted['packages/lib-e/src/index.ts']['not/found']);
16+
assert(issues.unlisted['packages/lib-e/src/index.ts']['not']);
1717

1818
assert.deepEqual(counters, {
1919
...baseCounters,

‎packages/knip/test/workspaces.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ test('Find unused files, dependencies and exports in workspaces (default)', asyn
2727
assert(issues.unlisted['apps/frontend/index.ts']['vanilla-js']);
2828
assert(issues.unlisted['apps/backend/index.ts']['globby']);
2929
assert(issues.unlisted['apps/backend/index.ts']['js-yaml']);
30-
assert(issues.unlisted['packages/tools/tsconfig.json']['@workspaces/tsconfig/tsconfig.base.json']);
30+
assert(issues.unlisted['packages/tools/tsconfig.json']['@workspaces/tsconfig']);
3131

3232
assert(issues.types['packages/shared/types.ts']['UnusedEnum']);
3333

0 commit comments

Comments
 (0)
Please sign in to comment.