import java.util.*;
public class FormatChangedTextUtil {
+ public static final Key<String> TEST_REVISION_CONTENT = Key.create("test.revision.content");
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.FormatChangedTextUtil");
+ protected static final Key<List<TextRange>> CHANGED_RANGES = Key.create("changed.ranges.since.last.revision");
+
+
private FormatChangedTextUtil() {
}
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile != null) {
final Change change = ChangeListManager.getInstance(project).getChange(virtualFile);
- if (change != null && change.getType() == Change.Type.NEW) {
- return true;
- }
+ return change != null;
}
-
- final LineStatusTrackerManagerI manager = LineStatusTrackerManager.getInstance(project);
- if (manager == null) {
- return false;
- }
-
- final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
- if (document == null) {
- return false;
- }
- final LineStatusTracker lineStatusTracker = manager.getLineStatusTracker(document);
- if (lineStatusTracker == null) {
- return false;
- }
- final List<Range> ranges = lineStatusTracker.getRanges();
- return !ranges.isEmpty();
+ return false;
}
/**
@NotNull
public static List<TextRange> getChangedTextRanges(@NotNull Project project, @NotNull PsiFile file) throws FilesTooBigForDiffException {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- List<TextRange> testData = file.getUserData(CHANGED_RANGES);
- if (testData != null) {
- return testData;
- }
- }
-
- Document document = PsiDocumentManager.getInstance(project).getDocument(file);
- if (document == null) return ContainerUtil.emptyList();
-
- List<TextRange> cachedChangedLines = getCachedChangedLines(project, document);
+ List<TextRange> cachedChangedLines = getCachedChangedLines(project, file);
if (cachedChangedLines != null) {
return cachedChangedLines;
}
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ String testContent = file.getUserData(TEST_REVISION_CONTENT);
+ if (testContent != null) {
+ return calculateChangedTextRanges(file.getProject(), file, testContent);
+ }
+ }
+
Change change = ChangeListManager.getInstance(project).getChange(file.getVirtualFile());
if (change == null) {
return ContainerUtilRt.emptyList();
}
String contentFromVcs = getRevisionedContentFrom(change);
- return contentFromVcs != null ? calculateChangedTextRanges(project, file, contentFromVcs)
+ return contentFromVcs != null ? calculateChangedTextRanges(document, contentFromVcs)
: ContainerUtil.<TextRange>emptyList();
}
@Nullable
- private static List<TextRange> getCachedChangedLines(@NotNull Project project, @NotNull PsiFile file) {
- Document document = PsiDocumentManager.getInstance(project).getDocument(file);
- if (document == null) {
- return ContainerUtil.emptyList();
- }
-
+ private static List<TextRange> getCachedChangedLines(@NotNull Project project, @NotNull Document document) {
LineStatusTracker tracker = LineStatusTrackerManager.getInstance(project).getLineStatusTracker(document);
if (tracker != null) {
List<Range> ranges = tracker.getRanges();
}
@NotNull
- private static List<TextRange> calculateChangedTextRanges(@NotNull Project project,
- @NotNull PsiFile file,
- @NotNull String contentFromVcs) throws FilesTooBigForDiffException
+ protected static List<TextRange> calculateChangedTextRanges(@NotNull Document document,
+ @NotNull CharSequence contentFromVcs) throws FilesTooBigForDiffException
{
Document documentFromVcs = ((EditorFactoryImpl)EditorFactory.getInstance()).createDocument(contentFromVcs, true, false);
- Document document = PsiDocumentManager.getInstance(project).getDocument(file);
-
- if (document == null) {
- return ContainerUtil.emptyList();
- }
-
List<Range> changedRanges = new RangesBuilder(document, documentFromVcs).getRanges();
return getChangedTextRanges(document, changedRanges);
}
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.arrangement.Rearranger;
import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine;
-import com.intellij.util.SmartList;
+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.Collection;
-import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public static final String COMMAND_NAME = "Rearrange code";
public static final String PROGRESS_TEXT = "Rearranging code...";
- @Nullable private SelectionModel mySelectionModel;
+ private static final Logger LOG = Logger.getInstance(RearrangeCodeProcessor.class);
+ private SelectionModel mySelectionModel;
public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor) {
super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT);
}
+ public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor, @NotNull SelectionModel model) {
+ super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT);
+ mySelectionModel = model;
+ }
+
+ public RearrangeCodeProcessor(@NotNull PsiFile file,
+ @NotNull SelectionModel selectionModel)
+ {
+ super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false);
++
+ public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor, @NotNull SelectionModel selectionModel) {
+ super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT);
+ mySelectionModel = selectionModel;
+ }
+
+ public RearrangeCodeProcessor(@NotNull Project project,
+ @NotNull PsiFile file,
+ @Nullable SelectionModel selectionModel) {
+ super(project, file, PROGRESS_TEXT, COMMAND_NAME, false);
mySelectionModel = selectionModel;
}
+ public RearrangeCodeProcessor(@NotNull PsiFile file) {
+ super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false);
+ }
+
public RearrangeCodeProcessor(@NotNull Project project,
@NotNull PsiFile[] files,
@NotNull String commandName,
return new FutureTask<Boolean>(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
- Collection<TextRange> ranges = processChangedTextOnly ? FormatChangedTextUtil.getChangedTextRanges(myProject, file)
- : getRangesToFormat(file);
-
- RearrangeCommand rearranger = new RearrangeCommand(myProject, file, COMMAND_NAME, ranges);
- if (rearranger.couldRearrange()) {
- rearranger.run();
+ try {
+ Collection<TextRange> ranges = getRangesToFormat(file, processChangedTextOnly);
+ RearrangeCommand rearranger = new RearrangeCommand(myProject, file, COMMAND_NAME, ranges);
+ if (rearranger.couldRearrange()) {
+ rearranger.run();
+ }
+ return true;
+ }
+ catch (FilesTooBigForDiffException e) {
+ handleFileTooBigException(LOG, e, file);
+ return false;
}
- return true;
}
});
}
- public Collection<TextRange> getRangesToFormat(@NotNull PsiFile file) {
- final List<TextRange> ranges = new SmartList<TextRange>();
- if (mySelectionModel != null && mySelectionModel.hasSelection()) {
- ranges.add(TextRange.create(mySelectionModel.getSelectionStart(), mySelectionModel.getSelectionEnd()));
+ public Collection<TextRange> getRangesToFormat(@NotNull PsiFile file, boolean processChangedTextOnly) throws FilesTooBigForDiffException {
+ if (mySelectionModel != null) {
+ return getSelectedRanges(mySelectionModel);
}
- else {
- ranges.add(TextRange.create(0, file.getTextLength()));
+
+ if (processChangedTextOnly) {
+ return FormatChangedTextUtil.getChangedTextRanges(myProject, file);
}
- return ranges;
+
+ return ContainerUtil.newSmartList(file.getTextRange());
}
}
package com.intellij.codeInsight.actions;
-import com.intellij.application.options.editor.EditorOptions;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.find.impl.FindInProjectUtil;
import com.intellij.formatting.FormattingModelBuilder;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.lang.LanguageFormatting;
-import com.intellij.notification.Notification;
-import com.intellij.notification.NotificationListener;
-import com.intellij.notification.NotificationType;
-import com.intellij.notification.Notifications;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vcs.changes.ChangeListManagerImpl;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.wm.IdeFrame;
-import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
-import javax.swing.*;
-import javax.swing.event.HyperlinkEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
PsiFile file = null;
- final PsiDirectory dir;
+ PsiDirectory dir = null;
boolean hasSelection = false;
if (editor != null){
if (selectedFlags == null)
return;
- final boolean processOnlyChangedText = selectedFlags.isProcessOnlyChangedText();
+ final boolean processOnlyChangedText = selectedFlags.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT;
final boolean shouldOptimizeImports = selectedFlags.isOptimizeImports() && !DumbService.getInstance(project).isDumb();
AbstractLayoutCodeProcessor processor = new ReformatCodeProcessor(project, convertToPsiFiles(files, project), null, processOnlyChangedText);
if (shouldOptimizeImports) {
processor = new OptimizeImportsProcessor(processor);
}
- if (selectedFlags.isRearrangeEntries()) {
+ if (selectedFlags.isRearrangeCode()) {
processor = new RearrangeCodeProcessor(processor);
}
}
return;
}
- else {
- Project projectContext = PlatformDataKeys.PROJECT_CONTEXT.getData(dataContext);
+ else if (PlatformDataKeys.PROJECT_CONTEXT.getData(dataContext) != null || LangDataKeys.MODULE_CONTEXT.getData(dataContext) != null) {
Module moduleContext = LangDataKeys.MODULE_CONTEXT.getData(dataContext);
-
- if (projectContext != null || moduleContext != null) {
- ReformatFilesOptions selectedFlags = getLayoutProjectOptions(project, moduleContext); // module menu - only 2 options available
- if (selectedFlags != null) {
- reformatModule(project, moduleContext, selectedFlags);
- }
- return;
+ ReformatFilesOptions selectedFlags = getLayoutProjectOptions(project, moduleContext);
+ if (selectedFlags != null) {
+ reformatModule(project, moduleContext, selectedFlags);
}
-
+ return;
+ }
+ else if (files != null && files.length == 1) {
+ file = PsiManager.getInstance(project).findFile(files[0]);
+ }
+ else {
PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
if (element == null) return;
if (element instanceof PsiDirectoryContainer) {
}
}
- boolean optimizeImports = ReformatFilesDialog.isOptmizeImportsOptionOn();
- boolean processWholeFile = false;
- boolean processChangedTextOnly = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false);
- boolean rearrangeEntries = getLastSavedRearrangeCbState(project, file);
-
- final boolean showDialog = EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG;
-
- if (file == null && dir == null) return;
- if (file == null) {
+ if (file == null && dir != null) {
DirectoryFormattingOptions options = getDirectoryFormattingOptions(project, dir);
if (options != null) {
reformatDirectory(project, dir, options);
return;
}
- if (showDialog) {
- LayoutCodeOptions selectedFlags = getLayoutCodeOptions(project, file, dir, hasSelection);
- if (selectedFlags == null)
- return;
+ if (file == null || editor == null) return;
- optimizeImports = selectedFlags.isOptimizeImports();
- rearrangeEntries = selectedFlags.isRearrangeEntries();
- processWholeFile = selectedFlags.isProcessWholeFile();
- processChangedTextOnly = selectedFlags.isProcessOnlyChangedText();
-
- if (selectedFlags.isProcessDirectory()) {
- assert dir != null : "File = " + file + ", Element = " + CommonDataKeys.PSI_ELEMENT.getData(dataContext);
- reformatDirectory(project, dir, selectedFlags);
- return;
- }
- }
-
- if (!showDialog && processChangedTextOnly && isChangeNotTrackedForFile(project, file)) {
- processChangedTextOnly = false;
- }
+ LastRunReformatCodeOptionsProvider provider = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance());
+ ReformatCodeRunOptions currentRunOptions = provider.getLastRunOptions(file);
- final TextRange range;
- final boolean processSelectedText = !processWholeFile && hasSelection;
- if (processSelectedText) {
- range = TextRange.create(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd());
+ TextRangeType processingScope = currentRunOptions.getTextRangeType();
+ if (hasSelection) {
+ processingScope = TextRangeType.SELECTED_TEXT;
}
- else{
- range = null;
- }
-
- AbstractLayoutCodeProcessor processor;
- if (optimizeImports && range == null) {
- processor = new OptimizeImportsProcessor(project, file);
- processor = new ReformatCodeProcessor(processor, processChangedTextOnly);
+ else if (processingScope == TextRangeType.VCS_CHANGED_TEXT) {
+ if (isChangeNotTrackedForFile(project, file)) {
+ processingScope = TextRangeType.WHOLE_FILE;
+ }
}
else {
- processor = new ReformatCodeProcessor(project, file, range, !processSelectedText && processChangedTextOnly);
- }
-
- if (rearrangeEntries) {
- if (processSelectedText && editor != null) {
- processor = new RearrangeCodeProcessor(processor, editor.getSelectionModel());
- }
- else {
- processor = new RearrangeCodeProcessor(processor);
- }
+ processingScope = TextRangeType.WHOLE_FILE;
}
- processor.run();
+ currentRunOptions.setProcessingScope(processingScope);
+ new CodeProcessor(file, editor, currentRunOptions).processCode();
}
+
private static boolean isChangeNotTrackedForFile(@NotNull Project project, @NotNull PsiFile file) {
boolean isUnderVcs = VcsUtil.isFileUnderVcs(project, VcsUtil.getFilePath(file.getVirtualFile()));
if (!isUnderVcs) return true;
@NotNull DirectoryFormattingOptions options)
{
AbstractLayoutCodeProcessor processor = new ReformatCodeProcessor(
- project,
- dir,
- options.isIncludeSubdirectories(),
- options.isProcessOnlyChangedText()
+ project, dir, options.isIncludeSubdirectories(), options.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT
);
registerScopeFilter(processor, options.getSearchScope());
if (options.isOptimizeImports()) {
processor = new OptimizeImportsProcessor(processor);
}
- if (options.isRearrangeEntries()) {
+ if (options.isRearrangeCode()) {
processor = new RearrangeCodeProcessor(processor);
}
@NotNull ReformatFilesOptions selectedFlags)
{
boolean shouldOptimizeImports = selectedFlags.isOptimizeImports() && !DumbService.getInstance(project).isDumb();
- boolean processOnlyChangedText = selectedFlags.isProcessOnlyChangedText();
+ boolean processOnlyChangedText = selectedFlags.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT;
AbstractLayoutCodeProcessor processor;
if (moduleContext != null)
processor = new OptimizeImportsProcessor(processor);
}
- if (selectedFlags.isRearrangeEntries()) {
+ if (selectedFlags.isRearrangeCode()) {
processor = new RearrangeCodeProcessor(processor);
}
}
}
- public static void updateShowDialogSetting(LayoutCodeDialog dialog, String title) {
- if (dialog.isDoNotAskMe()) {
- Notifications.Bus.notify(new Notification("Reformat Code", title,
- "<html>You can re-enable the dialog on the <a href=''>IDE Settings -> Editor</a> pane</html>",
- NotificationType.INFORMATION, new NotificationListener() {
- @Override
- public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent e) {
- if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
- final ShowSettingsUtil util = ShowSettingsUtil.getInstance();
- IdeFrame ideFrame = WindowManagerEx.getInstanceEx().findFrameFor(null);
- util.editConfigurable((JFrame)ideFrame, new EditorOptions());
- }
- }
- }));
- }
- }
-
public static PsiFile[] convertToPsiFiles(final VirtualFile[] files,Project project) {
final PsiManager manager = PsiManager.getInstance(project);
final ArrayList<PsiFile> result = new ArrayList<PsiFile>();
return dialog;
}
- @Nullable
- private static LayoutCodeOptions getLayoutCodeOptions(@NotNull Project project,
- @Nullable PsiFile file,
- @Nullable PsiDirectory dir,
- boolean hasSelection) {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- return (LayoutCodeOptions)myTestOptions;
- }
- LayoutCodeDialog dialog = new LayoutCodeDialog(project, CodeInsightBundle.message("process.reformat.code"),
- file, dir, hasSelection ? Boolean.TRUE : Boolean.FALSE, HELP_ID);
- if (!dialog.showAndGet()) {
- return null;
- }
- EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG = !dialog.isDoNotAskMe();
- updateShowDialogSetting(dialog, "\"Reformat Code\" dialog disabled");
- return dialog;
- }
-
- public static boolean getLastSavedRearrangeCbState(@NotNull Project project, @Nullable PsiFile file) {
- if (file != null) {
- return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project, file.getLanguage());
- }
- return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project);
- }
-
@TestOnly
protected static void setTestOptions(ReformatFilesOptions options) {
myTestOptions = options;
}
return true;
}
-
- //public LayoutCodeOptions getLastRunReformatCodeOptions() {
- // if (ApplicationManager.getApplication().isUnitTestMode()) {
- // return myTestOptions;
- // }
- // return new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance());
- //}
}