Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Kolosovsky
2013-10-31 19:59:59 +04:00
16 changed files with 725 additions and 627 deletions
@@ -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<T> {
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;
@@ -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();
@@ -0,0 +1,277 @@
/*
* 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.*;
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<Settings extends GrIntroduceSettings> extends AbstractInplaceIntroducer<GrVariable, PsiElement> {
private SmartTypePointer myTypePointer;
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;
}
@Override
protected void updateTitle(@Nullable GrVariable variable, String value) {
if (variable == null) {
super.updateTitle(variable, value);
}
else {
final String variableText = variable.getParent().getText();
final PsiElement identifier = variable.getNameIdentifierGroovy();
final int startOffsetInParent = identifier.getStartOffsetInParent() + variable.getStartOffsetInParent();
setPreviewText(
variableText.substring(0, startOffsetInParent) + value + variableText.substring(startOffsetInParent + identifier.getTextLength()));
revalidate();
}
}
@Override
protected void updateTitle(@Nullable GrVariable variable) {
if (variable == null) return;
setPreviewText(variable.getParent().getText());
revalidate();
}
@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<RangeMarker> 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<PsiElement> result = ContainerUtil.map(markers, new Function<RangeMarker, PsiElement>() {
@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<GrVariable> pointer = ApplicationManager.getApplication().runWriteAction(new Computable<SmartPsiElementPointer<GrVariable>>() {
@Override
public SmartPsiElementPointer<GrVariable> 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();
@Override
protected void restoreState(GrVariable psiField) {
PsiType declaredType = psiField.getDeclaredType();
myTypePointer = declaredType != null ? SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(declaredType) : null;
super.restoreState(psiField);
}
@Nullable
protected PsiType getSelectedType() {
return myTypePointer != null ? myTypePointer.getType() : null;
}
}
@@ -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<Settings extends GrIntroduceSettings, Scope extends PsiElement> implements RefactoringActionHandler {
private static final Logger LOG = Logger.getInstance(GrIntroduceHandlerBase.class);
@@ -144,15 +142,8 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
@Nullable
public abstract GrVariable runRefactoring(@NotNull GrIntroduceContext context, @NotNull Settings settings);
protected abstract GrInplaceIntroducer getIntroducer(@NotNull GrVariable var,
@NotNull GrIntroduceContext context,
@NotNull Settings settings,
@NotNull List<RangeMarker> occurrenceMarkers,
RangeMarker varRangeMarker,
@Nullable RangeMarker expressionRangeMarker,
@Nullable RangeMarker stringPartRangeMarker);
protected abstract Settings getSettingsForInplace(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice);
protected abstract GrAbstractInplaceIntroducer<Settings> getIntroducer(@NotNull GrIntroduceContext context,
OccurrencesChooser.ReplaceChoice choice);
public static Map<OccurrencesChooser.ReplaceChoice, List<Object>> fillChoice(GrIntroduceContext context) {
HashMap<OccurrencesChooser.ReplaceChoice, List<Object>> map = ContainerUtil.newLinkedHashMap();
@@ -296,7 +287,8 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
};
if (scopes.length == 0) {
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage( getRefactoringName() + "is not available in current scope"),
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle
.getCannotRefactorMessage(getRefactoringName() + "is not available in current scope"),
getRefactoringName(), getHelpID());
}
else if (scopes.length == 1) {
@@ -310,11 +302,11 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
protected abstract void showScopeChooser(Scope[] scopes, Pass<Scope> 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<PsiElement> list = Collections.synchronizedList(new ArrayList<PsiElement>());
ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor<PsiReference>() {
@@ -348,48 +340,6 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
checkOccurrences(context.getOccurrences());
final boolean isInplace = isInplace(context.getEditor(), context.getPlace());
Pass<OccurrencesChooser.ReplaceChoice> callback = new Pass<OccurrencesChooser.ReplaceChoice>() {
@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<RangeMarker> 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<GrVariable> pointer =
ApplicationManager.getApplication().runWriteAction(new Computable<SmartPsiElementPointer<GrVariable>>() {
@Override
public SmartPsiElementPointer<GrVariable> 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<String> suggestions = introducer.suggestNames(context);
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
introducer.performInplaceRefactoring(suggestions);
}
}
}, getRefactoringName(), getRefactoringName());
}
};
if (isInplace(context.getEditor(), context.getPlace())) {
Map<OccurrencesChooser.ReplaceChoice, List<Object>> occurrencesMap = fillChoice(context);
new OccurrencesChooser<Object>(editor) {
@@ -405,17 +355,28 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
return null;
}
}
}.showChooser(callback, occurrencesMap);
}.showChooser(new Pass<OccurrencesChooser.ReplaceChoice>() {
@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;
}
}
@@ -15,127 +15,118 @@
*/
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.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;
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<GrIntroduceConstantSettings> {
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<RangeMarker> 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<String> 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<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
List<PsiElement> 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 +136,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,17 +158,30 @@ public class GrInplaceConstantIntroducer extends GrInplaceIntroducer {
};
}
@Nullable
@Override
protected JComponent getComponent() {
//return myPanel.getRootPane();
return null;
}
@Nullable
@Override
protected PsiElement checkLocalScope() {
return getVariable().getContainingFile();
return ((PsiField)getVariable()).getContainingClass();
}
/**
* Created by Max Medvedev on 8/29/13
*/
public class GrInplaceIntroduceConstantPanel {
private JBCheckBox myMoveToAnotherClassJBCheckBox;
private JPanel myRootPane;
private JComponent myPreview;
public boolean isMoveToAnotherClass() {
return myMoveToAnotherClassJBCheckBox.isSelected();
}
public JComponent getRootPane() {
return myRootPane;
}
private void createUIComponents() {
myPreview = getPreviewComponent();
}
}
}
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrInplaceIntroduceConstantPanel">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrInplaceConstantIntroducer.GrInplaceIntroduceConstantPanel">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
@@ -10,17 +10,24 @@
<children>
<vspacer id="3c553">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="1ff44" class="com.intellij.ui.components.JBCheckBox" binding="myMoveToAnotherClassJBCheckBox" default-binding="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<focusable value="false"/>
<requestFocusEnabled value="true"/>
<text value="&amp;Move to another class"/>
</properties>
</component>
<component id="3e5fd" class="javax.swing.JComponent" binding="myPreview" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</component>
</children>
</grid>
</form>
@@ -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;
}
}
@@ -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<GrIn
}
@Override
protected GrInplaceIntroducer getIntroducer(@NotNull final GrVariable var,
@NotNull GrIntroduceContext context,
@NotNull GrIntroduceConstantSettings settings,
@NotNull List<RangeMarker> 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<GrIntroduceConstantSettings> getIntroducer(@NotNull GrIntroduceContext context,
OccurrencesChooser.ReplaceChoice choice) {
return new GrInplaceConstantIntroducer(context, choice);
}
private static class ConstantChecker extends GroovyRecursiveElementVisitor {
@@ -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();
@@ -17,140 +17,133 @@ 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 {
private final GrInplaceIntroduceFieldPanel myPanel;
private final GrIntroduceContext myContext;
private final RangeMarker myExpressionRangeMarker;
private final RangeMarker myStringPartRangeMarker;
private final GrExpression myInitializer;
public class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroducer<GrIntroduceFieldSettings> {
private GrInplaceIntroduceFieldPanel myPanel;
private final GrFinalListener finalListener;
private final boolean myReplaceAll;
private String[] mySuggestedNames;
private boolean myIsStatic;
@Nullable
@Override
protected PsiElement checkLocalScope() {
return getVariable().getContainingFile();
return ((PsiField)getVariable()).getContainingClass();
}
public GrInplaceFieldIntroducer(GrVariable var,
GrIntroduceContext context,
List<RangeMarker> occurrences,
boolean replaceAll,
@Nullable RangeMarker expressionRangeMarker,
@Nullable RangeMarker stringPartRangeMarker,
GrExpression initializer) {
super(var, context.getEditor(), context.getProject(), IntroduceFieldHandler.REFACTORING_NAME, occurrences, context.getPlace());
myContext = context;
myReplaceAll = replaceAll;
myExpressionRangeMarker = expressionRangeMarker;
myStringPartRangeMarker = stringPartRangeMarker;
myInitializer = initializer;
myPanel = new GrInplaceIntroduceFieldPanel(context.getProject(),
GrIntroduceFieldHandler.getApplicableInitPlaces(context, replaceAll));
public GrInplaceFieldIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
super(IntroduceFieldHandler.REFACTORING_NAME, choice, context);
finalListener = new GrFinalListener(myEditor);
mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(getContext()), false);
}
@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<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
List<PsiElement> 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 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
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;
@Override
protected GrIntroduceFieldSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context,
@NotNull final OccurrencesChooser.ReplaceChoice choice,
final 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 names[0];
}
@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;
}
};
}
@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() {
@Override
protected GrIntroduceFieldSettings getSettings() {
return new GrIntroduceFieldSettings() {
@Override
public boolean declareFinal() {
@@ -169,7 +162,7 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer {
@Override
public boolean isStatic() {
return getVariable().hasModifierProperty(PsiModifier.STATIC);
return myIsStatic;
}
@Override
@@ -180,39 +173,57 @@ 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() {
myPanel = new GrInplaceIntroduceFieldPanel(myProject, GrIntroduceFieldHandler.getApplicableInitPlaces(getContext(), isReplaceAllOccurrences()));
return myPanel.getRootPane();
}
@Override
public LinkedHashSet<String> suggestNames(GrIntroduceContext context) {
return ContainerUtil.newLinkedHashSet(
GroovyNameSuggestionUtil.suggestVariableNames(myInitializer, new GroovyInplaceFieldValidator(context), false));
}
public class GrInplaceIntroduceFieldPanel {
private final Project myProject;
private JPanel myRootPane;
private JComboBox myInitCB;
private NonFocusableCheckBox myDeclareFinalCB;
private JComponent myPreview;
public GrInplaceIntroduceFieldPanel(Project project, EnumSet<GrIntroduceFieldSettings.Init> initPlaces) {
myProject = project;
@@ -251,5 +262,9 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer {
public boolean isFinal() {
return myDeclareFinalCB.isSelected();
}
private void createUIComponents() {
myPreview = getPreviewComponent();
}
}
}
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.introduce.field.GrInplaceFieldIntroducer.GrInplaceIntroduceFieldPanel">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="540" height="63"/>
<xy x="20" y="20" width="540" height="88"/>
</constraints>
<properties/>
<border type="none"/>
@@ -11,7 +11,7 @@
<grid id="3dec1" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -35,13 +35,18 @@
</grid>
<component id="23db" class="com.intellij.ui.NonFocusableCheckBox" binding="myDeclareFinalCB">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<horizontalAlignment value="10"/>
<text value="Declare &amp;final"/>
</properties>
</component>
<component id="d8bd5" class="javax.swing.JComponent" binding="myPreview" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</component>
</children>
</grid>
</form>
@@ -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;
@@ -100,133 +96,39 @@ public class GrIntroduceFieldHandler extends GrIntroduceFieldHandlerBase<GrIntro
@Override
public GrVariable runRefactoring(@NotNull GrIntroduceContext context, @NotNull GrIntroduceFieldSettings settings) {
return new GrIntroduceFieldProcessor(context, settings, isInplace(context.getEditor(), context.getPlace())).run();
return new GrIntroduceFieldProcessor(context, settings).run();
}
@Override
protected GrInplaceFieldIntroducer getIntroducer(@NotNull final GrVariable var,
@NotNull GrIntroduceContext context,
@NotNull GrIntroduceFieldSettings settings,
@NotNull List<RangeMarker> 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<GrIntroduceFieldSettings> getIntroducer(@NotNull GrIntroduceContext context,
OccurrencesChooser.ReplaceChoice choice) {
return new GrInplaceFieldIntroducer(context, choice);
}
static EnumSet<GrIntroduceFieldSettings.Init> getApplicableInitPlaces(GrIntroduceContext context, boolean replaceAll) {
EnumSet<GrIntroduceFieldSettings.Init> result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION,
GrIntroduceFieldSettings.Init.CONSTRUCTOR);
EnumSet<GrIntroduceFieldSettings.Init> result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION);
if (!(context.getScope() instanceof GroovyScriptClass || context.getScope() instanceof GroovyFileBase)) {
result.add(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);
}
return result;
}
@Override
protected GrIntroduceFieldSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) {
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;
}
};
}
@NotNull
@Override
protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) {
@@ -25,8 +25,10 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster;
import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
@@ -62,19 +64,19 @@ public class GrIntroduceFieldProcessor {
private final GrIntroduceContext context;
private final GrIntroduceFieldSettings settings;
private boolean myForInplacePrepare;
public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context, @NotNull GrIntroduceFieldSettings settings, boolean forInplacePrepare) {
public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context,
@NotNull GrIntroduceFieldSettings settings) {
this.context = context;
this.settings = settings;
myForInplacePrepare = forInplacePrepare;
}
public GrVariable run() {
final PsiClass targetClass = (PsiClass)context.getScope();
PsiElement scope = context.getScope();
final PsiClass targetClass = scope instanceof GroovyFileBase ? ((GroovyFileBase)scope).getScriptClass() : (PsiClass)scope;
if (targetClass == null) return null;
final GrVariableDeclaration declaration = insertField(targetClass, createField());
final GrVariableDeclaration declaration = insertField(targetClass);
final GrVariable field = declaration.getVariables()[0];
switch (settings.initializeIn()) {
@@ -119,7 +121,7 @@ public class GrIntroduceFieldProcessor {
else {
final GrExpression expression = context.getExpression();
assert expression != null;
if (!myForInplacePrepare && PsiUtil.isExpressionStatement(expression)) {
if (PsiUtil.isExpressionStatement(expression)) {
expression.delete();
}
else {
@@ -135,7 +137,8 @@ public class GrIntroduceFieldProcessor {
}
@NotNull
protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass, @NotNull GrVariableDeclaration declaration) {
protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass) {
GrVariableDeclaration declaration = createField(targetClass);
if (targetClass instanceof GrEnumTypeDefinition) {
final GrEnumConstantList enumConstants = ((GrEnumTypeDefinition)targetClass).getEnumConstantList();
return (GrVariableDeclaration)targetClass.addAfter(declaration, enumConstants);
@@ -304,7 +307,7 @@ public class GrIntroduceFieldProcessor {
}
if (replaced instanceof GrQualifiedReference<?>) {
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<String> modifiers = new ArrayList<String>();
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 {
@@ -16,25 +16,31 @@
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.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.keymap.KeymapUtil;
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;
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 +48,40 @@ 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<GroovyIntroduceVariableSettings> {
private JCheckBox myCanBeFinalCb;
public GrInplaceVariableIntroducer(GrVariable elementToRename,
Editor editor,
Project project,
String title,
List<RangeMarker> occurrences,
@Nullable PsiElement elementToIntroduce) {
super(elementToRename, editor, project, title, occurrences, elementToIntroduce);
}
@Override
public LinkedHashSet<String> 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 +107,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 +171,40 @@ 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 GrInplaceVariableIntroducer.this.getSelectedType();
}
};
}
@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();
}
}
@@ -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() ||
@@ -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;
@@ -48,10 +40,8 @@ import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
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<GroovyIntroduceVariableSettings, GrControlFlowOwner> {
public static final String DUMMY_NAME = "________________xxx_________________";
@@ -129,8 +119,7 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
public GrVariable runRefactoring(@NotNull final GrIntroduceContext context, @NotNull final GroovyIntroduceVariableSettings settings) {
// Generating variable declaration
final GrVariableDeclaration varDecl = generateDeclaration(context, settings);
GrVariable insertedVar = processExpression(context, settings, varDecl);
GrVariable insertedVar = processExpression(context, settings, true);
if (context.getEditor() != null && getPositionMarker() != null) {
context.getEditor().getCaretModel().moveToOffset(getPositionMarker().getEndOffset());
@@ -140,72 +129,11 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
}
@Override
protected GrInplaceVariableIntroducer getIntroducer(@NotNull GrVariable var,
@NotNull GrIntroduceContext context,
@NotNull GroovyIntroduceVariableSettings settings,
@NotNull List<RangeMarker> 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";
}
}
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();
}
protected GrInplaceVariableIntroducer getIntroducer(@NotNull GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
return new GrInplaceVariableIntroducer(getRefactoringName(), choice, context) {
@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 GrVariable runRefactoring(GrIntroduceContext context, GroovyIntroduceVariableSettings settings, boolean processUsages) {
return processExpression(context, settings, processUsages);
}
};
}
@@ -231,24 +159,31 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
@NotNull
private GrVariable processExpression(@NotNull GrIntroduceContext context,
@NotNull GroovyIntroduceVariableSettings settings,
@NotNull GrVariableDeclaration varDecl) {
boolean processUsages) {
GrVariableDeclaration varDecl = generateDeclaration(context, settings);
if (context.getStringPart() != null) {
final GrExpression ref = processLiteral(DUMMY_NAME, context.getStringPart(), context.getProject());
return doProcessExpression(context, settings, varDecl, new PsiElement[]{ref}, ref);
return doProcessExpression(context, settings, varDecl, new PsiElement[]{ref}, ref, processUsages);
}
else {
final GrExpression expression = context.getExpression();
assert expression != null;
return doProcessExpression(context, settings, varDecl, context.getOccurrences(), expression);
return doProcessExpression(context, settings, varDecl, context.getOccurrences(), expression, processUsages);
}
}
private GrVariable doProcessExpression(@NotNull GrIntroduceContext context,
private GrVariable doProcessExpression(@NotNull final GrIntroduceContext context,
@NotNull GroovyIntroduceVariableSettings settings,
@NotNull GrVariableDeclaration varDecl,
@NotNull PsiElement[] elements,
@NotNull GrExpression expression) {
return new GrIntroduceLocalVariableProcessor(context, settings, elements, expression, this).processExpression(varDecl);
@NotNull GrExpression expression, boolean processUsages) {
return new GrIntroduceLocalVariableProcessor(context, settings, elements, expression, processUsages) {
@Override
protected void refreshPositionMarker(PsiElement e) {
GrIntroduceVariableHandler.this.refreshPositionMarker(context.getEditor().getDocument().createRangeMarker(e.getTextRange()));
}
}.processExpression(varDecl);
}
@NotNull