From 0f469fbc8469bbf48a06a567fdc539f58c3e2b6b Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Mon, 28 Oct 2013 16:22:25 +0400 Subject: [PATCH 1/9] fix CCE in introduce field to script --- .../introduce/field/GrIntroduceFieldHandler.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java index 0211ee378a4c..dad877d0da96 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java @@ -140,17 +140,16 @@ public class GrIntroduceFieldHandler extends GrIntroduceFieldHandlerBase result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION, GrIntroduceFieldSettings.Init.CONSTRUCTOR); - - GrTypeDefinition clazz = (GrTypeDefinition)context.getScope(); + PsiElement scope = context.getScope(); if (replaceAll) { - PsiElement anchor = GrIntroduceHandlerBase.findAnchor(context.getOccurrences(), clazz); + PsiElement anchor = GrIntroduceHandlerBase.findAnchor(context.getOccurrences(), scope); if (anchor != null) { result.add(GrIntroduceFieldSettings.Init.CUR_METHOD); } } - if (TestFrameworks.getInstance().isTestClass(clazz)) { + if (scope instanceof GrTypeDefinition && TestFrameworks.getInstance().isTestClass((PsiClass)scope)) { result.add(GrIntroduceFieldSettings.Init.SETUP_METHOD); } From 28533327badb1ae195cfc04bc2255b293a2233d9 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Tue, 29 Oct 2013 18:20:24 +0400 Subject: [PATCH 2/9] unnecessary 'static' --- .../refactoring/introduce/inplace/OccurrencesChooser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/OccurrencesChooser.java b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/OccurrencesChooser.java index 04a67b29b829..444bc492aa81 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/OccurrencesChooser.java +++ b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/OccurrencesChooser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,7 +44,7 @@ import java.util.List; // This prevents languages with polyadic expressions or sequences // from reusing it, use simpleChooser instead. public abstract class OccurrencesChooser { - public static enum ReplaceChoice { + public enum ReplaceChoice { NO("Replace this occurrence only"), NO_WRITE("Replace all occurrences but write"), ALL("Replace all {0} occurrences"); private final String myDescription; From 12d0c6400b7b3db466d63eb3355716815f15c8a4 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Wed, 30 Oct 2013 18:36:21 +0400 Subject: [PATCH 3/9] shorten reference --- .../refactoring/rename/inplace/InplaceRefactoring.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java index 33f23494b341..fc7335595a10 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import com.intellij.lang.refactoring.NamesValidator; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.command.impl.FinishMarkAction; @@ -327,7 +328,7 @@ public abstract class InplaceRefactoring { new WriteCommandAction(myProject, getCommandName()) { @Override - protected void run(com.intellij.openapi.application.Result result) throws Throwable { + protected void run(Result result) throws Throwable { startTemplate(builder); } }.execute(); From 4c1e69746ac8dc4dbad8a04de62dd30e35569139 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Wed, 30 Oct 2013 18:41:51 +0400 Subject: [PATCH 4/9] canceling introduce variable --- .../GrAbstractInplaceIntroducer.java | 246 ++++++ .../introduce/GrNewIntroduceHandlerBase.java | 765 ++++++++++++++++++ .../variable/GrInplaceVariableIntroducer.java | 158 +++- .../GrIntroduceLocalVariableProcessor.java | 14 +- .../variable/GrIntroduceVariableHandler.java | 107 +-- 5 files changed, 1167 insertions(+), 123 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java new file mode 100644 index 000000000000..c8c52d3f60d4 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java @@ -0,0 +1,246 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.introduce; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Computable; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.SmartPointerManager; +import com.intellij.psi.SmartPsiElementPointer; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer; +import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; +import com.intellij.util.Function; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; + +import java.util.List; + + +/** + * Created by Max Medvedev on 10/28/13 + */ +public abstract class GrAbstractInplaceIntroducer extends AbstractInplaceIntroducer { + + private OccurrencesChooser.ReplaceChoice myReplaceChoice; + + private RangeMarker myVarMarker; + private final PsiFile myFile; + + private final GrIntroduceContext myContext; + + public GrAbstractInplaceIntroducer(String title, + OccurrencesChooser.ReplaceChoice replaceChoice, + GrIntroduceContext context) { + super(context.getProject(), context.getEditor(), context.getExpression(), context.getVar(), context.getOccurrences(), title, GroovyFileType.GROOVY_FILE_TYPE); + myReplaceChoice = replaceChoice; + myContext = context; + myFile = context.getPlace().getContainingFile(); + } + + public GrIntroduceContext getContext() { + return myContext; + } + + @Override + public void setReplaceAllOccurrences(boolean allOccurrences) { + throw new IncorrectOperationException("don't invoke this method"); + } + + @Override + public GrExpression restoreExpression(PsiFile containingFile, GrVariable variable, RangeMarker marker, String exprText) { + if (exprText == null) return null; + if (variable == null || !variable.isValid()) return null; + final PsiElement refVariableElement = containingFile.findElementAt(marker.getStartOffset()); + final PsiElement refVariableElementParent = refVariableElement != null ? refVariableElement.getParent() : null; + GrExpression expression = + refVariableElementParent instanceof GrNewExpression && refVariableElement.getNode().getElementType() == GroovyTokenTypes.kNEW + ? (GrNewExpression)refVariableElementParent + : PsiTreeUtil.getParentOfType(refVariableElement, GrReferenceExpression.class); + if (expression instanceof GrReferenceExpression && !(expression.getParent() instanceof GrMethodCall)) { + final String referenceName = ((GrReferenceExpression)expression).getReferenceName(); + if (((GrReferenceExpression)expression).resolve() == variable || + Comparing.strEqual(variable.getName(), referenceName) || + Comparing.strEqual(exprText, referenceName)) { + return (GrExpression)expression + .replace(GroovyPsiElementFactory.getInstance(myProject).createExpressionFromText(exprText, variable)); + } + } + if (expression == null) { + expression = PsiTreeUtil.getParentOfType(refVariableElement, GrExpression.class); + } + while (expression instanceof GrReferenceExpression) { + final PsiElement parent = expression.getParent(); + if (parent instanceof GrMethodCallExpression) { + if (parent.getText().equals(exprText)) return (GrExpression)parent; + } + if (parent instanceof GrExpression) { + expression = (GrExpression)parent; + if (expression.getText().equals(exprText)) { + return expression; + } + } + else { + return null; + } + } + if (expression != null && expression.isValid() && expression.getText().equals(exprText)) { + return expression; + } + + if (refVariableElementParent instanceof GrExpression && refVariableElementParent.getText().equals(exprText)) { + return (GrExpression)refVariableElementParent; + } + + return null; + } + + @Nullable + @Override + protected PsiElement getNameIdentifier() { + return ((GrVariable)myElementToRename).getNameIdentifierGroovy(); + } + + @Override + protected GrVariable getVariable() { + if (myVarMarker == null) return null; + + int offset = myVarMarker.getStartOffset(); + PsiElement at = myFile.findElementAt(offset); + GrVariable var = PsiTreeUtil.getParentOfType(at, GrVariable.class); + return var; + } + + @Override + protected void performIntroduce() { + final List markers = getOccurrenceMarkers(); + GrIntroduceContext context = new GrIntroduceContext() { + @NotNull + @Override + public Project getProject() { + return myProject; + } + + @Override + public Editor getEditor() { + return myEditor; + } + + @Nullable + @Override + public GrExpression getExpression() { + return (GrExpression)getExpr(); + } + + @Nullable + @Override + public GrVariable getVar() { + return getLocalVariable(); + } + + @Nullable + @Override + public StringPartInfo getStringPart() { + return null; + } + + @NotNull + @Override + public PsiElement[] getOccurrences() { + List result = ContainerUtil.map(markers, new Function() { + @Override + public PsiElement fun(RangeMarker marker) { + return GroovyRefactoringUtil.findElementInRange(myFile, marker.getStartOffset(), marker.getEndOffset(), GrExpression.class); + } + }); + return PsiUtilCore.toPsiElementArray(result); + } + + @Override + public PsiElement getScope() { + return myScope; + } + + @NotNull + @Override + public PsiElement getPlace() { + GrExpression expression = getExpression(); + return expression != null ? expression : getLocalVariable(); + } + }; + runRefactoring(context, getSettings(), true); + } + + @Nullable + @Override + protected GrVariable createFieldToStartTemplateOn(boolean replaceAll, String[] names) { + + final Settings settings = getInitialSettingsForInplace(myContext, myReplaceChoice, names); + if (settings == null) return null; + + SmartPsiElementPointer pointer = ApplicationManager.getApplication().runWriteAction(new Computable>() { + @Override + public SmartPsiElementPointer compute() { + GrVariable var = runRefactoring(myContext, settings, false); + return var != null ? SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(var) : null; + } + }); + + if (pointer != null) { + GrVariable var = pointer.getElement(); + if (var != null) { + myVarMarker = myContext.getEditor().getDocument().createRangeMarker(var.getTextRange()); + } + return var; + } + else { + return null; + } + } + + protected abstract GrVariable runRefactoring(GrIntroduceContext context, Settings settings, boolean processUsages); + + @Nullable + protected abstract Settings getInitialSettingsForInplace(@NotNull GrIntroduceContext context, + @NotNull OccurrencesChooser.ReplaceChoice choice, + String[] names); + + @Override + public boolean isReplaceAllOccurrences() { + return myReplaceChoice != OccurrencesChooser.ReplaceChoice.NO || myContext.getOccurrences().length == 1; + } + + protected abstract Settings getSettings(); + +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java new file mode 100644 index 000000000000..3be3b0ac7740 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java @@ -0,0 +1,765 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.introduce; + +import com.intellij.codeInsight.highlighting.HighlightManager; +import com.intellij.diagnostic.LogMessageEx; +import com.intellij.lang.LanguageRefactoringSupport; +import com.intellij.lang.refactoring.RefactoringSupportProvider; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.editor.colors.EditorColors; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pass; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.psi.*; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.refactoring.IntroduceTargetChooser; +import com.intellij.refactoring.RefactoringActionHandler; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; +import com.intellij.refactoring.util.CommonRefactoringUtil; +import com.intellij.util.Function; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseLabel; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; +import org.jetbrains.plugins.groovy.refactoring.NameValidator; + +import java.util.*; + +import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipParentheses; + +/** + * Created by Max Medvedev on 10/29/13 + */ +public abstract class GrNewIntroduceHandlerBase implements RefactoringActionHandler { + private static final Logger LOG = Logger.getInstance(GrIntroduceHandlerBase.class); + + public static final Function GR_EXPRESSION_RENDERER = new Function() { + @Override + public String fun(@NotNull GrExpression expr) { + return expr.getText(); + } + }; + + public static GrExpression insertExplicitCastIfNeeded(GrVariable variable, GrExpression initializer) { + PsiType ltype = findLValueType(initializer); + PsiType rtype = initializer.getType(); + + GrExpression rawExpr = (GrExpression)skipParentheses(initializer, false); + + if (ltype == null || TypesUtil.isAssignableWithoutConversions(ltype, rtype, initializer) || !TypesUtil.isAssignable(ltype, rtype, initializer)) { + return rawExpr; + } + else { // implicit coercion should be replaced with explicit cast + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(variable.getProject()); + GrSafeCastExpression cast = + (GrSafeCastExpression)factory.createExpressionFromText("a as B"); + cast.getOperand().replaceWithExpression(rawExpr, false); + cast.getCastTypeElement().replace(factory.createTypeElement(ltype)); + return cast; + } + } + + @Nullable + private static PsiType findLValueType(GrExpression initializer) { + if (initializer.getParent() instanceof GrAssignmentExpression && ((GrAssignmentExpression)initializer.getParent()).getRValue() == initializer) { + return ((GrAssignmentExpression)initializer.getParent()).getLValue().getNominalType(); + } + else if (initializer.getParent() instanceof GrVariable) { + return ((GrVariable)initializer.getParent()).getDeclaredType(); + } + else { + return null; + } + } + + @NotNull + protected abstract String getRefactoringName(); + + @NotNull + protected abstract String getHelpID(); + + @NotNull + protected abstract Scope[] findPossibleScopes(GrExpression expression, GrVariable variable, StringPartInfo stringPart, Editor editor); + + protected abstract void checkExpression(@NotNull GrExpression selectedExpr) throws GrRefactoringError; + + protected abstract void checkVariable(@NotNull GrVariable variable) throws GrRefactoringError; + + protected abstract void checkStringLiteral(@NotNull StringPartInfo info) throws GrRefactoringError; + + protected abstract void checkOccurrences(@NotNull PsiElement[] occurrences); + + @NotNull + protected abstract GrIntroduceDialog getDialog(@NotNull GrIntroduceContext context); + + @Nullable + public abstract GrVariable runRefactoring(@NotNull GrIntroduceContext context, @NotNull Settings settings); + + protected abstract GrAbstractInplaceIntroducer getIntroducer(@NotNull GrIntroduceContext context, + OccurrencesChooser.ReplaceChoice choice); + + protected abstract Settings getSettingsForInplace(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice); + + public static Map> fillChoice(GrIntroduceContext context) { + HashMap> map = ContainerUtil.newLinkedHashMap(); + + if (context.getExpression() != null) { + map.put(OccurrencesChooser.ReplaceChoice.NO, Collections.singletonList(context.getExpression())); + } + else if (context.getStringPart() != null) { + map.put(OccurrencesChooser.ReplaceChoice.NO, Collections.singletonList(context.getStringPart())); + } + + PsiElement[] occurrences = context.getOccurrences(); + if (occurrences.length > 1) { + map.put(OccurrencesChooser.ReplaceChoice.ALL, Arrays.asList(occurrences)); + } + return map; + } + + @NotNull + public static List collectExpressions(final PsiFile file, final Editor editor, final int offset, boolean acceptVoidCalls) { + int correctedOffset = correctOffset(editor, offset); + final PsiElement elementAtCaret = file.findElementAt(correctedOffset); + final List expressions = new ArrayList(); + + for (GrExpression expression = PsiTreeUtil.getParentOfType(elementAtCaret, GrExpression.class); + expression != null; + expression = PsiTreeUtil.getParentOfType(expression, GrExpression.class)) { + if (expressions.contains(expression)) continue; + if (expression instanceof GrParenthesizedExpression && !expressions.contains(((GrParenthesizedExpression)expression).getOperand())) { + expressions.add(((GrParenthesizedExpression)expression).getOperand()); + } + if (expressionIsIncorrect(expression, acceptVoidCalls)) continue; + + expressions.add(expression); + } + return expressions; + } + + public static boolean expressionIsIncorrect(@Nullable GrExpression expression, boolean acceptVoidCalls) { + if (expression instanceof GrParenthesizedExpression) return true; + if (PsiUtil.isSuperReference(expression)) return true; + if (expression instanceof GrAssignmentExpression) return true; + if (expression instanceof GrReferenceExpression && expression.getParent() instanceof GrCall) { + final GroovyResolveResult resolveResult = ((GrReferenceExpression)expression).advancedResolve(); + final PsiElement resolved = resolveResult.getElement(); + return resolved instanceof PsiMethod && !resolveResult.isInvokedOnProperty() || resolved instanceof PsiClass; + } + + if (expression instanceof GrClosableBlock && expression.getParent() instanceof GrStringInjection) return true; + if (!acceptVoidCalls && expression instanceof GrMethodCall && PsiType.VOID == expression.getType()) return true; + + return false; + } + + public static int correctOffset(Editor editor, int offset) { + Document document = editor.getDocument(); + CharSequence text = document.getCharsSequence(); + int correctedOffset = offset; + int textLength = document.getTextLength(); + if (offset >= textLength) { + correctedOffset = textLength - 1; + } + else if (!Character.isJavaIdentifierPart(text.charAt(offset))) { + correctedOffset--; + } + + if (correctedOffset < 0) { + correctedOffset = offset; + } + else { + char c = text.charAt(correctedOffset); + if (c == ';' && correctedOffset != 0) {//initially caret on the end of line + correctedOffset--; + } + else if (!Character.isJavaIdentifierPart(c) && c != ')' && c != ']' && c != '}' && c != '\'' && c != '"' && c != '/') { + correctedOffset = offset; + } + } + return correctedOffset; + } + + @Nullable + public static GrVariable findVariableAtCaret(final PsiFile file, final Editor editor, final int offset) { + final int correctOffset = correctOffset(editor, offset); + final PsiElement elementAtCaret = file.findElementAt(correctOffset); + final GrVariable variable = PsiTreeUtil.getParentOfType(elementAtCaret, GrVariable.class); + if (variable != null && variable.getNameIdentifierGroovy().getTextRange().contains(correctOffset)) return variable; + return null; + } + + public void invoke(final @NotNull Project project, final Editor editor, final PsiFile file, final @Nullable DataContext dataContext) { + final SelectionModel selectionModel = editor.getSelectionModel(); + if (!selectionModel.hasSelection()) { + final int offset = editor.getCaretModel().getOffset(); + + final List expressions = collectExpressions(file, editor, offset, false); + if (expressions.isEmpty()) { + final GrVariable variable = findVariableAtCaret(file, editor, offset); + if (variable == null || variable instanceof GrField || variable instanceof GrParameter) { + selectionModel.selectLineAtCaret(); + } + else { + final TextRange textRange = variable.getTextRange(); + selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset()); + } + } + else if (expressions.size() == 1) { + final TextRange textRange = expressions.get(0).getTextRange(); + selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset()); + } + else { + IntroduceTargetChooser.showChooser(editor, expressions, new Pass() { + public void pass(final GrExpression selectedValue) { + invoke(project, editor, file, selectedValue.getTextRange().getStartOffset(), selectedValue.getTextRange().getEndOffset()); + } + }, GR_EXPRESSION_RENDERER); + return; + } + } + invoke(project, editor, file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); + } + + @Override + public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { + // Does nothing + } + + public void getContextAndInvoke(@NotNull final Project project, + @NotNull final Editor editor, + @Nullable final GrExpression expression, + @Nullable final GrVariable variable, + @Nullable final StringPartInfo stringPart) { + final Scope[] scopes = findPossibleScopes(expression, variable, stringPart, editor); + + Pass callback = new Pass() { + @Override + public void pass(Scope scope) { + GrIntroduceContext context = getContext(project, editor, expression, variable, stringPart, scope); + invokeImpl(project, context, editor); + } + }; + + if (scopes.length == 0) { + CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle + .getCannotRefactorMessage(getRefactoringName() + "is not available in current scope"), + getRefactoringName(), getHelpID()); + } + else if (scopes.length == 1) { + callback.pass(scopes[0]); + } + else { + showScopeChooser(scopes, callback, editor); + } + } + + protected abstract void showScopeChooser(Scope[] scopes, Pass callback, Editor editor); + + public GrIntroduceContext getContext(@NotNull Project project, + @NotNull Editor editor, + @Nullable GrExpression expression, + @Nullable GrVariable variable, + @Nullable StringPartInfo stringPart, + @NotNull PsiElement scope) { + if (variable != null) { + final List list = Collections.synchronizedList(new ArrayList()); + ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor() { + @Override + public boolean process(PsiReference psiReference) { + final PsiElement element = psiReference.getElement(); + if (element != null) { + list.add(element); + } + return true; + } + }); + final PsiElement[] occurrences = list.toArray(new PsiElement[list.size()]); + return new GrIntroduceContextImpl(project, editor, variable.getInitializerGroovy(), variable, stringPart, occurrences, scope); + } + else if (expression != null ) { + final PsiElement[] occurrences = findOccurrences(expression, scope); + return new GrIntroduceContextImpl(project, editor, expression, variable, stringPart, occurrences, scope); + } + else { + assert stringPart != null; + return new GrIntroduceContextImpl(project, editor, expression, variable, stringPart, new PsiElement[]{stringPart.getLiteral()}, scope); + } + } + + private boolean invokeImpl(final Project project, final GrIntroduceContext context, final Editor editor) { + try { + if (!CommonRefactoringUtil.checkReadOnlyStatus(project, context.getOccurrences())) { + return false; + } + checkOccurrences(context.getOccurrences()); + + + if (isInplace(context.getEditor(), context.getPlace())) { + Map> occurrencesMap = fillChoice(context); + new OccurrencesChooser(editor) { + @Override + protected TextRange getOccurrenceRange(Object occurrence) { + if (occurrence instanceof PsiElement) { + return ((PsiElement)occurrence).getTextRange(); + } + else if (occurrence instanceof StringPartInfo) { + return ((StringPartInfo)occurrence).getRange(); + } + else { + return null; + } + } + }.showChooser(new Pass() { + @Override + public void pass(final OccurrencesChooser.ReplaceChoice choice) { + getIntroducer(context, choice).startInplaceIntroduceTemplate(); + } + }, occurrencesMap); + } + else { + final Settings settings = showDialog(context); + if (settings == null) return false; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + runRefactoring(context, settings); + } + }); + } + + return true; + } + catch (GrRefactoringError e) { + CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID()); + return false; + } + } + + @NotNull + protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) { + final PsiElement[] occurrences = GroovyRefactoringUtil.getExpressionOccurrences(skipParentheses(expression, false), scope); + if (occurrences == null || occurrences.length == 0) { + throw new GrRefactoringError(GroovyRefactoringBundle.message("no.occurrences.found")); + } + return occurrences; + } + + private void invoke(@NotNull final Project project, + @NotNull final Editor editor, + @NotNull PsiFile file, + int startOffset, + int endOffset) throws GrRefactoringError { + try { + PsiDocumentManager.getInstance(project).commitAllDocuments(); + if (!(file instanceof GroovyFileBase)) { + throw new GrRefactoringError(GroovyRefactoringBundle.message("only.in.groovy.files")); + } + if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) { + throw new GrRefactoringError(RefactoringBundle.message("readonly.occurences.found")); + } + + GrExpression selectedExpr = findExpression(file, startOffset, endOffset); + final GrVariable variable = findVariable(file, startOffset, endOffset); + final StringPartInfo stringPart = StringPartInfo.findStringPart(file, startOffset, endOffset); + if (variable != null) { + checkVariable(variable); + } + else if (selectedExpr != null) { + checkExpression(selectedExpr); + } + else if (stringPart != null) { + checkStringLiteral(stringPart); + } + else { + throw new GrRefactoringError(null); + } + + getContextAndInvoke(project, editor, selectedExpr, variable, stringPart); + } + catch (GrRefactoringError e) { + CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID()); + } + } + + public static RangeMarker createRange(Document document, StringPartInfo part) { + if (part == null) { + return null; + } + TextRange range = part.getRange().shiftRight(part.getLiteral().getTextRange().getStartOffset()); + return document.createRangeMarker(range.getStartOffset(), range.getEndOffset(), true); + + } + + @Nullable + public static RangeMarker createRange(@NotNull Document document, @Nullable PsiElement expression) { + if (expression == null) { + return null; + } + TextRange range = expression.getTextRange(); + return document.createRangeMarker(range.getStartOffset(), range.getEndOffset(), false); + } + + + public static boolean isInplace(@NotNull Editor editor, @NotNull PsiElement place) { + final RefactoringSupportProvider supportProvider = LanguageRefactoringSupport.INSTANCE.forLanguage(place.getLanguage()); + return supportProvider != null && + editor.getSettings().isVariableInplaceRenameEnabled() && + supportProvider.isInplaceIntroduceAvailable(place, place) && + !ApplicationManager.getApplication().isUnitTestMode(); + } + + @Nullable + public static GrVariable findVariable(@NotNull PsiFile file, int startOffset, int endOffset) { + GrVariable var = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrVariable.class); + if (var == null) { + final GrVariableDeclaration variableDeclaration = + GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrVariableDeclaration.class); + if (variableDeclaration == null) return null; + final GrVariable[] variables = variableDeclaration.getVariables(); + if (variables.length == 1) { + var = variables[0]; + } + } + if (var instanceof GrParameter || var instanceof GrField) { + return null; + } + return var; + } + + @Nullable + public static GrVariable findVariable(@NotNull GrStatement statement) { + if (!(statement instanceof GrVariableDeclaration)) return null; + final GrVariableDeclaration variableDeclaration = (GrVariableDeclaration)statement; + final GrVariable[] variables = variableDeclaration.getVariables(); + + GrVariable var = null; + if (variables.length == 1) { + var = variables[0]; + } + if (var instanceof GrParameter || var instanceof GrField) { + return null; + } + return var; + } + + + @Nullable + public static GrExpression findExpression(PsiFile file, int startOffset, int endOffset) { + GrExpression selectedExpr = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrExpression.class); + return findExpression(selectedExpr); + } + + @Nullable + public static GrExpression findExpression(GrStatement selectedExpr) { + if (!(selectedExpr instanceof GrExpression)) return null; + + GrExpression selected = (GrExpression)selectedExpr; + while (selected instanceof GrParenthesizedExpression) selected = ((GrParenthesizedExpression)selected).getOperand(); + if (selected == null) return null; + PsiType type = selected.getType(); + if (type != null) type = TypeConversionUtil.erasure(type); + + if (PsiType.VOID.equals(type)) { + return null; + } + + return selected; + } + + @Nullable + private Settings showDialog(@NotNull GrIntroduceContext context) { + + // Add occurrences highlighting + ArrayList highlighters = new ArrayList(); + HighlightManager highlightManager = null; + if (context.getEditor() != null) { + highlightManager = HighlightManager.getInstance(context.getProject()); + EditorColorsManager colorsManager = EditorColorsManager.getInstance(); + TextAttributes attributes = colorsManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES); + if (context.getOccurrences().length > 1) { + highlightManager.addOccurrenceHighlights(context.getEditor(), context.getOccurrences(), attributes, true, highlighters); + } + } + + GrIntroduceDialog dialog = getDialog(context); + + dialog.show(); + if (dialog.isOK()) { + if (context.getEditor() != null) { + for (RangeHighlighter highlighter : highlighters) { + highlightManager.removeSegmentHighlighter(context.getEditor(), highlighter); + } + } + return dialog.getSettings(); + } + else { + if (context.getOccurrences().length > 1) { + WindowManager.getInstance().getStatusBar(context.getProject()) + .setInfo(GroovyRefactoringBundle.message("press.escape.to.remove.the.highlighting")); + } + } + return null; + } + + @Nullable + public static PsiElement findAnchor(@NotNull PsiElement[] occurrences, + @NotNull PsiElement container) { + if (occurrences.length == 0) return null; + + PsiElement candidate; + if (occurrences.length == 1) { + candidate = occurrences[0]; + candidate = findContainingStatement(candidate); + } + else { + candidate = occurrences[0]; + while (candidate != null && candidate.getParent() != container) { + candidate = candidate.getParent(); + } + } + + final GrStringInjection injection = PsiTreeUtil.getParentOfType(candidate, GrStringInjection.class); + if (injection != null && !injection.getText().contains("\n")) { + candidate = findContainingStatement(injection); + } + + if (candidate == null) return null; + + if ((container instanceof GrWhileStatement) && + candidate.equals(((GrWhileStatement)container).getCondition())) { + return container; + } + if ((container instanceof GrIfStatement) && + candidate.equals(((GrIfStatement)container).getCondition())) { + return container; + } + if ((container instanceof GrForStatement) && + candidate.equals(((GrForStatement)container).getClause())) { + return container; + } + + while (candidate instanceof GrIfStatement && + candidate.getParent() instanceof GrIfStatement && + ((GrIfStatement)candidate.getParent()).getElseBranch() == candidate) { + candidate = candidate.getParent(); + } + return candidate; + } + + public static void assertStatement(PsiElement anchor, PsiElement[] occurrences, PsiElement scope) { + if (!(anchor instanceof GrStatement)) { + StringBuilder error = new StringBuilder("scope:"); + error.append(scope.getText()); + error.append("\n---------------------------------------\n\n"); + error.append("occurrences: "); + for (PsiElement occurrence : occurrences) { + error.append(occurrence.getText()); + error.append("\n------------------\n"); + } + + LogMessageEx.error(LOG, "cannot find anchor for variable", error.toString()); + } + } + + + @Nullable + private static PsiElement findContainingStatement(@Nullable PsiElement candidate) { + while (candidate != null && !PsiUtil.isExpressionStatement(candidate)) { + candidate = candidate.getParent(); + if (candidate instanceof GrCaseLabel) candidate = candidate.getParent(); + } + return candidate; + } + + public static void deleteLocalVar(@NotNull GrIntroduceContext context) { + final GrVariable resolved = resolveLocalVar(context); + + final PsiElement parent = resolved.getParent(); + if (((GrVariableDeclaration)parent).getVariables().length == 1) { + parent.delete(); + } + else { + GrExpression initializer = resolved.getInitializerGroovy(); + if (initializer != null) initializer.delete(); //don't special check for tuple, but this line is for the tuple case + resolved.delete(); + } + } + + @NotNull + public static GrVariable resolveLocalVar(@NotNull GrIntroduceContext context) { + final GrVariable var = context.getVar(); + if (var != null) { + return var; + } + + final GrReferenceExpression expression = (GrReferenceExpression)context.getExpression(); + assert expression != null; + + final PsiElement resolved = expression.resolve(); + assert resolved instanceof GrVariable; + return (GrVariable)resolved; + } + + public static boolean hasLhs(@NotNull final PsiElement[] occurrences) { + for (PsiElement element : occurrences) { + if (element instanceof GrReferenceExpression) { + if (PsiUtil.isLValue((GroovyPsiElement)element)) return true; + if (ControlFlowUtils.isIncOrDecOperand((GrReferenceExpression)element)) return true; + } + } + return false; + } + + @NotNull + public static PsiElement getCurrentPlace(@Nullable GrExpression expr, + @Nullable GrVariable var, + @Nullable StringPartInfo stringPartInfo) { + if (var != null) return var; + if (expr != null) return expr; + if (stringPartInfo != null) return stringPartInfo.getLiteral(); + + throw new IncorrectOperationException(); + } + + @NotNull + public static GrExpression generateExpressionFromStringPart(final StringPartInfo stringPart, final Project project) { + Data data = new Data(stringPart); + String startQuote = data.getStartQuote(); + TextRange range = data.getRange(); + String literalText = data.getText(); + String endQuote = data.getEndQuote(); + + final String substringLiteral = startQuote + range.substring(literalText) + endQuote; + return GroovyPsiElementFactory.getInstance(project).createExpressionFromText(substringLiteral); + } + + @NotNull + public static GrExpression processLiteral(final String varName, final StringPartInfo stringPart, final Project project) { + Data data = new Data(stringPart); + String startQuote = data.getStartQuote(); + TextRange range = data.getRange(); + String literalText = data.getText(); + String endQuote = data.getEndQuote(); + + String prefix = literalText.substring(0, range.getStartOffset()) ; + String suffix = literalText.substring(range.getEndOffset()); + + StringBuilder buffer = new StringBuilder(); + if (!prefix.equals(startQuote)) { + buffer.append(prefix).append(endQuote).append('+'); + } + buffer.append(varName); + if (!suffix.equals(endQuote)) { + buffer.append('+').append(startQuote).append(suffix); + } + + final GrExpression concatenation = GroovyPsiElementFactory.getInstance(project).createExpressionFromText(buffer); + + final GrExpression concat = stringPart.getLiteral().replaceWithExpression(concatenation, false); + if (concat instanceof GrReferenceExpression) { + return concat; + } + else { + assert concat instanceof GrBinaryExpression; + final GrExpression left = ((GrBinaryExpression)concat).getLeftOperand(); + if (left instanceof GrReferenceExpression) { + return left; + } + else { + assert left instanceof GrBinaryExpression; + final GrExpression right = ((GrBinaryExpression)left).getRightOperand(); + assert right != null; + return right; + } + } + } + + public interface Validator extends NameValidator { + boolean isOK(GrIntroduceDialog dialog); + } + + private static class Data { + private String myText; + private String myStartQuote; + private String myEndQuote; + private TextRange myRange; + + public Data(final StringPartInfo stringPartInfo) { + assert stringPartInfo != null; + + final GrLiteral literal = stringPartInfo.getLiteral(); + + myText = literal.getText(); + + myStartQuote = GrStringUtil.getStartQuote(myText); + myEndQuote = GrStringUtil.getEndQuote(myText); + final TextRange dataRange = new TextRange(myStartQuote.length(), myText.length() - myEndQuote.length()); + + myRange = stringPartInfo.getRange().intersection(dataRange); + } + + public String getText() { + return myText; + } + + public String getStartQuote() { + return myStartQuote; + } + + public String getEndQuote() { + return myEndQuote; + } + + public TextRange getRange() { + return myRange; + } + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java index eb19b097c90f..d7d3fb7c33cc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java @@ -16,25 +16,29 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.variable; import com.intellij.codeInsight.template.TemplateBuilderImpl; +import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.RangeMarker; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; +import com.intellij.openapi.keymap.Keymap; +import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.psi.*; +import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; +import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.ui.NonFocusableCheckBox; -import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrFinalListener; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; +import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; import org.jetbrains.plugins.groovy.settings.GroovyApplicationSettings; import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression; @@ -42,30 +46,41 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.LinkedHashSet; -import java.util.List; /** - * @author Max Medvedev + * Created by Max Medvedev on 10/29/13 */ -public class GrInplaceVariableIntroducer extends GrInplaceIntroducer { +public abstract class GrInplaceVariableIntroducer extends GrAbstractInplaceIntroducer { private JCheckBox myCanBeFinalCb; + private SmartTypePointer myTypePointer; - public GrInplaceVariableIntroducer(GrVariable elementToRename, - Editor editor, - Project project, - String title, - List occurrences, - @Nullable PsiElement elementToIntroduce) { - super(elementToRename, editor, project, title, occurrences, elementToIntroduce); - } - - @Override - public LinkedHashSet suggestNames(GrIntroduceContext context) { - return ContainerUtil.newLinkedHashSet(GroovyNameSuggestionUtil.suggestVariableNames(getVariable().getInitializerGroovy(), new GroovyVariableValidator(context))); + public GrInplaceVariableIntroducer(String title, + OccurrencesChooser.ReplaceChoice replaceChoice, + GrIntroduceContext context) { + super(title, replaceChoice, context); + setAdvertisementText(getAdvertisementText()); } @Nullable + private static String getAdvertisementText() { + final Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); + final Shortcut[] shortcuts = keymap.getShortcuts("PreviousTemplateVariable"); + if (shortcuts.length > 0) { + return "Press " + KeymapUtil.getShortcutText(shortcuts[0]) + " to change type"; + } + return null; + } + + @Override + protected String getActionName() { + return GrIntroduceVariableHandler.REFACTORING_NAME; + } + + @Override + protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) { + return GroovyNameSuggestionUtil.suggestVariableNames(getContext().getExpression(), new GroovyVariableValidator(getContext())); + } + @Override protected JComponent getComponent() { myCanBeFinalCb = new NonFocusableCheckBox("Declare final"); @@ -91,22 +106,58 @@ public class GrInplaceVariableIntroducer extends GrInplaceIntroducer { panel.setBorder(null); if (myCanBeFinalCb != null) { - panel.add(myCanBeFinalCb, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + panel.add(myCanBeFinalCb, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, + new Insets(5, 5, 5, 5), 0, 0)); } - panel.add(Box.createVerticalBox(), new GridBagConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0,0)); + panel.add(Box.createVerticalBox(), + new GridBagConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); return panel; - } + @Nullable @Override - public void finish(boolean success) { - super.finish(success); + protected GroovyIntroduceVariableSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context, + @NotNull final OccurrencesChooser.ReplaceChoice choice, + final String[] names) { + return new GroovyIntroduceVariableSettings() { + private final CanonicalTypes.Type myType; - if (success) { - GroovyApplicationSettings.getInstance().INTRODUCE_LOCAL_SELECT_DEF = getVariable().getDeclaredType() == null; - } + { + GrExpression expression = context.getExpression(); + StringPartInfo stringPart = context.getStringPart(); + GrVariable var = context.getVar(); + PsiType type = expression != null ? expression.getType() : + var != null ? var.getType() : + stringPart != null ? stringPart.getLiteral().getType() : + null; + myType = type != null ? CanonicalTypes.createTypeWrapper(type) : null; + } + + + @Override + public boolean isDeclareFinal() { + return myCanBeFinalCb != null ? myCanBeFinalCb.isSelected() : false; + } + + @Nullable + @Override + public String getName() { + return names[0]; + } + + @Override + public boolean replaceAllOccurrences() { + return choice == OccurrencesChooser.ReplaceChoice.ALL; + } + + @Nullable + @Override + public PsiType getSelectedType() { + return myType != null ? myType.getType(context.getPlace(), context.getPlace().getManager()) : null; + } + }; } @Override @@ -119,4 +170,47 @@ public class GrInplaceVariableIntroducer extends GrInplaceIntroducer { : PsiUtil.findModifierInList(variable.getModifierList(), GrModifier.DEF); builder.replaceElement(element, "Variable_type", typeExpression, true, true); } -} + + protected GroovyIntroduceVariableSettings getSettings() { + return new GroovyIntroduceVariableSettings() { + @Override + public boolean isDeclareFinal() { + return myCanBeFinalCb.isSelected(); + } + + @Nullable + @Override + public String getName() { + return GrInplaceVariableIntroducer.this.getInputName(); + } + + @Override + public boolean replaceAllOccurrences() { + return isReplaceAllOccurrences(); + } + + @Nullable + @Override + public PsiType getSelectedType() { + return myTypePointer != null ? myTypePointer.getType() : null; + } + }; + } + + @Override + protected void saveSettings(@NotNull GrVariable variable) { + GroovyApplicationSettings.getInstance().INTRODUCE_LOCAL_SELECT_DEF = variable.getDeclaredType() == null; + } + + @Override + protected int getCaretOffset() { + return getVariable().getNameIdentifierGroovy().getTextRange().getEndOffset(); + } + + @Override + protected void restoreState(GrVariable psiField) { + PsiType declaredType = getVariable().getDeclaredType(); + myTypePointer = declaredType != null ? SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(declaredType) : null; + super.restoreState(psiField); + } +} \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java index 3d01195b1c4b..9546a20a24a4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java @@ -46,26 +46,26 @@ import java.util.List; /** * @author Max Medvedev */ -public class GrIntroduceLocalVariableProcessor { +public abstract class GrIntroduceLocalVariableProcessor { private static final Logger LOG = Logger.getInstance(GrIntroduceLocalVariableProcessor.class); private final GrIntroduceContext myContext; private final GroovyIntroduceVariableSettings mySettings; + private final boolean myProcessUsages; private final PsiElement[] myOccurrences; private GrExpression myExpression; - private final GrIntroduceVariableHandler myHandler; public GrIntroduceLocalVariableProcessor(@NotNull GrIntroduceContext context, @NotNull GroovyIntroduceVariableSettings settings, @NotNull PsiElement[] occurrences, @NotNull GrExpression expression, - @NotNull GrIntroduceVariableHandler handler) { + boolean processUsages) { myContext = context; mySettings = settings; + myProcessUsages = processUsages; myOccurrences = settings.replaceAllOccurrences() ? occurrences : new PsiElement[]{expression}; myExpression = expression; - myHandler = handler; } @NotNull @@ -75,7 +75,7 @@ public class GrIntroduceLocalVariableProcessor { preprocessOccurrences(); int expressionIndex = ArrayUtilRt.find(myOccurrences, myExpression); - final PsiElement[] replaced = processOccurrences(); + final PsiElement[] replaced = myProcessUsages ? processOccurrences() : myOccurrences; PsiElement replacedExpression = replaced[expressionIndex]; GrStatement anchor = getAnchor(replaced); @@ -84,9 +84,7 @@ public class GrIntroduceLocalVariableProcessor { return insertVariableDefinition(declaration, anchor, replacedExpression); } - private void refreshPositionMarker(PsiElement e) { - myHandler.refreshPositionMarker(myContext.getEditor().getDocument().createRangeMarker(e.getTextRange())); - } + protected abstract void refreshPositionMarker(PsiElement e); private static boolean isControlStatementBranch(GrStatement statement) { return statement.getParent() instanceof GrLoopStatement && statement == ((GrLoopStatement)statement.getParent()).getBody() || diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java index cd2d27b5bdbc..6f4c0ccca064 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java @@ -13,24 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.jetbrains.plugins.groovy.refactoring.introduce.variable; -import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; -import com.intellij.openapi.keymap.Keymap; -import com.intellij.openapi.keymap.KeymapManager; -import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.util.Pass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiModifier; -import com.intellij.psi.PsiType; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; -import com.intellij.refactoring.util.CanonicalTypes; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; @@ -46,14 +38,13 @@ import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrNewIntroduceHandlerBase; import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; -import java.util.List; - /** - * @author ilyas + * Created by Max Medvedev on 10/29/13 */ -public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase { +public class GrIntroduceVariableHandler extends GrNewIntroduceHandlerBase { public static final String DUMMY_NAME = "________________xxx_________________"; protected static final String REFACTORING_NAME = GroovyRefactoringBundle.message("introduce.variable.title"); private RangeMarker myPosition = null; @@ -130,7 +121,7 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase occurrenceMarkers, - RangeMarker varRangeMarker, RangeMarker expressionRangeMarker, - RangeMarker stringPartRangeMarker) { - context.getEditor().getCaretModel().moveToOffset(var.getTextOffset()); - GrInplaceVariableIntroducer introducer = new GrInplaceVariableIntroducer(var, context.getEditor(), context.getProject(), REFACTORING_NAME, occurrenceMarkers, var); - introducer.setAdvertisementText(getAdvertisementText(var.getDeclaredType() != null)); - - return introducer; - } - - @Nullable - private static String getAdvertisementText(final boolean hasTypeSuggestion) { - final Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); - if (hasTypeSuggestion) { - final Shortcut[] shortcuts = keymap.getShortcuts("PreviousTemplateVariable"); - if (shortcuts.length > 0) { - return "Press " + KeymapUtil.getShortcutText(shortcuts[0]) + " to change type"; + protected GrInplaceVariableIntroducer getIntroducer(@NotNull GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) { + return new GrInplaceVariableIntroducer(getRefactoringName(), choice, context) { + @Override + protected GrVariable runRefactoring(GrIntroduceContext context, GroovyIntroduceVariableSettings settings, boolean processUsages) { + final GrVariableDeclaration varDecl = generateDeclaration(context, settings); + return processExpression(context, settings, varDecl, processUsages); } - } - return null; + }; } @Override - protected GroovyIntroduceVariableSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) { - return new GroovyIntroduceVariableSettings() { - private final CanonicalTypes.Type myType; - private final String myName; - - - { - GrExpression expression = context.getExpression(); - StringPartInfo stringPart = context.getStringPart(); - GrVariable var = context.getVar(); - PsiType type = expression != null ? expression.getType() : - var != null ? var.getType() : - stringPart != null ? stringPart.getLiteral().getType() : - null; - myType = type != null ?CanonicalTypes.createTypeWrapper(type) : null; - - myName = new GrVariableNameSuggester(context, new GroovyVariableValidator(context)).suggestNames().iterator().next(); - } - - - @Override - public boolean isDeclareFinal() { - return false; - } - - @Nullable - @Override - public String getName() { - return myName; - } - - @Override - public boolean replaceAllOccurrences() { - return choice == OccurrencesChooser.ReplaceChoice.ALL; - } - - @Nullable - @Override - public PsiType getSelectedType() { - return myType != null ? myType.getType(context.getPlace(), context.getPlace().getManager()) : null; - } - }; + protected GroovyIntroduceVariableSettings getSettingsForInplace(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) { + return null; } @Override @@ -231,24 +167,29 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase Date: Thu, 31 Oct 2013 16:09:47 +0400 Subject: [PATCH 5/9] canceling introduce field --- .../GrAbstractInplaceIntroducer.java | 17 +- .../GrNewIntroduceFieldHandlerBase.java | 81 +++++++ .../introduce/GrNewIntroduceHandlerBase.java | 2 - .../field/GrInplaceFieldIntroducer.java | 220 +++++++++--------- .../field/GrIntroduceFieldHandler.java | 133 ++--------- .../field/GrIntroduceFieldProcessor.java | 25 +- .../variable/GrInplaceVariableIntroducer.java | 14 +- .../variable/GrIntroduceVariableHandler.java | 5 - 8 files changed, 247 insertions(+), 250 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceFieldHandlerBase.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java index c8c52d3f60d4..42aba9b55d30 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java @@ -21,10 +21,7 @@ import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.SmartPointerManager; -import com.intellij.psi.SmartPsiElementPointer; +import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer; @@ -53,6 +50,7 @@ import java.util.List; */ public abstract class GrAbstractInplaceIntroducer extends AbstractInplaceIntroducer { + private SmartTypePointer myTypePointer; private OccurrencesChooser.ReplaceChoice myReplaceChoice; private RangeMarker myVarMarker; @@ -243,4 +241,15 @@ public abstract class GrAbstractInplaceIntroducer extends GrNewIntroduceHandlerBase { + @NotNull + @Override + protected PsiClass[] findPossibleScopes(GrExpression expression, + GrVariable variable, + StringPartInfo partInfo, + Editor editor) { + PsiElement place = getCurrentPlace(expression, variable, partInfo); + PsiClass aClass = PsiUtil.getContextClass(place); + if (aClass instanceof GroovyScriptClass) { + return new PsiClass[]{aClass}; + } + else { + List result = ContainerUtil.newArrayList(aClass); + while (aClass != null) { + aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class); + ContainerUtil.addIfNotNull(result, aClass); + } + return result.toArray(new PsiClass[result.size()]); + } + } + + @Override + protected void showScopeChooser(PsiClass[] scopes, final Pass callback, Editor editor) { + PsiElementProcessor processor = new PsiElementProcessor() { + @Override + public boolean execute(@NotNull PsiClass element) { + callback.pass(element); + return false; + } + }; + + NavigationUtil.getPsiElementPopup(scopes, new PsiClassListCellRenderer(), "Choose class to introduce field", processor).showInBestPositionFor(editor); + } + + @NotNull + @Override + protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) { + if (scope instanceof GroovyScriptClass) { + scope = scope.getContainingFile(); + } + return super.findOccurrences(expression, scope); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java index 3be3b0ac7740..fc05ece3b41f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java @@ -145,8 +145,6 @@ public abstract class GrNewIntroduceHandlerBase getIntroducer(@NotNull GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice); - protected abstract Settings getSettingsForInplace(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice); - public static Map> fillChoice(GrIntroduceContext context) { HashMap> map = ContainerUtil.newLinkedHashMap(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java index c37d13ddd471..2f924f9e947a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java @@ -17,46 +17,36 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.field; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtilCore; import com.intellij.refactoring.introduce.inplace.KeyboardComboSwitcher; +import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; import com.intellij.refactoring.introduceField.IntroduceFieldHandler; import com.intellij.ui.NonFocusableCheckBox; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrFinalListener; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl; +import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.EnumSet; -import java.util.LinkedHashSet; -import java.util.List; /** * @author Max Medvedev */ -public class GrInplaceFieldIntroducer extends GrInplaceIntroducer { +public abstract class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroducer { private final GrInplaceIntroduceFieldPanel myPanel; - private final GrIntroduceContext myContext; - private final RangeMarker myExpressionRangeMarker; - private final RangeMarker myStringPartRangeMarker; - private final GrExpression myInitializer; private final GrFinalListener finalListener; - private final boolean myReplaceAll; + private String[] mySuggestedNames; + private boolean myIsStatic; @Nullable @Override @@ -64,93 +54,91 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer { return getVariable().getContainingFile(); } - public GrInplaceFieldIntroducer(GrVariable var, - GrIntroduceContext context, - List occurrences, - boolean replaceAll, - @Nullable RangeMarker expressionRangeMarker, - @Nullable RangeMarker stringPartRangeMarker, - GrExpression initializer) { - super(var, context.getEditor(), context.getProject(), IntroduceFieldHandler.REFACTORING_NAME, occurrences, context.getPlace()); + public GrInplaceFieldIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) { + super(IntroduceFieldHandler.REFACTORING_NAME, choice, context); - myContext = context; - myReplaceAll = replaceAll; - myExpressionRangeMarker = expressionRangeMarker; - myStringPartRangeMarker = stringPartRangeMarker; - myInitializer = initializer; - - myPanel = new GrInplaceIntroduceFieldPanel(context.getProject(), - GrIntroduceFieldHandler.getApplicableInitPlaces(context, replaceAll)); + myPanel = new GrInplaceIntroduceFieldPanel(context.getProject(), GrIntroduceFieldHandler.getApplicableInitPlaces(context, choice == OccurrencesChooser.ReplaceChoice.ALL)); finalListener = new GrFinalListener(myEditor); + + mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(getContext()), false); + } + + @Nullable + @Override + protected GrIntroduceFieldSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context, + @NotNull final OccurrencesChooser.ReplaceChoice choice, + String[] names) { + return new GrIntroduceFieldSettings() { + @Override + public boolean declareFinal() { + return false; + } + + @Override + public Init initializeIn() { + return Init.FIELD_DECLARATION; + } + + @Override + public String getVisibilityModifier() { + return PsiModifier.PRIVATE; + } + + @Override + public boolean isStatic() { + boolean hasInstanceInScope = true; + PsiClass clazz = (PsiClass)context.getScope(); + if (replaceAllOccurrences()) { + for (PsiElement occurrence : context.getOccurrences()) { + if (!PsiUtil.hasEnclosingInstanceInScope(clazz, occurrence, false)) { + hasInstanceInScope = false; + break; + } + } + } + else if (context.getExpression() != null) { + hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getExpression(), false); + } + else if (context.getStringPart() != null) { + hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getStringPart().getLiteral(), false); + } + + return !hasInstanceInScope; + } + + @Override + public boolean removeLocalVar() { + return context.getVar() != null; + } + + @Nullable + @Override + public String getName() { + return new GrFieldNameSuggester(context, new GroovyInplaceFieldValidator(context), false).suggestNames().iterator().next(); + } + + @Override + public boolean replaceAllOccurrences() { + return context.getVar() != null || choice == OccurrencesChooser.ReplaceChoice.ALL; + } + + @Nullable + @Override + public PsiType getSelectedType() { + GrExpression expression = context.getExpression(); + GrVariable var = context.getVar(); + StringPartInfo stringPart = context.getStringPart(); + return var != null ? var.getDeclaredType() : + expression != null ? expression.getType() : + stringPart != null ? stringPart.getLiteral().getType() : + null; + } + }; } @Override - protected void moveOffsetAfter(boolean success) { - if (success) { - final GrVariable field = getVariable(); - assert field != null; - GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(generateContext(), generateSettings(), false) { - @NotNull - @Override - protected GrExpression getInitializer() { - return myInitializer; - } - - @NotNull - @Override - protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass, @NotNull GrVariableDeclaration declaration) { - return (GrVariableDeclaration)field.getParent(); - } - }; - processor.run(); - } - super.moveOffsetAfter(success); - } - - private GrIntroduceContext generateContext() { - final List occurrenceMarkers = getOccurrenceMarkers(); - - List occurrences = ContainerUtil.newArrayList(); - for (RangeMarker marker : occurrenceMarkers) { - ContainerUtil.addIfNotNull(occurrences, findExpression(marker)); - } - - GrExpression expr = null; - if (myExpressionRangeMarker != null) expr = findExpression(myExpressionRangeMarker); - if (myStringPartRangeMarker != null) { - expr = findExpressionFromStringPartMarker(myStringPartRangeMarker); - occurrences.add(expr); - } - - return new GrIntroduceContextImpl(myContext.getProject(), myContext.getEditor(), expr, null, null, PsiUtilCore.toPsiElementArray( - occurrences), myContext.getScope()); - } - - @Nullable - private GrExpression findExpressionFromStringPartMarker(RangeMarker marker) { - PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument()); - if (file == null) return null; - PsiElement leaf = file.findElementAt(marker.getStartOffset()); - GrBinaryExpression binary = PsiTreeUtil.getParentOfType(leaf, GrBinaryExpression.class); - if (binary != null) { - return binary.getRightOperand(); - } - return null; - } - - @Nullable - private GrExpression findExpression(@NotNull RangeMarker marker) { - PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument()); - if (file == null) return null; - PsiElement leaf = file.findElementAt(marker.getStartOffset()); - if (leaf != null && leaf.getParent() instanceof GrReferenceExpression) { - return (GrExpression)leaf.getParent(); - } - return null; - } - - private GrIntroduceFieldSettings generateSettings() { + protected GrIntroduceFieldSettings getSettings() { return new GrIntroduceFieldSettings() { @Override public boolean declareFinal() { @@ -169,7 +157,7 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer { @Override public boolean isStatic() { - return getVariable().hasModifierProperty(PsiModifier.STATIC); + return myIsStatic; } @Override @@ -180,34 +168,50 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer { @Nullable @Override public String getName() { - return getVariable().getName(); + return getInputName(); } @Override public boolean replaceAllOccurrences() { - return myReplaceAll; + return isReplaceAllOccurrences(); } @Nullable @Override public PsiType getSelectedType() { - return getVariable().getDeclaredType(); + return GrInplaceFieldIntroducer.this.getSelectedType(); } }; } + @Override + protected String getActionName() { + return IntroduceFieldHandler.REFACTORING_NAME; + } + + @Override + protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) { + return mySuggestedNames; + } + + @Override + protected void saveSettings(@NotNull GrVariable variable) { + + } + + @Override + protected void restoreState(GrVariable psiField) { + myIsStatic = psiField.hasModifierProperty(PsiModifier.STATIC); + + super.restoreState(psiField); + } + @Nullable @Override protected JComponent getComponent() { return myPanel.getRootPane(); } - @Override - public LinkedHashSet suggestNames(GrIntroduceContext context) { - return ContainerUtil.newLinkedHashSet( - GroovyNameSuggestionUtil.suggestVariableNames(myInitializer, new GroovyInplaceFieldValidator(context), false)); - } - public class GrInplaceIntroduceFieldPanel { private final Project myProject; private JPanel myRootPane; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java index dad877d0da96..1279f74003ce 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java @@ -16,25 +16,21 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.field; import com.intellij.codeInsight.TestFrameworks; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiModifier; -import com.intellij.psi.PsiType; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; import com.intellij.refactoring.introduceField.IntroduceFieldHandler; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; @@ -47,7 +43,7 @@ import java.util.List; /** * @author Maxim.Medvedev */ -public class GrIntroduceFieldHandler extends GrIntroduceFieldHandlerBase { +public class GrIntroduceFieldHandler extends GrNewIntroduceFieldHandlerBase { @NotNull @Override @@ -100,45 +96,32 @@ public class GrIntroduceFieldHandler extends GrIntroduceFieldHandlerBase occurrenceMarkers, - @Nullable RangeMarker varRangeMarker, - @Nullable RangeMarker expressionRangeMarker, - @Nullable RangeMarker stringPartRangeMarker) { - if (varRangeMarker != null) { - context.getEditor().getCaretModel().moveToOffset(var.getNameIdentifierGroovy().getTextRange().getStartOffset()); - } - else if (expressionRangeMarker != null) { - context.getEditor().getCaretModel().moveToOffset(expressionRangeMarker.getStartOffset()); - } - else if (stringPartRangeMarker != null) { - int offset = stringPartRangeMarker.getStartOffset(); - PsiElement at = var.getContainingFile().findElementAt(offset); - GrExpression ref = PsiTreeUtil.getParentOfType(at, GrBinaryExpression.class).getRightOperand(); - context.getEditor().getCaretModel().moveToOffset(ref.getTextRange().getStartOffset()); - } - GrExpression initializer = - GroovyPsiElementFactory.getInstance(context.getProject()).createExpressionFromText(var.getInitializerGroovy().getText()); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - var.setInitializerGroovy(null); - } - }); - return new GrInplaceFieldIntroducer(var, context, occurrenceMarkers, settings.replaceAllOccurrences(), expressionRangeMarker, - stringPartRangeMarker, initializer); + @Override + protected GrAbstractInplaceIntroducer getIntroducer(@NotNull GrIntroduceContext context, + OccurrencesChooser.ReplaceChoice choice) { + return new GrInplaceFieldIntroducer(context, choice) { + @Override + protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceFieldSettings settings, boolean processUsages) { + if (processUsages) { + return GrIntroduceFieldHandler.this.runRefactoring(context, settings); + } + else { + return new GrIntroduceFieldProcessor(context, settings).insertField( (PsiClass)context.getScope()).getVariables()[0]; + } + } + }; } static EnumSet getApplicableInitPlaces(GrIntroduceContext context, boolean replaceAll) { - EnumSet result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION, - GrIntroduceFieldSettings.Init.CONSTRUCTOR); + EnumSet result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION); + + if (!(context.getScope() instanceof GroovyScriptClass || context.getScope() instanceof GroovyFileBase)) { + result.add(GrIntroduceFieldSettings.Init.CONSTRUCTOR); + } PsiElement scope = context.getScope(); @@ -156,76 +139,6 @@ public class GrIntroduceFieldHandler extends GrIntroduceFieldHandlerBase) { - org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster.shortenReference((GrQualifiedReference)replaced); + GrReferenceAdjuster.shortenReference((GrQualifiedReference)replaced); } if (isOriginal) { updateCaretPosition(replaced); @@ -326,13 +329,13 @@ public class GrIntroduceFieldProcessor { return GroovyPsiElementFactory.getInstance(place.getProject()).createReferenceExpressionFromText(refText, place); } - private GrVariableDeclaration createField() { + private GrVariableDeclaration createField(PsiClass targetClass) { final String name = settings.getName(); final PsiType type = settings.getSelectedType(); final String modifier = settings.getVisibilityModifier(); List modifiers = new ArrayList(); - if (context.getScope() instanceof GroovyScriptClass) { + if (targetClass instanceof GroovyScriptClass) { modifiers.add("@" + GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD); } if (settings.isStatic()) modifiers.add(PsiModifier.STATIC); @@ -341,7 +344,7 @@ public class GrIntroduceFieldProcessor { final String[] arr_modifiers = ArrayUtil.toStringArray(modifiers); final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.getProject()); - if (context.getScope() instanceof GroovyScriptClass) { + if (targetClass instanceof GroovyScriptClass) { return factory.createVariableDeclaration(arr_modifiers, ((GrExpression)null), type, name); } else { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java index d7d3fb7c33cc..a8732988a2c8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java @@ -22,7 +22,9 @@ import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.keymap.KeymapUtil; -import com.intellij.psi.*; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.ui.NonFocusableCheckBox; @@ -52,7 +54,6 @@ import java.awt.event.ActionListener; */ public abstract class GrInplaceVariableIntroducer extends GrAbstractInplaceIntroducer { private JCheckBox myCanBeFinalCb; - private SmartTypePointer myTypePointer; public GrInplaceVariableIntroducer(String title, OccurrencesChooser.ReplaceChoice replaceChoice, @@ -192,7 +193,7 @@ public abstract class GrInplaceVariableIntroducer extends GrAbstractInplaceIntro @Nullable @Override public PsiType getSelectedType() { - return myTypePointer != null ? myTypePointer.getType() : null; + return GrInplaceVariableIntroducer.this.getSelectedType(); } }; } @@ -206,11 +207,4 @@ public abstract class GrInplaceVariableIntroducer extends GrAbstractInplaceIntro protected int getCaretOffset() { return getVariable().getNameIdentifierGroovy().getTextRange().getEndOffset(); } - - @Override - protected void restoreState(GrVariable psiField) { - PsiType declaredType = getVariable().getDeclaredType(); - myTypePointer = declaredType != null ? SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(declaredType) : null; - super.restoreState(psiField); - } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java index 6f4c0ccca064..463db253b406 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java @@ -141,11 +141,6 @@ public class GrIntroduceVariableHandler extends GrNewIntroduceHandlerBase callback, Editor editor) { //todo do nothing right now From 0f4872fcf430ff46420487cef2cca73adc4b5cc2 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Thu, 31 Oct 2013 17:26:41 +0400 Subject: [PATCH 6/9] canceling introduce constant --- .../introduce/GrIntroduceHandlerBase.java | 89 +- .../GrNewIntroduceFieldHandlerBase.java | 81 -- .../introduce/GrNewIntroduceHandlerBase.java | 763 ------------------ .../constant/GrInplaceConstantIntroducer.java | 178 ++-- .../GrInplaceIntroduceConstantPanel.form | 2 + .../constant/GrIntroduceConstantHandler.java | 68 +- .../GrIntroduceConstantProcessor.java | 6 +- .../field/GrInplaceFieldIntroducer.java | 4 +- .../field/GrIntroduceFieldHandler.java | 2 +- .../variable/GrIntroduceVariableHandler.java | 3 +- 10 files changed, 119 insertions(+), 1077 deletions(-) delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceFieldHandlerBase.java delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java 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 ec3aefa1c717..6e147414b669 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 @@ -21,7 +21,6 @@ import com.intellij.lang.LanguageRefactoringSupport; import com.intellij.lang.refactoring.RefactoringSupportProvider; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -32,7 +31,6 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pass; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.wm.WindowManager; @@ -77,7 +75,7 @@ import java.util.*; import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipParentheses; /** - * @author Maxim.Medvedev + * Created by Max Medvedev on 10/29/13 */ public abstract class GrIntroduceHandlerBase implements RefactoringActionHandler { private static final Logger LOG = Logger.getInstance(GrIntroduceHandlerBase.class); @@ -144,15 +142,8 @@ public abstract class GrIntroduceHandlerBase occurrenceMarkers, - RangeMarker varRangeMarker, - @Nullable RangeMarker expressionRangeMarker, - @Nullable RangeMarker stringPartRangeMarker); - - protected abstract Settings getSettingsForInplace(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice); + protected abstract GrAbstractInplaceIntroducer getIntroducer(@NotNull GrIntroduceContext context, + OccurrencesChooser.ReplaceChoice choice); public static Map> fillChoice(GrIntroduceContext context) { HashMap> map = ContainerUtil.newLinkedHashMap(); @@ -296,7 +287,8 @@ public abstract class GrIntroduceHandlerBase callback, Editor editor); public GrIntroduceContext getContext(@NotNull Project project, - @NotNull Editor editor, - @Nullable GrExpression expression, - @Nullable GrVariable variable, - @Nullable StringPartInfo stringPart, - @NotNull PsiElement scope) { + @NotNull Editor editor, + @Nullable GrExpression expression, + @Nullable GrVariable variable, + @Nullable StringPartInfo stringPart, + @NotNull PsiElement scope) { if (variable != null) { final List list = Collections.synchronizedList(new ArrayList()); ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor() { @@ -348,48 +340,6 @@ public abstract class GrIntroduceHandlerBase callback = new Pass() { - @Override - public void pass(final OccurrencesChooser.ReplaceChoice choice) { - - final Settings settings = isInplace ? getSettingsForInplace(context, choice) : showDialog(context); - if (settings == null) return; - - CommandProcessor.getInstance().executeCommand(project, new Runnable() { - public void run() { - List occurrences = ContainerUtil.newArrayList(); - Document document = editor.getDocument(); - for (PsiElement element : context.getOccurrences()) { - occurrences.add(createRange(document, element)); - } - RangeMarker expressionRangeMarker = createRange(document, context.getExpression()); - RangeMarker stringPartRangeMarker = createRange(document, context.getStringPart()); - RangeMarker varRangeMarker = createRange(document, context.getVar()); - - SmartPsiElementPointer pointer = - ApplicationManager.getApplication().runWriteAction(new Computable>() { - @Override - public SmartPsiElementPointer compute() { - GrVariable var = runRefactoring(context, settings); - return var != null - ? SmartPointerManager.getInstance(context.getProject()).createSmartPsiElementPointer(var) - : null; - } - }); - GrVariable var = pointer != null ? pointer.getElement() : null; - - if (isInplace && var != null) { - GrInplaceIntroducer introducer = getIntroducer(var, context, settings, occurrences, varRangeMarker, expressionRangeMarker, stringPartRangeMarker); - LinkedHashSet suggestions = introducer.suggestNames(context); - PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); - introducer.performInplaceRefactoring(suggestions); - } - } - }, getRefactoringName(), getRefactoringName()); - } - }; - if (isInplace(context.getEditor(), context.getPlace())) { Map> occurrencesMap = fillChoice(context); new OccurrencesChooser(editor) { @@ -405,17 +355,28 @@ public abstract class GrIntroduceHandlerBase() { + @Override + public void pass(final OccurrencesChooser.ReplaceChoice choice) { + getIntroducer(context, choice).startInplaceIntroduceTemplate(); + } + }, occurrencesMap); } else { - callback.pass(null); + final Settings settings = showDialog(context); + if (settings == null) return false; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + runRefactoring(context, settings); + } + }); } return true; } catch (GrRefactoringError e) { - CommonRefactoringUtil - .showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID()); + CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID()); return false; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceFieldHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceFieldHandlerBase.java deleted file mode 100644 index 7ac5353d99f1..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceFieldHandlerBase.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.plugins.groovy.refactoring.introduce; - -import com.intellij.codeInsight.navigation.NavigationUtil; -import com.intellij.ide.util.PsiClassListCellRenderer; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.util.Pass; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.search.PsiElementProcessor; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; -import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; - -import java.util.List; - -/** - * Created by Max Medvedev on 10/31/13 - */ -public abstract class GrNewIntroduceFieldHandlerBase extends GrNewIntroduceHandlerBase { - @NotNull - @Override - protected PsiClass[] findPossibleScopes(GrExpression expression, - GrVariable variable, - StringPartInfo partInfo, - Editor editor) { - PsiElement place = getCurrentPlace(expression, variable, partInfo); - PsiClass aClass = PsiUtil.getContextClass(place); - if (aClass instanceof GroovyScriptClass) { - return new PsiClass[]{aClass}; - } - else { - List result = ContainerUtil.newArrayList(aClass); - while (aClass != null) { - aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class); - ContainerUtil.addIfNotNull(result, aClass); - } - return result.toArray(new PsiClass[result.size()]); - } - } - - @Override - protected void showScopeChooser(PsiClass[] scopes, final Pass callback, Editor editor) { - PsiElementProcessor processor = new PsiElementProcessor() { - @Override - public boolean execute(@NotNull PsiClass element) { - callback.pass(element); - return false; - } - }; - - NavigationUtil.getPsiElementPopup(scopes, new PsiClassListCellRenderer(), "Choose class to introduce field", processor).showInBestPositionFor(editor); - } - - @NotNull - @Override - protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) { - if (scope instanceof GroovyScriptClass) { - scope = scope.getContainingFile(); - } - return super.findOccurrences(expression, scope); - } -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java deleted file mode 100644 index fc05ece3b41f..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrNewIntroduceHandlerBase.java +++ /dev/null @@ -1,763 +0,0 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.plugins.groovy.refactoring.introduce; - -import com.intellij.codeInsight.highlighting.HighlightManager; -import com.intellij.diagnostic.LogMessageEx; -import com.intellij.lang.LanguageRefactoringSupport; -import com.intellij.lang.refactoring.RefactoringSupportProvider; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.RangeMarker; -import com.intellij.openapi.editor.SelectionModel; -import com.intellij.openapi.editor.colors.EditorColors; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.markup.RangeHighlighter; -import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Pass; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.wm.WindowManager; -import com.intellij.psi.*; -import com.intellij.psi.search.LocalSearchScope; -import com.intellij.psi.search.searches.ReferencesSearch; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.refactoring.IntroduceTargetChooser; -import com.intellij.refactoring.RefactoringActionHandler; -import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; -import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.intellij.util.Function; -import com.intellij.util.IncorrectOperationException; -import com.intellij.util.Processor; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; -import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseLabel; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; -import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; -import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; -import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; -import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; -import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; -import org.jetbrains.plugins.groovy.refactoring.NameValidator; - -import java.util.*; - -import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipParentheses; - -/** - * Created by Max Medvedev on 10/29/13 - */ -public abstract class GrNewIntroduceHandlerBase implements RefactoringActionHandler { - private static final Logger LOG = Logger.getInstance(GrIntroduceHandlerBase.class); - - public static final Function GR_EXPRESSION_RENDERER = new Function() { - @Override - public String fun(@NotNull GrExpression expr) { - return expr.getText(); - } - }; - - public static GrExpression insertExplicitCastIfNeeded(GrVariable variable, GrExpression initializer) { - PsiType ltype = findLValueType(initializer); - PsiType rtype = initializer.getType(); - - GrExpression rawExpr = (GrExpression)skipParentheses(initializer, false); - - if (ltype == null || TypesUtil.isAssignableWithoutConversions(ltype, rtype, initializer) || !TypesUtil.isAssignable(ltype, rtype, initializer)) { - return rawExpr; - } - else { // implicit coercion should be replaced with explicit cast - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(variable.getProject()); - GrSafeCastExpression cast = - (GrSafeCastExpression)factory.createExpressionFromText("a as B"); - cast.getOperand().replaceWithExpression(rawExpr, false); - cast.getCastTypeElement().replace(factory.createTypeElement(ltype)); - return cast; - } - } - - @Nullable - private static PsiType findLValueType(GrExpression initializer) { - if (initializer.getParent() instanceof GrAssignmentExpression && ((GrAssignmentExpression)initializer.getParent()).getRValue() == initializer) { - return ((GrAssignmentExpression)initializer.getParent()).getLValue().getNominalType(); - } - else if (initializer.getParent() instanceof GrVariable) { - return ((GrVariable)initializer.getParent()).getDeclaredType(); - } - else { - return null; - } - } - - @NotNull - protected abstract String getRefactoringName(); - - @NotNull - protected abstract String getHelpID(); - - @NotNull - protected abstract Scope[] findPossibleScopes(GrExpression expression, GrVariable variable, StringPartInfo stringPart, Editor editor); - - protected abstract void checkExpression(@NotNull GrExpression selectedExpr) throws GrRefactoringError; - - protected abstract void checkVariable(@NotNull GrVariable variable) throws GrRefactoringError; - - protected abstract void checkStringLiteral(@NotNull StringPartInfo info) throws GrRefactoringError; - - protected abstract void checkOccurrences(@NotNull PsiElement[] occurrences); - - @NotNull - protected abstract GrIntroduceDialog getDialog(@NotNull GrIntroduceContext context); - - @Nullable - public abstract GrVariable runRefactoring(@NotNull GrIntroduceContext context, @NotNull Settings settings); - - protected abstract GrAbstractInplaceIntroducer getIntroducer(@NotNull GrIntroduceContext context, - OccurrencesChooser.ReplaceChoice choice); - - public static Map> fillChoice(GrIntroduceContext context) { - HashMap> map = ContainerUtil.newLinkedHashMap(); - - if (context.getExpression() != null) { - map.put(OccurrencesChooser.ReplaceChoice.NO, Collections.singletonList(context.getExpression())); - } - else if (context.getStringPart() != null) { - map.put(OccurrencesChooser.ReplaceChoice.NO, Collections.singletonList(context.getStringPart())); - } - - PsiElement[] occurrences = context.getOccurrences(); - if (occurrences.length > 1) { - map.put(OccurrencesChooser.ReplaceChoice.ALL, Arrays.asList(occurrences)); - } - return map; - } - - @NotNull - public static List collectExpressions(final PsiFile file, final Editor editor, final int offset, boolean acceptVoidCalls) { - int correctedOffset = correctOffset(editor, offset); - final PsiElement elementAtCaret = file.findElementAt(correctedOffset); - final List expressions = new ArrayList(); - - for (GrExpression expression = PsiTreeUtil.getParentOfType(elementAtCaret, GrExpression.class); - expression != null; - expression = PsiTreeUtil.getParentOfType(expression, GrExpression.class)) { - if (expressions.contains(expression)) continue; - if (expression instanceof GrParenthesizedExpression && !expressions.contains(((GrParenthesizedExpression)expression).getOperand())) { - expressions.add(((GrParenthesizedExpression)expression).getOperand()); - } - if (expressionIsIncorrect(expression, acceptVoidCalls)) continue; - - expressions.add(expression); - } - return expressions; - } - - public static boolean expressionIsIncorrect(@Nullable GrExpression expression, boolean acceptVoidCalls) { - if (expression instanceof GrParenthesizedExpression) return true; - if (PsiUtil.isSuperReference(expression)) return true; - if (expression instanceof GrAssignmentExpression) return true; - if (expression instanceof GrReferenceExpression && expression.getParent() instanceof GrCall) { - final GroovyResolveResult resolveResult = ((GrReferenceExpression)expression).advancedResolve(); - final PsiElement resolved = resolveResult.getElement(); - return resolved instanceof PsiMethod && !resolveResult.isInvokedOnProperty() || resolved instanceof PsiClass; - } - - if (expression instanceof GrClosableBlock && expression.getParent() instanceof GrStringInjection) return true; - if (!acceptVoidCalls && expression instanceof GrMethodCall && PsiType.VOID == expression.getType()) return true; - - return false; - } - - public static int correctOffset(Editor editor, int offset) { - Document document = editor.getDocument(); - CharSequence text = document.getCharsSequence(); - int correctedOffset = offset; - int textLength = document.getTextLength(); - if (offset >= textLength) { - correctedOffset = textLength - 1; - } - else if (!Character.isJavaIdentifierPart(text.charAt(offset))) { - correctedOffset--; - } - - if (correctedOffset < 0) { - correctedOffset = offset; - } - else { - char c = text.charAt(correctedOffset); - if (c == ';' && correctedOffset != 0) {//initially caret on the end of line - correctedOffset--; - } - else if (!Character.isJavaIdentifierPart(c) && c != ')' && c != ']' && c != '}' && c != '\'' && c != '"' && c != '/') { - correctedOffset = offset; - } - } - return correctedOffset; - } - - @Nullable - public static GrVariable findVariableAtCaret(final PsiFile file, final Editor editor, final int offset) { - final int correctOffset = correctOffset(editor, offset); - final PsiElement elementAtCaret = file.findElementAt(correctOffset); - final GrVariable variable = PsiTreeUtil.getParentOfType(elementAtCaret, GrVariable.class); - if (variable != null && variable.getNameIdentifierGroovy().getTextRange().contains(correctOffset)) return variable; - return null; - } - - public void invoke(final @NotNull Project project, final Editor editor, final PsiFile file, final @Nullable DataContext dataContext) { - final SelectionModel selectionModel = editor.getSelectionModel(); - if (!selectionModel.hasSelection()) { - final int offset = editor.getCaretModel().getOffset(); - - final List expressions = collectExpressions(file, editor, offset, false); - if (expressions.isEmpty()) { - final GrVariable variable = findVariableAtCaret(file, editor, offset); - if (variable == null || variable instanceof GrField || variable instanceof GrParameter) { - selectionModel.selectLineAtCaret(); - } - else { - final TextRange textRange = variable.getTextRange(); - selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset()); - } - } - else if (expressions.size() == 1) { - final TextRange textRange = expressions.get(0).getTextRange(); - selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset()); - } - else { - IntroduceTargetChooser.showChooser(editor, expressions, new Pass() { - public void pass(final GrExpression selectedValue) { - invoke(project, editor, file, selectedValue.getTextRange().getStartOffset(), selectedValue.getTextRange().getEndOffset()); - } - }, GR_EXPRESSION_RENDERER); - return; - } - } - invoke(project, editor, file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); - } - - @Override - public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { - // Does nothing - } - - public void getContextAndInvoke(@NotNull final Project project, - @NotNull final Editor editor, - @Nullable final GrExpression expression, - @Nullable final GrVariable variable, - @Nullable final StringPartInfo stringPart) { - final Scope[] scopes = findPossibleScopes(expression, variable, stringPart, editor); - - Pass callback = new Pass() { - @Override - public void pass(Scope scope) { - GrIntroduceContext context = getContext(project, editor, expression, variable, stringPart, scope); - invokeImpl(project, context, editor); - } - }; - - if (scopes.length == 0) { - CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle - .getCannotRefactorMessage(getRefactoringName() + "is not available in current scope"), - getRefactoringName(), getHelpID()); - } - else if (scopes.length == 1) { - callback.pass(scopes[0]); - } - else { - showScopeChooser(scopes, callback, editor); - } - } - - protected abstract void showScopeChooser(Scope[] scopes, Pass callback, Editor editor); - - public GrIntroduceContext getContext(@NotNull Project project, - @NotNull Editor editor, - @Nullable GrExpression expression, - @Nullable GrVariable variable, - @Nullable StringPartInfo stringPart, - @NotNull PsiElement scope) { - if (variable != null) { - final List list = Collections.synchronizedList(new ArrayList()); - ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor() { - @Override - public boolean process(PsiReference psiReference) { - final PsiElement element = psiReference.getElement(); - if (element != null) { - list.add(element); - } - return true; - } - }); - final PsiElement[] occurrences = list.toArray(new PsiElement[list.size()]); - return new GrIntroduceContextImpl(project, editor, variable.getInitializerGroovy(), variable, stringPart, occurrences, scope); - } - else if (expression != null ) { - final PsiElement[] occurrences = findOccurrences(expression, scope); - return new GrIntroduceContextImpl(project, editor, expression, variable, stringPart, occurrences, scope); - } - else { - assert stringPart != null; - return new GrIntroduceContextImpl(project, editor, expression, variable, stringPart, new PsiElement[]{stringPart.getLiteral()}, scope); - } - } - - private boolean invokeImpl(final Project project, final GrIntroduceContext context, final Editor editor) { - try { - if (!CommonRefactoringUtil.checkReadOnlyStatus(project, context.getOccurrences())) { - return false; - } - checkOccurrences(context.getOccurrences()); - - - if (isInplace(context.getEditor(), context.getPlace())) { - Map> occurrencesMap = fillChoice(context); - new OccurrencesChooser(editor) { - @Override - protected TextRange getOccurrenceRange(Object occurrence) { - if (occurrence instanceof PsiElement) { - return ((PsiElement)occurrence).getTextRange(); - } - else if (occurrence instanceof StringPartInfo) { - return ((StringPartInfo)occurrence).getRange(); - } - else { - return null; - } - } - }.showChooser(new Pass() { - @Override - public void pass(final OccurrencesChooser.ReplaceChoice choice) { - getIntroducer(context, choice).startInplaceIntroduceTemplate(); - } - }, occurrencesMap); - } - else { - final Settings settings = showDialog(context); - if (settings == null) return false; - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - runRefactoring(context, settings); - } - }); - } - - return true; - } - catch (GrRefactoringError e) { - CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID()); - return false; - } - } - - @NotNull - protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) { - final PsiElement[] occurrences = GroovyRefactoringUtil.getExpressionOccurrences(skipParentheses(expression, false), scope); - if (occurrences == null || occurrences.length == 0) { - throw new GrRefactoringError(GroovyRefactoringBundle.message("no.occurrences.found")); - } - return occurrences; - } - - private void invoke(@NotNull final Project project, - @NotNull final Editor editor, - @NotNull PsiFile file, - int startOffset, - int endOffset) throws GrRefactoringError { - try { - PsiDocumentManager.getInstance(project).commitAllDocuments(); - if (!(file instanceof GroovyFileBase)) { - throw new GrRefactoringError(GroovyRefactoringBundle.message("only.in.groovy.files")); - } - if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) { - throw new GrRefactoringError(RefactoringBundle.message("readonly.occurences.found")); - } - - GrExpression selectedExpr = findExpression(file, startOffset, endOffset); - final GrVariable variable = findVariable(file, startOffset, endOffset); - final StringPartInfo stringPart = StringPartInfo.findStringPart(file, startOffset, endOffset); - if (variable != null) { - checkVariable(variable); - } - else if (selectedExpr != null) { - checkExpression(selectedExpr); - } - else if (stringPart != null) { - checkStringLiteral(stringPart); - } - else { - throw new GrRefactoringError(null); - } - - getContextAndInvoke(project, editor, selectedExpr, variable, stringPart); - } - catch (GrRefactoringError e) { - CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID()); - } - } - - public static RangeMarker createRange(Document document, StringPartInfo part) { - if (part == null) { - return null; - } - TextRange range = part.getRange().shiftRight(part.getLiteral().getTextRange().getStartOffset()); - return document.createRangeMarker(range.getStartOffset(), range.getEndOffset(), true); - - } - - @Nullable - public static RangeMarker createRange(@NotNull Document document, @Nullable PsiElement expression) { - if (expression == null) { - return null; - } - TextRange range = expression.getTextRange(); - return document.createRangeMarker(range.getStartOffset(), range.getEndOffset(), false); - } - - - public static boolean isInplace(@NotNull Editor editor, @NotNull PsiElement place) { - final RefactoringSupportProvider supportProvider = LanguageRefactoringSupport.INSTANCE.forLanguage(place.getLanguage()); - return supportProvider != null && - editor.getSettings().isVariableInplaceRenameEnabled() && - supportProvider.isInplaceIntroduceAvailable(place, place) && - !ApplicationManager.getApplication().isUnitTestMode(); - } - - @Nullable - public static GrVariable findVariable(@NotNull PsiFile file, int startOffset, int endOffset) { - GrVariable var = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrVariable.class); - if (var == null) { - final GrVariableDeclaration variableDeclaration = - GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrVariableDeclaration.class); - if (variableDeclaration == null) return null; - final GrVariable[] variables = variableDeclaration.getVariables(); - if (variables.length == 1) { - var = variables[0]; - } - } - if (var instanceof GrParameter || var instanceof GrField) { - return null; - } - return var; - } - - @Nullable - public static GrVariable findVariable(@NotNull GrStatement statement) { - if (!(statement instanceof GrVariableDeclaration)) return null; - final GrVariableDeclaration variableDeclaration = (GrVariableDeclaration)statement; - final GrVariable[] variables = variableDeclaration.getVariables(); - - GrVariable var = null; - if (variables.length == 1) { - var = variables[0]; - } - if (var instanceof GrParameter || var instanceof GrField) { - return null; - } - return var; - } - - - @Nullable - public static GrExpression findExpression(PsiFile file, int startOffset, int endOffset) { - GrExpression selectedExpr = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrExpression.class); - return findExpression(selectedExpr); - } - - @Nullable - public static GrExpression findExpression(GrStatement selectedExpr) { - if (!(selectedExpr instanceof GrExpression)) return null; - - GrExpression selected = (GrExpression)selectedExpr; - while (selected instanceof GrParenthesizedExpression) selected = ((GrParenthesizedExpression)selected).getOperand(); - if (selected == null) return null; - PsiType type = selected.getType(); - if (type != null) type = TypeConversionUtil.erasure(type); - - if (PsiType.VOID.equals(type)) { - return null; - } - - return selected; - } - - @Nullable - private Settings showDialog(@NotNull GrIntroduceContext context) { - - // Add occurrences highlighting - ArrayList highlighters = new ArrayList(); - HighlightManager highlightManager = null; - if (context.getEditor() != null) { - highlightManager = HighlightManager.getInstance(context.getProject()); - EditorColorsManager colorsManager = EditorColorsManager.getInstance(); - TextAttributes attributes = colorsManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES); - if (context.getOccurrences().length > 1) { - highlightManager.addOccurrenceHighlights(context.getEditor(), context.getOccurrences(), attributes, true, highlighters); - } - } - - GrIntroduceDialog dialog = getDialog(context); - - dialog.show(); - if (dialog.isOK()) { - if (context.getEditor() != null) { - for (RangeHighlighter highlighter : highlighters) { - highlightManager.removeSegmentHighlighter(context.getEditor(), highlighter); - } - } - return dialog.getSettings(); - } - else { - if (context.getOccurrences().length > 1) { - WindowManager.getInstance().getStatusBar(context.getProject()) - .setInfo(GroovyRefactoringBundle.message("press.escape.to.remove.the.highlighting")); - } - } - return null; - } - - @Nullable - public static PsiElement findAnchor(@NotNull PsiElement[] occurrences, - @NotNull PsiElement container) { - if (occurrences.length == 0) return null; - - PsiElement candidate; - if (occurrences.length == 1) { - candidate = occurrences[0]; - candidate = findContainingStatement(candidate); - } - else { - candidate = occurrences[0]; - while (candidate != null && candidate.getParent() != container) { - candidate = candidate.getParent(); - } - } - - final GrStringInjection injection = PsiTreeUtil.getParentOfType(candidate, GrStringInjection.class); - if (injection != null && !injection.getText().contains("\n")) { - candidate = findContainingStatement(injection); - } - - if (candidate == null) return null; - - if ((container instanceof GrWhileStatement) && - candidate.equals(((GrWhileStatement)container).getCondition())) { - return container; - } - if ((container instanceof GrIfStatement) && - candidate.equals(((GrIfStatement)container).getCondition())) { - return container; - } - if ((container instanceof GrForStatement) && - candidate.equals(((GrForStatement)container).getClause())) { - return container; - } - - while (candidate instanceof GrIfStatement && - candidate.getParent() instanceof GrIfStatement && - ((GrIfStatement)candidate.getParent()).getElseBranch() == candidate) { - candidate = candidate.getParent(); - } - return candidate; - } - - public static void assertStatement(PsiElement anchor, PsiElement[] occurrences, PsiElement scope) { - if (!(anchor instanceof GrStatement)) { - StringBuilder error = new StringBuilder("scope:"); - error.append(scope.getText()); - error.append("\n---------------------------------------\n\n"); - error.append("occurrences: "); - for (PsiElement occurrence : occurrences) { - error.append(occurrence.getText()); - error.append("\n------------------\n"); - } - - LogMessageEx.error(LOG, "cannot find anchor for variable", error.toString()); - } - } - - - @Nullable - private static PsiElement findContainingStatement(@Nullable PsiElement candidate) { - while (candidate != null && !PsiUtil.isExpressionStatement(candidate)) { - candidate = candidate.getParent(); - if (candidate instanceof GrCaseLabel) candidate = candidate.getParent(); - } - return candidate; - } - - public static void deleteLocalVar(@NotNull GrIntroduceContext context) { - final GrVariable resolved = resolveLocalVar(context); - - final PsiElement parent = resolved.getParent(); - if (((GrVariableDeclaration)parent).getVariables().length == 1) { - parent.delete(); - } - else { - GrExpression initializer = resolved.getInitializerGroovy(); - if (initializer != null) initializer.delete(); //don't special check for tuple, but this line is for the tuple case - resolved.delete(); - } - } - - @NotNull - public static GrVariable resolveLocalVar(@NotNull GrIntroduceContext context) { - final GrVariable var = context.getVar(); - if (var != null) { - return var; - } - - final GrReferenceExpression expression = (GrReferenceExpression)context.getExpression(); - assert expression != null; - - final PsiElement resolved = expression.resolve(); - assert resolved instanceof GrVariable; - return (GrVariable)resolved; - } - - public static boolean hasLhs(@NotNull final PsiElement[] occurrences) { - for (PsiElement element : occurrences) { - if (element instanceof GrReferenceExpression) { - if (PsiUtil.isLValue((GroovyPsiElement)element)) return true; - if (ControlFlowUtils.isIncOrDecOperand((GrReferenceExpression)element)) return true; - } - } - return false; - } - - @NotNull - public static PsiElement getCurrentPlace(@Nullable GrExpression expr, - @Nullable GrVariable var, - @Nullable StringPartInfo stringPartInfo) { - if (var != null) return var; - if (expr != null) return expr; - if (stringPartInfo != null) return stringPartInfo.getLiteral(); - - throw new IncorrectOperationException(); - } - - @NotNull - public static GrExpression generateExpressionFromStringPart(final StringPartInfo stringPart, final Project project) { - Data data = new Data(stringPart); - String startQuote = data.getStartQuote(); - TextRange range = data.getRange(); - String literalText = data.getText(); - String endQuote = data.getEndQuote(); - - final String substringLiteral = startQuote + range.substring(literalText) + endQuote; - return GroovyPsiElementFactory.getInstance(project).createExpressionFromText(substringLiteral); - } - - @NotNull - public static GrExpression processLiteral(final String varName, final StringPartInfo stringPart, final Project project) { - Data data = new Data(stringPart); - String startQuote = data.getStartQuote(); - TextRange range = data.getRange(); - String literalText = data.getText(); - String endQuote = data.getEndQuote(); - - String prefix = literalText.substring(0, range.getStartOffset()) ; - String suffix = literalText.substring(range.getEndOffset()); - - StringBuilder buffer = new StringBuilder(); - if (!prefix.equals(startQuote)) { - buffer.append(prefix).append(endQuote).append('+'); - } - buffer.append(varName); - if (!suffix.equals(endQuote)) { - buffer.append('+').append(startQuote).append(suffix); - } - - final GrExpression concatenation = GroovyPsiElementFactory.getInstance(project).createExpressionFromText(buffer); - - final GrExpression concat = stringPart.getLiteral().replaceWithExpression(concatenation, false); - if (concat instanceof GrReferenceExpression) { - return concat; - } - else { - assert concat instanceof GrBinaryExpression; - final GrExpression left = ((GrBinaryExpression)concat).getLeftOperand(); - if (left instanceof GrReferenceExpression) { - return left; - } - else { - assert left instanceof GrBinaryExpression; - final GrExpression right = ((GrBinaryExpression)left).getRightOperand(); - assert right != null; - return right; - } - } - } - - public interface Validator extends NameValidator { - boolean isOK(GrIntroduceDialog dialog); - } - - private static class Data { - private String myText; - private String myStartQuote; - private String myEndQuote; - private TextRange myRange; - - public Data(final StringPartInfo stringPartInfo) { - assert stringPartInfo != null; - - final GrLiteral literal = stringPartInfo.getLiteral(); - - myText = literal.getText(); - - myStartQuote = GrStringUtil.getStartQuote(myText); - myEndQuote = GrStringUtil.getEndQuote(myText); - final TextRange dataRange = new TextRange(myStartQuote.length(), myText.length() - myEndQuote.length()); - - myRange = stringPartInfo.getRange().intersection(dataRange); - } - - public String getText() { - return myText; - } - - public String getStartQuote() { - return myStartQuote; - } - - public String getEndQuote() { - return myEndQuote; - } - - public TextRange getRange() { - return myRange; - } - } -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java index ff5a264036fb..55d65de67fd5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java @@ -15,127 +15,120 @@ */ package org.jetbrains.plugins.groovy.refactoring.introduce.constant; -import com.intellij.openapi.editor.RangeMarker; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtilCore; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.PsiType; +import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; +import com.intellij.refactoring.introduceField.IntroduceConstantHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl; +import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; import org.jetbrains.plugins.groovy.refactoring.introduce.field.GroovyInplaceFieldValidator; import javax.swing.*; -import java.util.LinkedHashSet; -import java.util.List; /** * Created by Max Medvedev on 8/29/13 */ -public class GrInplaceConstantIntroducer extends GrInplaceIntroducer { +public class GrInplaceConstantIntroducer extends GrAbstractInplaceIntroducer { private final GrInplaceIntroduceConstantPanel myPanel; private final GrIntroduceContext myContext; - private final RangeMarker myExpressionRangeMarker; - private final RangeMarker myStringPartRangeMarker; - private final boolean myReplaceAll; + private String[] mySuggestedNames; - public GrInplaceConstantIntroducer(GrVariable var, - GrIntroduceContext context, - List occurrences, - boolean replaceAllOccurrences, - RangeMarker expressionRangeMarker, - RangeMarker stringPartRangeMarker) { - super(var, context.getEditor(), context.getProject(), GrIntroduceConstantHandler.REFACTORING_NAME, occurrences, context.getPlace()); + public GrInplaceConstantIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) { + super(IntroduceConstantHandler.REFACTORING_NAME, choice, context); myContext = context; - myReplaceAll = replaceAllOccurrences; - myExpressionRangeMarker = expressionRangeMarker; - myStringPartRangeMarker = stringPartRangeMarker; myPanel = new GrInplaceIntroduceConstantPanel(); + + mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(context), + true); } @Override - public LinkedHashSet suggestNames(GrIntroduceContext context) { - return ContainerUtil.newLinkedHashSet(GroovyNameSuggestionUtil.suggestVariableNames( - context.getExpression(), - new GroovyInplaceFieldValidator(context), - getVariable().hasModifierProperty(PsiModifier.STATIC)) - ); + protected String getActionName() { + return null; } @Override - protected void moveOffsetAfter(boolean success) { - if (success) { - final GrVariable field = getVariable(); - assert field != null; - GrIntroduceConstantProcessor processor = new GrIntroduceConstantProcessor(generateContext(), generateSettings()) { - @Override - protected GrVariableDeclaration addDeclaration(PsiClass targetClass, GrVariableDeclaration declaration) { - return (GrVariableDeclaration)field.getParent(); - } - - @Override - protected boolean checkErrors(@NotNull PsiClass targetClass) { - return false; - } - }; - processor.run(); - } - super.moveOffsetAfter(success); - } - - private GrIntroduceContext generateContext() { - final List occurrenceMarkers = getOccurrenceMarkers(); - - List occurrences = ContainerUtil.newArrayList(); - for (RangeMarker marker : occurrenceMarkers) { - ContainerUtil.addIfNotNull(occurrences, findExpression(marker)); - } - - GrExpression expr = null; - if (myExpressionRangeMarker != null) expr = findExpression(myExpressionRangeMarker); - if (myStringPartRangeMarker != null) { - expr = findExpressionFromStringPartMarker(myStringPartRangeMarker); - occurrences.add(expr); - } - - return new GrIntroduceContextImpl(myContext.getProject(), myContext.getEditor(), expr, null, null, PsiUtilCore.toPsiElementArray( - occurrences), myContext.getScope()); + protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) { + return mySuggestedNames; } @Nullable - private GrExpression findExpressionFromStringPartMarker(RangeMarker marker) { - PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument()); - if (file == null) return null; - PsiElement leaf = file.findElementAt(marker.getStartOffset()); - GrBinaryExpression binary = PsiTreeUtil.getParentOfType(leaf, GrBinaryExpression.class); - if (binary != null) { - return binary.getRightOperand(); + @Override + protected JComponent getComponent() { + return myPanel.getRootPane(); + } + + @Override + protected void saveSettings(@NotNull GrVariable variable) { + + } + + @Override + protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceConstantSettings settings, boolean processUsages) { + if (processUsages) { + return new GrIntroduceConstantProcessor(context, settings).run(); + } + else { + PsiElement scope = context.getScope(); + return new GrIntroduceConstantProcessor(context, settings).addDeclaration(scope instanceof GroovyFileBase ? ((GroovyFileBase)scope).getScriptClass() : (PsiClass)scope).getVariables()[0]; } - return null; } @Nullable - private GrExpression findExpression(@NotNull RangeMarker marker) { - PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument()); - if (file == null) return null; - PsiElement leaf = file.findElementAt(marker.getStartOffset()); - if (leaf != null && leaf.getParent() instanceof GrReferenceExpression) { - return (GrExpression)leaf.getParent(); - } - return null; + @Override + protected GrIntroduceConstantSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context, + @NotNull final OccurrencesChooser.ReplaceChoice choice, + final String[] names) { + return new GrIntroduceConstantSettings() { + @Override + public String getVisibilityModifier() { + return PsiModifier.PUBLIC; + } + + @Nullable + @Override + public PsiClass getTargetClass() { + return (PsiClass)context.getScope(); + } + + @Nullable + @Override + public String getName() { + return names[0]; + } + + @Override + public boolean replaceAllOccurrences() { + return isReplaceAllOccurrences(); + } + + @Nullable + @Override + public PsiType getSelectedType() { + GrExpression expression = context.getExpression(); + GrVariable var = context.getVar(); + StringPartInfo stringPart = context.getStringPart(); + return var != null ? var.getDeclaredType() : + expression != null ? expression.getType() : + stringPart != null ? stringPart.getLiteral().getType() : + null; + } + }; } - private GrIntroduceConstantSettings generateSettings() { + @Override + protected GrIntroduceConstantSettings getSettings() { return new GrIntroduceConstantSettings() { @Override public String getVisibilityModifier() { @@ -145,18 +138,18 @@ public class GrInplaceConstantIntroducer extends GrInplaceIntroducer { @Nullable @Override public String getName() { - return getVariable().getName(); + return getInputName(); } @Override public boolean replaceAllOccurrences() { - return myReplaceAll; + return isReplaceAllOccurrences(); } @Nullable @Override public PsiType getSelectedType() { - return getVariable().getDeclaredType(); + return GrInplaceConstantIntroducer.this.getSelectedType(); } @Nullable @@ -167,13 +160,6 @@ public class GrInplaceConstantIntroducer extends GrInplaceIntroducer { }; } - @Nullable - @Override - protected JComponent getComponent() { - //return myPanel.getRootPane(); - return null; - } - @Nullable @Override protected PsiElement checkLocalScope() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.form index da9c8bc90939..9d495a7b2e90 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.form @@ -18,6 +18,8 @@ + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java index 926c51eb5b77..9d03af8b5a78 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java @@ -15,7 +15,6 @@ */ package org.jetbrains.plugins.groovy.refactoring.introduce.constant; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; @@ -27,16 +26,11 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.introduce.*; -import org.jetbrains.plugins.groovy.refactoring.introduce.field.GrFieldNameSuggester; -import org.jetbrains.plugins.groovy.refactoring.introduce.field.GroovyInplaceFieldValidator; - -import java.util.List; /** * @author Maxim.Medvedev @@ -99,65 +93,9 @@ public class GrIntroduceConstantHandler extends GrIntroduceFieldHandlerBase occurrenceMarkers, - RangeMarker varRangeMarker, RangeMarker expressionRangeMarker, - RangeMarker stringPartRangeMarker) { - if (varRangeMarker != null) { - context.getEditor().getCaretModel().moveToOffset(var.getNameIdentifierGroovy().getTextRange().getStartOffset()); - } - else if (expressionRangeMarker != null) { - context.getEditor().getCaretModel().moveToOffset(expressionRangeMarker.getStartOffset()); - } - else if (stringPartRangeMarker != null) { - int offset = stringPartRangeMarker.getStartOffset(); - PsiElement at = var.getContainingFile().findElementAt(offset); - GrExpression ref = PsiTreeUtil.getParentOfType(at, GrBinaryExpression.class).getRightOperand(); - context.getEditor().getCaretModel().moveToOffset(ref.getTextRange().getStartOffset()); - } - - return new GrInplaceConstantIntroducer(var, context, occurrenceMarkers, settings.replaceAllOccurrences(), expressionRangeMarker, stringPartRangeMarker); - } - - @Override - protected GrIntroduceConstantSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) { - return new GrIntroduceConstantSettings() { - @Override - public String getVisibilityModifier() { - return PsiModifier.PUBLIC; - } - - @Nullable - @Override - public PsiClass getTargetClass() { - return (PsiClass)context.getScope(); - } - - @Nullable - @Override - public String getName() { - return new GrFieldNameSuggester(context, new GroovyInplaceFieldValidator(context), false).suggestNames().iterator().next(); - } - - @Override - public boolean replaceAllOccurrences() { - return choice == OccurrencesChooser.ReplaceChoice.ALL; - } - - @Nullable - @Override - public PsiType getSelectedType() { - GrExpression expression = context.getExpression(); - GrVariable var = context.getVar(); - StringPartInfo stringPart = context.getStringPart(); - return var != null ? var.getDeclaredType() : - expression != null ? expression.getType() : - stringPart != null ? stringPart.getLiteral().getType() : - null; - } - }; + protected GrAbstractInplaceIntroducer getIntroducer(@NotNull GrIntroduceContext context, + OccurrencesChooser.ReplaceChoice choice) { + return new GrInplaceConstantIntroducer(context, choice); } private static class ConstantChecker extends GroovyRecursiveElementVisitor { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java index 2e2f0007350f..bb13241a8d9e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java @@ -69,8 +69,7 @@ public class GrIntroduceConstantProcessor { return null; } - final GrVariableDeclaration rawDeclaration = createField(targetClass); - final GrVariableDeclaration declaration = addDeclaration(targetClass, rawDeclaration); + final GrVariableDeclaration declaration = addDeclaration(targetClass); final GrField field = (GrField)declaration.getVariables()[0]; if (context.getVar() != null) { @@ -102,7 +101,8 @@ public class GrIntroduceConstantProcessor { context.getEditor().getSelectionModel().removeSelection(); } - protected GrVariableDeclaration addDeclaration(PsiClass targetClass, GrVariableDeclaration declaration) { + protected GrVariableDeclaration addDeclaration(PsiClass targetClass) { + GrVariableDeclaration declaration = createField(targetClass); final GrVariableDeclaration added; if (targetClass instanceof GrEnumTypeDefinition) { final GrEnumConstantList enumConstants = ((GrEnumTypeDefinition)targetClass).getEnumConstantList(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java index 2f924f9e947a..0eb81b51075d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java @@ -68,7 +68,7 @@ public abstract class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroduc @Override protected GrIntroduceFieldSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context, @NotNull final OccurrencesChooser.ReplaceChoice choice, - String[] names) { + final String[] names) { return new GrIntroduceFieldSettings() { @Override public boolean declareFinal() { @@ -115,7 +115,7 @@ public abstract class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroduc @Nullable @Override public String getName() { - return new GrFieldNameSuggester(context, new GroovyInplaceFieldValidator(context), false).suggestNames().iterator().next(); + return names[0]; } @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java index 1279f74003ce..eea2625282f9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java @@ -43,7 +43,7 @@ import java.util.List; /** * @author Maxim.Medvedev */ -public class GrIntroduceFieldHandler extends GrNewIntroduceFieldHandlerBase { +public class GrIntroduceFieldHandler extends GrIntroduceFieldHandlerBase { @NotNull @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java index 463db253b406..ba48be41d77f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java @@ -38,13 +38,12 @@ import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrNewIntroduceHandlerBase; import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; /** * Created by Max Medvedev on 10/29/13 */ -public class GrIntroduceVariableHandler extends GrNewIntroduceHandlerBase { +public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase { public static final String DUMMY_NAME = "________________xxx_________________"; protected static final String REFACTORING_NAME = GroovyRefactoringBundle.message("introduce.variable.title"); private RangeMarker myPosition = null; From f382bd4d8a2ceac10cba77d2b3da378685275bc3 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Thu, 31 Oct 2013 17:56:48 +0400 Subject: [PATCH 7/9] simplifying --- .../introduce/field/GrInplaceFieldIntroducer.java | 9 ++++++++- .../introduce/field/GrIntroduceFieldHandler.java | 12 +----------- .../variable/GrIntroduceVariableHandler.java | 10 +++++----- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java index 0eb81b51075d..d1df3fefa1da 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java @@ -42,7 +42,7 @@ import java.util.EnumSet; /** * @author Max Medvedev */ -public abstract class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroducer { +public class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroducer { private final GrInplaceIntroduceFieldPanel myPanel; private final GrFinalListener finalListener; private String[] mySuggestedNames; @@ -64,6 +64,13 @@ public abstract class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroduc mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(getContext()), false); } + @Override + protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceFieldSettings settings, boolean processUsages) { + GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(context, settings); + return processUsages ? processor.run() + : processor.insertField((PsiClass)context.getScope()).getVariables()[0]; + } + @Nullable @Override protected GrIntroduceFieldSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context, diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java index eea2625282f9..a21dbe17f654 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java @@ -103,17 +103,7 @@ public class GrIntroduceFieldHandler extends GrIntroduceFieldHandlerBase getIntroducer(@NotNull GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) { - return new GrInplaceFieldIntroducer(context, choice) { - @Override - protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceFieldSettings settings, boolean processUsages) { - if (processUsages) { - return GrIntroduceFieldHandler.this.runRefactoring(context, settings); - } - else { - return new GrIntroduceFieldProcessor(context, settings).insertField( (PsiClass)context.getScope()).getVariables()[0]; - } - } - }; + return new GrInplaceFieldIntroducer(context, choice); } static EnumSet getApplicableInitPlaces(GrIntroduceContext context, boolean replaceAll) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java index ba48be41d77f..39fac55e7348 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java @@ -119,8 +119,7 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase Date: Thu, 31 Oct 2013 17:55:21 +0200 Subject: [PATCH 8/9] preview for introduce field --- .../GrAbstractInplaceIntroducer.java | 22 +++++++++++++++++++ .../field/GrInplaceFieldIntroducer.java | 12 ++++++---- .../field/GrInplaceIntroduceFieldPanel.form | 13 +++++++---- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java index 42aba9b55d30..32004067b0ca 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java @@ -124,6 +124,28 @@ public abstract class GrAbstractInplaceIntroducer { - private final GrInplaceIntroduceFieldPanel myPanel; + private GrInplaceIntroduceFieldPanel myPanel; private final GrFinalListener finalListener; private String[] mySuggestedNames; private boolean myIsStatic; @@ -51,14 +51,12 @@ public class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroducer initPlaces) { myProject = project; @@ -262,5 +262,9 @@ public class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroducer
- + - + @@ -11,7 +11,7 @@ - + @@ -35,13 +35,18 @@ - + + + + + + From b5a9cef9d47f36bddc8b9f3e6b21b7f69df55140 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Thu, 31 Oct 2013 17:55:40 +0200 Subject: [PATCH 9/9] preview for introduce constant --- .../constant/GrInplaceConstantIntroducer.java | 28 ++++++++++++--- .../GrInplaceIntroduceConstantPanel.form | 13 ++++--- .../GrInplaceIntroduceConstantPanel.java | 36 ------------------- 3 files changed, 32 insertions(+), 45 deletions(-) delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java index 55d65de67fd5..df6623b42a88 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java @@ -15,12 +15,10 @@ */ package org.jetbrains.plugins.groovy.refactoring.introduce.constant; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiModifier; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; import com.intellij.refactoring.introduceField.IntroduceConstantHandler; +import com.intellij.ui.components.JBCheckBox; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; @@ -163,7 +161,27 @@ public class GrInplaceConstantIntroducer extends GrAbstractInplaceIntroducer -
- + + @@ -10,12 +10,12 @@ - + - + @@ -23,6 +23,11 @@ + + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.java deleted file mode 100644 index 5bd7e5bf48df..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.plugins.groovy.refactoring.introduce.constant; - -import com.intellij.ui.components.JBCheckBox; - -import javax.swing.*; - -/** - * Created by Max Medvedev on 8/29/13 - */ -public class GrInplaceIntroduceConstantPanel { - private JBCheckBox myMoveToAnotherClassJBCheckBox; - private JPanel myRootPane; - - public boolean isMoveToAnotherClass() { - return myMoveToAnotherClassJBCheckBox.isSelected(); - } - - public JComponent getRootPane() { - return myRootPane; - } -}