FE: prefer enhancements for errors over enhancements for warnings

This commit is contained in:
pyos
2021-09-07 12:24:00 +02:00
committed by Victor Petukhov
parent 8f699248f1
commit 94402ba488
7 changed files with 24 additions and 54 deletions
@@ -34,7 +34,7 @@ public open class BK : B {
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@org.jspecify.nullness.NullMarked public open class C</*0*/ E : C<E!>!> : SelfType<E> {
@org.jspecify.nullness.NullMarked public open class C</*0*/ E : C<E!>!> : SelfType<E!> {
public constructor C</*0*/ E : C<E!>!>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun foo(/*0*/ t: E!): kotlin.Unit
@@ -1,35 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// JSR305_GLOBAL_REPORT: ignore
// JSR305_MIGRATION_REPORT: ignore
// JSR305_SPECIAL_REPORT: MyNonnull:warn, 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 "";
}
@MyNonnull
@MyMigrationNonnull
public String bar() {
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()!!.length
a.field?.length
a.field.length
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// JSR305_GLOBAL_REPORT: ignore
// JSR305_MIGRATION_REPORT: ignore
@@ -5,9 +5,10 @@ public fun main(/*0*/ a: A): kotlin.Unit
public open class A {
public constructor A()
@MyMigrationNullable public final var field: kotlin.String!
@MyNonnull @MyMigrationNonnull public open fun bar(): kotlin.String!
@MyNonnull @MyMigrationNonnull public open fun bar(): kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@MyMigrationNullable public open fun foo(/*0*/ @MyMigrationNonnull x: kotlin.String, /*1*/ y: kotlin.CharSequence!): kotlin.String!
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -121,17 +121,25 @@ abstract class AbstractAnnotationTypeQualifierResolver<TAnnotation : Any>(
fun extractNullability(
annotations: Iterable<TAnnotation>, forceWarning: TAnnotation.() -> Boolean = { false }
): NullabilityQualifierWithMigrationStatus? =
annotations.firstNotNullOfOrNull { extractNullability(it, forceWarning) }
annotations.fold(null as NullabilityQualifierWithMigrationStatus?) { found, annotation ->
val extracted = extractNullability(annotation, forceWarning)
when {
found == null -> extracted
extracted == null || extracted == found -> found
extracted.isForWarningOnly && !found.isForWarningOnly -> found
!extracted.isForWarningOnly && found.isForWarningOnly -> extracted
else -> return null // inconsistent
}
}
fun extractMutability(annotations: Iterable<TAnnotation>): MutabilityQualifier? {
return annotations.fold(null as MutabilityQualifier?) { found, annotation ->
fun extractMutability(annotations: Iterable<TAnnotation>): MutabilityQualifier? =
annotations.fold(null as MutabilityQualifier?) { found, annotation ->
when (annotation.fqName) {
in READ_ONLY_ANNOTATIONS -> MutabilityQualifier.READ_ONLY
in MUTABLE_ANNOTATIONS -> MutabilityQualifier.MUTABLE
else -> found
else -> return@fold found
}.also { if (found != null && found != it) return null /* inconsistent */ }
}
}
private fun extractDefaultQualifiers(annotation: TAnnotation): JavaDefaultQualifiers? {
resolveQualifierBuiltInDefaultAnnotation(annotation)?.let { return it }
@@ -135,18 +135,13 @@ abstract class AbstractSignatureParts<TAnnotation : Any> {
a: NullabilityQualifierWithMigrationStatus?,
b: NullabilityQualifierWithMigrationStatus?
): NullabilityQualifierWithMigrationStatus? {
if (a == null) return b
if (a == null) return b // null < not null
if (b == null) return a
// TODO: this probably behaves really weirdly when some of those are warnings.
if (a.qualifier == NullabilityQualifier.FORCE_FLEXIBILITY) return b
if (b.qualifier == NullabilityQualifier.FORCE_FLEXIBILITY) return a
if (a.qualifier == NullabilityQualifier.NULLABLE) return b
if (b.qualifier == NullabilityQualifier.NULLABLE) return a
assert(a.qualifier == b.qualifier && a.qualifier == NullabilityQualifier.NOT_NULL) {
"Expected everything is NOT_NULL, but $a and $b are found"
}
return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
if (a.isForWarningOnly && !b.isForWarningOnly) return b // warnings < errors
if (!a.isForWarningOnly && b.isForWarningOnly) return a
if (a.qualifier < b.qualifier) return b // T! < T? < T
if (a.qualifier > b.qualifier) return a
return b // they are equal
}
private val TypeParameterMarker.boundsNullability: NullabilityQualifierWithMigrationStatus?
@@ -6,9 +6,9 @@
package org.jetbrains.kotlin.load.java.typeEnhancement
enum class NullabilityQualifier {
FORCE_FLEXIBILITY,
NULLABLE,
NOT_NULL,
FORCE_FLEXIBILITY
}
enum class MutabilityQualifier {