UNPKG

knip

Version:

Find unused files, dependencies and exports in your TypeScript and JavaScript projects

88 lines (87 loc) 3.15 kB
import picomatch from 'picomatch'; import { initCounters, initIssues } from './issues/initializers.js'; import { timerify } from './util/Performance.js'; import { relative } from './util/path.js'; const hasConfigurationHint = (hints, hint) => Array.from(hints).some(item => item.identifier === hint.identifier && item.type === hint.type && item.workspaceName === hint.workspaceName); const isMatch = timerify(picomatch.isMatch, 'isMatch'); export class IssueCollector { cwd; rules; filters; issues = initIssues(); counters = initCounters(); referencedFiles = new Set(); configurationHints = new Set(); tagHints = new Set(); ignorePatterns = new Set(); isMatch; constructor({ cwd, rules, filters }) { this.cwd = cwd; this.rules = rules; this.filters = filters; this.isMatch = () => false; } addIgnorePatterns(patterns) { for (const pattern of patterns) this.ignorePatterns.add(pattern); const p = [...this.ignorePatterns]; this.isMatch = (filePath) => isMatch(filePath, p, { dot: true }); } addFileCounts({ processed, unused }) { this.counters.processed += processed; this.counters.total += processed + unused; } addFilesIssues(filePaths) { for (const filePath of filePaths) { if (this.filters.dir && !filePath.startsWith(`${this.filters.dir}/`)) continue; if (this.referencedFiles.has(filePath)) continue; if (this.isMatch(filePath)) continue; this.issues.files.add(filePath); this.issues._files.add({ type: 'files', filePath, symbol: relative(filePath), severity: this.rules.files }); this.counters.files++; this.counters.processed++; } } addIssue(issue) { if (this.filters.dir && !issue.filePath.startsWith(`${this.filters.dir}/`)) return; if (this.isMatch(issue.filePath)) return; const key = relative(this.cwd, issue.filePath); const { type } = issue; issue.severity = this.rules[type]; const issues = this.issues[type]; issues[key] = issues[key] ?? {}; const symbol = type.endsWith('Members') && issue.parentSymbol ? `${issue.parentSymbol}.${issue.symbol}` : issue.symbol; if (!issues[key][symbol]) { issues[key][symbol] = issue; this.counters[issue.type]++; } return issue; } addConfigurationHint(issue) { if (!hasConfigurationHint(this.configurationHints, issue)) { this.configurationHints.add(issue); } } addTagHint(issue) { this.tagHints.add(issue); } purge() { const unusedFiles = this.issues.files; this.issues = initIssues(); this.counters = initCounters(); return unusedFiles; } getIssues() { return { issues: this.issues, counters: this.counters, tagHints: this.tagHints, configurationHints: this.configurationHints, }; } }