[FIR] Introduce OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY diagnostic
^KT-60892
This commit is contained in:
committed by
Space Team
parent
dc1f1fe979
commit
b08df32cac
+6
@@ -3618,6 +3618,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY) { firDiagnostic ->
|
||||
OptionalDeclarationOutsideOfAnnotationEntryImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION) { firDiagnostic ->
|
||||
InitializerRequiredForDestructuringDeclarationImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
|
||||
+4
@@ -2533,6 +2533,10 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
val incompatibilityType: ExpectActualAnnotationsIncompatibilityType<FirAnnotation>
|
||||
}
|
||||
|
||||
interface OptionalDeclarationOutsideOfAnnotationEntry : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = OptionalDeclarationOutsideOfAnnotationEntry::class
|
||||
}
|
||||
|
||||
interface InitializerRequiredForDestructuringDeclaration : KtFirDiagnostic<KtDestructuringDeclaration> {
|
||||
override val diagnosticClass get() = InitializerRequiredForDestructuringDeclaration::class
|
||||
}
|
||||
|
||||
+5
@@ -3053,6 +3053,11 @@ internal class ActualAnnotationsNotMatchExpectImpl(
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.ActualAnnotationsNotMatchExpect
|
||||
|
||||
internal class OptionalDeclarationOutsideOfAnnotationEntryImpl(
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.OptionalDeclarationOutsideOfAnnotationEntry
|
||||
|
||||
internal class InitializerRequiredForDestructuringDeclarationImpl(
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
|
||||
+2
@@ -1236,6 +1236,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<Symbol>("actualSymbol")
|
||||
parameter<ExpectActualAnnotationsIncompatibilityType<FirAnnotation>>("incompatibilityType")
|
||||
}
|
||||
|
||||
val OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY by error<PsiElement>()
|
||||
}
|
||||
|
||||
val DESTRUCTING_DECLARATION by object : DiagnosticGroup("Destructuring declaration") {
|
||||
|
||||
@@ -649,6 +649,7 @@ object FirErrors {
|
||||
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)
|
||||
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>()
|
||||
|
||||
// Destructuring declaration
|
||||
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<KtDestructuringDeclaration>()
|
||||
|
||||
+1
@@ -71,6 +71,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
FirUnderscoredTypeArgumentSyntaxChecker,
|
||||
FirContractNotFirstStatementChecker,
|
||||
FirProtectedConstructorNotInSuperCallChecker,
|
||||
FirOptionalExpectationExpressionChecker
|
||||
)
|
||||
|
||||
override val propertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker>
|
||||
|
||||
+1
@@ -17,5 +17,6 @@ object CommonTypeCheckers : TypeCheckers() {
|
||||
FirUnsupportedDefaultValueInFunctionTypeParameterChecker,
|
||||
FirUnsupportedModifiersInFunctionTypeParameterChecker,
|
||||
FirStarProjectionModifierChecker,
|
||||
FirOptionalExpectationTypeChecker
|
||||
)
|
||||
}
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
fun FirRegularClassSymbol.isOptionalAnnotationClass(session: FirSession): Boolean {
|
||||
return classKind == ClassKind.ANNOTATION_CLASS &&
|
||||
isExpect &&
|
||||
hasAnnotation(StandardClassIds.Annotations.OptionalExpectation, session)
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.expression
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
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.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||
|
||||
object FirOptionalExpectationExpressionChecker : FirFunctionCallChecker() {
|
||||
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val constructorSymbol = expression.calleeReference.toResolvedConstructorSymbol() ?: return
|
||||
val declarationClass = constructorSymbol.resolvedReturnTypeRef.coneType.toRegularClassSymbol(context.session) ?: return
|
||||
if (!declarationClass.isOptionalAnnotationClass(context.session)) return
|
||||
|
||||
reporter.reportOn(expression.source, FirErrors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, context)
|
||||
}
|
||||
}
|
||||
+31
@@ -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.fir.analysis.checkers.type
|
||||
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
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.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||
|
||||
object FirOptionalExpectationTypeChecker : FirTypeRefChecker() {
|
||||
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val source = typeRef.source
|
||||
if (source?.kind is KtFakeSourceElementKind) return
|
||||
val classSymbol = typeRef.coneTypeSafe<ConeClassLikeType>()?.toRegularClassSymbol(context.session) ?: return
|
||||
if (!classSymbol.isOptionalAnnotationClass(context.session)) return
|
||||
|
||||
val annotationContainer = context.annotationContainers.lastOrNull()
|
||||
if (annotationContainer?.annotations?.any { it.typeRef == typeRef } == true) return
|
||||
|
||||
reporter.reportOn(source, FirErrors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, context)
|
||||
}
|
||||
}
|
||||
+5
@@ -435,6 +435,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULL_FOR_NONNULL_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ONLY_ONE_CLASS_BOUND_ALLOWED
|
||||
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.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
|
||||
@@ -1921,6 +1922,10 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.SYMBOL_RENDERER,
|
||||
FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.INCOMPATIBILITY,
|
||||
)
|
||||
map.put(
|
||||
OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY,
|
||||
"Declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry"
|
||||
)
|
||||
|
||||
// Destructuring declaration
|
||||
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")
|
||||
|
||||
+6
-6
@@ -8,7 +8,7 @@
|
||||
@OptionalExpectation
|
||||
expect annotation class A()
|
||||
|
||||
fun useInSignature(a: A) = a.toString()
|
||||
fun useInSignature(a: <!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY!>A<!>) = a.toString()
|
||||
|
||||
<!NO_ACTUAL_FOR_EXPECT{JVM}!><!WRONG_ANNOTATION_TARGET!>@OptionalExpectation<!>
|
||||
expect class NotAnAnnotationClass<!>
|
||||
@@ -16,9 +16,9 @@ expect class NotAnAnnotationClass<!>
|
||||
@OptionalExpectation
|
||||
annotation class NotAnExpectedClass
|
||||
|
||||
annotation class InOtherAnnotation(val a: A)
|
||||
annotation class InOtherAnnotation(val a: <!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY!>A<!>)
|
||||
|
||||
@InOtherAnnotation(A())
|
||||
@InOtherAnnotation(<!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY!>A()<!>)
|
||||
fun useInOtherAnnotation() {}
|
||||
|
||||
expect class C {
|
||||
@@ -29,11 +29,11 @@ expect class C {
|
||||
// MODULE: platform()()(common)
|
||||
// FILE: platform.kt
|
||||
|
||||
fun useInReturnType(): A? = null
|
||||
fun useInReturnType(): <!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY!>A?<!> = null
|
||||
|
||||
annotation class AnotherAnnotation(val a: A)
|
||||
annotation class AnotherAnnotation(val a: <!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY!>A<!>)
|
||||
|
||||
@AnotherAnnotation(A())
|
||||
@AnotherAnnotation(<!OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY!>A()<!>)
|
||||
fun useInAnotherAnnotation() {}
|
||||
|
||||
actual class C {
|
||||
|
||||
Reference in New Issue
Block a user