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;
}
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;
}
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;
}
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);
}
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;
}
Aggregations