[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,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY) { firDiagnostic ->
|
||||||
|
OptionalDeclarationOutsideOfAnnotationEntryImpl(
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION) { firDiagnostic ->
|
add(FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION) { firDiagnostic ->
|
||||||
InitializerRequiredForDestructuringDeclarationImpl(
|
InitializerRequiredForDestructuringDeclarationImpl(
|
||||||
firDiagnostic as KtPsiDiagnostic,
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
|||||||
+4
@@ -2533,6 +2533,10 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
val incompatibilityType: ExpectActualAnnotationsIncompatibilityType<FirAnnotation>
|
val incompatibilityType: ExpectActualAnnotationsIncompatibilityType<FirAnnotation>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface OptionalDeclarationOutsideOfAnnotationEntry : KtFirDiagnostic<PsiElement> {
|
||||||
|
override val diagnosticClass get() = OptionalDeclarationOutsideOfAnnotationEntry::class
|
||||||
|
}
|
||||||
|
|
||||||
interface InitializerRequiredForDestructuringDeclaration : KtFirDiagnostic<KtDestructuringDeclaration> {
|
interface InitializerRequiredForDestructuringDeclaration : KtFirDiagnostic<KtDestructuringDeclaration> {
|
||||||
override val diagnosticClass get() = InitializerRequiredForDestructuringDeclaration::class
|
override val diagnosticClass get() = InitializerRequiredForDestructuringDeclaration::class
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -3053,6 +3053,11 @@ internal class ActualAnnotationsNotMatchExpectImpl(
|
|||||||
token: KtLifetimeToken,
|
token: KtLifetimeToken,
|
||||||
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.ActualAnnotationsNotMatchExpect
|
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.ActualAnnotationsNotMatchExpect
|
||||||
|
|
||||||
|
internal class OptionalDeclarationOutsideOfAnnotationEntryImpl(
|
||||||
|
firDiagnostic: KtPsiDiagnostic,
|
||||||
|
token: KtLifetimeToken,
|
||||||
|
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.OptionalDeclarationOutsideOfAnnotationEntry
|
||||||
|
|
||||||
internal class InitializerRequiredForDestructuringDeclarationImpl(
|
internal class InitializerRequiredForDestructuringDeclarationImpl(
|
||||||
firDiagnostic: KtPsiDiagnostic,
|
firDiagnostic: KtPsiDiagnostic,
|
||||||
token: KtLifetimeToken,
|
token: KtLifetimeToken,
|
||||||
|
|||||||
+2
@@ -1236,6 +1236,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
parameter<Symbol>("actualSymbol")
|
parameter<Symbol>("actualSymbol")
|
||||||
parameter<ExpectActualAnnotationsIncompatibilityType<FirAnnotation>>("incompatibilityType")
|
parameter<ExpectActualAnnotationsIncompatibilityType<FirAnnotation>>("incompatibilityType")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY by error<PsiElement>()
|
||||||
}
|
}
|
||||||
|
|
||||||
val DESTRUCTING_DECLARATION by object : DiagnosticGroup("Destructuring declaration") {
|
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 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_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 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
|
// Destructuring declaration
|
||||||
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<KtDestructuringDeclaration>()
|
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<KtDestructuringDeclaration>()
|
||||||
|
|||||||
+1
@@ -71,6 +71,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
FirUnderscoredTypeArgumentSyntaxChecker,
|
FirUnderscoredTypeArgumentSyntaxChecker,
|
||||||
FirContractNotFirstStatementChecker,
|
FirContractNotFirstStatementChecker,
|
||||||
FirProtectedConstructorNotInSuperCallChecker,
|
FirProtectedConstructorNotInSuperCallChecker,
|
||||||
|
FirOptionalExpectationExpressionChecker
|
||||||
)
|
)
|
||||||
|
|
||||||
override val propertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker>
|
override val propertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker>
|
||||||
|
|||||||
+1
@@ -17,5 +17,6 @@ object CommonTypeCheckers : TypeCheckers() {
|
|||||||
FirUnsupportedDefaultValueInFunctionTypeParameterChecker,
|
FirUnsupportedDefaultValueInFunctionTypeParameterChecker,
|
||||||
FirUnsupportedModifiersInFunctionTypeParameterChecker,
|
FirUnsupportedModifiersInFunctionTypeParameterChecker,
|
||||||
FirStarProjectionModifierChecker,
|
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.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_MODIFIER_REQUIRED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_RENAMED_ON_IMPORT
|
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_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_CAN_ONLY_BE_USED_AS_ANNOTATION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_IS_NOT_ENABLED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_IS_NOT_ENABLED
|
||||||
@@ -1921,6 +1922,10 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.SYMBOL_RENDERER,
|
FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.SYMBOL_RENDERER,
|
||||||
FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.INCOMPATIBILITY,
|
FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.INCOMPATIBILITY,
|
||||||
)
|
)
|
||||||
|
map.put(
|
||||||
|
OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY,
|
||||||
|
"Declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry"
|
||||||
|
)
|
||||||
|
|
||||||
// Destructuring declaration
|
// Destructuring declaration
|
||||||
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")
|
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")
|
||||||
|
|||||||
+6
-6
@@ -8,7 +8,7 @@
|
|||||||
@OptionalExpectation
|
@OptionalExpectation
|
||||||
expect annotation class A()
|
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<!>
|
<!NO_ACTUAL_FOR_EXPECT{JVM}!><!WRONG_ANNOTATION_TARGET!>@OptionalExpectation<!>
|
||||||
expect class NotAnAnnotationClass<!>
|
expect class NotAnAnnotationClass<!>
|
||||||
@@ -16,9 +16,9 @@ expect class NotAnAnnotationClass<!>
|
|||||||
@OptionalExpectation
|
@OptionalExpectation
|
||||||
annotation class NotAnExpectedClass
|
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() {}
|
fun useInOtherAnnotation() {}
|
||||||
|
|
||||||
expect class C {
|
expect class C {
|
||||||
@@ -29,11 +29,11 @@ expect class C {
|
|||||||
// MODULE: platform()()(common)
|
// MODULE: platform()()(common)
|
||||||
// FILE: platform.kt
|
// 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() {}
|
fun useInAnotherAnnotation() {}
|
||||||
|
|
||||||
actual class C {
|
actual class C {
|
||||||
|
|||||||
Reference in New Issue
Block a user