[FIR] Introduce OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE diagnostic

^KT-60892
This commit is contained in:
Ivan Kochurkin
2023-08-08 16:00:08 +02:00
committed by Space Team
parent 9ec7218af6
commit 8e8de513ee
22 changed files with 77 additions and 33 deletions
@@ -3624,6 +3624,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE) { firDiagnostic ->
OptionalDeclarationUsageInNonCommonSourceImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION) { firDiagnostic ->
InitializerRequiredForDestructuringDeclarationImpl(
firDiagnostic as KtPsiDiagnostic,
@@ -2537,6 +2537,10 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = OptionalDeclarationOutsideOfAnnotationEntry::class
}
interface OptionalDeclarationUsageInNonCommonSource : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = OptionalDeclarationUsageInNonCommonSource::class
}
interface InitializerRequiredForDestructuringDeclaration : KtFirDiagnostic<KtDestructuringDeclaration> {
override val diagnosticClass get() = InitializerRequiredForDestructuringDeclaration::class
}
@@ -3058,6 +3058,11 @@ internal class OptionalDeclarationOutsideOfAnnotationEntryImpl(
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.OptionalDeclarationOutsideOfAnnotationEntry
internal class OptionalDeclarationUsageInNonCommonSourceImpl(
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.OptionalDeclarationUsageInNonCommonSource
internal class InitializerRequiredForDestructuringDeclarationImpl(
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
@@ -1238,6 +1238,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
}
val OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY by error<PsiElement>()
val OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE by error<PsiElement>()
}
val DESTRUCTING_DECLARATION by object : DiagnosticGroup("Destructuring declaration") {
@@ -650,6 +650,7 @@ object FirErrors {
val ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION by error1<KtTypeAlias, ClassId>(SourceElementPositioningStrategies.TYPEALIAS_TYPE_REFERENCE)
val ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT by warning3<KtElement, FirBasedSymbol<*>, FirBasedSymbol<*>, ExpectActualAnnotationsIncompatibilityType<FirAnnotation>>(SourceElementPositioningStrategies.DECLARATION_NAME_ONLY)
val OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY by error0<PsiElement>()
val OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE by error0<PsiElement>()
// Destructuring declaration
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<KtDestructuringDeclaration>()
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isOptionalAnnotationClass
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.references.toResolvedConstructorSymbol
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
@@ -21,6 +22,10 @@ object FirOptionalExpectationExpressionChecker : FirFunctionCallChecker() {
val declarationClass = constructorSymbol.resolvedReturnTypeRef.coneType.toRegularClassSymbol(context.session) ?: return
if (!declarationClass.isOptionalAnnotationClass(context.session)) return
if (!context.session.moduleData.isCommon) {
reporter.reportOn(expression.source, FirErrors.OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE, context)
}
reporter.reportOn(expression.source, FirErrors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, context)
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isOptionalAnnotationClass
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
@@ -23,6 +24,10 @@ object FirOptionalExpectationTypeChecker : FirTypeRefChecker() {
val classSymbol = typeRef.coneTypeSafe<ConeClassLikeType>()?.toRegularClassSymbol(context.session) ?: return
if (!classSymbol.isOptionalAnnotationClass(context.session)) return
if (!context.session.moduleData.isCommon) {
reporter.reportOn(source, FirErrors.OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE, context)
}
val annotationContainer = context.annotationContainers.lastOrNull()
if (annotationContainer?.annotations?.any { it.typeRef == typeRef } == true) return
@@ -436,6 +436,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ONLY_ONE_CLASS_BO
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_MODIFIER_REQUIRED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_RENAMED_ON_IMPORT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_ARGUMENT_IS_NOT_MARKER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_IS_NOT_ENABLED
@@ -1926,6 +1927,10 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY,
"Declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry"
)
map.put(
OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE,
"Declaration annotated with '@OptionalExpectation' can only be used in common module sources"
)
// Destructuring declaration
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")
@@ -4,6 +4,7 @@
// WITH_STDLIB
// MODULE: common
// TARGET_PLATFORM: Common
// FILE: expected.kt
package a
@@ -24,17 +25,24 @@ package a
actual annotation class A(actual val x: Int)
// MODULE: main(library)
// MODULE: common2
// TARGET_PLATFORM: Common
// FILE: common2.kt
package usage
import a.B
@B("OK")
@B.C(true)
fun ok() = "OK"
// MODULE: main(library)()(common2)
// FILE: main.kt
package usage
import a.A
import a.B
@A(42)
@B("OK")
@B.C(true)
fun box(): String {
return "OK"
}
fun box(): String = ok()
@@ -18,7 +18,7 @@ expect annotation class WithoutActual(val s: String)
expect fun k(): String
// MODULE: platform()()(common)
// MODULE: lib()()(common)
// FILE: lib.kt
actual class C {
@@ -29,9 +29,15 @@ actual annotation class WithActual(actual val x: Int)
actual fun k() = "K"
// MODULE: main(platform)
// MODULE: common2
// TARGET_PLATFORM: Common
// FILE: common2.kt
@WithoutActual("OK")
fun ok() = C().o() + k()
// MODULE: main(lib)()(common2)
// FILE: main.kt
@WithActual(42)
@WithoutActual("OK")
fun box() = C().o() + k()
fun box() = ok()
+1 -2
View File
@@ -1,6 +1,5 @@
// WITH_STDLIB
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K1: WASM, JS_IR, JS_IR_ES6
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, WASM
// !API_VERSION: 1.9
import kotlin.concurrent.*
+1 -2
View File
@@ -1,6 +1,5 @@
// WITH_STDLIB
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K1: WASM, JS_IR, JS_IR_ES6
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, WASM
// !API_VERSION: 1.9
import kotlin.concurrent.*
+1 -2
View File
@@ -1,6 +1,5 @@
// WITH_STDLIB
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K1: WASM, JS_IR, JS_IR_ES6
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, WASM
// !API_VERSION: 1.9
import kotlin.concurrent.*
+1 -2
View File
@@ -1,6 +1,5 @@
// WITH_STDLIB
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K1: WASM, JS_IR, JS_IR_ES6
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, WASM
// !API_VERSION: 1.9
import kotlin.concurrent.*
+1 -2
View File
@@ -1,6 +1,5 @@
// WITH_STDLIB
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K1: WASM, JS_IR, JS_IR_ES6
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, WASM
// !API_VERSION: 1.9
import kotlin.concurrent.*
+1 -2
View File
@@ -1,6 +1,5 @@
// WITH_STDLIB
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K1: WASM, JS_IR, JS_IR_ES6
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, WASM
// !API_VERSION: 1.9
import kotlin.concurrent.*
+1 -2
View File
@@ -1,6 +1,5 @@
// WITH_STDLIB
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K1: WASM, JS_IR, JS_IR_ES6
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, WASM
// !API_VERSION: 1.9
import kotlin.concurrent.*
+1 -2
View File
@@ -1,6 +1,5 @@
// WITH_STDLIB
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K1: WASM, JS_IR, JS_IR_ES6
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, WASM
// !API_VERSION: 1.9
import kotlin.concurrent.*
+1 -2
View File
@@ -1,6 +1,5 @@
// WITH_STDLIB
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K1: WASM, JS_IR, JS_IR_ES6
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, WASM
// !API_VERSION: 1.9
import kotlin.concurrent.*
@@ -29,11 +29,14 @@ expect class C {
// MODULE: platform()()(common)
// FILE: platform.kt
fun useInReturnType(): <!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY!>A?<!> = null
@<!OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE!>A<!>
class D
annotation class AnotherAnnotation(val a: <!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY!>A<!>)
fun useInReturnType(): <!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE!>A?<!> = null
@AnotherAnnotation(<!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY!>A()<!>)
annotation class AnotherAnnotation(val a: <!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE!>A<!>)
@AnotherAnnotation(<!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE!>A()<!>)
fun useInAnotherAnnotation() {}
actual class C {
@@ -29,6 +29,9 @@ expect class C {
// MODULE: platform()()(common)
// FILE: platform.kt
@<!OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE!>A<!>
class D
fun useInReturnType(): <!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE!>A<!>? = null
annotation class AnotherAnnotation(val a: <!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE!>A<!>)
@@ -1,5 +1,5 @@
// SKIP_KLIB_TEST
// IGNORE_BACKEND_K1: JS_IR
// IGNORE_BACKEND: JS_IR
// WITH_STDLIB
// LANGUAGE: +ValueClasses