2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.refactoring
.introduceField
;
18 import com
.intellij
.codeInsight
.highlighting
.HighlightManager
;
19 import com
.intellij
.openapi
.actionSystem
.DataContext
;
20 import com
.intellij
.openapi
.editor
.Editor
;
21 import com
.intellij
.openapi
.editor
.colors
.EditorColors
;
22 import com
.intellij
.openapi
.editor
.colors
.EditorColorsManager
;
23 import com
.intellij
.openapi
.editor
.markup
.RangeHighlighter
;
24 import com
.intellij
.openapi
.editor
.markup
.TextAttributes
;
25 import com
.intellij
.openapi
.project
.Project
;
26 import com
.intellij
.openapi
.util
.TextRange
;
27 import com
.intellij
.openapi
.wm
.WindowManager
;
28 import com
.intellij
.psi
.*;
29 import com
.intellij
.psi
.util
.PsiTreeUtil
;
30 import com
.intellij
.psi
.util
.PsiUtil
;
31 import com
.intellij
.refactoring
.HelpID
;
32 import com
.intellij
.refactoring
.RefactoringBundle
;
33 import com
.intellij
.refactoring
.ui
.TypeSelectorManagerImpl
;
34 import com
.intellij
.refactoring
.util
.CommonRefactoringUtil
;
35 import com
.intellij
.refactoring
.util
.classMembers
.ClassMemberReferencesVisitor
;
36 import com
.intellij
.refactoring
.util
.occurences
.ExpressionOccurenceManager
;
37 import com
.intellij
.refactoring
.util
.occurences
.OccurenceManager
;
38 import org
.jetbrains
.annotations
.NotNull
;
39 import org
.jetbrains
.annotations
.Nullable
;
40 import java
.util
.ArrayList
;
42 public class IntroduceConstantHandler
extends BaseExpressionToFieldHandler
{
43 public static final String REFACTORING_NAME
= RefactoringBundle
.message("introduce.constant.title");
45 protected String
getHelpID() {
46 return HelpID
.INTRODUCE_CONSTANT
;
49 public void invoke(Project project
, PsiExpression
[] expressions
) {
50 for (PsiExpression expression
: expressions
) {
51 final PsiFile file
= expression
.getContainingFile();
52 if (!CommonRefactoringUtil
.checkReadOnlyStatus(project
, file
)) return;
54 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
55 super.invoke(project
, expressions
, null);
58 public void invoke(@NotNull final Project project
, final Editor editor
, PsiFile file
, DataContext dataContext
) {
59 if (!CommonRefactoringUtil
.checkReadOnlyStatus(project
, file
)) return;
61 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
62 ElementToWorkOn
.processElementToWorkOn(editor
, file
, REFACTORING_NAME
, getHelpID(), project
, getElementProcessor(project
, editor
));
65 protected boolean invokeImpl(Project project
, final PsiLocalVariable localVariable
, Editor editor
) {
66 final LocalToFieldHandler localToFieldHandler
= new LocalToFieldHandler(project
, true);
67 return localToFieldHandler
.convertLocalToField(localVariable
, editor
);
71 protected Settings
showRefactoringDialog(Project project
,
76 PsiExpression
[] occurences
,
77 PsiElement anchorElement
,
78 PsiElement anchorElementIfAll
) {
79 PsiLocalVariable localVariable
= null;
80 if (expr
instanceof PsiReferenceExpression
) {
81 PsiElement ref
= ((PsiReferenceExpression
)expr
).resolve();
82 if (ref
instanceof PsiLocalVariable
) {
83 localVariable
= (PsiLocalVariable
)ref
;
87 if (localVariable
== null) {
88 final PsiElement errorElement
= isStaticFinalInitializer(expr
);
89 if (errorElement
!= null) {
91 RefactoringBundle
.getCannotRefactorMessage(RefactoringBundle
.message("selected.expression.cannot.be.a.constant.initializer"));
92 CommonRefactoringUtil
.showErrorHint(project
, editor
, message
, REFACTORING_NAME
, getHelpID());
93 highlightError(project
, editor
, errorElement
);
98 final PsiExpression initializer
= localVariable
.getInitializer();
99 if (initializer
== null) {
100 String message
= RefactoringBundle
101 .getCannotRefactorMessage(RefactoringBundle
.message("variable.does.not.have.an.initializer", localVariable
.getName()));
102 CommonRefactoringUtil
.showErrorHint(project
, editor
, message
, REFACTORING_NAME
, getHelpID());
105 final PsiElement errorElement
= isStaticFinalInitializer(initializer
);
106 if (errorElement
!= null) {
107 String message
= RefactoringBundle
.getCannotRefactorMessage(
108 RefactoringBundle
.message("initializer.for.variable.cannot.be.a.constant.initializer", localVariable
.getName()));
109 CommonRefactoringUtil
.showErrorHint(project
, editor
, message
, REFACTORING_NAME
, getHelpID());
110 highlightError(project
, editor
, errorElement
);
115 IntroduceConstantDialog dialog
=
116 new IntroduceConstantDialog(project
, parentClass
, expr
, localVariable
, false, occurences
, getParentClass(),
117 new TypeSelectorManagerImpl(project
, type
, expr
, occurences
));
119 if (!dialog
.isOK()) {
120 if (occurences
.length
> 1) {
121 WindowManager
.getInstance().getStatusBar(project
).setInfo(RefactoringBundle
.message("press.escape.to.remove.the.highlighting"));
125 return new Settings(dialog
.getEnteredName(), dialog
.isReplaceAllOccurrences(), true, true,
126 BaseExpressionToFieldHandler
.InitializationPlace
.IN_FIELD_DECLARATION
, dialog
.getFieldVisibility(), localVariable
,
127 dialog
.getSelectedType(), dialog
.isDeleteVariable(), dialog
.getDestinationClass(), dialog
.isAnnotateAsNonNls(),
128 dialog
.introduceEnumConstant());
131 private static void highlightError(Project project
, Editor editor
, PsiElement errorElement
) {
132 if (editor
!= null) {
133 final TextAttributes attributes
= EditorColorsManager
.getInstance().getGlobalScheme().getAttributes(EditorColors
.SEARCH_RESULT_ATTRIBUTES
);
134 final TextRange textRange
= errorElement
.getTextRange();
135 HighlightManager
.getInstance(project
).addRangeHighlight(editor
, textRange
.getStartOffset(), textRange
.getEndOffset(), attributes
, true, new ArrayList
<RangeHighlighter
>());
139 protected String
getRefactoringName() {
140 return REFACTORING_NAME
;
144 private PsiElement
isStaticFinalInitializer(PsiExpression expr
) {
145 PsiClass parentClass
= getParentClass(expr
);
146 if (parentClass
== null) return null;
147 IsStaticFinalInitializerExpression visitor
= new IsStaticFinalInitializerExpression(parentClass
, expr
);
148 expr
.accept(visitor
);
149 return visitor
.getElementReference();
152 protected OccurenceManager
createOccurenceManager(final PsiExpression selectedExpr
, final PsiClass parentClass
) {
153 return new ExpressionOccurenceManager(selectedExpr
, parentClass
, null);
156 private static class IsStaticFinalInitializerExpression
extends ClassMemberReferencesVisitor
{
157 private PsiElement myElementReference
= null;
158 private final PsiExpression myInitializer
;
160 public IsStaticFinalInitializerExpression(PsiClass aClass
, PsiExpression initializer
) {
162 myInitializer
= initializer
;
166 public void visitReferenceExpression(PsiReferenceExpression expression
) {
167 final PsiElement psiElement
= expression
.resolve();
168 if ((psiElement
instanceof PsiLocalVariable
|| psiElement
instanceof PsiParameter
) &&
169 !PsiTreeUtil
.isAncestor(myInitializer
, psiElement
, false)) {
170 myElementReference
= expression
;
173 super.visitReferenceExpression(expression
);
178 protected void visitClassMemberReferenceElement(PsiMember classMember
, PsiJavaCodeReferenceElement classMemberReference
) {
179 if (!classMember
.hasModifierProperty(PsiModifier
.STATIC
)) {
180 myElementReference
= classMemberReference
;
185 public void visitElement(PsiElement element
) {
186 if (myElementReference
!= null) return;
187 super.visitElement(element
);
191 public PsiElement
getElementReference() {
192 return myElementReference
;
196 public PsiClass
getParentClass(PsiExpression initializerExpression
) {
197 final PsiType type
= initializerExpression
.getType();
199 if (type
!= null && PsiUtil
.isConstantExpression(initializerExpression
)) {
200 if (type
instanceof PsiPrimitiveType
||
201 PsiType
.getJavaLangString(initializerExpression
.getManager(), initializerExpression
.getResolveScope()).equals(type
)) {
202 return super.getParentClass(initializerExpression
);
206 PsiElement parent
= initializerExpression
.getUserData(ElementToWorkOn
.PARENT
);
207 if (parent
== null) parent
= initializerExpression
;
208 PsiClass aClass
= PsiTreeUtil
.getParentOfType(parent
, PsiClass
.class);
209 while (aClass
!= null) {
210 if (aClass
.hasModifierProperty(PsiModifier
.STATIC
)) return aClass
;
211 if (aClass
.getParent() instanceof PsiJavaFile
) return aClass
;
212 aClass
= PsiTreeUtil
.getParentOfType(aClass
, PsiClass
.class);
217 protected boolean validClass(PsiClass parentClass
, Editor editor
) {
221 protected boolean isStaticField() {