Fix some light tree to FIR converter bugs after testing

This commit is contained in:
Ivan Cilcic
2019-07-17 12:31:13 +03:00
committed by Mikhail Glukhikh
parent 08ab530ef0
commit e0bebba42e
4 changed files with 123 additions and 68 deletions
@@ -103,9 +103,7 @@ class DeclarationsConverter(
when (it.tokenType) {
//TODO("not implemented")
BLOCK -> ""
BINARY_EXPRESSION -> firStatements += expressionConverter.convertBinaryExpression(it)
PREFIX_EXPRESSION, POSTFIX_EXPRESSION -> firStatements += expressionConverter.convertUnaryExpression(it)
else -> if (it.isExpression()) firStatements += expressionConverter.visitExpression(it)
else -> if (it.isExpression()) firStatements += expressionConverter.getAsFirExpression<FirStatement>(it)
}
}
return FirBlockImpl(session, null).apply {
@@ -263,7 +261,7 @@ class DeclarationsConverter(
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseAnnotationOrList
*/
private fun convertAnnotation(annotationNode: LighterASTNode): List<FirAnnotationCall> {
fun convertAnnotation(annotationNode: LighterASTNode): List<FirAnnotationCall> {
var annotationTarget: AnnotationUseSiteTarget? = null
return annotationNode.forEachChildrenReturnList { node, container ->
when (node.tokenType) {
@@ -299,7 +297,7 @@ class DeclarationsConverter(
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseAnnotation
* can be treated as unescapedAnnotation
*/
private fun convertAnnotationEntry(
fun convertAnnotationEntry(
unescapedAnnotation: LighterASTNode,
defaultAnnotationUseSiteTarget: AnnotationUseSiteTarget? = null
): FirAnnotationCall {
@@ -429,16 +427,16 @@ class DeclarationsConverter(
var modifiers = Modifier(session)
lateinit var identifier: String
var hasInitializerList = false
val enumSuperTypeCallEntry = mutableListOf<FirExpression>() //TODO get from INITIALIZER_LIST
val enumSuperTypeCallEntry = mutableListOf<FirExpression>()
val firDeclarations = mutableListOf<FirDeclaration>()
enumEntry.forEachChildren {
when (it.tokenType) {
MODIFIER_LIST -> modifiers = convertModifierList(it)
IDENTIFIER -> identifier = it.getAsString()
INITIALIZER_LIST -> hasInitializerList = true //TODO implement
/*enumSuperTypeCallEntry += initializerList.valueParameters.map { firValueParameter ->
firValueParameter.toFirExpression(stubMode)
}*/
INITIALIZER_LIST -> {
hasInitializerList = true
enumSuperTypeCallEntry += convertInitializerList(it)
}
CLASS_BODY -> firDeclarations += convertClassBody(it, classWrapper)
}
}
@@ -469,6 +467,22 @@ class DeclarationsConverter(
}
}
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseEnumEntry
*/
private fun convertInitializerList(initializerList: LighterASTNode): List<FirExpression> {
val firValueArguments = mutableListOf<FirExpression>()
initializerList.forEachChildren {
when (it.tokenType) {
SUPER_TYPE_CALL_ENTRY -> convertConstructorInvocation(it).apply {
firValueArguments += second
}
}
}
return firValueArguments
}
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseClassBody
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseEnumClassBody
@@ -678,13 +692,13 @@ class DeclarationsConverter(
COLON -> isReturnType = true
TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it)
TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
PROPERTY_DELEGATE -> firDelegateExpression = expressionConverter.visitExpression(it)
PROPERTY_DELEGATE -> firDelegateExpression = expressionConverter.getAsFirExpression(it)
VAR_KEYWORD -> isVar = true
PROPERTY_ACCESSOR -> {
val propertyAccessor = convertGetterOrSetter(it, returnType)
if (propertyAccessor.isGetter) getter = propertyAccessor else setter = propertyAccessor
}
else -> if (it.isExpression()) firExpression = expressionConverter.visitExpression(it)
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it)
}
}
@@ -746,7 +760,7 @@ class DeclarationsConverter(
TYPE_REFERENCE -> returnType = convertType(it)
VALUE_PARAMETER_LIST -> firValueParameters = convertSetterParameter(it, propertyTypeRef)
BLOCK -> firBlock = visitBlock(it)
else -> if (it.isExpression()) firExpression = expressionConverter.visitExpression(it)
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it)
}
}
@@ -823,7 +837,7 @@ class DeclarationsConverter(
TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it)
TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
BLOCK -> firBlock = visitBlock(it)
else -> if (it.isExpression()) firExpression = expressionConverter.visitExpression(it)
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it)
}
}
@@ -941,11 +955,11 @@ class DeclarationsConverter(
* ;
*/
private fun convertConstructorInvocation(constructorInvocation: LighterASTNode): Pair<FirTypeRef, List<FirExpression>> {
lateinit var firTypeRef: FirTypeRef
var firTypeRef: FirTypeRef = implicitType
val firValueArguments = mutableListOf<FirExpression>()
constructorInvocation.forEachChildren {
when (it.tokenType) {
CONSTRUCTOR_CALLEE -> firTypeRef = convertType(it)
CONSTRUCTOR_CALLEE -> if (it.getAsString().isNotEmpty()) firTypeRef = convertType(it) //is empty in enum entry constructor
VALUE_ARGUMENT_LIST -> firValueArguments += expressionConverter.convertValueArguments(it)
}
}
@@ -965,7 +979,7 @@ class DeclarationsConverter(
explicitDelegation.forEachChildren {
when (it.tokenType) {
TYPE_REFERENCE -> firTypeRef = convertType(it)
else -> if (it.isExpression()) firExpression = expressionConverter.visitExpression(it)
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it)
}
}
@@ -1216,7 +1230,7 @@ class DeclarationsConverter(
VAR_KEYWORD -> isVar = true
IDENTIFIER -> identifier = it.getAsString()
TYPE_REFERENCE -> firType = convertType(it)
else -> if (it.isExpression()) firExpression = expressionConverter.visitExpression(it)
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it)
}
}
@@ -25,13 +25,11 @@ import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirExplicitSuperReference
import org.jetbrains.kotlin.fir.references.FirExplicitThisReference
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtSuperExpression
import org.jetbrains.kotlin.psi.KtThisExpression
import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
import org.jetbrains.kotlin.resolve.constants.evaluate.*
import org.jetbrains.kotlin.types.expressions.OperatorConventions
@@ -44,23 +42,28 @@ class ExpressionsConverter(
private val declarationsConverter: DeclarationsConverter
) : BaseConverter(session, tree) {
inline fun <reified R : FirElement> getAsFirExpression(expression: LighterASTNode): R {
return convertExpression(expression) as R
}
/***** EXPRESSIONS *****/
fun visitExpression(expression: LighterASTNode): FirExpression {
fun convertExpression(expression: LighterASTNode): FirElement {
if (!stubMode) {
when (expression.tokenType) {
BINARY_EXPRESSION -> return convertBinaryExpression(expression) as FirExpression
PREFIX_EXPRESSION, POSTFIX_EXPRESSION -> return convertUnaryExpression(expression) as FirExpression
in qualifiedAccessTokens -> return convertQualifiedExpression(expression)
CALL_EXPRESSION -> return convertCallExpression(expression)
ARRAY_ACCESS_EXPRESSION -> return convertArrayAccessExpression(expression)
STRING_TEMPLATE -> return convertStringTemplate(expression)
is KtConstantExpressionElementType -> return convertConstantExpression(expression)
REFERENCE_EXPRESSION -> return convertSimpleNameExpression(expression)
PARENTHESIZED, PROPERTY_DELEGATE, INDICES -> return visitExpression(expression.getExpressionInParentheses())
THIS_EXPRESSION -> return convertThisExpression(expression)
SUPER_EXPRESSION -> return convertSuperExpression(expression)
return when (expression.tokenType) {
BINARY_EXPRESSION -> convertBinaryExpression(expression)
PREFIX_EXPRESSION, POSTFIX_EXPRESSION -> convertUnaryExpression(expression)
ANNOTATED_EXPRESSION -> convertAnnotatedExpression(expression)
in qualifiedAccessTokens -> convertQualifiedExpression(expression)
CALL_EXPRESSION -> convertCallExpression(expression)
ARRAY_ACCESS_EXPRESSION -> convertArrayAccessExpression(expression)
STRING_TEMPLATE -> convertStringTemplate(expression)
is KtConstantExpressionElementType -> convertConstantExpression(expression)
REFERENCE_EXPRESSION -> convertSimpleNameExpression(expression)
PARENTHESIZED, PROPERTY_DELEGATE, INDICES -> convertExpression(expression.getExpressionInParentheses())
THIS_EXPRESSION -> convertThisExpression(expression)
SUPER_EXPRESSION -> convertSuperExpression(expression)
else -> FirExpressionStub(session, null)
}
return FirExpressionStub(session, null)
//TODO("not fully implemented")
}
@@ -71,7 +74,7 @@ class ExpressionsConverter(
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseBinaryExpression
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitBinaryExpression
*/
fun convertBinaryExpression(binaryExpression: LighterASTNode): FirStatement {
private fun convertBinaryExpression(binaryExpression: LighterASTNode): FirStatement {
var isLeftArgument = true
lateinit var operationTokenName: String
lateinit var leftArgNode: LighterASTNode
@@ -86,7 +89,7 @@ class ExpressionsConverter(
if (isLeftArgument) {
leftArgNode = it
} else {
rightArgAsFir = visitExpression(it)
rightArgAsFir = getAsFirExpression(it)
}
}
}
@@ -95,11 +98,17 @@ class ExpressionsConverter(
val operationToken = operationTokenName.getOperationSymbol()
when (operationToken) {
ELVIS ->
return visitExpression(leftArgNode).generateNotNullOrOther(session, rightArgAsFir, "elvis", null)
return getAsFirExpression<FirExpression>(leftArgNode).generateNotNullOrOther(
session, rightArgAsFir, "elvis", null
)
ANDAND, OROR ->
return visitExpression(leftArgNode).generateLazyLogicalOperation(session, rightArgAsFir, operationToken == ANDAND, null)
return getAsFirExpression<FirExpression>(leftArgNode).generateLazyLogicalOperation(
session, rightArgAsFir, operationToken == ANDAND, null
)
in OperatorConventions.IN_OPERATIONS ->
return rightArgAsFir.generateContainsOperation(session, visitExpression(leftArgNode), operationToken == NOT_IN, null, null)
return rightArgAsFir.generateContainsOperation(
session, getAsFirExpression(leftArgNode), operationToken == NOT_IN, null, null
)
}
val conventionCallName = operationToken.toBinaryName()
return if (conventionCallName != null || operationToken == IDENTIFIER) {
@@ -108,7 +117,7 @@ class ExpressionsConverter(
this@ExpressionsConverter.session, null,
conventionCallName ?: operationTokenName.nameAsSafeName()
)
explicitReceiver = visitExpression(leftArgNode)
explicitReceiver = getAsFirExpression(leftArgNode)
arguments += rightArgAsFir
}
} else {
@@ -117,7 +126,7 @@ class ExpressionsConverter(
return convertAssignment(leftArgNode, rightArgAsFir, firOperation)
} else {
FirOperatorCallImpl(session, null, firOperation).apply {
arguments += visitExpression(leftArgNode)
arguments += getAsFirExpression<FirExpression>(leftArgNode)
arguments += rightArgAsFir
}
}
@@ -129,7 +138,7 @@ class ExpressionsConverter(
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parsePrefixExpression
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitUnaryExpression
*/
fun convertUnaryExpression(unaryExpression: LighterASTNode): FirStatement {
private fun convertUnaryExpression(unaryExpression: LighterASTNode): FirExpression {
lateinit var operationTokenName: String
lateinit var argument: LighterASTNode
unaryExpression.forEachChildren {
@@ -141,7 +150,7 @@ class ExpressionsConverter(
val operationToken = operationTokenName.getOperationSymbol()
if (operationToken == EXCLEXCL) {
return bangBangToWhen(session, visitExpression(argument))
return bangBangToWhen(session, getAsFirExpression(argument))
}
val conventionCallName = operationToken.toUnaryName()
@@ -155,16 +164,32 @@ class ExpressionsConverter(
}
FirFunctionCallImpl(session, null).apply {
calleeReference = FirSimpleNamedReference(this@ExpressionsConverter.session, null, conventionCallName)
explicitReceiver = visitExpression(argument)
explicitReceiver = getAsFirExpression(argument)
}
} else {
val firOperation = operationToken.toFirOperation()
FirOperatorCallImpl(session, null, firOperation).apply {
arguments += visitExpression(argument)
arguments += getAsFirExpression<FirExpression>(argument)
}
}
}
private fun convertAnnotatedExpression(annotatedExpression: LighterASTNode): FirElement {
var firExpression: FirElement? = null
val firAnnotationList = mutableListOf<FirAnnotationCall>()
annotatedExpression.forEachChildren {
when (it.tokenType) {
ANNOTATION -> firAnnotationList += declarationsConverter.convertAnnotation(it)
ANNOTATION_ENTRY -> firAnnotationList += declarationsConverter.convertAnnotationEntry(it)
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
}
}
return (firExpression as? FirAbstractAnnotatedElement)?.apply {
annotations += firAnnotationList
} ?: FirErrorExpressionImpl(session, null, "Strange annotated expression: ${firExpression?.render()}")
}
/**
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parsePostfixExpression
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitQualifiedExpression
@@ -181,7 +206,7 @@ class ExpressionsConverter(
isSafe = true
isSelector = true
}
else -> if (isSelector) firSelector = visitExpression(it) else firReceiver = visitExpression(it)
else -> if (isSelector) firSelector = getAsFirExpression(it) else firReceiver = getAsFirExpression(it)
}
}
@@ -211,7 +236,7 @@ class ExpressionsConverter(
TYPE_ARGUMENT_LIST -> firTypeArguments += declarationsConverter.convertTypeArguments(it)
VALUE_ARGUMENT_LIST -> firValueArguments += convertValueArguments(it)
LAMBDA_ARGUMENT -> firValueArguments += convertAnnotatedLambda(it)
else -> additionalArgument = visitExpression(it)
else -> additionalArgument = getAsFirExpression(it)
}
}
@@ -294,8 +319,8 @@ class ExpressionsConverter(
private fun convertShortOrLongStringTemplate(shortOrLongString: LighterASTNode): FirExpression {
lateinit var firExpression: FirExpression
shortOrLongString.forEachChildren {
firExpression = visitExpression(it)
shortOrLongString.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) {
firExpression = getAsFirExpression(it)
}
return firExpression
}
@@ -355,24 +380,34 @@ class ExpressionsConverter(
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseArrayAccess
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitArrayAccessExpression
*/
private fun convertArrayAccessExpression(arrayAccess: LighterASTNode): FirFunctionCall {//Pair<LighterASTNode, List<FirExpression>> {
lateinit var expression: FirExpression
val indexes: MutableList<FirExpression> = mutableListOf()
private fun convertArrayAccessExpression(arrayAccess: LighterASTNode): FirFunctionCall {
lateinit var firExpression: FirExpression
val indices: MutableList<FirExpression> = mutableListOf()
arrayAccess.forEachChildren {
when (it.tokenType) {
INDICES -> indexes += visitExpression(it)
else -> if (it.isExpression()) expression = visitExpression(it)
INDICES -> indices += convertIndices(it)
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
}
}
return FirFunctionCallImpl(session, null).apply {
calleeReference = FirSimpleNamedReference(this@ExpressionsConverter.session, null, OperatorNameConventions.GET)
explicitReceiver = expression
for (indexExpression in indexes) {
arguments += indexExpression
}
explicitReceiver = firExpression
arguments += indices
}
}
/**
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseAsCollectionLiteralExpression
*/
private fun convertIndices(indices: LighterASTNode): List<FirExpression> {
val firExpressionList: MutableList<FirExpression> = mutableListOf()
indices.forEachChildren {
if (it.isExpression()) firExpressionList += getAsFirExpression<FirExpression>(it)
}
return firExpressionList
}
/**
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseSimpleNameExpression
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitSimpleNameExpression
@@ -443,7 +478,7 @@ class ExpressionsConverter(
MUL -> isSpread = true
STRING_TEMPLATE -> firExpression = convertStringTemplate(it)
is KtConstantExpressionElementType -> firExpression = convertConstantExpression(it)
else -> if (it.isExpression()) firExpression = visitExpression(it)
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
}
}
return when {
@@ -458,7 +493,7 @@ class ExpressionsConverter(
return when (it.tokenType) {
THIS_EXPRESSION -> convertThisExpression(leftArgNode).calleeReference
REFERENCE_EXPRESSION -> FirSimpleNamedReference(session, null, it.getAsString().nameAsSafeName())
in qualifiedAccessTokens -> (visitExpression(it) as FirQualifiedAccess).let { firQualifiedAccess ->
in qualifiedAccessTokens -> (getAsFirExpression(it) as FirQualifiedAccess).let { firQualifiedAccess ->
container.explicitReceiver = firQualifiedAccess.explicitReceiver
container.safe = firQualifiedAccess.safe
return@let firQualifiedAccess.calleeReference
@@ -43,7 +43,7 @@ fun ExpressionsConverter.convertAssignment(
return convertAssignment(leftArgNode.getExpressionInParentheses(), rightArgAsFir, operation)
}
if (leftArgNode.tokenType == ARRAY_ACCESS_EXPRESSION) {
val arrayAccessFunctionCall = visitExpression(leftArgNode) as FirFunctionCall
val arrayAccessFunctionCall = getAsFirExpression(leftArgNode) as FirFunctionCall
val firArrayExpression = arrayAccessFunctionCall.explicitReceiver!!
val arraySet = if (operation != FirOperation.ASSIGN) {
FirArraySetCallImpl(session, null, rightArgAsFir, operation).apply {
@@ -74,7 +74,7 @@ fun ExpressionsConverter.convertAssignment(
) {
return FirBlockImpl(session, null).apply {
val name = Name.special("<complex-set>")
statements += generateTemporaryVariable(this@convertAssignment.session, null, name, visitExpression(leftArgNode))
statements += generateTemporaryVariable(this@convertAssignment.session, null, name, getAsFirExpression(leftArgNode))
statements += FirVariableAssignmentImpl(this@convertAssignment.session, null, rightArgAsFir, operation).apply {
lValue = FirSimpleNamedReference(this@convertAssignment.session, null, name)
}
@@ -96,12 +96,16 @@ fun ExpressionsConverter.generateIncrementOrDecrementBlock(
}
return FirBlockImpl(session, null).apply {
val tempName = Name.special("<unary>")
val temporaryVariable = generateTemporaryVariable(this@generateIncrementOrDecrementBlock.session, null, tempName, visitExpression(argument))
val temporaryVariable = generateTemporaryVariable(
this@generateIncrementOrDecrementBlock.session, null, tempName, getAsFirExpression(argument)
)
statements += temporaryVariable
val resultName = Name.special("<unary-result>")
val resultInitializer = FirFunctionCallImpl(this@generateIncrementOrDecrementBlock.session, null).apply {
this.calleeReference = FirSimpleNamedReference(this@generateIncrementOrDecrementBlock.session, null, callName)
this.explicitReceiver = generateResolvedAccessExpression(this@generateIncrementOrDecrementBlock.session, null, temporaryVariable)
this.explicitReceiver = generateResolvedAccessExpression(
this@generateIncrementOrDecrementBlock.session, null, temporaryVariable
)
}
val resultVar = generateTemporaryVariable(this@generateIncrementOrDecrementBlock.session, null, resultName, resultInitializer)
val assignment = convertAssignment(
@@ -128,7 +132,9 @@ fun ExpressionsConverter.generateIncrementOrDecrementBlock(
statements += generateResolvedAccessExpression(this@generateIncrementOrDecrementBlock.session, null, resultVar)
} else {
appendAssignment()
statements += generateAccessExpression(this@generateIncrementOrDecrementBlock.session, null, argument.getAsString().nameAsSafeName())
statements += generateAccessExpression(
this@generateIncrementOrDecrementBlock.session, null, argument.getAsString().nameAsSafeName()
)
}
} else {
appendAssignment()
@@ -62,7 +62,7 @@ class FirPartialTransformer(
}
override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Nothing?): CompositeTransformResult<FirDeclaration> {
return if (!visitNamedFunction || (namedFunction is FirAbstractCallableMember && namedFunction.visibility == Visibilities.LOCAL)) {
return if (!visitNamedFunction && namedFunction is FirAbstractCallableMember && namedFunction.visibility == Visibilities.LOCAL) {
DummyFirDeclaration().compose()
} else {
(namedFunction.transformChildren(this, data) as FirNamedFunction).compose()
@@ -73,7 +73,7 @@ class FirPartialTransformer(
memberDeclaration: FirMemberDeclaration,
data: Nothing?
): CompositeTransformResult<FirDeclaration> {
return if (!visitMemberDeclaration || memberDeclaration.visibility == Visibilities.LOCAL) {
return if (!visitMemberDeclaration && memberDeclaration.visibility == Visibilities.LOCAL) {
DummyFirDeclaration().compose()
} else {
(memberDeclaration.transformChildren(this, data) as FirMemberDeclaration).compose()