package krasa.formatter.plugin;
import com.intellij.lang.ImportOptimizer;
import com.intellij.lang.java.JavaImportOptimizer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.psi.*;
import krasa.formatter.exception.FileDoesNotExistsException;
import krasa.formatter.exception.ParsingFailedException;
import krasa.formatter.settings.ProjectSettingsComponent;
import krasa.formatter.settings.Settings;
import krasa.formatter.settings.provider.ImportOrderProvider;
import krasa.formatter.utils.FileUtils;
import org.jetbrains.annotations.NotNull;
/**
* @author Vojtech Krasa
*/
public class EclipseImportOptimizer implements ImportOptimizer {
private static final Logger LOG = Logger.getInstance("#krasa.formatter.plugin.processor.ImportOrderProcessor");
private Notifier notifier = new Notifier();
@NotNull
@Override
public Runnable processFile(final PsiFile file) {
final Runnable intellijRunnable = new JavaImportOptimizer().processFile(file);
if (!(file instanceof PsiJavaFile)) {
return intellijRunnable;
}
if (!isEnabled(file)) {
return intellijRunnable;
}
return new Runnable() {
@Override
public void run() {
intellijRunnable.run();
try {
Settings settings = ProjectSettingsComponent.getSettings(file);
if (isEnabled(settings)) {
optimizeImportsByEclipse((PsiJavaFile) file, settings);
}
} catch (ParsingFailedException e) {
notifier.configurationError(e, file.getProject());
LOG.info("Eclipse Import Optimizer failed", e);
} catch (FileDoesNotExistsException e) {
notifier.configurationError(e, file.getProject());
LOG.info("Eclipse Import Optimizer failed", e);
} catch (IndexNotReadyException e) {
throw e;
} catch (Exception e) {
LOG.error("Eclipse Import Optimizer failed", e);
}
}
};
}
private void optimizeImportsByEclipse(PsiJavaFile psiFile, Settings settings) {
ImportSorterAdapter importSorter = null;
try {
importSorter = getImportSorter(settings);
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(psiFile.getProject());
commitDocument(psiFile, psiDocumentManager);
importSorter.sortImports(psiFile);
commitDocumentAndSave(psiFile, psiDocumentManager);
} catch (ParsingFailedException e) {
throw e;
} catch (IndexNotReadyException e) {
throw e;
} catch (FileDoesNotExistsException e) {
throw e;
} catch (Exception e) {
final PsiImportList oldImportList = (psiFile).getImportList();
StringBuilder stringBuilder = new StringBuilder();
if (oldImportList != null) {
PsiImportStatementBase[] allImportStatements = oldImportList.getAllImportStatements();
for (PsiImportStatementBase allImportStatement : allImportStatements) {
String text = allImportStatement.getText();
stringBuilder.append(text);
}
}
String message = "imports: " + stringBuilder.toString() + ", settings: "
+ (importSorter != null ? importSorter.getImportsOrderAsString() : null);
throw new ImportSorterException(message, e);
}
}
/**
* very strange, https://github.com/krasa/EclipseCodeFormatter/issues/59
*/
private void commitDocument(PsiJavaFile psiFile, PsiDocumentManager psiDocumentManager) {
Document document = psiDocumentManager.getDocument(psiFile);
if (document != null) {
psiDocumentManager.commitDocument(document);
}
}
private void commitDocumentAndSave(PsiJavaFile psiFile, PsiDocumentManager psiDocumentManager) {
Document document = psiDocumentManager.getDocument(psiFile);
if (document != null) {
psiDocumentManager.doPostponedOperationsAndUnblockDocument(document);
psiDocumentManager.commitDocument(document);
FileDocumentManager.getInstance().saveDocument(document);
}
}
protected ImportSorterAdapter getImportSorter(Settings settings) {
if (settings.isImportOrderFromFile()) {
final ImportOrderProvider importOrderProviderFromFile = settings.getImportOrderProvider();
return new ImportSorterAdapter(settings.getImportOrdering(), importOrderProviderFromFile.get());
} else {
return new ImportSorterAdapter(settings.getImportOrdering(), ImportOrderProvider.toList(settings.getImportOrder()));
}
}
@Override
public boolean supports(PsiFile file) {
return FileUtils.isJava(file) && isEnabled(file);
}
private boolean isEnabled(Settings settings) {
return settings.isEnabled() && settings.isEnableJavaFormatting() && settings.isOptimizeImports();
}
private boolean isEnabled(PsiFile file) {
Settings settings = ProjectSettingsComponent.getSettings(file);
return isEnabled(settings);
}
}