
de.is24.deadcode4j.DeadCodeFinder Maven / Gradle / Ivy
package de.is24.deadcode4j;
import org.apache.commons.io.DirectoryWalker;
import javax.annotation.Nonnull;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newHashSet;
/**
* The DeadCodeFinder
ties everything together in order to ultimately find dead code.
*
* @since 1.0.0
*/
public class DeadCodeFinder {
private final Set extends Analyzer> analyzers;
public DeadCodeFinder(@Nonnull Set extends Analyzer> analyzers) {
this.analyzers = analyzers;
}
@Nonnull
public DeadCode findDeadCode(@Nonnull Iterable codeRepositories) {
AnalyzedCode analyzedCode = analyzeCode(codeRepositories);
return computeDeadCode(analyzedCode);
}
@Nonnull
private AnalyzedCode analyzeCode(@Nonnull Iterable codeRepositories) {
CodeContext codeContext = new CodeContext();
for (CodeRepository codeRepository : codeRepositories) {
analyzeRepository(codeContext, codeRepository);
}
return codeContext.getAnalyzedCode();
}
@Nonnull
private DeadCode computeDeadCode(@Nonnull AnalyzedCode analyzedCode) {
Collection deadClasses = determineDeadClasses(analyzedCode);
return new DeadCode(analyzedCode.getAnalyzedClasses(), deadClasses);
}
private void analyzeRepository(@Nonnull CodeContext codeContext, @Nonnull CodeRepository codeRepository) {
CodeRepositoryAnalyzer codeRepositoryAnalyzer =
new CodeRepositoryAnalyzer(codeRepository.getFileFilter(), this.analyzers, codeContext);
try {
codeRepositoryAnalyzer.analyze(codeRepository.getDirectory());
} catch (IOException e) {
throw new RuntimeException("Failed to parse files of " + codeRepository + "!", e);
}
}
@Nonnull
Collection determineDeadClasses(@Nonnull AnalyzedCode analyzedCode) {
Set classesInUse = newHashSet();
for (Iterable usedClasses : analyzedCode.getCodeDependencies().values()) {
for (String clazz : usedClasses) {
classesInUse.add(clazz);
}
}
List deadClasses = newArrayList(analyzedCode.getAnalyzedClasses());
deadClasses.removeAll(classesInUse);
return deadClasses;
}
private static class CodeRepositoryAnalyzer extends DirectoryWalker {
private final Iterable extends Analyzer> analyzers;
private final CodeContext codeContext;
public CodeRepositoryAnalyzer(@Nonnull FileFilter fileFilter, @Nonnull Iterable extends Analyzer> analyzers, @Nonnull CodeContext codeContext) {
super(fileFilter, -1);
this.analyzers = analyzers;
this.codeContext = codeContext;
}
public void analyze(File codeRepository) throws IOException {
super.walk(codeRepository, null);
}
@Override
protected void handleFile(File file, int depth, Collection results) throws IOException {
for (Analyzer analyzer : this.analyzers)
analyzer.doAnalysis(this.codeContext, file);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy