diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java
index 9b944910847e..8c1777873ec2 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java
@@ -17,12 +17,12 @@ package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.NullableNotNullManager;
+import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
import com.intellij.codeInspection.dataFlow.instructions.Instruction;
import com.intellij.codeInspection.dataFlow.instructions.MethodCallInstruction;
import com.intellij.codeInspection.dataFlow.instructions.ReturnInstruction;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.util.Ref;
-import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
@@ -93,15 +93,28 @@ public class DfaPsiUtil {
Nullness fromType = getTypeNullability(resultType);
if (fromType != Nullness.UNKNOWN) return fromType;
- if (PsiJavaPatterns.psiParameter().withParents(PsiParameterList.class, PsiLambdaExpression.class).accepts(owner)) {
- PsiLambdaExpression lambda = (PsiLambdaExpression)owner.getParent().getParent();
- int index = lambda.getParameterList().getParameterIndex((PsiParameter)owner);
- return getFunctionalParameterNullability(lambda, index);
+ if (owner instanceof PsiParameter) {
+ return inferParameterNullability((PsiParameter)owner);
}
return Nullness.UNKNOWN;
}
+ @NotNull
+ public static Nullness inferParameterNullability(@NotNull PsiParameter parameter) {
+ PsiElement parent = parameter.getParent();
+ if (parent instanceof PsiParameterList && parent.getParent() instanceof PsiLambdaExpression) {
+ return getFunctionalParameterNullability((PsiLambdaExpression)parent.getParent(), ((PsiParameterList)parent).getParameterIndex(parameter));
+ }
+ if (parent instanceof PsiForeachStatement) {
+ PsiExpression iteratedValue = ((PsiForeachStatement)parent).getIteratedValue();
+ if (iteratedValue != null) {
+ return getTypeNullability(JavaGenericsUtil.getCollectionItemType(iteratedValue));
+ }
+ }
+ return Nullness.UNKNOWN;
+ }
+
@NotNull
public static Nullness getTypeNullability(@Nullable PsiType type) {
if (type == null) return Nullness.UNKNOWN;
@@ -142,7 +155,7 @@ public class DfaPsiUtil {
if(nullness != Nullness.UNKNOWN) {
return nullness;
}
- PsiClassType type = ObjectUtils.tryCast(function.getFunctionalInterfaceType(), PsiClassType.class);
+ PsiClassType type = ObjectUtils.tryCast(LambdaUtil.getFunctionalInterfaceType(function, true), PsiClassType.class);
PsiMethod sam = LambdaUtil.getFunctionalInterfaceMethod(type);
if (sam != null && index < sam.getParameterList().getParametersCount()) {
PsiParameter parameter = sam.getParameterList().getParameters()[index];
@@ -151,7 +164,7 @@ public class DfaPsiUtil {
return nullness;
}
PsiType parameterType = type.resolveGenerics().getSubstitutor().substitute(parameter.getType());
- return getTypeNullability(parameterType);
+ return getTypeNullability(GenericsUtil.eliminateWildcards(parameterType, false, true));
}
return Nullness.UNKNOWN;
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java
index 7b6b3328ea00..b0cde632df71 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java
@@ -523,22 +523,24 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo
PsiAnnotation annotation = isDeclaredNotNull == null ? isDeclaredNullable : isDeclaredNotNull;
reportPrimitiveType(holder, annotation, annotation, parameter);
}
- if (parameter.getParent() instanceof PsiForeachStatement) {
- PsiExpression iteratedValue = ((PsiForeachStatement)parameter.getParent()).getIteratedValue();
- Nullness itemTypeNullability = DfaPsiUtil.getTypeNullability(iteratedValue == null ? null : JavaGenericsUtil.getCollectionItemType(iteratedValue));
- if (isDeclaredNotNull != null && itemTypeNullability == Nullness.NULLABLE) {
- holder.registerProblem(isDeclaredNotNull, "Loop parameter can be null",
- new RemoveAnnotationQuickFix(isDeclaredNotNull, null));
- }
- else if (isDeclaredNullable != null && itemTypeNullability == Nullness.NOT_NULL) {
- holder.registerProblem(isDeclaredNullable, "Loop parameter is always not-null",
- new RemoveAnnotationQuickFix(isDeclaredNullable, null));
- }
+ if (parameter instanceof PsiParameter) {
+ checkLoopParameterNullability(holder, isDeclaredNotNull, isDeclaredNullable, DfaPsiUtil.inferParameterNullability((PsiParameter)parameter));
}
return new Annotated(isDeclaredNotNull != null,isDeclaredNullable != null);
}
+ private static void checkLoopParameterNullability(ProblemsHolder holder, @Nullable PsiAnnotation notNull, @Nullable PsiAnnotation nullable, Nullness expectedNullability) {
+ if (notNull != null && expectedNullability == Nullness.NULLABLE) {
+ holder.registerProblem(notNull, "Parameter can be null",
+ new RemoveAnnotationQuickFix(notNull, null));
+ }
+ else if (nullable != null && expectedNullability == Nullness.NOT_NULL) {
+ holder.registerProblem(nullable, "Parameter is always not-null",
+ new RemoveAnnotationQuickFix(nullable, null));
+ }
+ }
+
private static void reportPrimitiveType(final ProblemsHolder holder, final PsiElement psiElement, final PsiAnnotation annotation,
final PsiModifierListOwner listOwner) {
holder.registerProblem(psiElement.isPhysical() ? psiElement : listOwner.getNavigationElement(),
diff --git a/java/java-tests/testData/inspection/nullableProblems/ForeachParameterNullability.java b/java/java-tests/testData/inspection/nullableProblems/ForeachParameterNullability.java
index 5d4268a5c4d3..874b0ab2ac14 100644
--- a/java/java-tests/testData/inspection/nullableProblems/ForeachParameterNullability.java
+++ b/java/java-tests/testData/inspection/nullableProblems/ForeachParameterNullability.java
@@ -11,11 +11,13 @@ class JC {
}
void usage() {
- for (@NotNull Object o : getNullableStuff()) {
+ for (@NotNull Object o : getNullableStuff()) {
System.out.println(o.getClass());
}
- for (@Nullable Object o : getNotNullStuff()) {
+ for (@Nullable Object o : getNotNullStuff()) {
System.out.println(o.getClass());
}
+ getNullableStuff().forEach((@NotNull Object s) -> System.out.println(s.hashCode()));
+ getNotNullStuff().forEach((@Nullable Object s) -> System.out.println(s.hashCode()));
}
}
\ No newline at end of file