Skip to content

Commit

Permalink
Highlight package name in specifier in symbols reporter
Browse files Browse the repository at this point in the history
  • Loading branch information
webpro committed Oct 28, 2024
1 parent c881d78 commit eca123b
Show file tree
Hide file tree
Showing 15 changed files with 49 additions and 25 deletions.
7 changes: 4 additions & 3 deletions packages/knip/src/IssueCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ export class IssueCollector {
if (this.isMatch(issue.filePath)) return;
const key = relative(this.cwd, issue.filePath);
issue.severity = this.rules[issue.type];
this.issues[issue.type][key] = this.issues[issue.type][key] ?? {};
if (!this.issues[issue.type][key][issue.symbol]) {
this.issues[issue.type][key][issue.symbol] = issue;
const issues = this.issues[issue.type];
issues[key] = issues[key] ?? {};
if (!issues[key][issue.symbol]) {
issues[key][issue.symbol] = issue;
this.counters[issue.type]++;
}
return issue;
Expand Down
9 changes: 8 additions & 1 deletion packages/knip/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,14 @@ export const main = async (unresolvedConfiguration: CommandLineOptions) => {
for (const specifier of file.imports.external) {
const packageName = getPackageNameFromModuleSpecifier(specifier);
const isHandled = packageName && deputy.maybeAddReferencedExternalDependency(ws, packageName);
if (!isHandled) collector.addIssue({ type: 'unlisted', filePath, workspace: ws.name, symbol: specifier });
if (!isHandled)
collector.addIssue({
type: 'unlisted',
filePath,
workspace: ws.name,
symbol: packageName ?? specifier,
specifier,
});
}
}

Expand Down
24 changes: 18 additions & 6 deletions packages/knip/src/reporters/symbols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,26 @@ import type { Issue, ReporterOptions } from '../types/issues.js';
import { relative, toRelative } from '../util/path.js';
import { getTitle, identity, logTitle } from './util.js';

const dim = picocolors.gray;
const bright = picocolors.whiteBright;

const TRUNCATE_WIDTH = 40;
const truncate = (text: string) => (text.length > TRUNCATE_WIDTH ? `${text.slice(0, TRUNCATE_WIDTH - 3)}...` : text);

const hl = (issue: Issue) => {
if (issue.specifier && issue.specifier !== issue.symbol && issue.specifier.includes(issue.symbol)) {
const parts = issue.specifier.split(issue.symbol);
const rest = parts.slice(1).join('');
return [dim(parts[0]), bright(issue.symbol), dim(rest)].join('');
}
return issue.symbol;
};

const logIssueRecord = (issues: Issue[]) => {
const table = new EasyTable();
for (const issue of issues) {
const print = issue.isFixed || issue.severity === 'warn' ? picocolors.gray : identity;
table.cell('symbol', print(issue.symbols ? truncate(issue.symbols.map(s => s.symbol).join(', ')) : issue.symbol));
const print = issue.isFixed || issue.severity === 'warn' ? dim : identity;
table.cell('symbol', print(issue.symbols ? truncate(issue.symbols.map(s => s.symbol).join(', ')) : hl(issue)));
issue.parentSymbol && table.cell('parentSymbol', print(issue.parentSymbol));
issue.symbolType && table.cell('symbolType', print(issue.symbolType));
const pos = issue.line === undefined ? '' : `:${issue.line}${issue.col === undefined ? '' : `:${issue.col}`}`;
Expand Down Expand Up @@ -41,8 +53,8 @@ export default ({ report, issues, tagHints, configurationHints, noConfigHints, i
title && logTitle(title, issuesForType.length);
for (const issue of issuesForType) {
const relPath = toRelative(issue.filePath);
if (issue.isFixed) console.log(picocolors.gray(`${relPath} (removed)`));
else if (issue.severity === 'warn') console.log(picocolors.gray(relPath));
if (issue.isFixed) console.log(dim(`${relPath} (removed)`));
else if (issue.severity === 'warn') console.log(dim(relPath));
else console.log(relPath);
}
totalIssues = totalIssues + issuesForType.length;
Expand All @@ -66,15 +78,15 @@ export default ({ report, issues, tagHints, configurationHints, noConfigHints, i
const message = `Unused item in ${type}`;
const workspace =
workspaceName && workspaceName !== ROOT_WORKSPACE_NAME ? ` (workspace: ${workspaceName})` : '';
console.warn(picocolors.gray(`${message}${workspace}:`), identifier);
console.warn(dim(`${message}${workspace}:`), identifier);
}
}
if (tagHints.size > 0) {
logTitle('Tag issues', tagHints.size);
for (const hint of tagHints) {
const { filePath, identifier, tagName } = hint;
const message = `Unused tag in ${toRelative(filePath)}:`;
console.warn(picocolors.gray(message), `${identifier}${tagName}`);
console.warn(dim(message), `${identifier}${tagName}`);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/knip/src/types/issues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type Issue = {
symbols?: IssueSymbol[];
symbolType?: SymbolType;
parentSymbol?: string;
specifier?: string;
severity?: IssueSeverity;
pos?: number;
line?: number;
Expand Down
5 changes: 4 additions & 1 deletion packages/knip/src/util/get-referenced-inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const getReferencedInputsHandler =
filePath: containingFilePath,
workspace: workspace.name,
symbol: binaryName,
specifier,
});
return;
}
Expand All @@ -59,7 +60,8 @@ export const getReferencedInputsHandler =
type: 'unlisted',
filePath: containingFilePath,
workspace: specifierWorkspace.name,
symbol: specifier,
symbol: packageName ?? specifier,
specifier,
});
}
return;
Expand Down Expand Up @@ -92,6 +94,7 @@ export const getReferencedInputsHandler =
filePath: containingFilePath,
workspace: workspace.name,
symbol: packageName ?? specifier,
specifier,
});
} else if (!isGitIgnored(filePath)) {
// Let's start out conservatively
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test('Resolve modules properly using tsconfig paths and globs', async () => {
assert.equal(issues.dependencies['package.json']['internal'].symbol, 'internal');

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

assert.equal(issues.exports['internal-package/index.ts']['unused'].symbol, 'unused');
assert.equal(issues.exports['unprefixed/module.ts']['unused'].symbol, 'unused');
Expand Down
4 changes: 2 additions & 2 deletions packages/knip/test/plugins/cypress-multi-reporter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ test('Find dependencies with the cypress-multi-reporter plugin', async () => {
cwd,
});

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

assert.deepEqual(counters, {
Expand Down
4 changes: 2 additions & 2 deletions packages/knip/test/plugins/cypress.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ test('Find dependencies with the Cypress plugin', async () => {
cwd,
});

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

assert.deepEqual(counters, {
...baseCounters,
Expand Down
2 changes: 1 addition & 1 deletion packages/knip/test/plugins/jest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test('Find dependencies with the Jest plugin', async () => {
});

assert(issues.unlisted['jest.config.shared.js']['@jest/types']);
assert(issues.unlisted['jest.setup.js']['@testing-library/jest-dom/extend-expect']);
assert(issues.unlisted['jest.setup.js']['@testing-library/jest-dom']);
assert(issues.unlisted['jest.config.js']['@jest/types']);
assert(issues.unresolved['jest.config.js']['@nrwl/react/plugins/jest']);
assert(issues.unresolved['jest.config.js']['babel-jest']);
Expand Down
2 changes: 1 addition & 1 deletion packages/knip/test/plugins/nx-crystal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test('Find dependencies with the Nx plugin', async () => {

assert(issues.devDependencies['package.json']['@nx/cypress']);
assert(issues.devDependencies['package.json']['@nrwl/workspace']);
assert(issues.unlisted['nx.json']['@nx/nuxt/plugin']);
assert(issues.unlisted['nx.json']['@nx/nuxt']);
assert(issues.binaries['package.json']['nx']);

assert.deepEqual(counters, {
Expand Down
4 changes: 2 additions & 2 deletions packages/knip/test/plugins/remix.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ test('Find dependencies with the Remix plugin', async () => {

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

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

assert(issues.unlisted['app/root.tsx']['@remix-run/node']);
assert(issues.unlisted['app/root.tsx']['@remix-run/react']);
Expand Down
2 changes: 1 addition & 1 deletion packages/knip/test/plugins/storybook.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ test('Find dependencies with Storybook plugin', async () => {
assert(issues.unlisted['main.js']['@storybook/builder-webpack5']);
assert(issues.unlisted['main.js']['@storybook/manager-webpack5']);
assert(issues.unlisted['main.js']['@storybook/react-webpack5']);
assert(issues.unlisted['preview.js']['cypress-storybook/react']);
assert(issues.unlisted['preview.js']['cypress-storybook']);
assert(issues.unresolved['main.js']['@storybook/addon-knobs/preset']);
assert(issues.unresolved['main.js']['storybook-addon-export-to-codesandbox']);
assert(issues.binaries['package.json']['storybook']);
Expand Down
4 changes: 2 additions & 2 deletions packages/knip/test/plugins/typescript.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ test('Find dependencies with the TypeScript plugin', async () => {
assert(issues.unlisted['tsconfig.jsx-import-source-preact.json']['preact']);
assert(issues.unresolved['tsconfig.jsx-import-source-preact.json']['preact']);
assert(issues.unresolved['tsconfig.jsx-import-source-react.json']['vitest/globals']);
assert(issues.unlisted['tsconfig.jsx-import-source-react.json']['hastscript/svg']);
assert(issues.unlisted['tsconfig.jsx-import-source-react.json']['hastscript']);

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

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

assert.deepEqual(counters, {
...baseCounters,
Expand Down
2 changes: 1 addition & 1 deletion packages/knip/test/workspaces-paths.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ test('Find unused files, dependencies and exports in workspaces (w/ paths)', asy
});

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

assert.deepEqual(counters, {
...baseCounters,
Expand Down
2 changes: 1 addition & 1 deletion packages/knip/test/workspaces.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ test('Find unused files, dependencies and exports in workspaces (default)', asyn
assert(issues.unlisted['apps/frontend/index.ts']['vanilla-js']);
assert(issues.unlisted['apps/backend/index.ts']['globby']);
assert(issues.unlisted['apps/backend/index.ts']['js-yaml']);
assert(issues.unlisted['packages/tools/tsconfig.json']['@workspaces/tsconfig/tsconfig.base.json']);
assert(issues.unlisted['packages/tools/tsconfig.json']['@workspaces/tsconfig']);

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

Expand Down

0 comments on commit eca123b

Please sign in to comment.