diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java index f59a387a9fb4..19f37c372305 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java @@ -223,9 +223,7 @@ class FormatProcessor { return; } - while (myCurrentState.getStateId() == FormattingStateId.PROCESSING_BLOCKS && !myCurrentState.isDone()) { - myCurrentState.iteration(); - } + doIterationsSynchronously(FormattingStateId.PROCESSING_BLOCKS); } private void reset() { @@ -246,15 +244,27 @@ class FormatProcessor { assert !myDisposed; myCurrentState.setNext(new ApplyChangesState(model)); - if (!sequentially) { + if (sequentially) { return; } - while (myCurrentState.getStateId() == FormattingStateId.APPLYING_CHANGES && !myCurrentState.isDone()) { + doIterationsSynchronously(FormattingStateId.APPLYING_CHANGES); + } + + /** + * Perform iterations against the {@link #myCurrentState current state} until it's {@link FormattingStateId type} + * is {@link FormattingStateId#getPreviousStates() less} or equal to the given state. + * + * @param state target state to process + */ + private void doIterationsSynchronously(@NotNull FormattingStateId state) { + while ((myCurrentState.getStateId() == state || state.getPreviousStates().contains(myCurrentState.getStateId())) + && !myCurrentState.isDone()) + { myCurrentState.iteration(); } } - + public void setJavaIndentOptions(final CodeStyleSettings.IndentOptions javaIndentOptions) { myJavaIndentOptions = javaIndentOptions; } diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java index 052a2ca8a559..02a7cc6ff350 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java @@ -214,6 +214,7 @@ public class FormatterImpl extends FormatterEx } finally { enableFormatting(); + myProgressIndicator = null; } } else { diff --git a/platform/lang-impl/src/com/intellij/formatting/FormattingProgressIndicatorImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormattingProgressIndicatorImpl.java index 6916a1dcedcb..1a57f2c4a1bc 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormattingProgressIndicatorImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormattingProgressIndicatorImpl.java @@ -35,6 +35,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.HashMap; @@ -81,10 +82,9 @@ public class FormattingProgressIndicatorImpl extends Task.Modal implements Forma private final Map> myCallbacks = new HashMap>(); - @Nullable - private final VirtualFile myFile; - private final Document myDocument; - private final int myFileTextLength; + private final WeakReference myFile; + private final WeakReference myDocument; + private final int myFileTextLength; @NotNull private FormattingStateId myLastState = FormattingStateId.WRAPPING_BLOCKS; @@ -98,8 +98,8 @@ public class FormattingProgressIndicatorImpl extends Task.Modal implements Forma public FormattingProgressIndicatorImpl(@Nullable Project project, @NotNull PsiFile file, @NotNull Document document) { super(project, getTitle(file), true); - myFile = file.getVirtualFile(); - myDocument = document; + myFile = new WeakReference(file.getVirtualFile()); + myDocument = new WeakReference(document); myFileTextLength = file.getTextLength(); addCallback(EventType.CANCEL, new MyCancelCallback()); } @@ -140,7 +140,10 @@ public class FormattingProgressIndicatorImpl extends Task.Modal implements Forma UIUtil.invokeAndWaitIfNeeded(new Runnable() { @Override public void run() { - myDocumentModificationStampBefore = myDocument.getModificationStamp(); + Document document = myDocument.get(); + if (document != null) { + myDocumentModificationStampBefore = document.getModificationStamp(); + } task.prepare(); } }); @@ -282,16 +285,18 @@ public class FormattingProgressIndicatorImpl extends Task.Modal implements Forma @Override public void run() { myRunning = false; - if (myFile == null || myDocumentModificationStampBefore < 0) { + VirtualFile file = myFile.get(); + Document document = myDocument.get(); + if (file == null || document == null || myDocumentModificationStampBefore < 0) { return; } - FileEditor editor = FileEditorManager.getInstance(myProject).getSelectedEditor(myFile); + FileEditor editor = FileEditorManager.getInstance(myProject).getSelectedEditor(file); if (editor == null) { return; } UndoManager manager = UndoManager.getInstance(myProject); - while (manager.isUndoAvailable(editor) && myDocument.getModificationStamp() != myDocumentModificationStampBefore) { + while (manager.isUndoAvailable(editor) && document.getModificationStamp() != myDocumentModificationStampBefore) { manager.undo(editor); } } diff --git a/platform/platform-api/src/com/intellij/execution/configurations/CommandLineTokenizer.java b/platform/platform-api/src/com/intellij/execution/configurations/CommandLineTokenizer.java new file mode 100644 index 000000000000..0fc5654e909f --- /dev/null +++ b/platform/platform-api/src/com/intellij/execution/configurations/CommandLineTokenizer.java @@ -0,0 +1,87 @@ +package com.intellij.execution.configurations; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +/** + * Splits input String to tokens being aware of quoted tokens, + * usually used for splitting command line to separate arguments that may contain space symbols. + * Escaped symbols are not handled so there's no way to get token that itself contains quotation mark. + */ +public class CommandLineTokenizer extends StringTokenizer { + + private static String DEFAULT_DELIMITERS = " \t\n\r\f"; + // keep source level 1.4 + private List myTokens = new ArrayList(); + private int myCurrentToken = 0; + + public CommandLineTokenizer(String str) { + super(str, DEFAULT_DELIMITERS, true); + parseTokens(); + } + + public CommandLineTokenizer(String str, String delim) { + super(str, delim, true); + parseTokens(); + } + + public boolean hasMoreTokens() { + return myCurrentToken < myTokens.size(); + } + + public String nextToken() { + return (String) myTokens.get(myCurrentToken++); + } + + public int countTokens() { + return myTokens.size() - myCurrentToken; + } + + + public String nextToken(String delim) { + throw new UnsupportedOperationException(); + } + + private void parseTokens() { + String token; + while ((token = nextTokenInternal()) != null) { + myTokens.add(token); + } + } + + private String nextTokenInternal() { + String nextToken; + do { + if (super.hasMoreTokens()) { + nextToken = super.nextToken(); + } else { + nextToken = null; + } + } while (nextToken != null && nextToken.length() == 1 && DEFAULT_DELIMITERS.indexOf(nextToken.charAt(0)) >= 0); + + if (nextToken == null) { + return null; + } + + int i; + int quotationMarks = 0; + final StringBuffer buffer = new StringBuffer(); + + do { + while ((i = nextToken.indexOf('"')) >= 0) { + quotationMarks++; + buffer.append(nextToken.substring(0, i)); + nextToken = nextToken.substring(i + 1); + } + buffer.append(nextToken); + if (quotationMarks % 2 == 1 && super.hasMoreTokens()) { + nextToken = super.nextToken(); + } else { + nextToken = null; + } + } while (nextToken != null); + + return buffer.toString(); + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 42fbeae96ca5..3be56bce173b 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -38,6 +38,7 @@ import com.intellij.openapi.util.Iconable; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ex.WindowManagerEx; @@ -588,7 +589,12 @@ public class Switcher extends AnAction implements DumbAware { } else if (value instanceof VirtualFile) { final VirtualFile file = (VirtualFile)value; - FileEditorManager.getInstance(project).openFile(file, true, true); + IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() { + @Override + public void run() { + FileEditorManager.getInstance(project).openFile(file, true, true); + } + }); } } diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 50525a8295f3..078c4ec16588 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -975,6 +975,27 @@ public class StringUtil { }; } + @NotNull + public static Iterable tokenize(@NotNull String s, final StringTokenizer tokenizer) { + return new Iterable() { + public Iterator iterator() { + return new Iterator() { + public boolean hasNext() { + return tokenizer.hasMoreTokens(); + } + + public String next() { + return tokenizer.nextToken(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + @NotNull public static List getWordsIn(@NotNull String text) { List result = new SmartList();