Fix NPE in JavaNullabilityChecker when checking equals-calls
This NPE was introduced in ce41b5745a
Prior to the latter change there was a synthetic PSI element for each
equals-related call, thus callOperationNode was not null here.
== are intentionally treated as safe calls, but for nullability checker
it's not relevant, it only should report warnings on real safe-calls
This commit is contained in:
+2
-1
@@ -109,8 +109,9 @@ class JavaNullabilityChecker : AdditionalTypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (safeAccess) {
|
if (safeAccess) {
|
||||||
|
val safeAccessElement = c.call.callOperationNode?.psi ?: return
|
||||||
doIfNotNull(receiverArgument.type, { dataFlowValue }, c) {
|
doIfNotNull(receiverArgument.type, { dataFlowValue }, c) {
|
||||||
c.trace.report(Errors.UNNECESSARY_SAFE_CALL.on(c.call.callOperationNode!!.psi, receiverArgument.type))
|
c.trace.report(Errors.UNNECESSARY_SAFE_CALL.on(safeAccessElement, receiverArgument.type))
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||||
|
// JSR305_GLOBAL_REPORT warn
|
||||||
|
|
||||||
|
// FILE: spr/NonNullApi.java
|
||||||
|
|
||||||
|
package spr;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.meta.TypeQualifierDefault;
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Nonnull
|
||||||
|
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
|
||||||
|
public @interface NonNullApi {
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: A.java
|
||||||
|
|
||||||
|
import spr.*;
|
||||||
|
|
||||||
|
@NonNullApi
|
||||||
|
public class A {
|
||||||
|
public String getBar() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun main(a: A) {
|
||||||
|
if (a.getBar() == "1" && a.hashCode() != 0) return
|
||||||
|
if (a.getBar() != "2" && a.hashCode() != 0) return
|
||||||
|
|
||||||
|
if (<!SENSELESS_COMPARISON!>a.getBar() == null<!> && a.hashCode() != 0) return
|
||||||
|
if (<!SENSELESS_COMPARISON!>a.getBar() != null<!> && a.hashCode() != 0) return
|
||||||
|
|
||||||
|
if (a.bar == "1" && a.hashCode() != 0) return
|
||||||
|
if (a.bar != "2" && a.hashCode() != 0) return
|
||||||
|
|
||||||
|
if (<!SENSELESS_COMPARISON!>a.bar == null<!> && a.hashCode() != 0) return
|
||||||
|
if (<!SENSELESS_COMPARISON!>a.bar != null<!> && a.hashCode() != 0) return
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun main(/*0*/ a: A): kotlin.Unit
|
||||||
|
|
||||||
|
@spr.NonNullApi public open class A {
|
||||||
|
public constructor A()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open fun getBar(): kotlin.String!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
package spr {
|
||||||
|
|
||||||
|
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FILE}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @javax.annotation.Nonnull @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.METHOD, ElementType.PARAMETER}) public final annotation class NonNullApi : kotlin.Annotation {
|
||||||
|
public constructor NonNullApi()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -294,6 +294,12 @@ public class ForeignAnnotationsNoAnnotationInClasspathTestGenerated extends Abst
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("equalsOnNonNull.kt")
|
||||||
|
public void testEqualsOnNonNull() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/equalsOnNonNull.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("fieldsAreNullable.kt")
|
@TestMetadata("fieldsAreNullable.kt")
|
||||||
public void testFieldsAreNullable() throws Exception {
|
public void testFieldsAreNullable() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/fieldsAreNullable.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/fieldsAreNullable.kt");
|
||||||
|
|||||||
+6
@@ -294,6 +294,12 @@ public class ForeignAnnotationsNoAnnotationInClasspathWithFastClassReadingTestGe
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("equalsOnNonNull.kt")
|
||||||
|
public void testEqualsOnNonNull() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/equalsOnNonNull.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("fieldsAreNullable.kt")
|
@TestMetadata("fieldsAreNullable.kt")
|
||||||
public void testFieldsAreNullable() throws Exception {
|
public void testFieldsAreNullable() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/fieldsAreNullable.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/fieldsAreNullable.kt");
|
||||||
|
|||||||
@@ -294,6 +294,12 @@ public class ForeignAnnotationsTestGenerated extends AbstractForeignAnnotationsT
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("equalsOnNonNull.kt")
|
||||||
|
public void testEqualsOnNonNull() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/equalsOnNonNull.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("fieldsAreNullable.kt")
|
@TestMetadata("fieldsAreNullable.kt")
|
||||||
public void testFieldsAreNullable() throws Exception {
|
public void testFieldsAreNullable() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/fieldsAreNullable.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/fieldsAreNullable.kt");
|
||||||
|
|||||||
+6
@@ -294,6 +294,12 @@ public class JavacForeignAnnotationsTestGenerated extends AbstractJavacForeignAn
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("equalsOnNonNull.kt")
|
||||||
|
public void testEqualsOnNonNull() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/equalsOnNonNull.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("fieldsAreNullable.kt")
|
@TestMetadata("fieldsAreNullable.kt")
|
||||||
public void testFieldsAreNullable() throws Exception {
|
public void testFieldsAreNullable() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/fieldsAreNullable.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305/nullabilityWarnings/typeQualifierDefault/fieldsAreNullable.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user