[FIR] Implement UNNECESSARY_NOT_NULL_ASSERTION checker for java warning level types
This commit is contained in:
committed by
Space Team
parent
d6bd31b313
commit
7fb5cbd1f8
+5
@@ -77,4 +77,9 @@ object JvmExpressionCheckers : ExpressionCheckers() {
|
||||
get() = setOf(
|
||||
FirJavaUnnecessarySafeCallChecker,
|
||||
)
|
||||
|
||||
override val checkNotNullCallCheckers: Set<FirCheckNotNullCallChecker>
|
||||
get() = setOf(
|
||||
FirJavaUnnecessaryNotNullChecker,
|
||||
)
|
||||
}
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirCheckNotNullCallChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall
|
||||
import org.jetbrains.kotlin.fir.expressions.arguments
|
||||
import org.jetbrains.kotlin.fir.java.enhancement.EnhancedForWarningConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.types.canBeNull
|
||||
import org.jetbrains.kotlin.fir.types.resolvedType
|
||||
import org.jetbrains.kotlin.fir.types.typeContext
|
||||
|
||||
object FirJavaUnnecessaryNotNullChecker: FirCheckNotNullCallChecker() {
|
||||
override fun check(expression: FirCheckNotNullCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val argument = expression.arguments.singleOrNull() ?: return
|
||||
val argumentType = EnhancedForWarningConeSubstitutor(context.session.typeContext)
|
||||
.substituteOrNull(argument.resolvedType)
|
||||
?.fullyExpandedType(context.session) ?: return
|
||||
|
||||
if (!argumentType.canBeNull(context.session) && context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) {
|
||||
reporter.reportOn(expression.source, FirErrors.UNNECESSARY_NOT_NULL_ASSERTION, argumentType, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -30,7 +30,7 @@ fun main(a: A<String>, a1: A<String?>) {
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "")<!>.length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.field<!>.length
|
||||
@@ -44,9 +44,9 @@ fun main(a: A<String>, a1: A<String?>) {
|
||||
|
||||
a.baz2("").length
|
||||
a.baz2("")<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.baz2("")!!.length
|
||||
a.baz2("")<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.baz2(null).length
|
||||
a.baz2(null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.baz2(null)!!.length
|
||||
a.baz2(null)<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
}
|
||||
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: warn
|
||||
|
||||
// FILE: MyNullable.java
|
||||
import javax.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.annotation.meta.TypeQualifierNickname;
|
||||
import javax.annotation.meta.When;
|
||||
|
||||
@Documented
|
||||
@TypeQualifierNickname
|
||||
@Nonnull(when = When.MAYBE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyNullable {
|
||||
|
||||
}
|
||||
|
||||
// FILE: MyCheckForNull.java
|
||||
import javax.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.annotation.meta.TypeQualifierNickname;
|
||||
import javax.annotation.meta.When;
|
||||
|
||||
@Documented
|
||||
@TypeQualifierNickname
|
||||
@CheckForNull
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyCheckForNull {
|
||||
|
||||
}
|
||||
|
||||
// FILE: MyNonnull.java
|
||||
import javax.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.annotation.meta.TypeQualifierNickname;
|
||||
import javax.annotation.meta.When;
|
||||
|
||||
@Documented
|
||||
@TypeQualifierNickname
|
||||
@Nonnull(when = When.ALWAYS)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyNonnull {
|
||||
|
||||
}
|
||||
|
||||
// FILE: A.java
|
||||
import javax.annotation.*;
|
||||
|
||||
public class A {
|
||||
@MyNullable public String field = null;
|
||||
|
||||
@MyNullable
|
||||
public String foo(@MyNonnull String x, @MyNullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyNonnull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyCheckForNull
|
||||
public String baz(@MyNonnull String x, @MyCheckForNull CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: A) {
|
||||
a.foo("", null)?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo("", null)<!>.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "")<!>.length
|
||||
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.baz("", null)<!>.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.baz(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "")<!>.length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
|
||||
a.field?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.field<!>.length
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: warn
|
||||
|
||||
|
||||
-181
@@ -1,181 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: warn
|
||||
|
||||
// FILE: NonNullApi.java
|
||||
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;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Nonnull
|
||||
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
|
||||
public @interface NonNullApi {
|
||||
}
|
||||
|
||||
// FILE: NullableApi.java
|
||||
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.CheckForNull;
|
||||
import javax.annotation.meta.TypeQualifierDefault;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@CheckForNull
|
||||
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
|
||||
public @interface NullableApi {
|
||||
}
|
||||
|
||||
// FILE: FieldsAreNullable.java
|
||||
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.CheckForNull;
|
||||
import javax.annotation.meta.TypeQualifierDefault;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@CheckForNull
|
||||
@TypeQualifierDefault({ElementType.FIELD})
|
||||
public @interface FieldsAreNullable {
|
||||
}
|
||||
|
||||
// FILE: A.java
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@NonNullApi
|
||||
public class A {
|
||||
public String field = null;
|
||||
|
||||
public String foo(String x, @CheckForNull CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NullableApi
|
||||
public String foobar(String x, @Nonnull CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public java.util.List<String> baz() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NullableApi
|
||||
public class B {
|
||||
public String field = null;
|
||||
|
||||
public String foo(String x, @Nonnull CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NonNullApi
|
||||
public String foobar(String x, @Nullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public java.util.List<String> baz() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@FieldsAreNullable
|
||||
public class C {
|
||||
public String field = null;
|
||||
|
||||
public String foo(String x, @Nullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NullableApi
|
||||
public String foobar(String x, @Nullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public java.util.List<String> baz() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: A, b: A.B, c: A.C) {
|
||||
a.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.foo("", null).length
|
||||
a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "").length
|
||||
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foobar(null, "")<!>.length
|
||||
a.foobar("", <!NULL_FOR_NONNULL_TYPE!>null<!>)?.length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
|
||||
a.field<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.field.length
|
||||
|
||||
a.baz()<!UNSAFE_CALL!>.<!>get(0)
|
||||
a.baz()!!.get(0).get(0)
|
||||
a.baz()!!.get(0)?.get(0)
|
||||
|
||||
// b
|
||||
b.foo("", <!NULL_FOR_NONNULL_TYPE!>null<!>)?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>b.foo("", <!NULL_FOR_NONNULL_TYPE!>null<!>)<!>.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>b.foo(null, "")<!>.length
|
||||
|
||||
b.foobar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "").length
|
||||
b.foobar("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>b.bar()<!>.length
|
||||
b.bar()!!.length
|
||||
|
||||
b.field?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>b.field<!>.length
|
||||
|
||||
b.baz()<!UNSAFE_CALL!>.<!>get(0)
|
||||
b.baz()!!.get(0).get(0)
|
||||
b.baz()!!.get(0)?.get(0)
|
||||
|
||||
// c
|
||||
c.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
c.foo("", null).length
|
||||
c.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "").length
|
||||
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>c.foobar(null, "")<!>.length
|
||||
c.foobar("", null)?.length
|
||||
|
||||
c.bar().length
|
||||
c.bar()!!.length
|
||||
|
||||
c.field?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>c.field<!>.length
|
||||
|
||||
c.baz()<!UNSAFE_CALL!>.<!>get(0)
|
||||
c.baz()!!.get(0).get(0)
|
||||
c.baz()!!.get(0)?.get(0)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: warn
|
||||
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ fun main(a: A) {
|
||||
a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "").length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
a.field.length
|
||||
|
||||
-84
@@ -1,84 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: warn
|
||||
|
||||
// FILE: spr/Nullable.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.TypeQualifierNickname;
|
||||
import javax.annotation.meta.When;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Nonnull(when = When.MAYBE)
|
||||
@TypeQualifierNickname
|
||||
public @interface Nullable {
|
||||
}
|
||||
|
||||
// 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.PACKAGE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Nonnull
|
||||
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
|
||||
public @interface NonNullApi {
|
||||
}
|
||||
|
||||
// FILE: test/package-info.java
|
||||
@spr.NonNullApi()
|
||||
package test;
|
||||
|
||||
// FILE: test/A.java
|
||||
package test;
|
||||
|
||||
import spr.*;
|
||||
|
||||
public class A {
|
||||
public String field = null;
|
||||
|
||||
public String foo(String x, @Nullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public java.util.List<String> baz() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: test.A) {
|
||||
a.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.foo("", null).length
|
||||
a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "").length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
|
||||
a.field?.length
|
||||
a.field.length
|
||||
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.baz()<!>.get(0)
|
||||
a.baz()!!.get(0).get(0)
|
||||
a.baz()!!.get(0)?.get(0)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: warn
|
||||
|
||||
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: ignore
|
||||
// JSR305_MIGRATION_REPORT: strict
|
||||
// JSR305_SPECIAL_REPORT: MyNonnull:warn
|
||||
|
||||
// FILE: A.java
|
||||
import javax.annotation.*;
|
||||
|
||||
public class A {
|
||||
@MyMigrationNullable public String field = null;
|
||||
|
||||
@MyMigrationNullable
|
||||
public String foo(@MyMigrationNonnull String x, CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyMigrationNonnull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyNullable public String field2 = null;
|
||||
@MyNullable
|
||||
public String foo2(@MyNonnull String x, CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyNonnull
|
||||
public String bar2() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: A) {
|
||||
a.foo("", null)?.length
|
||||
a.foo("", null)<!UNSAFE_CALL!>.<!>length
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
a.field<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a.foo2("", null)?.length
|
||||
a.foo2("", null).length
|
||||
a.foo2(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "").length
|
||||
|
||||
a.bar2().length
|
||||
a.bar2()!!.length
|
||||
|
||||
a.field2?.length
|
||||
a.field2.length
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: ignore
|
||||
// JSR305_MIGRATION_REPORT: strict
|
||||
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: warn
|
||||
// JSR305_MIGRATION_REPORT: ignore
|
||||
// JSR305_SPECIAL_REPORT: MyNullable:strict, MyMigrationNonnull:strict
|
||||
|
||||
// FILE: A.java
|
||||
import javax.annotation.*;
|
||||
|
||||
public class A {
|
||||
@MyMigrationNullable public String field = null;
|
||||
|
||||
@MyMigrationNullable
|
||||
public String foo(@MyMigrationNonnull String x, CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyMigrationNonnull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyNullable public String field2 = null;
|
||||
@MyNullable
|
||||
public String foo2(@MyNonnull String x, CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyNonnull
|
||||
public String bar2() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: A) {
|
||||
a.foo("", null)?.length
|
||||
a.foo("", null).length
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
a.field.length
|
||||
|
||||
a.foo2("", null)?.length
|
||||
a.foo2("", null)<!UNSAFE_CALL!>.<!>length
|
||||
a.foo2(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "")<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a.bar2().length
|
||||
a.bar2()!!.length
|
||||
|
||||
a.field2?.length
|
||||
a.field2<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: warn
|
||||
// JSR305_MIGRATION_REPORT: ignore
|
||||
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: strict
|
||||
// JSR305_MIGRATION_REPORT: warn
|
||||
// JSR305_SPECIAL_REPORT: MyNullable:ignore, MyMigrationNullable:strict
|
||||
|
||||
// FILE: A.java
|
||||
import javax.annotation.*;
|
||||
|
||||
public class A {
|
||||
@MyMigrationNullable public String field = null;
|
||||
|
||||
@MyMigrationNullable
|
||||
public String foo(@MyMigrationNonnull String x, CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyMigrationNonnull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyNullable public String field2 = null;
|
||||
@MyNullable
|
||||
public String foo2(@MyNonnull String x, CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyNonnull
|
||||
public String bar2() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: A) {
|
||||
a.foo("", null)?.length
|
||||
a.foo("", null)<!UNSAFE_CALL!>.<!>length
|
||||
a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "")<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
|
||||
a.field?.length
|
||||
a.field<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a.foo2("", null)?.length
|
||||
a.foo2("", null).length
|
||||
a.foo2(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a.bar2().length
|
||||
a.bar2()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field2?.length
|
||||
a.field2.length
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: strict
|
||||
// JSR305_MIGRATION_REPORT: warn
|
||||
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: ignore
|
||||
// JSR305_MIGRATION_REPORT: warn
|
||||
// JSR305_SPECIAL_REPORT: MyNonnull:strict
|
||||
|
||||
// FILE: A.java
|
||||
import javax.annotation.*;
|
||||
|
||||
public class A {
|
||||
@MyMigrationNullable public String field = null;
|
||||
|
||||
@MyMigrationNullable
|
||||
public String foo(@MyMigrationNonnull String x, CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyMigrationNonnull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyNullable public String field2 = null;
|
||||
@MyNullable
|
||||
public String foo2(@MyNonnull String x, CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@MyNonnull
|
||||
public String bar2() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: A) {
|
||||
a.foo("", null)?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo("", null)<!>.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "")<!>.length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
|
||||
a.field?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.field<!>.length
|
||||
|
||||
a.foo2("", null)?.length
|
||||
a.foo2("", null).length
|
||||
a.foo2(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a.bar2().length
|
||||
a.bar2()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field2?.length
|
||||
a.field2.length
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: ignore
|
||||
// JSR305_MIGRATION_REPORT: warn
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
// NULLABILITY_ANNOTATIONS: @io.reactivex.annotations:strict, @org.eclipse.jdt.annotation:warn, @androidx.annotation:strict, @com.android.annotations:ignore
|
||||
|
||||
// FILE: A1.java
|
||||
import io.reactivex.annotations.*;
|
||||
|
||||
public class A1<T> {
|
||||
@Nullable public String field = null;
|
||||
|
||||
@Nullable
|
||||
public String foo(@NonNull String x, @Nullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T baz(@NonNull T x) { return x; }
|
||||
}
|
||||
|
||||
// FILE: A2.java
|
||||
import org.eclipse.jdt.annotation.*;
|
||||
|
||||
public class A2<T> {
|
||||
@Nullable public String field = null;
|
||||
|
||||
@Nullable
|
||||
public String foo(@NonNull String x, @Nullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T baz(@NonNull T x) { return x; }
|
||||
}
|
||||
|
||||
// FILE: A3.java
|
||||
import androidx.annotation.*;
|
||||
|
||||
public class A3<T> {
|
||||
@Nullable public String field = null;
|
||||
|
||||
@Nullable
|
||||
public String foo(@NonNull String x, @Nullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T baz(@NonNull T x) { return x; }
|
||||
}
|
||||
|
||||
// FILE: A4.java
|
||||
import com.android.annotations.*;
|
||||
|
||||
public class A4<T> {
|
||||
@Nullable public String field = null;
|
||||
|
||||
@Nullable
|
||||
public String foo(@NonNull String x, @Nullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T baz(@NonNull T x) { return x; }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main1(a: A1<String>, a1: A1<String?>) {
|
||||
a.foo("", null)?.length
|
||||
a.foo("", null)<!UNSAFE_CALL!>.<!>length
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
a.field<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a.baz("")<!UNSAFE_CALL!>.<!>length
|
||||
a.baz("")?.length
|
||||
a.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>)<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a1.baz("")!!.length
|
||||
a1.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>)!!.length
|
||||
}
|
||||
|
||||
fun main2(a: A2<String>, a1: A2<String?>) {
|
||||
a.foo("", null)?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo("", null)<!>.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "")<!>.length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
|
||||
a.field?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.field<!>.length
|
||||
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.baz("")<!>.length
|
||||
a.baz("")?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.baz(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)<!>.length
|
||||
|
||||
a1.baz("")!!.length
|
||||
a1.baz(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)!!.length
|
||||
}
|
||||
|
||||
fun main3(a: A3<String>, a1: A3<String?>) {
|
||||
a.foo("", null)?.length
|
||||
a.foo("", null)<!UNSAFE_CALL!>.<!>length
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
a.field<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a.baz("")<!UNSAFE_CALL!>.<!>length
|
||||
a.baz("")?.length
|
||||
a.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>)<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a1.baz("")!!.length
|
||||
a1.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>)!!.length
|
||||
}
|
||||
|
||||
fun main4(a: A4<String>, a1: A4<String?>) {
|
||||
a.foo("", null)?.length
|
||||
a.foo("", null).length
|
||||
a.foo(null, "").length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
|
||||
a.field?.length
|
||||
a.field.length
|
||||
|
||||
a.baz("").length
|
||||
a.baz("")?.length
|
||||
a.baz(null).length
|
||||
|
||||
a1.baz("")!!.length
|
||||
a1.baz(null)!!.length
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// NULLABILITY_ANNOTATIONS: @io.reactivex.annotations:strict, @org.eclipse.jdt.annotation:warn, @androidx.annotation:strict, @com.android.annotations:ignore
|
||||
|
||||
// FILE: A1.java
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
// FILE: A.java
|
||||
|
||||
import io.reactivex.rxjava3.annotations.*;
|
||||
|
||||
public class A<T> {
|
||||
@Nullable public String field = null;
|
||||
|
||||
@Nullable
|
||||
public String foo(@NonNull String x, @Nullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T baz(@NonNull T x) { return x; }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(a: A<String>, a1: A<String?>) {
|
||||
a.foo("", null)?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo("", null)<!>.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "")<!>.length
|
||||
a.foo("", null)!!.length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
|
||||
a.field?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.field<!>.length
|
||||
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.baz("")<!>.length
|
||||
a.baz("")?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.baz(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)<!>.length
|
||||
|
||||
a1.baz("")!!.length
|
||||
a1.baz(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)!!.length
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// FILE: A.java
|
||||
|
||||
import io.reactivex.rxjava3.annotations.*;
|
||||
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
// NULLABILITY_ANNOTATIONS: @io.reactivex.rxjava3.annotations:warn
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
import io.reactivex.rxjava3.annotations.*;
|
||||
|
||||
public class A<T> {
|
||||
@Nullable public String field = null;
|
||||
|
||||
@Nullable
|
||||
public String foo(@NonNull String x, @Nullable CharSequence y) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String bar() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T baz(@NonNull T x) { return x; }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(a: A<String>, a1: A<String?>) {
|
||||
a.foo("", null)?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo("", null)<!>.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, "")<!>.length
|
||||
|
||||
a.bar().length
|
||||
a.bar()!!.length
|
||||
|
||||
a.field?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.field<!>.length
|
||||
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.baz("")<!>.length
|
||||
a.baz("")?.length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>a.baz(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)<!>.length
|
||||
|
||||
a1.baz("")!!.length
|
||||
a1.baz(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)!!.length
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// NULLABILITY_ANNOTATIONS: @io.reactivex.rxjava3.annotations:warn
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
Reference in New Issue
Block a user