-
-
\ No newline at end of file
diff --git a/colorSchemes/src/colorSchemes/vibrant_ink.xml b/colorSchemes/src/colorSchemes/vibrant_ink.xml
new file mode 100644
index 000000000000..5adcecdc4cc8
--- /dev/null
+++ b/colorSchemes/src/colorSchemes/vibrant_ink.xml
@@ -0,0 +1,1569 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
index 8f88be86d8ee..4d7359ab4b49 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
@@ -50,6 +50,7 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.LibraryPro
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ModuleProjectStructureElement;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureDaemonAnalyzer;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
+import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.NamedConfigurable;
@@ -64,6 +65,7 @@ import com.intellij.openapi.wm.WindowManager;
import com.intellij.ui.navigation.Place;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
+import com.intellij.util.PathUtil;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.tree.TreeUtil;
@@ -783,27 +785,23 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
final NamedConfigurable namedConfigurable = getSelectedConfugurable();
if (namedConfigurable instanceof ModuleConfigurable) {
try {
+ final ModuleEditor moduleEditor = ((ModuleConfigurable)namedConfigurable).getModuleEditor();
final String modulePresentation = IdeBundle.message("project.new.wizard.module.identification");
- final NamePathComponent component = new NamePathComponent(IdeBundle.message("label.project.name"), IdeBundle.message(
- "label.component.file.location", StringUtil.capitalize(modulePresentation)), IdeBundle.message(
- "title.select.project.file.directory", modulePresentation), IdeBundle.message("description.select.project.file.directory",
- StringUtil.capitalize(modulePresentation)), true, false);
- final DialogWrapper copyModuleDialog = new DialogWrapper(myTree, false) {
- {
- setTitle(ProjectBundle.message("copy.module.dialog.title"));
- init();
- }
+ final NamePathComponent component = new NamePathComponent(IdeBundle.message("label.module.name"), IdeBundle.message("label.component.file.location", StringUtil.capitalize(modulePresentation)), IdeBundle.message("title.select.project.file.directory", modulePresentation),
+ IdeBundle.message("description.select.project.file.directory", StringUtil.capitalize(modulePresentation)), true,
+ false);
+ final Module originalModule = moduleEditor.getModule();
+ if (originalModule != null) {
+ component.setPath(PathUtil.getParentPath(originalModule.getModuleFilePath()));
+ }
- public JComponent getPreferredFocusedComponent() {
- return component.getNameComponent();
- }
-
- @Nullable
- protected JComponent createCenterPanel() {
- return component;
- }
-
- protected void doOKAction() {
+ final DialogBuilder dialogBuilder = new DialogBuilder(myTree);
+ dialogBuilder.setTitle(ProjectBundle.message("copy.module.dialog.title"));
+ dialogBuilder.setCenterPanel(component);
+ dialogBuilder.setPreferedFocusComponent(component.getNameComponent());
+ dialogBuilder.setOkOperation(new Runnable() {
+ @Override
+ public void run() {
if (component.getNameValue().length() == 0) {
Messages.showErrorDialog(ProjectBundle.message("enter.module.copy.name.error.message"), CommonBundle.message("title.error"));
return;
@@ -815,16 +813,17 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
return;
}
if (!ProjectWizardUtil
- .createDirectoryIfNotExists(IdeBundle.message("directory.project.file.directory", modulePresentation), component.getPath(), true)) {
+ .createDirectoryIfNotExists(IdeBundle.message("directory.project.file.directory", modulePresentation), component.getPath(),
+ true)) {
Messages.showErrorDialog(ProjectBundle.message("path.0.is.invalid.error.message", component.getPath()), CommonBundle.message("title.error"));
return;
}
- super.doOKAction();
+ dialogBuilder.getDialogWrapper().close(DialogWrapper.OK_EXIT_CODE);
}
- };
- copyModuleDialog.show();
- if (!copyModuleDialog.isOK()) return;
- final ModifiableRootModel rootModel = ((ModuleConfigurable)namedConfigurable).getModuleEditor().getModifiableRootModel();
+ });
+ if (dialogBuilder.show() != DialogWrapper.OK_EXIT_CODE) return;
+
+ final ModifiableRootModel rootModel = moduleEditor.getModifiableRootModel();
final String path = component.getPath();
final ModuleBuilder builder = new ModuleBuilder() {
public void setupRootModel(final ModifiableRootModel modifiableRootModel) throws ConfigurationException {
diff --git a/java/java-impl/src/com/intellij/codeInsight/unwrap/AbstractUnwrapper.java b/java/java-impl/src/com/intellij/codeInsight/unwrap/AbstractUnwrapper.java
new file mode 100644
index 000000000000..53f07e9ba579
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/unwrap/AbstractUnwrapper.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2000-2009 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.unwrap;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.*;
+import com.intellij.util.IncorrectOperationException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public abstract class AbstractUnwrapper implements Unwrapper {
+ private final String myDescription;
+
+ public AbstractUnwrapper(String description) {
+ myDescription = description;
+ }
+
+ public abstract boolean isApplicableTo(PsiElement e);
+
+ public void collectElementsToIgnore(PsiElement element, Set result) {
+ }
+
+ public String getDescription(PsiElement e) {
+ return myDescription;
+ }
+
+ public PsiElement collectAffectedElements(PsiElement e, List toExtract) {
+ try {
+ C c = createContext(false);
+ doUnwrap(e, c);
+ toExtract.addAll(c.myElementsToExtract);
+ return e;
+ }
+ catch (IncorrectOperationException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public List unwrap(Editor editor, PsiElement element) throws IncorrectOperationException {
+ C c = createContext(true);
+ doUnwrap(element, c);
+ return c.myElementsToExtract;
+ }
+
+ protected abstract void doUnwrap(PsiElement element, C context) throws IncorrectOperationException;
+
+ protected abstract C createContext(boolean isEffective);
+
+ public abstract static class AbstractContext {
+ protected final List myElementsToExtract = new ArrayList();
+ protected final boolean myIsEffective;
+
+ public AbstractContext(boolean isEffective) {
+ myIsEffective = isEffective;
+ }
+
+ public void addElementToExtract(PsiElement e) {
+ myElementsToExtract.add(e);
+ }
+
+ public void extractElement(PsiElement element, PsiElement from) throws IncorrectOperationException {
+ extract(element, element, from);
+ }
+
+ protected abstract boolean isWhiteSpace(PsiElement element);
+
+ protected void extract(PsiElement first, PsiElement last, PsiElement from) throws IncorrectOperationException {
+ // trim leading empty spaces
+ while (first != last && isWhiteSpace(first)) {
+ //noinspection ConstantConditions
+ first = first.getNextSibling();
+ }
+
+ // trim trailing empty spaces
+ while (last != first && isWhiteSpace(last)) {
+ //noinspection ConstantConditions
+ last = last.getPrevSibling();
+ }
+
+ // nothing to extract
+ if (first == null || last == null || first == last && isWhiteSpace(last)) return;
+
+ PsiElement toExtract = first;
+ if (myIsEffective) {
+ toExtract = from.getParent().addRangeBefore(first, last, from);
+ }
+
+ do {
+ if (toExtract != null) {
+ addElementToExtract(toExtract);
+ toExtract = toExtract.getNextSibling();
+ }
+ first = first.getNextSibling();
+ }
+ while (first != null && first.getPrevSibling() != last);
+ }
+
+ public void delete(PsiElement e) throws IncorrectOperationException {
+ if (myIsEffective) e.delete();
+ }
+
+ public void deleteExactly(PsiElement e) throws IncorrectOperationException {
+ if (myIsEffective) {
+ // have to use 'parent.deleteChildRange' since 'e.delete' is too smart:
+ // it attempts to remove not only the element but sometimes whole expression.
+ e.getParent().deleteChildRange(e, e);
+ }
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/unwrap/JavaUnwrapDescriptor.java b/java/java-impl/src/com/intellij/codeInsight/unwrap/JavaUnwrapDescriptor.java
index f1af90bc8db1..d9e87eadf59f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/unwrap/JavaUnwrapDescriptor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/unwrap/JavaUnwrapDescriptor.java
@@ -29,19 +29,31 @@ import java.util.List;
import java.util.Set;
public class JavaUnwrapDescriptor implements UnwrapDescriptor {
- private static final Unwrapper[] UNWRAPPERS = new Unwrapper[] {
- new JavaMethodParameterUnwrapper(),
- new JavaElseUnwrapper(),
- new JavaElseRemover(),
- new JavaIfUnwrapper(),
- new JavaWhileUnwrapper(),
- new JavaForUnwrapper(),
- new JavaBracesUnwrapper(),
- new JavaTryUnwrapper(),
- new JavaCatchRemover(),
- new JavaSynchronizedUnwrapper(),
- new JavaAnonymousUnwrapper(),
- };
+ private Unwrapper[] myUnwrappers;
+
+ public final Unwrapper[] getUnwrappers() {
+ if (myUnwrappers == null) {
+ myUnwrappers = createUnwrappers();
+ }
+
+ return myUnwrappers;
+ }
+
+ protected Unwrapper[] createUnwrappers() {
+ return new Unwrapper[] {
+ new JavaMethodParameterUnwrapper(),
+ new JavaElseUnwrapper(),
+ new JavaElseRemover(),
+ new JavaIfUnwrapper(),
+ new JavaWhileUnwrapper(),
+ new JavaForUnwrapper(),
+ new JavaBracesUnwrapper(),
+ new JavaTryUnwrapper(),
+ new JavaCatchRemover(),
+ new JavaSynchronizedUnwrapper(),
+ new JavaAnonymousUnwrapper(),
+ };
+ }
public List> collectUnwrappers(Project project, Editor editor, PsiFile file) {
PsiElement e = findTargetElement(editor, file);
@@ -49,7 +61,7 @@ public class JavaUnwrapDescriptor implements UnwrapDescriptor {
List> result = new ArrayList>();
Set ignored = new HashSet();
while (e != null) {
- for (Unwrapper u : UNWRAPPERS) {
+ for (Unwrapper u : getUnwrappers()) {
if (u.isApplicableTo(e) && !ignored.contains(e)) {
result.add(new Pair(e, u));
u.collectElementsToIgnore(e, ignored);
diff --git a/java/java-impl/src/com/intellij/codeInsight/unwrap/JavaUnwrapper.java b/java/java-impl/src/com/intellij/codeInsight/unwrap/JavaUnwrapper.java
index dbec98c6a72d..ac6940f77517 100644
--- a/java/java-impl/src/com/intellij/codeInsight/unwrap/JavaUnwrapper.java
+++ b/java/java-impl/src/com/intellij/codeInsight/unwrap/JavaUnwrapper.java
@@ -15,60 +15,24 @@
*/
package com.intellij.codeInsight.unwrap;
-import com.intellij.openapi.editor.Editor;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-public abstract class JavaUnwrapper implements Unwrapper {
- private final String myDescription;
+public abstract class JavaUnwrapper extends AbstractUnwrapper {
public JavaUnwrapper(String description) {
- myDescription = description;
+ super(description);
}
- public abstract boolean isApplicableTo(PsiElement e);
-
- public void collectElementsToIgnore(PsiElement element, Set result) {
+ @Override
+ protected Context createContext(boolean isEffective) {
+ return new Context(isEffective);
}
- public String getDescription(PsiElement e) {
- return myDescription;
- }
-
- public PsiElement collectAffectedElements(PsiElement e, List toExtract) {
- try {
- Context c = new Context(false);
- doUnwrap(e, c);
- toExtract.addAll(c.myElementsToExtract);
- return e;
- }
- catch (IncorrectOperationException ex) {
- throw new RuntimeException(ex);
- }
- }
-
- public List unwrap(Editor editor, PsiElement element) throws IncorrectOperationException {
- Context c = new Context(true);
- doUnwrap(element, c);
- return c.myElementsToExtract;
- }
-
- protected abstract void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException;
-
- protected static class Context {
- private final List myElementsToExtract = new ArrayList();
- private final boolean myIsEffective;
+ protected static class Context extends AbstractUnwrapper.AbstractContext {
public Context(boolean isEffective) {
- myIsEffective = isEffective;
- }
-
- public void addElementToExtract(PsiElement e) {
- myElementsToExtract.add(e);
+ super(isEffective);
}
public void extractFromBlockOrSingleStatement(PsiStatement block, PsiElement from) throws IncorrectOperationException {
@@ -85,51 +49,6 @@ public abstract class JavaUnwrapper implements Unwrapper {
extract(block.getFirstBodyElement(), block.getLastBodyElement(), from);
}
- public void extractElement(PsiElement element, PsiElement from) throws IncorrectOperationException {
- extract(element, element, from);
- }
-
- private void extract(PsiElement first, PsiElement last, PsiElement from) throws IncorrectOperationException {
- // trim leading empty spaces
- while (first != last && first instanceof PsiWhiteSpace) {
- first = first.getNextSibling();
- }
-
- // trim trailing empty spaces
- while (last != first && last instanceof PsiWhiteSpace) {
- last = last.getPrevSibling();
- }
-
- // nothing to extract
- if (first == null || last == null || first == last && last instanceof PsiWhiteSpace) return;
-
- PsiElement toExtract = first;
- if (myIsEffective) {
- toExtract = from.getParent().addRangeBefore(first, last, from);
- }
-
- do {
- if (toExtract != null) {
- addElementToExtract(toExtract);
- toExtract = toExtract.getNextSibling();
- }
- first = first.getNextSibling();
- }
- while (first != null && first.getPrevSibling() != last);
- }
-
- public void delete(PsiElement e) throws IncorrectOperationException {
- if (myIsEffective) e.delete();
- }
-
- public void deleteExactly(PsiElement e) throws IncorrectOperationException {
- if (myIsEffective) {
- // have to use 'parent.deleteChildRange' since 'e.delete' is too smart:
- // it attempts to remove not only the element but sometimes whole expression.
- e.getParent().deleteChildRange(e, e);
- }
- }
-
public void setElseBranch(PsiIfStatement ifStatement, PsiStatement elseBranch) throws IncorrectOperationException {
PsiStatement toExtract = elseBranch;
if (myIsEffective) {
@@ -139,6 +58,11 @@ public abstract class JavaUnwrapper implements Unwrapper {
addElementToExtract(toExtract);
}
+ @Override
+ protected boolean isWhiteSpace(PsiElement element) {
+ return element instanceof PsiWhiteSpace;
+ }
+
private static PsiStatement copyElement(PsiStatement e) throws IncorrectOperationException {
// We cannot call el.copy() for 'else' since it sets context to parent 'if'.
// This causes copy to be invalidated after parent 'if' is removed by setElseBranch method.
diff --git a/java/java-impl/src/com/intellij/lang/java/JavaCommenter.java b/java/java-impl/src/com/intellij/lang/java/JavaCommenter.java
index ea5118e52944..4d20c1a9b393 100644
--- a/java/java-impl/src/com/intellij/lang/java/JavaCommenter.java
+++ b/java/java-impl/src/com/intellij/lang/java/JavaCommenter.java
@@ -85,6 +85,6 @@ public class JavaCommenter implements CodeDocumentationAwareCommenterEx {
public boolean isDocumentationCommentText(final PsiElement element) {
if (element == null) return false;
final ASTNode node = element.getNode();
- return node != null && node.getElementType() == JavaDocTokenType.DOC_COMMENT_DATA;
+ return node != null && (node.getElementType() == JavaDocTokenType.DOC_COMMENT_DATA || node.getElementType() == JavaDocTokenType.DOC_TAG_VALUE_TOKEN);
}
}
diff --git a/platform/core-api/src/com/intellij/openapi/util/SimpleTimer.java b/platform/core-api/src/com/intellij/openapi/util/SimpleTimer.java
index c04d74b0a3e1..68cc8f97a3d8 100644
--- a/platform/core-api/src/com/intellij/openapi/util/SimpleTimer.java
+++ b/platform/core-api/src/com/intellij/openapi/util/SimpleTimer.java
@@ -18,6 +18,7 @@ package com.intellij.openapi.util;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -30,21 +31,23 @@ public class SimpleTimer {
private final Timer ourTimer;
- private static final SimpleTimer ourInstance = new SimpleTimer();
- @NonNls private static final String THREAD_NAME = "SimpleTimer";
+ private static final SimpleTimer ourInstance = newInstance("Shared SimpleTimer");
private long myNextScheduledTime = Long.MAX_VALUE;
private TimerTask myNextProcessingTask;
private final Map> myTime2Task = new TreeMap>();
+ private String myThreadName;
- private SimpleTimer() {
+ private SimpleTimer(@NotNull String threadName) {
+ myThreadName = threadName;
+
final Thread thread = Thread.currentThread();
final int currentPrio = thread.getPriority();
try {
// need this becase the timer's thread will inherit the priority on creation
thread.setPriority(Thread.MIN_PRIORITY + 1);
- ourTimer = new Timer(THREAD_NAME, true);
+ ourTimer = new Timer(threadName, true);
}
finally {
thread.setPriority(currentPrio);
@@ -54,6 +57,10 @@ public class SimpleTimer {
public static SimpleTimer getInstance() {
return ourInstance;
}
+
+ public static SimpleTimer newInstance(@NotNull String name) {
+ return new SimpleTimer(name);
+ }
public SimpleTimerTask setUp(final Runnable runnable, long delay) {
synchronized (myTime2Task) {
@@ -150,7 +157,7 @@ public class SimpleTimer {
}
public boolean isTimerThread(Thread thread) {
- return THREAD_NAME.equals(thread.getName());
+ return myThreadName.equals(thread.getName());
}
void onCancelled(SimpleTimerTask task) {
diff --git a/platform/funcTests/project1/module1/scripts/generateActions/_suite.ijs b/platform/funcTests/project1/module1/scripts/generateActions/_suite.ijs
new file mode 100644
index 000000000000..4e3edad05246
--- /dev/null
+++ b/platform/funcTests/project1/module1/scripts/generateActions/_suite.ijs
@@ -0,0 +1,6 @@
+%startTest Generate actions
+
+%include extract_Superclass.ijs
+%include newClass_projectView.ijs
+
+%endTest
\ No newline at end of file
diff --git a/platform/funcTests/project1/module1/scripts/generateActions/extract_Superclass.ijs b/platform/funcTests/project1/module1/scripts/generateActions/extract_Superclass.ijs
index 7012ffb1e60a..c78f7c40a9db 100644
--- a/platform/funcTests/project1/module1/scripts/generateActions/extract_Superclass.ijs
+++ b/platform/funcTests/project1/module1/scripts/generateActions/extract_Superclass.ijs
@@ -1,12 +1,15 @@
-%startTest Create superclass
+%startTest Create superclass from popup menu
-%%include ../include/project1Init.ijs
-%%action GotoClass
-%%PsiManager\n
-
-%include ../include/init.ijs
+%include ../include/project1Init.ijs
+%action GotoClass
+FileEditorManager\n
+%call checkFocus(editorTab=FileEditorManager.java)
%call contextMenu(Refactor|Extract Superclass)
TestSuperclass\n
-%call checkFocus(dialog=Analyze and Replace Usages)
+%call waitForDialog(Analyze and Replace Usages)
+%[space]
+%call waitForDialog(Use Interface Where Possible)
+%[space]
+%call checkFocus(editorTab=FileEditorManager.java)
%endTest
\ No newline at end of file
diff --git a/platform/funcTests/project1/module1/scripts/navbar/basicTest.ijs b/platform/funcTests/project1/module1/scripts/navbar/basicTest.ijs
index ad5ac84c24ce..29ee97d49e8b 100644
--- a/platform/funcTests/project1/module1/scripts/navbar/basicTest.ijs
+++ b/platform/funcTests/project1/module1/scripts/navbar/basicTest.ijs
@@ -8,9 +8,9 @@ PsiManager\n
%[left]
%[left]
%[down]
-%call checkFocus(navBar=module1>src>com>intellij>[testProject]>idea>PsiManager|navBarPopup=[fabrique]>idea>mps)
+%call checkFocus(navBar=module1>src>com>intellij>[testProject]>idea>PsiManager|navBarPopup=fabrique>[idea]>mps)
\n
%call flushUi()
\n
-%call checkFocus(editorTab=ActiveLibrary.java)
+%call checkFocus(editorTab=FileEditorManager.java)
diff --git a/platform/lang-api/src/com/intellij/psi/search/TodoAttributes.java b/platform/lang-api/src/com/intellij/psi/search/TodoAttributes.java
index 08c9d17d9fa0..7f7b74f6d08c 100644
--- a/platform/lang-api/src/com/intellij/psi/search/TodoAttributes.java
+++ b/platform/lang-api/src/com/intellij/psi/search/TodoAttributes.java
@@ -79,7 +79,7 @@ public class TodoAttributes implements JDOMExternalizable, Cloneable {
}
private static TextAttributes getDefaultColorSchemeTextAttributes() {
- return EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.TODO_DEFAULT_ATTRIBUTES);
+ return EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.TODO_DEFAULT_ATTRIBUTES).clone();
}
public void readExternal(Element element) throws InvalidDataException {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialogBase.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialogBase.java
index af569088d49e..a8b269f15608 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialogBase.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialogBase.java
@@ -30,7 +30,6 @@ import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.psi.PsiCodeFragment;
@@ -47,7 +46,7 @@ import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.PlatformIcons;
-import com.intellij.util.ui.MacUIUtil;
+import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.table.JBListTable;
import com.intellij.util.ui.table.JBTableRow;
import com.intellij.util.ui.table.JBTableRowEditor;
@@ -282,7 +281,13 @@ public abstract class ChangeSignatureDialogBase
() {
@Override
public Boolean compute() {
- return CopyFilesOrDirectoriesHandler.checkFileExist(targetDirectory, choice, file, file.getName());
+ return CopyFilesOrDirectoriesHandler.checkFileExist(targetDirectory, choice, file, file.getName(), "Move");
}
});
if (fileExist) continue;
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java
index 60cb7ac1dbeb..77cb4110667c 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java
@@ -307,7 +307,7 @@ public class RenameProcessor extends BaseRefactoringProcessor {
if (entry.getKey() instanceof PsiFile) {
final PsiFile file = (PsiFile)entry.getKey();
final PsiDirectory containingDirectory = file.getContainingDirectory();
- if (CopyFilesOrDirectoriesHandler.checkFileExist(containingDirectory, choice, file, entry.getValue())) {
+ if (CopyFilesOrDirectoriesHandler.checkFileExist(containingDirectory, choice, file, entry.getValue(), "Rename")) {
iterator.remove();
continue;
}
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/Separator.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/Separator.java
index 92e08842edfc..9bc7e8c1519a 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/Separator.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/Separator.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.actionSystem;
import com.intellij.openapi.project.DumbAware;
+import org.jetbrains.annotations.Nullable;
/**
* Represents a separator.
@@ -28,7 +29,7 @@ public final class Separator extends AnAction implements DumbAware {
public Separator() {
}
- public Separator(String text) {
+ public Separator(@Nullable final String text) {
myText = text;
}
diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java
index db6d6546a8fc..863c1ec2387c 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java
@@ -94,8 +94,29 @@ public class FileChooser {
@Nullable final VirtualFile toSelect,
@NotNull final Consumer onChosenCallback
) {
- if (SystemInfo.isMac && isNativeMacChooserEnabled()) descriptor.putUserData(MacFileChooserDialog.NATIVE_MAC_FILE_CHOOSER_ENABLED, Boolean.TRUE);
- final FileChooserDialog dialog = FileChooserFactory.getInstance().createFileChooser(descriptor, project);
+ chooseFilesWithSlideEffect(descriptor, project, null, toSelect, onChosenCallback);
+ }
+
+ /**
+ * Shows file/folder open dialog, allows user to choose files/folders and then passes result to callback in EDT.
+ * On MacOS Open Dialog will be shown with slide effect if Macish UI is turned on.
+ * @param descriptor File chooser descriptor
+ * @param project project
+ * @param parent parent component
+ * @param toSelect file to preselect
+ * @param onChosenCallback Callback will be invoked after user have closed dialog
+ */
+ public static void chooseFilesWithSlideEffect(@NotNull final FileChooserDescriptor descriptor,
+ @Nullable final Project project,
+ @Nullable final Component parent,
+ @Nullable final VirtualFile toSelect,
+ @NotNull final Consumer onChosenCallback
+ ) {
+ if (SystemInfo.isMac && isNativeMacChooserEnabled()) descriptor.putUserData(MacFileChooserDialog.NATIVE_MAC_FILE_CHOOSER_ENABLED, Boolean.TRUE);
+ final FileChooserFactory factory = FileChooserFactory.getInstance();
+ final FileChooserDialog dialog = parent != null
+ ? factory.createFileChooser(descriptor, parent)
+ : factory.createFileChooser(descriptor, project);
if (dialog instanceof MacFileChooserDialog) {
((MacFileChooserDialog)dialog).chooseWithSheet(toSelect, project, new MacFileChooserDialog.MacFileChooserCallback() {
public void onChosen(@NotNull final VirtualFile[] files) {
diff --git a/platform/platform-api/src/com/intellij/openapi/util/EdtRunnable.java b/platform/platform-api/src/com/intellij/openapi/util/EdtRunnable.java
index 8e470f548a62..84f174706322 100644
--- a/platform/platform-api/src/com/intellij/openapi/util/EdtRunnable.java
+++ b/platform/platform-api/src/com/intellij/openapi/util/EdtRunnable.java
@@ -17,15 +17,28 @@ package com.intellij.openapi.util;
import com.intellij.util.ui.UIUtil;
-public abstract class EdtRunnable implements Runnable {
+public abstract class EdtRunnable implements ExpirableRunnable {
+
+ private boolean myExpired;
public final void run() {
UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
- runEdt();
+ if (!isExpired()) {
+ runEdt();
+ }
}
});
}
+ public void expire() {
+ myExpired = true;
+ }
+
+ @Override
+ public boolean isExpired() {
+ return myExpired;
+ }
+
public abstract void runEdt();
}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java
index df0256266971..d26dcdd0afc8 100644
--- a/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java
@@ -319,10 +319,8 @@ public class DataManagerImpl extends DataManager implements ApplicationComponent
myEventCount + "; current event count = " + currentEventCount
);
*/
- if (false) {
LOG.error("cannot share data context between Swing events; initial event count = " + myEventCount + "; current event count = " +
currentEventCount);
- }
}
Component _component = myRef.get();
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java
index c1b6548b60ff..c9684dbc24cb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java
@@ -247,19 +247,25 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa
super.stop();
- if (myDialog != null) {
- myDialog.hide();
- if (myDialog.wasShown()) {
- myFocusTrackback.restoreFocus();
- }
- else {
- myFocusTrackback.consume();
- }
- }
- myStoppedAlready = true;
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ if (myDialog != null) {
+ myDialog.hide();
+ if (myDialog.wasShown()) {
+ myFocusTrackback.restoreFocus();
+ }
+ else {
+ myFocusTrackback.consume();
+ }
+ }
- Disposer.dispose(this);
+ myStoppedAlready = true;
+
+ Disposer.dispose(ProgressWindow.this);
+ }
+ });
SwingUtilities.invokeLater(EmptyRunnable.INSTANCE); // Just to give blocking dispatching a chance to go out.
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/util/WindowSystemPlaybackCall.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/util/WindowSystemPlaybackCall.java
index 84f2f0dfd96c..6f31ee622eeb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/util/WindowSystemPlaybackCall.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/util/WindowSystemPlaybackCall.java
@@ -24,6 +24,9 @@ import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.ui.playback.PlaybackContext;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.AsyncResult;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.SimpleTimer;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.ToolWindow;
@@ -34,8 +37,10 @@ import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
+import java.awt.event.AWTEventListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
+import java.awt.event.WindowEvent;
import java.util.*;
public class WindowSystemPlaybackCall {
@@ -67,6 +72,46 @@ public class WindowSystemPlaybackCall {
return result;
}
+
+ public static AsyncResult waitForDialog(final PlaybackContext context, final String title) {
+ final AsyncResult result = new AsyncResult();
+
+ final Ref listener = new Ref();
+ listener.set(new AWTEventListener() {
+ @Override
+ public void eventDispatched(AWTEvent event) {
+ if (event.getID() == WindowEvent.WINDOW_ACTIVATED) {
+ final Window wnd = ((WindowEvent)event).getWindow();
+ if (wnd instanceof JDialog) {
+ if (title.equals(((JDialog)wnd).getTitle())) {
+ Toolkit.getDefaultToolkit().removeAWTEventListener(listener.get());
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ getUiReady(context).notify(result);
+ }
+ });
+ }
+ }
+ }
+ }
+ });
+
+ Toolkit.getDefaultToolkit().addAWTEventListener(listener.get(), WindowEvent.WINDOW_EVENT_MASK);
+
+ SimpleTimer.getInstance().setUp(new Runnable() {
+ @Override
+ public void run() {
+ Toolkit.getDefaultToolkit().removeAWTEventListener(listener.get());
+ if (!result.isProcessed()) {
+ result.setRejected("Timed out waiting for window: " + title);
+ }
+ }
+ }, Registry.intValue("actionSystem.commandProcessingTimeout"));
+
+ return result;
+ }
+
public static AsyncResult checkFocus(final PlaybackContext context, String expected) {
final AsyncResult result = new AsyncResult();
final Map expectedMap = new LinkedHashMap();
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
index 42c57c9dd791..0973b1662520 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
@@ -27,10 +27,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.ui.popup.JBPopup;
-import com.intellij.openapi.util.ActionCallback;
-import com.intellij.openapi.util.EdtRunnable;
-import com.intellij.openapi.util.Expirable;
-import com.intellij.openapi.util.ExpirableRunnable;
+import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.*;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
@@ -79,24 +76,11 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
final EdtAlarm myFocusedComponentAlaram;
private final EdtAlarm myForcedFocusRequestsAlarm;
+ private SimpleTimer myTimer = SimpleTimer.newInstance("FocusManager timer");
+
private final EdtAlarm myIdleAlarm;
private final Set myIdleRequests = new LinkedHashSet();
- private final EdtRunnable myIdleRunnable = new EdtRunnable() {
- public void runEdt() {
- if (canFlushIdleRequests()) {
- flushIdleRequests();
- }
- else {
- if (processFocusRevalidation()) {
- if (isFocusTransferReady()) {
- flushIdleRequests();
- }
- }
-
- restartIdleAlarm();
- }
- }
- };
+
private boolean myFlushWasDelayedToFixFocus;
private ExpirableRunnable myFocusRevalidator;
@@ -106,6 +90,24 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
private UiActivityMonitor myActivityMonitor;
private boolean myTypeaheadEnabled = true;
+
+ private class IdleRunnable extends EdtRunnable {
+ public void runEdt() {
+ if (canFlushIdleRequests()) {
+ flushIdleRequests();
+ }
+ else {
+ if (processFocusRevalidation()) {
+ if (isFocusTransferReady()) {
+ flushIdleRequests();
+ }
+ }
+
+ restartIdleAlarm();
+ }
+ }
+ }
+
private boolean canFlushIdleRequests() {
Component focusOwner = getFocusOwner();
return isFocusTransferReady()
@@ -128,9 +130,9 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
myQueue = IdeEventQueue.getInstance();
myActivityMonitor = UiActivityMonitor.getInstance();
- myFocusedComponentAlaram = new EdtAlarm(this);
- myForcedFocusRequestsAlarm = new EdtAlarm(this);
- myIdleAlarm = new EdtAlarm(this);
+ myFocusedComponentAlaram = new EdtAlarm();
+ myForcedFocusRequestsAlarm = new EdtAlarm();
+ myIdleAlarm = new EdtAlarm();
final AppListener myAppListener = new AppListener();
myApp.getMessageBus().connect().subscribe(ApplicationActivationListener.TOPIC, myAppListener);
@@ -183,6 +185,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@NotNull
public ActionCallback requestFocus(@NotNull final FocusCommand command, final boolean forced) {
+ assertDispatchThread();
+
if (isInternalMode) {
recordCommand(command, new Throwable(), forced);
}
@@ -460,7 +464,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
private void restartIdleAlarm() {
myIdleAlarm.cancelAllRequests();
- myIdleAlarm.addRequest(myIdleRunnable, Registry.intValue("actionSystem.focusIdleTimeout"));
+ myIdleAlarm.addRequest(new IdleRunnable(), Registry.intValue("actionSystem.focusIdleTimeout"));
}
private void flushIdleRequests() {
@@ -602,6 +606,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
}
public boolean isFocusTransferReady() {
+ assertDispatchThread();
+
if (myRunContext != null) return true;
invalidateFocusRequestsQueue();
@@ -741,6 +747,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
}
public void suspendKeyProcessingUntil(@NotNull final ActionCallback done) {
+ assertDispatchThread();
+
requestFocus(new FocusCommand(done) {
public ActionCallback run() {
return done;
@@ -749,6 +757,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
}
public Expirable getTimestamp(final boolean trackOnlyForcedCommands) {
+ assertDispatchThread();
+
return new Expirable() {
long myOwnStamp = trackOnlyForcedCommands ? myForcedCmdTimestamp : myCmdTimestamp;
@@ -760,6 +770,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@Override
public FocusRequestor getFurtherRequestor() {
+ assertDispatchThread();
+
FurtherRequestor requestor = new FurtherRequestor(this, getTimestamp(true));
myValidFurtherRequestors.add(requestor);
revalidateFurtherRequestors();
@@ -789,6 +801,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@Override
public Component getFocusOwner() {
+ assertDispatchThread();
+
Component result = null;
if (myRunContext != null) {
result = (Component)myRunContext.getData(PlatformDataKeys.CONTEXT_COMPONENT.getName());
@@ -815,6 +829,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@Override
public void runOnOwnContext(DataContext context, Runnable runnable) {
+ assertDispatchThread();
+
myRunContext = context;
try {
runnable.run();
@@ -825,12 +841,16 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
@Override
public Component getLastFocusedFor(IdeFrame frame) {
+ assertDispatchThread();
+
WeakReference ref = myLastFocused.get(frame);
return ref != null ? ref.get() : null;
}
@Override
public void toFront(JComponent c) {
+ assertDispatchThread();
+
if (c == null) return;
final Window window = UIUtil.getParentOfType(Window.class, c);
@@ -877,19 +897,20 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
}
- static class EdtAlarm {
- private final Alarm myAlarm;
-
- private EdtAlarm(Disposable parent) {
- myAlarm = new Alarm(Alarm.ThreadToUse.OWN_THREAD, parent);
- }
+ class EdtAlarm {
+ private Set myRequests = new HashSet();
+
public void cancelAllRequests() {
- myAlarm.cancelAllRequests();
+ for (EdtRunnable each : myRequests) {
+ each.expire();
+ }
+ myRequests.clear();
}
public void addRequest(EdtRunnable runnable, int delay) {
- myAlarm.addRequest(runnable, delay);
+ myRequests.add(runnable);
+ myTimer.setUp(runnable, delay);
}
}
@@ -1018,4 +1039,8 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
public boolean isFocusTransferEnabled() {
return myApp.isActive() || !Registry.is("actionSystem.suspendFocusTransferIfApplicationInactive");
}
+
+ private void assertDispatchThread() {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java
index b9a95273df92..f1497fcedde4 100644
--- a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java
+++ b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java
@@ -56,11 +56,13 @@ public abstract class JBListTable extends JPanel {
mainTable = new JBTable(model) {
@Override
protected void processKeyEvent(KeyEvent e) {
+ if (e.isAltDown()) return;
if (e.getKeyCode() == KeyEvent.VK_ENTER && e.getModifiers() == 0) {
if (!isEditing() && e.getID() == KeyEvent.KEY_PRESSED) {
editCellAt(getSelectedRow(), getSelectedColumn());
}
e.consume();
+ return;
}
//todo[kb] JBTabsImpl breaks focus traversal policy. Need a workaround here
else if (e.getKeyCode() == KeyEvent.VK_TAB) {
@@ -73,10 +75,9 @@ public abstract class JBListTable extends JPanel {
}
}
e.consume();
+ return;
}
- else {
- super.processKeyEvent(e);
- }
+ super.processKeyEvent(e);
}
@Override
diff --git a/platform/platform-resources-en/src/messages/SMTestsRunnerBundle.properties b/platform/platform-resources-en/src/messages/SMTestsRunnerBundle.properties
index d519fe788278..c698828d276d 100644
--- a/platform/platform-resources-en/src/messages/SMTestsRunnerBundle.properties
+++ b/platform/platform-resources-en/src/messages/SMTestsRunnerBundle.properties
@@ -13,7 +13,7 @@ sm.test.runner.ui.tests.tree.presentation.labels.instantiating.tests=Instantiati
sm.test.runner.ui.tests.tree.presentation.labels.not.test.results=No Test Results
sm.test.runner.ui.tests.tree.presentation.labels.was.terminated=Terminated
sm.test.runner.ui.tests.tree.presentation.labels.no.tests.were.found=No tests were found
-sm.test.runner.ui.tests.tree.presentation.labels.test.reporter.not.attached=Unable to attach test reporter to test framework
+sm.test.runner.ui.tests.tree.presentation.labels.test.reporter.not.attached=Unable to attach test reporter to test framework or test framework quit unexpectedly
sm.test.runner.ui.tests.tree.presentation.labels.no.tests.were.found.with.errors=No tests were found. Errors occurred
sm.test.runner.ui.tests.tree.presentation.labels.empty.test.suite=Empty test suite
sm.test.runner.ui.tests.tree.presentation.labels.all.tests.passed=All Tests Passed
diff --git a/platform/platform-resources/src/DefaultColorSchemesManager.xml b/platform/platform-resources/src/DefaultColorSchemesManager.xml
index 1499d4e0b511..45616099a0c3 100644
--- a/platform/platform-resources/src/DefaultColorSchemesManager.xml
+++ b/platform/platform-resources/src/DefaultColorSchemesManager.xml
@@ -1175,6 +1175,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/platform/platform-resources/src/idea/Keymap_Mac.xml b/platform/platform-resources/src/idea/Keymap_Mac.xml
index cc862b1e2b6e..2f82b8830f3a 100644
--- a/platform/platform-resources/src/idea/Keymap_Mac.xml
+++ b/platform/platform-resources/src/idea/Keymap_Mac.xml
@@ -218,7 +218,8 @@
-
+
+
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/FileUrlProvider.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/FileUrlProvider.java
index 33764f466176..a10a86bffcbc 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/FileUrlProvider.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/FileUrlProvider.java
@@ -19,6 +19,7 @@ import com.intellij.execution.Location;
import com.intellij.execution.PsiLocation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -36,7 +37,7 @@ import java.util.List;
/**
* @author Roman Chernyatchik
*/
-public class FileUrlProvider implements TestLocationProvider {
+public class FileUrlProvider implements TestLocationProvider, DumbAware {
private static final Logger LOG = Logger.getInstance(FileUrlProvider.class.getName());
@NonNls private static final String FILE_PROTOCOL_ID = "file";
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
index 5a896c2db8d1..e6ecb19be407 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
@@ -28,6 +28,7 @@ import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.ide.util.EditSourceUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.pom.Navigatable;
@@ -180,6 +181,8 @@ public class SMTestProxy extends AbstractTestProxy {
final String protocolId = TestsLocationProviderUtil.extractProtocol(myLocationUrl);
final String path = TestsLocationProviderUtil.extractPath(myLocationUrl);
+ final boolean isDumbMode = DumbService.isDumb(project);
+
if (protocolId != null && path != null) {
if (myLocator != null) {
List locations = myLocator.getLocation(protocolId, path, project);
@@ -188,6 +191,9 @@ public class SMTestProxy extends AbstractTestProxy {
}
}
for (TestLocationProvider provider : Extensions.getExtensions(TestLocationProvider.EP_NAME)) {
+ if (isDumbMode && !DumbService.isDumbAware(provider)) {
+ continue;
+ }
final List locations = provider.getLocation(protocolId, path, project);
if (!locations.isEmpty()) {
return locations.iterator().next();
diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtilTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtilTest.java
index 81fe4ead2ffa..023eb3ee610a 100644
--- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtilTest.java
+++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtilTest.java
@@ -547,7 +547,7 @@ public class TestsPresentationUtilTest extends BaseSMTRunnerTestCase {
assertEquals(PoolOfTestIcons.NOT_RAN, myRenderer.getIcon());
assertOneElement(myFragContainer.getFragments());
- assertEquals("Unable to attach test reporter to test framework", myFragContainer.getTextAt(0));
+ assertEquals("Unable to attach test reporter to test framework or test framework quit unexpectedly", myFragContainer.getTextAt(0));
assertEquals(SimpleTextAttributes.ERROR_ATTRIBUTES, myFragContainer.getAttribsAt(0));
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java
index cca7926e64b0..6b2d4e650753 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -135,8 +135,8 @@ public class CommitHelper {
if (failed > 0) {
text += ", " + failed + " " + StringUtil.pluralize("change", failed) + " failed to commit";
}
- String content = StringUtil.isEmpty(myCommitMessage) ? text : text + ": " + myCommitMessage;
- VcsBalloonProblemNotifier.NOTIFICATION_GROUP.createNotification(content, NotificationType.INFORMATION).notify( myProject);
+ String content = StringUtil.isEmpty(myCommitMessage) ? text : text + ": " + StringUtil.escapeXml(myCommitMessage);
+ VcsBalloonProblemNotifier.NOTIFICATION_GROUP.createNotification(content, NotificationType.INFORMATION).notify(myProject);
return new NotificationInfo("VCS Commit", "VCS Commit Finished", text, true);
}
};
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerHistoryManager.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerHistoryManager.java
index e8557400aafe..71cd07f8e16e 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerHistoryManager.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerHistoryManager.java
@@ -34,7 +34,8 @@ public class XDebuggerHistoryManager {
}
public void addRecentExpression(@NotNull @NonNls String id, @NotNull String expression) {
- if (expression.trim().length() == 0) return;
+ final String trimmedExpression = expression.trim();
+ if (trimmedExpression.length() == 0) return;
LinkedList list = myRecentExpressions.get(id);
if (list == null) {
@@ -44,8 +45,8 @@ public class XDebuggerHistoryManager {
if (list.size() == MAX_RECENT_EXPRESSIONS) {
list.removeLast();
}
- list.remove(expression);
- list.addFirst(expression);
+ list.remove(trimmedExpression);
+ list.addFirst(trimmedExpression);
}
public List getRecentExpressions(@NonNls String id) {
diff --git a/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java b/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java
index 540c1f8dd7a0..2687a1a6a6db 100644
--- a/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java
+++ b/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.actions.VcsQuickListContentProvider;
import git4idea.GitVcs;
+import git4idea.i18n.GitBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -66,6 +67,14 @@ public class GitQuickListContentProvider implements VcsQuickListContentProvider
add("Git.Stash", manager, actions);
add("Git.Unstash", manager, actions);
+ // Github
+ addSeparator(actions);
+ final AnAction githubRebase = manager.getAction("Github.Rebase");
+ if (githubRebase != null) {
+ actions.add(new Separator(GitBundle.message("vcs.popup.git.github.section")));
+ actions.add(githubRebase);
+ }
+
return actions;
}
@@ -81,7 +90,7 @@ public class GitQuickListContentProvider implements VcsQuickListContentProvider
return true;
}
- private void addSeparator(List actions) {
+ private void addSeparator(@NotNull final List actions) {
actions.add(new Separator());
}
diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
index d4ce5b26e37b..215633bea117 100644
--- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
+++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
@@ -516,3 +516,5 @@ branch.delete.not_fully_merged.description.not_on_branch=You are currently not o
branch.delete.merged_to.many=The branch {0} is however fully merged to the following branches: {1}.
branch.delete.merged_to.one=The branch {0} is however fully merged to the branch {1}.
branch.delete.warning=You may still delete the branch {0}, but beware that it cannot be undone.
+
+vcs.popup.git.github.section=GitHub
\ No newline at end of file
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebase.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebase.java
index 8071d1faf418..6355e05006af 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebase.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebase.java
@@ -31,7 +31,7 @@ import java.util.List;
* @date 12/10/10
*/
public class GithubRebase extends GitRebase {
- private String myParent;
+ private String myOriginName;
/**
* {@inheritDoc}
@@ -39,7 +39,7 @@ public class GithubRebase extends GitRebase {
@Nullable
protected GitLineHandler createHandler(final Project project, final List gitRoots, final VirtualFile defaultRoot) {
final GithubRebaseDialog dialog = new GithubRebaseDialog(project, gitRoots, defaultRoot);
- dialog.configure(myParent);
+ dialog.configure(myOriginName);
dialog.show();
if (!dialog.isOK()) {
return null;
@@ -47,8 +47,8 @@ public class GithubRebase extends GitRebase {
return dialog.handler();
}
- public void setRebaseOrigin(final String parent) {
- myParent = parent;
+ public void setRebaseOrigin(final String originName) {
+ myOriginName = originName;
}
}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
index 9148996e28b3..bb09ef4ee4ef 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
@@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.IconLoader;
+import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
@@ -124,15 +125,15 @@ public class GithubRebaseAction extends DumbAwareAction {
final String parentRepoUrl = "git://github.com/" + parentRepoSuffix;
// Check that corresponding remote branch is configured for the fork origin repo
- boolean remoteForParentSeen = false;
+ final Ref remoteForForkParentRepo = new Ref();
for (GitRemote gitRemote : gitRemotes) {
final String fetchUrl = gitRemote.fetchUrl();
if (fetchUrl.endsWith(parent + ".git")) {
- remoteForParentSeen = true;
+ remoteForForkParentRepo.set(gitRemote.name());
break;
}
}
- if (!remoteForParentSeen){
+ if (remoteForForkParentRepo.isNull()){
final int result = Messages.showYesNoDialog(project, "It is necessary to have '" +
parentRepoUrl +
"' as a configured remote. Add remote?", "Github Rebase",
@@ -149,8 +150,9 @@ public class GithubRebaseAction extends DumbAwareAction {
final GitSimpleHandler addRemoteHandler = new GitSimpleHandler(project, root, GitCommand.REMOTE);
addRemoteHandler.setNoSSH(true);
addRemoteHandler.setSilent(true);
- final String remoteName = parent.substring(0, parent.lastIndexOf('/'));
- addRemoteHandler.addParameters("add", remoteName, parentRepoUrl);
+
+ remoteForForkParentRepo.set("upstream");
+ addRemoteHandler.addParameters("add", remoteForForkParentRepo.get(), parentRepoUrl);
addRemoteHandler.run();
if (addRemoteHandler.getExitCode() != 0) {
showErrorMessageInEDT(project, "Failed to add GitHub remote: '" + parentRepoUrl + "'");
@@ -180,7 +182,7 @@ public class GithubRebaseAction extends DumbAwareAction {
BasicAction.saveAll();
final GithubRebase action = (GithubRebase) ActionManager.getInstance().getAction("Github.Rebase.Internal");
- action.setRebaseOrigin(parent);
+ action.setRebaseOrigin(remoteForForkParentRepo.get());
final AnActionEvent actionEvent =
new AnActionEvent(e.getInputEvent(), e.getDataContext(), e.getPlace(), e.getPresentation(), e.getActionManager(), e.getModifiers());
action.actionPerformed(actionEvent);
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java
index 6af7001bedca..a9382f961f1e 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java
@@ -365,13 +365,20 @@ public class GithubUtil {
@Nullable
public static GitRemote findGitHubRemoteBranch(final Project project, final VirtualFile root) {
+ // i.e. find origin which points on my github repo
try {
// Check that given repository is properly configured git repository
- final String host = GithubSettings.getInstance().getHost();
+ final GithubSettings githubSettings = GithubSettings.getInstance();
+ final String host = githubSettings.getHost();
+ final String username = githubSettings.getLogin();
+
+ final String userRepoMarkerSSHProtocol = host + ":" + username + "/";
+ final String userRepoMarkerOtherProtocols = host + "/" + username + "/";
+
final List gitRemotes = GitRemote.list(project, root);
for (GitRemote gitRemote : gitRemotes) {
final String pushUrl = gitRemote.pushUrl();
- if (pushUrl.contains(host)) {
+ if (pushUrl.contains(userRepoMarkerSSHProtocol) || pushUrl.contains(userRepoMarkerOtherProtocols)) {
return gitRemote;
}
}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubRebaseDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubRebaseDialog.java
index 9f381d0ea1dd..9bce8d8ef355 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubRebaseDialog.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubRebaseDialog.java
@@ -16,10 +16,13 @@
package org.jetbrains.plugins.github.ui;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitBranch;
import git4idea.rebase.GitRebaseDialog;
import git4idea.ui.GitUIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -35,14 +38,13 @@ public class GithubRebaseDialog extends GitRebaseDialog {
super(project, roots, defaultRoot);
}
- public void configure(final String parent) {
+ public void configure(final String originName) {
setTitle("Rebase GitHub");
myShowRemoteBranchesCheckBox.setSelected(true);
myShowRemoteBranchesCheckBox.getParent().remove(myShowRemoteBranchesCheckBox);
myGitRootComboBox.setEnabled(false);
myLocalBranches.clear();
- final String originName = parent.substring(0, parent.lastIndexOf('/'));
final ArrayList remoteCopy = new ArrayList();
remoteCopy.addAll(myRemoteBranches);
myRemoteBranches.clear();
@@ -55,14 +57,41 @@ public class GithubRebaseDialog extends GitRebaseDialog {
updateOntoFrom();
// Preselect remote master
- final String preselected = "/" + originName + "/master";
+ GitBranch remoteBranch = null;
+ String currentLocalBranchName = null;
+ try {
+ final GitBranch currentBranch = GitBranch.current(myProject, gitRoot());
+ if (currentBranch != null) {
+ currentLocalBranchName = currentBranch.getName();
+ }
+ }
+ catch (VcsException e) {
+ // Do noting;
+ }
+
+ if (currentLocalBranchName != null) {
+ // try to find corresponding remote branch
+ remoteBranch = findBranch("/" + originName + "/" + currentLocalBranchName);
+ }
+ if (remoteBranch == null) {
+ // else use master
+ remoteBranch = findBranch("/" + originName + "/master");
+ }
+
+ if (remoteBranch != null) {
+ myOntoComboBox.setSelectedItem(remoteBranch);
+ GitUIUtil.getTextField(myOntoComboBox).setText(remoteBranch.getFullName());
+ }
+ }
+
+ @Nullable
+ private GitBranch findBranch(@NotNull String preselected) {
for (GitBranch remoteBranch : myRemoteBranches) {
final String branchFullName = remoteBranch.getFullName();
if (branchFullName.endsWith(preselected)){
- myOntoComboBox.setSelectedItem(remoteBranch);
- GitUIUtil.getTextField(myOntoComboBox).setText(branchFullName);
- break;
+ return remoteBranch;
}
}
+ return null;
}
}
diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml
index e04d3d1a8635..e11d5f10d3e9 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -255,6 +255,7 @@
+
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyAnonymousUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyAnonymousUnwrapper.java
new file mode 100644
index 000000000000..0da4e87a5b7f
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyAnonymousUnwrapper.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.unwrap.JavaUnwrapper;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
+
+import java.util.List;
+
+public class GroovyAnonymousUnwrapper extends GroovyUnwrapper {
+ public GroovyAnonymousUnwrapper() {
+ super(CodeInsightBundle.message("unwrap.anonymous"));
+ }
+
+ public boolean isApplicableTo(PsiElement e) {
+ return e instanceof GrAnonymousClassDefinition
+ && ((GrAnonymousClassDefinition)e).getMethods().length <= 1;
+ }
+
+ @Override
+ public PsiElement collectAffectedElements(PsiElement e, List toExtract) {
+ super.collectAffectedElements(e, toExtract);
+ return findElementToExtractFrom(e);
+ }
+
+ @Override
+ protected void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException {
+ PsiElement from = findElementToExtractFrom(element);
+
+ for (PsiMethod m : ((PsiAnonymousClass)element).getMethods()) {
+ //context.extractFromCodeBlock(m.getBody(), from);
+ }
+
+ PsiElement next = from.getNextSibling();
+ if (next instanceof PsiJavaToken && ((PsiJavaToken)next).getTokenType() == JavaTokenType.SEMICOLON) {
+ context.deleteExactly(from.getNextSibling());
+ }
+ context.deleteExactly(from);
+ }
+
+ private static PsiElement findElementToExtractFrom(PsiElement el) {
+ if (el.getParent() instanceof PsiNewExpression) el = el.getParent();
+ el = findTopmostParentOfType(el, PsiMethodCallExpression.class);
+ el = findTopmostParentOfType(el, PsiAssignmentExpression.class);
+ el = findTopmostParentOfType(el, PsiDeclarationStatement.class);
+
+ while (el.getParent() instanceof PsiExpressionStatement) {
+ el = el.getParent();
+ }
+
+ return el;
+ }
+
+ private static PsiElement findTopmostParentOfType(PsiElement el, Class extends PsiElement> clazz) {
+ while (true) {
+ @SuppressWarnings({"unchecked"})
+ PsiElement temp = PsiTreeUtil.getParentOfType(el, clazz, true, PsiAnonymousClass.class);
+ if (temp == null || temp instanceof PsiFile) return el;
+ el = temp;
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyBracesUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyBracesUnwrapper.java
new file mode 100644
index 000000000000..85970ef0c1f3
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyBracesUnwrapper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.unwrap.JavaUnwrapper;
+import com.intellij.psi.*;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.plugins.groovy.lang.psi.api.formatter.GrControlStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrCatchClause;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTryCatchStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
+
+public class GroovyBracesUnwrapper extends GroovyUnwrapper {
+ public GroovyBracesUnwrapper() {
+ super(CodeInsightBundle.message("unwrap.braces"));
+ }
+
+ public boolean isApplicableTo(PsiElement e) {
+ if (e instanceof GrClosableBlock && !((GrClosableBlock)e).hasParametersSection()) {
+ PsiElement parent = e.getParent();
+ return parent instanceof GrOpenBlock || parent instanceof GrClosableBlock;
+ }
+ return false;
+ }
+
+ @Override
+ protected void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException {
+ context.extractFromCodeBlock(((GrClosableBlock)element), element);
+ context.delete(element);
+ }
+}
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyCatchRemover.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyCatchRemover.java
new file mode 100644
index 000000000000..5892563a3a51
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyCatchRemover.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.unwrap.JavaUnwrapper;
+import com.intellij.psi.PsiCatchSection;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiTryStatement;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrCatchClause;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTryCatchStatement;
+
+public class GroovyCatchRemover extends GroovyUnwrapper {
+ public GroovyCatchRemover() {
+ super(CodeInsightBundle.message("remove.catch"));
+ }
+
+ public boolean isApplicableTo(PsiElement e) {
+ return e instanceof GrCatchClause && tryHasSeveralCatches(e);
+ }
+
+ private static boolean tryHasSeveralCatches(PsiElement el) {
+ return ((GrTryCatchStatement)el.getParent()).getCatchClauses().length > 1;
+ }
+
+ @Override
+ protected void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException {
+ context.delete(element);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyForUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyForUnwrapper.java
new file mode 100644
index 000000000000..d376883f8ff4
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyForUnwrapper.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.unwrap.JavaUnwrapper;
+import com.intellij.psi.*;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrForStatement;
+
+public class GroovyForUnwrapper extends GroovyUnwrapper {
+ public GroovyForUnwrapper() {
+ super(CodeInsightBundle.message("unwrap.for"));
+ }
+
+ public boolean isApplicableTo(PsiElement e) {
+ return e instanceof GrForStatement;
+ }
+
+ @Override
+ protected void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException {
+ if (element instanceof GrForStatement) {
+ context.extractFromBlockOrSingleStatement(((GrForStatement)element).getBody(), element);
+ }
+
+ context.delete(element);
+ }
+}
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyIfUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyIfUnwrapper.java
new file mode 100644
index 000000000000..ccc386ca7dd6
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyIfUnwrapper.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.unwrap.JavaUnwrapper;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiIfStatement;
+import com.intellij.psi.PsiStatement;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+
+public class GroovyIfUnwrapper extends GroovyUnwrapper {
+ public GroovyIfUnwrapper() {
+ super(CodeInsightBundle.message("unwrap.if"));
+ }
+
+ public boolean isApplicableTo(PsiElement e) {
+ return e instanceof GrIfStatement && !isElseBlock(e);
+ }
+
+ @Override
+ protected void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException {
+ GrStatement then = ((GrIfStatement)element).getThenBranch();
+ context.extractFromBlockOrSingleStatement(then, element);
+
+ context.delete(element);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyMethodParameterUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyMethodParameterUnwrapper.java
new file mode 100644
index 000000000000..287337f92a3b
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyMethodParameterUnwrapper.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+
+import java.util.List;
+
+public class GroovyMethodParameterUnwrapper extends GroovyUnwrapper {
+ public GroovyMethodParameterUnwrapper() {
+ super("");
+ }
+
+ @Override
+ public String getDescription(PsiElement e) {
+ String text = e.getText();
+ if (text.length() > 20) text = text.substring(0, 17) + "...";
+ return CodeInsightBundle.message("unwrap.method.parameter", text);
+ }
+
+ public boolean isApplicableTo(PsiElement e) {
+ return (e instanceof GrExpression) && e.getParent() instanceof GrArgumentList;
+ }
+
+ @Override
+ public PsiElement collectAffectedElements(PsiElement e, List toExtract) {
+ super.collectAffectedElements(e, toExtract);
+ return e.getParent().getParent();
+ }
+
+ @Override
+ protected void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException {
+ PsiElement methodCall = element.getParent().getParent();
+ context.extractElement(element, methodCall);
+ if (methodCall.getParent() instanceof GrArgumentList) {
+ context.delete(methodCall);
+ }
+ else {
+ context.deleteExactly(methodCall);
+ }
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovySynchronizedUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovySynchronizedUnwrapper.java
new file mode 100644
index 000000000000..a61c3e352429
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovySynchronizedUnwrapper.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.unwrap.JavaUnwrapper;
+import com.intellij.psi.PsiCodeBlock;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiSynchronizedStatement;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrSynchronizedStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
+
+public class GroovySynchronizedUnwrapper extends GroovyUnwrapper {
+ public GroovySynchronizedUnwrapper() {
+ super(CodeInsightBundle.message("unwrap.synchronized"));
+ }
+
+ public boolean isApplicableTo(PsiElement e) {
+ return e instanceof GrSynchronizedStatement;
+ }
+
+ @Override
+ protected void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException {
+ GrOpenBlock body = ((GrSynchronizedStatement)element).getBody();
+ context.extractFromCodeBlock(body, element);
+
+ context.delete(element);
+ }
+}
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyTryUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyTryUnwrapper.java
new file mode 100644
index 000000000000..1df5cc300ef1
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyTryUnwrapper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.unwrap.JavaUnwrapper;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiTryStatement;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrFinallyClause;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTryCatchStatement;
+
+public class GroovyTryUnwrapper extends GroovyUnwrapper {
+ public GroovyTryUnwrapper() {
+ super(CodeInsightBundle.message("unwrap.try"));
+ }
+
+ public boolean isApplicableTo(PsiElement e) {
+ return e instanceof GrTryCatchStatement;
+ }
+
+ @Override
+ protected void doUnwrap(final PsiElement element, final Context context) throws IncorrectOperationException {
+ GrTryCatchStatement trySt = (GrTryCatchStatement)element;
+
+ context.extractFromCodeBlock(trySt.getTryBlock(), trySt);
+
+ GrFinallyClause finallyClause = trySt.getFinallyClause();
+ if (finallyClause != null) {
+ context.extractFromCodeBlock(finallyClause.getBody(), trySt);
+ }
+
+ context.delete(trySt);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapDescriptor.java
new file mode 100644
index 000000000000..d0ef0644e10a
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapDescriptor.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.unwrap.*;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.SelectionModel;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class GroovyUnwrapDescriptor extends JavaUnwrapDescriptor {
+
+ @Override
+ protected Unwrapper[] createUnwrappers() {
+ return new Unwrapper[]{
+ new GroovyIfUnwrapper(),
+ new GroovyWhileUnwrapper(),
+ new GroovyTryUnwrapper(),
+ new GroovySynchronizedUnwrapper(),
+ new GroovyMethodParameterUnwrapper(),
+ new GroovyForUnwrapper(),
+ new GroovyCatchRemover(),
+ new GroovyBracesUnwrapper(),
+ };
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java
new file mode 100644
index 000000000000..dfa011475155
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.unwrap.AbstractUnwrapper;
+import com.intellij.codeInsight.unwrap.Unwrapper;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.*;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
+import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public abstract class GroovyUnwrapper extends AbstractUnwrapper {
+ public GroovyUnwrapper(String description) {
+ super(description);
+ }
+
+ @Override
+ protected Context createContext(boolean isEffective) {
+ return new Context(isEffective);
+ }
+
+ public static boolean isElseBlock(@Nullable final PsiElement element) {
+ if (element == null) return false;
+ final PsiElement parent = element.getParent();
+ return parent instanceof GrIfStatement && element == ((GrIfStatement)parent).getElseBranch();
+ }
+
+ protected static class Context extends AbstractUnwrapper.AbstractContext {
+
+ public Context(boolean isEffective) {
+ super(isEffective);
+ }
+
+ public void extractFromBlockOrSingleStatement(GrStatement block, PsiElement from) throws IncorrectOperationException {
+ if (block instanceof GrBlockStatement) {
+ extractFromCodeBlock(((GrBlockStatement)block).getBlock(), from);
+ }
+ else if (block != null) {
+ extract(block, block, from);
+ }
+ }
+
+ public void extractFromCodeBlock(GrCodeBlock block, PsiElement from) throws IncorrectOperationException {
+ if (block == null) return;
+
+ PsiElement rBrace = block.getRBrace();
+ PsiElement lBrace = block.getLBrace();
+
+ PsiElement firstBodyElement;
+ if (lBrace == null) {
+ firstBodyElement = null;
+ }
+ else {
+ firstBodyElement = lBrace.getNextSibling();
+ if (firstBodyElement == rBrace) {
+ firstBodyElement = null;
+ }
+ }
+
+ PsiElement lastBodyElement;
+ if (rBrace == null) {
+ lastBodyElement = null;
+ }
+ else {
+ lastBodyElement = rBrace.getPrevSibling();
+ if (lastBodyElement == lBrace) {
+ lastBodyElement = null;
+ }
+ }
+
+ extract(firstBodyElement, lastBodyElement, from);
+ }
+
+ protected boolean isWhiteSpace(PsiElement element) {
+ return PsiUtil.isLeafElementOfType(element, TokenSets.WHITE_SPACES_SET);
+ }
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyWhileUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyWhileUnwrapper.java
new file mode 100644
index 000000000000..403d9089f9a9
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyWhileUnwrapper.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2009 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 org.jetbrains.plugins.groovy.unwrap;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.psi.PsiDoWhileStatement;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiLoopStatement;
+import com.intellij.psi.PsiStatement;
+import com.intellij.psi.impl.source.tree.java.PsiWhileStatementImpl;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrWhileStatement;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+public class GroovyWhileUnwrapper extends GroovyUnwrapper {
+ public GroovyWhileUnwrapper() {
+ super(CodeInsightBundle.message("unwrap.while"));
+ }
+
+ public boolean isApplicableTo(PsiElement e) {
+ return e instanceof GrWhileStatement;
+ }
+
+ @Override
+ protected void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException {
+ GrStatement body = ((GrWhileStatement)element).getBody();
+
+ context.extractFromBlockOrSingleStatement(body, element);
+ context.delete(element);
+ }
+}
\ No newline at end of file