| /* |
| * Copyright 2000-2014 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.field; |
| |
| import com.intellij.codeInsight.TestFrameworks; |
| import com.intellij.openapi.application.Result; |
| import com.intellij.openapi.command.WriteCommandAction; |
| import com.intellij.psi.*; |
| import com.intellij.psi.util.PsiTreeUtil; |
| 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.ArrayUtil; |
| import com.intellij.util.containers.ContainerUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; |
| 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.GrExpression; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; |
| 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.GroovyNameSuggestionUtil; |
| import org.jetbrains.plugins.groovy.refactoring.introduce.*; |
| |
| import javax.swing.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.util.ArrayList; |
| import java.util.EnumSet; |
| |
| /** |
| * @author Max Medvedev |
| */ |
| public class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroducer<GrIntroduceFieldSettings> { |
| private final EnumSet<GrIntroduceFieldSettings.Init> myApplicablePlaces; |
| private GrInplaceIntroduceFieldPanel myPanel; |
| private final GrFinalListener finalListener; |
| private final String[] mySuggestedNames; |
| private boolean myIsStatic; |
| private final GrVariable myLocalVar; |
| |
| public GrInplaceFieldIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) { |
| super(IntroduceFieldHandler.REFACTORING_NAME, choice, context); |
| |
| finalListener = new GrFinalListener(myEditor); |
| |
| myLocalVar = GrIntroduceHandlerBase.resolveLocalVar(context); |
| if (myLocalVar != null) { |
| //myLocalVariable = myLocalVar; |
| ArrayList<String> result = ContainerUtil.newArrayList(myLocalVar.getName()); |
| |
| GrExpression initializer = myLocalVar.getInitializerGroovy(); |
| if (initializer != null) { |
| ContainerUtil.addAll(result, GroovyNameSuggestionUtil.suggestVariableNames(initializer, new GroovyInplaceFieldValidator(getContext()), false)); |
| } |
| mySuggestedNames = ArrayUtil.toStringArray(result); |
| } |
| else { |
| mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(getContext()), false); |
| } |
| myApplicablePlaces = getApplicableInitPlaces(); |
| } |
| |
| @Nullable |
| @Override |
| protected PsiElement checkLocalScope() { |
| final GrVariable variable = getVariable(); |
| if (variable instanceof PsiField) { |
| return ((PsiField)getVariable()).getContainingClass(); |
| } |
| else { |
| final PsiFile file = variable.getContainingFile(); |
| if (file instanceof GroovyFile) { |
| return ((GroovyFile)file).getScriptClass(); |
| } |
| else { |
| return null; |
| } |
| } |
| } |
| |
| @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, |
| @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 myLocalVar != 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; |
| } |
| }; |
| } |
| |
| @Override |
| protected GrIntroduceFieldSettings getSettings() { |
| return new GrIntroduceFieldSettings() { |
| @Override |
| public boolean declareFinal() { |
| return myPanel.isFinal(); |
| } |
| |
| @Override |
| public Init initializeIn() { |
| return myPanel.getInitPlace(); |
| } |
| |
| @Override |
| public String getVisibilityModifier() { |
| return PsiModifier.PRIVATE; |
| } |
| |
| @Override |
| public boolean isStatic() { |
| return myIsStatic; |
| } |
| |
| @Override |
| public boolean removeLocalVar() { |
| return myLocalVar != null; |
| } |
| |
| @Nullable |
| @Override |
| public String getName() { |
| return getInputName(); |
| } |
| |
| @Override |
| public boolean replaceAllOccurrences() { |
| return isReplaceAllOccurrences(); |
| } |
| |
| @Nullable |
| @Override |
| public PsiType getSelectedType() { |
| 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(); |
| return myPanel.getRootPane(); |
| } |
| |
| private EnumSet<GrIntroduceFieldSettings.Init> getApplicableInitPlaces() { |
| GrIntroduceContext context = getContext(); |
| PsiElement[] occurrences = getOccurrences(); |
| EnumSet<GrIntroduceFieldSettings.Init> result = EnumSet.noneOf(GrIntroduceFieldSettings.Init.class); |
| |
| if (context.getExpression() != null || |
| context.getVar() != null && context.getVar().getInitializerGroovy() != null || |
| context.getStringPart() != null) { |
| result.add(GrIntroduceFieldSettings.Init.FIELD_DECLARATION); |
| } |
| |
| if (!(context.getScope() instanceof GroovyScriptClass || context.getScope() instanceof GroovyFileBase)) { |
| result.add(GrIntroduceFieldSettings.Init.CONSTRUCTOR); |
| } |
| |
| PsiElement scope = context.getScope(); |
| |
| if (isReplaceAllOccurrences()) { |
| PsiElement parent = PsiTreeUtil.findCommonParent(occurrences); |
| PsiElement container = GrIntroduceHandlerBase.getEnclosingContainer(parent); |
| if (container != null) { |
| PsiElement anchor = GrIntroduceHandlerBase.findAnchor(occurrences, container); |
| if (anchor != null) { |
| result.add(GrIntroduceFieldSettings.Init.CUR_METHOD); |
| } |
| } |
| } |
| |
| if (scope instanceof GrTypeDefinition && TestFrameworks.getInstance().isTestClass((PsiClass)scope)) { |
| result.add(GrIntroduceFieldSettings.Init.SETUP_METHOD); |
| } |
| |
| return result; |
| } |
| |
| public class GrInplaceIntroduceFieldPanel { |
| private JPanel myRootPane; |
| private JComboBox myInitCB; |
| private NonFocusableCheckBox myDeclareFinalCB; |
| private JComponent myPreview; |
| |
| public GrInplaceIntroduceFieldPanel() { |
| |
| KeyboardComboSwitcher.setupActions(myInitCB, myProject); |
| |
| for (GrIntroduceFieldSettings.Init place : myApplicablePlaces) { |
| myInitCB.addItem(place); |
| } |
| |
| myDeclareFinalCB.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| new WriteCommandAction(myProject, getCommandName(), getCommandName()) { |
| @Override |
| protected void run(Result result) throws Throwable { |
| PsiDocumentManager.getInstance(myProject).commitDocument(myEditor.getDocument()); |
| final GrVariable variable = getVariable(); |
| if (variable != null) { |
| finalListener.perform(myDeclareFinalCB.isSelected(), variable); |
| } |
| } |
| }.execute(); |
| } |
| }); |
| } |
| |
| public JPanel getRootPane() { |
| return myRootPane; |
| } |
| |
| public GrIntroduceFieldSettings.Init getInitPlace() { |
| return (GrIntroduceFieldSettings.Init)myInitCB.getSelectedItem(); |
| } |
| |
| public boolean isFinal() { |
| return myDeclareFinalCB.isSelected(); |
| } |
| |
| private void createUIComponents() { |
| myPreview = getPreviewComponent(); |
| } |
| } |
| } |