[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:
committed by
Space Team
parent
9189154cae
commit
371b1eb3d5
+2
@@ -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,
|
||||||
)
|
)
|
||||||
|
|||||||
+2
@@ -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> {
|
||||||
|
|||||||
+2
@@ -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
|
||||||
|
|||||||
+12
@@ -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 {
|
||||||
|
|||||||
+12
@@ -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 {
|
||||||
|
|||||||
+12
@@ -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 {
|
||||||
|
|||||||
+2
@@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -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>()
|
||||||
|
|||||||
+7
-4
@@ -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(
|
||||||
|
|||||||
+12
-4
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-1
@@ -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
|
||||||
|
|||||||
Vendored
+39
@@ -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<!>)
|
||||||
|
}
|
||||||
+2
-1
@@ -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; }
|
||||||
|
|||||||
Vendored
+71
@@ -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
|
||||||
|
}
|
||||||
+71
@@ -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
|
||||||
|
}
|
||||||
Vendored
+71
@@ -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
|
||||||
|
}
|
||||||
Vendored
+71
@@ -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
|
||||||
|
}
|
||||||
+12
@@ -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 {
|
||||||
|
|||||||
+12
@@ -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 {
|
||||||
|
|||||||
+12
@@ -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 --------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user