ngx-unused
Version:
Detect unused classes (components, pipes, services and directives) defined in Angular workspace.
61 lines (60 loc) • 2.63 kB
JavaScript
import { stdout } from 'process';
import { RELEVANT_DECORATOR_NAMES } from '../constants.js';
import { print } from '../output.js';
import { hasUsagesByPipeName } from './hasUsagesByPipeName.js';
import { hasUsagesBySelectors } from './hasUsagesBySelectors.js';
import { hasUsagesInTs } from './hasUsagesInTs.js';
import { TemplateService } from './templateService.js';
export function findUnusedClasses(sourceFiles) {
const classes = sourceFiles
.filter(file => !file.getBaseName().includes('.spec.ts'))
.flatMap(file => file.getClasses())
.filter(declaration => getRelevantDecorator(declaration) !== undefined);
const componentClasses = classes
.filter(declaration => { var _a; return ((_a = getRelevantDecorator(declaration)) === null || _a === void 0 ? void 0 : _a.getFullName()) === 'Component'; })
.map(getRelevantDecorator)
.filter(decorator => decorator !== undefined);
const templateService = new TemplateService(componentClasses);
if (stdout.isTTY) {
print(`Found ${classes.length} classes from ${sourceFiles.length} files.\n`);
}
return classes
.filter((declaration, index, { length }) => {
const percentage = Math.round(((index + 1) / length) * 100);
if (stdout.isTTY) {
print(`Analyzing ${index + 1}/${length} (${percentage}%)`, true);
if (index === length - 1)
stdout.write('\n');
}
return !isUsed(declaration, templateService);
})
.map(asResult);
}
function isUsed(declaration, templateService) {
const relevantDecorator = getRelevantDecorator(declaration);
const classType = relevantDecorator.getFullName();
const hasTsUsages = hasUsagesInTs(declaration);
if (hasTsUsages) {
return true;
}
if (classType === 'Component' || classType === 'Directive') {
return hasUsagesBySelectors(relevantDecorator, templateService);
}
if (classType === 'Pipe') {
return hasUsagesByPipeName(relevantDecorator, templateService);
}
return false;
}
function asResult(declaration) {
var _a;
const sourceFile = declaration.getSourceFile();
return {
classType: getRelevantDecorator(declaration).getFullName(),
className: (_a = declaration.getName()) !== null && _a !== void 0 ? _a : '',
fileName: sourceFile.getBaseName(),
directory: sourceFile.getDirectory().getPath().toString(),
};
}
function getRelevantDecorator(classDeclaration) {
return classDeclaration.getDecorator(decorator => RELEVANT_DECORATOR_NAMES.includes(decorator.getFullName()));
}