1 package com
.intellij
.refactoring
.inheritanceToDelegation
;
3 import com
.intellij
.codeInsight
.AnnotationUtil
;
4 import com
.intellij
.codeInsight
.generation
.GenerateMembersUtil
;
5 import com
.intellij
.find
.findUsages
.PsiElement2UsageTargetAdapter
;
6 import com
.intellij
.openapi
.diagnostic
.Logger
;
7 import com
.intellij
.openapi
.project
.Project
;
8 import com
.intellij
.openapi
.util
.Ref
;
9 import com
.intellij
.openapi
.wm
.WindowManager
;
10 import com
.intellij
.psi
.*;
11 import com
.intellij
.psi
.codeStyle
.CodeStyleManager
;
12 import com
.intellij
.psi
.codeStyle
.JavaCodeStyleManager
;
13 import com
.intellij
.psi
.codeStyle
.VariableKind
;
14 import com
.intellij
.psi
.javadoc
.PsiDocComment
;
15 import com
.intellij
.psi
.search
.searches
.ClassInheritorsSearch
;
16 import com
.intellij
.psi
.util
.*;
17 import com
.intellij
.refactoring
.BaseRefactoringProcessor
;
18 import com
.intellij
.refactoring
.RefactoringBundle
;
19 import com
.intellij
.refactoring
.inheritanceToDelegation
.usageInfo
.*;
20 import com
.intellij
.refactoring
.ui
.ConflictsDialog
;
21 import com
.intellij
.refactoring
.util
.*;
22 import com
.intellij
.refactoring
.util
.classMembers
.ClassMemberReferencesVisitor
;
23 import com
.intellij
.refactoring
.util
.classRefs
.ClassInstanceScanner
;
24 import com
.intellij
.refactoring
.util
.classRefs
.ClassReferenceScanner
;
25 import com
.intellij
.refactoring
.util
.classRefs
.ClassReferenceSearchingScanner
;
26 import com
.intellij
.usageView
.UsageInfo
;
27 import com
.intellij
.usageView
.UsageViewDescriptor
;
28 import com
.intellij
.usageView
.UsageViewUtil
;
29 import com
.intellij
.usages
.UsageInfoToUsageConverter
;
30 import com
.intellij
.usages
.UsageTarget
;
31 import com
.intellij
.usages
.UsageViewManager
;
32 import com
.intellij
.usages
.UsageViewPresentation
;
33 import com
.intellij
.util
.IncorrectOperationException
;
34 import com
.intellij
.util
.VisibilityUtil
;
35 import com
.intellij
.util
.containers
.HashMap
;
36 import org
.jetbrains
.annotations
.NonNls
;
37 import org
.jetbrains
.annotations
.NotNull
;
38 import org
.jetbrains
.annotations
.Nullable
;
45 public class InheritanceToDelegationProcessor
extends BaseRefactoringProcessor
{
46 private static final Logger LOG
= Logger
.getInstance("#com.intellij.refactoring.inheritanceToDelegation.InheritanceToDelegationProcessor");
47 private final PsiClass myClass
;
48 private final String myInnerClassName
;
49 private final boolean myIsDelegateOtherMembers
;
50 private final Set
<PsiClass
> myDelegatedInterfaces
;
51 private final Set
<PsiMethod
> myDelegatedMethods
;
52 private final HashMap
<PsiMethod
,String
> myDelegatedMethodsVisibility
;
53 private final Set
<PsiMethod
> myOverriddenMethods
;
55 private final PsiClass myBaseClass
;
56 private final Set
<PsiMember
> myBaseClassMembers
;
57 private final String myFieldName
;
58 private final String myGetterName
;
59 private final boolean myGenerateGetter
;
60 private final Set
<PsiClass
> myBaseClassBases
;
61 private Set
<PsiClass
> myClassImplementedInterfaces
;
62 private final PsiElementFactory myFactory
;
63 private final PsiClassType myBaseClassType
;
64 private final PsiManager myManager
;
65 private final boolean myIsInnerClassNeeded
;
66 private Set
<PsiClass
> myClassInheritors
;
67 private HashSet
<PsiMethod
> myAbstractDelegatedMethods
;
68 private final Map
<PsiClass
, PsiSubstitutor
> mySuperClassesToSubstitutors
= new HashMap
<PsiClass
, PsiSubstitutor
>();
71 public InheritanceToDelegationProcessor(Project project
,
73 PsiClass targetBaseClass
,
75 String innerClassName
,
76 PsiClass
[] delegatedInterfaces
,
77 PsiMethod
[] delegatedMethods
,
78 boolean delegateOtherMembers
,
79 boolean generateGetter
) {
83 myInnerClassName
= innerClassName
;
84 myIsDelegateOtherMembers
= delegateOtherMembers
;
85 myManager
= myClass
.getManager();
86 myFactory
= JavaPsiFacade
.getInstance(myManager
.getProject()).getElementFactory();
88 myBaseClass
= targetBaseClass
;
90 myBaseClass
!= null // && !myBaseClass.isInterface()
91 && (myBaseClass
.getQualifiedName() == null || !myBaseClass
.getQualifiedName().equals("java.lang.Object"))
93 myBaseClassMembers
= getAllBaseClassMembers();
94 myBaseClassBases
= getAllBases();
95 myBaseClassType
= myFactory
.createType(myBaseClass
, getSuperSubstitutor (myBaseClass
));
97 myIsInnerClassNeeded
= InheritanceToDelegationUtil
.isInnerClassNeeded(myClass
, myBaseClass
);
100 myFieldName
= fieldName
;
101 final String propertyName
= JavaCodeStyleManager
.getInstance(myProject
).variableNameToPropertyName(myFieldName
, VariableKind
.FIELD
);
102 myGetterName
= PropertyUtil
.suggestGetterName(propertyName
, myBaseClassType
);
103 myGenerateGetter
= generateGetter
;
105 myDelegatedInterfaces
= new LinkedHashSet
<PsiClass
>();
106 addAll(myDelegatedInterfaces
, delegatedInterfaces
);
107 myDelegatedMethods
= new LinkedHashSet
<PsiMethod
>();
108 addAll(myDelegatedMethods
, delegatedMethods
);
109 myDelegatedMethodsVisibility
= new HashMap
<PsiMethod
, String
>();
110 for (PsiMethod method
: myDelegatedMethods
) {
111 MethodSignature signature
= method
.getSignature(getSuperSubstitutor(method
.getContainingClass()));
112 PsiMethod overridingMethod
= MethodSignatureUtil
.findMethodBySignature(myClass
, signature
, false);
113 if (overridingMethod
!= null) {
114 myDelegatedMethodsVisibility
.put(method
,
115 VisibilityUtil
.getVisibilityModifier(overridingMethod
.getModifierList()));
119 myOverriddenMethods
= getOverriddenMethods();
122 private PsiSubstitutor
getSuperSubstitutor(final PsiClass superClass
) {
123 PsiSubstitutor result
= mySuperClassesToSubstitutors
.get(superClass
);
124 if (result
== null) {
125 result
= TypeConversionUtil
.getSuperClassSubstitutor(superClass
, myClass
, PsiSubstitutor
.EMPTY
);
126 mySuperClassesToSubstitutors
.put(superClass
, result
);
131 protected UsageViewDescriptor
createUsageViewDescriptor(UsageInfo
[] usages
) {
132 return new InheritanceToDelegationViewDescriptor(myClass
);
136 protected UsageInfo
[] findUsages() {
137 ArrayList
<UsageInfo
> usages
= new ArrayList
<UsageInfo
>();
138 final PsiClass
[] inheritors
= ClassInheritorsSearch
.search(myClass
, myClass
.getUseScope(), true).toArray(PsiClass
.EMPTY_ARRAY
);
139 myClassInheritors
= new HashSet
<PsiClass
>();
140 myClassInheritors
.add(myClass
);
141 addAll(myClassInheritors
, inheritors
);
144 ClassReferenceScanner scanner
= new ClassReferenceSearchingScanner(myClass
);
145 final MyClassInstanceReferenceVisitor instanceReferenceVisitor
= new MyClassInstanceReferenceVisitor(myClass
, usages
);
146 scanner
.processReferences(new ClassInstanceScanner(myClass
, instanceReferenceVisitor
));
148 MyClassMemberReferencesVisitor visitor
= new MyClassMemberReferencesVisitor(usages
, instanceReferenceVisitor
);
149 myClass
.accept(visitor
);
151 myClassImplementedInterfaces
= instanceReferenceVisitor
.getImplementedInterfaces();
153 for (PsiClass inheritor
: inheritors
) {
154 processClass(inheritor
, usages
);
157 return usages
.toArray(new UsageInfo
[usages
.size()]);
160 private FieldAccessibility
getFieldAccessibility(PsiElement element
) {
161 for (PsiClass aClass
: myClassInheritors
) {
162 if (PsiTreeUtil
.isAncestor(aClass
, element
, false)) {
163 return new FieldAccessibility(true, aClass
);
166 return FieldAccessibility
.INVISIBLE
;
169 protected boolean preprocessUsages(Ref
<UsageInfo
[]> refUsages
) {
170 UsageInfo
[] usagesIn
= refUsages
.get();
171 ArrayList
<UsageInfo
> oldUsages
= new ArrayList
<UsageInfo
>();
172 addAll(oldUsages
, usagesIn
);
173 final ObjectUpcastedUsageInfo
[] objectUpcastedUsageInfos
= objectUpcastedUsages(usagesIn
);
174 if (myPrepareSuccessfulSwingThreadCallback
!= null) {
175 Map
<PsiElement
, String
> conflicts
= new LinkedHashMap
<PsiElement
, String
>();
176 if (objectUpcastedUsageInfos
.length
> 0) {
177 final String message
= RefactoringBundle
.message("instances.of.0.upcasted.to.1.were.found",
178 RefactoringUIUtil
.getDescription(myClass
, true), CommonRefactoringUtil
.htmlEmphasize("java.lang.Object"));
180 conflicts
.put(myClass
, message
);
183 analyzeConflicts(usagesIn
, conflicts
);
184 if (!conflicts
.isEmpty()) {
185 ConflictsDialog conflictsDialog
=
186 new ConflictsDialog(myProject
, conflicts
);
187 conflictsDialog
.show();
188 if (!conflictsDialog
.isOK()){
189 if (conflictsDialog
.isShowConflicts()) prepareSuccessful();
194 if (objectUpcastedUsageInfos
.length
> 0) {
195 showObjectUpcastedUsageView(objectUpcastedUsageInfos
);
196 setPreviewUsages(true);
199 ArrayList
<UsageInfo
> filteredUsages
= filterUsages(oldUsages
);
200 refUsages
.set(filteredUsages
.toArray(new UsageInfo
[filteredUsages
.size()]));
205 private void analyzeConflicts(UsageInfo
[] usage
, Map
<PsiElement
, String
> conflicts
) {
206 HashMap
<PsiElement
,HashSet
<PsiElement
>> reportedNonDelegatedUsages
= new HashMap
<PsiElement
, HashSet
<PsiElement
>>();
207 HashMap
<PsiClass
,HashSet
<PsiElement
>> reportedUpcasts
= new HashMap
<PsiClass
, HashSet
<PsiElement
>>();
208 // HashSet reportedObjectUpcasts = new HashSet();
210 // final String nameJavaLangObject = ConflictsUtil.htmlEmphasize("java.lang.Object");
211 final String classDescription
= RefactoringUIUtil
.getDescription(myClass
, false);
213 for (UsageInfo aUsage
: usage
) {
214 final PsiElement element
= aUsage
.getElement();
215 if (aUsage
instanceof InheritanceToDelegationUsageInfo
) {
216 InheritanceToDelegationUsageInfo usageInfo
= (InheritanceToDelegationUsageInfo
)aUsage
;
217 /*if (usageInfo instanceof ObjectUpcastedUsageInfo) {
218 PsiElement container = ConflictsUtil.getContainer(usageInfo.element);
219 if (!reportedObjectUpcasts.contains(container)) {
220 String message = "An instance of " + classDescription + " is upcasted to "
221 + nameJavaLangObject + " in " + ConflictsUtil.getDescription(container, true) + ".";
222 conflicts.add(message);
223 reportedObjectUpcasts.add(container);
226 if (!myIsDelegateOtherMembers
&& !usageInfo
.getDelegateFieldAccessible().isAccessible()) {
227 if (usageInfo
instanceof NonDelegatedMemberUsageInfo
) {
228 final PsiElement nonDelegatedMember
= ((NonDelegatedMemberUsageInfo
)usageInfo
).nonDelegatedMember
;
229 HashSet
<PsiElement
> reportedContainers
= reportedNonDelegatedUsages
.get(nonDelegatedMember
);
230 if (reportedContainers
== null) {
231 reportedContainers
= new HashSet
<PsiElement
>();
232 reportedNonDelegatedUsages
.put(nonDelegatedMember
, reportedContainers
);
234 final PsiElement container
= ConflictsUtil
.getContainer(element
);
235 if (container
!= null && !reportedContainers
.contains(container
)) {
236 String message
= RefactoringBundle
.message("0.uses.1.of.an.instance.of.a.2", RefactoringUIUtil
.getDescription(container
, true),
237 RefactoringUIUtil
.getDescription(nonDelegatedMember
, true), classDescription
);
238 conflicts
.put(container
, CommonRefactoringUtil
.capitalize(message
));
239 reportedContainers
.add(container
);
242 else if (usageInfo
instanceof UpcastedUsageInfo
) {
243 final PsiClass upcastedTo
= ((UpcastedUsageInfo
)usageInfo
).upcastedTo
;
244 HashSet
<PsiElement
> reportedContainers
= reportedUpcasts
.get(upcastedTo
);
245 if (reportedContainers
== null) {
246 reportedContainers
= new HashSet
<PsiElement
>();
247 reportedUpcasts
.put(upcastedTo
, reportedContainers
);
249 final PsiElement container
= ConflictsUtil
.getContainer(element
);
250 if (container
!= null && !reportedContainers
.contains(container
)) {
251 String message
= RefactoringBundle
.message("0.upcasts.an.instance.of.1.to.2",
252 RefactoringUIUtil
.getDescription(container
, true), classDescription
,
253 RefactoringUIUtil
.getDescription(upcastedTo
, false));
254 conflicts
.put(container
, CommonRefactoringUtil
.capitalize(message
));
255 reportedContainers
.add(container
);
260 else if (aUsage
instanceof NoLongerOverridingSubClassMethodUsageInfo
) {
261 NoLongerOverridingSubClassMethodUsageInfo info
= (NoLongerOverridingSubClassMethodUsageInfo
)aUsage
;
262 String message
= RefactoringBundle
.message("0.will.no.longer.override.1",
263 RefactoringUIUtil
.getDescription(info
.getSubClassMethod(), true),
264 RefactoringUIUtil
.getDescription(info
.getOverridenMethod(), true));
265 conflicts
.put(info
.getSubClassMethod(), message
);
270 private static ObjectUpcastedUsageInfo
[] objectUpcastedUsages(UsageInfo
[] usages
) {
271 ArrayList
<ObjectUpcastedUsageInfo
> result
= new ArrayList
<ObjectUpcastedUsageInfo
>();
272 for (UsageInfo usage
: usages
) {
273 if (usage
instanceof ObjectUpcastedUsageInfo
) {
274 result
.add(((ObjectUpcastedUsageInfo
)usage
));
277 return result
.toArray(new ObjectUpcastedUsageInfo
[result
.size()]);
280 private ArrayList
<UsageInfo
> filterUsages(ArrayList
<UsageInfo
> usages
) {
281 ArrayList
<UsageInfo
> result
= new ArrayList
<UsageInfo
>();
283 for (UsageInfo usageInfo
: usages
) {
284 if (!(usageInfo
instanceof InheritanceToDelegationUsageInfo
)) {
287 if (usageInfo
instanceof ObjectUpcastedUsageInfo
) {
291 if (!myIsDelegateOtherMembers
) {
292 final FieldAccessibility delegateFieldAccessible
= ((InheritanceToDelegationUsageInfo
)usageInfo
).getDelegateFieldAccessible();
293 if (!delegateFieldAccessible
.isAccessible()) continue;
296 result
.add(usageInfo
);
301 private void processClass(PsiClass inheritor
, ArrayList
<UsageInfo
> usages
) {
302 ClassReferenceScanner scanner
= new ClassReferenceSearchingScanner(inheritor
);
303 final MyClassInstanceReferenceVisitor instanceVisitor
= new MyClassInstanceReferenceVisitor(inheritor
, usages
);
304 scanner
.processReferences(
305 new ClassInstanceScanner(inheritor
,
308 MyClassInheritorMemberReferencesVisitor classMemberVisitor
= new MyClassInheritorMemberReferencesVisitor(inheritor
, usages
, instanceVisitor
);
309 inheritor
.accept(classMemberVisitor
);
310 PsiSubstitutor inheritorSubstitutor
= TypeConversionUtil
.getSuperClassSubstitutor(myClass
, inheritor
, PsiSubstitutor
.EMPTY
);
312 PsiMethod
[] methods
= inheritor
.getMethods();
313 for (PsiMethod method
: methods
) {
314 final PsiMethod baseMethod
= findSuperMethodInBaseClass(method
);
316 if (baseMethod
!= null) {
317 if (!baseMethod
.hasModifierProperty(PsiModifier
.ABSTRACT
)) {
318 usages
.add(new NoLongerOverridingSubClassMethodUsageInfo(method
, baseMethod
));
321 final PsiMethod
[] methodsByName
= myClass
.findMethodsByName(method
.getName(), false);
322 for (final PsiMethod classMethod
: methodsByName
) {
323 final MethodSignature signature
= classMethod
.getSignature(inheritorSubstitutor
);
324 if (signature
.equals(method
.getSignature(PsiSubstitutor
.EMPTY
))) {
325 if (!classMethod
.hasModifierProperty(PsiModifier
.ABSTRACT
)) {
326 usages
.add(new NoLongerOverridingSubClassMethodUsageInfo(method
, baseMethod
));
336 protected void refreshElements(PsiElement
[] elements
) {
339 protected void performRefactoring(UsageInfo
[] usages
) {
341 for (UsageInfo aUsage
: usages
) {
342 InheritanceToDelegationUsageInfo usage
= (InheritanceToDelegationUsageInfo
)aUsage
;
345 if (usage
instanceof UnqualifiedNonDelegatedMemberUsageInfo
) {
346 delegateUsageFromClass(usage
.getElement(), ((NonDelegatedMemberUsageInfo
)usage
).nonDelegatedMember
,
347 usage
.getDelegateFieldAccessible());
350 upcastToDelegation(usage
.getElement(), usage
.getDelegateFieldAccessible());
354 myAbstractDelegatedMethods
= new HashSet
<PsiMethod
>();
358 addImplementingInterfaces();
359 } catch (IncorrectOperationException e
) {
364 private void addInnerClass() throws IncorrectOperationException
{
365 if (!myIsInnerClassNeeded
) return;
367 PsiClass innerClass
= myFactory
.createClass(myInnerClassName
);
368 final PsiJavaCodeReferenceElement baseClassReferenceElement
= myFactory
.createClassReferenceElement(myBaseClass
);
369 if (!myBaseClass
.isInterface()) {
370 innerClass
.getExtendsList().add(baseClassReferenceElement
);
372 innerClass
.getImplementsList().add(baseClassReferenceElement
);
374 PsiUtil
.setModifierProperty(innerClass
, PsiModifier
.PRIVATE
, true);
375 innerClass
= (PsiClass
) myClass
.add(innerClass
);
377 List
<InnerClassMethod
> innerClassMethods
= getInnerClassMethods();
378 for (InnerClassMethod innerClassMethod
: innerClassMethods
) {
379 innerClassMethod
.createMethod(innerClass
);
383 private void delegateUsageFromClass(PsiElement element
, PsiElement nonDelegatedMember
,
384 FieldAccessibility fieldAccessibility
) throws IncorrectOperationException
{
385 if (element
instanceof PsiReferenceExpression
) {
386 PsiReferenceExpression referenceExpression
= (PsiReferenceExpression
) element
;
387 if (referenceExpression
.getQualifierExpression() != null) {
388 upcastToDelegation(referenceExpression
.getQualifierExpression(), fieldAccessibility
);
390 final String name
= ((PsiNamedElement
) nonDelegatedMember
).getName();
391 final String qualifier
;
392 if (isStatic (nonDelegatedMember
)) {
393 qualifier
= myBaseClass
.getName();
395 else if (!fieldAccessibility
.isAccessible() && myGenerateGetter
) {
396 qualifier
= myGetterName
+ "()";
399 qualifier
= myFieldName
;
402 PsiExpression newExpr
= myFactory
.createExpressionFromText(qualifier
+ "." + name
, element
);
403 newExpr
= (PsiExpression
) CodeStyleManager
.getInstance(myProject
).reformat(newExpr
);
404 element
.replace(newExpr
);
407 else if (element
instanceof PsiJavaCodeReferenceElement
) {
408 final String name
= ((PsiNamedElement
) nonDelegatedMember
).getName();
410 PsiElement parent
= element
.getParent ();
411 if (!isStatic (nonDelegatedMember
) && parent
instanceof PsiNewExpression
) {
412 final PsiNewExpression newExpr
= (PsiNewExpression
) parent
;
413 if (newExpr
.getQualifier() != null) {
414 upcastToDelegation(newExpr
.getQualifier(), fieldAccessibility
);
416 final String qualifier
;
417 if (!fieldAccessibility
.isAccessible() && myGenerateGetter
) {
418 qualifier
= myGetterName
+ "()";
421 qualifier
= myFieldName
;
423 newExpr
.replace(myFactory
.createExpressionFromText(qualifier
+ "." + newExpr
.getText(), parent
));
427 final String qualifier
= myBaseClass
.getName();
428 PsiJavaCodeReferenceElement newRef
= myFactory
.createFQClassNameReferenceElement(qualifier
+ "." + name
, element
.getResolveScope ());
429 //newRef = (PsiJavaCodeReferenceElement) CodeStyleManager.getInstance(myProject).reformat(newRef);
430 element
.replace(newRef
);
433 LOG
.assertTrue(false);
437 private static boolean isStatic(PsiElement member
) {
438 if (member
instanceof PsiModifierListOwner
) {
439 final PsiModifierListOwner method
= (PsiModifierListOwner
) member
;
440 return method
.hasModifierProperty (PsiModifier
.STATIC
);
445 private void upcastToDelegation(PsiElement element
, FieldAccessibility fieldAccessibility
) throws IncorrectOperationException
{
446 final PsiExpression expression
= (PsiExpression
) element
;
448 final PsiExpression newExpr
;
449 final PsiReferenceExpression ref
;
450 @NonNls final String delegateQualifier
;
451 if (!(expression
instanceof PsiThisExpression
|| expression
instanceof PsiSuperExpression
)) {
452 delegateQualifier
= "a.";
454 PsiResolveHelper resolveHelper
= JavaPsiFacade
.getInstance(myProject
).getResolveHelper();
455 final PsiVariable psiVariable
= resolveHelper
.resolveReferencedVariable(myFieldName
, element
);
456 if (psiVariable
== null) {
457 delegateQualifier
= "";
459 delegateQualifier
= "a.";
462 if (!fieldAccessibility
.isAccessible() && myGenerateGetter
) {
463 newExpr
= myFactory
.createExpressionFromText(delegateQualifier
+ myGetterName
+ "()", expression
);
464 ref
= (PsiReferenceExpression
) ((PsiMethodCallExpression
) newExpr
).getMethodExpression().getQualifierExpression();
466 newExpr
= myFactory
.createExpressionFromText(delegateQualifier
+ myFieldName
, expression
);
467 ref
= (PsiReferenceExpression
) ((PsiReferenceExpression
) newExpr
).getQualifierExpression();
469 // LOG.debug("upcastToDelegation:" + element + ":newExpr = " + newExpr);
470 // LOG.debug("upcastToDelegation:" + element + ":ref = " + ref);
472 ref
.replace(expression
);
474 expression
.replace(newExpr
);
475 // LOG.debug("upcastToDelegation:" + element + ":replaced = " + replaced);
478 private void delegateMethods() throws IncorrectOperationException
{
479 for (PsiMethod method
: myDelegatedMethods
) {
480 if (!myAbstractDelegatedMethods
.contains(method
)) {
481 PsiMethod methodToAdd
= delegateMethod(myFieldName
, method
, getSuperSubstitutor(method
.getContainingClass()));
483 String visibility
= myDelegatedMethodsVisibility
.get(method
);
484 if (visibility
!= null) {
485 PsiUtil
.setModifierProperty(methodToAdd
, visibility
, true);
488 myClass
.add(methodToAdd
);
493 private PsiMethod
delegateMethod(@NonNls String delegationTarget
,
495 PsiSubstitutor substitutor
) throws IncorrectOperationException
{
496 substitutor
= GenerateMembersUtil
.correctSubstitutor(method
, substitutor
);
497 PsiMethod methodToAdd
= GenerateMembersUtil
.substituteGenericMethod(method
, substitutor
);
499 final PsiModifierList modifierList
= methodToAdd
.getModifierList();
500 modifierList
.setModifierProperty(PsiModifier
.ABSTRACT
, false);
501 if (AnnotationUtil
.isAnnotated(method
, AnnotationUtil
.NULLABLE
, false)) {
502 modifierList
.addAfter(myFactory
.createAnnotationFromText("@" + AnnotationUtil
.NULLABLE
, methodToAdd
), null);
504 else if (AnnotationUtil
.isAnnotated(method
, AnnotationUtil
.NOT_NULL
, false)) {
505 modifierList
.addAfter(myFactory
.createAnnotationFromText("@" + AnnotationUtil
.NOT_NULL
, methodToAdd
), null);
508 final String delegationBody
= getDelegationBody(methodToAdd
, delegationTarget
);
509 PsiCodeBlock newBody
= myFactory
.createCodeBlockFromText(delegationBody
, method
);
511 PsiCodeBlock oldBody
= methodToAdd
.getBody();
512 if (oldBody
!= null) {
513 oldBody
.replace(newBody
);
516 methodToAdd
.addBefore(newBody
, null);
519 if (methodToAdd
.getDocComment() != null) methodToAdd
.getDocComment().delete();
520 methodToAdd
= (PsiMethod
)CodeStyleManager
.getInstance(myProject
).reformat(methodToAdd
);
521 methodToAdd
= (PsiMethod
)JavaCodeStyleManager
.getInstance(myProject
).shortenClassReferences(methodToAdd
);
525 private static String
getDelegationBody(PsiMethod methodToAdd
, String delegationTarget
) {
526 @NonNls final StringBuffer buffer
= new StringBuffer();
527 buffer
.append("{\n");
529 if (methodToAdd
.getReturnType() != PsiType
.VOID
) {
530 buffer
.append("return ");
533 buffer
.append(delegationTarget
);
535 buffer
.append(methodToAdd
.getName());
537 PsiParameter
[] params
= methodToAdd
.getParameterList().getParameters();
538 for (int i
= 0; i
< params
.length
; i
++) {
539 PsiParameter param
= params
[i
];
543 buffer
.append(param
.getName());
545 buffer
.append(");\n}");
546 return buffer
.toString();
549 private void addImplementingInterfaces() throws IncorrectOperationException
{
550 final PsiReferenceList implementsList
= myClass
.getImplementsList();
551 for (PsiClass delegatedInterface
: myDelegatedInterfaces
) {
552 if (!myClassImplementedInterfaces
.contains(delegatedInterface
)) {
553 implementsList
.add(myFactory
.createClassReferenceElement(delegatedInterface
));
557 if (!myBaseClass
.isInterface()) {
558 final PsiReferenceList extendsList
= myClass
.getExtendsList();
559 extendsList
.getReferenceElements()[0].delete();
561 final PsiJavaCodeReferenceElement
[] interfaceRefs
= implementsList
.getReferenceElements();
562 for (PsiJavaCodeReferenceElement interfaceRef
: interfaceRefs
) {
563 final PsiElement resolved
= interfaceRef
.resolve();
564 if (myManager
.areElementsEquivalent(myBaseClass
, resolved
)) {
565 interfaceRef
.delete();
572 private void addField(UsageInfo
[] usages
) throws IncorrectOperationException
{
573 final String fieldVisibility
= getFieldVisibility(usages
);
575 final boolean fieldInitializerNeeded
= isFieldInitializerNeeded();
577 PsiField field
= createField(fieldVisibility
, fieldInitializerNeeded
, defaultClassFieldType());
579 if (!myIsInnerClassNeeded
) {
580 field
.getTypeElement().replace(myFactory
.createTypeElement(myBaseClassType
));
581 if (fieldInitializerNeeded
) {
582 final PsiJavaCodeReferenceElement classReferenceElement
= myFactory
.createReferenceElementByType(myBaseClassType
);
583 PsiNewExpression newExpression
= (PsiNewExpression
) field
.getInitializer();
584 newExpression
.getClassReference().replace(classReferenceElement
);
588 field
= (PsiField
) CodeStyleManager
.getInstance(myProject
).reformat(field
);
590 if (!fieldInitializerNeeded
) {
594 if (myGenerateGetter
) {
595 final String getterVisibility
= PsiModifier
.PUBLIC
;
596 @NonNls StringBuffer getterBuffer
= new StringBuffer();
597 getterBuffer
.append(getterVisibility
);
598 getterBuffer
.append(" Object ");
599 getterBuffer
.append(myGetterName
);
600 getterBuffer
.append("() {\n return ");
601 getterBuffer
.append(myFieldName
);
602 getterBuffer
.append(";\n}");
603 PsiMethod getter
= myFactory
.createMethodFromText(getterBuffer
.toString(), myClass
);
604 getter
.getReturnTypeElement().replace(myFactory
.createTypeElement(myBaseClassType
));
605 getter
= (PsiMethod
) CodeStyleManager
.getInstance(myProject
).reformat(getter
);
610 private String
getFieldVisibility(UsageInfo
[] usages
) {
611 if (myIsDelegateOtherMembers
&& !myGenerateGetter
) {
612 return PsiModifier
.PUBLIC
;
615 for (UsageInfo aUsage
: usages
) {
616 InheritanceToDelegationUsageInfo usage
= (InheritanceToDelegationUsageInfo
)aUsage
;
617 final FieldAccessibility delegateFieldAccessible
= usage
.getDelegateFieldAccessible();
618 if (delegateFieldAccessible
.isAccessible() && delegateFieldAccessible
.getContainingClass() != myClass
) {
619 return PsiModifier
.PROTECTED
;
622 return PsiModifier
.PRIVATE
;
625 private @NonNls String
defaultClassFieldType() {
626 return (myIsInnerClassNeeded ? myInnerClassName
: "Object");
629 private PsiField
createField(final String fieldVisibility
, final boolean fieldInitializerNeeded
, String defaultTypeName
) throws IncorrectOperationException
{
630 @NonNls StringBuffer buffer
= new StringBuffer();
631 buffer
.append(fieldVisibility
);
632 buffer
.append(" final " + defaultTypeName
+ " ");
633 buffer
.append(myFieldName
);
634 if (fieldInitializerNeeded
) {
635 buffer
.append(" = new " + defaultTypeName
+ "()");
638 return myFactory
.createFieldFromText(buffer
.toString(), myClass
);
641 private void fixConstructors() throws IncorrectOperationException
{
642 if (myBaseClass
.isInterface()) return;
643 final PsiJavaCodeReferenceElement baseClassReference
= myFactory
.createClassReferenceElement(myBaseClass
);
645 PsiMethod
[] constructors
= myClass
.getConstructors();
646 for (PsiMethod constructor
: constructors
) {
647 PsiCodeBlock body
= constructor
.getBody();
648 final PsiStatement
[] statements
= body
.getStatements();
649 @NonNls String fieldQualifier
= "";
650 PsiParameter
[] constructorParams
= constructor
.getParameterList().getParameters();
651 for (PsiParameter constructorParam
: constructorParams
) {
652 if (myFieldName
.equals(constructorParam
.getName())) {
653 fieldQualifier
= "this.";
657 final @NonNls String assignmentText
= fieldQualifier
+ myFieldName
+ "= new " + defaultClassFieldType() + "()";
658 if (statements
.length
< 1 || !RefactoringUtil
.isSuperOrThisCall(statements
[0], true, true) || myBaseClass
.isInterface()) {
659 PsiExpressionStatement assignmentStatement
=
660 (PsiExpressionStatement
)myFactory
.createStatementFromText(
663 if (!myIsInnerClassNeeded
) {
664 final PsiAssignmentExpression assignmentExpr
= (PsiAssignmentExpression
)assignmentStatement
.getExpression();
665 final PsiNewExpression newExpression
= (PsiNewExpression
)assignmentExpr
.getRExpression();
666 assert newExpression
!= null;
667 final PsiJavaCodeReferenceElement classRef
= newExpression
.getClassReference();
668 assert classRef
!= null;
669 classRef
.replace(baseClassReference
);
672 assignmentStatement
= (PsiExpressionStatement
)CodeStyleManager
.getInstance(myProject
).reformat(assignmentStatement
);
673 if (statements
.length
> 0) {
674 if (!RefactoringUtil
.isSuperOrThisCall(statements
[0], true, false)) {
675 body
.addBefore(assignmentStatement
, statements
[0]);
678 body
.addAfter(assignmentStatement
, statements
[0]);
682 body
.add(assignmentStatement
);
686 final PsiExpressionStatement callStatement
= ((PsiExpressionStatement
)statements
[0]);
687 if (!RefactoringUtil
.isSuperOrThisCall(callStatement
, false, true)) {
688 final PsiMethodCallExpression superConstructorCall
=
689 (PsiMethodCallExpression
)callStatement
.getExpression();
690 PsiAssignmentExpression assignmentExpression
=
691 (PsiAssignmentExpression
)myFactory
.createExpressionFromText(
692 assignmentText
, superConstructorCall
694 PsiNewExpression newExpression
=
695 (PsiNewExpression
)assignmentExpression
.getRExpression();
696 if (!myIsInnerClassNeeded
) {
697 newExpression
.getClassReference().replace(baseClassReference
);
699 assignmentExpression
= (PsiAssignmentExpression
)CodeStyleManager
.getInstance(myProject
).reformat(assignmentExpression
);
700 newExpression
.getArgumentList().replace(superConstructorCall
.getArgumentList());
701 superConstructorCall
.replace(assignmentExpression
);
707 private boolean isFieldInitializerNeeded() {
708 if (myBaseClass
.isInterface()) return true;
709 PsiMethod
[] constructors
= myClass
.getConstructors();
710 for (PsiMethod constructor
: constructors
) {
711 final PsiStatement
[] statements
= constructor
.getBody().getStatements();
712 if (statements
.length
> 0 && RefactoringUtil
.isSuperOrThisCall(statements
[0], true, false)) return false;
717 private List
<InnerClassMethod
> getInnerClassMethods() {
718 ArrayList
<InnerClassMethod
> result
= new ArrayList
<InnerClassMethod
>();
720 // find all neccessary constructors
721 if (!myBaseClass
.isInterface()) {
722 PsiMethod
[] constructors
= myClass
.getConstructors();
723 for (PsiMethod constructor
: constructors
) {
724 final PsiStatement
[] statements
= constructor
.getBody().getStatements();
725 if (statements
.length
> 0 && RefactoringUtil
.isSuperOrThisCall(statements
[0], true, false)) {
726 final PsiMethodCallExpression superConstructorCall
=
727 (PsiMethodCallExpression
)((PsiExpressionStatement
)statements
[0]).getExpression();
728 PsiElement superConstructor
= superConstructorCall
.getMethodExpression().resolve();
729 if (superConstructor
instanceof PsiMethod
&& ((PsiMethod
)superConstructor
).isConstructor()) {
730 result
.add(new InnerClassConstructor((PsiMethod
)superConstructor
));
736 // find overriding/implementing method
738 class InnerClassOverridingMethod
extends InnerClassMethod
{
739 public InnerClassOverridingMethod(PsiMethod method
) {
743 public void createMethod(PsiClass innerClass
)
744 throws IncorrectOperationException
{
745 OverriddenMethodClassMemberReferencesVisitor visitor
= new OverriddenMethodClassMemberReferencesVisitor();
746 myClass
.accept(visitor
);
747 final List
<PsiAction
> actions
= visitor
.getPsiActions();
748 for (PsiAction action
: actions
) {
751 innerClass
.add(myMethod
);
753 // myMethod.replace(delegateMethod(myMethod));
757 for (PsiMethod method
: myOverriddenMethods
) {
758 result
.add(new InnerClassOverridingMethod(method
));
762 // fix abstract methods
764 class InnerClassAbstractMethod
extends InnerClassMethod
{
765 private final boolean myImplicitImplementation
;
767 public InnerClassAbstractMethod(PsiMethod method
, final boolean implicitImplementation
) {
769 myImplicitImplementation
= implicitImplementation
;
772 public void createMethod(PsiClass innerClass
)
773 throws IncorrectOperationException
{
774 PsiSubstitutor substitutor
= getSuperSubstitutor(myMethod
.getContainingClass());
775 PsiMethod method
= delegateMethod(myClass
.getName() + ".this", myMethod
, substitutor
);
776 final PsiClass containingClass
= myMethod
.getContainingClass();
777 if (myBaseClass
.isInterface() || containingClass
.isInterface()) {
778 PsiUtil
.setModifierProperty(method
, PsiModifier
.PUBLIC
, true);
780 innerClass
.add(method
);
781 if (!myImplicitImplementation
) {
782 final MethodSignature signature
= myMethod
.getSignature(substitutor
);
783 PsiMethod outerMethod
= MethodSignatureUtil
.findMethodBySignature(myClass
, signature
, false);
784 if (outerMethod
== null) {
785 @Modifier String visibility
= checkOuterClassAbstractMethod(signature
);
786 PsiMethod newOuterMethod
= (PsiMethod
)myClass
.add(myMethod
);
787 PsiUtil
.setModifierProperty(newOuterMethod
, visibility
, true);
788 final PsiDocComment docComment
= newOuterMethod
.getDocComment();
789 if (docComment
!= null) {
797 PsiMethod
[] methods
= myBaseClass
.getAllMethods();
799 for (PsiMethod method
: methods
) {
800 if (method
.hasModifierProperty(PsiModifier
.ABSTRACT
)) {
801 final MethodSignature signature
= method
.getSignature(getSuperSubstitutor(method
.getContainingClass()));
802 PsiMethod classMethod
= MethodSignatureUtil
.findMethodBySignature(myClass
, signature
, true);
803 if (classMethod
== null || classMethod
.hasModifierProperty(PsiModifier
.ABSTRACT
)) {
804 result
.add(new InnerClassAbstractMethod(method
, false));
806 else if ((myBaseClass
.isInterface() && classMethod
.getContainingClass() != myClass
)) { // IDEADEV-19675
807 result
.add(new InnerClassAbstractMethod(method
, true));
817 private void showObjectUpcastedUsageView(final ObjectUpcastedUsageInfo
[] usages
) {
818 UsageViewPresentation presentation
= new UsageViewPresentation();
819 presentation
.setTargetsNodeText(RefactoringBundle
.message("replacing.inheritance.with.delegation"));
820 presentation
.setCodeUsagesString(RefactoringBundle
.message("instances.casted.to.java.lang.object"));
821 final String upcastedString
= RefactoringBundle
.message("instances.upcasted.to.object");
822 presentation
.setUsagesString(upcastedString
);
823 presentation
.setTabText(upcastedString
);
825 UsageViewManager manager
= UsageViewManager
.getInstance(myProject
);
827 new UsageTarget
[]{new PsiElement2UsageTargetAdapter(myClass
)},
828 UsageInfoToUsageConverter
.convert(new UsageInfoToUsageConverter
.TargetElementsDescriptor(myClass
), usages
),
832 WindowManager
.getInstance().getStatusBar(myProject
).setInfo(RefactoringBundle
.message("instances.upcasted.to.java.lang.object.found"));
837 * @param methodSignature
841 private String
checkOuterClassAbstractMethod(MethodSignature methodSignature
) {
842 @Modifier String visibility
= PsiModifier
.PROTECTED
;
843 for (PsiMethod method
: myDelegatedMethods
) {
844 MethodSignature otherSignature
= method
.getSignature(getSuperSubstitutor(method
.getContainingClass()));
846 if (MethodSignatureUtil
.areSignaturesEqual(otherSignature
, methodSignature
)) {
847 visibility
= VisibilityUtil
.getHighestVisibility(visibility
,
848 VisibilityUtil
.getVisibilityModifier(method
.getModifierList()));
849 myAbstractDelegatedMethods
.add(method
);
855 private Set
<PsiMethod
> getOverriddenMethods() {
856 LinkedHashSet
<PsiMethod
> result
= new LinkedHashSet
<PsiMethod
>();
858 PsiMethod
[] methods
= myClass
.getMethods();
859 for (PsiMethod method
: methods
) {
860 if (findSuperMethodInBaseClass(method
) != null) result
.add(method
);
866 private PsiMethod
findSuperMethodInBaseClass (PsiMethod method
) {
867 final PsiMethod
[] superMethods
= method
.findSuperMethods();
868 for (PsiMethod superMethod
: superMethods
) {
869 PsiClass containingClass
= superMethod
.getContainingClass();
870 if (InheritanceUtil
.isInheritorOrSelf(myBaseClass
, containingClass
, true)) {
871 String qName
= containingClass
.getQualifiedName();
872 if (qName
== null || !"java.lang.Object".equals(qName
)) {
881 protected String
getCommandName() {
882 return RefactoringBundle
.message("replace.inheritance.with.delegation.command", UsageViewUtil
.getDescriptiveName(myClass
));
885 private Set
<PsiMember
> getAllBaseClassMembers() {
886 HashSet
<PsiMember
> result
= new HashSet
<PsiMember
>();
887 addAll(result
, myBaseClass
.getAllFields());
888 addAll(result
, myBaseClass
.getAllInnerClasses());
889 addAll(result
, myBaseClass
.getAllMethods());
891 //remove java.lang.Object members
892 for (Iterator
<PsiMember
> iterator
= result
.iterator(); iterator
.hasNext();) {
893 PsiMember member
= iterator
.next();
894 if ("java.lang.Object".equals(member
.getContainingClass().getQualifiedName())) {
898 return Collections
.unmodifiableSet(result
);
901 private Set
<PsiClass
> getAllBases() {
902 HashSet
<PsiClass
> temp
= new HashSet
<PsiClass
>();
903 InheritanceUtil
.getSuperClasses(myBaseClass
, temp
, true);
904 temp
.add(myBaseClass
);
905 return Collections
.unmodifiableSet(temp
);
908 private static <T
> void addAll(Collection
<T
> collection
, T
[] objs
) {
914 private boolean isDelegated(PsiMember classMember
) {
915 if(!(classMember
instanceof PsiMethod
)) return false;
916 final PsiMethod method
= (PsiMethod
) classMember
;
917 for (PsiMethod delegatedMethod
: myDelegatedMethods
) {
918 //methods reside in base class, so no substitutor needed
919 if (MethodSignatureUtil
.areSignaturesEqual(method
.getSignature(PsiSubstitutor
.EMPTY
),
920 delegatedMethod
.getSignature(PsiSubstitutor
.EMPTY
))) {
927 private class MyClassInheritorMemberReferencesVisitor
extends ClassMemberReferencesVisitor
{
928 private final List
<UsageInfo
> myUsageInfoStorage
;
929 private final ClassInstanceScanner
.ClassInstanceReferenceVisitor myInstanceVisitor
;
931 MyClassInheritorMemberReferencesVisitor(PsiClass aClass
, List
<UsageInfo
> usageInfoStorage
,
932 ClassInstanceScanner
.ClassInstanceReferenceVisitor instanceScanner
) {
935 myUsageInfoStorage
= usageInfoStorage
;
936 myInstanceVisitor
= instanceScanner
;
939 @Override public void visitTypeElement(PsiTypeElement type
) {
940 super.visitTypeElement (type
);
943 @Override public void visitReferenceElement(PsiJavaCodeReferenceElement element
) {
944 super.visitReferenceElement (element
);
947 protected void visitClassMemberReferenceElement(PsiMember classMember
, PsiJavaCodeReferenceElement classMemberReference
) {
948 if ("super".equals(classMemberReference
.getText()) && classMemberReference
.getParent() instanceof PsiMethodCallExpression
) {
952 if (classMember
!= null && myBaseClassMembers
.contains(classMember
) && !isDelegated(classMember
)) {
953 final FieldAccessibility delegateFieldVisibility
= new FieldAccessibility(true, getPsiClass());
954 final InheritanceToDelegationUsageInfo usageInfo
;
955 if (classMemberReference
instanceof PsiReferenceExpression
) {
956 if (((PsiReferenceExpression
) classMemberReference
).getQualifierExpression() == null) {
957 usageInfo
= new UnqualifiedNonDelegatedMemberUsageInfo(classMemberReference
, classMember
,
958 delegateFieldVisibility
);
960 usageInfo
= new NonDelegatedMemberUsageInfo(
961 ((PsiReferenceExpression
) classMemberReference
).getQualifierExpression(),
962 classMember
, delegateFieldVisibility
965 myUsageInfoStorage
.add(usageInfo
);
967 else /*if (classMemberReference instanceof PsiJavaCodeReferenceElement)*/ {
968 usageInfo
= new UnqualifiedNonDelegatedMemberUsageInfo(classMemberReference
, classMember
,
969 delegateFieldVisibility
);
970 myUsageInfoStorage
.add(usageInfo
);
976 @Override public void visitThisExpression(PsiThisExpression expression
) {
977 ClassInstanceScanner
.processNonArrayExpression(myInstanceVisitor
, expression
, null);
981 private class MyClassMemberReferencesVisitor
extends MyClassInheritorMemberReferencesVisitor
{
982 MyClassMemberReferencesVisitor(List
<UsageInfo
> usageInfoStorage
,
983 ClassInstanceScanner
.ClassInstanceReferenceVisitor instanceScanner
) {
984 super(InheritanceToDelegationProcessor
.this.myClass
, usageInfoStorage
, instanceScanner
);
987 @Override public void visitMethod(PsiMethod method
) {
988 if (!myOverriddenMethods
.contains(method
)) {
989 super.visitMethod(method
);
994 interface PsiAction
{
995 void run() throws IncorrectOperationException
;
999 * This visitor should be called for overriden methods before they are moved to an inner class
1001 private class OverriddenMethodClassMemberReferencesVisitor
extends ClassMemberReferencesVisitor
{
1002 private final ArrayList
<PsiAction
> myPsiActions
;
1003 private final PsiThisExpression myQualifiedThis
;
1005 OverriddenMethodClassMemberReferencesVisitor() throws IncorrectOperationException
{
1007 myPsiActions
= new ArrayList
<PsiAction
>();
1008 final PsiJavaCodeReferenceElement classReferenceElement
= myFactory
.createClassReferenceElement(myClass
);
1009 myQualifiedThis
= (PsiThisExpression
) myFactory
.createExpressionFromText("A.this", null);
1010 myQualifiedThis
.getQualifier().replace(classReferenceElement
);
1013 public List
<PsiAction
> getPsiActions() {
1014 return myPsiActions
;
1017 class QualifyThis
implements PsiAction
{
1018 private final PsiThisExpression myThisExpression
;
1020 QualifyThis(PsiThisExpression thisExpression
) {
1021 myThisExpression
= thisExpression
;
1024 public void run() throws IncorrectOperationException
{
1025 myThisExpression
.replace(myQualifiedThis
);
1029 class QualifyName
implements PsiAction
{
1030 private final PsiReferenceExpression myRef
;
1031 private final String myReferencedName
;
1033 QualifyName(PsiReferenceExpression ref
, String name
) {
1035 myReferencedName
= name
;
1038 public void run() throws IncorrectOperationException
{
1039 PsiReferenceExpression newRef
=
1040 (PsiReferenceExpression
) myFactory
.createExpressionFromText("a." + myReferencedName
, null);
1041 newRef
.getQualifierExpression().replace(myQualifiedThis
);
1042 myRef
.replace(newRef
);
1046 class QualifyWithField
implements PsiAction
{
1047 private final PsiReferenceExpression myReference
;
1048 private final String myReferencedName
;
1050 public QualifyWithField(final PsiReferenceExpression reference
, final String name
) {
1051 myReference
= reference
;
1052 myReferencedName
= name
;
1055 public void run() throws IncorrectOperationException
{
1056 PsiReferenceExpression newRef
=
1057 (PsiReferenceExpression
) myFactory
.createExpressionFromText(myFieldName
+ "." + myReferencedName
, null);
1058 myReference
.replace(newRef
);
1062 protected void visitClassMemberReferenceExpression(PsiMember classMember
,
1063 PsiReferenceExpression classMemberReference
) {
1064 if (classMember
instanceof PsiField
) {
1065 final PsiField field
= (PsiField
) classMember
;
1067 if (field
.getContainingClass().equals(myClass
)) {
1068 final String name
= field
.getName();
1069 final PsiField baseField
= myBaseClass
.findFieldByName(name
, true);
1070 if (baseField
!= null) {
1071 myPsiActions
.add(new QualifyName(classMemberReference
, name
));
1072 } else if (classMemberReference
.getQualifierExpression() instanceof PsiThisExpression
) {
1073 myPsiActions
.add(new QualifyThis((PsiThisExpression
) classMemberReference
.getQualifierExpression()));
1076 } else if (classMember
instanceof PsiMethod
) {
1077 final PsiMethod method
= (PsiMethod
) classMember
;
1079 if (method
.getContainingClass().equals(myClass
)) {
1080 if (!myOverriddenMethods
.contains(method
)) {
1081 final PsiMethod baseMethod
= findSuperMethodInBaseClass(method
);
1082 if (baseMethod
!= null) {
1083 myPsiActions
.add(new QualifyName(classMemberReference
, baseMethod
.getName()));
1084 } else if (classMemberReference
.getQualifierExpression() instanceof PsiThisExpression
) {
1085 myPsiActions
.add(new QualifyThis((PsiThisExpression
) classMemberReference
.getQualifierExpression()));
1088 else if (!myDelegatedMethods
.contains(method
)) {
1089 myPsiActions
.add(new QualifyWithField(classMemberReference
, method
.getName()));
1095 @Override public void visitThisExpression(final PsiThisExpression expression
) {
1096 class Visitor
implements ClassInstanceScanner
.ClassInstanceReferenceVisitor
{
1097 public void visitQualifier(PsiReferenceExpression qualified
, PsiExpression instanceRef
, PsiElement referencedInstance
) {
1098 LOG
.assertTrue(false);
1101 public void visitTypeCast(PsiTypeCastExpression typeCastExpression
, PsiExpression instanceRef
, PsiElement referencedInstance
) {
1102 processType(typeCastExpression
.getCastType().getType());
1105 public void visitReadUsage(PsiExpression instanceRef
, PsiType expectedType
, PsiElement referencedInstance
) {
1106 processType(expectedType
);
1109 public void visitWriteUsage(PsiExpression instanceRef
, PsiType assignedType
, PsiElement referencedInstance
) {
1110 LOG
.assertTrue(false);
1113 private void processType(PsiType type
) {
1114 final PsiClass resolved
= PsiUtil
.resolveClassInType(type
);
1115 if (resolved
!= null && !myBaseClassBases
.contains(resolved
)) {
1116 myPsiActions
.add(new QualifyThis(expression
));
1120 Visitor visitor
= new Visitor();
1121 ClassInstanceScanner
.processNonArrayExpression(visitor
, expression
, null);
1124 protected void visitClassMemberReferenceElement(PsiMember classMember
, PsiJavaCodeReferenceElement classMemberReference
) {
1130 private final class MyClassInstanceReferenceVisitor
implements ClassInstanceScanner
.ClassInstanceReferenceVisitor
{
1131 private final PsiClass myClass
;
1132 private final List
<UsageInfo
> myUsageInfoStorage
;
1133 private final Set
<PsiClass
> myImplementedInterfaces
;
1135 public MyClassInstanceReferenceVisitor(PsiClass aClass
, List
<UsageInfo
> usageInfoStorage
) {
1137 myUsageInfoStorage
= usageInfoStorage
;
1138 myImplementedInterfaces
= getImplementedInterfaces();
1141 public Set
<PsiClass
> getImplementedInterfaces() {
1142 PsiClass aClass
= myClass
;
1143 HashSet
<PsiClass
> result
= new HashSet
<PsiClass
>();
1144 while (aClass
!= null && !myManager
.areElementsEquivalent(aClass
, myBaseClass
)) {
1145 final PsiClassType
[] implementsTypes
= aClass
.getImplementsListTypes();
1146 for (PsiClassType implementsType
: implementsTypes
) {
1147 PsiClass resolved
= implementsType
.resolve();
1148 if (resolved
!= null && !myManager
.areElementsEquivalent(resolved
, myBaseClass
)) {
1149 result
.add(resolved
);
1150 InheritanceUtil
.getSuperClasses(resolved
, result
, true);
1154 aClass
= aClass
.getSuperClass();
1160 public void visitQualifier(PsiReferenceExpression qualified
, PsiExpression instanceRef
, PsiElement referencedInstance
) {
1161 final PsiExpression qualifierExpression
= qualified
.getQualifierExpression();
1163 // do not add usages inside a class
1164 if (qualifierExpression
== null
1165 || qualifierExpression
instanceof PsiThisExpression
1166 || qualifierExpression
instanceof PsiSuperExpression
) {
1170 PsiElement resolved
= qualified
.resolve();
1171 if (resolved
!= null && (myBaseClassMembers
.contains(resolved
) || myOverriddenMethods
.contains(resolved
))
1172 && !isDelegated((PsiMember
)resolved
)) {
1173 myUsageInfoStorage
.add(new NonDelegatedMemberUsageInfo(instanceRef
, resolved
, getFieldAccessibility(instanceRef
)));
1177 public void visitTypeCast(PsiTypeCastExpression typeCastExpression
, PsiExpression instanceRef
, PsiElement referencedInstance
) {
1178 processTypedUsage(typeCastExpression
.getCastType().getType(), instanceRef
);
1182 public void visitReadUsage(PsiExpression instanceRef
, PsiType expectedType
, PsiElement referencedInstance
) {
1183 processTypedUsage(expectedType
, instanceRef
);
1186 public void visitWriteUsage(PsiExpression instanceRef
, PsiType assignedType
, PsiElement referencedInstance
) {
1189 private void processTypedUsage(PsiType type
, PsiExpression instanceRef
) {
1190 final PsiClass aClass
= PsiUtil
.resolveClassInType(type
);
1191 if (aClass
== null) return;
1192 String qName
= aClass
.getQualifiedName();
1193 if (qName
!= null && "java.lang.Object".equals(qName
)) {
1194 myUsageInfoStorage
.add(new ObjectUpcastedUsageInfo(instanceRef
, aClass
, getFieldAccessibility(instanceRef
)));
1196 if (myBaseClassBases
.contains(aClass
)
1197 && !myImplementedInterfaces
.contains(aClass
) && !myDelegatedInterfaces
.contains(aClass
)) {
1198 myUsageInfoStorage
.add(new UpcastedUsageInfo(instanceRef
, aClass
, getFieldAccessibility(instanceRef
)));