From 3fb647577faf91bae47d4338c1a26f97b7c85cb4 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 31 Jan 2012 16:35:46 +0400 Subject: [PATCH] EA-32658 - initialize field in method while introduce field --- .../lang/psi/api/util/GrStatementOwner.java | 1 + .../lang/psi/impl/GroovyFileBaseImpl.java | 1 + .../impl/statements/blocks/GrBlockImpl.java | 1 + .../statements/clauses/GrCaseSectionImpl.java | 1 + .../GroovyRefactoringBundle.properties | 6 +- .../refactoring/GroovyRefactoringUtil.java | 120 ++++-------------- .../extract/ExtractHandlerBase.java | 2 +- .../introduce/GrIntroduceHandlerBase.java | 10 +- .../field/GrIntroduceFieldHandler.java | 60 +++++---- .../GrIntroduceParameterHandler.java | 4 +- .../introduce/field/GrIntroduceFieldTest.java | 4 + .../InitializeInCurrentMethod.groovy | 8 ++ .../InitializeInCurrentMethod_after.groovy | 10 ++ 13 files changed, 97 insertions(+), 131 deletions(-) create mode 100644 plugins/groovy/testdata/refactoring/introduceField/InitializeInCurrentMethod.groovy create mode 100644 plugins/groovy/testdata/refactoring/introduceField/InitializeInCurrentMethod_after.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/util/GrStatementOwner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/util/GrStatementOwner.java index 758b2360d651..851e6ffa7429 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/util/GrStatementOwner.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/util/GrStatementOwner.java @@ -28,6 +28,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; */ public interface GrStatementOwner extends GroovyPsiElement { + @NotNull GrStatement addStatementBefore(@NotNull GrStatement statement, @Nullable GrStatement anchor) throws IncorrectOperationException; void removeElements(PsiElement[] elements) throws IncorrectOperationException; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java index d4a83cba0ec7..8c5f23028ba9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java @@ -187,6 +187,7 @@ public abstract class GroovyFileBaseImpl extends PsiFileBase implements GroovyFi return findChildrenByClass(GrStatement.class); } + @NotNull public GrStatement addStatementBefore(@NotNull GrStatement statement, @Nullable GrStatement anchor) throws IncorrectOperationException { final PsiElement result = addBefore(statement, anchor); if (anchor != null) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java index a4b905bda277..3b187166df19 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java @@ -144,6 +144,7 @@ public abstract class GrBlockImpl extends LazyParseablePsiElement implements GrC return result.toArray(new GrStatement[result.size()]); } + @NotNull public GrStatement addStatementBefore(@NotNull GrStatement element, @Nullable GrStatement anchor) throws IncorrectOperationException { if (anchor == null && getRBrace() == null) { throw new IncorrectOperationException(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/clauses/GrCaseSectionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/clauses/GrCaseSectionImpl.java index f55361a82edd..dac4361ef6f4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/clauses/GrCaseSectionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/clauses/GrCaseSectionImpl.java @@ -74,6 +74,7 @@ public class GrCaseSectionImpl extends GroovyPsiElementImpl implements GrCaseSec return findChildrenByClass(GrStatement.class); } + @NotNull public GrStatement addStatementBefore(@NotNull GrStatement element, @Nullable GrStatement anchor) throws IncorrectOperationException { ASTNode elemNode = element.copy().getNode(); assert elemNode != null; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index 9ef43f59b460..41aa8b233267 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -26,7 +26,6 @@ declare.final=Declare final press.escape.to.remove.the.highlighting=Press Escape to remove the highlighting specify.the.type.explicitly=Specify the type explicitly variable.of.type=Variable of type: -name.prompt=Name: selected.expression.has.void.type=Selected expression has void type selected.expression.in.command.expression=Selected expression is part of command expression introduced.variable.conflicts.with.parameter.0=Introduced variable will conflict with parameter {0} @@ -44,14 +43,12 @@ cannot.find.a.single.definition.to.inline.field=No initializer present for the f inline.local.command=Inline Variable local.varaible.is.lvalue=Variable to be inlined has occurrence as lvalue in assignment inline.local.variable.prompt.0.1=Inline local variable ''{0}''? -inline.field.prompt=Inline field ''{0}''? ######################################################################################################################## # Extract method ######################################################################################################################## extract.method.title=Extract Method selected.block.should.represent.a.statement.set=Selected block should represent a set of statements or an expression -cannot.perform.analysis=Code analysis cannot be performed multiple.output.values=There are multiple output values for the selected code fragment selected.block.contains.invocation.of.another.class.constructor=Selected block contains invocation of another class constructor specify.type.label=Specify return &type explicitly @@ -84,7 +81,6 @@ refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow refactoring.is.not.supported.for.recursive.methods=Refactoring is not supported for recursive methods refactoring.cannot.be.applied.to.constructors=Refactoring cannot be applied to constructors refactoring.is.not.supported.in.parameter.initializers=Refactoring is not supported in parameter initializers -multiple.method.inline.is.not.suppored=Multiple method inline is not supported inline.method.prompt.0=Inline method ''{0}'' invocation? refactoring.is.available.only.for.method.calls=Refactoring is available only for method calls method.is.not.accessible.form.context.0=Method {0} used in inlined method is not accessible from call site @@ -127,7 +123,7 @@ refactored.method.will.cover.closure.property=Refactored method will override cl changeSignature.not.throwable.type=Wrong type: ''{0}'' for exception, should extend java.lang.Throwable changeSignature.wrong.type.for.exception=Wrong type: ''{0}'' for exception changeSignature.no.type.for.exception=Specify a type for exception -no.occurences.found=No occurences found +no.occurrences.found=No occurrences found expression.is.not.constant=Selected expression is not a constant class.does.not.exists=Class {0} does not exists class.does.not.exist.in.the.module=Class does not exists in the module. Do you want to create it? diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java index e79950900934..6b231263878d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java @@ -35,7 +35,7 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtilBase; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.ReflectionCache; @@ -131,10 +131,6 @@ public abstract class GroovyRefactoringUtil { } public static PsiElement[] getExpressionOccurrences(@NotNull PsiElement expr, @NotNull PsiElement scope) { - return getExpressionOccurrences(expr, scope, false); - } - - public static PsiElement[] getExpressionOccurrences(@NotNull PsiElement expr, @NotNull PsiElement scope, boolean gotoInner) { ArrayList occurrences = new ArrayList(); Comparator comparator = new Comparator() { public int compare(PsiElement element1, PsiElement element2) { @@ -144,9 +140,7 @@ public abstract class GroovyRefactoringUtil { element2 instanceof GrParameter) { final String name1 = ((GrParameter) element1).getName(); final String name2 = ((GrParameter) element2).getName(); - if (name1 != null && name2 != null) { - return name1.compareTo(name2); - } + return name1.compareTo(name2); } return 1; } @@ -162,7 +156,7 @@ public abstract class GroovyRefactoringUtil { } else { collectOccurrences(expr, scope, occurrences, comparator, scope instanceof GrTypeDefinition || scope instanceof GroovyFileBase); } - return PsiUtilBase.toPsiElementArray(occurrences); + return PsiUtilCore.toPsiElementArray(occurrences); } @@ -192,8 +186,8 @@ public abstract class GroovyRefactoringUtil { tempContainer instanceof GrIfStatement; } - public static void sortOccurrences(PsiElement[] occurences) { - Arrays.sort(occurences, new Comparator() { + public static void sortOccurrences(PsiElement[] occurrences) { + Arrays.sort(occurrences, new Comparator() { public int compare(PsiElement elem1, PsiElement elem2) { final int offset1 = elem1.getTextRange().getStartOffset(); final int offset2 = elem2.getTextRange().getStartOffset(); @@ -302,7 +296,7 @@ public abstract class GroovyRefactoringUtil { return new PsiElement[]{parent.getParent()}; } - // calcualte children + // calculate children PsiElement[] children = PsiElement.EMPTY_ARRAY; PsiElement psiChild = parent.getFirstChild(); if (psiChild != null) { @@ -311,7 +305,7 @@ public abstract class GroovyRefactoringUtil { result.add(psiChild); psiChild = psiChild.getNextSibling(); } - children = PsiUtilBase.toPsiElementArray(result); + children = PsiUtilCore.toPsiElementArray(result); } @@ -338,7 +332,7 @@ public abstract class GroovyRefactoringUtil { } } - return PsiUtilBase.toPsiElementArray(possibleStatements); + return PsiUtilCore.toPsiElementArray(possibleStatements); } public static boolean isSuperOrThisCall(GrStatement statement, boolean testForSuper, boolean testForThis) { @@ -365,7 +359,7 @@ public abstract class GroovyRefactoringUtil { } } - public static boolean haswrongContinueStatements(PsiElement element) { + public static boolean hasWrongContinueStatements(PsiElement element) { ArrayList vector = new ArrayList(); addContinueStatements(element, vector); return !vector.isEmpty(); @@ -457,70 +451,6 @@ public abstract class GroovyRefactoringUtil { return id; } - public static GrExpression convertJavaExpr2GroovyExpr(PsiElement expr) { - final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(expr.getProject()); - - final List localVariables = new ArrayList(); - final List fields = new ArrayList(); - final List parameters = new ArrayList(); - - expr.accept(new JavaRecursiveElementVisitor() { - @Override - public void visitReferenceExpression(PsiReferenceExpression expression) { - final PsiExpression qualifierExpression = expression.getQualifierExpression(); - if (qualifierExpression != null && !(qualifierExpression instanceof PsiThisExpression)) return; - - PsiElement el = expression.resolve(); - if (el instanceof PsiField) { - fields.add((PsiField)el); - } - else if (el instanceof PsiParameter) { - parameters.add((PsiParameter)el); - } - else if (el instanceof PsiLocalVariable) { - localVariables.add((PsiLocalVariable)el); - } - super.visitReferenceExpression(expression); - } - }); - - PsiJavaFile file = (PsiJavaFile)expr.getContainingFile(); - - StringBuilder cf = new StringBuilder(); - - final PsiPackageStatement packageStatement = file.getPackageStatement(); - if (packageStatement != null) cf.append(packageStatement.getText()); - - final PsiImportList importList = file.getImportList(); - if (importList != null) cf.append(importList.getText()); - - cf.append("class A{"); - for (PsiField field : fields) { - cf.append(field.getText()); - } - - cf.append("void foo("); - for (int i = 0, parametersSize = parameters.size() - 1; i < parametersSize; i++) { - PsiParameter parameter = parameters.get(i); - cf.append(parameter.getText()).append(','); - } - if (parameters.size() > 0) { - cf.append(parameters.get(parameters.size() - 1).getText()); - } - cf.append("){"); - for (PsiLocalVariable localVariable : localVariables) { - cf.append(localVariable.getText()); - } - cf.append("Object _________________ooooooo_______________="); - cf.append(expr.getText()); - cf.append(";}}"); - final GroovyFile grFile = factory.createGroovyFile(cf.toString(), false, expr); - - final GrMethod method = (GrMethod)grFile.getClasses()[0].getMethods()[0]; - final GrVariableDeclaration variableDeclaration = (GrVariableDeclaration)method.getBlock().getStatements()[0]; - return variableDeclaration.getVariables()[0].getInitializerGroovy(); - } - public static int verifySafeCopyExpression(GrExpression expression) { return verifySafeCopyExpressionSubElement(expression); } @@ -649,19 +579,20 @@ public abstract class GroovyRefactoringUtil { } /** - * adds block statement in parent of expr if needed. For Example: + * adds block statement in parent of statement if needed. For Example: * while (true) a=foo() * will be replaced with * while(true) {a=foo()} - * @param expr - * @return corresponding expr inside block if it has been created or expr itself. + * @param statement + * @return corresponding statement inside block if it has been created or statement itself. * @throws com.intellij.util.IncorrectOperationException */ - public static GrExpression addBlockIntoParent(GrExpression expr) throws IncorrectOperationException { + @NotNull + public static Type addBlockIntoParent(@NotNull Type statement) throws IncorrectOperationException { - PsiElement parent = expr.getParent(); - PsiElement child = expr; + PsiElement parent = statement.getParent(); + PsiElement child = statement; while (!(parent instanceof GrLoopStatement) && !(parent instanceof GrIfStatement) && !(parent instanceof GrVariableDeclarationOwner) && @@ -675,11 +606,11 @@ public abstract class GroovyRefactoringUtil { } assert parent != null; if (parent instanceof GrVariableDeclarationOwner) { - return expr; + return statement; } - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(expr.getProject()); - PsiElement tempStmt = expr; + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(statement.getProject()); + PsiElement tempStmt = statement; while (parent != tempStmt.getParent()) { tempStmt = tempStmt.getParent(); } @@ -697,14 +628,17 @@ public abstract class GroovyRefactoringUtil { ifStatement.replaceElseBranch(blockStatement); } } - GrStatement statement = blockStatement.getBlock().addStatementBefore(toAdd, null); - if (statement instanceof GrReturnStatement) { - expr = ((GrReturnStatement)statement).getReturnValue(); + GrStatement result = blockStatement.getBlock().addStatementBefore(toAdd, null); + if (result instanceof GrReturnStatement) { + //noinspection ConstantConditions,unchecked + statement = (Type)((GrReturnStatement)result).getReturnValue(); } else { - expr = (GrExpression)statement; + //noinspection unchecked + statement = (Type)result; } - return expr; + + return statement; } public static boolean isDiamondNewOperator(GrExpression expression) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java index 44060186614d..fd3ed96b3bb0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractHandlerBase.java @@ -143,7 +143,7 @@ public abstract class ExtractHandlerBase implements RefactoringActionHandler { for (GrStatement statement : statements) { hasInterruptingStatements = - GroovyRefactoringUtil.hasWrongBreakStatements(statement) || GroovyRefactoringUtil.haswrongContinueStatements(statement); + GroovyRefactoringUtil.hasWrongBreakStatements(statement) || GroovyRefactoringUtil.hasWrongContinueStatements(statement); if (hasInterruptingStatements) break; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java index 6ed7c8e88f1b..0656d2356a73 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java @@ -54,7 +54,6 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import org.jetbrains.plugins.groovy.refactoring.NameValidator; -import org.jetbrains.plugins.groovy.refactoring.introduce.field.GrIntroduceFieldHandler; import java.util.ArrayList; import java.util.Collections; @@ -203,7 +202,7 @@ public abstract class GrIntroduceHandlerBase filtered = new ArrayList(); - for (PsiElement occurence : occurences) { - if (!shouldBeStatic(occurence, clazz)) { - filtered.add(occurence); + for (PsiElement occurrence : occurrences) { + if (!shouldBeStatic(occurrence, clazz)) { + filtered.add(occurrence); } } return ContainerUtil.toArray(filtered, new PsiElement[filtered.size()]); @@ -180,18 +181,17 @@ public class GrIntroduceFieldHandler extends GrIntroduceHandlerBasei + } + } +} diff --git a/plugins/groovy/testdata/refactoring/introduceField/InitializeInCurrentMethod_after.groovy b/plugins/groovy/testdata/refactoring/introduceField/InitializeInCurrentMethod_after.groovy new file mode 100644 index 000000000000..e126a9b38c03 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceField/InitializeInCurrentMethod_after.groovy @@ -0,0 +1,10 @@ +class X { + final def f + + def foo() { + if (true) { + f = "5" + ptint f + } + } +}