package org.infernus.idea.checkstyle.service.cmd;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.puppycrawl.tools.checkstyle.Checker;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import org.infernus.idea.checkstyle.checker.Problem;
import org.infernus.idea.checkstyle.checker.ScannableFile;
import org.infernus.idea.checkstyle.checks.CheckFactory;
import org.infernus.idea.checkstyle.csapi.CheckstyleInternalObject;
import org.infernus.idea.checkstyle.exception.CheckstyleVersionMixException;
import org.infernus.idea.checkstyle.service.CheckStyleAuditListener;
import org.infernus.idea.checkstyle.service.entities.CheckerWithConfig;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.*;
import static java.util.stream.Collectors.toList;
public class OpScan implements CheckstyleCommand<Map<PsiFile, List<Problem>>> {
private final CheckerWithConfig checkerWithConfig;
private final List<ScannableFile> scannableFiles;
private final boolean suppressErrors;
private final int tabWidth;
private final Optional<String> baseDir;
public OpScan(@NotNull final CheckstyleInternalObject checkerWithConfig,
@NotNull final List<ScannableFile> scannableFiles,
final boolean suppressErrors,
final int tabWidth,
final Optional<String> baseDir) {
if (!(checkerWithConfig instanceof CheckerWithConfig)) {
throw new CheckstyleVersionMixException(CheckerWithConfig.class, checkerWithConfig);
}
this.checkerWithConfig = (CheckerWithConfig) checkerWithConfig;
this.scannableFiles = scannableFiles;
this.suppressErrors = suppressErrors;
this.tabWidth = tabWidth;
this.baseDir = baseDir;
}
@NotNull
@Override
public Map<PsiFile, List<Problem>> execute(@NotNull final Project project) throws CheckstyleException {
if (scannableFiles.isEmpty()) {
return Collections.emptyMap();
}
return processAndAudit(filesOf(scannableFiles), createListener(mapFilesToElements(scannableFiles), project))
.getProblems();
}
private Map<String, PsiFile> mapFilesToElements(final List<ScannableFile> filesToScan) {
final Map<String, PsiFile> filePathsToElements = new HashMap<>();
for (ScannableFile scannableFile : filesToScan) {
filePathsToElements.put(scannableFile.getAbsolutePath(), scannableFile.getPsiFile());
}
return filePathsToElements;
}
private List<File> filesOf(final List<ScannableFile> filesToScan) {
return filesToScan.stream().map(ScannableFile::getFile).collect(toList());
}
private CheckStyleAuditListener processAndAudit(final List<File> files,
final CheckStyleAuditListener auditListener)
throws CheckstyleException {
final Checker checker = checkerWithConfig.getChecker();
synchronized (checkerWithConfig.getChecker()) {
checker.addListener(auditListener);
try {
checker.process(files);
} finally {
checker.removeListener(auditListener);
}
}
return auditListener;
}
private CheckStyleAuditListener createListener(final Map<String, PsiFile> filesToScan,
final Project project) {
return new CheckStyleAuditListener(filesToScan, suppressErrors, tabWidth, baseDir,
CheckFactory.getChecks(project, checkerWithConfig));
}
}