[FIR] Get rid of unnecessary creation of error expression for LightTree, other minor simplifications

This commit is contained in:
Ivan Kochurkin
2021-06-25 17:29:26 +03:00
parent 9f7a8c3948
commit 9b71175902
4 changed files with 122 additions and 73 deletions
@@ -83,16 +83,17 @@ inline fun isClassLocal(classNode: LighterASTNode, getParent: LighterASTNode.()
while (currentNode != null) { while (currentNode != null) {
val tokenType = currentNode.tokenType val tokenType = currentNode.tokenType
val parent = currentNode.getParent() val parent = currentNode.getParent()
val parentTokenType = parent?.tokenType
if (tokenType == PROPERTY || tokenType == FUN) { if (tokenType == PROPERTY || tokenType == FUN) {
val grandParent = parent?.getParent() val grandParent = parent?.getParent()
when { when {
parent?.tokenType == KT_FILE -> return true parentTokenType == KT_FILE -> return true
parent?.tokenType == CLASS_BODY && !(grandParent?.tokenType == OBJECT_DECLARATION && grandParent?.getParent()?.tokenType == OBJECT_LITERAL) -> return true parentTokenType == CLASS_BODY && !(grandParent?.tokenType == OBJECT_DECLARATION && grandParent?.getParent()?.tokenType == OBJECT_LITERAL) -> return true
parent?.tokenType == BLOCK && grandParent?.tokenType == SCRIPT -> return true parentTokenType == BLOCK && grandParent?.tokenType == SCRIPT -> return true
} }
} }
// NB: enum entry nested classes are considered local by FIR design (see discussion in KT-45115) // NB: enum entry nested classes are considered local by FIR design (see discussion in KT-45115)
if (parent?.tokenType == ENUM_ENTRY) { if (parentTokenType == ENUM_ENTRY) {
return true return true
} }
if (tokenType == BLOCK) { if (tokenType == BLOCK) {
@@ -226,30 +226,30 @@ class DeclarationsConverter(
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeModifierList * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeModifierList
*/ */
private fun convertTypeModifierList(modifiers: LighterASTNode): TypeModifier { private fun convertTypeModifierList(modifiers: LighterASTNode): TypeModifier {
val typeModifierList = TypeModifier() val typeModifier = TypeModifier()
modifiers.forEachChildren { modifiers.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
ANNOTATION -> typeModifierList.annotations += convertAnnotation(it) ANNOTATION -> typeModifier.annotations += convertAnnotation(it)
ANNOTATION_ENTRY -> typeModifierList.annotations += convertAnnotationEntry(it) ANNOTATION_ENTRY -> typeModifier.annotations += convertAnnotationEntry(it)
is KtModifierKeywordToken -> typeModifierList.addModifier(it) is KtModifierKeywordToken -> typeModifier.addModifier(it)
} }
} }
return typeModifierList return typeModifier
} }
/** /**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeArgumentModifierList * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeArgumentModifierList
*/ */
private fun convertTypeArgumentModifierList(modifiers: LighterASTNode): TypeProjectionModifier { private fun convertTypeArgumentModifierList(modifiers: LighterASTNode): TypeProjectionModifier {
val typeArgumentModifierList = TypeProjectionModifier() val typeArgumentModifier = TypeProjectionModifier()
modifiers.forEachChildren { modifiers.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
ANNOTATION -> typeArgumentModifierList.annotations += convertAnnotation(it) ANNOTATION -> typeArgumentModifier.annotations += convertAnnotation(it)
ANNOTATION_ENTRY -> typeArgumentModifierList.annotations += convertAnnotationEntry(it) ANNOTATION_ENTRY -> typeArgumentModifier.annotations += convertAnnotationEntry(it)
is KtModifierKeywordToken -> typeArgumentModifierList.addModifier(it) is KtModifierKeywordToken -> typeArgumentModifier.addModifier(it)
} }
} }
return typeArgumentModifierList return typeArgumentModifier
} }
/** /**
@@ -1143,8 +1143,7 @@ class DeclarationsConverter(
var isVar = false var isVar = false
val entries = mutableListOf<FirVariable?>() val entries = mutableListOf<FirVariable?>()
val source = destructingDeclaration.toFirSourceElement() val source = destructingDeclaration.toFirSourceElement()
var firExpression: FirExpression = var firExpression: FirExpression? = null
buildErrorExpression(null, ConeSimpleDiagnostic("Initializer required for destructuring declaration", DiagnosticKind.Syntax))
destructingDeclaration.forEachChildren { destructingDeclaration.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
VAR_KEYWORD -> isVar = true VAR_KEYWORD -> isVar = true
@@ -1154,7 +1153,15 @@ class DeclarationsConverter(
} }
} }
return DestructuringDeclaration(isVar, entries, firExpression, source) return DestructuringDeclaration(
isVar,
entries,
firExpression ?: buildErrorExpression(
null,
ConeSimpleDiagnostic("Initializer required for destructuring declaration", DiagnosticKind.Syntax)
),
source
)
} }
/** /**
@@ -1583,9 +1590,7 @@ class DeclarationsConverter(
*/ */
private fun convertExplicitDelegation(explicitDelegation: LighterASTNode, delegateFields: MutableList<FirField>): FirTypeRef { private fun convertExplicitDelegation(explicitDelegation: LighterASTNode, delegateFields: MutableList<FirField>): FirTypeRef {
lateinit var firTypeRef: FirTypeRef lateinit var firTypeRef: FirTypeRef
var firExpression: FirExpression? = buildErrorExpression( var firExpression: FirExpression? = null
explicitDelegation.toFirSourceElement(), ConeSimpleDiagnostic("Should have delegate", DiagnosticKind.Syntax)
)
explicitDelegation.forEachChildren { explicitDelegation.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
TYPE_REFERENCE -> firTypeRef = convertType(it) TYPE_REFERENCE -> firTypeRef = convertType(it)
@@ -1593,10 +1598,14 @@ class DeclarationsConverter(
} }
} }
val calculatedFirExpression = firExpression ?: buildErrorExpression(
explicitDelegation.toFirSourceElement(), ConeSimpleDiagnostic("Should have delegate", DiagnosticKind.Syntax)
)
val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>") val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>")
delegateFields.add( delegateFields.add(
buildField { buildField {
source = firExpression!!.source?.fakeElement(FirFakeSourceElementKind.ClassDelegationField) source = calculatedFirExpression.source?.fakeElement(FirFakeSourceElementKind.ClassDelegationField)
moduleData = baseModuleData moduleData = baseModuleData
origin = FirDeclarationOrigin.Synthetic origin = FirDeclarationOrigin.Synthetic
name = delegateName name = delegateName
@@ -1604,7 +1613,7 @@ class DeclarationsConverter(
symbol = FirFieldSymbol(CallableId(name)) symbol = FirFieldSymbol(CallableId(name))
isVar = false isVar = false
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL) status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL)
initializer = firExpression initializer = calculatedFirExpression
} }
) )
return firTypeRef return firTypeRef
@@ -1719,10 +1728,7 @@ class DeclarationsConverter(
// TODO: Report MODIFIER_LIST_NOT_ALLOWED error when there are multiple modifier lists. How do we report on each of them? // TODO: Report MODIFIER_LIST_NOT_ALLOWED error when there are multiple modifier lists. How do we report on each of them?
val allTypeModifiers = mutableListOf<TypeModifier>() val allTypeModifiers = mutableListOf<TypeModifier>()
var firType: FirTypeRef = buildErrorTypeRef { var firType: FirTypeRef? = null
source = typeRefSource
diagnostic = ConeSimpleDiagnostic("Incomplete code", DiagnosticKind.Syntax)
}
type.forEachChildren { type.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
TYPE_REFERENCE -> firType = convertType(it) TYPE_REFERENCE -> firType = convertType(it)
@@ -1743,10 +1749,15 @@ class DeclarationsConverter(
} }
} }
for (modifierList in allTypeModifiers) { val calculatedFirType = firType ?: buildErrorTypeRef {
(firType.annotations as MutableList<FirAnnotationCall>) += modifierList.annotations source = typeRefSource
diagnostic = ConeSimpleDiagnostic("Incomplete code", DiagnosticKind.Syntax)
} }
return firType
for (modifierList in allTypeModifiers) {
(calculatedFirType.annotations as MutableList<FirAnnotationCall>) += modifierList.annotations
}
return calculatedFirType
} }
private fun Collection<TypeModifier>.hasSuspend() = any { it.hasSuspend() } private fun Collection<TypeModifier>.hasSuspend() = any { it.hasSuspend() }
@@ -278,7 +278,12 @@ class ExpressionsConverter(
} else { } else {
val firOperation = operationToken.toFirOperation() val firOperation = operationToken.toFirOperation()
if (firOperation in FirOperation.ASSIGNMENTS) { if (firOperation in FirOperation.ASSIGNMENTS) {
return leftArgNode.generateAssignment(binaryExpression.toFirSourceElement(), rightArg, rightArgAsFir, firOperation) { getAsFirExpression(this) } return leftArgNode.generateAssignment(
binaryExpression.toFirSourceElement(),
rightArg,
rightArgAsFir,
firOperation
) { getAsFirExpression(this) }
} else { } else {
buildEqualityOperatorCall { buildEqualityOperatorCall {
source = binaryExpression.toFirSourceElement() source = binaryExpression.toFirSourceElement()
@@ -299,7 +304,7 @@ class ExpressionsConverter(
toFirOperation: String.() -> FirOperation toFirOperation: String.() -> FirOperation
): FirTypeOperatorCall { ): FirTypeOperatorCall {
lateinit var operationTokenName: String lateinit var operationTokenName: String
var leftArgAsFir: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("No left operand", DiagnosticKind.Syntax)) var leftArgAsFir: FirExpression? = null
lateinit var firType: FirTypeRef lateinit var firType: FirTypeRef
binaryExpression.forEachChildren { binaryExpression.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
@@ -313,7 +318,9 @@ class ExpressionsConverter(
source = binaryExpression.toFirSourceElement() source = binaryExpression.toFirSourceElement()
operation = operationTokenName.toFirOperation() operation = operationTokenName.toFirOperation()
conversionTypeRef = firType conversionTypeRef = firType
argumentList = buildUnaryArgumentList(leftArgAsFir) argumentList = buildUnaryArgumentList(
leftArgAsFir ?: buildErrorExpression(null, ConeSimpleDiagnostic("No left operand", DiagnosticKind.Syntax))
)
} }
} }
@@ -431,14 +438,17 @@ class ExpressionsConverter(
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitClassLiteralExpression * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitClassLiteralExpression
*/ */
private fun convertClassLiteralExpression(classLiteralExpression: LighterASTNode): FirExpression { private fun convertClassLiteralExpression(classLiteralExpression: LighterASTNode): FirExpression {
var firReceiverExpression: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("No receiver in class literal", DiagnosticKind.Syntax)) var firReceiverExpression: FirExpression? = null
classLiteralExpression.forEachChildren { classLiteralExpression.forEachChildren {
if (it.isExpression()) firReceiverExpression = getAsFirExpression(it, "No receiver in class literal") if (it.isExpression()) firReceiverExpression = getAsFirExpression(it, "No receiver in class literal")
} }
return buildGetClassCall { return buildGetClassCall {
source = classLiteralExpression.toFirSourceElement() source = classLiteralExpression.toFirSourceElement()
argumentList = buildUnaryArgumentList(firReceiverExpression) argumentList = buildUnaryArgumentList(
firReceiverExpression
?: buildErrorExpression(null, ConeSimpleDiagnostic("No receiver in class literal", DiagnosticKind.Syntax))
)
} }
} }
@@ -643,11 +653,11 @@ class ExpressionsConverter(
} }
private fun LighterASTNode?.convertShortOrLongStringTemplate(errorReason: String): FirExpression { private fun LighterASTNode?.convertShortOrLongStringTemplate(errorReason: String): FirExpression {
var firExpression: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.Syntax)) var firExpression: FirExpression? = null
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 return firExpression ?: buildErrorExpression(null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.Syntax))
} }
/** /**
@@ -756,13 +766,22 @@ class ExpressionsConverter(
return WhenEntry(conditions, firBlock, whenEntry, isElse) return WhenEntry(conditions, firBlock, whenEntry, isElse)
} }
private fun convertWhenConditionExpression(whenCondition: LighterASTNode, whenRefWithSubject: FirExpressionRef<FirWhenExpression>?): FirExpression { private fun convertWhenConditionExpression(
var firExpression: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("No expression in condition with expression", DiagnosticKind.Syntax)) whenCondition: LighterASTNode,
whenRefWithSubject: FirExpressionRef<FirWhenExpression>?
): FirExpression {
var firExpression: FirExpression? = null
whenCondition.forEachChildren { whenCondition.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "No expression in condition with expression") else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "No expression in condition with expression")
} }
} }
val calculatedFirExpression = firExpression ?: buildErrorExpression(
null,
ConeSimpleDiagnostic("No expression in condition with expression", DiagnosticKind.Syntax)
)
return if (whenRefWithSubject != null) { return if (whenRefWithSubject != null) {
buildEqualityOperatorCall { buildEqualityOperatorCall {
source = whenCondition.toFirSourceElement(FirFakeSourceElementKind.WhenCondition) source = whenCondition.toFirSourceElement(FirFakeSourceElementKind.WhenCondition)
@@ -770,18 +789,20 @@ class ExpressionsConverter(
argumentList = buildBinaryArgumentList( argumentList = buildBinaryArgumentList(
buildWhenSubjectExpression { buildWhenSubjectExpression {
whenRef = whenRefWithSubject whenRef = whenRefWithSubject
}, firExpression }, calculatedFirExpression
) )
} }
} else { } else {
firExpression calculatedFirExpression
} }
} }
private fun convertWhenConditionInRange(whenCondition: LighterASTNode, whenRefWithSubject: FirExpressionRef<FirWhenExpression>?): FirExpression { private fun convertWhenConditionInRange(
whenCondition: LighterASTNode,
whenRefWithSubject: FirExpressionRef<FirWhenExpression>?
): FirExpression {
var isNegate = false var isNegate = false
var firExpression: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("No range in condition with range", DiagnosticKind.Syntax)) var firExpression: FirExpression? = null
var conditionSource: FirLightSourceElement? = null var conditionSource: FirLightSourceElement? = null
whenCondition.forEachChildren { whenCondition.forEachChildren {
when { when {
@@ -808,7 +829,12 @@ class ExpressionsConverter(
} }
} }
return firExpression.generateContainsOperation( val calculatedFirExpression = firExpression ?: buildErrorExpression(
null,
ConeSimpleDiagnostic("No range in condition with range", DiagnosticKind.Syntax)
)
return calculatedFirExpression.generateContainsOperation(
subjectExpression, subjectExpression,
inverted = isNegate, inverted = isNegate,
baseSource = whenCondition.toFirSourceElement(), baseSource = whenCondition.toFirSourceElement(),
@@ -816,7 +842,10 @@ class ExpressionsConverter(
) )
} }
private fun convertWhenConditionIsPattern(whenCondition: LighterASTNode, whenRefWithSubject: FirExpressionRef<FirWhenExpression>?): FirExpression { private fun convertWhenConditionIsPattern(
whenCondition: LighterASTNode,
whenRefWithSubject: FirExpressionRef<FirWhenExpression>?
): FirExpression {
lateinit var firOperation: FirOperation lateinit var firOperation: FirOperation
lateinit var firType: FirTypeRef lateinit var firType: FirTypeRef
whenCondition.forEachChildren { whenCondition.forEachChildren {
@@ -851,7 +880,7 @@ class ExpressionsConverter(
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitArrayAccessExpression * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitArrayAccessExpression
*/ */
private fun convertArrayAccessExpression(arrayAccess: LighterASTNode): FirFunctionCall { private fun convertArrayAccessExpression(arrayAccess: LighterASTNode): FirFunctionCall {
var firExpression: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("No array expression", DiagnosticKind.Syntax)) var firExpression: FirExpression? = null
val indices: MutableList<FirExpression> = mutableListOf() val indices: MutableList<FirExpression> = mutableListOf()
arrayAccess.forEachChildren { arrayAccess.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
@@ -867,7 +896,8 @@ class ExpressionsConverter(
source = arrayAccess.toFirSourceElement().fakeElement(FirFakeSourceElementKind.ArrayAccessNameReference) source = arrayAccess.toFirSourceElement().fakeElement(FirFakeSourceElementKind.ArrayAccessNameReference)
name = if (isGet) OperatorNameConventions.GET else OperatorNameConventions.SET name = if (isGet) OperatorNameConventions.GET else OperatorNameConventions.SET
} }
explicitReceiver = firExpression explicitReceiver =
firExpression ?: buildErrorExpression(null, ConeSimpleDiagnostic("No array expression", DiagnosticKind.Syntax))
argumentList = buildArgumentList { argumentList = buildArgumentList {
arguments += indices arguments += indices
getArgument?.let { arguments += it } getArgument?.let { arguments += it }
@@ -925,8 +955,7 @@ class ExpressionsConverter(
*/ */
private fun convertDoWhile(doWhileLoop: LighterASTNode): FirElement { private fun convertDoWhile(doWhileLoop: LighterASTNode): FirElement {
var block: LighterASTNode? = null var block: LighterASTNode? = null
var firCondition: FirExpression = var firCondition: FirExpression? = null
buildErrorExpression(null, ConeSimpleDiagnostic("No condition in do-while loop", DiagnosticKind.Syntax))
val target: FirLoopTarget val target: FirLoopTarget
return FirDoWhileLoopBuilder().apply { return FirDoWhileLoopBuilder().apply {
@@ -939,7 +968,8 @@ class ExpressionsConverter(
CONDITION -> firCondition = getAsFirExpression(it, "No condition in do-while loop") CONDITION -> firCondition = getAsFirExpression(it, "No condition in do-while loop")
} }
} }
condition = firCondition condition =
firCondition ?: buildErrorExpression(null, ConeSimpleDiagnostic("No condition in do-while loop", DiagnosticKind.Syntax))
}.configure(target) { convertLoopBody(block) } }.configure(target) { convertLoopBody(block) }
} }
@@ -949,7 +979,7 @@ class ExpressionsConverter(
*/ */
private fun convertWhile(whileLoop: LighterASTNode): FirElement { private fun convertWhile(whileLoop: LighterASTNode): FirElement {
var block: LighterASTNode? = null var block: LighterASTNode? = null
var firCondition: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("No condition in while loop", DiagnosticKind.Syntax)) var firCondition: FirExpression? = null
whileLoop.forEachChildren { whileLoop.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
BODY -> block = it BODY -> block = it
@@ -960,7 +990,8 @@ class ExpressionsConverter(
val target: FirLoopTarget val target: FirLoopTarget
return FirWhileLoopBuilder().apply { return FirWhileLoopBuilder().apply {
source = whileLoop.toFirSourceElement() source = whileLoop.toFirSourceElement()
condition = firCondition condition =
firCondition ?: buildErrorExpression(null, ConeSimpleDiagnostic("No condition in while loop", DiagnosticKind.Syntax))
// 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() target = prepareTarget()
@@ -973,7 +1004,7 @@ class ExpressionsConverter(
*/ */
private fun convertFor(forLoop: LighterASTNode): FirElement { private fun convertFor(forLoop: LighterASTNode): FirElement {
var parameter: ValueParameter? = null var parameter: ValueParameter? = null
var rangeExpression: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("No range in for loop", DiagnosticKind.Syntax)) var rangeExpression: FirExpression? = null
var blockNode: LighterASTNode? = null var blockNode: LighterASTNode? = null
forLoop.forEachChildren { forLoop.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
@@ -983,6 +1014,8 @@ class ExpressionsConverter(
} }
} }
val calculatedRangeExpression =
rangeExpression ?: buildErrorExpression(null, ConeSimpleDiagnostic("No range in for loop", DiagnosticKind.Syntax))
val fakeSource = forLoop.toFirSourceElement(FirFakeSourceElementKind.DesugaredForLoop) val fakeSource = forLoop.toFirSourceElement(FirFakeSourceElementKind.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
@@ -990,7 +1023,7 @@ class ExpressionsConverter(
source = fakeSource source = fakeSource
val iteratorVal = generateTemporaryVariable( val iteratorVal = generateTemporaryVariable(
baseModuleData, baseModuleData,
rangeExpression.source?.fakeElement(FirFakeSourceElementKind.DesugaredForLoop), calculatedRangeExpression.source?.fakeElement(FirFakeSourceElementKind.DesugaredForLoop),
ITERATOR_NAME, ITERATOR_NAME,
buildFunctionCall { buildFunctionCall {
source = fakeSource source = fakeSource
@@ -998,7 +1031,7 @@ class ExpressionsConverter(
source = fakeSource source = fakeSource
name = OperatorNameConventions.ITERATOR name = OperatorNameConventions.ITERATOR
} }
explicitReceiver = rangeExpression explicitReceiver = calculatedRangeExpression
} }
) )
statements += iteratorVal statements += iteratorVal
@@ -1047,7 +1080,6 @@ class ExpressionsConverter(
} else { } else {
statements.add(0, firLoopParameter) statements.add(0, firLoopParameter)
} }
} }
} }
} }
@@ -1138,7 +1170,7 @@ class ExpressionsConverter(
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitIfExpression * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitIfExpression
*/ */
private fun convertIfExpression(ifExpression: LighterASTNode): FirExpression { private fun convertIfExpression(ifExpression: LighterASTNode): FirExpression {
var firCondition: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("If statement should have condition", DiagnosticKind.Syntax)) var firCondition: FirExpression? = null
var thenBlock: LighterASTNode? = null var thenBlock: LighterASTNode? = null
var elseBlock: LighterASTNode? = null var elseBlock: LighterASTNode? = null
ifExpression.forEachChildren { ifExpression.forEachChildren {
@@ -1154,7 +1186,10 @@ class ExpressionsConverter(
val trueBranch = convertLoopBody(thenBlock) val trueBranch = convertLoopBody(thenBlock)
branches += buildWhenBranch { branches += buildWhenBranch {
source = thenBlock?.toFirSourceElement() source = thenBlock?.toFirSourceElement()
condition = firCondition condition = firCondition ?: buildErrorExpression(
null,
ConeSimpleDiagnostic("If statement should have condition", DiagnosticKind.Syntax)
)
result = trueBranch result = trueBranch
} }
if (elseBlock != null) { if (elseBlock != null) {
@@ -1212,9 +1247,7 @@ class ExpressionsConverter(
*/ */
private fun convertReturn(returnExpression: LighterASTNode): FirExpression { private fun convertReturn(returnExpression: LighterASTNode): FirExpression {
var labelName: String? = null var labelName: String? = null
var firExpression: FirExpression = buildUnitExpression { var firExpression: FirExpression? = null
source = returnExpression.toFirSourceElement(FirFakeSourceElementKind.ImplicitUnit)
}
returnExpression.forEachChildren { returnExpression.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
LABEL_QUALIFIER -> labelName = it.getAsStringWithoutBacktick().replace("@", "") LABEL_QUALIFIER -> labelName = it.getAsStringWithoutBacktick().replace("@", "")
@@ -1222,7 +1255,10 @@ class ExpressionsConverter(
} }
} }
return firExpression.toReturn( val calculatedFirExpression = firExpression ?: buildUnitExpression {
source = returnExpression.toFirSourceElement(FirFakeSourceElementKind.ImplicitUnit)
}
return calculatedFirExpression.toReturn(
baseSource = returnExpression.toFirSourceElement(), baseSource = returnExpression.toFirSourceElement(),
labelName = labelName, labelName = labelName,
fromKtReturnExpression = true fromKtReturnExpression = true
@@ -1234,14 +1270,14 @@ class ExpressionsConverter(
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitThrowExpression * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitThrowExpression
*/ */
private fun convertThrow(throwExpression: LighterASTNode): FirExpression { private fun convertThrow(throwExpression: LighterASTNode): FirExpression {
var firExpression: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("Nothing to throw", DiagnosticKind.Syntax)) var firExpression: FirExpression? = null
throwExpression.forEachChildren { throwExpression.forEachChildren {
if (it.isExpression()) firExpression = getAsFirExpression(it, "Nothing to throw") if (it.isExpression()) firExpression = getAsFirExpression(it, "Nothing to throw")
} }
return buildThrowExpression { return buildThrowExpression {
source = throwExpression.toFirSourceElement() source = throwExpression.toFirSourceElement()
exception = firExpression exception = firExpression ?: buildErrorExpression(null, ConeSimpleDiagnostic("Nothing to throw", DiagnosticKind.Syntax))
} }
} }
@@ -1303,7 +1339,7 @@ class ExpressionsConverter(
private fun convertValueArgument(valueArgument: LighterASTNode): FirExpression { private fun convertValueArgument(valueArgument: LighterASTNode): FirExpression {
var identifier: String? = null var identifier: String? = null
var isSpread = false var isSpread = false
var firExpression: FirExpression = buildErrorExpression(null, ConeSimpleDiagnostic("Argument is absent", DiagnosticKind.Syntax)) var firExpression: FirExpression? = null
valueArgument.forEachChildren { valueArgument.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
VALUE_ARGUMENT_NAME -> identifier = it.asText VALUE_ARGUMENT_NAME -> identifier = it.asText
@@ -1313,18 +1349,20 @@ class ExpressionsConverter(
else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "Argument is absent") else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "Argument is absent")
} }
} }
val calculatedFirExpression =
firExpression ?: buildErrorExpression(null, ConeSimpleDiagnostic("Argument is absent", DiagnosticKind.Syntax))
return when { return when {
identifier != null -> buildNamedArgumentExpression { identifier != null -> buildNamedArgumentExpression {
source = valueArgument.toFirSourceElement() source = valueArgument.toFirSourceElement()
expression = firExpression expression = calculatedFirExpression
this.isSpread = isSpread this.isSpread = isSpread
name = identifier.nameAsSafeName() name = identifier.nameAsSafeName()
} }
isSpread -> buildSpreadArgumentExpression { isSpread -> buildSpreadArgumentExpression {
source = valueArgument.toFirSourceElement() source = valueArgument.toFirSourceElement()
expression = firExpression expression = calculatedFirExpression
} }
else -> firExpression else -> calculatedFirExpression
} }
} }
} }
@@ -81,11 +81,10 @@ fun escapedStringToCharacter(text: String): CharacterWithDiagnostic {
5 -> { 5 -> {
// unicode escape // unicode escape
if (escape[0] == 'u') { if (escape[0] == 'u') {
try { val intValue = escape.substring(1).toIntOrNull(16)
val intValue = Integer.valueOf(escape.substring(1), 16) // If error occurs it will be reported below
return CharacterWithDiagnostic(intValue.toInt().toChar()) if (intValue != null) {
} catch (e: NumberFormatException) { return CharacterWithDiagnostic(intValue.toChar())
// Will be reported below
} }
} }
} }