/* * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.formatting.FormattingProgressTask; import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { public static final String COMMAND_NAME = CodeInsightBundle.message("process.reformat.code"); private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.ReformatCodeProcessor"); private final Collection myRanges = new ArrayList(); private static final String PROGRESS_TEXT = CodeInsightBundle.message("reformat.progress.common.text"); public ReformatCodeProcessor(Project project, boolean processChangedTextOnly) { super(project, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly); } public ReformatCodeProcessor(Project project, Module module, boolean processChangedTextOnly) { super(project, module, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly); } public ReformatCodeProcessor(Project project, PsiDirectory directory, boolean includeSubdirs, boolean processChangedTextOnly) { super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly); } public ReformatCodeProcessor(Project project, PsiFile file, @Nullable TextRange range, boolean processChangedTextOnly) { super(project, file, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly); if (range != null) { myRanges.add(range); } } public ReformatCodeProcessor(Project project, PsiFile[] files, @Nullable Runnable postRunnable, boolean processChangedTextOnly) { this(project, files, COMMAND_NAME, postRunnable, processChangedTextOnly); } public ReformatCodeProcessor(Project project, PsiFile[] files, String commandName, @Nullable Runnable postRunnable, boolean processChangedTextOnly) { super(project, files, PROGRESS_TEXT, commandName, postRunnable, processChangedTextOnly); } @Override @NotNull protected FutureTask prepareTask(@NotNull final PsiFile file, final boolean processChangedTextOnly) throws IncorrectOperationException { return new FutureTask(new Callable() { @Override public Boolean call() throws Exception { FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false); try { Collection ranges = getRangesToFormat(processChangedTextOnly, file); CodeStyleManager.getInstance(myProject).reformatText(file, ranges); return !FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get(); } catch (FilesTooBigForDiffException e) { LOG.info("Error while calculating changed ranges for: " + file.getVirtualFile(), e); if (!ApplicationManager.getApplication().isUnitTestMode()) { Notification notification = new Notification(ApplicationBundle.message("reformat.changed.text.file.too.big.notification.groupId"), ApplicationBundle.message("reformat.changed.text.file.too.big.notification.title"), ApplicationBundle.message("reformat.changed.text.file.too.big.notification.text", file.getName()), NotificationType.INFORMATION); notification.notify(file.getProject()); } return false; } catch (IncorrectOperationException e) { LOG.error(e); return false; } finally { myRanges.clear(); } } }); } @NotNull private Collection getRangesToFormat(boolean processChangedTextOnly, PsiFile file) throws FilesTooBigForDiffException { if (processChangedTextOnly) { return FormatChangedTextUtil.getChangedTextRanges(myProject, file); } return !myRanges.isEmpty() ? myRanges : ContainerUtil.newArrayList(file.getTextRange()); } }