EA-33078 - assert: TypeMigrationLabeler.migrateExpressionType
[idea/community.git] / java / java-impl / src / com / intellij / refactoring / typeMigration / rules / RootTypeConversionRule.java
1 /*
2  * Copyright 2000-2011 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.refactoring.typeMigration.rules;
17
18 import com.intellij.psi.*;
19 import com.intellij.psi.util.InheritanceUtil;
20 import com.intellij.psi.util.TypeConversionUtil;
21 import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
22 import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
23
24 /**
25  * @author anna
26  * Date: 08-Aug-2008
27  */
28 public class RootTypeConversionRule extends TypeConversionRule {
29   public TypeConversionDescriptorBase findConversion(final PsiType from,
30                                                      final PsiType to,
31                                                      final PsiMember member,
32                                                      final PsiExpression context,
33                                                      final TypeMigrationLabeler labeler) {
34     if (to instanceof PsiClassType && from instanceof PsiClassType) {
35       final PsiClass targetClass = ((PsiClassType)to).resolve();
36       if (targetClass != null && member instanceof PsiMethod && member.isPhysical()) {
37         PsiMethod method = (PsiMethod)member;
38         PsiMethod replacer = targetClass.findMethodBySignature(method, true);
39         if (replacer == null) {
40           for (PsiMethod superMethod : method.findDeepestSuperMethods()) {
41             replacer = targetClass.findMethodBySignature(superMethod, true);
42             if (replacer != null) {
43               method = superMethod;
44               break;
45             }
46           }
47         }
48         if (replacer != null && TypeConversionUtil.areTypesConvertible(method.getReturnType(), replacer.getReturnType())) {
49           final PsiElement parent = context.getParent();
50           if (context instanceof PsiReferenceExpression && parent instanceof PsiMethodCallExpression) {
51             final JavaResolveResult resolveResult = ((PsiReferenceExpression)context).advancedResolve(false);
52             final PsiSubstitutor aSubst;
53             final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)parent).getMethodExpression();
54             final PsiExpression qualifier = methodExpression.getQualifierExpression();
55             final PsiClass substitutionClass = method.getContainingClass();
56             if (qualifier != null) {
57               final PsiType evaluatedQualifierType = labeler.getTypeEvaluator().evaluateType(qualifier);
58               if (evaluatedQualifierType instanceof PsiClassType) {
59                 aSubst = ((PsiClassType)evaluatedQualifierType).resolveGenerics().getSubstitutor();
60               }
61               else {
62                 aSubst = PsiSubstitutor.EMPTY;
63               }
64             }
65             else {
66               aSubst = TypeConversionUtil.getClassSubstitutor(member.getContainingClass(), substitutionClass, PsiSubstitutor.EMPTY);
67             }
68
69             final PsiParameter[] originalParams = ((PsiMethod)member).getParameterList().getParameters();
70             final PsiParameter[] migrationParams = replacer.getParameterList().getParameters();
71             final PsiExpression[] actualParams = ((PsiMethodCallExpression)parent).getArgumentList().getExpressions();
72
73             assert originalParams.length == migrationParams.length;
74             final PsiSubstitutor methodTypeParamsSubstitutor =
75               labeler.getTypeEvaluator().createMethodSubstitution(originalParams, actualParams, method, context, aSubst != null ? aSubst : PsiSubstitutor.EMPTY, true);
76             for (int i = 0; i < originalParams.length; i++) {
77               final PsiType originalType = resolveResult.getSubstitutor().substitute(originalParams[i].getType());
78
79               PsiType type = migrationParams[i].getType();
80               if (InheritanceUtil.isInheritorOrSelf(targetClass, substitutionClass, true)) {
81                 final PsiSubstitutor superClassSubstitutor =
82                   TypeConversionUtil.getClassSubstitutor(substitutionClass, targetClass, PsiSubstitutor.EMPTY);
83                 assert (superClassSubstitutor != null);
84                 type = superClassSubstitutor.substitute(type);
85               }
86
87               if (!originalType.equals(type)) {
88                 labeler.migrateExpressionType(actualParams[i], methodTypeParamsSubstitutor.substitute(type), context, false, true);
89               }
90             }
91           }
92           return new TypeConversionDescriptorBase();
93         }
94       }
95     }
96     return null;
97   }
98 }