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) { if (!stubMode) {
return when (expression.tokenType) { return when (expression.tokenType) {
BINARY_EXPRESSION -> convertBinaryExpression(expression) BINARY_EXPRESSION -> convertBinaryExpression(expression)
BINARY_WITH_TYPE -> convertBinaryWithType(expression)
IS_EXPRESSION -> convertIsExpression(expression)
PREFIX_EXPRESSION, POSTFIX_EXPRESSION -> convertUnaryExpression(expression) PREFIX_EXPRESSION, POSTFIX_EXPRESSION -> convertUnaryExpression(expression)
ANNOTATED_EXPRESSION -> convertAnnotatedExpression(expression) ANNOTATED_EXPRESSION -> convertAnnotatedExpression(expression)
in qualifiedAccessTokens -> convertQualifiedExpression(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.parsePostfixExpression
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parsePrefixExpression * @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.fir.references.FirSimpleNamedReference
import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.DOT import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.lexer.KtTokens.SAFE_ACCESS
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parsing.KotlinExpressionParsing import org.jetbrains.kotlin.parsing.KotlinExpressionParsing
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -31,7 +30,8 @@ fun String.getOperationSymbol(): IElementType {
KotlinExpressionParsing.ALL_OPERATIONS.types.forEach { KotlinExpressionParsing.ALL_OPERATIONS.types.forEach {
if (it is KtSingleValueToken && it.value == this) return it if (it is KtSingleValueToken && it.value == this) return it
} }
return KtTokens.IDENTIFIER if (this == "as?") return AS_SAFE
return IDENTIFIER
} }
fun ExpressionsConverter.convertAssignment( fun ExpressionsConverter.convertAssignment(
@@ -23,9 +23,7 @@ class FirPartialTransformer(
private val visitMemberDeclaration: Boolean = false, private val visitMemberDeclaration: Boolean = false,
private val visitVariable: Boolean = false, private val visitVariable: Boolean = false,
private val visitAnnotation: Boolean = false, private val visitAnnotation: Boolean = false,
private val visitOperatorCall: Boolean = false,
private val visitTypeOperatorCall: Boolean = false, private val visitTypeOperatorCall: Boolean = false,
private val visitStringConcatenationCall: Boolean = false,
private val visitArrayOfCall: Boolean = false, private val visitArrayOfCall: Boolean = false,
private val visitFunctionCall: Boolean = false, private val visitFunctionCall: Boolean = false,
private val visitGetClassCall: 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> { override fun transformTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Nothing?): CompositeTransformResult<FirStatement> {
return if (visitTypeOperatorCall) { return if (visitTypeOperatorCall) {
(typeOperatorCall.transformChildren(this, data) as FirTypeOperatorCall).compose() (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> { override fun transformArrayOfCall(arrayOfCall: FirArrayOfCall, data: Nothing?): CompositeTransformResult<FirStatement> {
return if (visitArrayOfCall) { return if (visitArrayOfCall) {
(arrayOfCall.transformChildren(this, data) as FirArrayOfCall).compose() (arrayOfCall.transformChildren(this, data) as FirArrayOfCall).compose()
@@ -63,9 +63,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() {
visitMemberDeclaration: Boolean = false, visitMemberDeclaration: Boolean = false,
visitVariable: Boolean = false, visitVariable: Boolean = false,
visitAnnotation: Boolean = false, visitAnnotation: Boolean = false,
visitOperatorCall: Boolean = false,
visitTypeOperatorCall: Boolean = false, visitTypeOperatorCall: Boolean = false,
visitStringConcatenationCall: Boolean = false,
visitArrayOfCall: Boolean = false, visitArrayOfCall: Boolean = false,
visitFunctionCall: Boolean = false, visitFunctionCall: Boolean = false,
visitGetClassCall: Boolean = false, visitGetClassCall: Boolean = false,
@@ -95,9 +93,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() {
visitMemberDeclaration = visitMemberDeclaration, visitMemberDeclaration = visitMemberDeclaration,
visitVariable = visitVariable, visitVariable = visitVariable,
visitAnnotation = visitAnnotation, visitAnnotation = visitAnnotation,
visitOperatorCall = visitOperatorCall,
visitTypeOperatorCall = visitTypeOperatorCall, visitTypeOperatorCall = visitTypeOperatorCall,
visitStringConcatenationCall = visitStringConcatenationCall,
visitArrayOfCall = visitArrayOfCall, visitArrayOfCall = visitArrayOfCall,
visitFunctionCall = visitFunctionCall, visitFunctionCall = visitFunctionCall,
visitGetClassCall = visitGetClassCall, visitGetClassCall = visitGetClassCall,
@@ -162,4 +158,14 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() {
fun testQualifiedAccessExpression() { fun testQualifiedAccessExpression() {
compare(stubMode = false, visitFunctionCall = true, visitQualifiedAccessExpression = true) compare(stubMode = false, visitFunctionCall = true, visitQualifiedAccessExpression = true)
} }
fun testTypeOperatorCall() {
compare(
stubMode = false,
visitTypeOperatorCall = true,
visitFunctionCall = true,
visitConstExpression = true,
visitQualifiedAccessExpression = true
)
}
} }