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
.move
;
18 import com
.intellij
.psi
.*;
19 import com
.intellij
.psi
.util
.PsiTreeUtil
;
20 import com
.intellij
.util
.containers
.HashSet
;
21 import com
.intellij
.openapi
.util
.Pair
;
25 import java
.util
.LinkedHashMap
;
27 import org
.jetbrains
.annotations
.Nullable
;
32 public class MoveInstanceMembersUtil
{
34 * @param member nonstatic class member to search for class references in
35 * @return Set<PsiMember> in result map may be null in case no member is needed, but class itself is.
37 public static Map
<PsiClass
, Set
<PsiMember
>> getThisClassesToMembers(final PsiMember member
) {
38 Map
<PsiClass
, Set
<PsiMember
>> map
= new LinkedHashMap
<PsiClass
, Set
<PsiMember
>>();
39 getThisClassesToMembers (member
, map
, member
);
43 private static void getThisClassesToMembers(final PsiElement scope
, final Map
<PsiClass
, Set
<PsiMember
>> map
, final PsiMember refMember
) {
44 if (scope
instanceof PsiExpression
) {
45 final PsiExpression expression
= (PsiExpression
)scope
;
46 if (!(scope
instanceof PsiReferenceExpression
) || !((PsiReferenceExpression
)scope
).isReferenceTo(refMember
)) {
47 final Pair
<PsiMember
, PsiClass
> pair
= getMemberAndClassReferencedByThis(expression
);
49 PsiClass refClass
= pair
.getSecond();
50 PsiMember member
= pair
.getFirst();
51 if (refClass
!= null && !PsiTreeUtil
.isAncestor(refMember
, member
, false)) {
52 addReferencedMember(map
, refClass
, member
);
56 if (expression
instanceof PsiThisExpression
) {
57 final PsiJavaCodeReferenceElement thisQualifier
= ((PsiThisExpression
)expression
).getQualifier();
58 PsiClass thisClass
= thisQualifier
== null ? PsiTreeUtil
.getParentOfType(expression
, PsiClass
.class, true) : ((PsiClass
)thisQualifier
.resolve());
59 if (thisClass
!= null) {
60 addReferencedMember(map
, thisClass
, null);
66 final PsiElement
[] children
= scope
.getChildren();
67 for (PsiElement child
: children
) {
68 getThisClassesToMembers(child
, map
, refMember
);
72 private static void addReferencedMember(final Map
<PsiClass
, Set
<PsiMember
>> map
, final PsiClass classReferenced
, final PsiMember member
) {
73 Set
<PsiMember
> members
= map
.get(classReferenced
);
74 if (members
== null) {
75 members
= new HashSet
<PsiMember
>();
76 map
.put(classReferenced
, members
);
82 private static Pair
<PsiMember
, PsiClass
> getMemberAndClassReferencedByThis(final PsiExpression expression
) {
83 if (expression
instanceof PsiReferenceExpression
) {
84 final PsiExpression qualifier
= ((PsiReferenceExpression
)expression
).getQualifierExpression();
85 if (qualifier
== null || qualifier
instanceof PsiThisExpression
) {
86 final PsiElement resolved
= ((PsiReferenceExpression
)expression
).resolve();
87 if (resolved
instanceof PsiMember
&& !((PsiMember
)resolved
).hasModifierProperty(PsiModifier
.STATIC
)) {
88 PsiClass referencedClass
= getReferencedClass((PsiMember
)resolved
, qualifier
, expression
);
89 return new Pair
<PsiMember
, PsiClass
>((PsiMember
)resolved
, referencedClass
);
92 } else if (expression
instanceof PsiNewExpression
) {
93 final PsiNewExpression newExpression
= (PsiNewExpression
)expression
;
94 final PsiExpression qualifier
= newExpression
.getQualifier();
95 if (qualifier
== null || qualifier
instanceof PsiThisExpression
) {
96 PsiJavaCodeReferenceElement classReference
= newExpression
.getClassOrAnonymousClassReference();
97 if (classReference
!= null) {
98 final PsiClass resolved
= (PsiClass
)classReference
.resolve();
99 if (resolved
!= null && !resolved
.hasModifierProperty(PsiModifier
.STATIC
)) {
100 PsiClass referencedClass
= getReferencedClass(resolved
, qualifier
, expression
);
101 return new Pair
<PsiMember
, PsiClass
>(resolved
, referencedClass
);
111 private static PsiClass
getReferencedClass(final PsiMember member
, final PsiExpression exprQualifier
, final PsiExpression expression
) {
112 if (exprQualifier
!= null) {
113 final PsiType type
= exprQualifier
.getType();
114 if (type
instanceof PsiClassType
) {
115 return ((PsiClassType
)type
).resolve();
119 PsiClass referencedClass
= member
.getContainingClass();
120 if (referencedClass
== null) return null;
121 final PsiClass parentClass
= PsiTreeUtil
.getParentOfType(expression
, PsiClass
.class);
122 assert parentClass
!= null;
123 if (!PsiTreeUtil
.isAncestor(referencedClass
, parentClass
, false)) {
124 referencedClass
= parentClass
;
126 return referencedClass
;
131 public static PsiClass
getClassReferencedByThis(final PsiExpression expression
) {
132 PsiClass enclosingClass
= PsiTreeUtil
.getParentOfType(expression
, PsiClass
.class);
133 if (enclosingClass
== null) return null;
134 final Pair
<PsiMember
, PsiClass
> pair
= getMemberAndClassReferencedByThis(expression
);
135 if (pair
!= null) return pair
.getSecond();
137 if (expression
instanceof PsiThisExpression
) {
138 final PsiJavaCodeReferenceElement thisQualifier
= ((PsiThisExpression
)expression
).getQualifier();
139 if (thisQualifier
== null) {
140 return enclosingClass
;
143 return (PsiClass
)thisQualifier
.resolve();