void (@NotNull HighlightInfo.Builder info, @NotNull TextRange textRange, @NotNull PsiMethodCallExpression call, @NotNull PsiMethod method, @NotNull PsiType expectedTypeByParent, @NotNull PsiType actualType) { JavaResolveResult result = call.resolveMethodGenerics(); if (!(result instanceof MethodCandidateInfo)) return; PsiType methodType = method.getReturnType(); Substitution.TypeParameterSubstitution substitution = tryCast(findDesiredSubstitution(expectedTypeByParent, actualType, methodType, 0), Substitution.TypeParameterSubstitution.class); if (substitution == null) return; PsiTypeParameter typeParameter = substitution.myTypeParameter; PsiType expectedTypeValue = substitution.myDesiredType; PsiParameter[] parameters = method.getParameterList().getParameters(); Set<PsiTypeParameter> set = Set.of(typeParameter); if (!PsiTreeUtil.isAncestor(method, typeParameter, true)) { registerPatchQualifierFixes(info, textRange, call, method, typeParameter, expectedTypeValue, parameters, set); return; } PsiParameter parameter = StreamEx.of(parameters).collect(MoreCollectors.onlyOne(p -> PsiTypesUtil.mentionsTypeParameters(p.getType(), set))).orElse(null); PsiSubstitutor substitutor = ((MethodCandidateInfo)result).getSubstitutor(false); PsiSubstitutor desiredSubstitutor = substitutor.put(typeParameter, expectedTypeValue); if (parameter == null) { parameter = findWrongParameter(call, method, desiredSubstitutor, typeParameter); } if (parameter == null) return; PsiExpression arg = PsiUtil.skipParenthesizedExprDown(MethodCallUtils.getArgumentForParameter(call, parameter)); if (arg == null) return; PsiType parameterType = parameter.getType(); if (parameterType instanceof PsiEllipsisType && MethodCallUtils.isVarArgCall(call)) { // Replace vararg only if there's single value if (call.getArgumentList().getExpressionCount() != parameters.length) return; parameterType = ((PsiEllipsisType)parameterType).getComponentType(); } if (parameterType instanceof PsiClassType && ((PsiClassType)parameterType).rawType().equalsToText(CommonClassNames.JAVA_LANG_CLASS) && typeParameter == getSoleTypeParameter(parameterType)) { if (expectedTypeValue instanceof PsiClassType classType && JavaGenericsUtil.isReifiableType(expectedTypeValue)) { ReplaceExpressionAction fix = new ReplaceExpressionAction( arg, classType.rawType().getCanonicalText() + ".class", classType.rawType().getPresentableText() + ".class"); info.registerFix(fix, null, null, null, null); } } PsiType expectedArgType = desiredSubstitutor.substitute(parameterType); if (arg instanceof PsiLambdaExpression && parameterType instanceof PsiClassType) { registerLambdaReturnFixes(info, textRange, (PsiLambdaExpression)arg, (PsiClassType)parameterType, expectedArgType, typeParameter); return; } PsiType actualArgType = PsiPolyExpressionUtil.isPolyExpression(arg) ? substitutor.put(typeParameter, substitution.myActualType).substitute(parameterType) : arg.getType(); registerExpectedTypeFixes(info, textRange, arg, expectedArgType, actualArgType); }