diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index cb3877f66bc..525aef58f2e 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -51,6 +51,8 @@ class ExpressionsConverter( if (!stubMode) { return when (expression.tokenType) { BINARY_EXPRESSION -> convertBinaryExpression(expression) + BINARY_WITH_TYPE -> convertBinaryWithType(expression) + IS_EXPRESSION -> convertIsExpression(expression) PREFIX_EXPRESSION, POSTFIX_EXPRESSION -> convertUnaryExpression(expression) ANNOTATED_EXPRESSION -> convertAnnotatedExpression(expression) in qualifiedAccessTokens -> convertQualifiedExpression(expression) @@ -133,6 +135,49 @@ class ExpressionsConverter( } } + /** + * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.Precedence.parseRightHandSide + * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitBinaryWithTypeRHSExpression + */ + private fun convertBinaryWithType(binaryExpression: LighterASTNode): FirTypeOperatorCall { + lateinit var operationTokenName: String + lateinit var leftArgAsFir: FirExpression + lateinit var firType: FirTypeRef + binaryExpression.forEachChildren { + when (it.tokenType) { + OPERATION_REFERENCE -> operationTokenName = it.getAsString() + TYPE_REFERENCE -> firType = declarationsConverter.convertType(it) + else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it) + } + } + + val operation = operationTokenName.getOperationSymbol().toFirOperation() + return FirTypeOperatorCallImpl(session, null, operation, firType).apply { + arguments += leftArgAsFir + } + } + + /** + * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitIsExpression + */ + private fun convertIsExpression(isExpression: LighterASTNode): FirTypeOperatorCall { + lateinit var operationTokenName: String + lateinit var leftArgAsFir: FirExpression + lateinit var firType: FirTypeRef + isExpression.forEachChildren { + when (it.tokenType) { + OPERATION_REFERENCE -> operationTokenName = it.getAsString() + TYPE_REFERENCE -> firType = declarationsConverter.convertType(it) + else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it) + } + } + + val operation = if (operationTokenName == "is") FirOperation.IS else FirOperation.NOT_IS + return FirTypeOperatorCallImpl(session, null, operation, firType).apply { + arguments += leftArgAsFir + } + } + /** * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parsePostfixExpression * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parsePrefixExpression diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt index 7f28d20c04d..560b5d66cb5 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt @@ -19,8 +19,7 @@ import org.jetbrains.kotlin.fir.lightTree.converter.ExpressionsConverter import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.lexer.KtTokens.DOT -import org.jetbrains.kotlin.lexer.KtTokens.SAFE_ACCESS +import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.parsing.KotlinExpressionParsing import org.jetbrains.kotlin.util.OperatorNameConventions @@ -31,7 +30,8 @@ fun String.getOperationSymbol(): IElementType { KotlinExpressionParsing.ALL_OPERATIONS.types.forEach { if (it is KtSingleValueToken && it.value == this) return it } - return KtTokens.IDENTIFIER + if (this == "as?") return AS_SAFE + return IDENTIFIER } fun ExpressionsConverter.convertAssignment( diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt index 2f78cdd1e92..2af2da5aa6a 100644 --- a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt @@ -23,9 +23,7 @@ class FirPartialTransformer( private val visitMemberDeclaration: Boolean = false, private val visitVariable: Boolean = false, private val visitAnnotation: Boolean = false, - private val visitOperatorCall: Boolean = false, private val visitTypeOperatorCall: Boolean = false, - private val visitStringConcatenationCall: Boolean = false, private val visitArrayOfCall: Boolean = false, private val visitFunctionCall: Boolean = false, private val visitGetClassCall: Boolean = false, @@ -104,14 +102,6 @@ class FirPartialTransformer( } } - override fun transformOperatorCall(operatorCall: FirOperatorCall, data: Nothing?): CompositeTransformResult { - return if (visitOperatorCall) { - (operatorCall.transformChildren(this, data) as FirOperatorCall).compose() - } else { - DummyFirStatement().compose() - } - } - override fun transformTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Nothing?): CompositeTransformResult { return if (visitTypeOperatorCall) { (typeOperatorCall.transformChildren(this, data) as FirTypeOperatorCall).compose() @@ -120,17 +110,6 @@ class FirPartialTransformer( } } - override fun transformStringConcatenationCall( - stringConcatenationCall: FirStringConcatenationCall, - data: Nothing? - ): CompositeTransformResult { - return if (visitStringConcatenationCall) { - (stringConcatenationCall.transformChildren(this, data) as FirStringConcatenationCall).compose() - } else { - DummyFirStatement().compose() - } - } - override fun transformArrayOfCall(arrayOfCall: FirArrayOfCall, data: Nothing?): CompositeTransformResult { return if (visitArrayOfCall) { (arrayOfCall.transformChildren(this, data) as FirArrayOfCall).compose() diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt index a0df6e50018..b144d93dad2 100644 --- a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt @@ -63,9 +63,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { visitMemberDeclaration: Boolean = false, visitVariable: Boolean = false, visitAnnotation: Boolean = false, - visitOperatorCall: Boolean = false, visitTypeOperatorCall: Boolean = false, - visitStringConcatenationCall: Boolean = false, visitArrayOfCall: Boolean = false, visitFunctionCall: Boolean = false, visitGetClassCall: Boolean = false, @@ -95,9 +93,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { visitMemberDeclaration = visitMemberDeclaration, visitVariable = visitVariable, visitAnnotation = visitAnnotation, - visitOperatorCall = visitOperatorCall, visitTypeOperatorCall = visitTypeOperatorCall, - visitStringConcatenationCall = visitStringConcatenationCall, visitArrayOfCall = visitArrayOfCall, visitFunctionCall = visitFunctionCall, visitGetClassCall = visitGetClassCall, @@ -162,4 +158,14 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { fun testQualifiedAccessExpression() { compare(stubMode = false, visitFunctionCall = true, visitQualifiedAccessExpression = true) } + + fun testTypeOperatorCall() { + compare( + stubMode = false, + visitTypeOperatorCall = true, + visitFunctionCall = true, + visitConstExpression = true, + visitQualifiedAccessExpression = true + ) + } }