knip
Version:
Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects
95 lines (94 loc) • 3.42 kB
JavaScript
import { createHash } from 'node:crypto';
import { ISSUE_TYPE_TITLE } from '../constants.js';
import { toRelative } from '../util/path.js';
import { getIssueTypeTitle } from './util/util.js';
export default async ({ report, issues }) => {
const entries = [];
for (const [type, isReportType] of Object.entries(report)) {
if (!isReportType) {
continue;
}
const fixedType = type === 'files' ? '_files' : type;
for (const issue of flatten(issues[fixedType])) {
const { filePath } = issue;
if (fixedType === 'duplicates' && issue.symbols) {
entries.push(...issue.symbols.map(symbol => ({
type: 'issue',
check_name: getIssueTypeTitle(fixedType),
description: getSymbolDescription({ type: issue.type, symbol, parentSymbol: issue.parentSymbol }),
categories: ['Duplication'],
location: createLocation(filePath, symbol.line, symbol.col),
severity: convertSeverity(issue.severity),
fingerprint: createFingerprint(filePath, symbol.symbol),
})));
}
else {
entries.push({
type: 'issue',
check_name: getIssueTypeTitle(fixedType),
description: getIssueDescription(issue),
categories: ['Bug Risk'],
location: createLocation(filePath, issue.line, issue.col),
severity: convertSeverity(issue.severity),
fingerprint: createFingerprint(filePath, issue.symbol),
});
}
}
}
const output = JSON.stringify(entries);
process.stdout._handle?.setBlocking?.(true);
process.stdout.write(`${output}\n`);
};
function flatten(issues) {
return Object.values(issues).flatMap(Object.values);
}
function convertSeverity(severity) {
switch (severity) {
case 'error':
return 'major';
case 'warn':
return 'minor';
default:
return 'info';
}
}
function getPrefix(type) {
return ISSUE_TYPE_TITLE[type].replace(/ies$/, 'y').replace(/s$/, '');
}
function getIssueDescription({ type, symbol, symbols, parentSymbol }) {
const symbolDescription = symbols ? `${symbols.map(s => s.symbol).join(', ')}` : symbol;
return `${getPrefix(type)}: ${symbolDescription}${parentSymbol ? ` (${parentSymbol})` : ''}`;
}
function getSymbolDescription({ type, symbol, parentSymbol, }) {
return `${getPrefix(type)}: ${symbol.symbol}${parentSymbol ? ` (${parentSymbol})` : ''}`;
}
function createLocation(filePath, line, col) {
if (col !== undefined) {
return {
path: toRelative(filePath),
positions: {
begin: {
line: line ?? 0,
column: col,
},
end: {
line: line ?? 0,
column: col,
},
},
};
}
return {
path: toRelative(filePath),
lines: {
begin: line ?? 0,
end: line ?? 0,
},
};
}
function createFingerprint(filePath, message) {
const md5 = createHash('md5');
md5.update(toRelative(filePath));
md5.update(message);
return md5.digest('hex');
}