Write type operator call parsing (light tree to FIR)

This commit is contained in:
Ivan Cilcic
2019-07-17 13:30:35 +03:00
committed by Mikhail Glukhikh
parent e0bebba42e
commit 9d36855cb6
4 changed files with 58 additions and 28 deletions
@@ -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
@@ -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(
@@ -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<FirStatement> {
return if (visitOperatorCall) {
(operatorCall.transformChildren(this, data) as FirOperatorCall).compose()
} else {
DummyFirStatement().compose()
}
}
override fun transformTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Nothing?): CompositeTransformResult<FirStatement> {
return if (visitTypeOperatorCall) {
(typeOperatorCall.transformChildren(this, data) as FirTypeOperatorCall).compose()
@@ -120,17 +110,6 @@ class FirPartialTransformer(
}
}
override fun transformStringConcatenationCall(
stringConcatenationCall: FirStringConcatenationCall,
data: Nothing?
): CompositeTransformResult<FirStatement> {
return if (visitStringConcatenationCall) {
(stringConcatenationCall.transformChildren(this, data) as FirStringConcatenationCall).compose()
} else {
DummyFirStatement().compose()
}
}
override fun transformArrayOfCall(arrayOfCall: FirArrayOfCall, data: Nothing?): CompositeTransformResult<FirStatement> {
return if (visitArrayOfCall) {
(arrayOfCall.transformChildren(this, data) as FirArrayOfCall).compose()
@@ -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
)
}
}