UNPKG

knip

Version:

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

86 lines (85 loc) 4.48 kB
import watchReporter from '../reporters/watch.js'; import { debugLog } from './debug.js'; import { isFile } from './fs.js'; import { updateImportMap } from './module-graph.js'; import { join, toPosix } from './path.js'; export const getWatchHandler = async ({ analyzedFiles, analyzeSourceFile, chief, collector, analyze, cwd, factory, graph, isDebug, isIgnored, report, streamer, unreferencedFiles, }) => { const reportIssues = async (startTime) => { const { issues } = collector.getIssues(); watchReporter({ report, issues, streamer, startTime, size: analyzedFiles.size, isDebug }); }; const listener = async (eventType, filename) => { debugLog('*', `(raw) ${eventType} ${filename}`); if (typeof filename === 'string') { const startTime = performance.now(); const filePath = join(cwd, toPosix(filename)); if (isIgnored(filePath)) { debugLog('*', `ignoring ${eventType} ${filename}`); return; } const workspace = chief.findWorkspaceByFilePath(filePath); if (workspace) { const principal = factory.getPrincipalByPackageName(workspace.pkgName); if (principal) { const event = eventType === 'rename' ? (isFile(filePath) ? 'added' : 'deleted') : 'modified'; principal.invalidateFile(filePath); unreferencedFiles.clear(); const cachedUnusedFiles = collector.purge(); switch (event) { case 'added': principal.addProjectPath(filePath); principal.deletedFiles.delete(filePath); cachedUnusedFiles.add(filePath); debugLog(workspace.name, `Watcher: + ${filename}`); break; case 'deleted': analyzedFiles.delete(filePath); principal.removeProjectPath(filePath); cachedUnusedFiles.delete(filePath); debugLog(workspace.name, `Watcher: - ${filename}`); break; case 'modified': debugLog(workspace.name, `Watcher: ± ${filename}`); break; } const filePaths = factory.getPrincipals().flatMap(p => p.getUsedResolvedFiles()); if (event === 'added' || event === 'deleted') { graph.clear(); for (const filePath of filePaths) analyzeSourceFile(filePath, principal); } else { for (const [filePath, file] of graph) { if (filePaths.includes(filePath)) { file.imported = undefined; } else { graph.delete(filePath); analyzedFiles.delete(filePath); if (principal.projectPaths.has(filePath)) cachedUnusedFiles.add(filePath); } } for (const filePath of filePaths) if (!graph.has(filePath)) analyzeSourceFile(filePath, principal); if (!cachedUnusedFiles.has(filePath)) analyzeSourceFile(filePath, principal); for (const filePath of filePaths) { const file = graph.get(filePath); if (file?.internalImportCache) updateImportMap(file, file.internalImportCache, graph); } } await analyze(); const unusedFiles = [...cachedUnusedFiles].filter(filePath => !analyzedFiles.has(filePath)); collector.addFilesIssues(unusedFiles); collector.addFileCounts({ processed: analyzedFiles.size, unused: unusedFiles.length }); await reportIssues(startTime); } } } }; await reportIssues(); return listener; };