From bdb57eea2b6acc46713fd7504a61a33e80b9e15c Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 18 Mar 2011 21:22:47 +0100 Subject: [PATCH] inplace introduce constant: move it afterwards if needed --- .../InplaceIntroduceConstantPopup.java | 414 ++++++++++++++++++ .../InplaceIntroduceFieldPopup.java | 63 +-- .../IntroduceConstantDialog.java | 28 +- .../IntroduceConstantHandler.java | 12 +- .../AbstractInplaceIntroducer.java | 63 +++ .../VariableInplaceIntroducer.java | 10 +- .../AutomaticVariableRenamerFactory.java | 3 +- 7 files changed, 527 insertions(+), 66 deletions(-) create mode 100644 java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java b/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java new file mode 100644 index 000000000000..a4c4ff989210 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java @@ -0,0 +1,414 @@ +/* + * Copyright 2000-2011 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 com.intellij.refactoring.introduceField; + +import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.codeInsight.intention.impl.TypeExpression; +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.openapi.util.Computable; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.VariableKind; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.refactoring.JavaRefactoringSettings; +import com.intellij.refactoring.introduceParameter.AbstractInplaceIntroducer; +import com.intellij.refactoring.move.moveMembers.MoveMembersImpl; +import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer; +import com.intellij.refactoring.ui.JavaVisibilityPanel; +import com.intellij.refactoring.ui.TypeSelectorManagerImpl; +import com.intellij.refactoring.util.occurences.OccurenceManager; +import com.intellij.ui.StateRestoringCheckBox; +import com.intellij.ui.TitlePanel; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; + +/** + * User: anna + * Date: 3/18/11 + */ +public class InplaceIntroduceConstantPopup { + private final Project myProject; + private final PsiClass myParentClass; + private PsiExpression myExpr; + private final PsiLocalVariable myLocalVariable; + private final PsiExpression[] myOccurrences; + private final TypeSelectorManagerImpl myTypeSelectorManager; + private final PsiElement myAnchorElement; + private final PsiElement myAnchorElementIfAll; + private final OccurenceManager myOccurenceManager; + + private Editor myEditor; + private String myConstantName; + private List myOccurrenceMarkers; + private final String myExprText; + private final String myLocalName; + private RangeMarker myExprMarker; + + private boolean myInitListeners = false; + private JCheckBox myReplaceAllCb; + private JCheckBox myAnnotateNonNls; + private StateRestoringCheckBox myCbDeleteVariable; + + private JCheckBox myMoveToAnotherClassCb; + + private JavaVisibilityPanel myVisibilityPanel; + + private JPanel myWholePanel; + + public InplaceIntroduceConstantPopup(Project project, + Editor editor, + PsiClass parentClass, + PsiExpression expr, + PsiLocalVariable localVariable, + PsiExpression[] occurrences, + TypeSelectorManagerImpl typeSelectorManager, + PsiElement anchorElement, + PsiElement anchorElementIfAll, OccurenceManager occurenceManager) { + myProject = project; + myEditor = editor; + myParentClass = parentClass; + myExpr = expr; + myLocalVariable = localVariable; + myOccurrences = occurrences; + myTypeSelectorManager = typeSelectorManager; + myAnchorElement = anchorElement; + myAnchorElementIfAll = anchorElementIfAll; + myOccurenceManager = occurenceManager; + + myExprMarker = expr != null ? myEditor.getDocument().createRangeMarker(expr.getTextRange()) : null; + myExprText = expr != null ? expr.getText() : null; + myLocalName = localVariable != null ? localVariable.getName() : null; + + myWholePanel = new JPanel(new GridBagLayout()); + GridBagConstraints gc = new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0 , 0, 0), 0, 0); + + final TitlePanel titlePanel = new TitlePanel(); + titlePanel.setBorder(null); + titlePanel.setText(IntroduceConstantHandler.REFACTORING_NAME); + + myWholePanel.add(titlePanel, gc); + + gc.insets = new Insets(5, 5, 5, 5); + + myVisibilityPanel = new JavaVisibilityPanel(false, true); + myVisibilityPanel.setVisibility(JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY); + myWholePanel.add(myVisibilityPanel, gc); + + myReplaceAllCb = new JCheckBox("Replace all occurrences"); + myReplaceAllCb.setMnemonic('a'); + myReplaceAllCb.setFocusable(false); + myWholePanel.add(myReplaceAllCb, gc); + myReplaceAllCb.setVisible(myOccurrences.length > 1); + + + myCbDeleteVariable = new StateRestoringCheckBox("Delete variable declaration"); + myCbDeleteVariable.setMnemonic('d'); + myCbDeleteVariable.setFocusable(false); + myWholePanel.add(myCbDeleteVariable, gc); + if (myLocalVariable != null) { + if (myReplaceAllCb != null) { + updateCbDeleteVariable(); + myReplaceAllCb.addItemListener( + new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateCbDeleteVariable(); + } + }); + } + } else { + myCbDeleteVariable.setVisible(false); + } + + myAnnotateNonNls = new JCheckBox("Annotate field as @NonNls"); + myAnnotateNonNls.setMnemonic('f'); + myAnnotateNonNls.setFocusable(false); + myWholePanel.add(myAnnotateNonNls, gc); + final PsiManager psiManager = PsiManager.getInstance(myProject); + if ((myTypeSelectorManager.isSuggestedType("java.lang.String") || (myLocalVariable != null && AnnotationUtil.isAnnotated(myLocalVariable, AnnotationUtil.NON_NLS, false)))&& + LanguageLevelProjectExtension.getInstance(psiManager.getProject()).getLanguageLevel().hasEnumKeywordAndAutoboxing() && + JavaPsiFacade.getInstance(psiManager.getProject()).findClass(AnnotationUtil.NON_NLS, myParentClass.getResolveScope()) != null) { + final PropertiesComponent component = PropertiesComponent.getInstance(myProject); + myAnnotateNonNls.setSelected(component.isTrueValue(IntroduceConstantDialog.NONNLS_SELECTED_PROPERTY)); + myAnnotateNonNls.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + component.setValue(IntroduceConstantDialog.NONNLS_SELECTED_PROPERTY, Boolean.toString(myAnnotateNonNls.isSelected())); + } + }); + } else { + myAnnotateNonNls.setVisible(false); + } + + myMoveToAnotherClassCb = new JCheckBox("Move to another class"); + myMoveToAnotherClassCb.setMnemonic('m'); + myMoveToAnotherClassCb.setFocusable(false); + myWholePanel.add(myMoveToAnotherClassCb, gc); + + + } + + public void performInplaceIntroduce() { + startIntroduceTemplate(false); + } + + private void startIntroduceTemplate(final boolean replaceAllOccurrences) { + CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { + public void run() { + myTypeSelectorManager.setAllOccurences(replaceAllOccurrences); + final PsiType defaultType = myTypeSelectorManager.getTypeSelector().getSelectedType(); + final String propName = myLocalVariable != null ? JavaCodeStyleManager + .getInstance(myProject).variableNameToPropertyName(myLocalVariable.getName(), VariableKind.LOCAL_VARIABLE) : null; + final String[] names = IntroduceConstantDialog.createNameSuggestionGenerator(propName, myExpr, JavaCodeStyleManager.getInstance(myProject)) + .getSuggestedNameInfo(defaultType).names; + final PsiField field = createFieldToStartTemplateOn(names, defaultType); + if (field != null) { + myEditor.getCaretModel().moveToOffset(field.getTextOffset()); + final LinkedHashSet nameSuggestions = new LinkedHashSet(); + nameSuggestions.add(field.getName()); + nameSuggestions.addAll(Arrays.asList(names)); + final VariableInplaceRenamer renamer = new FieldInplaceIntroducer(field); + renamer.performInplaceRename(false, nameSuggestions); + } + } + }, IntroduceConstantHandler.REFACTORING_NAME, null); + } + + private PsiField createFieldToStartTemplateOn(final String[] names, final PsiType psiType) { + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject); + return ApplicationManager.getApplication().runWriteAction(new Computable() { + @Override + public PsiField compute() { + PsiField field = elementFactory.createField(myConstantName != null ? myConstantName : names[0], psiType); + field = (PsiField)myParentClass.add(field); + PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true); + PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true); + return field; + } + }); + } + + public List getOccurrenceMarkers() { + if (myOccurrenceMarkers == null) { + myOccurrenceMarkers = new ArrayList(); + for (PsiExpression occurrence : myOccurrences) { + myOccurrenceMarkers.add(myEditor.getDocument().createRangeMarker(occurrence.getTextRange())); + } + } + return myOccurrenceMarkers; + } + + private void updateCbDeleteVariable() { + if (!myReplaceAllCb.isSelected()) { + myCbDeleteVariable.makeUnselectable(false); + } + else { + myCbDeleteVariable.makeSelectable(); + } + } + + private class FieldInplaceIntroducer extends AbstractInplaceIntroducer { + private RangeMarker myFieldRangeStart; + + + private SmartTypePointer myDefaultParameterTypePointer; + + private SmartTypePointer myFieldTypePointer; + + public FieldInplaceIntroducer(PsiField field) { + super(myProject, new TypeExpression(myProject, myTypeSelectorManager.getTypesForAll()), + myEditor, field, false, + myTypeSelectorManager.getTypesForAll().length > 1, + myExpr != null ? myEditor.getDocument().createRangeMarker(myExpr.getTextRange()) : null, InplaceIntroduceConstantPopup.this.getOccurrenceMarkers()); + + myDefaultParameterTypePointer = + SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(myTypeSelectorManager.getDefaultType()); + myFieldRangeStart = myEditor.getDocument().createRangeMarker(field.getTextRange()); + } + + @Override + protected boolean isReplaceAllOccurrences() { + return myReplaceAllCb.isSelected(); + } + + @Override + protected PsiExpression getExpr() { + return myExpr; + } + + @Override + protected PsiExpression[] getOccurrences() { + return myOccurrences; + } + + @Override + protected List getOccurrenceMarkers() { + return InplaceIntroduceConstantPopup.this.getOccurrenceMarkers(); + } + + @Override + protected PsiElement checkLocalScope() { + return myParentClass; + } + + @Override + public RangeMarker getExprMarker() { + return myExprMarker; + } + + @Override + protected void saveSettings(PsiVariable psiVariable) { + TypeSelectorManagerImpl.typeSelected(psiVariable.getType(), myDefaultParameterTypePointer.getType()); + JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY = myVisibilityPanel.getVisibility(); + } + + @Override + protected PsiVariable getVariable() { + PsiElement element = myParentClass.getContainingFile().findElementAt(myFieldRangeStart.getStartOffset()); + if (element instanceof PsiWhiteSpace) { + element = PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace.class); + } + return PsiTreeUtil.getParentOfType(element, PsiField.class, false); + } + + @Override + protected void moveOffsetAfter(boolean success) { + if (success) { + final BaseExpressionToFieldHandler.Settings settings = + new BaseExpressionToFieldHandler.Settings(myConstantName, + isReplaceAllOccurrences(), true, + true, + BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, + myVisibilityPanel.getVisibility(), myLocalVariable, + myFieldTypePointer.getType(), + isDeleteVariable(), + myParentClass, isAnnotateNonNls(), false); + if (myLocalVariable != null) { + final LocalToFieldHandler.IntroduceFieldRunnable fieldRunnable = + new LocalToFieldHandler.IntroduceFieldRunnable(false, myLocalVariable, myParentClass, settings, true, myOccurrences); + fieldRunnable.run(); + } + else { + final BaseExpressionToFieldHandler.ConvertToFieldRunnable convertToFieldRunnable = + new BaseExpressionToFieldHandler.ConvertToFieldRunnable(myExpr, settings, settings.getForcedType(), + myOccurrences, myOccurenceManager, + myAnchorElementIfAll, myAnchorElement, myEditor, + myParentClass); + convertToFieldRunnable.run(); + } + } + super.moveOffsetAfter(success); + if (myMoveToAnotherClassCb.isSelected()) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + MoveMembersImpl.doMove(myProject, new PsiElement[]{myParentClass.findFieldByName(myConstantName, false)}, null, null); + } + }); + } + } + + @Override + protected JComponent getComponent() { + if (!myInitListeners) { + myInitListeners = true; + myVisibilityPanel.addListener(new VisibilityListener(myProject, myEditor){ + @Override + protected String getVisibility() { + return myVisibilityPanel.getVisibility(); + } + }); + myReplaceAllCb.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + final TemplateState templateState = TemplateManagerImpl.getTemplateState(myEditor); + if (templateState != null) { + templateState.gotoEnd(true); + startIntroduceTemplate(isReplaceAllOccurrences()); + } + } + }); + + myAnnotateNonNls.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + //todo it is unresolved; import here is not a good idea new FinalListener(myProject).perform(myAnnotateNonNls.isSelected(), "@NonNls"); + } + }); + } + return myWholePanel; + } + + @Override + public void finish() { + super.finish(); + final PsiField psiField = (PsiField)getVariable(); + LOG.assertTrue(psiField != null); + myFieldTypePointer = SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(psiField.getType()); + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + myConstantName = psiField.getName(); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final PsiFile containingFile = myParentClass.getContainingFile(); + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject); + myExpr = restoreExpression(containingFile, psiField, elementFactory, getExprMarker(), myExprText); + if (myExpr != null) { + myExprMarker = myEditor.getDocument().createRangeMarker(myExpr.getTextRange()); + } + final List occurrenceMarkers = getOccurrenceMarkers(); + for (int i = 0, occurrenceMarkersSize = occurrenceMarkers.size(); i < occurrenceMarkersSize; i++) { + RangeMarker marker = occurrenceMarkers.get(i); + if (getExprMarker() != null && marker.getStartOffset() == getExprMarker().getStartOffset()) { + myOccurrences[i] = myExpr; + continue; + } + final PsiExpression psiExpression = restoreExpression(containingFile, psiField, elementFactory, marker, myLocalVariable != null ? myLocalName : myExprText); + if (psiExpression != null) { + myOccurrences[i] = psiExpression; + } + } + myOccurrenceMarkers = null; + if (psiField.isValid()) { + psiField.delete(); + } + } + }); + } + } + + private boolean isAnnotateNonNls() { + return myAnnotateNonNls.isSelected(); + } + + private boolean isDeleteVariable() { + return myCbDeleteVariable.isSelected(); + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceFieldPopup.java b/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceFieldPopup.java index c45f5cdb775a..ee209603664b 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceFieldPopup.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceFieldPopup.java @@ -73,6 +73,7 @@ public class InplaceIntroduceFieldPopup { private JPanel myWholePanel; private String myExprText; + private String myLocalName; private RangeMarker myExprMarker; private String myFieldName; @@ -95,6 +96,7 @@ public class InplaceIntroduceFieldPopup { myOccurrences = occurrences; myInitializerExpression = initializerExpression; myExprText = myInitializerExpression != null ? myInitializerExpression.getText() : null; + myLocalName = localVariable != null ? localVariable.getName() : null; myExprMarker = myInitializerExpression != null ? editor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null; myTypeSelectorManager = typeSelectorManager; myAnchorElement = anchorElement; @@ -163,7 +165,7 @@ public class InplaceIntroduceFieldPopup { IntroduceFieldDialog.createGenerator(myStatic, myLocalVariable, myInitializerExpression, myLocalVariable != null) .getSuggestedNameInfo(defaultType); - final PsiField field = createFieldToStartTemplateOn(suggestedNameInfo.names, defaultType, null); + final PsiField field = createFieldToStartTemplateOn(suggestedNameInfo.names, defaultType); if (field != null) { myEditor.getCaretModel().moveToOffset(field.getTextOffset()); final LinkedHashSet nameSuggestions = new LinkedHashSet(); @@ -177,14 +179,13 @@ public class InplaceIntroduceFieldPopup { } private PsiField createFieldToStartTemplateOn(final String[] names, - final PsiType defaultType, - final PsiElement anchor) { + final PsiType defaultType) { final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject); return ApplicationManager.getApplication().runWriteAction(new Computable() { @Override public PsiField compute() { PsiField field = elementFactory.createField(myFieldName != null ? myFieldName : names[0], defaultType); - field = anchor != null ? (PsiField)myParentClass.addBefore(field, anchor) : (PsiField)myParentClass.add(field); + field = (PsiField)myParentClass.add(field); PsiUtil.setModifierProperty(field, PsiModifier.FINAL, myIntroduceFieldPanel.isDeclareFinal()); return field; } @@ -266,7 +267,12 @@ public class InplaceIntroduceFieldPopup { protected JComponent getComponent() { if (!myInitListeners) { myInitListeners = true; - myIntroduceFieldPanel.addVisibilityListener(new VisibilityListener()); + myIntroduceFieldPanel.addVisibilityListener(new VisibilityListener(myProject, myEditor){ + @Override + protected String getVisibility() { + return myIntroduceFieldPanel.getFieldVisibility(); + } + }); final FinalListener finalListener = new FinalListener(myProject); myIntroduceFieldPanel.addFinalListener(new ItemListener() { @Override @@ -340,7 +346,7 @@ public class InplaceIntroduceFieldPopup { myOccurrences[i] = myInitializerExpression; continue; } - final PsiExpression psiExpression = restoreExpression(containingFile, psiField, elementFactory, marker, myExprText); + final PsiExpression psiExpression = restoreExpression(containingFile, psiField, elementFactory, marker, myLocalVariable != null ? myLocalName : myExprText); if (psiExpression != null) { myOccurrences[i] = psiExpression; } @@ -353,51 +359,6 @@ public class InplaceIntroduceFieldPopup { }); } - private class VisibilityListener implements ChangeListener { - @Override - public void stateChanged(ChangeEvent e) { - new WriteCommandAction(myProject) { - @Override - protected void run(Result result) throws Throwable { - final Document document = myEditor.getDocument(); - PsiDocumentManager.getInstance(getProject()).commitDocument(document); - final PsiVariable variable = getVariable(); - LOG.assertTrue(variable != null); - final PsiModifierList modifierList = variable.getModifierList(); - LOG.assertTrue(modifierList != null); - int textOffset = modifierList.getTextOffset(); - String visibility = myIntroduceFieldPanel.getFieldVisibility(); - if (visibility == PsiModifier.PACKAGE_LOCAL) { - visibility = ""; - } - final String modifierListText = modifierList.getText(); - - int length = PsiModifier.PUBLIC.length(); - int idx = modifierListText.indexOf(PsiModifier.PUBLIC); - - if (idx == -1) { - idx = modifierListText.indexOf(PsiModifier.PROTECTED); - length = PsiModifier.PROTECTED.length(); - } - - if (idx == -1) { - idx = modifierListText.indexOf(PsiModifier.PRIVATE); - length = PsiModifier.PRIVATE.length(); - } - - final int startOffset = textOffset + idx; - final int endOffset; - if (idx == -1) { - endOffset = startOffset; - } else { - endOffset = textOffset + length; - } - - document.replaceString(startOffset, endOffset, visibility); - } - }.execute(); - } - } } } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java index 8fcb8390d532..85f6cc440e15 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java @@ -65,7 +65,7 @@ import java.util.Set; class IntroduceConstantDialog extends DialogWrapper { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.introduceField.IntroduceConstantDialog"); @NonNls private static final String RECENTS_KEY = "IntroduceConstantDialog.RECENTS_KEY"; - @NonNls private static final String NONNLS_SELECTED_PROPERTY = "INTRODUCE_CONSTANT_NONNLS"; + @NonNls protected static final String NONNLS_SELECTED_PROPERTY = "INTRODUCE_CONSTANT_NONNLS"; private final Project myProject; private final PsiClass myParentClass; @@ -221,15 +221,8 @@ class IntroduceConstantDialog extends DialogWrapper { propertyName = null; } final NameSuggestionsManager nameSuggestionsManager = - new NameSuggestionsManager(myTypeSelector, myNameField, new NameSuggestionsGenerator() { - public SuggestedNameInfo getSuggestedNameInfo(PsiType type) { - final SuggestedNameInfo nameInfo = - myCodeStyleManager.suggestVariableName(VariableKind.STATIC_FINAL_FIELD, propertyName, myInitializerExpression, type); - final String[] strings = JavaCompletionUtil.completeVariableNameForRefactoring(myCodeStyleManager, type, VariableKind.LOCAL_VARIABLE, nameInfo); - return new SuggestedNameInfo.Delegate(strings, nameInfo); - } - - }); + new NameSuggestionsManager(myTypeSelector, myNameField, createNameSuggestionGenerator(propertyName, myInitializerExpression, + myCodeStyleManager)); nameSuggestionsManager.setLabelsFor(myTypeLabel, myNameSuggestionLabel); ////////// @@ -287,6 +280,21 @@ class IntroduceConstantDialog extends DialogWrapper { return myPanel; } + protected static NameSuggestionsGenerator createNameSuggestionGenerator(final String propertyName, + final PsiExpression psiExpression, + final JavaCodeStyleManager codeStyleManager) { + return new NameSuggestionsGenerator() { + public SuggestedNameInfo getSuggestedNameInfo(PsiType type) { + final SuggestedNameInfo nameInfo = + codeStyleManager.suggestVariableName(VariableKind.STATIC_FINAL_FIELD, propertyName, psiExpression, type); + final String[] strings = JavaCompletionUtil + .completeVariableNameForRefactoring(codeStyleManager, type, VariableKind.LOCAL_VARIABLE, nameInfo); + return new SuggestedNameInfo.Delegate(strings, nameInfo); + } + + }; + } + private void updateButtons() { setOKActionEnabled(JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(getEnteredName())); } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java index b34ac13ee7f1..cafa4655d741 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java @@ -17,6 +17,7 @@ package com.intellij.refactoring.introduceField; import com.intellij.codeInsight.highlighting.HighlightManager; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; @@ -138,9 +139,18 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler { } } + final TypeSelectorManagerImpl typeSelectorManager = new TypeSelectorManagerImpl(project, type, containingMethod, expr, occurences); + if (editor != null && editor.getSettings().isVariableInplaceRenameEnabled() && ApplicationManagerEx.getApplicationEx().isInternal()) { + new InplaceIntroduceConstantPopup(project, editor, parentClass, expr, localVariable, occurences, typeSelectorManager, + anchorElement, anchorElementIfAll, + createOccurenceManager(expr, parentClass)).performInplaceIntroduce(); + return null; + } + + final IntroduceConstantDialog dialog = new IntroduceConstantDialog(project, parentClass, expr, localVariable, false, occurences, getParentClass(), - new TypeSelectorManagerImpl(project, type, containingMethod, expr, occurences)); + typeSelectorManager); dialog.show(); if (!dialog.isOK()) { if (occurences.length > 1) { diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/AbstractInplaceIntroducer.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/AbstractInplaceIntroducer.java index 724a1ec316fa..3290859e8c1b 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/AbstractInplaceIntroducer.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/AbstractInplaceIntroducer.java @@ -17,6 +17,9 @@ package com.intellij.refactoring.introduceParameter; import com.intellij.codeInsight.highlighting.HighlightManager; import com.intellij.codeInsight.intention.impl.TypeExpression; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.colors.EditorColors; @@ -33,6 +36,8 @@ import com.intellij.refactoring.introduceVariable.VariableInplaceIntroducer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import java.util.Collection; import java.util.List; import java.util.Map; @@ -131,4 +136,62 @@ public abstract class AbstractInplaceIntroducer extends VariableInplaceIntroduce } return null; } + + protected abstract class VisibilityListener implements ChangeListener { + private Project myProject; + private Editor myEditor; + + protected VisibilityListener(Project project, Editor editor) { + myProject = project; + myEditor = editor; + } + + @Override + public void stateChanged(ChangeEvent e) { + new WriteCommandAction(myProject) { + @Override + protected void run(Result result) throws Throwable { + final Document document = myEditor.getDocument(); + PsiDocumentManager.getInstance(getProject()).commitDocument(document); + final PsiVariable variable = getVariable(); + LOG.assertTrue(variable != null); + final PsiModifierList modifierList = variable.getModifierList(); + LOG.assertTrue(modifierList != null); + int textOffset = modifierList.getTextOffset(); + + String visibility = getVisibility(); + if (visibility == PsiModifier.PACKAGE_LOCAL) { + visibility = ""; + } + final String modifierListText = modifierList.getText(); + + int length = PsiModifier.PUBLIC.length(); + int idx = modifierListText.indexOf(PsiModifier.PUBLIC); + + if (idx == -1) { + idx = modifierListText.indexOf(PsiModifier.PROTECTED); + length = PsiModifier.PROTECTED.length(); + } + + if (idx == -1) { + idx = modifierListText.indexOf(PsiModifier.PRIVATE); + length = PsiModifier.PRIVATE.length(); + } + + final int startOffset = textOffset + idx; + final int endOffset; + if (idx == -1) { + endOffset = startOffset; + } + else { + endOffset = textOffset + length; + } + + document.replaceString(startOffset, endOffset, visibility); + } + }.execute(); + } + + protected abstract String getVisibility(); + } } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java index 25f995bfc129..786817dff467 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java @@ -378,6 +378,10 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer { } public void perform(final boolean generateFinal) { + perform(generateFinal, PsiModifier.FINAL); + } + + public void perform(final boolean generateFinal, final String modifier) { new WriteCommandAction(myProject){ @Override protected void run(com.intellij.openapi.application.Result result) throws Throwable { @@ -391,11 +395,11 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer { if (generateFinal) { final PsiTypeElement typeElement = variable.getTypeElement(); final int typeOffset = typeElement != null ? typeElement.getTextOffset() : textOffset; - document.insertString(typeOffset, PsiModifier.FINAL + " "); + document.insertString(typeOffset, modifier + " "); } else { - final int idx = modifierList.getText().indexOf(PsiModifier.FINAL); - document.deleteString(textOffset + idx, textOffset + idx + PsiModifier.FINAL.length() + 1); + final int idx = modifierList.getText().indexOf(modifier); + document.deleteString(textOffset + idx, textOffset + idx + modifier.length() + 1); } } }.execute(); diff --git a/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticVariableRenamerFactory.java b/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticVariableRenamerFactory.java index f8abcd8c89ac..445bc28b8cd9 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticVariableRenamerFactory.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticVariableRenamerFactory.java @@ -15,6 +15,7 @@ */ package com.intellij.refactoring.rename.naming; +import com.intellij.psi.PsiAnonymousClass; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.refactoring.JavaRefactoringSettings; @@ -28,7 +29,7 @@ import java.util.Collection; */ public class AutomaticVariableRenamerFactory implements AutomaticRenamerFactory { public boolean isApplicable(final PsiElement element) { - return element instanceof PsiClass; + return element instanceof PsiClass && !(element instanceof PsiAnonymousClass); } public String getOptionName() {