--- /dev/null
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class Test {
+
+ public static void main(String[] args) {
+ List<String> list = new ArrayList<String>();
+ int a = 3;
+
+int b = 3;
+ }
+
+}
--- /dev/null
+import java.lang.String;
+import java.util.List;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.HashSet;
+
+
+public class Test {
+
+ public static void main(String[] args) {
+<selection>List<String> list = new ArrayList<String>();
+int a = 3;</selection>
+
+int b = 3;
+ }
+
+}
--- /dev/null
+public class Test {
+
+ int a = 2;
+ int b = 3;
+
+
+ public void run() {
+ int myFirst = 12;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+public class Test {
+
+ <selection>int a = 2;
+ int b = 3;</selection>
+
+
+ public void run() {
+ int myFirst = 12;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class Test {
+
+ public static void main(String[] args) {
+ List<String> list = new ArrayList<String>();
+ int a = 3;
+
+int b = 3;
+ }
+
+
+ public void test() {
+ }
+
+}
--- /dev/null
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
+
+
+public class Test {
+
+ public static void main(String[] args) {
+<selection> List<String> list = new ArrayList<String>();
+int a = 3;<caret></selection>
+
+int b = 3;
+ }
+
+
+<selection><caret>
+public void test() {
+}</selection>
+
+}
--- /dev/null
+public class Test {
+
+ int a = 3;
+ int b = 12;
+
+long t = 12;
+
+ public void test() {
+
+ int a = 3;
+ int b = 4;
+ }
+
+ int rest = -12;
+
+ public void run() {
+ }
+
+}
\ No newline at end of file
--- /dev/null
+public class Test {
+
+<selection> int a = 3;
+ <caret>int b = 12;</selection>
+
+long t = 12;
+
+ public void test() {
+
+<selection> int a = 3;
+ <caret>int b = 4;</selection>
+ }
+
+ int rest = -12;
+
+<selection>public void run() {}<caret></selection>
+
+}
\ No newline at end of file
--- /dev/null
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class Test {
+
+ public static void main(String[] args) {
+ List<String> list = new ArrayList<String>();
+ }
+
+}
--- /dev/null
+import java.lang.String;
+import java.util.List;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.HashSet;
+
+
+public class Test {
+
+ public static void main(String[] args) {
+List<String> list = new ArrayList<String>();
+ }
+
+}
--- /dev/null
+public class Test {
+
+ public int a = 3;
+
+
+ public void test() {
+ int c = 3;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+public class Test {
+
+ public int a = 3;
+
+
+ public void test() {
+ int c = 3;
+ }
+
+}
\ No newline at end of file
}
}
-class MockReformatFileSettings implements LayoutCodeOptions {
- private boolean myProcessWholeFile;
- private boolean myProcessDirectories;
- private boolean myRearrange;
- private boolean myIncludeSubdirs;
+class MockReformatFileSettings implements ReformatFilesOptions {
private boolean myOptimizeImports;
- private boolean myProcessOnlyChangedText;
- private boolean myIsOK = true;
+ private boolean myIncludeSubdirs;
@Nullable
@Override
}
@Override
- public boolean isProcessWholeFile() {
- return myProcessWholeFile;
- }
-
- MockReformatFileSettings setProcessWholeFile(boolean processWholeFile) {
- myProcessWholeFile = processWholeFile;
- return this;
+ public TextRangeType getTextRangeType() {
+ return TextRangeType.WHOLE_FILE;
}
@Override
- public boolean isProcessDirectory() {
- return myProcessDirectories;
- }
-
- MockReformatFileSettings setProcessDirectory(boolean processDirectories) {
- myProcessDirectories = processDirectories;
- return this;
- }
-
- @Override
- public boolean isRearrangeEntries() {
- return myRearrange;
- }
-
- @Override
- public boolean isIncludeSubdirectories() {
- return myIncludeSubdirs;
+ public boolean isRearrangeCode() {
+ return false;
}
@Override
return this;
}
- @Override
- public boolean isProcessOnlyChangedText() {
- return myProcessOnlyChangedText;
- }
-
- @NotNull
- MockReformatFileSettings setProcessOnlyChangedText(boolean processOnlyChangedText) {
- myProcessOnlyChangedText = processOnlyChangedText;
- return this;
- }
-
- @NotNull
- MockReformatFileSettings setRearrange(boolean rearrange) {
- myRearrange = rearrange;
- return this;
- }
-
@NotNull
MockReformatFileSettings setIncludeSubdirs(boolean includeSubdirs) {
myIncludeSubdirs = includeSubdirs;
--- /dev/null
+/*
+ * Copyright 2000-2014 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.JavaTestUtil;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.CaretModel;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+
+import java.util.List;
+
+import static com.intellij.codeInsight.actions.TextRangeType.*;
+
+public class MultiActionCodeProcessorTest extends LightPlatformCodeInsightFixtureTestCase {
+
+ @Override
+ protected String getTestDataPath() {
+ return JavaTestUtil.getJavaTestDataPath() + "/actions/codeProcessor/";
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ myFixture.getFile().putUserData(FormatChangedTextUtil.CHANGED_RANGES, null);
+ super.tearDown();
+ }
+
+ public void doTest(LayoutCodeOptions options) {
+ myFixture.configureByFile(getTestDataPath() + getTestName(true) + "_before.java");
+ CodeProcessor processor = new CodeProcessor(myFixture.getFile(), myFixture.getEditor(), options);
+
+ if (options.getTextRangeType() == VCS_CHANGED_TEXT) {
+ CaretModel model = myFixture.getEditor().getCaretModel();
+ List<TextRange> ranges = ContainerUtil.mapNotNull(model.getAllCarets(), new Function<Caret, TextRange>() {
+ @Override
+ public TextRange fun(Caret caret) {
+ if (caret.hasSelection()) {
+ return new TextRange(caret.getSelectionStart(), caret.getSelectionEnd());
+ }
+ return null;
+ }
+ });
+ myFixture.getFile().putUserData(FormatChangedTextUtil.CHANGED_RANGES, ranges);
+ }
+
+ processor.processCode();
+ myFixture.checkResultByFile(getTestName(true) + "_after.java");
+ }
+
+ public void testSelectionReformat() {
+ doTest(new ReformatCodeRunOptions(SELECTED_TEXT));
+ }
+
+ public void testWholeFileReformat() {
+ doTest(new ReformatCodeRunOptions(WHOLE_FILE));
+ }
+
+ public void testVcsChangedTextReformat() {
+ doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT));
+ }
+
+ public void testWholeFileReformatAndOptimize() {
+ doTest(new ReformatCodeRunOptions(WHOLE_FILE).setOptimizeImports(true));
+ }
+
+ public void testSelectedTextAndOptimizeImports() {
+ doTest(new ReformatCodeRunOptions(SELECTED_TEXT).setOptimizeImports(true));
+ }
+
+ //public void testVcsChangedTextReformatAndOptimize() {
+ // doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT).setOptimizeImports(true));
+ //}
+}
public void testReformatAndOptimizeMultipleFiles() throws IOException {
List<PsiFile> files = createTestFiles(getTempRootDirectory(), classNames);
- injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true));
+
+ //todo mock this guy
+ //LastRunReformatCodeOptionsProvider provider = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance());
performReformatActionOnSelectedFiles(files);
checkFormationAndImportsOptimizationFor(files);
}
- public void testReformatSingleSelectedFile() throws IOException {
- List<PsiFile> files = createTestFiles(getTempRootDirectory(), classNames);
- PsiFile fileToReformat = files.get(0);
- List<PsiFile> shouldNotBeFormatted = files.subList(1, files.size());
- injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true));
-
- performReformatActionOnSelectedFile(fileToReformat);
-
- checkFormationAndImportsOptimizationFor(Arrays.asList(fileToReformat));
- checkNoProcessingWasPerformedOn(shouldNotBeFormatted);
+ public void testReformatSingleSelected_FileWithoutEditor() throws IOException {
+ //todo fill
}
public void testReformatAndOptimizeFileFromEditor() throws IOException {
checkNoProcessingWasPerformedOn(noProcessing);
}
- public void testOptimizeAndReformatAllFilesInDirectoryIncludeSubdirs() throws IOException {
- TestFileStructure fileStructure = getThreeLevelDirectoryStructure();
- injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true).setProcessDirectory(true).setIncludeSubdirs(true));
- PsiFile fileInEditor = fileStructure.getFilesAtLevel(2).get(0);
- List<PsiFile> shouldNotBeFormatted = fileStructure.getFilesAtLevel(1);
-
- performReformatActionOnFileInEditor(fileInEditor);
-
- checkFormationAndImportsOptimizationFor(fileStructure.getFilesAtLevel(2), fileStructure.getFilesAtLevel(3));
- checkNoProcessingWasPerformedOn(shouldNotBeFormatted);
- }
-
- public void testOptimizeAndReformatAllFilesInDirectoryExcludeSubdirs() throws IOException {
- TestFileStructure fileStructure = getThreeLevelDirectoryStructure();
- injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true).setIncludeSubdirs(false));
-
- performReformatActionOnSelectedFiles(fileStructure.getFilesAtLevel(2));
-
- checkFormationAndImportsOptimizationFor(fileStructure.getFilesAtLevel(2));
- checkNoProcessingWasPerformedOn(fileStructure.getFilesAtLevel(1), fileStructure.getFilesAtLevel(3));
+ public void testOptimizeAndReformat_AllFilesInDirectoryIncludeSubdirs() throws IOException {
+ //todo create tests for AbstractLayoutCodeProcessor
}
public void testOptimizeAndReformatInModule() throws IOException {
checkFormationAndImportsOptimizationFor(files);
}
- private TestFileStructure getThreeLevelDirectoryStructure() throws IOException {
- TestFileStructure fileStructure = new TestFileStructure(getModule(), getTempRootDirectory());
- fileStructure.createDirectoryAndMakeItCurrent("dir");
- addFilesToCurrentDirectory(fileStructure);
- fileStructure.createDirectoryAndMakeItCurrent("innerDir");
- addFilesToCurrentDirectory(fileStructure);
- fileStructure.createDirectoryAndMakeItCurrent("innerInnerDir");
- addFilesToCurrentDirectory(fileStructure);
- return fileStructure;
- }
- private void addFilesToCurrentDirectory(TestFileStructure fileStructure) throws IOException {
- for (int i = 0; i < 5; i++) {
- String className = "Test" + i;
- fileStructure.addTestFile("Test" + i + ".java", getUntouchedJavaSourceForTotalProcessing(className));
- }
- }
}
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
if (file == null) {
return;
}
- new RearrangeCodeProcessor(project, file, editor.getSelectionModel()).run();
+
+ SelectionModel model = editor.getSelectionModel();
+ if (model.hasSelection()) {
+ new RearrangeCodeProcessor(file, model).run();
+ }
+ else {
+ new RearrangeCodeProcessor(file).run();
+ }
}
}
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.lang.LanguageFormatting;
+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.application.ModalityState;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.roots.GeneratedSourcesFilter;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ex.MessagesEx;
+import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiBundle;
import com.intellij.psi.PsiDirectory;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SequentialModalProgressTask;
import com.intellij.util.SequentialTask;
+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.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
private final String myProgressText;
private final String myCommandName;
- private final Runnable myPostRunnable;
+ private Runnable myPostRunnable;
private boolean myProcessChangedTextOnly;
protected AbstractLayoutCodeProcessor myPreviousCodeProcessor;
return list;
}
+ public void setPostRunnable(Runnable postRunnable) {
+ myPostRunnable = postRunnable;
+ }
+
@Nullable
private FutureTask<Boolean> getPreviousProcessorTask(@NotNull PsiFile file, boolean processChangedTextOnly) {
return myPreviousCodeProcessor != null ? myPreviousCodeProcessor.preprocessFile(file, processChangedTextOnly)
return true;
}
+
+ protected static List<TextRange> getSelectedRanges(@NotNull SelectionModel selectionModel) {
+ final List<TextRange> ranges = new SmartList<TextRange>();
+ if (selectionModel.hasSelection()) {
+ TextRange range = TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
+ ranges.add(range);
+ }
+ else if (selectionModel.hasBlockSelection()) {
+ int[] starts = selectionModel.getBlockSelectionStarts();
+ int[] ends = selectionModel.getBlockSelectionEnds();
+ for (int i = 0; i < starts.length; i++) {
+ ranges.add(TextRange.create(starts[i], ends[i]));
+ }
+ }
+
+ return ranges;
+ }
+
+ protected void handleFileTooBigException(Logger logger, FilesTooBigForDiffException e, @NotNull PsiFile file) {
+ logger.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());
+ }
+ }
}
--- /dev/null
+/*
+ * Copyright 2000-2014 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.hint.HintManager;
+import com.intellij.codeInsight.hint.HintManagerImpl;
+import com.intellij.codeInsight.hint.HintUtil;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.keymap.KeymapUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.ui.LightweightHint;
+import com.intellij.util.diff.FilesTooBigForDiffException;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.List;
+
+import static com.intellij.codeInsight.actions.TextRangeType.*;
+
+class CodeProcessor {
+ private final Editor myEditor;
+
+ private final boolean myShouldOptimizeImports;
+ private final boolean myShouldRearrangeCode;
+ private final boolean myProcessSelectedText;
+ private final boolean myProcessChangesTextOnly;
+ private final boolean myShouldNotify;
+
+ private final Project myProject;
+ private final PsiFile myFile;
+ private final TextRangeType myProcessingType;
+
+ public CodeProcessor(PsiFile file,
+ Editor editor,
+ LayoutCodeOptions runOptions)
+ {
+ myFile = file;
+ myProject = file.getProject();
+ myEditor = editor;
+
+ myProcessingType = runOptions.getTextRangeType();
+
+ myShouldOptimizeImports = runOptions.isOptimizeImports();
+ myShouldRearrangeCode = runOptions.isRearrangeCode();
+ myProcessSelectedText = myEditor != null && runOptions.getTextRangeType() == SELECTED_TEXT;
+ myProcessChangesTextOnly = runOptions.getTextRangeType() == VCS_CHANGED_TEXT;
+
+ myShouldNotify = myEditor != null && !myProcessSelectedText;
+ }
+
+ public void processCode() {
+ AbstractLayoutCodeProcessor processor = null;
+ if (myShouldOptimizeImports) {
+ processor = new OptimizeImportsProcessor(myProject, myFile);
+ }
+
+ if (processor != null) {
+ if (myProcessSelectedText) {
+ processor = new ReformatCodeProcessor(processor, myEditor.getSelectionModel());
+ }
+ else {
+ processor = new ReformatCodeProcessor(processor, myProcessChangesTextOnly);
+ }
+ }
+ else {
+ if (myProcessSelectedText) {
+ processor = new ReformatCodeProcessor(myFile, myEditor.getSelectionModel());
+ }
+ else {
+ processor = new ReformatCodeProcessor(myFile, myProcessChangesTextOnly);
+ }
+ }
+
+ if (myShouldRearrangeCode) {
+ if (myProcessSelectedText) {
+ processor = new RearrangeCodeProcessor(processor, myEditor.getSelectionModel());
+ }
+ else {
+ processor = new RearrangeCodeProcessor(processor);
+ }
+ }
+
+ if (myShouldNotify) {
+ Document document = PsiDocumentManager.getInstance(myProject).getDocument(myFile);
+ if (document != null) {
+ processor.setPostRunnable(getNotificationCallBack(document));
+ }
+ }
+
+ processor.run();
+ }
+
+ private Runnable getNotificationCallBack(@NotNull final Document document) {
+ final CharSequence textBeforeChange = document.getImmutableCharSequence();
+ final Runnable calculateChangesAndNotify = new Runnable() {
+ @Override
+ public void run() {
+ final String info = prepareMessage(document, textBeforeChange);
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (!myEditor.isDisposed() && myEditor.getComponent().isShowing()) {
+ showHint(myEditor, info);
+ }
+ }
+ });
+ }
+ };
+
+ return new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().executeOnPooledThread(calculateChangesAndNotify);
+ }
+ };
+ }
+
+ private static int getProcessedLinesNumber(final Document document, final CharSequence before) {
+ int totalLinesProcessed = 0;
+ try {
+ List<TextRange> ranges = FormatChangedTextUtil.calculateChangedTextRanges(document, before);
+ for (TextRange range : ranges) {
+ int lineStartNumber = document.getLineNumber(range.getStartOffset());
+ int lineEndNumber = document.getLineNumber(range.getEndOffset());
+
+ totalLinesProcessed += lineEndNumber - lineStartNumber + 1;
+ }
+ }
+ catch (FilesTooBigForDiffException e) {
+ return -1;
+ }
+ return totalLinesProcessed;
+ }
+
+ @NotNull
+ private String prepareMessage(@NotNull Document document, @NotNull CharSequence textBeforeChange) {
+ int totalLinesProcessed = getProcessedLinesNumber(document, textBeforeChange);
+
+ String linesInfo = "";
+ if (totalLinesProcessed >= 0) {
+ linesInfo = "Changed " + totalLinesProcessed + " lines";
+ }
+
+ String scopeInfo = myProcessingType == VCS_CHANGED_TEXT ? ", processed only changed lines since last revision" : null;
+ String actionsInfo = "Performed: formatting";
+ if (myShouldOptimizeImports) {
+ actionsInfo += ", import optimization";
+ }
+ if (myShouldRearrangeCode) {
+ actionsInfo += " and code rearrangement";
+ }
+
+ String shortcutInfo = "Show reformat dialog: " + KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile"));
+
+ String info = linesInfo;
+ if (scopeInfo != null) {
+ info += scopeInfo;
+ }
+ info += "\n";
+ info += actionsInfo + "\n";
+ info += shortcutInfo;
+
+ return info;
+ }
+
+ private static void showHint(@NotNull Editor editor, @NotNull String info) {
+ JComponent component = HintUtil.createInformationLabel(info);
+ LightweightHint hint = new LightweightHint(component);
+ HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER,
+ HintManager.HIDE_BY_ANY_KEY |
+ HintManager.HIDE_BY_TEXT_CHANGE |
+ HintManager.HIDE_BY_SCROLLING,
+ 0, false);
+ }
+}
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;
}
/**
}
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);
}
--- /dev/null
+/*
+ * Copyright 2000-2014 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.ide.util.PropertiesComponent;
+import com.intellij.lang.Language;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+public class LastRunReformatCodeOptionsProvider {
+
+ private static final String OPTIMIZE_IMPORTS_KEY = "LayoutCode.optimizeImports";
+ private static final String REARRANGE_ENTRIES_KEY = "LayoutCode.rearrangeEntries";
+ private static final String PROCESS_CHANGED_TEXT_KEY = "LayoutCode.processChangedText";
+
+ private final PropertiesComponent myPropertiesComponent;
+
+ public LastRunReformatCodeOptionsProvider(@NotNull PropertiesComponent propertiesComponent) {
+ myPropertiesComponent = propertiesComponent;
+ }
+
+ public ReformatCodeRunOptions getLastRunOptions(@NotNull PsiFile file) {
+ Language language = file.getLanguage();
+
+ ReformatCodeRunOptions settings = new ReformatCodeRunOptions(getLastTextRangeType());
+ settings.setOptimizeImports(getLastOptimizeImports());
+ settings.setRearrangeCode(isRearrangeCode(language));
+
+ return settings;
+ }
+
+ public void saveRearrangeState(@NotNull Language language, boolean value) {
+ String key = getRearrangeCodeKeyFor(language);
+ myPropertiesComponent.setValue(key, Boolean.toString(value));
+ }
+
+ public void saveOptimizeImportsState(boolean value) {
+ String optimizeImports = Boolean.toString(value);
+ myPropertiesComponent.setValue(OPTIMIZE_IMPORTS_KEY, optimizeImports);
+ }
+
+ public boolean getLastOptimizeImports() {
+ return myPropertiesComponent.getBoolean(OPTIMIZE_IMPORTS_KEY, false);
+ }
+
+ public TextRangeType getLastTextRangeType() {
+ return myPropertiesComponent.getBoolean(PROCESS_CHANGED_TEXT_KEY, false) ? TextRangeType.VCS_CHANGED_TEXT : TextRangeType.WHOLE_FILE;
+ }
+
+ public void saveProcessVcsChangedTextState(boolean value) {
+ String processOnlyVcsChangedText = Boolean.toString(value);
+ myPropertiesComponent.setValue(PROCESS_CHANGED_TEXT_KEY, processOnlyVcsChangedText);
+ }
+
+ public void saveRearrangeCodeState(boolean value) {
+ myPropertiesComponent.setValue(REARRANGE_ENTRIES_KEY, Boolean.toString(value));
+ }
+
+ public boolean getLastRearrangeCode() {
+ return myPropertiesComponent.getBoolean(REARRANGE_ENTRIES_KEY, false);
+ }
+
+ public boolean isRearrangeCode(@NotNull Language language) {
+ String key = getRearrangeCodeKeyFor(language);
+ return myPropertiesComponent.getBoolean(key, false);
+ }
+
+ private static String getRearrangeCodeKeyFor(@NotNull Language language) {
+ return REARRANGE_ENTRIES_KEY + language.getDisplayName();
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.codeInsight.actions.LayoutCodeDialog">
+ <grid id="27dc6" binding="myButtonsPanel" layout-manager="GridLayoutManager" row-count="3" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="472" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <vspacer id="52898">
+ <constraints>
+ <grid row="2" column="3" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <component id="8ca39" class="com.intellij.openapi.ui.Splitter">
+ <constraints>
+ <grid row="1" column="4" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <grid id="91e0a" binding="myActionsPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="9d93" class="javax.swing.JCheckBox" binding="myOptimizeImportsCb" default-binding="true">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <text value="&Optimize imports"/>
+ </properties>
+ </component>
+ <vspacer id="2d364">
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <component id="a291" class="javax.swing.JCheckBox" binding="myRearrangeCodeCb" default-binding="true">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <text value="Rearra&nge code"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="b1a5c" binding="myScopePanel" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="cea7f" class="javax.swing.JRadioButton" binding="myOnlyVCSChangedTextRb" default-binding="true">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <text value="Only &VCS changed text"/>
+ </properties>
+ </component>
+ <hspacer id="6a094">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ <vspacer id="467fa">
+ <constraints>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <component id="27301" class="javax.swing.JRadioButton" binding="mySelectedTextRadioButton" default-binding="true">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <text value="&Selected text"/>
+ </properties>
+ </component>
+ <component id="2eea6" class="javax.swing.JRadioButton" binding="myWholeFileRadioButton" default-binding="true">
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <text value="&Whole file"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <component id="38fdd" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Scope:"/>
+ </properties>
+ </component>
+ <component id="1fda7" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Optional:"/>
+ </properties>
+ </component>
+ <hspacer id="b6b1d">
+ <constraints>
+ <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
+ <buttonGroups>
+ <group name="myGroup1">
+ <member id="e5942"/>
+ <member id="4a767"/>
+ <member id="2b374"/>
+ <member id="27301"/>
+ <member id="2eea6"/>
+ <member id="cea7f"/>
+ </group>
+ </buttonGroups>
+</form>
package com.intellij.codeInsight.actions;
-import com.intellij.CommonBundle;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.lang.LanguageImportStatements;
-import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.arrangement.Rearranger;
-import com.intellij.psi.search.SearchScope;
+import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions {
+public class LayoutCodeDialog extends DialogWrapper {
@NotNull private final Project myProject;
- @Nullable private final PsiFile myFile;
- @Nullable private final PsiDirectory myDirectory;
- private final Boolean myTextSelected;
-
- private JRadioButton myRbFile;
- private JRadioButton myRbSelectedText;
- private JRadioButton myRbDirectory;
- private JCheckBox myCbIncludeSubdirs;
- private JCheckBox myCbOptimizeImports;
- private JCheckBox myCbArrangeEntries;
- private JCheckBox myCbOnlyVcsChangedRegions;
- private JCheckBox myDoNotAskMeCheckBox;
+ @NotNull private final PsiFile myFile;
+
+ private final boolean myTextSelected;
private final String myHelpId;
- @Nullable private CommonCodeStyleSettings myCommonSettings;
- private boolean myRearrangeAlwaysEnabled;
+ private final LastRunReformatCodeOptionsProvider myLastRunOptions;
+
+ private JPanel myButtonsPanel;
- private final boolean myOptimizeImportProcessorsForFileLanguageExists;
- private final boolean myRearrangerProcessorsForFileLanguageExists;
- private final boolean myFileHasChanges;
+ private JCheckBox myOptimizeImportsCb;
+ private JCheckBox myRearrangeCodeCb;
- private boolean myOptimizeImportsSelected;
- private boolean myFormatOnlyVCSChangedRegionsSelected;
- private boolean myDoNotShowDialogSelected;
- private boolean myRearrangeEntriesSelected;
+ private JRadioButton myOnlyVCSChangedTextRb;
+ private JRadioButton mySelectedTextRadioButton;
+ private JRadioButton myWholeFileRadioButton;
+ private JPanel myActionsPanel;
+ private JPanel myScopePanel;
- public LayoutCodeDialog(@NotNull Project project,
- @NotNull String title,
- @Nullable PsiFile file,
- @Nullable PsiDirectory directory,
- Boolean isTextSelected,
+ private LayoutCodeOptions myRunOptions;
+
+ public LayoutCodeDialog(@NotNull Project project,
+ @NotNull PsiFile file,
+ boolean textSelected,
final String helpId) {
super(project, true);
myFile = file;
myProject = project;
- myDirectory = directory;
- myTextSelected = isTextSelected;
-
- myOptimizeImportProcessorsForFileLanguageExists = myFile != null && !LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty();
- myRearrangerProcessorsForFileLanguageExists = myFile != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null;
- myFileHasChanges = myFile != null && FormatChangedTextUtil.hasChanges(myFile);
+ myTextSelected = textSelected;
+ myHelpId = helpId;
- if (myFile != null) myCommonSettings = CodeStyleSettingsManager.getSettings(myProject).getCommonSettings(myFile.getLanguage());
- myRearrangeAlwaysEnabled = myCommonSettings != null
- && myCommonSettings.isForceArrangeMenuAvailable()
- && myCommonSettings.FORCE_REARRANGE_MODE == CommonCodeStyleSettings.REARRANGE_ALWAYS;
+ myLastRunOptions = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance());
+ myRunOptions = createOptionsBundledOnDialog();
setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text"));
- setTitle(title);
+ setTitle("Reformat File: " + file.getName());
+
init();
- myHelpId = helpId;
}
- @Override
protected void init() {
super.init();
- loadCbsStates();
- setUpInitialSelection();
+ setUpActions();
+ setUpTextRangeMode();
+ }
- myRbFile.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- saveEnabledCbsSelectedState();
- setUpCbsStateForFileFormatting();
- }
- });
- myRbDirectory.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- saveEnabledCbsSelectedState();
- setUpCbsStatesForDirectoryFormatting();
- }
- });
+ private void setUpTextRangeMode() {
+ mySelectedTextRadioButton.setEnabled(myTextSelected);
+ if (!myTextSelected) {
+ mySelectedTextRadioButton.setToolTipText("No text selected in editor");
+ }
- myRbSelectedText.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- saveEnabledCbsSelectedState();
- setUpCbsStatesForSelectedTextFormatting();
+ final boolean fileHasChanges = FormatChangedTextUtil.hasChanges(myFile);
+ if (myFile.getVirtualFile() instanceof LightVirtualFile) {
+ myOnlyVCSChangedTextRb.setVisible(false);
+ }
+ else {
+ myOnlyVCSChangedTextRb.setEnabled(fileHasChanges);
+ if (!fileHasChanges) {
+ String hint = getChangesNotAvailableHint();
+ if (hint != null) myOnlyVCSChangedTextRb.setToolTipText(hint);
}
- });
- }
+ }
- private void setUpInitialSelection() {
- if (myTextSelected == Boolean.TRUE) {
- myRbSelectedText.setSelected(true);
- setUpCbsStatesForSelectedTextFormatting();
+ myWholeFileRadioButton.setEnabled(true);
+
+ if (myTextSelected) {
+ mySelectedTextRadioButton.setSelected(true);
}
else {
- if (myFile != null) {
- myRbFile.setSelected(true);
- setUpCbsStateForFileFormatting();
+ boolean lastRunProcessedChangedText = myLastRunOptions.getLastTextRangeType() == TextRangeType.VCS_CHANGED_TEXT;
+ if (lastRunProcessedChangedText && fileHasChanges) {
+ myOnlyVCSChangedTextRb.setSelected(true);
}
else {
- myRbDirectory.setSelected(true);
- setUpCbsStatesForDirectoryFormatting();
+ myWholeFileRadioButton.setSelected(true);
}
}
- myCbIncludeSubdirs.setSelected(true);
- }
-
- private void loadCbsStates() {
- myOptimizeImportsSelected = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false);
- myRearrangeEntriesSelected = myRearrangeAlwaysEnabled || ReformatCodeAction.getLastSavedRearrangeCbState(myProject, myFile);
- myFormatOnlyVCSChangedRegionsSelected = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false);
}
- private void saveEnabledCbsSelectedState() {
- if (myCbArrangeEntries.isEnabled()) {
- myRearrangeEntriesSelected = myCbArrangeEntries.isSelected();
- }
- if (myCbOptimizeImports.isEnabled()) {
- myOptimizeImportsSelected = myCbOptimizeImports.isSelected();
- }
- if (myCbOnlyVcsChangedRegions.isEnabled()) {
- myFormatOnlyVCSChangedRegionsSelected = myCbOnlyVcsChangedRegions.isSelected();
- }
- if (myDoNotAskMeCheckBox.isEnabled()) {
- myDoNotShowDialogSelected = myDoNotAskMeCheckBox.isSelected();
+ private void setUpActions() {
+ boolean canOptimizeImports = !LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty();
+ myOptimizeImportsCb.setVisible(canOptimizeImports);
+ if (canOptimizeImports) {
+ myOptimizeImportsCb.setSelected(myLastRunOptions.getLastOptimizeImports());
}
- }
-
- private void setUpCbsStateForFileFormatting() {
- myCbOptimizeImports.setEnabled(myOptimizeImportProcessorsForFileLanguageExists);
- myCbOptimizeImports.setSelected(myOptimizeImportProcessorsForFileLanguageExists && myOptimizeImportsSelected);
-
- myCbArrangeEntries.setEnabled(myRearrangerProcessorsForFileLanguageExists);
- myCbArrangeEntries.setSelected(myRearrangerProcessorsForFileLanguageExists && myRearrangeEntriesSelected);
-
- myCbOnlyVcsChangedRegions.setEnabled(myFileHasChanges);
- myCbOnlyVcsChangedRegions.setSelected(myFileHasChanges && myFormatOnlyVCSChangedRegionsSelected);
-
- myDoNotAskMeCheckBox.setEnabled(true);
- myDoNotAskMeCheckBox.setSelected(myDoNotShowDialogSelected);
-
- myCbIncludeSubdirs.setEnabled(false);
- }
-
- private void setUpCbsStatesForDirectoryFormatting() {
- myCbOptimizeImports.setEnabled(true);
- myCbOptimizeImports.setSelected(myOptimizeImportsSelected);
-
- myCbArrangeEntries.setEnabled(true);
- myCbArrangeEntries.setSelected(myRearrangeEntriesSelected);
-
- myCbOnlyVcsChangedRegions.setEnabled(myDirectory != null && FormatChangedTextUtil.hasChanges(myDirectory));
- myCbOnlyVcsChangedRegions.setSelected(false);
-
- myDoNotAskMeCheckBox.setEnabled(false);
- myDoNotAskMeCheckBox.setSelected(false);
-
- myCbIncludeSubdirs.setEnabled(true);
- }
- private void setUpCbsStatesForSelectedTextFormatting() {
- myCbOptimizeImports.setEnabled(false);
- myCbOptimizeImports.setSelected(false);
-
- myCbArrangeEntries.setEnabled(true);
- myCbArrangeEntries.setSelected(myRearrangeEntriesSelected);
-
- myCbOnlyVcsChangedRegions.setEnabled(false);
- myCbOnlyVcsChangedRegions.setSelected(false);
-
- myDoNotAskMeCheckBox.setEnabled(true);
- myDoNotAskMeCheckBox.setSelected(myDoNotShowDialogSelected);
-
- myCbIncludeSubdirs.setEnabled(false);
+ boolean canRearrangeCode = Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null;
+ myRearrangeCodeCb.setVisible(canRearrangeCode);
+ if (canRearrangeCode) {
+ myRearrangeCodeCb.setSelected(myLastRunOptions.isRearrangeCode(myFile.getLanguage()));
+ }
}
- @Override
- protected JComponent createCenterPanel() {
- JPanel panel = new JPanel(new GridBagLayout());
- panel.setBorder(BorderFactory.createEmptyBorder(4, 8, 8, 0));
- GridBagConstraints gbConstraints = new GridBagConstraints();
- gbConstraints.gridy = 0;
- gbConstraints.gridx = 0;
- gbConstraints.gridwidth = 3;
- gbConstraints.gridheight = 1;
- gbConstraints.weightx = 1;
-
- gbConstraints.fill = GridBagConstraints.BOTH;
- gbConstraints.insets = new Insets(0, 0, 0, 0);
-
- myRbFile = new JRadioButton(CodeInsightBundle.message("process.scope.file",
- (myFile != null ? "'" + myFile.getVirtualFile().getPresentableUrl() + "'" : "")));
- panel.add(myRbFile, gbConstraints);
-
- myRbSelectedText = new JRadioButton(CodeInsightBundle.message("reformat.option.selected.text"));
- if (myTextSelected != null) {
- gbConstraints.gridy++;
- gbConstraints.insets = new Insets(0, 0, 0, 0);
- panel.add(myRbSelectedText, gbConstraints);
+ @Nullable
+ private String getChangesNotAvailableHint() {
+ if (!VcsUtil.isFileUnderVcs(myProject, VcsUtil.getFilePath(myFile.getVirtualFile()))) {
+ return "File not under VCS root";
}
-
- myRbDirectory = new JRadioButton();
- myCbIncludeSubdirs = new JCheckBox(CodeInsightBundle.message("reformat.option.include.subdirectories"));
- if (myDirectory != null) {
- myRbDirectory.setText(CodeInsightBundle.message("reformat.option.all.files.in.directory",
- myDirectory.getVirtualFile().getPresentableUrl()));
- gbConstraints.gridy++;
- gbConstraints.insets = new Insets(0, 0, 0, 0);
- panel.add(myRbDirectory, gbConstraints);
-
- if (myDirectory.getSubdirectories().length > 0) {
- gbConstraints.gridy++;
- gbConstraints.insets = new Insets(0, 20, 0, 0);
- panel.add(myCbIncludeSubdirs, gbConstraints);
- }
+ else if (!FormatChangedTextUtil.hasChanges(myFile)) {
+ return "File was not changed since last revision";
}
+ return null;
+ }
- myCbOptimizeImports = new JCheckBox(CodeInsightBundle.message("reformat.option.optimize.imports"));
- if (myTextSelected != null && LanguageImportStatements.INSTANCE.hasAnyExtensions()) {
- gbConstraints.gridy++;
- gbConstraints.insets = new Insets(0, 0, 0, 0);
- panel.add(myCbOptimizeImports, gbConstraints);
+ private void saveCurrentConfiguration() {
+ if (myOptimizeImportsCb.isEnabled()) {
+ myLastRunOptions.saveOptimizeImportsState(myRunOptions.isOptimizeImports());
}
-
- myCbArrangeEntries = new JCheckBox(CodeInsightBundle.message("reformat.option.rearrange.entries"));
- if (myDirectory != null || myFile != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null)
- {
- gbConstraints.gridy++;
- gbConstraints.insets = new Insets(0, 0, 0, 0);
- panel.add(myCbArrangeEntries, gbConstraints);
+ if (myRearrangeCodeCb.isEnabled()) {
+ myLastRunOptions.saveRearrangeState(myFile.getLanguage(), myRunOptions.isRearrangeCode());
}
- myCbOnlyVcsChangedRegions = new JCheckBox(CodeInsightBundle.message("reformat.option.vcs.changed.region"));
- gbConstraints.gridy++;
- panel.add(myCbOnlyVcsChangedRegions, gbConstraints);
+ if (!mySelectedTextRadioButton.isSelected()) {
+ myLastRunOptions.saveProcessVcsChangedTextState(myOnlyVCSChangedTextRb.isSelected());
+ }
+ }
- ButtonGroup buttonGroup = new ButtonGroup();
- buttonGroup.add(myRbFile);
- buttonGroup.add(myRbSelectedText);
- buttonGroup.add(myRbDirectory);
+ @NotNull
+ private LayoutCodeOptions createOptionsBundledOnDialog() {
+ return new LayoutCodeOptions() {
+ @Override
+ public TextRangeType getTextRangeType() {
+ if (myOnlyVCSChangedTextRb.isSelected()) {
+ return TextRangeType.VCS_CHANGED_TEXT;
+ }
+ if (mySelectedTextRadioButton.isSelected()) {
+ return TextRangeType.SELECTED_TEXT;
+ }
+ return TextRangeType.WHOLE_FILE;
+ }
- myRbFile.setEnabled(myFile != null);
- myRbSelectedText.setEnabled(myTextSelected == Boolean.TRUE);
+ @Override
+ public boolean isRearrangeCode() {
+ return myRearrangeCodeCb.isEnabled() && myRearrangeCodeCb.isSelected();
+ }
- return panel;
+ @Override
+ public boolean isOptimizeImports() {
+ return myOptimizeImportsCb.isEnabled() && myOptimizeImportsCb.isSelected();
+ }
+ };
}
+ @Nullable
@Override
- protected JComponent createSouthPanel() {
- JComponent southPanel = super.createSouthPanel();
- myDoNotAskMeCheckBox = new JCheckBox(CommonBundle.message("dialog.options.do.not.show"));
- return DialogWrapper.addDoNotShowCheckBox(southPanel, myDoNotAskMeCheckBox);
+ protected JComponent createCenterPanel() {
+ return myButtonsPanel;
}
@NotNull
HelpManager.getInstance().invokeHelp(myHelpId);
}
- @Override
- public boolean isProcessWholeFile() {
- return myRbFile.isSelected();
- }
-
- @Override
- public boolean isProcessDirectory() {
- return myRbDirectory.isSelected();
- }
-
- @Override
- public boolean isIncludeSubdirectories() {
- return myCbIncludeSubdirs.isSelected();
- }
-
- @Override
- public boolean isOptimizeImports() {
- return myCbOptimizeImports.isSelected();
- }
-
- @Override
- public boolean isRearrangeEntries() {
- return myCbArrangeEntries.isSelected();
- }
-
- @Nullable
- @Override
- public String getFileTypeMask() {
- return null;
- }
-
- @Nullable
- @Override
- public SearchScope getSearchScope() {
- return null;
- }
-
- @Override
- public boolean isProcessOnlyChangedText() {
- return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected();
- }
-
- public boolean isDoNotAskMe() {
- if (myDoNotAskMeCheckBox.isEnabled()) {
- return myDoNotAskMeCheckBox.isSelected();
- }
- else {
- return !EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG;
- }
- }
-
@Override
protected void doOKAction() {
super.doOKAction();
- persistEnabledCbsStates();
+ saveCurrentConfiguration();
}
- private void persistEnabledCbsStates() {
- if (myCbOptimizeImports.isEnabled()) {
- String optimizeImports = Boolean.toString(myCbOptimizeImports.isSelected());
- PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, optimizeImports);
- }
- if (myCbOnlyVcsChangedRegions.isEnabled()) {
- String formatVcsChangedRegions = Boolean.toString(myCbOnlyVcsChangedRegions.isSelected());
- PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, formatVcsChangedRegions);
- }
- if (myCbArrangeEntries.isEnabled()) {
- saveRearrangeCbState(myCbArrangeEntries.isSelected());
- }
+ public LayoutCodeOptions getRunOptions() {
+ return myRunOptions;
}
- private void saveRearrangeCbState(boolean isSelected) {
- if (myFile != null)
- LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, myFile.getLanguage(), isSelected);
- else
- LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isSelected);
- }
}
*/
package com.intellij.codeInsight.actions;
-public interface LayoutCodeOptions extends DirectoryFormattingOptions {
+public interface LayoutCodeOptions extends OptionalReformatActions {
- boolean isProcessWholeFile();
+ TextRangeType getTextRangeType();
- boolean isProcessDirectory();
+}
+enum TextRangeType {
+ VCS_CHANGED_TEXT,
+ SELECTED_TEXT,
+ WHOLE_FILE
}
+++ /dev/null
-/*
- * Copyright 2000-2013 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.ide.util.PropertiesComponent;
-import com.intellij.lang.Language;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.NotNull;
-
-public class LayoutCodeSettingsStorage {
-
- private LayoutCodeSettingsStorage() {
- }
-
- public static void saveRearrangeEntriesOptionFor(@NotNull Project project, @NotNull Language language, boolean value) {
- String key = getRearrangeEntriesKeyForLanguage(language);
- PropertiesComponent.getInstance(project).setValue(key, Boolean.toString(value));
- }
-
- public static void saveRearrangeEntriesOptionFor(@NotNull Project project, boolean value) {
- PropertiesComponent.getInstance(project).setValue(LayoutCodeConstants.REARRANGE_ENTRIES_KEY, Boolean.toString(value));
- }
-
- public static boolean getLastSavedRearrangeEntriesCbStateFor(@NotNull Project project) {
- return PropertiesComponent.getInstance(project).getBoolean(LayoutCodeConstants.REARRANGE_ENTRIES_KEY, false);
- }
-
- public static boolean getLastSavedRearrangeEntriesCbStateFor(@NotNull Project project, @NotNull Language language) {
- String key = getRearrangeEntriesKeyForLanguage(language);
- return PropertiesComponent.getInstance(project).getBoolean(key, false);
- }
-
- private static String getRearrangeEntriesKeyForLanguage(@NotNull Language language) {
- return LayoutCodeConstants.REARRANGE_ENTRIES_KEY + language.getDisplayName();
- }
-
-}
private final Project myProject;
private final String myText;
private final boolean myEnableOnlyVCSChangedTextCb;
+ private final LastRunReformatCodeOptionsProvider myLastRunOptions;
private JLabel myTitle;
protected JCheckBox myIncludeSubdirsCb;
myText = text;
myProject = project;
myEnableOnlyVCSChangedTextCb = enableOnlyVCSChangedTextCb;
+ myLastRunOptions = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance());
setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text"));
setTitle(title);
}
private void restoreCbsStates() {
- myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false));
- myCbRearrangeEntries.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject));
+ myCbOptimizeImports.setSelected(myLastRunOptions.getLastOptimizeImports());
+ myCbRearrangeEntries.setSelected(myLastRunOptions.getLastRearrangeCode());
myCbOnlyVcsChangedRegions.setEnabled(myEnableOnlyVCSChangedTextCb);
myCbOnlyVcsChangedRegions.setSelected(
- myEnableOnlyVCSChangedTextCb && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)
+ myEnableOnlyVCSChangedTextCb && myLastRunOptions.getLastTextRangeType() == TextRangeType.VCS_CHANGED_TEXT
);
}
}
@Override
- public boolean isRearrangeEntries() {
+ public boolean isRearrangeCode() {
return myCbRearrangeEntries.isSelected();
}
@Override
protected void doOKAction() {
super.doOKAction();
- PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(isOptimizeImports()));
- LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries());
+ myLastRunOptions.saveOptimizeImportsState(isOptimizeImports());
+ myLastRunOptions.saveRearrangeCodeState(isRearrangeCode());
if (myEnableOnlyVCSChangedTextCb) {
- PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myCbOnlyVcsChangedRegions.isSelected()));
+ myLastRunOptions.saveProcessVcsChangedTextState(getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT);
}
}
return myCbOptimizeImports.isSelected();
}
- public boolean isProcessOnlyChangedText() {
- return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected();
- }
-
@Nullable
public String getFileTypeMask() {
if (myEnableFileNameFilterCb.isSelected()) {
return false;
}
+ @Override
+ public TextRangeType getTextRangeType() {
+ return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected()
+ ? TextRangeType.VCS_CHANGED_TEXT
+ : TextRangeType.WHOLE_FILE;
+ }
}
package com.intellij.codeInsight.actions;
import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.ide.util.PropertiesComponent;
import com.intellij.lang.LanguageImportStatements;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
if (projectContext != null || moduleContext != null) {
final String text;
+ final boolean hasChanges;
if (moduleContext != null) {
text = CodeInsightBundle.message("process.scope.module", moduleContext.getName());
+ hasChanges = FormatChangedTextUtil.hasChanges(moduleContext);
}
else {
text = CodeInsightBundle.message("process.scope.project", projectContext.getPresentableUrl());
+ hasChanges = FormatChangedTextUtil.hasChanges(projectContext);
}
- DialogWrapper dialog = new OptimizeOnModuleDialog(project, text);
+ DialogWrapper dialog = new OptimizeImportsDialog(project, text, hasChanges);
if (!dialog.showAndGet()) {
return;
}
}
}
- boolean processDirectory;
- boolean includeSubdirectories;
-
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- includeSubdirectories = processDirectory = false;
- }
- else if (!EditorSettingsExternalizable.getInstance().getOptions().SHOW_OPIMIZE_IMPORTS_DIALOG && file != null) {
- includeSubdirectories = processDirectory = false;
- }
- else {
- final LayoutCodeDialog dialog =
- new LayoutCodeDialog(project, CodeInsightBundle.message("process.optimize.imports"), file, dir, null, HELP_ID);
- if (!dialog.showAndGet()) {
+ boolean processDirectory = false;
+ boolean processOnlyVcsChangedFiles = false;
+ if (!ApplicationManager.getApplication().isUnitTestMode() && file == null && dir != null) {
+ String message = CodeInsightBundle.message("process.scope.directory", dir.getName());
+ OptimizeImportsDialog dialog = new OptimizeImportsDialog(project, message, FormatChangedTextUtil.hasChanges(dir));
+ dialog.show();
+ if (!dialog.isOK()) {
return;
}
- EditorSettingsExternalizable.getInstance().getOptions().SHOW_OPIMIZE_IMPORTS_DIALOG = !dialog.isDoNotAskMe();
- ReformatCodeAction.updateShowDialogSetting(dialog, "\"Optimize Imports\" dialog disabled");
- processDirectory = dialog.isProcessDirectory();
- includeSubdirectories = dialog.isIncludeSubdirectories();
+ processDirectory = true;
+ processOnlyVcsChangedFiles = dialog.isProcessOnlyVcsChangedFiles();
}
if (processDirectory){
- new OptimizeImportsProcessor(project, dir, includeSubdirectories).run();
+ new OptimizeImportsProcessor(project, dir, true, processOnlyVcsChangedFiles).run();
}
else{
new OptimizeImportsProcessor(project, file).run();
return !LanguageImportStatements.INSTANCE.forFile(file).isEmpty();
}
- private static class OptimizeOnModuleDialog extends DialogWrapper {
+ private static class OptimizeImportsDialog extends DialogWrapper {
+ private final boolean myContextHasChanges;
+
private final String myText;
+ private JCheckBox myOnlyVcsCheckBox;
+ private final LastRunReformatCodeOptionsProvider myLastRunOptions;
- OptimizeOnModuleDialog(Project project, String text) {
+ OptimizeImportsDialog(Project project, String text, boolean hasChanges) {
super(project, false);
myText = text;
+ myContextHasChanges = hasChanges;
+ myLastRunOptions = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance());
setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text"));
setTitle(CodeInsightBundle.message("process.optimize.imports"));
init();
}
+ public boolean isProcessOnlyVcsChangedFiles() {
+ return myOnlyVcsCheckBox.isSelected();
+ }
+
@Nullable
@Override
protected JComponent createCenterPanel() {
- return new JLabel(myText);
+ JPanel panel = new JPanel();
+ BoxLayout layout = new BoxLayout(panel, BoxLayout.Y_AXIS);
+ panel.setLayout(layout);
+
+ panel.add(new JLabel(myText));
+ myOnlyVcsCheckBox = new JCheckBox("only VCS changed files");
+
+ boolean lastRunVcsChangedTextEnabled = myLastRunOptions.getLastTextRangeType() == TextRangeType.VCS_CHANGED_TEXT;
+
+ myOnlyVcsCheckBox.setEnabled(myContextHasChanges);
+ myOnlyVcsCheckBox.setSelected(myContextHasChanges && lastRunVcsChangedTextEnabled);
+
+ panel.add(myOnlyVcsCheckBox);
+ return panel;
}
}
}
super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, false);
}
+ public OptimizeImportsProcessor(Project project, PsiDirectory directory, boolean includeSubdirs, boolean processOnlyVcsChangedFiles) {
+ super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, processOnlyVcsChangedFiles);
+ }
+
public OptimizeImportsProcessor(Project project, PsiFile file) {
super(project, file, PROGRESS_TEXT, COMMAND_NAME, false);
}
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
*/
package com.intellij.codeInsight.actions;
-import org.jetbrains.annotations.NonNls;
+public interface OptionalReformatActions {
-/**
- * @author Denis Zhdanov
- * @since 12/16/11 6:10 PM
- */
-public class LayoutCodeConstants {
+ boolean isOptimizeImports();
- @NonNls public static final String OPTIMIZE_IMPORTS_KEY = "LayoutCode.optimizeImports";
- @NonNls public static final String REARRANGE_ENTRIES_KEY = "LayoutCode.rearrangeEntries";
- @NonNls public static final String PROCESS_CHANGED_TEXT_KEY = "LayoutCode.processChangedText";
+ boolean isRearrangeCode();
- private LayoutCodeConstants() {
- }
}
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;
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;
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);
}
}
}
- 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;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.ReformatCodeProcessor");
- private final Collection<TextRange> myRanges = new ArrayList<TextRange>();
private static final String PROGRESS_TEXT = CodeInsightBundle.message("reformat.progress.common.text");
+ private final Collection<TextRange> myRanges = new ArrayList<TextRange>();
+ private SelectionModel mySelectionModel;
public ReformatCodeProcessor(Project project, boolean processChangedTextOnly) {
super(project, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly);
}
+ public ReformatCodeProcessor(@NotNull PsiFile file, @NotNull SelectionModel selectionModel) {
+ super(file.getProject(), COMMAND_NAME, PROGRESS_TEXT, false);
+ mySelectionModel = selectionModel;
+ }
+
+ public ReformatCodeProcessor(AbstractLayoutCodeProcessor processor, @NotNull SelectionModel selectionModel) {
+ super(processor, COMMAND_NAME, PROGRESS_TEXT);
+ mySelectionModel = selectionModel;
+ }
+
public ReformatCodeProcessor(AbstractLayoutCodeProcessor processor, boolean processChangedTextOnly) {
super(processor, COMMAND_NAME, PROGRESS_TEXT);
setProcessChangedTextOnly(processChangedTextOnly);
}
}
+ public ReformatCodeProcessor(@NotNull PsiFile file, boolean processChangedTextOnly) {
+ super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly);
+ }
+
public ReformatCodeProcessor(Project project, PsiFile[] files, @Nullable Runnable postRunnable, boolean processChangedTextOnly) {
this(project, files, COMMAND_NAME, postRunnable, processChangedTextOnly);
}
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());
- }
+ handleFileTooBigException(LOG, e, file);
return false;
}
catch (IncorrectOperationException e) {
@NotNull
private Collection<TextRange> getRangesToFormat(boolean processChangedTextOnly, PsiFile file) throws FilesTooBigForDiffException {
+ if (mySelectionModel != null) {
+ return getSelectedRanges(mySelectionModel);
+ }
+
if (processChangedTextOnly) {
return FormatChangedTextUtil.getChangedTextRanges(myProject, file);
}
--- /dev/null
+/*
+ * Copyright 2000-2014 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;
+
+public class ReformatCodeRunOptions implements LayoutCodeOptions {
+
+ private boolean myRearrangeCode;
+ private boolean myOptimizeImports;
+ private TextRangeType myProcessingScope;
+
+ public ReformatCodeRunOptions(TextRangeType processingScope) {
+ myProcessingScope = processingScope;
+ }
+
+ public void setProcessingScope(TextRangeType processingScope) {
+ myProcessingScope = processingScope;
+ }
+
+ @Override
+ public boolean isOptimizeImports() {
+ return myOptimizeImports;
+ }
+
+ @Override
+ public boolean isRearrangeCode() {
+ return myRearrangeCode;
+ }
+
+ public ReformatCodeRunOptions setRearrangeCode(boolean rearrangeCode) {
+ myRearrangeCode = rearrangeCode;
+ return this;
+ }
+
+ public ReformatCodeRunOptions setOptimizeImports(boolean optimizeImports) {
+ myOptimizeImports = optimizeImports;
+ return this;
+ }
+
+ @Override
+ public TextRangeType getTextRangeType() {
+ return myProcessingScope;
+ }
+
+}
+
--- /dev/null
+/*
+ * Copyright 2000-2014 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.lang.LanguageFormatting;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NonNls;
+
+public class ReformatFileAction extends AnAction implements DumbAware {
+ private static final @NonNls String HELP_ID = "editing.codeReformatting";
+
+ @Override
+ public void update(AnActionEvent event) {
+ Presentation presentation = event.getPresentation();
+ DataContext dataContext = event.getDataContext();
+ Project project = CommonDataKeys.PROJECT.getData(dataContext);
+ Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
+ if (project == null || editor == null) {
+ presentation.setEnabled(false);
+ return;
+ }
+
+ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+ if (file == null || file.getVirtualFile() == null) {
+ presentation.setEnabled(false);
+ return;
+ }
+
+ if (LanguageFormatting.INSTANCE.forContext(file) != null) {
+ presentation.setEnabled(true);
+ }
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent event) {
+ Presentation presentation = event.getPresentation();
+ DataContext dataContext = event.getDataContext();
+ Project project = CommonDataKeys.PROJECT.getData(dataContext);
+ Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
+ if (project == null || editor == null) {
+ presentation.setEnabled(false);
+ return;
+ }
+
+ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+ if (file == null || file.getVirtualFile() == null) {
+ presentation.setEnabled(false);
+ return;
+ }
+
+ boolean hasSelection = editor.getSelectionModel().hasSelection();
+ LayoutCodeDialog dialog = new LayoutCodeDialog(project, file, hasSelection, HELP_ID);
+ dialog.show();
+
+ if (dialog.isOK()) {
+ new CodeProcessor(file, editor, dialog.getRunOptions()).processCode();
+ }
+ }
+}
import javax.swing.*;
+import static com.intellij.codeInsight.actions.TextRangeType.*;
+
public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesOptions {
- @NotNull private Project myProject;
private JPanel myPanel;
private JCheckBox myOptimizeImports;
private JCheckBox myOnlyChangedText;
private JCheckBox myRearrangeEntriesCb;
+ private final LastRunReformatCodeOptionsProvider myLastRunSettings;
+
public ReformatFilesDialog(@NotNull Project project, @NotNull VirtualFile[] files) {
super(project, true);
- myProject = project;
- setTitle(CodeInsightBundle.message("dialog.reformat.files.title"));
- myOptimizeImports.setSelected(isOptmizeImportsOptionOn());
+ myLastRunSettings = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance());
+
boolean canTargetVcsChanges = FormatChangedTextUtil.hasChanges(files, project);
myOnlyChangedText.setEnabled(canTargetVcsChanges);
- myOnlyChangedText.setSelected(
- canTargetVcsChanges && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)
- );
- myOptimizeImports.setSelected(isOptmizeImportsOptionOn());
- myRearrangeEntriesCb.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject));
+ myOnlyChangedText.setSelected(canTargetVcsChanges && myLastRunSettings.getLastTextRangeType() == VCS_CHANGED_TEXT);
+ myOptimizeImports.setSelected(myLastRunSettings.getLastOptimizeImports());
+ myRearrangeEntriesCb.setSelected(myLastRunSettings.getLastRearrangeCode());
+
+ setTitle(CodeInsightBundle.message("dialog.reformat.files.title"));
init();
}
}
@Override
- public boolean isProcessOnlyChangedText() {
- return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected();
+ public TextRangeType getTextRangeType() {
+ return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected()
+ ? VCS_CHANGED_TEXT
+ : WHOLE_FILE;
}
@Override
- public boolean isRearrangeEntries() {
+ public boolean isRearrangeCode() {
return myRearrangeEntriesCb.isSelected();
}
@Override
protected void doOKAction() {
super.doOKAction();
- PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myOptimizeImports.isSelected()));
- PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myOnlyChangedText.isSelected()));
- LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries());
- }
-
- static boolean isOptmizeImportsOptionOn() {
- return PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false);
+ myLastRunSettings.saveOptimizeImportsState(isOptimizeImports());
+ myLastRunSettings.saveRearrangeCodeState(isRearrangeCode());
+ if (myOnlyChangedText.isEnabled()) {
+ myLastRunSettings.saveProcessVcsChangedTextState(getTextRangeType() == VCS_CHANGED_TEXT);
+ }
}
@Nullable
import com.intellij.psi.search.SearchScope;
import org.jetbrains.annotations.Nullable;
-public interface ReformatFilesOptions {
-
- boolean isOptimizeImports();
-
- boolean isProcessOnlyChangedText();
-
- boolean isRearrangeEntries();
+public interface ReformatFilesOptions extends LayoutCodeOptions {
@Nullable
String getFileTypeMask();
<action id="ReformatCode">
<keyboard-shortcut first-keystroke="control alt L"/>
</action>
+ <action id="ReformatFile">
+ <keyboard-shortcut first-keystroke="control shift alt L"/>
+ </action>
<action id="Generate">
<keyboard-shortcut first-keystroke="alt INSERT"/>
</action>
<reference ref="Arrangement.Rule.Group.Condition.Move.Down"/>
</group>
+ <action id="ReformatFile" class="com.intellij.codeInsight.actions.ReformatFileAction"/>
+
</actions>
</component>