diff --git a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java index 8dd97edddd42..bd794cd7d81d 100644 --- a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java @@ -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 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; } diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index e3545e092504..d83e81247c5f 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -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 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. diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java index d60efc946974..3b149fdbbb0b 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java @@ -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 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 typeParameters) { return mentionsTypeParametersOrUnboundedWildcard(type, typeParameters, false); } - public static Boolean mentionsTypeParametersOrUnboundedWildcard(@Nullable PsiType type, - Set 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 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 typeParameters, + boolean acceptUnboundedWildcard) { if (type == null) return false; return type.accept(new PsiTypeVisitor() { - @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);