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
.util
;
18 import com
.intellij
.openapi
.diagnostic
.Logger
;
19 import com
.intellij
.psi
.*;
20 import com
.intellij
.psi
.codeStyle
.CodeStyleManager
;
21 import com
.intellij
.psi
.search
.LocalSearchScope
;
22 import com
.intellij
.psi
.search
.searches
.ReferencesSearch
;
23 import com
.intellij
.psi
.util
.InheritanceUtil
;
24 import com
.intellij
.psi
.util
.PsiTreeUtil
;
25 import com
.intellij
.util
.IncorrectOperationException
;
26 import org
.jetbrains
.annotations
.Nullable
;
28 import java
.util
.ArrayList
;
29 import java
.util
.List
;
32 * Resolves conflicts with fields in a class, when new local variable is
33 * introduced in code block
36 public class FieldConflictsResolver
{
37 private static final Logger LOG
= Logger
.getInstance("#com.intellij.refactoring.util.FieldConflictsResolver");
38 private final PsiCodeBlock myScope
;
39 private final PsiField myField
;
40 private final List
<PsiReferenceExpression
> myReferenceExpressions
;
41 private PsiClass myQualifyingClass
;
43 public FieldConflictsResolver(String name
, PsiCodeBlock scope
) {
45 if (myScope
== null) {
47 myReferenceExpressions
= null;
50 JavaPsiFacade facade
= JavaPsiFacade
.getInstance(myScope
.getProject());
51 final PsiVariable oldVariable
= facade
.getResolveHelper().resolveReferencedVariable(name
, myScope
);
52 myField
= oldVariable
instanceof PsiField ?
(PsiField
) oldVariable
: null;
53 if (!(oldVariable
instanceof PsiField
)) {
54 myReferenceExpressions
= null;
57 myReferenceExpressions
= new ArrayList
<PsiReferenceExpression
>();
58 for (PsiReference reference
: ReferencesSearch
.search(myField
, new LocalSearchScope(myScope
), false)) {
59 final PsiElement element
= reference
.getElement();
60 if (element
instanceof PsiReferenceExpression
) {
61 final PsiReferenceExpression referenceExpression
= (PsiReferenceExpression
)element
;
62 if (referenceExpression
.getQualifierExpression() == null) {
63 myReferenceExpressions
.add(referenceExpression
);
67 if (myField
.hasModifierProperty(PsiModifier
.STATIC
)) {
68 myQualifyingClass
= myField
.getContainingClass();
72 public PsiExpression
fixInitializer(PsiExpression initializer
) {
73 if (myField
== null) return initializer
;
74 final PsiReferenceExpression
[] replacedRef
= {null};
75 initializer
.accept(new JavaRecursiveElementVisitor() {
77 public void visitReferenceExpression(PsiReferenceExpression expression
) {
78 final PsiExpression qualifierExpression
= expression
.getQualifierExpression();
79 if (qualifierExpression
!= null) {
80 qualifierExpression
.accept(this);
83 final PsiElement result
= expression
.resolve();
84 if (expression
.getManager().areElementsEquivalent(result
, myField
)) {
86 replacedRef
[0] = qualifyReference(expression
, myField
, myQualifyingClass
);
88 catch (IncorrectOperationException e
) {
95 if (!initializer
.isValid()) return replacedRef
[0];
99 public void fix() throws IncorrectOperationException
{
100 if (myField
== null) return;
101 final PsiManager manager
= myScope
.getManager();
102 for (PsiReferenceExpression referenceExpression
: myReferenceExpressions
) {
103 if (!referenceExpression
.isValid()) continue;
104 final PsiElement newlyResolved
= referenceExpression
.resolve();
105 if (!manager
.areElementsEquivalent(newlyResolved
, myField
)) {
106 qualifyReference(referenceExpression
, myField
, myQualifyingClass
);
112 public static PsiReferenceExpression
qualifyReference(PsiReferenceExpression referenceExpression
,
113 final PsiMember member
,
114 @Nullable final PsiClass qualifyingClass
) throws IncorrectOperationException
{
115 PsiManager manager
= referenceExpression
.getManager();
116 PsiReferenceExpression expressionFromText
;
117 final PsiElementFactory factory
= JavaPsiFacade
.getInstance(manager
.getProject()).getElementFactory();
118 if (qualifyingClass
== null) {
119 PsiClass parentClass
= PsiTreeUtil
.getParentOfType(referenceExpression
, PsiClass
.class);
120 final PsiClass containingClass
= member
.getContainingClass();
121 if (parentClass
!= null && !InheritanceUtil
.isInheritorOrSelf(parentClass
, containingClass
, true)) {
122 while (parentClass
!= null && !InheritanceUtil
.isInheritorOrSelf(parentClass
, containingClass
, true)) {
123 parentClass
= PsiTreeUtil
.getParentOfType(parentClass
, PsiClass
.class, true);
125 LOG
.assertTrue(parentClass
!= null);
126 expressionFromText
= (PsiReferenceExpression
)factory
.createExpressionFromText("A.this." + member
.getName(), null);
127 ((PsiThisExpression
)expressionFromText
.getQualifierExpression()).getQualifier().replace(factory
.createClassReferenceElement(parentClass
));
130 expressionFromText
= (PsiReferenceExpression
)factory
.createExpressionFromText("this." + member
.getName(), null);
134 expressionFromText
= (PsiReferenceExpression
)factory
.createExpressionFromText("A." + member
.getName(), null);
135 expressionFromText
.setQualifierExpression(factory
.createReferenceExpression(qualifyingClass
));
137 CodeStyleManager codeStyleManager
= manager
.getCodeStyleManager();
138 expressionFromText
= (PsiReferenceExpression
)codeStyleManager
.reformat(expressionFromText
);
139 return (PsiReferenceExpression
)referenceExpression
.replace(expressionFromText
);