Search in sources :

Example 1 with OverriderUsageInfo

use of com.intellij.refactoring.typeMigration.usageInfo.OverriderUsageInfo in project intellij-community by JetBrains.

the class TypeMigrationLabeler method addMigrationRoot.

boolean addMigrationRoot(PsiElement element, PsiType type, final PsiElement place, boolean alreadyProcessed, final boolean isContraVariantPosition, final boolean userDefinedType) {
    if (type.equals(PsiType.NULL)) {
        return false;
    }
    final PsiElement resolved = Util.normalizeElement(element);
    if (!canBeRoot(resolved, myRules.getSearchScope())) {
        return false;
    }
    final PsiType originalType = getElementType(resolved);
    LOG.assertTrue(originalType != null);
    type = userDefinedType ? type : TypeEvaluator.substituteType(type, originalType, isContraVariantPosition);
    if (!userDefinedType) {
        final Set<PsiTypeParameter> collector;
        if (type instanceof PsiClassType) {
            collector = type.accept(new PsiExtendedTypeVisitor<Set<PsiTypeParameter>>() {

                private final Set<PsiTypeParameter> myResult = new HashSet<>();

                @Override
                public Set<PsiTypeParameter> visitClassType(PsiClassType classType) {
                    super.visitClassType(classType);
                    final PsiClass resolved = classType.resolve();
                    if (resolved instanceof PsiTypeParameter) {
                        myResult.add((PsiTypeParameter) resolved);
                    }
                    return myResult;
                }
            });
        } else {
            collector = Collections.emptySet();
        }
        if (typeContainsTypeParameters(originalType, collector))
            return false;
    }
    if (type instanceof PsiCapturedWildcardType) {
        return false;
    }
    if (resolved instanceof PsiMethod) {
        final PsiMethod method = ((PsiMethod) resolved);
        final PsiClass containingClass = method.getContainingClass();
        if (containingClass instanceof PsiAnonymousClass) {
            final HierarchicalMethodSignature signature = method.getHierarchicalMethodSignature();
            final List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
            if (!superSignatures.isEmpty()) {
                final HierarchicalMethodSignature superSignature = superSignatures.get(0);
                final PsiSubstitutor substitutor = superSignature.getSubstitutor();
                if (!substitutor.getSubstitutionMap().isEmpty()) {
                    final PsiMethod superMethod = superSignature.getMethod();
                    final PsiType superReturnType = superMethod.getReturnType();
                    if (superReturnType instanceof PsiClassType) {
                        final PsiClass resolvedClass = ((PsiClassType) superReturnType).resolve();
                        if (resolvedClass instanceof PsiTypeParameter) {
                            final PsiType expectedReturnType = substitutor.substitute((PsiTypeParameter) resolvedClass);
                            if (Comparing.equal(expectedReturnType, method.getReturnType())) {
                                final PsiClassType baseClassType = ((PsiAnonymousClass) containingClass).getBaseClassType();
                                final PsiClassType.ClassResolveResult result = baseClassType.resolveGenerics();
                                final PsiClass anonymousBaseClass = result.getElement();
                                final PsiSubstitutor superHierarchySubstitutor = TypeConversionUtil.getClassSubstitutor(superMethod.getContainingClass(), anonymousBaseClass, PsiSubstitutor.EMPTY);
                                final PsiType maybeTypeParameter = superHierarchySubstitutor.substitute((PsiTypeParameter) resolvedClass);
                                if (maybeTypeParameter instanceof PsiClassType && ((PsiClassType) maybeTypeParameter).resolve() instanceof PsiTypeParameter) {
                                    final PsiSubstitutor newSubstitutor = result.getSubstitutor().put((PsiTypeParameter) ((PsiClassType) maybeTypeParameter).resolve(), type);
                                    addRoot(new TypeMigrationUsageInfo(((PsiAnonymousClass) containingClass).getBaseClassReference().getParameterList()), new PsiImmediateClassType(anonymousBaseClass, newSubstitutor), place, alreadyProcessed);
                                }
                            }
                        }
                    }
                }
            }
        }
        final PsiMethod[] methods = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
        final OverriderUsageInfo[] overriders = new OverriderUsageInfo[methods.length];
        for (int i = -1; i < methods.length; i++) {
            final TypeMigrationUsageInfo m;
            if (i < 0) {
                final OverriddenUsageInfo overriddenUsageInfo = new OverriddenUsageInfo(method);
                m = overriddenUsageInfo;
                final String newMethodName = isMethodNameCanBeChanged(method);
                if (newMethodName != null) {
                    final MigrateGetterNameSetting migrateGetterNameSetting = myRules.getConversionSettings(MigrateGetterNameSetting.class);
                    migrateGetterNameSetting.askUserIfNeed(overriddenUsageInfo, newMethodName, myTypeEvaluator.getType(myCurrentRoot));
                }
            } else {
                overriders[i] = new OverriderUsageInfo(methods[i], method);
                m = overriders[i];
            }
            alreadyProcessed = addRoot(m, type, place, alreadyProcessed);
        }
        return !alreadyProcessed;
    } else if (resolved instanceof PsiParameter && ((PsiParameter) resolved).getDeclarationScope() instanceof PsiMethod) {
        final PsiMethod method = (PsiMethod) ((PsiParameter) resolved).getDeclarationScope();
        final int index = method.getParameterList().getParameterIndex(((PsiParameter) resolved));
        final PsiMethod[] methods = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
        final OverriderUsageInfo[] overriders = new OverriderUsageInfo[methods.length];
        final OverriddenUsageInfo overriddenUsageInfo = new OverriddenUsageInfo(method.getParameterList().getParameters()[index]);
        for (int i = -1; i < methods.length; i++) {
            final PsiMethod m = i < 0 ? method : methods[i];
            final PsiParameter p = m.getParameterList().getParameters()[index];
            final TypeMigrationUsageInfo paramUsageInfo;
            if (i < 0) {
                paramUsageInfo = overriddenUsageInfo;
            } else {
                overriders[i] = new OverriderUsageInfo(p, method);
                paramUsageInfo = overriders[i];
            }
            alreadyProcessed = addRoot(paramUsageInfo, type, place, alreadyProcessed);
        }
        return !alreadyProcessed;
    } else {
        return !addRoot(new TypeMigrationUsageInfo(resolved), type, place, alreadyProcessed);
    }
}
Also used : PsiImmediateClassType(com.intellij.psi.impl.source.PsiImmediateClassType) TypeMigrationUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo) PsiExtendedTypeVisitor(com.intellij.refactoring.typeCook.deductive.PsiExtendedTypeVisitor) OverriddenUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.OverriddenUsageInfo) OverriderUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.OverriderUsageInfo)

Aggregations

PsiImmediateClassType (com.intellij.psi.impl.source.PsiImmediateClassType)1 PsiExtendedTypeVisitor (com.intellij.refactoring.typeCook.deductive.PsiExtendedTypeVisitor)1 OverriddenUsageInfo (com.intellij.refactoring.typeMigration.usageInfo.OverriddenUsageInfo)1 OverriderUsageInfo (com.intellij.refactoring.typeMigration.usageInfo.OverriderUsageInfo)1 TypeMigrationUsageInfo (com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo)1