From b2ef1abf03f16e3ec89cd761aa3634b30a01c273 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 19 Sep 2011 15:58:30 +0400 Subject: [PATCH] IDEA-45767 ("unwrap" for groovy) Add unwrapper for 'else' branch. --- .../lang/psi/GroovyPsiElementFactory.java | 2 +- .../psi/impl/GroovyPsiElementFactoryImpl.java | 2 +- .../impl/statements/GrIfStatementImpl.java | 14 ++++ .../groovy/unwrap/GroovyElseRemover.java | 58 +++++++++++++++ .../groovy/unwrap/GroovyElseUnwrapper.java | 56 +++++++++++++++ .../unwrap/GroovyElseUnwrapperBase.java | 72 +++++++++++++++++++ .../groovy/unwrap/GroovyUnwrapDescriptor.java | 17 ++--- .../groovy/unwrap/GroovyUnwrapper.java | 28 +++++--- 8 files changed, 225 insertions(+), 24 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseRemover.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseUnwrapper.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseUnwrapperBase.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java index e0a7e41d1bd3..b32078927371 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java @@ -84,7 +84,7 @@ public abstract class GroovyPsiElementFactory implements JVMElementFactory { public abstract GrNamedArgument createNamedArgument(String name, GrExpression expression); public abstract GrStatement createStatementFromText(String text); - public abstract GrStatement createStatementFromText(String text, PsiElement context); + public abstract GrStatement createStatementFromText(String text, @Nullable PsiElement context); public abstract GrBlockStatement createBlockStatement(GrStatement... statements); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index fa0b448a3978..ae643b7d546d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -519,7 +519,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { } @Override - public GrStatement createStatementFromText(String text, PsiElement context) { + public GrStatement createStatementFromText(String text, @Nullable PsiElement context) { PsiFile file = createGroovyFile(text, false, context); assert ((GroovyFileBase) file).getTopStatements()[0] instanceof GrStatement; return (GrStatement) ((GroovyFileBase) file).getTopStatements()[0]; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrIfStatementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrIfStatementImpl.java index 4e0456c8156b..c41a0f0833e4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrIfStatementImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrIfStatementImpl.java @@ -77,6 +77,20 @@ public class GrIfStatementImpl extends GroovyPsiElementImpl implements GrIfState return null; } + @Override + public void deleteChildInternal(@NotNull ASTNode child) { + GrStatement elseBranch = getElseBranch(); + + if (elseBranch != null && child == elseBranch.getNode()) { + PsiElement elseKeywordElement = findChildByType(GroovyTokenTypes.kELSE); + if (elseKeywordElement != null) { + super.deleteChildInternal(elseKeywordElement.getNode()); + } + } + + super.deleteChildInternal(child); + } + public T replaceThenBranch(T newBranch) throws IncorrectOperationException { return PsiImplUtil.replaceBody(newBranch, getThenBranch(), getNode(), getProject()); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseRemover.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseRemover.java new file mode 100644 index 000000000000..81fed34aa094 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseRemover.java @@ -0,0 +1,58 @@ +/* + * 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.GrIfStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; + +import java.util.List; + +public class GroovyElseRemover extends GroovyElseUnwrapperBase { + public GroovyElseRemover() { + super(CodeInsightBundle.message("remove.else")); + } + + @Override + public PsiElement collectAffectedElements(PsiElement e, List toExtract) { + super.collectAffectedElements(e, toExtract); + return ((GrIfStatement)e.getParent()).getElseBranch(); + } + + @Override + protected void unwrapElseBranch(GrStatement branch, PsiElement parent, Context context) throws IncorrectOperationException { + if (branch instanceof GrIfStatement) { + deleteSelectedElseIf((GrIfStatement)branch, context); + } + else { + context.delete(branch); + } + } + + private static void deleteSelectedElseIf(GrIfStatement selectedBranch, Context context) throws IncorrectOperationException { + GrIfStatement parentIf = (GrIfStatement)selectedBranch.getParent(); + GrStatement childElse = selectedBranch.getElseBranch(); + + if (childElse == null) { + context.delete(selectedBranch); + return; + } + + context.setElseBranch(parentIf, childElse); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseUnwrapper.java new file mode 100644 index 000000000000..bff4a7f396d1 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseUnwrapper.java @@ -0,0 +1,56 @@ +/* + * 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.GrIfStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; + +import java.util.List; + +public class GroovyElseUnwrapper extends GroovyElseUnwrapperBase { + public GroovyElseUnwrapper() { + super(CodeInsightBundle.message("unwrap.else")); + } + + @Override + public PsiElement collectAffectedElements(PsiElement e, List toExtract) { + super.collectAffectedElements(e, toExtract); + return findTopmostIfStatement(e); + } + + @Override + protected void unwrapElseBranch(GrStatement branch, PsiElement parent, Context context) throws IncorrectOperationException { + // if we have 'else if' then we have to extract statements from the 'if' branch + if (branch instanceof GrIfStatement) { + branch = ((GrIfStatement)branch).getThenBranch(); + } + + parent = findTopmostIfStatement(parent); + + context.extractFromBlockOrSingleStatement(branch, parent); + context.delete(parent); + } + + private static PsiElement findTopmostIfStatement(PsiElement parent) { + while (parent.getParent() instanceof GrIfStatement) { + parent = parent.getParent(); + } + return parent; + } +} \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseUnwrapperBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseUnwrapperBase.java new file mode 100644 index 000000000000..cf33b38cb81e --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyElseUnwrapperBase.java @@ -0,0 +1,72 @@ +/* + * 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.psi.PsiElement; +import com.intellij.psi.PsiIfStatement; +import com.intellij.psi.PsiStatement; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +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.util.PsiUtil; + +import java.util.Set; + +public abstract class GroovyElseUnwrapperBase extends GroovyUnwrapper { + public GroovyElseUnwrapperBase(String description) { + super(description); + } + + public boolean isApplicableTo(PsiElement e) { + return (isElseBlock(e) || isElseKeyword(e)) && isValidConstruct(e); + } + + private static boolean isElseKeyword(PsiElement e) { + PsiElement p = e.getParent(); + return p instanceof GrIfStatement && PsiUtil.isLeafElementOfType(e, GroovyTokenTypes.kELSE); + } + + private static boolean isValidConstruct(PsiElement e) { + return ((GrIfStatement)e.getParent()).getElseBranch() != null; + } + + @Override + public void collectElementsToIgnore(PsiElement element, Set result) { + PsiElement parent = element.getParent(); + + while (parent instanceof GrIfStatement) { + result.add(parent); + parent = parent.getParent(); + } + } + + @Override + protected void doUnwrap(PsiElement element, Context context) throws IncorrectOperationException { + GrStatement elseBranch; + + if (isElseKeyword(element)) { + elseBranch = ((GrIfStatement)element.getParent()).getElseBranch(); + } + else { + elseBranch = (GrStatement)element; + } + + unwrapElseBranch(elseBranch, element.getParent(), context); + } + + protected abstract void unwrapElseBranch(GrStatement branch, PsiElement parent, Context context) throws IncorrectOperationException; +} \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapDescriptor.java index d0ef0644e10a..02c1e486239c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapDescriptor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapDescriptor.java @@ -15,19 +15,8 @@ */ 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; +import com.intellij.codeInsight.unwrap.JavaUnwrapDescriptor; +import com.intellij.codeInsight.unwrap.Unwrapper; public class GroovyUnwrapDescriptor extends JavaUnwrapDescriptor { @@ -42,6 +31,8 @@ public class GroovyUnwrapDescriptor extends JavaUnwrapDescriptor { new GroovyForUnwrapper(), new GroovyCatchRemover(), new GroovyBracesUnwrapper(), + new GroovyElseRemover(), + new GroovyElseUnwrapper(), }; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java index dfa011475155..1995bdd5b434 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java @@ -16,24 +16,17 @@ 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.psi.PsiElement; 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.GroovyPsiElementFactory; 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); @@ -99,5 +92,22 @@ public abstract class GroovyUnwrapper extends AbstractUnwrapper