[FIR] Refactor DiagnosticKind.Syntax into ConeSyntaxDiagnostic

#KT-58469
This commit is contained in:
Kirill Rakhman
2023-05-08 10:29:39 +02:00
committed by Space Team
parent 7a9021aa6b
commit 93ee4d7ce7
11 changed files with 76 additions and 76 deletions
@@ -16,11 +16,8 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.declarations.FirVariable import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSyntaxDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.isError import org.jetbrains.kotlin.fir.references.isError
import org.jetbrains.kotlin.fir.references.toResolvedVariableSymbol import org.jetbrains.kotlin.fir.references.toResolvedVariableSymbol
import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolve.diagnostics.*
@@ -97,7 +94,7 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
val needToReport = val needToReport =
when (initializer) { when (initializer) {
null -> true null -> true
is FirErrorExpression -> (initializer.diagnostic as? ConeSimpleDiagnostic)?.kind == DiagnosticKind.Syntax is FirErrorExpression -> initializer.diagnostic is ConeSyntaxDiagnostic
else -> false else -> false
} }
if (needToReport) { if (needToReport) {
@@ -100,9 +100,10 @@ private fun ConeDiagnostic.toKtDiagnostic(
is ConeNoTypeArgumentsOnRhsError -> is ConeNoTypeArgumentsOnRhsError ->
FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.createOn(qualifiedAccessSource ?: source, this.desiredCount, this.symbol) FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.createOn(qualifiedAccessSource ?: source, this.desiredCount, this.symbol)
is ConeSyntaxDiagnostic -> FirSyntaxErrors.SYNTAX.createOn(qualifiedAccessSource ?: source, reason)
is ConeSimpleDiagnostic -> when { is ConeSimpleDiagnostic -> when {
source.kind is KtFakeSourceElementKind && source.kind != KtFakeSourceElementKind.ReferenceInAtomicQualifiedAccess -> null source.kind is KtFakeSourceElementKind && source.kind != KtFakeSourceElementKind.ReferenceInAtomicQualifiedAccess -> null
kind == DiagnosticKind.Syntax -> FirSyntaxErrors.SYNTAX.createOn(qualifiedAccessSource ?: source, reason)
else -> this.getFactory(source).createOn(qualifiedAccessSource ?: source) else -> this.getFactory(source).createOn(qualifiedAccessSource ?: source)
} }
@@ -534,7 +535,6 @@ private fun ConeSimpleDiagnostic.getFactory(source: KtSourceElement): KtDiagnost
DiagnosticKind.UnresolvedSupertype, DiagnosticKind.UnresolvedSupertype,
DiagnosticKind.UnresolvedExpandedType, DiagnosticKind.UnresolvedExpandedType,
DiagnosticKind.Other -> FirErrors.OTHER_ERROR DiagnosticKind.Other -> FirErrors.OTHER_ERROR
DiagnosticKind.Syntax -> error("Must not be called on `Syntax` because a message is required.")
} }
} }
@@ -29,10 +29,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.DanglingTypeConstraint
import org.jetbrains.kotlin.fir.declarations.utils.addDeclarations import org.jetbrains.kotlin.fir.declarations.utils.addDeclarations
import org.jetbrains.kotlin.fir.declarations.utils.addDefaultBoundIfNecessary import org.jetbrains.kotlin.fir.declarations.utils.addDefaultBoundIfNecessary
import org.jetbrains.kotlin.fir.declarations.utils.danglingTypeConstraints import org.jetbrains.kotlin.fir.declarations.utils.danglingTypeConstraints
import org.jetbrains.kotlin.fir.diagnostics.ConeDanglingModifierOnTopLevel import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
@@ -47,10 +44,13 @@ import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
import org.jetbrains.kotlin.fir.types.builder.* import org.jetbrains.kotlin.fir.types.builder.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
import org.jetbrains.kotlin.fir.types.impl.FirQualifierPartImpl import org.jetbrains.kotlin.fir.types.impl.FirQualifierPartImpl
import org.jetbrains.kotlin.fir.types.impl.FirTypeArgumentListImpl import org.jetbrains.kotlin.fir.types.impl.FirTypeArgumentListImpl
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
@@ -1329,7 +1329,7 @@ class DeclarationsConverter(
entries, entries,
firExpression ?: buildErrorExpression( firExpression ?: buildErrorExpression(
null, null,
ConeSimpleDiagnostic("Initializer required for destructuring declaration", DiagnosticKind.Syntax) ConeSyntaxDiagnostic("Initializer required for destructuring declaration")
), ),
source, source,
modifiers modifiers
@@ -1875,7 +1875,7 @@ class DeclarationsConverter(
} }
val calculatedFirExpression = firExpression ?: buildErrorExpression( val calculatedFirExpression = firExpression ?: buildErrorExpression(
explicitDelegation.toFirSourceElement(), ConeSimpleDiagnostic("Should have delegate", DiagnosticKind.Syntax) explicitDelegation.toFirSourceElement(), ConeSyntaxDiagnostic("Should have delegate")
) )
delegateFieldsMap.put( delegateFieldsMap.put(
@@ -2028,14 +2028,14 @@ class DeclarationsConverter(
CONTEXT_RECEIVER_LIST, TokenType.ERROR_ELEMENT -> firType = CONTEXT_RECEIVER_LIST, TokenType.ERROR_ELEMENT -> firType =
buildErrorTypeRef { buildErrorTypeRef {
source = typeRefSource source = typeRefSource
diagnostic = ConeSimpleDiagnostic("Unwrapped type is null", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Unwrapped type is null")
} }
} }
} }
val calculatedFirType = firType ?: buildErrorTypeRef { val calculatedFirType = firType ?: buildErrorTypeRef {
source = typeRefSource source = typeRefSource
diagnostic = ConeSimpleDiagnostic("Incomplete code", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Incomplete code")
} }
for (modifierList in allTypeModifiers) { for (modifierList in allTypeModifiers) {
@@ -2057,7 +2057,7 @@ class DeclarationsConverter(
if (children.size != 2) { if (children.size != 2) {
return buildErrorTypeRef { return buildErrorTypeRef {
source = typeRefSource source = typeRefSource
diagnostic = ConeSimpleDiagnostic("Wrong code", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Wrong code")
} }
} }
@@ -2140,7 +2140,7 @@ class DeclarationsConverter(
if (identifier == null) if (identifier == null)
return buildErrorTypeRef { return buildErrorTypeRef {
source = typeRefSource source = typeRefSource
diagnostic = ConeSimpleDiagnostic("Incomplete user type", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Incomplete user type")
} }
val qualifierPart = FirQualifierPartImpl( val qualifierPart = FirQualifierPartImpl(
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
import org.jetbrains.kotlin.fir.expressions.impl.buildSingleExpressionBlock import org.jetbrains.kotlin.fir.expressions.impl.buildSingleExpressionBlock
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter
import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry
import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference
@@ -210,7 +209,7 @@ class ExpressionsConverter(
statements.addAll(0, destructuringStatements) statements.addAll(0, destructuringStatements)
}.build() }.build()
} else { } else {
buildSingleExpressionBlock(buildErrorExpression(null, ConeSimpleDiagnostic("Lambda has no body", DiagnosticKind.Syntax))) buildSingleExpressionBlock(buildErrorExpression(null, ConeSyntaxDiagnostic("Lambda has no body")))
} }
context.firFunctionTargets.removeLast() context.firFunctionTargets.removeLast()
}.also { }.also {
@@ -261,7 +260,7 @@ class ExpressionsConverter(
if (rightArg != null) if (rightArg != null)
getAsFirExpression<FirExpression>(rightArg, "No right operand") getAsFirExpression<FirExpression>(rightArg, "No right operand")
else else
buildErrorExpression(null, ConeSimpleDiagnostic("No right operand", DiagnosticKind.Syntax)) buildErrorExpression(null, ConeSyntaxDiagnostic("No right operand"))
val leftArgAsFir = getAsFirExpression<FirExpression>(leftArgNode, "No left operand") val leftArgAsFir = getAsFirExpression<FirExpression>(leftArgNode, "No left operand")
@@ -336,7 +335,7 @@ class ExpressionsConverter(
operation = operationTokenName.toFirOperation() operation = operationTokenName.toFirOperation()
conversionTypeRef = firType conversionTypeRef = firType
argumentList = buildUnaryArgumentList( argumentList = buildUnaryArgumentList(
leftArgAsFir ?: buildErrorExpression(null, ConeSimpleDiagnostic("No left operand", DiagnosticKind.Syntax)) leftArgAsFir ?: buildErrorExpression(null, ConeSyntaxDiagnostic("No left operand"))
) )
} }
} }
@@ -466,7 +465,7 @@ class ExpressionsConverter(
source = classLiteralExpression.toFirSourceElement() source = classLiteralExpression.toFirSourceElement()
argumentList = buildUnaryArgumentList( argumentList = buildUnaryArgumentList(
firReceiverExpression firReceiverExpression
?: buildErrorExpression(null, ConeSimpleDiagnostic("No receiver in class literal", DiagnosticKind.Syntax)) ?: buildErrorExpression(null, ConeSyntaxDiagnostic("No receiver in class literal"))
) )
} }
} }
@@ -567,14 +566,14 @@ class ExpressionsConverter(
this.receiver = receiver this.receiver = receiver
this.selector = errorExpression this.selector = errorExpression
source = dotQualifiedExpression.toFirSourceElement() source = dotQualifiedExpression.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Qualified expression with unexpected selector", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Qualified expression with unexpected selector")
} }
} }
} }
return result ?: buildErrorExpression { return result ?: buildErrorExpression {
source = null source = null
diagnostic = ConeSimpleDiagnostic("Qualified expression without selector", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Qualified expression without selector")
// if there is no selector, we still want to resolve the receiver // if there is no selector, we still want to resolve the receiver
expression = firReceiver expression = firReceiver
@@ -653,7 +652,7 @@ class ExpressionsConverter(
else -> CalleeAndReceiver( else -> CalleeAndReceiver(
buildErrorNamedReference { buildErrorNamedReference {
this.source = source this.source = source
diagnostic = ConeSimpleDiagnostic("Call has no callee", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Call has no callee")
} }
) )
} }
@@ -692,7 +691,7 @@ class ExpressionsConverter(
this?.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) { this?.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) {
firExpression = getAsFirExpression(it, errorReason) firExpression = getAsFirExpression(it, errorReason)
} }
return firExpression ?: buildErrorExpression(null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.Syntax)) return firExpression ?: buildErrorExpression(null, ConeSyntaxDiagnostic(errorReason))
} }
/** /**
@@ -822,7 +821,7 @@ class ExpressionsConverter(
val calculatedFirExpression = firExpression ?: buildErrorExpression( val calculatedFirExpression = firExpression ?: buildErrorExpression(
source = null, source = null,
ConeSimpleDiagnostic("No expression in condition with expression", DiagnosticKind.Syntax) ConeSyntaxDiagnostic("No expression in condition with expression")
) )
if (whenRefWithSubject == null) { if (whenRefWithSubject == null) {
@@ -879,7 +878,7 @@ class ExpressionsConverter(
val calculatedFirExpression = firExpression ?: buildErrorExpression( val calculatedFirExpression = firExpression ?: buildErrorExpression(
null, null,
ConeSimpleDiagnostic("No range in condition with range", DiagnosticKind.Syntax) ConeSyntaxDiagnostic("No range in condition with range")
) )
return calculatedFirExpression.generateContainsOperation( return calculatedFirExpression.generateContainsOperation(
@@ -949,7 +948,7 @@ class ExpressionsConverter(
name = if (isGet) OperatorNameConventions.GET else OperatorNameConventions.SET name = if (isGet) OperatorNameConventions.GET else OperatorNameConventions.SET
} }
explicitReceiver = explicitReceiver =
firExpression ?: buildErrorExpression(null, ConeSimpleDiagnostic("No array expression", DiagnosticKind.Syntax)) firExpression ?: buildErrorExpression(null, ConeSyntaxDiagnostic("No array expression"))
argumentList = buildArgumentList { argumentList = buildArgumentList {
arguments += indices arguments += indices
getArgument?.let { arguments += it } getArgument?.let { arguments += it }
@@ -1038,7 +1037,7 @@ class ExpressionsConverter(
} }
} }
condition = condition =
firCondition ?: buildErrorExpression(null, ConeSimpleDiagnostic("No condition in do-while loop", DiagnosticKind.Syntax)) firCondition ?: buildErrorExpression(null, ConeSyntaxDiagnostic("No condition in do-while loop"))
}.configure(target) { convertLoopBody(block) } }.configure(target) { convertLoopBody(block) }
} }
@@ -1060,7 +1059,7 @@ class ExpressionsConverter(
return FirWhileLoopBuilder().apply { return FirWhileLoopBuilder().apply {
source = whileLoop.toFirSourceElement() source = whileLoop.toFirSourceElement()
condition = condition =
firCondition ?: buildErrorExpression(null, ConeSimpleDiagnostic("No condition in while loop", DiagnosticKind.Syntax)) firCondition ?: buildErrorExpression(null, ConeSyntaxDiagnostic("No condition in while loop"))
// break/continue in the while loop condition will refer to an outer loop if any. // break/continue in the while loop condition will refer to an outer loop if any.
// So, prepare the loop target after building the condition. // So, prepare the loop target after building the condition.
target = prepareTarget(whileLoop) target = prepareTarget(whileLoop)
@@ -1084,7 +1083,7 @@ class ExpressionsConverter(
} }
val calculatedRangeExpression = val calculatedRangeExpression =
rangeExpression ?: buildErrorExpression(null, ConeSimpleDiagnostic("No range in for loop", DiagnosticKind.Syntax)) rangeExpression ?: buildErrorExpression(null, ConeSyntaxDiagnostic("No range in for loop"))
val fakeSource = forLoop.toFirSourceElement(KtFakeSourceElementKind.DesugaredForLoop) val fakeSource = forLoop.toFirSourceElement(KtFakeSourceElementKind.DesugaredForLoop)
val target: FirLoopTarget val target: FirLoopTarget
// NB: FirForLoopChecker relies on this block existence and structure // NB: FirForLoopChecker relies on this block existence and structure
@@ -1271,7 +1270,7 @@ class ExpressionsConverter(
source = thenBlock?.toFirSourceElement() source = thenBlock?.toFirSourceElement()
condition = firCondition ?: buildErrorExpression( condition = firCondition ?: buildErrorExpression(
null, null,
ConeSimpleDiagnostic("If statement should have condition", DiagnosticKind.Syntax) ConeSyntaxDiagnostic("If statement should have condition")
) )
result = trueBranch result = trueBranch
} }
@@ -1393,7 +1392,7 @@ class ExpressionsConverter(
return buildThrowExpression { return buildThrowExpression {
source = throwExpression.toFirSourceElement() source = throwExpression.toFirSourceElement()
exception = firExpression ?: buildErrorExpression(null, ConeSimpleDiagnostic("Nothing to throw", DiagnosticKind.Syntax)) exception = firExpression ?: buildErrorExpression(null, ConeSyntaxDiagnostic("Nothing to throw"))
} }
} }
@@ -1466,7 +1465,7 @@ class ExpressionsConverter(
} }
} }
val calculatedFirExpression = val calculatedFirExpression =
firExpression ?: buildErrorExpression(null, ConeSimpleDiagnostic("Argument is absent", DiagnosticKind.Syntax)) firExpression ?: buildErrorExpression(null, ConeSyntaxDiagnostic("Argument is absent"))
return when { return when {
identifier != null -> buildNamedArgumentExpression { identifier != null -> buildNamedArgumentExpression {
source = valueArgument.toFirSourceElement() source = valueArgument.toFirSourceElement()
@@ -28,8 +28,7 @@ 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.declarations.utils.fromPrimaryConstructor import org.jetbrains.kotlin.fir.declarations.utils.fromPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.utils.isFromVararg import org.jetbrains.kotlin.fir.declarations.utils.isFromVararg
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSyntaxDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.builder.buildPropertyAccessExpression
@@ -106,7 +105,7 @@ class ValueParameter(
val name = this.firValueParameter.name val name = this.firValueParameter.name
var type = this.firValueParameter.returnTypeRef var type = this.firValueParameter.returnTypeRef
if (type is FirImplicitTypeRef) { if (type is FirImplicitTypeRef) {
type = buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("Incomplete code", DiagnosticKind.Syntax) } type = buildErrorTypeRef { diagnostic = ConeSyntaxDiagnostic("Incomplete code") }
} }
return buildProperty { return buildProperty {
@@ -7,8 +7,7 @@ package org.jetbrains.kotlin.fir.lightTree.fir
import com.intellij.lang.LighterASTNode import com.intellij.lang.LighterASTNode
import org.jetbrains.kotlin.fir.builder.buildBalancedOrExpressionTree import org.jetbrains.kotlin.fir.builder.buildBalancedOrExpressionTree
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.ConeSyntaxDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.buildErrorExpression import org.jetbrains.kotlin.fir.expressions.buildErrorExpression
@@ -26,7 +25,7 @@ data class WhenEntry(
fun toFirWhenConditionWithoutSubject(): FirExpression { fun toFirWhenConditionWithoutSubject(): FirExpression {
return when (val condition = conditions.firstOrNull()) { return when (val condition = conditions.firstOrNull()) {
null -> buildErrorExpression(null, ConeSimpleDiagnostic("No expression in condition with expression", DiagnosticKind.Syntax)) null -> buildErrorExpression(null, ConeSyntaxDiagnostic("No expression in condition with expression"))
else -> condition else -> condition
} }
} }
@@ -14,8 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirVariable import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSyntaxDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
@@ -62,7 +61,7 @@ internal fun KtWhenCondition.toFirWhenCondition(
} }
} }
else -> { else -> {
buildErrorExpression(firSubjectSource, ConeSimpleDiagnostic("Unsupported when condition: ${this.javaClass}", DiagnosticKind.Syntax)) buildErrorExpression(firSubjectSource, ConeSyntaxDiagnostic("Unsupported when condition: ${this.javaClass}"))
} }
} }
} }
@@ -253,8 +253,8 @@ open class RawFirBuilder(
private fun KtTypeReference?.toFirOrErrorType(): FirTypeRef = private fun KtTypeReference?.toFirOrErrorType(): FirTypeRef =
convertSafe() ?: buildErrorTypeRef { convertSafe() ?: buildErrorTypeRef {
source = this@toFirOrErrorType?.toFirSourceElement() source = this@toFirOrErrorType?.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic( diagnostic = ConeSyntaxDiagnostic(
if (this@toFirOrErrorType == null) "Incomplete code" else "Conversion failed", DiagnosticKind.Syntax if (this@toFirOrErrorType == null) "Incomplete code" else "Conversion failed"
) )
} }
@@ -265,9 +265,11 @@ open class RawFirBuilder(
private fun KtElement?.toFirExpression( private fun KtElement?.toFirExpression(
errorReason: String, errorReason: String,
kind: DiagnosticKind = DiagnosticKind.ExpressionExpected kind: DiagnosticKind = DiagnosticKind.ExpressionExpected
): FirExpression { ): FirExpression = toFirExpression { ConeSimpleDiagnostic(errorReason, kind) }
private inline fun KtElement?.toFirExpression(diagnosticFn: () -> ConeDiagnostic): FirExpression {
if (this == null) { if (this == null) {
return buildErrorExpression(source = null, ConeSimpleDiagnostic(errorReason, kind)) return buildErrorExpression(source = null, diagnosticFn())
} }
val result = when (val fir = convertElement(this)) { val result = when (val fir = convertElement(this)) {
@@ -275,13 +277,16 @@ open class RawFirBuilder(
else -> { else -> {
return buildErrorExpression { return buildErrorExpression {
nonExpressionElement = fir nonExpressionElement = fir
diagnostic = ConeSimpleDiagnostic(errorReason, kind) diagnostic = diagnosticFn()
source = toFirSourceElement() source = toFirSourceElement()
} }
} }
} }
return toFirExpression(result)
}
private fun KtElement.toFirExpression(result: FirExpression): FirExpression {
val callExpressionCallee = (this as? KtCallExpression)?.calleeExpression?.unwrapParenthesesLabelsAndAnnotations() val callExpressionCallee = (this as? KtCallExpression)?.calleeExpression?.unwrapParenthesesLabelsAndAnnotations()
if (this is KtNameReferenceExpression || if (this is KtNameReferenceExpression ||
@@ -307,7 +312,7 @@ open class RawFirBuilder(
is FirStatement -> fir is FirStatement -> fir
else -> buildErrorExpression { else -> buildErrorExpression {
nonExpressionElement = fir nonExpressionElement = fir
diagnostic = ConeSimpleDiagnostic(errorReasonLazy(), DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic(errorReasonLazy())
source = toFirSourceElement() source = toFirSourceElement()
} }
} }
@@ -393,7 +398,7 @@ open class RawFirBuilder(
if (this == null) { if (this == null) {
return buildErrorExpression( return buildErrorExpression(
source = null, source = null,
ConeSimpleDiagnostic("No argument given", DiagnosticKind.Syntax), ConeSyntaxDiagnostic("No argument given"),
) )
} }
val name = this.getArgumentName()?.asName val name = this.getArgumentName()?.asName
@@ -1614,7 +1619,7 @@ open class RawFirBuilder(
} }
val ktBody = literal.bodyExpression val ktBody = literal.bodyExpression
body = if (ktBody == null) { body = if (ktBody == null) {
val errorExpression = buildErrorExpression(source, ConeSimpleDiagnostic("Lambda has no body", DiagnosticKind.Syntax)) val errorExpression = buildErrorExpression(source, ConeSyntaxDiagnostic("Lambda has no body"))
FirSingleExpressionBlock(errorExpression.toReturn()) FirSingleExpressionBlock(errorExpression.toReturn())
} else { } else {
configureBlockWithoutBuilding(ktBody).apply { configureBlockWithoutBuilding(ktBody).apply {
@@ -1959,7 +1964,7 @@ open class RawFirBuilder(
} else { } else {
FirErrorTypeRefBuilder().apply { FirErrorTypeRefBuilder().apply {
this.source = source this.source = source
diagnostic = ConeSimpleDiagnostic("Incomplete user type", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Incomplete user type")
} }
} }
} }
@@ -1997,7 +2002,7 @@ open class RawFirBuilder(
} }
null -> FirErrorTypeRefBuilder().apply { null -> FirErrorTypeRefBuilder().apply {
this.source = source this.source = source
diagnostic = ConeSimpleDiagnostic("Incomplete code", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Incomplete code")
} }
else -> throw AssertionError("Unexpected type element: ${unwrappedElement.text}") else -> throw AssertionError("Unexpected type element: ${unwrappedElement.text}")
} }
@@ -2538,7 +2543,7 @@ open class RawFirBuilder(
null -> { null -> {
CalleeAndReceiver( CalleeAndReceiver(
buildErrorNamedReference { diagnostic = ConeSimpleDiagnostic("Call has no callee", DiagnosticKind.Syntax) } buildErrorNamedReference { diagnostic = ConeSyntaxDiagnostic("Call has no callee") }
) )
} }
@@ -2620,7 +2625,7 @@ open class RawFirBuilder(
val selector = expression.selectorExpression val selector = expression.selectorExpression
?: return buildErrorExpression { ?: return buildErrorExpression {
source = expression.toFirSourceElement() source = expression.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Qualified expression without selector", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Qualified expression without selector")
// if there is no selector, we still want to resolve the receiver // if there is no selector, we still want to resolve the receiver
this.expression = receiver this.expression = receiver
@@ -2644,7 +2649,7 @@ open class RawFirBuilder(
this.receiver = receiver this.receiver = receiver
this.selector = firSelector this.selector = firSelector
source = expression.toFirSourceElement() source = expression.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Qualified expression with unexpected selector", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Qualified expression with unexpected selector")
} }
} }
return firSelector return firSelector
@@ -2679,7 +2684,7 @@ open class RawFirBuilder(
return expression.expression?.accept(this, data) return expression.expression?.accept(this, data)
?: buildErrorExpression( ?: buildErrorExpression(
expression.toFirSourceElement(), expression.toFirSourceElement(),
ConeSimpleDiagnostic("Empty parentheses", DiagnosticKind.Syntax) ConeSyntaxDiagnostic("Empty parentheses")
) )
} }
@@ -2726,10 +2731,7 @@ open class RawFirBuilder(
baseModuleData, baseModuleData,
multiDeclaration.toFirSourceElement(), multiDeclaration.toFirSourceElement(),
"destruct", "destruct",
multiDeclaration.initializer.toFirExpression( multiDeclaration.initializer.toFirExpression { ConeSyntaxDiagnostic("Initializer required for destructuring declaration") },
"Initializer required for destructuring declaration",
DiagnosticKind.Syntax
),
extractAnnotationsTo = { extractAnnotationsTo(it) } extractAnnotationsTo = { extractAnnotationsTo(it) }
) )
return generateDestructuringBlock( return generateDestructuringBlock(
@@ -22,7 +22,9 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.diagnostics.* import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.references.builder.* import org.jetbrains.kotlin.fir.references.builder.buildImplicitThisReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
@@ -460,7 +462,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
hasExpressions = true hasExpressions = true
buildErrorExpression { buildErrorExpression {
source = entry.toFirSourceElement() source = entry.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Incorrect template entry: ${entry.asText}", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Incorrect template entry: ${entry.asText}")
} }
} }
} }
@@ -482,7 +484,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
convert: T.() -> FirExpression convert: T.() -> FirExpression
): FirExpression { ): FirExpression {
val unwrappedReceiver = receiver.unwrap() ?: return buildErrorExpression { val unwrappedReceiver = receiver.unwrap() ?: return buildErrorExpression {
diagnostic = ConeSimpleDiagnostic("Inc/dec without operand", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Inc/dec without operand")
} }
if (unwrappedReceiver.elementType == ARRAY_ACCESS_EXPRESSION) { if (unwrappedReceiver.elementType == ARRAY_ACCESS_EXPRESSION) {
@@ -668,7 +670,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
): FirExpression { ): FirExpression {
val receiverFir = receiver?.convert() ?: buildErrorExpression { val receiverFir = receiver?.convert() ?: buildErrorExpression {
source = sourceElementForError source = sourceElementForError
diagnostic = ConeSimpleDiagnostic("No receiver expression", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("No receiver expression")
} }
if (receiverFir is FirSafeCallExpression) { if (receiverFir is FirSafeCallExpression) {
@@ -677,7 +679,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
init( init(
receiverFir.selector as? FirExpression ?: buildErrorExpression { receiverFir.selector as? FirExpression ?: buildErrorExpression {
source = sourceElementForError source = sourceElementForError
diagnostic = ConeSimpleDiagnostic("Safe call selector expected to be an expression here", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Safe call selector expected to be an expression here")
} }
) )
} }
@@ -706,7 +708,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
convert: T.() -> FirExpression convert: T.() -> FirExpression
): FirStatement { ): FirStatement {
val unwrappedLhs = this.unwrap() ?: return buildErrorExpression { val unwrappedLhs = this.unwrap() ?: return buildErrorExpression {
diagnostic = ConeSimpleDiagnostic("Inc/dec without operand", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Inc/dec without operand")
} }
val tokenType = unwrappedLhs.elementType val tokenType = unwrappedLhs.elementType
@@ -830,7 +832,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
this.lhsGetCall = receiver this.lhsGetCall = receiver
this.rhs = rhs?.convert() ?: buildErrorExpression( this.rhs = rhs?.convert() ?: buildErrorExpression(
null, null,
ConeSimpleDiagnostic("No value for array set", DiagnosticKind.Syntax) ConeSyntaxDiagnostic("No value for array set")
) )
this.arrayAccessSource = arrayAccessSource this.arrayAccessSource = arrayAccessSource
this.annotations += annotations this.annotations += annotations
@@ -944,7 +946,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
element element
} }
} else { } else {
buildErrorExpression(elementSource, ConeSimpleDiagnostic("Empty label", DiagnosticKind.Syntax)) buildErrorExpression(elementSource, ConeSyntaxDiagnostic("Empty label"))
} }
} }
@@ -22,7 +22,9 @@ import org.jetbrains.kotlin.fir.extensions.assignAltererExtensions
import org.jetbrains.kotlin.fir.extensions.expressionResolutionExtensions import org.jetbrains.kotlin.fir.extensions.expressionResolutionExtensions
import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.references.builder.* import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildExplicitSuperReference
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.calls.*
@@ -701,7 +703,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val expression = when (originalExpression) { val expression = when (originalExpression) {
is FirSafeCallExpression -> originalExpression.selector as? FirExpression ?: buildErrorExpression { is FirSafeCallExpression -> originalExpression.selector as? FirExpression ?: buildErrorExpression {
source = originalExpression.source source = originalExpression.source
diagnostic = ConeSimpleDiagnostic("Safe call selector expected to be an expression here", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("Safe call selector expected to be an expression here")
} }
else -> originalExpression else -> originalExpression
} }
@@ -1519,7 +1521,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
initializer = lhsGetCall.explicitReceiver ?: buildErrorExpression { initializer = lhsGetCall.explicitReceiver ?: buildErrorExpression {
source = augmentedArraySetCall.source source = augmentedArraySetCall.source
?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment) ?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
diagnostic = ConeSimpleDiagnostic("No receiver for array access", DiagnosticKind.Syntax) diagnostic = ConeSyntaxDiagnostic("No receiver for array access")
} }
) )
@@ -15,6 +15,8 @@ import org.jetbrains.kotlin.name.Name
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 ConeSyntaxDiagnostic(override val reason: String) : ConeDiagnostic
class ConeNotAnnotationContainer(val text: String) : ConeDiagnostic { class ConeNotAnnotationContainer(val text: String) : ConeDiagnostic {
override val reason: String get() = "Strange annotated expression: $text" override val reason: String get() = "Strange annotated expression: $text"
} }
@@ -70,7 +72,6 @@ class ConeAmbiguousFunctionTypeKinds(val kinds: List<FunctionTypeKind>) : ConeDi
} }
enum class DiagnosticKind { enum class DiagnosticKind {
Syntax,
ExpressionExpected, ExpressionExpected,
NotLoopLabel, NotLoopLabel,
JumpOutsideLoop, JumpOutsideLoop,