[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.lexer.KtKeywordToken;
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.metadata.deserialization.VersionRequirement;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
@@ -837,6 +838,8 @@ public interface Errors {
DiagnosticFactory0<PsiElement> OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> NOT_A_MULTIPLATFORM_COMPILATION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtNamedDeclaration> EXPECT_ACTUAL_OPT_IN_ANNOTATION = DiagnosticFactory0.create(ERROR, EXPECT_ACTUAL_MODIFIER);
DiagnosticFactory1<KtTypeAlias, ClassId> ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION =
DiagnosticFactory1.create(ERROR, TYPEALIAS_TYPE_REFERENCE);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -393,6 +393,9 @@ public class DefaultErrorMessages {
MAP.put(OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE, "Declaration annotated with '@OptionalExpectation' can only be used in common module sources");
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);
MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties");
MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here");
@@ -58,6 +58,7 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
DataObjectContentChecker,
EnumEntriesRedeclarationChecker,
VolatileAnnotationChecker,
ActualTypealiasToSpecialAnnotationChecker,
)
private val DEFAULT_CALL_CHECKERS = listOf(
@@ -0,0 +1,31 @@
/*
* 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.resolve.checkers
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtTypeAlias
import org.jetbrains.kotlin.resolve.calls.mpp.ActualTypealiasToSpecialAnnotationUtils.isAnnotationProhibitedInActualTypeAlias
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
internal object ActualTypealiasToSpecialAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (declaration !is KtTypeAlias || descriptor !is TypeAliasDescriptor || !descriptor.isActual) {
return
}
val classDescriptor = descriptor.classDescriptor ?: return
if (classDescriptor.kind != ClassKind.ANNOTATION_CLASS) {
return
}
val classId = classDescriptor.classId ?: return
if (isAnnotationProhibitedInActualTypeAlias(classId)) {
context.trace.report(Errors.ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION.on(declaration, classId))
}
}
}