FIR: handle annotations on non-containers more precisely
This commit is contained in:
+2
-1
@@ -10,12 +10,13 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirWrappedArgumentExpression
|
||||||
|
|
||||||
object FirAnnotationUsedAsAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
object FirAnnotationUsedAsAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
||||||
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val args = expression.argumentList.arguments
|
val args = expression.argumentList.arguments
|
||||||
for (arg in args) {
|
for (arg in args) {
|
||||||
for (ann in arg.annotations) {
|
for (ann in ((arg as? FirWrappedArgumentExpression)?.expression ?: arg).annotations) {
|
||||||
reporter.reportOn(ann.source, FirErrors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT, context)
|
reporter.reportOn(ann.source, FirErrors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -63,6 +63,7 @@ private fun ConeDiagnostic.toFirDiagnostic(
|
|||||||
is ConeContractDescriptionError -> FirErrors.ERROR_IN_CONTRACT_DESCRIPTION.on(source, this.reason)
|
is ConeContractDescriptionError -> FirErrors.ERROR_IN_CONTRACT_DESCRIPTION.on(source, this.reason)
|
||||||
is ConeTypeParameterSupertype -> FirErrors.SUPERTYPE_NOT_A_CLASS_OR_INTERFACE.on(source, this.reason)
|
is ConeTypeParameterSupertype -> FirErrors.SUPERTYPE_NOT_A_CLASS_OR_INTERFACE.on(source, this.reason)
|
||||||
is ConeTypeParameterInQualifiedAccess -> null // reported in various checkers instead
|
is ConeTypeParameterInQualifiedAccess -> null // reported in various checkers instead
|
||||||
|
is ConeNotAnnotationContainer -> null
|
||||||
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}")
|
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
|
|||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
|
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.ConeNotAnnotationContainer
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
@@ -411,10 +412,10 @@ class ExpressionsConverter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return firExpression?.also {
|
val result = firExpression ?: buildErrorExpression(null, ConeNotAnnotationContainer(firExpression?.render() ?: "???"))
|
||||||
require(it is FirAnnotationContainer)
|
require(result is FirAnnotationContainer)
|
||||||
(it.annotations as MutableList<FirAnnotationCall>) += firAnnotationList
|
(result.annotations as MutableList<FirAnnotationCall>) += firAnnotationList
|
||||||
} ?: buildErrorExpression(null, ConeSimpleDiagnostic("Strange annotated expression: ${firExpression?.render()}", DiagnosticKind.Syntax))
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
|||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.ConeNotAnnotationContainer
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
@@ -2083,15 +2084,10 @@ open class RawFirBuilder(
|
|||||||
|
|
||||||
override fun visitAnnotatedExpression(expression: KtAnnotatedExpression, data: Unit): FirElement {
|
override fun visitAnnotatedExpression(expression: KtAnnotatedExpression, data: Unit): FirElement {
|
||||||
val rawResult = expression.baseExpression?.accept(this, data)
|
val rawResult = expression.baseExpression?.accept(this, data)
|
||||||
// return rawResult ?: buildErrorExpression(
|
|
||||||
// expression.toFirSourceElement(),
|
|
||||||
// FirSimpleDiagnostic("Strange annotated expression: ${rawResult?.render()}", DiagnosticKind.Syntax),
|
|
||||||
// )
|
|
||||||
// TODO !!!!!!!!
|
|
||||||
val result = rawResult as? FirAnnotationContainer
|
val result = rawResult as? FirAnnotationContainer
|
||||||
?: return buildErrorExpression(
|
?: buildErrorExpression(
|
||||||
expression.toFirSourceElement(),
|
expression.toFirSourceElement(),
|
||||||
ConeSimpleDiagnostic("Strange annotated expression: ${rawResult?.render()}", DiagnosticKind.Syntax),
|
ConeNotAnnotationContainer(rawResult?.render() ?: "???")
|
||||||
)
|
)
|
||||||
expression.extractAnnotationsTo(result.annotations as MutableList<FirAnnotationCall>)
|
expression.extractAnnotationsTo(result.annotations as MutableList<FirAnnotationCall>)
|
||||||
return result
|
return result
|
||||||
|
|||||||
+2
-3
@@ -27,11 +27,13 @@ import org.jetbrains.kotlin.fir.visitors.*
|
|||||||
@FirBuilderDsl
|
@FirBuilderDsl
|
||||||
class FirErrorExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBuilder {
|
class FirErrorExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBuilder {
|
||||||
override var source: FirSourceElement? = null
|
override var source: FirSourceElement? = null
|
||||||
|
override val annotations: MutableList<FirAnnotationCall> = mutableListOf()
|
||||||
lateinit var diagnostic: ConeDiagnostic
|
lateinit var diagnostic: ConeDiagnostic
|
||||||
|
|
||||||
override fun build(): FirErrorExpression {
|
override fun build(): FirErrorExpression {
|
||||||
return FirErrorExpressionImpl(
|
return FirErrorExpressionImpl(
|
||||||
source,
|
source,
|
||||||
|
annotations,
|
||||||
diagnostic,
|
diagnostic,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -43,9 +45,6 @@ class FirErrorExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBu
|
|||||||
set(_) {
|
set(_) {
|
||||||
throw IllegalStateException()
|
throw IllegalStateException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Modification of 'annotations' has no impact for FirErrorExpressionBuilder", level = DeprecationLevel.HIDDEN)
|
|
||||||
override val annotations: MutableList<FirAnnotationCall> = mutableListOf()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalContracts::class)
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
|||||||
+4
-1
@@ -21,21 +21,24 @@ import org.jetbrains.kotlin.fir.visitors.*
|
|||||||
|
|
||||||
internal class FirErrorExpressionImpl(
|
internal class FirErrorExpressionImpl(
|
||||||
override val source: FirSourceElement?,
|
override val source: FirSourceElement?,
|
||||||
|
override val annotations: MutableList<FirAnnotationCall>,
|
||||||
override val diagnostic: ConeDiagnostic,
|
override val diagnostic: ConeDiagnostic,
|
||||||
) : FirErrorExpression() {
|
) : FirErrorExpression() {
|
||||||
override var typeRef: FirTypeRef = FirErrorTypeRefImpl(source, null, ConeStubDiagnostic(diagnostic))
|
override var typeRef: FirTypeRef = FirErrorTypeRefImpl(source, null, ConeStubDiagnostic(diagnostic))
|
||||||
override val annotations: List<FirAnnotationCall> get() = emptyList()
|
|
||||||
|
|
||||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||||
typeRef.accept(visitor, data)
|
typeRef.accept(visitor, data)
|
||||||
|
annotations.forEach { it.accept(visitor, data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirErrorExpressionImpl {
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirErrorExpressionImpl {
|
||||||
typeRef = typeRef.transform(transformer, data)
|
typeRef = typeRef.transform(transformer, data)
|
||||||
|
transformAnnotations(transformer, data)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirErrorExpressionImpl {
|
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirErrorExpressionImpl {
|
||||||
|
annotations.transformInplace(transformer, data)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ internal class FirErrorLoopImpl(
|
|||||||
override val diagnostic: ConeDiagnostic,
|
override val diagnostic: ConeDiagnostic,
|
||||||
) : FirErrorLoop() {
|
) : FirErrorLoop() {
|
||||||
override var block: FirBlock = FirEmptyExpressionBlock()
|
override var block: FirBlock = FirEmptyExpressionBlock()
|
||||||
override var condition: FirExpression = FirErrorExpressionImpl(source, ConeStubDiagnostic(diagnostic))
|
override var condition: FirExpression = FirErrorExpressionImpl(source, mutableListOf(), ConeStubDiagnostic(diagnostic))
|
||||||
|
|
||||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||||
annotations.forEach { it.accept(visitor, data) }
|
annotations.forEach { it.accept(visitor, data) }
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ package org.jetbrains.kotlin.fir.diagnostics
|
|||||||
|
|
||||||
class ConeSimpleDiagnostic(override val reason: String, val kind: DiagnosticKind = DiagnosticKind.Other) : ConeDiagnostic()
|
class ConeSimpleDiagnostic(override val reason: String, val kind: DiagnosticKind = DiagnosticKind.Other) : ConeDiagnostic()
|
||||||
|
|
||||||
|
class ConeNotAnnotationContainer(val text: String) : ConeDiagnostic() {
|
||||||
|
override val reason: String get() = "Strange annotated expression: $text"
|
||||||
|
}
|
||||||
|
|
||||||
enum class DiagnosticKind {
|
enum class DiagnosticKind {
|
||||||
Syntax,
|
Syntax,
|
||||||
ExpressionExpected,
|
ExpressionExpected,
|
||||||
|
|||||||
+1
-2
@@ -128,7 +128,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
|||||||
|
|
||||||
impl(errorLoop) {
|
impl(errorLoop) {
|
||||||
default("block", "FirEmptyExpressionBlock()")
|
default("block", "FirEmptyExpressionBlock()")
|
||||||
default("condition", "FirErrorExpressionImpl(source, ConeStubDiagnostic(diagnostic))")
|
default("condition", "FirErrorExpressionImpl(source, mutableListOf(), ConeStubDiagnostic(diagnostic))")
|
||||||
useTypes(emptyExpressionBlock, coneStubDiagnosticType)
|
useTypes(emptyExpressionBlock, coneStubDiagnosticType)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +394,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl(errorExpression) {
|
impl(errorExpression) {
|
||||||
defaultEmptyList("annotations")
|
|
||||||
default("typeRef", "FirErrorTypeRefImpl(source, null, ConeStubDiagnostic(diagnostic))")
|
default("typeRef", "FirErrorTypeRefImpl(source, null, ConeStubDiagnostic(diagnostic))")
|
||||||
useTypes(errorTypeRefImpl, coneStubDiagnosticType)
|
useTypes(errorTypeRefImpl, coneStubDiagnosticType)
|
||||||
}
|
}
|
||||||
|
|||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
// SKIP_ERRORS_BEFORE
|
|
||||||
|
|
||||||
annotation class X(val value: Y, val y: Y)
|
|
||||||
annotation class Y()
|
|
||||||
|
|
||||||
@X(@Y()<!SYNTAX!><!>, y = Y())
|
|
||||||
fun foo1() {
|
|
||||||
}
|
|
||||||
@X(@Y()<!SYNTAX!><!>, y = @Y()<!SYNTAX!><!>)
|
|
||||||
fun foo2() {
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// SKIP_ERRORS_BEFORE
|
// SKIP_ERRORS_BEFORE
|
||||||
|
|
||||||
annotation class X(val value: Y, val y: Y)
|
annotation class X(val value: Y, val y: Y)
|
||||||
|
|||||||
Reference in New Issue
Block a user