[FE] Prohibit actual typealias to certain compiler annotations

^KT-58554
This commit is contained in:
Roman Efremov
2023-07-13 11:29:24 +02:00
committed by Space Team
parent f4a648aa3e
commit a79282cec1
21 changed files with 198 additions and 0 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
@@ -1176,6 +1177,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val NOT_A_MULTIPLATFORM_COMPILATION by error<PsiElement>()
val EXPECT_ACTUAL_OPT_IN_ANNOTATION by error<KtNamedDeclaration>(PositioningStrategy.EXPECT_ACTUAL_MODIFIER)
val ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION by error<KtTypeAlias>(PositioningStrategy.TYPEALIAS_TYPE_REFERENCE) {
parameter<ClassId>("typealiasedClassId")
}
}
val DESTRUCTING_DECLARATION by object : DiagnosticGroup("Destructuring declaration") {
@@ -114,6 +114,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
INLINE_FUN_MODIFIER,
CALL_ELEMENT_WITH_DOT,
EXPECT_ACTUAL_MODIFIER,
TYPEALIAS_TYPE_REFERENCE,
;
val expressionToCreate get() = "SourceElementPositioningStrategies.${strategy ?: name}"
@@ -627,6 +627,7 @@ object FirErrors {
val ACTUAL_MISSING by error0<KtNamedDeclaration>(SourceElementPositioningStrategies.ACTUAL_DECLARATION_NAME)
val NOT_A_MULTIPLATFORM_COMPILATION by error0<PsiElement>()
val EXPECT_ACTUAL_OPT_IN_ANNOTATION by error0<KtNamedDeclaration>(SourceElementPositioningStrategies.EXPECT_ACTUAL_MODIFIER)
val ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION by error1<KtTypeAlias, ClassId>(SourceElementPositioningStrategies.TYPEALIAS_TYPE_REFERENCE)
// Destructuring declaration
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<KtDestructuringDeclaration>()
@@ -159,6 +159,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
get() = setOf(
FirTopLevelTypeAliasChecker,
FirActualTypeAliasChecker,
FirActualTypealiasToSpecialAnnotationChecker,
)
override val anonymousFunctionCheckers: Set<FirAnonymousFunctionChecker>
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.classKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.declarations.utils.isActual
import org.jetbrains.kotlin.fir.types.toSymbol
import org.jetbrains.kotlin.resolve.calls.mpp.ActualTypealiasToSpecialAnnotationUtils.isAnnotationProhibitedInActualTypeAlias
internal object FirActualTypealiasToSpecialAnnotationChecker : FirTypeAliasChecker() {
override fun check(declaration: FirTypeAlias, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.isActual) return
val typealiasedClassSymbol = declaration.expandedConeType?.toSymbol(context.session) ?: return
if (typealiasedClassSymbol.classKind != ClassKind.ANNOTATION_CLASS) {
return
}
val classId = typealiasedClassSymbol.classId
if (isAnnotationProhibitedInActualTypeAlias(classId)) {
reporter.reportOn(declaration.source, FirErrors.ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION, classId, context)
}
}
}
@@ -54,6 +54,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACCESSOR_FOR_DELE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_MISSING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPE_ALIAS_NOT_TO_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION
@@ -1847,6 +1848,11 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put(ACTUAL_MISSING, "Declaration must be marked with 'actual'")
map.put(NOT_A_MULTIPLATFORM_COMPILATION, "'expect' and 'actual' declarations can be used only in multiplatform projects. Learn more about Kotlin Multiplatform: https://kotl.in/multiplatform-setup")
map.put(EXPECT_ACTUAL_OPT_IN_ANNOTATION, "Opt-in annotations are prohibited to be `expect` or `actual`. Instead, declare annotation once in common sources.")
map.put(
ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION,
"`actual typealias` to annotation which affects code compilation can lead to incorrect behavior. Instead, use ''{0}'' annotation directly.",
TO_STRING
)
// Destructuring declaration
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")