simplify API for unchecked calls; javadoc

IDEA-CR-47704

GitOrigin-RevId: 2ba16b203de098f3755e293fba96d88f1a64373b
This commit is contained in:
Anna Kozlova
2019-05-29 23:06:05 +03:00
committed by intellij-monorepo-bot
parent b1831299d4
commit 793c2a6862
3 changed files with 55 additions and 37 deletions
@@ -28,8 +28,9 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.*;
import java.util.function.Supplier;
public class UncheckedWarningLocalInspection extends AbstractBaseJavaLocalInspectionTool {
@@ -520,18 +521,12 @@ public class UncheckedWarningLocalInspection extends AbstractBaseJavaLocalInspec
}
return null;
}
final PsiParameter[] parameters = method.getParameterList().getParameters();
for (final PsiParameter parameter : parameters) {
final PsiType parameterType = parameter.getType();
Set<PsiTypeParameter> typeParameters = new HashSet<>(substitutor.getSubstitutionMap().keySet());
Arrays.stream(method.getTypeParameters()).forEach(typeParameters::remove);
if (PsiTypesUtil.mentionsTypeParametersOrUnboundedWildcard(parameterType, typeParameters, true)) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(method.getProject());
PsiType type = elementFactory.createType(method.getContainingClass(), substitutor);
return JavaErrorMessages.message("generics.unchecked.call.to.member.of.raw.type",
JavaHighlightUtil.formatMethod(method),
JavaHighlightUtil.formatType(type));
}
if (PsiTypesUtil.isUncheckedCall(resolveResult)) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(method.getProject());
PsiType type = elementFactory.createType(method.getContainingClass(), substitutor);
return JavaErrorMessages.message("generics.unchecked.call.to.member.of.raw.type",
JavaHighlightUtil.formatMethod(method),
JavaHighlightUtil.formatType(type));
}
return null;
}
@@ -911,7 +911,8 @@ public class LambdaUtil {
//and the type of the call would be erased => red code may appear
!lambda.hasFormalParameterTypes()) {
PsiExpression expressionFromBody = extractSingleExpressionFromBody(body);
if (expressionFromBody instanceof PsiMethodCallExpression && isUncheckedCall((PsiMethodCallExpression)expressionFromBody)) {
if (expressionFromBody instanceof PsiMethodCallExpression &&
PsiTypesUtil.isUncheckedCall(((PsiMethodCallExpression)expressionFromBody).resolveMethodGenerics())) {
return false;
}
}
@@ -920,21 +921,6 @@ public class LambdaUtil {
return true;
}
private static boolean isUncheckedCall(PsiMethodCallExpression callExpression) {
JavaResolveResult resolveResult = callExpression.resolveMethodGenerics();
if (resolveResult instanceof MethodCandidateInfo) {
PsiSubstitutor substitutor = resolveResult.getSubstitutor();
PsiElement element = resolveResult.getElement();
if (element instanceof PsiMethod && PsiUtil.isRawSubstitutor(((PsiMethod)element), substitutor)) {
PsiMethod method = (PsiMethod)element;
Set<PsiTypeParameter> typeParameters = substitutor.getSubstitutionMap().keySet();
return Arrays.stream(method.getParameterList().getParameters())
.anyMatch(parameter -> PsiTypesUtil.mentionsTypeParametersOrUnboundedWildcard(parameter.getType(), typeParameters, true));
}
}
return false;
}
/**
* Returns false if after suggested replacement of lambda body, containing method call would resolve to something else
* or its return type will change.
@@ -31,6 +31,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -485,22 +486,42 @@ public class PsiTypesUtil {
return null;
}
public static Boolean mentionsTypeParameters(@Nullable PsiType type, Set<PsiTypeParameter> typeParameters) {
/**
* Checks if {@code type} mentions type parameters from the passed {@code Set}
* Implicit type arguments of types based on inner classes of generic outer classes are explicitly checked
*/
public static boolean mentionsTypeParameters(@Nullable PsiType type, Set<PsiTypeParameter> typeParameters) {
return mentionsTypeParametersOrUnboundedWildcard(type, typeParameters, false);
}
public static Boolean mentionsTypeParametersOrUnboundedWildcard(@Nullable PsiType type,
Set<PsiTypeParameter> typeParameters,
boolean acceptUnboundedWildcard) {
/**
* Checks if {@code resolveResult} depicts unchecked method call
*/
public static boolean isUncheckedCall(JavaResolveResult resolveResult) {
final PsiElement element = resolveResult.getElement();
if (element instanceof PsiMethod) {
PsiMethod method = (PsiMethod)element;
PsiSubstitutor substitutor = resolveResult.getSubstitutor();
if (PsiUtil.isRawSubstitutor(method, substitutor)) {
Set<PsiTypeParameter> typeParameters = new HashSet<>(substitutor.getSubstitutionMap().keySet());
Arrays.stream(method.getTypeParameters()).forEach(typeParameters::remove);
return Arrays.stream(method.getParameterList().getParameters())
.anyMatch(parameter -> mentionsTypeParametersOrUnboundedWildcard(parameter.getType(), typeParameters, true));
}
}
return false;
}
private static boolean mentionsTypeParametersOrUnboundedWildcard(@Nullable PsiType type,
Set<PsiTypeParameter> typeParameters,
boolean acceptUnboundedWildcard) {
if (type == null) return false;
return type.accept(new PsiTypeVisitor<Boolean>() {
@NotNull
@Override
public Boolean visitType(PsiType type) {
return false;
}
@Nullable
@Override
public Boolean visitWildcardType(PsiWildcardType wildcardType) {
final PsiType bound = wildcardType.getBound();
@@ -510,7 +531,6 @@ public class PsiTypesUtil {
return acceptUnboundedWildcard;
}
@NotNull
@Override
public Boolean visitClassType(PsiClassType classType) {
PsiClassType.ClassResolveResult result = classType.resolveGenerics();
@@ -525,7 +545,24 @@ public class PsiTypesUtil {
return psiClass instanceof PsiTypeParameter && typeParameters.contains(psiClass);
}
@Nullable
@Override
public Boolean visitIntersectionType(PsiIntersectionType intersectionType) {
for (PsiType conjunct : intersectionType.getConjuncts()) {
if (conjunct.accept(this)) return true;
}
return false;
}
@Override
public Boolean visitMethodReferenceType(PsiMethodReferenceType methodReferenceType) {
return false;
}
@Override
public Boolean visitLambdaExpressionType(PsiLambdaExpressionType lambdaExpressionType) {
return false;
}
@Override
public Boolean visitArrayType(PsiArrayType arrayType) {
return arrayType.getComponentType().accept(this);