UNPKG

knip

Version:

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

114 lines (113 loc) 4.49 kB
import { STOP } from "./constants.js"; import { getAliasReExportMap, getPassThroughReExportSources, getStarReExportSources } from "./visitors.js"; export const walkDown = (graph, filePath, identifier, visitor, entryPaths, visited = new Set()) => { const key = `${filePath}:${identifier}`; if (visited.has(key)) return false; visited.add(key); const file = graph.get(filePath); if (!file?.importedBy) return false; const restIds = identifier.split('.'); const id = restIds.shift(); if (!id) return false; const imported = file.importedBy; const importedByFiles = imported.import.get(id); if (importedByFiles) { for (const importingFile of importedByFiles) { const isEntry = entryPaths.has(importingFile); if (visitor(filePath, id, importingFile, id, isEntry, 'import') === STOP) return true; } } const importAsAliases = imported.importAs.get(id); if (importAsAliases) { for (const [alias, byFilePaths] of importAsAliases) { for (const importingFile of byFilePaths) { const isEntry = entryPaths.has(importingFile); if (visitor(filePath, id, importingFile, alias, isEntry, 'importAs') === STOP) return true; } } } for (const [namespace, byFilePaths] of imported.importNs) { for (const importingFile of byFilePaths) { const isEntry = entryPaths.has(importingFile); if (visitor(filePath, identifier, importingFile, `${namespace}.${identifier}`, isEntry, 'importNS') === STOP) { return true; } } } let done = false; if (!done) { const passThroughSources = getPassThroughReExportSources(imported, id); if (passThroughSources) { for (const reExportingFile of passThroughSources) { const isEntry = entryPaths.has(reExportingFile); if (visitor(filePath, id, reExportingFile, id, isEntry, 'reExport') === STOP) { done = true; break; } if (walkDown(graph, reExportingFile, identifier, visitor, entryPaths, visited)) { done = true; break; } } } } if (!done) { const aliasReExportMap = getAliasReExportMap(imported, id); if (aliasReExportMap) { for (const [alias, sources] of aliasReExportMap) { for (const reExportingFile of sources) { const isEntry = entryPaths.has(reExportingFile); if (visitor(filePath, id, reExportingFile, alias, isEntry, 'reExportAs') === STOP) { done = true; break; } if (walkDown(graph, reExportingFile, [alias, ...restIds].join('.'), visitor, entryPaths, visited)) { done = true; break; } } if (done) break; } } } if (!done) { for (const [namespace, sources] of imported.reExportNs) { for (const reExportingFile of sources) { const isEntry = entryPaths.has(reExportingFile); if (visitor(filePath, identifier, reExportingFile, `${namespace}.${identifier}`, isEntry, 'reExportNS') === STOP) { done = true; break; } if (walkDown(graph, reExportingFile, `${namespace}.${identifier}`, visitor, entryPaths, visited)) { done = true; break; } } if (done) break; } } if (!done) { const starSources = getStarReExportSources(imported); if (starSources) { for (const reExportingFile of starSources) { const isEntry = entryPaths.has(reExportingFile); if (visitor(filePath, id, reExportingFile, id, isEntry, 'reExportStar') === STOP) { done = true; break; } if (walkDown(graph, reExportingFile, identifier, visitor, entryPaths, visited)) { done = true; break; } } } } return done; };