[FIR] Don't lose error level enhancements in warning-level-enhanced arguments

The error-level enhancement is kept as warning-level and a new
LanguageFeature is introduced to turn the warning into an error.

#KT-63208 Fixed
#KT-63209
This commit is contained in:
Kirill Rakhman
2024-01-05 15:14:29 +01:00
committed by Space Team
parent 9189154cae
commit 371b1eb3d5
22 changed files with 470 additions and 33 deletions
@@ -5091,6 +5091,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
ReceiverNullabilityMismatchBasedOnJavaAnnotationsImpl( ReceiverNullabilityMismatchBasedOnJavaAnnotationsImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b), firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
firDiagnostic.c,
firDiagnostic as KtPsiDiagnostic, firDiagnostic as KtPsiDiagnostic,
token, token,
) )
@@ -5099,6 +5100,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
NullabilityMismatchBasedOnJavaAnnotationsImpl( NullabilityMismatchBasedOnJavaAnnotationsImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b), firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
firDiagnostic.c,
firDiagnostic as KtPsiDiagnostic, firDiagnostic as KtPsiDiagnostic,
token, token,
) )
@@ -3544,12 +3544,14 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = ReceiverNullabilityMismatchBasedOnJavaAnnotations::class override val diagnosticClass get() = ReceiverNullabilityMismatchBasedOnJavaAnnotations::class
val actualType: KtType val actualType: KtType
val expectedType: KtType val expectedType: KtType
val messageSuffix: String
} }
interface NullabilityMismatchBasedOnJavaAnnotations : KtFirDiagnostic<PsiElement> { interface NullabilityMismatchBasedOnJavaAnnotations : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = NullabilityMismatchBasedOnJavaAnnotations::class override val diagnosticClass get() = NullabilityMismatchBasedOnJavaAnnotations::class
val actualType: KtType val actualType: KtType
val expectedType: KtType val expectedType: KtType
val messageSuffix: String
} }
interface UpperBoundCannotBeArray : KtFirDiagnostic<PsiElement> { interface UpperBoundCannotBeArray : KtFirDiagnostic<PsiElement> {
@@ -4274,6 +4274,7 @@ internal class JavaTypeMismatchImpl(
internal class ReceiverNullabilityMismatchBasedOnJavaAnnotationsImpl( internal class ReceiverNullabilityMismatchBasedOnJavaAnnotationsImpl(
override val actualType: KtType, override val actualType: KtType,
override val expectedType: KtType, override val expectedType: KtType,
override val messageSuffix: String,
firDiagnostic: KtPsiDiagnostic, firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken, token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.ReceiverNullabilityMismatchBasedOnJavaAnnotations ) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.ReceiverNullabilityMismatchBasedOnJavaAnnotations
@@ -4281,6 +4282,7 @@ internal class ReceiverNullabilityMismatchBasedOnJavaAnnotationsImpl(
internal class NullabilityMismatchBasedOnJavaAnnotationsImpl( internal class NullabilityMismatchBasedOnJavaAnnotationsImpl(
override val actualType: KtType, override val actualType: KtType,
override val expectedType: KtType, override val expectedType: KtType,
override val messageSuffix: String,
firDiagnostic: KtPsiDiagnostic, firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken, token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.NullabilityMismatchBasedOnJavaAnnotations ) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.NullabilityMismatchBasedOnJavaAnnotations
@@ -68,6 +68,18 @@ public class FirPsiOldFrontendForeignAnnotationsCompiledJavaTestGenerated extend
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt"); runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt");
} }
@Test
@TestMetadata("errorArgumentOfWarningAfter.kt")
public void testErrorArgumentOfWarningAfter() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningAfter.kt");
}
@Test
@TestMetadata("errorArgumentOfWarningBefore.kt")
public void testErrorArgumentOfWarningBefore() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningBefore.kt");
}
@Test @Test
@TestMetadata("findBugsSimple.kt") @TestMetadata("findBugsSimple.kt")
public void testFindBugsSimple() throws Exception { public void testFindBugsSimple() throws Exception {
@@ -68,6 +68,18 @@ public class FirPsiOldFrontendForeignAnnotationsCompiledJavaWithPsiClassReadingT
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt"); runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt");
} }
@Test
@TestMetadata("errorArgumentOfWarningAfter.kt")
public void testErrorArgumentOfWarningAfter() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningAfter.kt");
}
@Test
@TestMetadata("errorArgumentOfWarningBefore.kt")
public void testErrorArgumentOfWarningBefore() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningBefore.kt");
}
@Test @Test
@TestMetadata("findBugsSimple.kt") @TestMetadata("findBugsSimple.kt")
public void testFindBugsSimple() throws Exception { public void testFindBugsSimple() throws Exception {
@@ -68,6 +68,18 @@ public class FirPsiOldFrontendForeignAnnotationsSourceJavaTestGenerated extends
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt"); runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt");
} }
@Test
@TestMetadata("errorArgumentOfWarningAfter.kt")
public void testErrorArgumentOfWarningAfter() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningAfter.kt");
}
@Test
@TestMetadata("errorArgumentOfWarningBefore.kt")
public void testErrorArgumentOfWarningBefore() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningBefore.kt");
}
@Test @Test
@TestMetadata("findBugsSimple.kt") @TestMetadata("findBugsSimple.kt")
public void testFindBugsSimple() throws Exception { public void testFindBugsSimple() throws Exception {
@@ -56,10 +56,12 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
val RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS by warning<PsiElement> { val RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS by warning<PsiElement> {
parameter<ConeKotlinType>("actualType") parameter<ConeKotlinType>("actualType")
parameter<ConeKotlinType>("expectedType") parameter<ConeKotlinType>("expectedType")
parameter<String>("messageSuffix")
} }
val NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS by warning<PsiElement> { val NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS by warning<PsiElement> {
parameter<ConeKotlinType>("actualType") parameter<ConeKotlinType>("actualType")
parameter<ConeKotlinType>("expectedType") parameter<ConeKotlinType>("expectedType")
parameter<String>("messageSuffix")
} }
} }
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0 import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory1 import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory1
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory2 import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory2
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory3
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryForDeprecation0 import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryForDeprecation0
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryForDeprecation2 import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryForDeprecation2
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryForDeprecation4 import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryForDeprecation4
@@ -52,8 +53,8 @@ object FirJvmErrors {
// Types // Types
val JAVA_TYPE_MISMATCH: KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> by error2<KtExpression, ConeKotlinType, ConeKotlinType>() val JAVA_TYPE_MISMATCH: KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> by error2<KtExpression, ConeKotlinType, ConeKotlinType>()
val RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS: KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> by warning2<PsiElement, ConeKotlinType, ConeKotlinType>() val RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS: KtDiagnosticFactory3<ConeKotlinType, ConeKotlinType, String> by warning3<PsiElement, ConeKotlinType, ConeKotlinType, String>()
val NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS: KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> by warning2<PsiElement, ConeKotlinType, ConeKotlinType>() val NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS: KtDiagnosticFactory3<ConeKotlinType, ConeKotlinType, String> by warning3<PsiElement, ConeKotlinType, ConeKotlinType, String>()
// Type parameters // Type parameters
val UPPER_BOUND_CANNOT_BE_ARRAY: KtDiagnosticFactory0 by error0<PsiElement>() val UPPER_BOUND_CANNOT_BE_ARRAY: KtDiagnosticFactory0 by error0<PsiElement>()
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.NAME import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.NAME
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.OPTIONAL_SENTENCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.CONCURRENT_HASH_MAP_CONTAINS_OPERATOR import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.CONCURRENT_HASH_MAP_CONTAINS_OPERATOR
@@ -94,15 +95,17 @@ object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put( map.put(
NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS, NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS,
"Java type mismatch: inferred type is ''{1}'', but ''{0}'' was expected.", "Java type mismatch: inferred type is ''{1}'', but ''{0}'' was expected.{2}",
RENDER_TYPE, RENDER_TYPE,
RENDER_TYPE RENDER_TYPE,
OPTIONAL_SENTENCE,
) )
map.put( map.put(
RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS, RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS,
"Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type ''{0}''.", "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type ''{0}''.{2}",
RENDER_TYPE, RENDER_TYPE,
NOT_RENDERED NOT_RENDERED,
OPTIONAL_SENTENCE,
) )
map.put( map.put(
@@ -5,8 +5,9 @@
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression 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.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory2 import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory3
import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -15,11 +16,11 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
import org.jetbrains.kotlin.fir.java.enhancement.EnhancedForWarningConeSubstitutor import org.jetbrains.kotlin.fir.java.enhancement.EnhancedForWarningConeSubstitutor
import org.jetbrains.kotlin.fir.java.enhancement.isEnhancedTypeForWarningDeprecation
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import java.util.*
// TODO reimplement using AdditionalTypeChecker KT-62864 // TODO reimplement using AdditionalTypeChecker KT-62864
object FirQualifiedAccessJavaNullabilityWarningChecker : FirQualifiedAccessExpressionChecker() { object FirQualifiedAccessJavaNullabilityWarningChecker : FirQualifiedAccessExpressionChecker() {
@@ -142,7 +143,7 @@ internal fun FirExpression.checkExpressionForEnhancedTypeMismatch(
expectedType: ConeKotlinType?, expectedType: ConeKotlinType?,
reporter: DiagnosticReporter, reporter: DiagnosticReporter,
context: CheckerContext, context: CheckerContext,
factory: KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType>, factory: KtDiagnosticFactory3<ConeKotlinType, ConeKotlinType, String>,
) { ) {
if (expectedType == null) return if (expectedType == null) return
val actualType = resolvedType val actualType = resolvedType
@@ -154,7 +155,14 @@ internal fun FirExpression.checkExpressionForEnhancedTypeMismatch(
// Don't report anything if the original types didn't match. // Don't report anything if the original types didn't match.
actualType.isSubtypeOf(context.session.typeContext, expectedType) actualType.isSubtypeOf(context.session.typeContext, expectedType)
) { ) {
reporter.reportOn(source, factory, actualTypeForComparison, expectedTypeForComparison, context) val suffix =
if (actualType.isEnhancedTypeForWarningDeprecation || expectedType.isEnhancedTypeForWarningDeprecation) {
val versionString = LanguageFeature.SupportJavaErrorEnhancementOfArgumentsOfWarningLevelEnhanced.sinceVersion?.versionString
"This will become an error in Kotlin $versionString. See https://youtrack.jetbrains.com/issue/KT-63209"
} else {
""
}
reporter.reportOn(source, factory, actualTypeForComparison, expectedTypeForComparison, suffix, context)
} }
} }
@@ -12,13 +12,14 @@ import kotlin.reflect.KClass
class EnhancedTypeForWarningAttribute( class EnhancedTypeForWarningAttribute(
override val coneType: ConeKotlinType, override val coneType: ConeKotlinType,
val isDeprecation: Boolean,
) : ConeAttributeWithConeType<EnhancedTypeForWarningAttribute>() { ) : ConeAttributeWithConeType<EnhancedTypeForWarningAttribute>() {
override fun union(other: EnhancedTypeForWarningAttribute?): EnhancedTypeForWarningAttribute? = null override fun union(other: EnhancedTypeForWarningAttribute?): EnhancedTypeForWarningAttribute? = null
override fun intersect(other: EnhancedTypeForWarningAttribute?): EnhancedTypeForWarningAttribute? = null override fun intersect(other: EnhancedTypeForWarningAttribute?): EnhancedTypeForWarningAttribute? = null
override fun add(other: EnhancedTypeForWarningAttribute?): EnhancedTypeForWarningAttribute = other ?: this override fun add(other: EnhancedTypeForWarningAttribute?): EnhancedTypeForWarningAttribute = other ?: this
override fun isSubtypeOf(other: EnhancedTypeForWarningAttribute?): Boolean = true override fun isSubtypeOf(other: EnhancedTypeForWarningAttribute?): Boolean = true
override fun toString(): String = "Enhanced for warning(${coneType.renderForDebugging()})" override fun toString(): String = "Enhanced for warning(${coneType.renderForDebugging()})"
override fun copyWith(newType: ConeKotlinType): EnhancedTypeForWarningAttribute = EnhancedTypeForWarningAttribute(newType) override fun copyWith(newType: ConeKotlinType): EnhancedTypeForWarningAttribute = EnhancedTypeForWarningAttribute(newType, isDeprecation)
override val key: KClass<out EnhancedTypeForWarningAttribute> override val key: KClass<out EnhancedTypeForWarningAttribute>
get() = EnhancedTypeForWarningAttribute::class get() = EnhancedTypeForWarningAttribute::class
@@ -36,12 +37,14 @@ class EnhancedTypeForWarningAttribute(
other as EnhancedTypeForWarningAttribute other as EnhancedTypeForWarningAttribute
if (coneType != other.coneType) return false if (coneType != other.coneType) return false
if (isDeprecation != other.isDeprecation) return false
return true return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = coneType.hashCode() var result = coneType.hashCode()
result = 31 * result + isDeprecation.hashCode()
return result return result
} }
} }
@@ -51,6 +54,9 @@ val ConeAttributes.enhancedTypeForWarning: EnhancedTypeForWarningAttribute? by C
val ConeKotlinType.enhancedTypeForWarning: ConeKotlinType? val ConeKotlinType.enhancedTypeForWarning: ConeKotlinType?
get() = attributes.enhancedTypeForWarning?.coneType get() = attributes.enhancedTypeForWarning?.coneType
val ConeKotlinType.isEnhancedTypeForWarningDeprecation: Boolean
get() = attributes.enhancedTypeForWarning?.isDeprecation == true
/** /**
* Substitutor that substitutes types with their [ConeKotlinType.enhancedTypeForWarning] recursively. * Substitutor that substitutes types with their [ConeKotlinType.enhancedTypeForWarning] recursively.
*/ */
@@ -6,7 +6,9 @@
package org.jetbrains.kotlin.fir.java.enhancement package org.jetbrains.kotlin.fir.java.enhancement
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
@@ -15,7 +17,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.utils.addToStdlib.applyIf import org.jetbrains.kotlin.utils.addToStdlib.applyIf
internal fun ConeKotlinType.enhance(session: FirSession, qualifiers: IndexedJavaTypeQualifiers): ConeKotlinType? = internal fun ConeKotlinType.enhance(session: FirSession, qualifiers: IndexedJavaTypeQualifiers): ConeKotlinType? =
enhanceConeKotlinType(session, qualifiers, 0, mutableListOf<Int>().apply { computeSubtreeSizes(this) }) enhanceConeKotlinType(session, qualifiers, 0, mutableListOf<Int>().apply { computeSubtreeSizes(this) }, convertErrorsToWarnings = false)
// The index in the lambda is the position of the type component in a depth-first walk of the tree. // The index in the lambda is the position of the type component in a depth-first walk of the tree.
// Example: A<B<C, D>, E<F>> - 0<1<2, 3>, 4<5>>. For flexible types, some arguments in the lower bound // Example: A<B<C, D>, E<F>> - 0<1<2, 3>, 4<5>>. For flexible types, some arguments in the lower bound
@@ -37,7 +39,8 @@ private fun ConeKotlinType.enhanceConeKotlinType(
session: FirSession, session: FirSession,
qualifiers: IndexedJavaTypeQualifiers, qualifiers: IndexedJavaTypeQualifiers,
index: Int, index: Int,
subtreeSizes: List<Int> subtreeSizes: List<Int>,
convertErrorsToWarnings: Boolean,
): ConeKotlinType? { ): ConeKotlinType? {
return when (this) { return when (this) {
is ConeFlexibleType -> { is ConeFlexibleType -> {
@@ -46,10 +49,12 @@ private fun ConeKotlinType.enhanceConeKotlinType(
// It's not totally correct, but tolerable since we would like to avoid excessive breaking changes and the warnings should be // It's not totally correct, but tolerable since we would like to avoid excessive breaking changes and the warnings should be
// anyway reported. // anyway reported.
val lowerResult = lowerBound.enhanceInflexibleType( val lowerResult = lowerBound.enhanceInflexibleType(
session, TypeComponentPosition.FLEXIBLE_LOWER, qualifiers, index, subtreeSizes session, TypeComponentPosition.FLEXIBLE_LOWER, qualifiers, index, subtreeSizes,
isFromDefinitelyNotNullType = false, convertErrorToWarning = convertErrorsToWarnings,
) )
val upperResult = upperBound.enhanceInflexibleType( val upperResult = upperBound.enhanceInflexibleType(
session, TypeComponentPosition.FLEXIBLE_UPPER, qualifiers, index, subtreeSizes session, TypeComponentPosition.FLEXIBLE_UPPER, qualifiers, index, subtreeSizes,
isFromDefinitelyNotNullType = false, convertErrorToWarning = convertErrorsToWarnings,
) )
when { when {
@@ -59,7 +64,8 @@ private fun ConeKotlinType.enhanceConeKotlinType(
} }
} }
is ConeSimpleKotlinType -> enhanceInflexibleType( is ConeSimpleKotlinType -> enhanceInflexibleType(
session, TypeComponentPosition.INFLEXIBLE, qualifiers, index, subtreeSizes session, TypeComponentPosition.INFLEXIBLE, qualifiers, index, subtreeSizes,
isFromDefinitelyNotNullType = false, convertErrorToWarning = convertErrorsToWarnings,
) )
else -> null else -> null
} }
@@ -79,10 +85,11 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
qualifiers: IndexedJavaTypeQualifiers, qualifiers: IndexedJavaTypeQualifiers,
index: Int, index: Int,
subtreeSizes: List<Int>, subtreeSizes: List<Int>,
isFromDefinitelyNotNullType: Boolean = false, isFromDefinitelyNotNullType: Boolean,
convertErrorToWarning: Boolean,
): ConeSimpleKotlinType? { ): ConeSimpleKotlinType? {
if (this is ConeDefinitelyNotNullType) { if (this is ConeDefinitelyNotNullType) {
return original.enhanceInflexibleType(session, position, qualifiers, index, subtreeSizes, isFromDefinitelyNotNullType = true) return original.enhanceInflexibleType(session, position, qualifiers, index, subtreeSizes, isFromDefinitelyNotNullType = true, convertErrorToWarning)
} }
val shouldEnhance = position.shouldEnhance() val shouldEnhance = position.shouldEnhance()
@@ -103,19 +110,20 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
isFromDefinitelyNotNullType, isFromDefinitelyNotNullType,
effectiveQualifiers.definitelyNotNull, effectiveQualifiers.definitelyNotNull,
nullabilityFromQualifiers, nullabilityFromQualifiers,
enhancedTag enhancedTag,
convertNestedErrorsToWarnings = convertErrorToWarning ||
effectiveQualifiers.isNullabilityQualifierForWarning &&
!session.languageVersionSettings.supportsFeature(LanguageFeature.SupportJavaErrorEnhancementOfArgumentsOfWarningLevelEnhanced),
) )
return if (effectiveQualifiers.isNullabilityQualifierForWarning && enhanced != null) { return if (enhanced != null && (effectiveQualifiers.isNullabilityQualifierForWarning || convertErrorToWarning)) {
val newAttributes = attributes.plus(EnhancedTypeForWarningAttribute(enhanced)) val newAttributes = attributes.plus(EnhancedTypeForWarningAttribute(enhanced, isDeprecation = convertErrorToWarning && effectiveQualifiers.enhancesSomethingForError()))
// TODO if the arguments of `enhanced` are error-level annotated, we're losing them here for compatibility with K1,
// a fix requires a deprecation cycle, see KT-63208
if (enhancedTag != lookupTag) { if (enhancedTag != lookupTag) {
// Handle case when mutability was enhanced and nullability was enhanced for warning. // Handle case when mutability was enhanced and nullability was enhanced for warning.
enhancedTag.constructType(typeArguments, isNullable, newAttributes) enhancedTag.constructType(enhanced.typeArguments, isNullable, newAttributes)
} else { } else {
this.withAttributes(newAttributes) this.withAttributes(newAttributes).withArguments(enhanced.typeArguments)
}.applyIf(isFromDefinitelyNotNullType) { }.applyIf(isFromDefinitelyNotNullType) {
// If the original type was DNN, we need to wrap the result in a DNN type because `this` is the non-DNN part of the original. // If the original type was DNN, we need to wrap the result in a DNN type because `this` is the non-DNN part of the original.
// In the non-warning case, this happens in the nested call and so `enhanced` is already DNN. // In the non-warning case, this happens in the nested call and so `enhanced` is already DNN.
@@ -126,6 +134,10 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
} }
} }
private fun JavaTypeQualifiers.enhancesSomethingForError(): Boolean {
return !isNullabilityQualifierForWarning && (nullability != null || mutability != null || definitelyNotNull)
}
private fun ConeLookupTagBasedType.enhanceInflexibleType( private fun ConeLookupTagBasedType.enhanceInflexibleType(
session: FirSession, session: FirSession,
qualifiers: IndexedJavaTypeQualifiers, qualifiers: IndexedJavaTypeQualifiers,
@@ -135,6 +147,7 @@ private fun ConeLookupTagBasedType.enhanceInflexibleType(
isDefinitelyNotNull: Boolean, isDefinitelyNotNull: Boolean,
nullabilityFromQualifiers: NullabilityQualifier?, nullabilityFromQualifiers: NullabilityQualifier?,
enhancedTag: ConeClassifierLookupTag, enhancedTag: ConeClassifierLookupTag,
convertNestedErrorsToWarnings: Boolean,
): ConeSimpleKotlinType? { ): ConeSimpleKotlinType? {
val enhancedIsNullable = when (nullabilityFromQualifiers) { val enhancedIsNullable = when (nullabilityFromQualifiers) {
NullabilityQualifier.NULLABLE -> true NullabilityQualifier.NULLABLE -> true
@@ -145,14 +158,15 @@ private fun ConeLookupTagBasedType.enhanceInflexibleType(
var globalArgIndex = index + 1 var globalArgIndex = index + 1
val enhancedArguments = typeArguments.map { arg -> val enhancedArguments = typeArguments.map { arg ->
val argIndex = globalArgIndex.also { globalArgIndex += subtreeSizes[it] } val argIndex = globalArgIndex.also { globalArgIndex += subtreeSizes[it] }
arg.type?.enhanceConeKotlinType(session, qualifiers, argIndex, subtreeSizes)?.let { arg.type?.enhanceConeKotlinType(session, qualifiers, argIndex, subtreeSizes, convertErrorsToWarnings = convertNestedErrorsToWarnings)
when (arg.kind) { ?.let {
ProjectionKind.IN -> ConeKotlinTypeProjectionIn(it) when (arg.kind) {
ProjectionKind.OUT -> ConeKotlinTypeProjectionOut(it) ProjectionKind.IN -> ConeKotlinTypeProjectionIn(it)
ProjectionKind.STAR -> ConeStarProjection ProjectionKind.OUT -> ConeKotlinTypeProjectionOut(it)
ProjectionKind.INVARIANT -> it ProjectionKind.STAR -> ConeStarProjection
ProjectionKind.INVARIANT -> it
}
} }
}
} }
val shouldAddAttribute = nullabilityFromQualifiers == NullabilityQualifier.NOT_NULL && !hasEnhancedNullability val shouldAddAttribute = nullabilityFromQualifiers == NullabilityQualifier.NOT_NULL && !hasEnhancedNullability
@@ -0,0 +1,39 @@
// FULL_JDK
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// LANGUAGE: -SupportJavaErrorEnhancementOfArgumentsOfWarningLevelEnhanced
// FILE: ElementTypesAreNonnullByDefault.java
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)
@Target({ElementType.TYPE})
@TypeQualifierDefault({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Nonnull
@interface ElementTypesAreNonnullByDefault {
}
// FILE: Maps.java
import org.checkerframework.checker.nullness.qual.Nullable;
// Here it's important that @ElementTypesAreNonnullByDefault is a JSR-305 default qualifier and disabled by default (resulting in warnings-only)
// Thus return type (head type) is considered as warningly-annotated as not-nullable and that makes annotations on bounds for K and V
// be effectively ignored on non-warnings level.
// Behavior was changed in K2, see KT-63209.
@ElementTypesAreNonnullByDefault
public final class Maps {
public static <K extends @Nullable Object, V extends @Nullable Object> java.util.HashMap<K,V> newHashMap() { return null; }
}
// FILE: main.kt
fun foo() {
val x = Maps.newHashMap<String, Int>()
x.put("", 1)
// If there were no @ElementTypesAreNonnullByDefault on the Maps class, there would be an error on `null` argument because the type of `x`
// would be `HashMap<String, Int>!`, i.e. with non-flexible type arguments, thus not allowing nulls.
x.put("", <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
}
@@ -1,6 +1,6 @@
// FIR_IDENTICAL
// FULL_JDK // FULL_JDK
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// LANGUAGE: -SupportJavaErrorEnhancementOfArgumentsOfWarningLevelEnhanced
// FILE: ElementTypesAreNonnullByDefault.java // FILE: ElementTypesAreNonnullByDefault.java
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
@@ -22,6 +22,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
// Here it's important that @ElementTypesAreNonnullByDefault is a JSR-305 default qualifier and disabled by default (resulting in warnings-only) // Here it's important that @ElementTypesAreNonnullByDefault is a JSR-305 default qualifier and disabled by default (resulting in warnings-only)
// Thus return type (head type) is considered as warningly-annotated as not-nullable and that makes annotations on bounds for K and V // Thus return type (head type) is considered as warningly-annotated as not-nullable and that makes annotations on bounds for K and V
// be effectively ignored on non-warnings level. // be effectively ignored on non-warnings level.
// Behavior was changed in K2, see KT-63209.
@ElementTypesAreNonnullByDefault @ElementTypesAreNonnullByDefault
public final class Maps { public final class Maps {
public static <K extends @Nullable Object, V extends @Nullable Object> java.util.HashMap<K,V> newHashMap() { return null; } public static <K extends @Nullable Object, V extends @Nullable Object> java.util.HashMap<K,V> newHashMap() { return null; }
@@ -0,0 +1,71 @@
// NULLABILITY_ANNOTATIONS: @io.reactivex.rxjava3.annotations:strict, @org.eclipse.jdt.annotation:warn
// LANGUAGE: +SupportJavaErrorEnhancementOfArgumentsOfWarningLevelEnhanced
// SOURCE_RETENTION_ANNOTATIONS
// MUTE_FOR_PSI_CLASS_FILES_READING
// ^because annotations don't allow type parameter use.
// ISSUE: KT-63209
// FILE: A1.java
import java.util.List;
public class A1 {
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable String> warningError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable List<@io.reactivex.rxjava3.annotations.Nullable String>> warningErrorError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@org.eclipse.jdt.annotation.Nullable List<@io.reactivex.rxjava3.annotations.Nullable String>> warningWarningError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable List<@org.eclipse.jdt.annotation.Nullable String>> warningErrorWarning() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<List<@io.reactivex.rxjava3.annotations.Nullable String>> warningPlatformError() {
return null;
}
}
// FILE: main.kt
fun main1() {
val list = A1.warningError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element<!UNSAFE_CALL!>.<!>length
}
fun main2() {
val list = A1.warningErrorError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element<!UNSAFE_CALL!>.<!>get(0)
element!!.get(0)<!UNSAFE_CALL!>.<!>length
}
fun main3() {
val list = A1.warningWarningError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>element<!>.get(0)
element!!.get(0)<!UNSAFE_CALL!>.<!>length
}
fun main4() {
val list = A1.warningErrorWarning()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element<!UNSAFE_CALL!>.<!>get(0)
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>element!!.get(0)<!>.length
}
fun main5() {
val list = A1.warningPlatformError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.get(0)
element!!.get(0)<!UNSAFE_CALL!>.<!>length
}
@@ -0,0 +1,71 @@
// NULLABILITY_ANNOTATIONS: @io.reactivex.rxjava3.annotations:strict, @org.eclipse.jdt.annotation:warn
// LANGUAGE: +SupportJavaErrorEnhancementOfArgumentsOfWarningLevelEnhanced
// SOURCE_RETENTION_ANNOTATIONS
// MUTE_FOR_PSI_CLASS_FILES_READING
// ^because annotations don't allow type parameter use.
// ISSUE: KT-63209
// FILE: A1.java
import java.util.List;
public class A1 {
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable String> warningError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable List<@io.reactivex.rxjava3.annotations.Nullable String>> warningErrorError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@org.eclipse.jdt.annotation.Nullable List<@io.reactivex.rxjava3.annotations.Nullable String>> warningWarningError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable List<@org.eclipse.jdt.annotation.Nullable String>> warningErrorWarning() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<List<@io.reactivex.rxjava3.annotations.Nullable String>> warningPlatformError() {
return null;
}
}
// FILE: main.kt
fun main1() {
val list = A1.warningError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.length
}
fun main2() {
val list = A1.warningErrorError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.get(0)
element!!.get(0).length
}
fun main3() {
val list = A1.warningWarningError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.get(0)
element!!.get(0).length
}
fun main4() {
val list = A1.warningErrorWarning()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.get(0)
element!!.get(0).length
}
fun main5() {
val list = A1.warningPlatformError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.get(0)
element!!.get(0).length
}
@@ -0,0 +1,71 @@
// NULLABILITY_ANNOTATIONS: @io.reactivex.rxjava3.annotations:strict, @org.eclipse.jdt.annotation:warn
// LANGUAGE: -SupportJavaErrorEnhancementOfArgumentsOfWarningLevelEnhanced
// SOURCE_RETENTION_ANNOTATIONS
// MUTE_FOR_PSI_CLASS_FILES_READING
// ^because annotations don't allow type parameter use.
// ISSUE: KT-63209
// FILE: A1.java
import java.util.List;
public class A1 {
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable String> warningError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable List<@io.reactivex.rxjava3.annotations.Nullable String>> warningErrorError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@org.eclipse.jdt.annotation.Nullable List<@io.reactivex.rxjava3.annotations.Nullable String>> warningWarningError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable List<@org.eclipse.jdt.annotation.Nullable String>> warningErrorWarning() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<List<@io.reactivex.rxjava3.annotations.Nullable String>> warningPlatformError() {
return null;
}
}
// FILE: main.kt
fun main1() {
val list = A1.warningError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("kotlin.collections.(Mutable)List<@Nullable() kotlin.String?>?")!>list<!>.get(0)
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("@Nullable() kotlin.String?; This will become an error in Kotlin 2.1. See https://youtrack.jetbrains.com/issue/KT-63209.")!>element<!>.length
}
fun main2() {
val list = A1.warningErrorError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("kotlin.collections.(Mutable)List<(@Nullable() kotlin.collections.MutableList<@Nullable() kotlin.String?>?..@Nullable() kotlin.collections.List<@Nullable() kotlin.String?>?)>?")!>list<!>.get(0)
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("(@Nullable() kotlin.collections.MutableList<@Nullable() kotlin.String?>?..@Nullable() kotlin.collections.List<@Nullable() kotlin.String?>?); This will become an error in Kotlin 2.1. See https://youtrack.jetbrains.com/issue/KT-63209.")!>element<!>.get(0)
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("@Nullable() kotlin.String?; This will become an error in Kotlin 2.1. See https://youtrack.jetbrains.com/issue/KT-63209.")!>element!!.get(0)<!>.length
}
fun main3() {
val list = A1.warningWarningError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("kotlin.collections.(Mutable)List<(@Nullable() kotlin.collections.MutableList<@Nullable() kotlin.String?>?..@Nullable() kotlin.collections.List<@Nullable() kotlin.String?>?)>?")!>list<!>.get(0)
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("(@Nullable() kotlin.collections.MutableList<@Nullable() kotlin.String?>?..@Nullable() kotlin.collections.List<@Nullable() kotlin.String?>?)")!>element<!>.get(0)
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("@Nullable() kotlin.String?; This will become an error in Kotlin 2.1. See https://youtrack.jetbrains.com/issue/KT-63209.")!>element!!.get(0)<!>.length
}
fun main4() {
val list = A1.warningErrorWarning()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("kotlin.collections.(Mutable)List<(@Nullable() kotlin.collections.MutableList<@Nullable() kotlin.String?>?..@Nullable() kotlin.collections.List<@Nullable() kotlin.String?>?)>?")!>list<!>.get(0)
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("(@Nullable() kotlin.collections.MutableList<@Nullable() kotlin.String?>?..@Nullable() kotlin.collections.List<@Nullable() kotlin.String?>?); This will become an error in Kotlin 2.1. See https://youtrack.jetbrains.com/issue/KT-63209.")!>element<!>.get(0)
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("@Nullable() kotlin.String?")!>element!!.get(0)<!>.length
}
fun main5() {
val list = A1.warningPlatformError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("kotlin.collections.(Mutable)List<kotlin.collections.(Mutable)List<@Nullable() kotlin.String?>!>?")!>list<!>.get(0)
element.get(0)
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS("@Nullable() kotlin.String?; This will become an error in Kotlin 2.1. See https://youtrack.jetbrains.com/issue/KT-63209.")!>element!!.get(0)<!>.length
}
@@ -0,0 +1,71 @@
// NULLABILITY_ANNOTATIONS: @io.reactivex.rxjava3.annotations:strict, @org.eclipse.jdt.annotation:warn
// LANGUAGE: -SupportJavaErrorEnhancementOfArgumentsOfWarningLevelEnhanced
// SOURCE_RETENTION_ANNOTATIONS
// MUTE_FOR_PSI_CLASS_FILES_READING
// ^because annotations don't allow type parameter use.
// ISSUE: KT-63209
// FILE: A1.java
import java.util.List;
public class A1 {
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable String> warningError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable List<@io.reactivex.rxjava3.annotations.Nullable String>> warningErrorError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@org.eclipse.jdt.annotation.Nullable List<@io.reactivex.rxjava3.annotations.Nullable String>> warningWarningError() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<@io.reactivex.rxjava3.annotations.Nullable List<@org.eclipse.jdt.annotation.Nullable String>> warningErrorWarning() {
return null;
}
@org.eclipse.jdt.annotation.Nullable
public static List<List<@io.reactivex.rxjava3.annotations.Nullable String>> warningPlatformError() {
return null;
}
}
// FILE: main.kt
fun main1() {
val list = A1.warningError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.length
}
fun main2() {
val list = A1.warningErrorError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.get(0)
element!!.get(0).length
}
fun main3() {
val list = A1.warningWarningError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.get(0)
element!!.get(0).length
}
fun main4() {
val list = A1.warningErrorWarning()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.get(0)
element!!.get(0).length
}
fun main5() {
val list = A1.warningPlatformError()
val element = <!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>list<!>.get(0)
element.get(0)
element!!.get(0).length
}
@@ -68,6 +68,18 @@ public class ForeignAnnotationsCompiledJavaTestGenerated extends AbstractForeign
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt"); runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt");
} }
@Test
@TestMetadata("errorArgumentOfWarningAfter.kt")
public void testErrorArgumentOfWarningAfter() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningAfter.kt");
}
@Test
@TestMetadata("errorArgumentOfWarningBefore.kt")
public void testErrorArgumentOfWarningBefore() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningBefore.kt");
}
@Test @Test
@TestMetadata("findBugsSimple.kt") @TestMetadata("findBugsSimple.kt")
public void testFindBugsSimple() throws Exception { public void testFindBugsSimple() throws Exception {
@@ -68,6 +68,18 @@ public class ForeignAnnotationsCompiledJavaWithPsiClassReadingTestGenerated exte
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt"); runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt");
} }
@Test
@TestMetadata("errorArgumentOfWarningAfter.kt")
public void testErrorArgumentOfWarningAfter() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningAfter.kt");
}
@Test
@TestMetadata("errorArgumentOfWarningBefore.kt")
public void testErrorArgumentOfWarningBefore() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningBefore.kt");
}
@Test @Test
@TestMetadata("findBugsSimple.kt") @TestMetadata("findBugsSimple.kt")
public void testFindBugsSimple() throws Exception { public void testFindBugsSimple() throws Exception {
@@ -68,6 +68,18 @@ public class ForeignAnnotationsSourceJavaTestGenerated extends AbstractForeignAn
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt"); runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/eclipse.kt");
} }
@Test
@TestMetadata("errorArgumentOfWarningAfter.kt")
public void testErrorArgumentOfWarningAfter() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningAfter.kt");
}
@Test
@TestMetadata("errorArgumentOfWarningBefore.kt")
public void testErrorArgumentOfWarningBefore() throws Exception {
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/errorArgumentOfWarningBefore.kt");
}
@Test @Test
@TestMetadata("findBugsSimple.kt") @TestMetadata("findBugsSimple.kt")
public void testFindBugsSimple() throws Exception { public void testFindBugsSimple() throws Exception {
@@ -318,6 +318,7 @@ enum class LanguageFeature(
ProhibitSingleNamedFunctionAsExpression(KOTLIN_2_1, kind = BUG_FIX), // KT-62573 ProhibitSingleNamedFunctionAsExpression(KOTLIN_2_1, kind = BUG_FIX), // KT-62573
ForbidLambdaParameterWithMissingDependencyType(KOTLIN_2_1, kind = BUG_FIX), // KT-64266 ForbidLambdaParameterWithMissingDependencyType(KOTLIN_2_1, kind = BUG_FIX), // KT-64266
JsAllowInvalidCharsIdentifiersEscaping(KOTLIN_2_1, kind = OTHER), // KT-31799 JsAllowInvalidCharsIdentifiersEscaping(KOTLIN_2_1, kind = OTHER), // KT-31799
SupportJavaErrorEnhancementOfArgumentsOfWarningLevelEnhanced(KOTLIN_2_1, kind = BUG_FIX), // KT-63209
// End of 2.* language features -------------------------------------------------- // End of 2.* language features --------------------------------------------------