mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-inspections] IDEA-381019 Invalid local variable type inference in JSpecify mode with generic functions
GitOrigin-RevId: 4a99f16a371b9ad909500aadc14031ebcf547149
This commit is contained in:
committed by
intellij-monorepo-bot
parent
bcf0ff8249
commit
581215e7e9
+1
-1
@@ -266,7 +266,7 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
|
||||
}
|
||||
else if (type != null) {
|
||||
PsiElement context = type instanceof PsiClassType classType ? classType.getPsiContext() : annotation;
|
||||
if (context != null) {
|
||||
if (context != null && !(PsiUtil.isJavaToken(context, JavaTokenType.VAR_KEYWORD))) {
|
||||
checkRedundantInContainerScope(annotation, manager.findDefaultTypeUseNullability(context), nullability);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,6 +255,7 @@ public abstract class PsiClassType extends PsiType implements JvmReferenceType {
|
||||
|
||||
/**
|
||||
* If class-type is created from the explicit reference in the code returns that reference.
|
||||
* If type is created from `var` keyword, return this keyword
|
||||
* @return reference which the type is created from. Returns null if not applicable.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
|
||||
@@ -71,7 +71,8 @@ public final class JavaTypeNullabilityUtil {
|
||||
|
||||
private static boolean isLocal(PsiClassType classType) {
|
||||
PsiElement context = classType.getPsiContext();
|
||||
return context instanceof PsiJavaCodeReferenceElement &&
|
||||
//PsiKeyword is used for `var` case
|
||||
return (context instanceof PsiJavaCodeReferenceElement || PsiUtil.isJavaToken(context, JavaTokenType.VAR_KEYWORD)) &&
|
||||
context.getParent() instanceof PsiTypeElement &&
|
||||
context.getParent().getParent() instanceof PsiLocalVariable;
|
||||
}
|
||||
|
||||
@@ -89,6 +89,15 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
|
||||
else if (PsiUtil.isJavaToken(child, JavaTokenType.VAR_KEYWORD)) {
|
||||
assert type == null : this;
|
||||
type = inferVarType(parent);
|
||||
if (type instanceof PsiClassType) {
|
||||
PsiClassType psiClassType = (PsiClassType)type;
|
||||
PsiClassType.ClassResolveResult result = psiClassType.resolveGenerics();
|
||||
PsiClass element = result.getElement();
|
||||
if (element != null) {
|
||||
type = new PsiImmediateClassType(element, result.getSubstitutor(), psiClassType.getLanguageLevel(),
|
||||
psiClassType.getAnnotationProvider(), child);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (child instanceof PsiJavaCodeReferenceElement) {
|
||||
assert type == null : this;
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@NullMarked
|
||||
class Scratch {
|
||||
void exact(ExactFactory factory) {
|
||||
var created = factory.create();
|
||||
System.out.println("Created: " + created);
|
||||
System.out.println("Created: " + created.<warning descr="Method invocation 'hashCode' may produce 'NullPointerException'">hashCode</warning>());
|
||||
}
|
||||
|
||||
<T> void exact(GenericFactory<T> factory) {
|
||||
var created = factory.create();
|
||||
System.out.println("Created: " + created);
|
||||
System.out.println("Created: " + created.<warning descr="Method invocation 'hashCode' may produce 'NullPointerException'">hashCode</warning>());
|
||||
}
|
||||
|
||||
<T> void exact(GenericFactoryList<T> factory) {
|
||||
for (var o : factory.createList()) {
|
||||
if (o.<warning descr="Method invocation 'hashCode' may produce 'NullPointerException'">hashCode</warning>() == 1) {
|
||||
System.out.println("null");
|
||||
}
|
||||
System.out.println("Created: " + o);
|
||||
}
|
||||
}
|
||||
|
||||
<T> void polyNullNotNull(PolyNullGenericFactory<T> factory) {
|
||||
var created = factory.create();
|
||||
System.out.println("Created: " + created);
|
||||
System.out.println("Created: " + created.hashCode());
|
||||
}
|
||||
|
||||
<T extends @Nullable Object> void polyNullNullable(PolyNullGenericFactory<T> factory) {
|
||||
var created = factory.create();
|
||||
System.out.println("Created: " + created);
|
||||
System.out.println("Created: " + created.<warning descr="Method invocation 'hashCode' may produce 'NullPointerException'">hashCode</warning>());
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ExactFactory {
|
||||
@Nullable String create();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface GenericFactory<T> {
|
||||
@Nullable T create();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface GenericFactoryList<T> {
|
||||
List<@Nullable T> createList();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface PolyNullGenericFactory<T extends @Nullable Object> {
|
||||
T create();
|
||||
}
|
||||
}
|
||||
@@ -163,6 +163,12 @@ public class DataFlowInspection21Test extends DataFlowInspectionTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testJSpecifyLocalWithGenericsWithVar() {
|
||||
addJSpecifyNullMarked(myFixture);
|
||||
setupTypeUseAnnotations("org.jspecify.annotations", myFixture);
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testJSpecifyCallExplicitTypeParameters() {
|
||||
addJSpecifyNullMarked(myFixture);
|
||||
setupTypeUseAnnotations("org.jspecify.annotations", myFixture);
|
||||
|
||||
Reference in New Issue
Block a user