Search in sources :

Example 1 with TypeConversionDescriptorBase

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

the class RootTypeConversionRule method findConversion.

public TypeConversionDescriptorBase findConversion(final PsiType from, final PsiType to, final PsiMember member, final PsiExpression context, final TypeMigrationLabeler labeler) {
    if (member != null && to instanceof PsiClassType && from instanceof PsiClassType) {
        final PsiClass targetClass = ((PsiClassType) to).resolve();
        if (targetClass != null && member.isPhysical()) {
            if (member instanceof PsiMethod) {
                PsiMethod method = (PsiMethod) member;
                PsiMethod replacer = targetClass.findMethodBySignature(method, true);
                if (replacer == null) {
                    for (PsiMethod superMethod : method.findDeepestSuperMethods()) {
                        replacer = targetClass.findMethodBySignature(superMethod, true);
                        if (replacer != null) {
                            method = superMethod;
                            break;
                        }
                    }
                }
                if (replacer != null) {
                    final boolean isStaticMethodConversion = replacer.hasModifierProperty(PsiModifier.STATIC);
                    boolean isValid = isStaticMethodConversion ? TypeConversionUtil.areTypesConvertible(method.getReturnType(), from) && TypeConversionUtil.areTypesConvertible(replacer.getReturnType(), to) : TypeConversionUtil.areTypesConvertible(method.getReturnType(), replacer.getReturnType());
                    if (isValid) {
                        final PsiElement parent = context.getParent();
                        if (context instanceof PsiMethodReferenceExpression) {
                            final PsiType functionalInterfaceType = ((PsiMethodReferenceExpression) context).getFunctionalInterfaceType();
                            if (Comparing.equal(functionalInterfaceType, to) && method.isEquivalentTo(LambdaUtil.getFunctionalInterfaceMethod(from))) {
                                return new TypeConversionDescriptorBase() {

                                    @Override
                                    public PsiExpression replace(PsiExpression expression, @NotNull TypeEvaluator evaluator) throws IncorrectOperationException {
                                        final PsiMethodReferenceExpression methodReferenceExpression = (PsiMethodReferenceExpression) expression;
                                        final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression();
                                        if (qualifierExpression != null) {
                                            return (PsiExpression) expression.replace(qualifierExpression);
                                        } else {
                                            return expression;
                                        }
                                    }
                                };
                            }
                        }
                        if (context instanceof PsiReferenceExpression && parent instanceof PsiMethodCallExpression) {
                            final JavaResolveResult resolveResult = ((PsiReferenceExpression) context).advancedResolve(false);
                            final PsiSubstitutor aSubst;
                            final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression) parent).getMethodExpression();
                            final PsiExpression qualifier = methodExpression.getQualifierExpression();
                            final PsiClass substitutionClass = method.getContainingClass();
                            if (qualifier != null) {
                                final PsiType evaluatedQualifierType = labeler.getTypeEvaluator().evaluateType(qualifier);
                                if (evaluatedQualifierType instanceof PsiClassType) {
                                    aSubst = ((PsiClassType) evaluatedQualifierType).resolveGenerics().getSubstitutor();
                                } else {
                                    aSubst = PsiSubstitutor.EMPTY;
                                }
                            } else {
                                aSubst = TypeConversionUtil.getClassSubstitutor(member.getContainingClass(), substitutionClass, PsiSubstitutor.EMPTY);
                            }
                            final PsiParameter[] originalParams = ((PsiMethod) member).getParameterList().getParameters();
                            final PsiParameter[] migrationParams = replacer.getParameterList().getParameters();
                            final PsiExpression[] actualParams = ((PsiMethodCallExpression) parent).getArgumentList().getExpressions();
                            assert originalParams.length == migrationParams.length;
                            final PsiSubstitutor methodTypeParamsSubstitutor = labeler.getTypeEvaluator().createMethodSubstitution(originalParams, actualParams, method, context, aSubst != null ? aSubst : PsiSubstitutor.EMPTY, true);
                            for (int i = 0; i < originalParams.length; i++) {
                                final PsiType originalType = resolveResult.getSubstitutor().substitute(originalParams[i].getType());
                                PsiType type = migrationParams[i].getType();
                                if (InheritanceUtil.isInheritorOrSelf(targetClass, substitutionClass, true)) {
                                    final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getClassSubstitutor(substitutionClass, targetClass, PsiSubstitutor.EMPTY);
                                    assert (superClassSubstitutor != null);
                                    type = superClassSubstitutor.substitute(type);
                                }
                                final PsiType migrationType = methodTypeParamsSubstitutor.substitute(type);
                                if (!originalType.equals(migrationType) && !areParametersAssignable(migrationType, i, actualParams)) {
                                    if (migrationType instanceof PsiEllipsisType && actualParams.length != migrationParams.length) {
                                        return null;
                                    }
                                    labeler.migrateExpressionType(actualParams[i], migrationType, context, false, true);
                                }
                            }
                        }
                        return isStaticMethodConversion ? new MyStaticMethodConversionDescriptor(targetClass) : new TypeConversionDescriptorBase();
                    }
                }
            } else if (member instanceof PsiField) {
                final PsiClass fieldContainingClass = member.getContainingClass();
                if (InheritanceUtil.isInheritorOrSelf(targetClass, fieldContainingClass, true)) {
                    return new TypeConversionDescriptorBase();
                }
            }
        }
    }
    return null;
}
Also used : NotNull(org.jetbrains.annotations.NotNull) TypeConversionDescriptorBase(com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase) TypeEvaluator(com.intellij.refactoring.typeMigration.TypeEvaluator)

Example 2 with TypeConversionDescriptorBase

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

the class EnumTypeConversionRule method findConversion.

@Override
public TypeConversionDescriptorBase findConversion(PsiType from, PsiType to, PsiMember member, PsiExpression context, TypeMigrationLabeler labeler) {
    final PsiMethodCallExpression callExpression = PsiTreeUtil.getParentOfType(context, PsiMethodCallExpression.class, false);
    if (callExpression != null) {
        final PsiMethod resolved = callExpression.resolveMethod();
        if (resolved != null) {
            final SearchScope searchScope = labeler.getRules().getSearchScope();
            if (!PsiSearchScopeUtil.isInScope(searchScope, resolved)) {
                return null;
            }
        }
    }
    final PsiField field = PsiTreeUtil.getParentOfType(context, PsiField.class);
    if (field != null && !myEnumConstants.contains(field) && field.hasModifierProperty(PsiModifier.STATIC) && field.hasModifierProperty(PsiModifier.FINAL) && field.hasInitializer()) {
        return null;
    }
    final PsiClass toClass = PsiUtil.resolveClassInType(to);
    if (toClass != null && toClass.isEnum()) {
        final PsiMethod[] constructors = toClass.getConstructors();
        if (constructors.length == 1) {
            final PsiMethod constructor = constructors[0];
            final PsiParameter[] parameters = constructor.getParameterList().getParameters();
            if (parameters.length == 1) {
                if (TypeConversionUtil.isAssignable(parameters[0].getType(), from)) {
                    return new TypeConversionDescriptorBase();
                }
            }
        }
    }
    return null;
}
Also used : TypeConversionDescriptorBase(com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase) SearchScope(com.intellij.psi.search.SearchScope)

Example 3 with TypeConversionDescriptorBase

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

the class VoidConversionRule method findConversion.

@Nullable
@Override
public TypeConversionDescriptorBase findConversion(PsiType from, PsiType to, PsiMember member, PsiExpression context, TypeMigrationLabeler labeler) {
    if (PsiType.VOID.equals(to) && context.getParent() instanceof PsiReturnStatement && !SideEffectChecker.mayHaveSideEffects(context)) {
        return new TypeConversionDescriptorBase() {

            @Override
            public PsiExpression replace(PsiExpression expression, @NotNull TypeEvaluator evaluator) throws IncorrectOperationException {
                final PsiElement parent = expression.getParent();
                final Project project = expression.getProject();
                if (parent instanceof PsiReturnStatement) {
                    final PsiReturnStatement replaced = (PsiReturnStatement) parent.replace(JavaPsiFacade.getElementFactory(project).createStatementFromText("return;", null));
                    if (UnnecessaryReturnInspection.isReturnRedundant(replaced, false, null)) {
                        DeleteUnnecessaryStatementFix.deleteUnnecessaryStatement(replaced);
                    }
                }
                return null;
            }
        };
    }
    return null;
}
Also used : Project(com.intellij.openapi.project.Project) TypeConversionDescriptorBase(com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase) TypeEvaluator(com.intellij.refactoring.typeMigration.TypeEvaluator) NotNull(org.jetbrains.annotations.NotNull) Nullable(org.jetbrains.annotations.Nullable)

Example 4 with TypeConversionDescriptorBase

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

the class GuavaFluentIterableConversionRule method buildCompoundDescriptor.

@Nullable
public static GuavaChainedConversionDescriptor buildCompoundDescriptor(PsiMethodCallExpression expression, PsiType to, TypeMigrationLabeler labeler) {
    List<TypeConversionDescriptorBase> methodDescriptors = new SmartList<>();
    NotNullLazyValue<TypeConversionRule> optionalDescriptor = new NotNullLazyValue<TypeConversionRule>() {

        @NotNull
        @Override
        protected TypeConversionRule compute() {
            for (TypeConversionRule rule : TypeConversionRule.EP_NAME.getExtensions()) {
                if (rule instanceof GuavaOptionalConversionRule) {
                    return rule;
                }
            }
            throw new RuntimeException("GuavaOptionalConversionRule extension is not found");
        }
    };
    PsiMethodCallExpression current = expression;
    while (true) {
        final PsiMethod method = current.resolveMethod();
        if (method == null) {
            break;
        }
        final String methodName = method.getName();
        final PsiClass containingClass = method.getContainingClass();
        if (containingClass == null) {
            break;
        }
        TypeConversionDescriptorBase descriptor = null;
        if (FLUENT_ITERABLE.equals(containingClass.getQualifiedName())) {
            descriptor = getOneMethodDescriptor(methodName, method, current.getType(), null, current);
            if (descriptor == null) {
                return null;
            }
        } else if (GuavaOptionalConversionRule.GUAVA_OPTIONAL.equals(containingClass.getQualifiedName())) {
            descriptor = optionalDescriptor.getValue().findConversion(null, null, method, current.getMethodExpression(), labeler);
            if (descriptor == null) {
                return null;
            }
        }
        if (descriptor == null) {
            addToMigrateChainQualifier(labeler, current);
            break;
        }
        methodDescriptors.add(descriptor);
        final PsiExpression qualifier = current.getMethodExpression().getQualifierExpression();
        if (qualifier instanceof PsiMethodCallExpression) {
            current = (PsiMethodCallExpression) qualifier;
        } else if (method.hasModifierProperty(PsiModifier.STATIC)) {
            if (!CHAIN_HEAD_METHODS.contains(methodName)) {
                return null;
            }
            final PsiClass aClass = method.getContainingClass();
            if (aClass == null || !(FLUENT_ITERABLE.equals(aClass.getQualifiedName()) || GuavaOptionalConversionRule.GUAVA_OPTIONAL.equals(aClass.getQualifiedName()))) {
                return null;
            }
            break;
        } else if (qualifier instanceof PsiReferenceExpression && ((PsiReferenceExpression) qualifier).resolve() instanceof PsiVariable) {
            addToMigrateChainQualifier(labeler, qualifier);
            break;
        } else {
            return null;
        }
    }
    return new GuavaChainedConversionDescriptor(methodDescriptors, to);
}
Also used : TypeConversionRule(com.intellij.refactoring.typeMigration.rules.TypeConversionRule) NotNullLazyValue(com.intellij.openapi.util.NotNullLazyValue) TypeConversionDescriptorBase(com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase) SmartList(com.intellij.util.SmartList) Nullable(org.jetbrains.annotations.Nullable)

Example 5 with TypeConversionDescriptorBase

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

the class GuavaLambdaConversionRule method findConversionForAnonymous.

@Nullable
@Override
protected TypeConversionDescriptorBase findConversionForAnonymous(@NotNull PsiAnonymousClass anonymousClass, GuavaConversionSettings settings) {
    final TypeConversionDescriptorBase conversion = super.findConversionForAnonymous(anonymousClass, settings);
    if (conversion != null) {
        return conversion;
    }
    final PsiClass baseClass = anonymousClass.getBaseClassType().resolve();
    return baseClass != null && myLambda.getClassQName().equals(baseClass.getQualifiedName()) ? new ConvertLambdaClassToJavaClassDescriptor() : null;
}
Also used : TypeConversionDescriptorBase(com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase) Nullable(org.jetbrains.annotations.Nullable)

Aggregations

TypeConversionDescriptorBase (com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase)7 Nullable (org.jetbrains.annotations.Nullable)4 TypeEvaluator (com.intellij.refactoring.typeMigration.TypeEvaluator)3 NotNull (org.jetbrains.annotations.NotNull)2 Project (com.intellij.openapi.project.Project)1 NotNullLazyValue (com.intellij.openapi.util.NotNullLazyValue)1 SearchScope (com.intellij.psi.search.SearchScope)1 TypeConversionDescriptor (com.intellij.refactoring.typeMigration.TypeConversionDescriptor)1 GuavaConversionSettings (com.intellij.refactoring.typeMigration.inspections.GuavaConversionSettings)1 TypeConversionRule (com.intellij.refactoring.typeMigration.rules.TypeConversionRule)1 SmartList (com.intellij.util.SmartList)1