Write syntactically incorrect constructions processing (light tree to FIR)
This commit is contained in:
committed by
Mikhail Glukhikh
parent
ef535a2d85
commit
c253ff7953
+2
-2
@@ -46,12 +46,12 @@ open class BaseConverter(
|
||||
return kidsRef.get()
|
||||
}
|
||||
|
||||
fun LighterASTNode.getExpressionInParentheses(): LighterASTNode {
|
||||
fun LighterASTNode.getExpressionInParentheses(): LighterASTNode? {
|
||||
this.forEachChildren {
|
||||
if (it.isExpression()) return it
|
||||
}
|
||||
|
||||
throw Exception()
|
||||
return null
|
||||
}
|
||||
|
||||
protected inline fun LighterASTNode.forEachChildren(vararg skipTokens: KtToken, f: (LighterASTNode) -> Unit) {
|
||||
|
||||
+17
-6
@@ -9,6 +9,7 @@ import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.KtNodeType
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.KtNodeTypes.*
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirFunctionTarget
|
||||
@@ -43,10 +44,10 @@ import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
object ConverterUtil {
|
||||
private val expressionSet = listOf(
|
||||
KtNodeTypes.REFERENCE_EXPRESSION,
|
||||
KtNodeTypes.DOT_QUALIFIED_EXPRESSION,
|
||||
KtNodeTypes.LAMBDA_EXPRESSION,
|
||||
KtNodeTypes.FUN
|
||||
REFERENCE_EXPRESSION,
|
||||
DOT_QUALIFIED_EXPRESSION,
|
||||
LAMBDA_EXPRESSION,
|
||||
FUN
|
||||
)
|
||||
|
||||
fun String?.nameAsSafeName(defaultName: String = ""): Name {
|
||||
@@ -157,10 +158,20 @@ object ConverterUtil {
|
||||
inline fun isClassLocal(classNode: LighterASTNode, getParent: LighterASTNode.() -> LighterASTNode?): Boolean {
|
||||
var currentNode: LighterASTNode? = classNode
|
||||
while (currentNode != null) {
|
||||
if (currentNode.tokenType == KtNodeTypes.BLOCK) {
|
||||
val tokenType = currentNode.tokenType
|
||||
val parent = currentNode.getParent()
|
||||
if (tokenType == PROPERTY || tokenType == FUN) {
|
||||
val grandParent = parent?.getParent()
|
||||
when {
|
||||
parent?.tokenType == KT_FILE -> return true
|
||||
parent?.tokenType == CLASS_BODY && !(grandParent?.tokenType == OBJECT_DECLARATION && grandParent?.getParent()?.tokenType == OBJECT_LITERAL) -> return true
|
||||
parent?.tokenType == BLOCK && grandParent?.tokenType == SCRIPT -> return true
|
||||
}
|
||||
}
|
||||
if (tokenType == BLOCK) {
|
||||
return true
|
||||
}
|
||||
currentNode = currentNode.getParent()
|
||||
currentNode = parent
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+106
-67
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.lightTree.converter
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.TokenType
|
||||
import com.intellij.psi.tree.IFileElementType
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
import org.jetbrains.kotlin.KtNodeTypes.*
|
||||
@@ -49,6 +50,7 @@ import org.jetbrains.kotlin.fir.types.impl.*
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
|
||||
class DeclarationsConverter(
|
||||
@@ -141,15 +143,14 @@ class DeclarationsConverter(
|
||||
return packageName
|
||||
}
|
||||
|
||||
private fun convertImportAlias(importAlias: LighterASTNode): String {
|
||||
private fun convertImportAlias(importAlias: LighterASTNode): String? {
|
||||
importAlias.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
IDENTIFIER -> return it.getAsString()
|
||||
}
|
||||
}
|
||||
|
||||
//TODO specify error
|
||||
throw Exception()
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,7 +179,7 @@ class DeclarationsConverter(
|
||||
null,
|
||||
importedFqName,
|
||||
isAllUnder,
|
||||
aliasName.nameAsSafeName()
|
||||
aliasName?.let { Name.identifier(it) }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -332,7 +333,7 @@ class DeclarationsConverter(
|
||||
*/
|
||||
private fun convertClass(classNode: LighterASTNode): FirDeclaration {
|
||||
var modifiers = Modifier(session)
|
||||
lateinit var classKind: ClassKind
|
||||
var classKind: ClassKind = ClassKind.CLASS //TODO
|
||||
var identifier: String? = null
|
||||
val firTypeParameters = mutableListOf<FirTypeParameter>()
|
||||
var primaryConstructor: LighterASTNode? = null
|
||||
@@ -360,17 +361,20 @@ class DeclarationsConverter(
|
||||
}
|
||||
}
|
||||
|
||||
classKind = when {
|
||||
modifiers.isEnum() -> ClassKind.ENUM_CLASS
|
||||
modifiers.isAnnotation() -> ClassKind.ANNOTATION_CLASS
|
||||
else -> classKind
|
||||
}
|
||||
val defaultDelegatedSuperTypeRef = when {
|
||||
modifiers.isEnum() -> implicitEnumType
|
||||
modifiers.isAnnotation() -> implicitAnnotationType
|
||||
modifiers.isEnum() && (classKind == ClassKind.CLASS || classKind == ClassKind.INTERFACE) -> implicitEnumType
|
||||
modifiers.isAnnotation() && (classKind == ClassKind.CLASS || classKind == ClassKind.INTERFACE) -> implicitAnnotationType
|
||||
else -> implicitAnyType
|
||||
}
|
||||
|
||||
if (classKind == ClassKind.CLASS) {
|
||||
classKind = when {
|
||||
modifiers.isEnum() -> ClassKind.ENUM_CLASS
|
||||
modifiers.isAnnotation() -> ClassKind.ANNOTATION_CLASS
|
||||
else -> classKind
|
||||
}
|
||||
}
|
||||
|
||||
val className = identifier.nameAsSafeName(if (modifiers.isCompanion()) "Companion" else "")
|
||||
superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef }
|
||||
val isLocal = isClassLocal(classNode) { getParent() }
|
||||
@@ -387,8 +391,8 @@ class DeclarationsConverter(
|
||||
modifiers.hasActual(),
|
||||
classKind,
|
||||
isInner = modifiers.isInner(),
|
||||
isCompanion = modifiers.isCompanion(),
|
||||
isData = modifiers.isDataClass(),
|
||||
isCompanion = modifiers.isCompanion() && classKind == ClassKind.OBJECT,
|
||||
isData = modifiers.isDataClass() && classKind != ClassKind.OBJECT,
|
||||
isInline = modifiers.hasInline()
|
||||
)
|
||||
firClass.annotations += modifiers.annotations
|
||||
@@ -406,13 +410,16 @@ class DeclarationsConverter(
|
||||
val firPrimaryConstructor = convertPrimaryConstructor(primaryConstructor, classWrapper)
|
||||
firPrimaryConstructor?.let { firClass.declarations += it }
|
||||
|
||||
//parse properties
|
||||
val properties = primaryConstructor
|
||||
.getChildNodesByType(VALUE_PARAMETER_LIST)
|
||||
.flatMap { convertValueParameters(it) }
|
||||
.filter { it.hasValOrVar() }
|
||||
.map { it.toFirProperty() }
|
||||
firClass.addDeclarations(properties)
|
||||
val properties = mutableListOf<FirProperty>()
|
||||
if (primaryConstructor != null && firPrimaryConstructor != null) {
|
||||
//parse properties
|
||||
properties += primaryConstructor
|
||||
.getChildNodesByType(VALUE_PARAMETER_LIST)
|
||||
.flatMap { convertValueParameters(it) }
|
||||
.filter { it.hasValOrVar() }
|
||||
.map { it.toFirProperty() }
|
||||
firClass.addDeclarations(properties)
|
||||
}
|
||||
|
||||
//parse declarations
|
||||
classBody?.let {
|
||||
@@ -465,7 +472,7 @@ class DeclarationsConverter(
|
||||
val classWrapper = ClassWrapper(
|
||||
this@DeclarationsConverter.session, SpecialNames.NO_NAME_PROVIDED, modifiers, ClassKind.OBJECT,
|
||||
hasPrimaryConstructor = false,
|
||||
hasSecondaryConstructor = false,
|
||||
hasSecondaryConstructor = classBody.getChildNodesByType(SECONDARY_CONSTRUCTOR).isNotEmpty(),
|
||||
delegatedSelfTypeRef = delegatedType,
|
||||
delegatedSuperTypeRef = delegatedType,
|
||||
superTypeCallEntry = superTypeCallEntry
|
||||
@@ -490,6 +497,7 @@ class DeclarationsConverter(
|
||||
var hasInitializerList = false
|
||||
val enumSuperTypeCallEntry = mutableListOf<FirExpression>()
|
||||
val firDeclarations = mutableListOf<FirDeclaration>()
|
||||
var classBodyNode: LighterASTNode? = null
|
||||
enumEntry.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||
@@ -498,7 +506,7 @@ class DeclarationsConverter(
|
||||
hasInitializerList = true
|
||||
enumSuperTypeCallEntry += convertInitializerList(it)
|
||||
}
|
||||
CLASS_BODY -> firDeclarations += convertClassBody(it, classWrapper)
|
||||
CLASS_BODY -> classBodyNode = it
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,16 +520,23 @@ class DeclarationsConverter(
|
||||
)
|
||||
firEnumEntry.annotations += modifiers.annotations
|
||||
|
||||
val defaultDelegatedSuperTypeRef = when {
|
||||
modifiers.isEnum() -> implicitEnumType
|
||||
modifiers.isAnnotation() -> implicitAnnotationType
|
||||
else -> implicitAnyType
|
||||
}
|
||||
|
||||
val enumClassWrapper = ClassWrapper(
|
||||
session, enumEntryName, modifiers, ClassKind.ENUM_ENTRY,
|
||||
hasPrimaryConstructor = true, hasSecondaryConstructor = false,
|
||||
hasPrimaryConstructor = true,
|
||||
hasSecondaryConstructor = classBodyNode.getChildNodesByType(SECONDARY_CONSTRUCTOR).isNotEmpty(),
|
||||
delegatedSelfTypeRef = toDelegatedSelfType(firEnumEntry),
|
||||
delegatedSuperTypeRef = if (hasInitializerList) classWrapper.getFirUserTypeFromClassName() else implicitAnyType,
|
||||
delegatedSuperTypeRef = if (hasInitializerList) classWrapper.getFirUserTypeFromClassName() else defaultDelegatedSuperTypeRef,
|
||||
superTypeCallEntry = enumSuperTypeCallEntry
|
||||
)
|
||||
firEnumEntry.superTypeRefs += enumClassWrapper.delegatedSuperTypeRef
|
||||
val firEnumPrimaryConstructor = convertPrimaryConstructor(null, enumClassWrapper)!!
|
||||
firEnumEntry.addDeclaration(firEnumPrimaryConstructor)
|
||||
convertPrimaryConstructor(null, enumClassWrapper)?.let { firEnumEntry.addDeclaration(it) }
|
||||
classBodyNode?.also { firDeclarations += convertClassBody(it, /*classWrapper*/enumClassWrapper) }
|
||||
firDeclarations.forEach { firEnumEntry.addDeclaration(it) }
|
||||
|
||||
return@withChildClassName firEnumEntry
|
||||
@@ -641,6 +656,10 @@ class DeclarationsConverter(
|
||||
}
|
||||
}
|
||||
|
||||
val delegatedSelfTypeRef =
|
||||
if (classWrapper.isObjectLiteral()) FirErrorTypeRefImpl(session, null, "Constructor in object")
|
||||
else classWrapper.delegatedSelfTypeRef
|
||||
|
||||
val firConstructor = FirConstructorImpl(
|
||||
session,
|
||||
null,
|
||||
@@ -648,13 +667,13 @@ class DeclarationsConverter(
|
||||
modifiers.getVisibility(),
|
||||
modifiers.hasExpect(),
|
||||
modifiers.hasActual(),
|
||||
classWrapper.delegatedSelfTypeRef,
|
||||
delegatedSelfTypeRef,
|
||||
constructorDelegationCall
|
||||
)
|
||||
|
||||
FunctionUtil.firFunctions += firConstructor
|
||||
firConstructor.annotations += modifiers.annotations
|
||||
firConstructor.typeParameters += ConverterUtil.typeParametersFromSelfType(classWrapper.delegatedSelfTypeRef)
|
||||
firConstructor.typeParameters += ConverterUtil.typeParametersFromSelfType(delegatedSelfTypeRef)
|
||||
firConstructor.valueParameters += firValueParameters.map { it.firValueParameter }
|
||||
firConstructor.body = convertFunctionBody(block, null)
|
||||
FunctionUtil.firFunctions.removeLast()
|
||||
@@ -680,10 +699,15 @@ class DeclarationsConverter(
|
||||
|
||||
val isImplicit = constructorDelegationCall.getAsString().isEmpty()
|
||||
val isThis = (isImplicit && classWrapper.hasPrimaryConstructor) || thisKeywordPresent
|
||||
val delegatedType = when {
|
||||
isThis -> classWrapper.delegatedSelfTypeRef
|
||||
else -> classWrapper.delegatedSuperTypeRef
|
||||
}
|
||||
val delegatedType =
|
||||
if (classWrapper.isObjectLiteral() || classWrapper.isInterface()) when {
|
||||
isThis -> FirErrorTypeRefImpl(session, null, "Constructor in object")
|
||||
else -> FirErrorTypeRefImpl(session, null, "No super type")
|
||||
}
|
||||
else when {
|
||||
isThis -> classWrapper.delegatedSelfTypeRef
|
||||
else -> classWrapper.delegatedSuperTypeRef
|
||||
}
|
||||
|
||||
return FirDelegatedConstructorCallImpl(
|
||||
session,
|
||||
@@ -698,7 +722,7 @@ class DeclarationsConverter(
|
||||
*/
|
||||
private fun convertTypeAlias(typeAlias: LighterASTNode): FirDeclaration {
|
||||
var modifiers = Modifier(session)
|
||||
lateinit var identifier: String
|
||||
var identifier: String? = null
|
||||
lateinit var firType: FirTypeRef
|
||||
val firTypeParameters = mutableListOf<FirTypeParameter>()
|
||||
typeAlias.forEachChildren {
|
||||
@@ -733,10 +757,10 @@ class DeclarationsConverter(
|
||||
*/
|
||||
fun convertPropertyDeclaration(property: LighterASTNode): FirDeclaration {
|
||||
var modifiers = Modifier(session)
|
||||
lateinit var identifier: String
|
||||
var identifier: String? = null
|
||||
val firTypeParameters = mutableListOf<FirTypeParameter>()
|
||||
var isReturnType = false
|
||||
var firDelegateExpression: FirExpression? = null
|
||||
var delegateExpression: LighterASTNode? = null
|
||||
var isVar = false
|
||||
var receiverType: FirTypeRef? = null
|
||||
var returnType: FirTypeRef = implicitType
|
||||
@@ -752,13 +776,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.getAsFirExpression(it)
|
||||
PROPERTY_DELEGATE -> delegateExpression = 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.getAsFirExpression(it)
|
||||
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it, "Should have initializer")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -774,7 +798,7 @@ class DeclarationsConverter(
|
||||
returnType,
|
||||
isVar,
|
||||
firExpression,
|
||||
delegate = firDelegateExpression
|
||||
delegate = delegateExpression?.let { expressionConverter.getAsFirExpression(it, "Incorrect delegate expression") }
|
||||
).apply {
|
||||
annotations += modifiers.annotations
|
||||
}
|
||||
@@ -797,7 +821,7 @@ class DeclarationsConverter(
|
||||
firExpression,
|
||||
getter ?: FirDefaultPropertyGetter(session, null, returnType, modifiers.getVisibility()),
|
||||
if (isVar) setter ?: FirDefaultPropertySetter(session, null, returnType, modifiers.getVisibility()) else null,
|
||||
firDelegateExpression
|
||||
delegateExpression?.let { expressionConverter.getAsFirExpression(it, "Should have delegate") }
|
||||
).apply {
|
||||
this.typeParameters += firTypeParameters
|
||||
this.joinTypeParameters(typeConstraints)
|
||||
@@ -812,12 +836,13 @@ class DeclarationsConverter(
|
||||
private fun convertDestructingDeclaration(destructingDeclaration: LighterASTNode): DestructuringDeclaration {
|
||||
var isVar = false
|
||||
val entries = mutableListOf<FirVariable<*>>()
|
||||
var firExpression: FirExpression? = null
|
||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Destructuring declaration without initializer")
|
||||
destructingDeclaration.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
VAR_KEYWORD -> isVar = true
|
||||
DESTRUCTURING_DECLARATION_ENTRY -> entries += convertDestructingDeclarationEntry(it)
|
||||
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it)
|
||||
else -> if (it.isExpression()) firExpression =
|
||||
expressionConverter.getAsFirExpression(it, "Destructuring declaration without initializer")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,7 +854,7 @@ class DeclarationsConverter(
|
||||
*/
|
||||
private fun convertDestructingDeclarationEntry(entry: LighterASTNode): FirVariable<*> {
|
||||
var modifiers = Modifier(session)
|
||||
lateinit var identifier: String
|
||||
var identifier: String? = null
|
||||
var firType: FirTypeRef? = null
|
||||
entry.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
@@ -882,7 +907,7 @@ class DeclarationsConverter(
|
||||
firAccessor.valueParameters += firValueParameters
|
||||
}
|
||||
|
||||
firAccessor.body = convertFunctionBody(block, expression?.let { expressionConverter.getAsFirExpression(it) })
|
||||
firAccessor.body = convertFunctionBody(block, expression)
|
||||
FunctionUtil.firFunctions.removeLast()
|
||||
return firAccessor
|
||||
}
|
||||
@@ -909,11 +934,11 @@ class DeclarationsConverter(
|
||||
firValueParameter.name,
|
||||
if (firValueParameter.returnTypeRef == implicitType) propertyTypeRef else firValueParameter.returnTypeRef,
|
||||
firValueParameter.defaultValue,
|
||||
isCrossinline = modifiers.hasCrossinline(),
|
||||
isNoinline = modifiers.hasNoinline(),
|
||||
isVararg = modifiers.hasVararg()
|
||||
isCrossinline = modifiers.hasCrossinline() || firValueParameter.isCrossinline,
|
||||
isNoinline = modifiers.hasNoinline() || firValueParameter.isNoinline,
|
||||
isVararg = modifiers.hasVararg() || firValueParameter.isVararg
|
||||
).apply {
|
||||
annotations += modifiers.annotations
|
||||
annotations += modifiers.annotations + firValueParameter.annotations
|
||||
}
|
||||
}
|
||||
|
||||
@@ -924,30 +949,32 @@ class DeclarationsConverter(
|
||||
var modifiers = Modifier(session)
|
||||
var identifier: String? = null
|
||||
val firTypeParameters = mutableListOf<FirTypeParameter>()
|
||||
val valueParametersList = mutableListOf<ValueParameter>()
|
||||
var valueParametersList: LighterASTNode? = null
|
||||
var isReturnType = false
|
||||
var receiverType: FirTypeRef? = null
|
||||
var returnType: FirTypeRef? = null
|
||||
val typeConstraints = mutableListOf<TypeConstraint>()
|
||||
var block: LighterASTNode? = null
|
||||
var expression: LighterASTNode? = null
|
||||
var hasEqToken = false
|
||||
functionDeclaration.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||
IDENTIFIER -> identifier = it.getAsString()
|
||||
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
||||
VALUE_PARAMETER_LIST -> valueParametersList += convertValueParameters(it)
|
||||
VALUE_PARAMETER_LIST -> valueParametersList = it //must convert later, because it can contains "return"
|
||||
COLON -> isReturnType = true
|
||||
TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it)
|
||||
TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
|
||||
BLOCK -> block = it
|
||||
EQ -> hasEqToken = true
|
||||
else -> if (it.isExpression()) expression = it
|
||||
}
|
||||
}
|
||||
|
||||
if (returnType == null) {
|
||||
returnType =
|
||||
if (block != null || (block == null && expression == null)) implicitUnitType
|
||||
if (block != null || !hasEqToken) implicitUnitType
|
||||
else implicitType
|
||||
}
|
||||
|
||||
@@ -986,8 +1013,8 @@ class DeclarationsConverter(
|
||||
firFunction.joinTypeParameters(typeConstraints)
|
||||
}
|
||||
|
||||
firFunction.valueParameters += valueParametersList.map { it.firValueParameter }
|
||||
firFunction.body = convertFunctionBody(block, expression?.let { expressionConverter.getAsFirExpression(it) })
|
||||
valueParametersList?.let { firFunction.valueParameters += convertValueParameters(it).map { it.firValueParameter } }
|
||||
firFunction.body = convertFunctionBody(block, expression)
|
||||
FunctionUtil.firFunctions.removeLast()
|
||||
return firFunction
|
||||
}
|
||||
@@ -996,10 +1023,13 @@ class DeclarationsConverter(
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseFunctionBody
|
||||
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.buildFirBody
|
||||
*/
|
||||
private fun convertFunctionBody(blockNode: LighterASTNode?, firExpression: FirExpression?): FirBlock? {
|
||||
private fun convertFunctionBody(blockNode: LighterASTNode?, expression: LighterASTNode?): FirBlock? {
|
||||
return when {
|
||||
blockNode != null -> return convertBlock(blockNode)
|
||||
firExpression != null -> FirSingleExpressionBlock(session, firExpression.toReturn())
|
||||
expression != null -> FirSingleExpressionBlock(
|
||||
session,
|
||||
expressionConverter.getAsFirExpression<FirExpression>(expression, "Function has no body (but should)").toReturn()
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -1081,11 +1111,11 @@ class DeclarationsConverter(
|
||||
*/
|
||||
private fun convertExplicitDelegation(explicitDelegation: LighterASTNode): FirDelegatedTypeRef {
|
||||
lateinit var firTypeRef: FirTypeRef
|
||||
var firExpression: FirExpression? = null
|
||||
var firExpression: FirExpression? = FirErrorExpressionImpl(session, null, "Should have delegate")
|
||||
explicitDelegation.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
TYPE_REFERENCE -> firTypeRef = convertType(it)
|
||||
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it)
|
||||
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it, "Should have delegate")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1143,7 +1173,7 @@ class DeclarationsConverter(
|
||||
*/
|
||||
private fun convertTypeParameter(typeParameter: LighterASTNode): FirTypeParameter {
|
||||
var typeParameterModifiers = TypeParameterModifier(session)
|
||||
lateinit var identifier: String
|
||||
var identifier: String? = null
|
||||
var firType: FirTypeRef? = null
|
||||
typeParameter.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
@@ -1171,16 +1201,22 @@ class DeclarationsConverter(
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeRef
|
||||
*/
|
||||
fun convertType(type: LighterASTNode): FirTypeRef {
|
||||
if (type.getAsString().isEmpty()) {
|
||||
return FirErrorTypeRefImpl(session, null, "Unwrapped type is null")
|
||||
}
|
||||
var typeModifiers = TypeModifier(session) //TODO what with suspend?
|
||||
lateinit var firType: FirTypeRef
|
||||
var firType: FirTypeRef = FirErrorTypeRefImpl(session, null, "Incomplete code")
|
||||
var afterLPar = false
|
||||
type.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
LPAR -> afterLPar = true
|
||||
TYPE_REFERENCE -> firType = convertType(it)
|
||||
MODIFIER_LIST -> typeModifiers = convertTypeModifierList(it)
|
||||
USER_TYPE -> firType = convertUserType(it).also { firUserType -> (firUserType as FirUserTypeRefImpl).qualifier.reverse() }
|
||||
MODIFIER_LIST -> if (!afterLPar || typeModifiers.hasNoAnnotations()) typeModifiers = convertTypeModifierList(it)
|
||||
USER_TYPE -> firType = convertUserType(it)
|
||||
NULLABLE_TYPE -> firType = convertNullableType(it)
|
||||
FUNCTION_TYPE -> firType = convertFunctionType(it)
|
||||
DYNAMIC_TYPE -> firType = FirDynamicTypeRefImpl(session, null, false)
|
||||
TokenType.ERROR_ELEMENT -> firType = FirErrorTypeRefImpl(session, null, "Unwrapped type is null")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1209,7 +1245,7 @@ class DeclarationsConverter(
|
||||
nullableType.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
USER_TYPE -> firType =
|
||||
convertUserType(it, true).also { firUserType -> (firUserType as FirUserTypeRefImpl).qualifier.reverse() }
|
||||
convertUserType(it, true)
|
||||
FUNCTION_TYPE -> firType = convertFunctionType(it, true)
|
||||
NULLABLE_TYPE -> firType = convertNullableType(it)
|
||||
DYNAMIC_TYPE -> firType = FirDynamicTypeRefImpl(session, null, true)
|
||||
@@ -1222,18 +1258,21 @@ class DeclarationsConverter(
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseUserType
|
||||
*/
|
||||
private fun convertUserType(userType: LighterASTNode, isNullable: Boolean = false): FirUserTypeRef {
|
||||
private fun convertUserType(userType: LighterASTNode, isNullable: Boolean = false): FirTypeRef {
|
||||
var simpleFirUserType: FirUserTypeRef? = null
|
||||
lateinit var identifier: String
|
||||
var identifier: String? = null
|
||||
val firTypeArguments = mutableListOf<FirTypeProjection>()
|
||||
userType.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
USER_TYPE -> simpleFirUserType = convertUserType(it) //simple user type
|
||||
USER_TYPE -> simpleFirUserType = convertUserType(it) as? FirUserTypeRef //simple user type
|
||||
REFERENCE_EXPRESSION -> identifier = it.getAsString()
|
||||
TYPE_ARGUMENT_LIST -> firTypeArguments += convertTypeArguments(it)
|
||||
}
|
||||
}
|
||||
|
||||
if (identifier == null)
|
||||
return FirErrorTypeRefImpl(session, null, "Incomplete user type")
|
||||
|
||||
val qualifier = FirQualifierPartImpl(
|
||||
identifier.nameAsSafeName()
|
||||
).apply { typeArguments += firTypeArguments }
|
||||
@@ -1244,7 +1283,7 @@ class DeclarationsConverter(
|
||||
isNullable
|
||||
).apply {
|
||||
this.qualifier.add(qualifier)
|
||||
simpleFirUserType?.qualifier?.let { this@apply.qualifier.addAll(it) }
|
||||
simpleFirUserType?.qualifier?.let { this@apply.qualifier.addAll(0, it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1338,7 +1377,7 @@ class DeclarationsConverter(
|
||||
IDENTIFIER -> identifier = it.getAsString()
|
||||
TYPE_REFERENCE -> firType = convertType(it)
|
||||
DESTRUCTURING_DECLARATION -> destructuringDeclaration = convertDestructingDeclaration(it)
|
||||
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it)
|
||||
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it, "Should have default value")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+103
-106
@@ -6,33 +6,31 @@
|
||||
package org.jetbrains.kotlin.fir.lightTree.converter
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.TokenType
|
||||
import com.intellij.psi.impl.source.tree.java.PsiForStatementImpl
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
import org.jetbrains.kotlin.KtNodeTypes.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.builder.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousFunctionImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousObjectImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirErrorLoop
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirVariableImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.fir.labels.FirLabelImpl
|
||||
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringWithoutBacktick
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toReturn
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.pop
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.utils.*
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.ClassWrapper
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirExplicitSuperReference
|
||||
import org.jetbrains.kotlin.fir.references.FirExplicitThisReference
|
||||
@@ -57,12 +55,12 @@ class ExpressionsConverter(
|
||||
private val declarationsConverter: DeclarationsConverter
|
||||
) : BaseConverter(session, tree) {
|
||||
|
||||
inline fun <reified R : FirElement> getAsFirExpression(expression: LighterASTNode): R {
|
||||
return convertExpression(expression) as R
|
||||
inline fun <reified R : FirElement> getAsFirExpression(expression: LighterASTNode?, errorReason: String = ""): R {
|
||||
return expression?.let { convertExpression(it, errorReason) } as? R ?: (FirErrorExpressionImpl(session, null, errorReason) as R)
|
||||
}
|
||||
|
||||
/***** EXPRESSIONS *****/
|
||||
fun convertExpression(expression: LighterASTNode): FirElement {
|
||||
fun convertExpression(expression: LighterASTNode, errorReason: String): FirElement {
|
||||
if (!stubMode) {
|
||||
return when (expression.tokenType) {
|
||||
LAMBDA_EXPRESSION -> {
|
||||
@@ -93,22 +91,28 @@ class ExpressionsConverter(
|
||||
BREAK, CONTINUE -> convertLoopJump(expression)
|
||||
RETURN -> convertReturn(expression)
|
||||
THROW -> convertThrow(expression)
|
||||
PARENTHESIZED, PROPERTY_DELEGATE, INDICES -> convertExpression(expression.getExpressionInParentheses())
|
||||
PARENTHESIZED -> getAsFirExpression(expression.getExpressionInParentheses(), "Empty parentheses")
|
||||
PROPERTY_DELEGATE, INDICES, CONDITION, LOOP_RANGE ->
|
||||
getAsFirExpression(expression.getExpressionInParentheses(), errorReason)
|
||||
THIS_EXPRESSION -> convertThisExpression(expression)
|
||||
SUPER_EXPRESSION -> convertSuperExpression(expression)
|
||||
|
||||
OBJECT_LITERAL -> declarationsConverter.convertObjectLiteral(expression)
|
||||
FUN -> declarationsConverter.convertFunctionDeclaration(expression)
|
||||
else -> FirExpressionStub(session, null)
|
||||
else -> FirErrorExpressionImpl(session, null, errorReason)
|
||||
}
|
||||
}
|
||||
|
||||
return FirExpressionStub(session, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseFunctionLiteral
|
||||
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitLambdaExpression
|
||||
*/
|
||||
private fun convertLambdaExpression(lambdaExpression: LighterASTNode): FirExpression {
|
||||
val valueParameterList = mutableListOf<ValueParameter>()
|
||||
lateinit var block: LighterASTNode
|
||||
var block: LighterASTNode? = null
|
||||
lambdaExpression.getChildNodesByType(FUNCTION_LITERAL).first().forEachChildren {
|
||||
when (it.tokenType) {
|
||||
VALUE_PARAMETER_LIST -> valueParameterList += declarationsConverter.convertValueParameters(it)
|
||||
@@ -141,7 +145,8 @@ class ExpressionsConverter(
|
||||
label = FunctionUtil.firLabels.pop() ?: FunctionUtil.firFunctionCalls.lastOrNull()?.calleeReference?.name?.let {
|
||||
FirLabelImpl(this@ExpressionsConverter.session, null, it.asString())
|
||||
}
|
||||
val bodyExpression = declarationsConverter.convertBlockExpression(block)
|
||||
val bodyExpression = block?.let { declarationsConverter.convertBlockExpression(it) }
|
||||
?: FirErrorExpressionImpl(session, null, "Lambda has no body")
|
||||
body = if (bodyExpression is FirBlockImpl) {
|
||||
if (bodyExpression.statements.isEmpty()) {
|
||||
bodyExpression.statements.add(FirUnitExpression(this@ExpressionsConverter.session, null))
|
||||
@@ -167,8 +172,8 @@ class ExpressionsConverter(
|
||||
private fun convertBinaryExpression(binaryExpression: LighterASTNode): FirStatement {
|
||||
var isLeftArgument = true
|
||||
lateinit var operationTokenName: String
|
||||
lateinit var leftArgNode: LighterASTNode
|
||||
lateinit var rightArgAsFir: FirExpression
|
||||
var leftArgNode: LighterASTNode? = null
|
||||
var rightArgAsFir: FirExpression = FirErrorExpressionImpl(session, null, "No right operand")
|
||||
binaryExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
OPERATION_REFERENCE -> {
|
||||
@@ -179,7 +184,7 @@ class ExpressionsConverter(
|
||||
if (isLeftArgument) {
|
||||
leftArgNode = it
|
||||
} else {
|
||||
rightArgAsFir = getAsFirExpression(it)
|
||||
rightArgAsFir = getAsFirExpression(it, "No right operand")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,16 +193,16 @@ class ExpressionsConverter(
|
||||
val operationToken = operationTokenName.getOperationSymbol()
|
||||
when (operationToken) {
|
||||
ELVIS ->
|
||||
return getAsFirExpression<FirExpression>(leftArgNode).generateNotNullOrOther(
|
||||
return getAsFirExpression<FirExpression>(leftArgNode, "No left operand").generateNotNullOrOther(
|
||||
session, rightArgAsFir, "elvis", null
|
||||
)
|
||||
ANDAND, OROR ->
|
||||
return getAsFirExpression<FirExpression>(leftArgNode).generateLazyLogicalOperation(
|
||||
return getAsFirExpression<FirExpression>(leftArgNode, "No left operand").generateLazyLogicalOperation(
|
||||
session, rightArgAsFir, operationToken == ANDAND, null
|
||||
)
|
||||
in OperatorConventions.IN_OPERATIONS ->
|
||||
return rightArgAsFir.generateContainsOperation(
|
||||
session, getAsFirExpression(leftArgNode), operationToken == NOT_IN, null, null
|
||||
session, getAsFirExpression(leftArgNode, "No left operand"), operationToken == NOT_IN, null, null
|
||||
)
|
||||
}
|
||||
val conventionCallName = operationToken.toBinaryName()
|
||||
@@ -207,7 +212,7 @@ class ExpressionsConverter(
|
||||
this@ExpressionsConverter.session, null,
|
||||
conventionCallName ?: operationTokenName.nameAsSafeName()
|
||||
)
|
||||
explicitReceiver = getAsFirExpression(leftArgNode)
|
||||
explicitReceiver = getAsFirExpression(leftArgNode, "No left operand")
|
||||
arguments += rightArgAsFir
|
||||
}
|
||||
} else {
|
||||
@@ -216,7 +221,7 @@ class ExpressionsConverter(
|
||||
return convertAssignment(leftArgNode, rightArgAsFir, firOperation)
|
||||
} else {
|
||||
FirOperatorCallImpl(session, null, firOperation).apply {
|
||||
arguments += getAsFirExpression<FirExpression>(leftArgNode)
|
||||
arguments += getAsFirExpression<FirExpression>(leftArgNode, "No left operand")
|
||||
arguments += rightArgAsFir
|
||||
}
|
||||
}
|
||||
@@ -229,13 +234,13 @@ class ExpressionsConverter(
|
||||
*/
|
||||
private fun convertBinaryWithType(binaryExpression: LighterASTNode): FirTypeOperatorCall {
|
||||
lateinit var operationTokenName: String
|
||||
lateinit var leftArgAsFir: FirExpression
|
||||
var leftArgAsFir: FirExpression = FirErrorExpressionImpl(session, null, "No left operand")
|
||||
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)
|
||||
else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it, "No left operand")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,13 +255,13 @@ class ExpressionsConverter(
|
||||
*/
|
||||
private fun convertIsExpression(isExpression: LighterASTNode): FirTypeOperatorCall {
|
||||
lateinit var operationTokenName: String
|
||||
lateinit var leftArgAsFir: FirExpression
|
||||
var leftArgAsFir: FirExpression = FirErrorExpressionImpl(session, null, "No left operand")
|
||||
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)
|
||||
else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it, "No left operand")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,6 +281,8 @@ class ExpressionsConverter(
|
||||
labeledExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
LABEL_QUALIFIER -> FunctionUtil.firLabels += FirLabelImpl(session, null, it.toString().replace("@", ""))
|
||||
BLOCK -> firExpression = declarationsConverter.convertBlock(it)
|
||||
PROPERTY -> firExpression = declarationsConverter.convertPropertyDeclaration(it)
|
||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
|
||||
}
|
||||
}
|
||||
@@ -294,7 +301,7 @@ class ExpressionsConverter(
|
||||
*/
|
||||
private fun convertUnaryExpression(unaryExpression: LighterASTNode): FirExpression {
|
||||
lateinit var operationTokenName: String
|
||||
lateinit var argument: LighterASTNode
|
||||
var argument: LighterASTNode? = null
|
||||
unaryExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
OPERATION_REFERENCE -> operationTokenName = it.getAsString()
|
||||
@@ -304,7 +311,7 @@ class ExpressionsConverter(
|
||||
|
||||
val operationToken = operationTokenName.getOperationSymbol()
|
||||
if (operationToken == EXCLEXCL) {
|
||||
return bangBangToWhen(session, getAsFirExpression(argument))
|
||||
return bangBangToWhen(session, getAsFirExpression(argument, "No operand"))
|
||||
}
|
||||
|
||||
val conventionCallName = operationToken.toUnaryName()
|
||||
@@ -318,12 +325,12 @@ class ExpressionsConverter(
|
||||
}
|
||||
FirFunctionCallImpl(session, null).apply {
|
||||
calleeReference = FirSimpleNamedReference(this@ExpressionsConverter.session, null, conventionCallName)
|
||||
explicitReceiver = getAsFirExpression(argument)
|
||||
explicitReceiver = getAsFirExpression(argument, "No operand")
|
||||
}
|
||||
} else {
|
||||
val firOperation = operationToken.toFirOperation()
|
||||
FirOperatorCallImpl(session, null, firOperation).apply {
|
||||
arguments += getAsFirExpression<FirExpression>(argument)
|
||||
arguments += getAsFirExpression<FirExpression>(argument, "No operand")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -353,9 +360,9 @@ class ExpressionsConverter(
|
||||
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitClassLiteralExpression
|
||||
*/
|
||||
private fun convertClassLiteralExpression(classLiteralExpression: LighterASTNode): FirExpression {
|
||||
lateinit var firReceiverExpression: FirExpression
|
||||
var firReceiverExpression: FirExpression = FirErrorExpressionImpl(session, null, "No receiver in class literal")
|
||||
classLiteralExpression.forEachChildren {
|
||||
if (it.isExpression()) firReceiverExpression = getAsFirExpression(it)
|
||||
if (it.isExpression()) firReceiverExpression = getAsFirExpression(it, "No receiver in class literal")
|
||||
}
|
||||
|
||||
return FirGetClassCallImpl(session, null).apply {
|
||||
@@ -376,7 +383,7 @@ class ExpressionsConverter(
|
||||
COLONCOLON -> isReceiver = false
|
||||
else -> if (it.isExpression()) {
|
||||
if (isReceiver) {
|
||||
firReceiverExpression = getAsFirExpression(it)
|
||||
firReceiverExpression = getAsFirExpression(it, "Incorrect receiver expression")
|
||||
} else {
|
||||
firCallableReference = convertSimpleNameExpression(it)
|
||||
}
|
||||
@@ -397,8 +404,8 @@ class ExpressionsConverter(
|
||||
private fun convertQualifiedExpression(dotQualifiedExpression: LighterASTNode): FirExpression {
|
||||
var isSelector = false
|
||||
var isSafe = false
|
||||
var firSelector: FirExpression? = null //after dot
|
||||
lateinit var firReceiver: FirExpression //before dot
|
||||
var firSelector: FirExpression = FirErrorExpressionImpl(session, null, "Qualified expression without selector") //after dot
|
||||
var firReceiver: FirExpression? = null //before dot
|
||||
dotQualifiedExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
DOT -> isSelector = true
|
||||
@@ -406,20 +413,21 @@ class ExpressionsConverter(
|
||||
isSafe = true
|
||||
isSelector = true
|
||||
}
|
||||
else -> if (isSelector) firSelector = getAsFirExpression(it) else firReceiver = getAsFirExpression(it)
|
||||
else -> {
|
||||
if (isSelector && it.tokenType != TokenType.ERROR_ELEMENT)
|
||||
firSelector = getAsFirExpression(it, "Incorrect selector expression")
|
||||
else
|
||||
firReceiver = getAsFirExpression(it, "Incorrect receiver expression")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (firSelector == null) {
|
||||
return FirErrorExpressionImpl(session, null, "Qualified expression without selector")
|
||||
}
|
||||
|
||||
//TODO use contracts?
|
||||
if (firSelector is FirModifiableQualifiedAccess<*>) {
|
||||
(firSelector as FirModifiableQualifiedAccess<*>).safe = isSafe
|
||||
(firSelector as FirModifiableQualifiedAccess<*>).explicitReceiver = firReceiver
|
||||
}
|
||||
return firSelector!!
|
||||
return firSelector
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,12 +443,13 @@ class ExpressionsConverter(
|
||||
REFERENCE_EXPRESSION -> name = it.getAsString()
|
||||
TYPE_ARGUMENT_LIST -> firTypeArguments += declarationsConverter.convertTypeArguments(it)
|
||||
VALUE_ARGUMENT_LIST, LAMBDA_ARGUMENT -> valueArguments += it
|
||||
else -> additionalArgument = getAsFirExpression(it)
|
||||
else -> if (it.tokenType != TokenType.ERROR_ELEMENT) additionalArgument =
|
||||
getAsFirExpression(it, "Incorrect invoke receiver")
|
||||
}
|
||||
}
|
||||
|
||||
return FirFunctionCallImpl(session, null).apply {
|
||||
val calleeReference = when {
|
||||
this.calleeReference = when {
|
||||
name != null -> FirSimpleNamedReference(this@ExpressionsConverter.session, null, name.nameAsSafeName())
|
||||
additionalArgument != null -> {
|
||||
arguments += additionalArgument!!
|
||||
@@ -448,7 +457,7 @@ class ExpressionsConverter(
|
||||
}
|
||||
else -> FirErrorNamedReference(this@ExpressionsConverter.session, null, "Call has no callee")
|
||||
}
|
||||
this.calleeReference = calleeReference
|
||||
|
||||
FunctionUtil.firFunctionCalls += this
|
||||
this.extractArgumentsFrom(valueArguments.flatMap { convertValueArguments(it) }, stubMode)
|
||||
typeArguments += firTypeArguments
|
||||
@@ -472,8 +481,11 @@ class ExpressionsConverter(
|
||||
FirConstExpressionImpl(session, null, IrConstKind.String, it.getAsString())
|
||||
}
|
||||
ESCAPE_STRING_TEMPLATE_ENTRY -> {
|
||||
sb.append(escapedStringToCharacter(it.getAsString()))
|
||||
FirConstExpressionImpl(session, null, IrConstKind.String, escapedStringToCharacter(it.getAsString())?.toString() ?: "")
|
||||
val escape = it.getAsString()
|
||||
val unescaped = escapedStringToCharacter(escape)?.toString()
|
||||
?: escape.replace("\\", "").replace("u", "\\u")
|
||||
sb.append(unescaped)
|
||||
FirConstExpressionImpl(session, null, IrConstKind.String, unescaped)
|
||||
}
|
||||
SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> {
|
||||
hasExpressions = true
|
||||
@@ -503,9 +515,9 @@ class ExpressionsConverter(
|
||||
}
|
||||
|
||||
private fun convertShortOrLongStringTemplate(shortOrLongString: LighterASTNode): FirExpression {
|
||||
lateinit var firExpression: FirExpression
|
||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Incorrect template argument")
|
||||
shortOrLongString.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) {
|
||||
firExpression = getAsFirExpression(it)
|
||||
firExpression = getAsFirExpression(it, "Incorrect template argument")
|
||||
}
|
||||
return firExpression
|
||||
}
|
||||
@@ -571,22 +583,24 @@ class ExpressionsConverter(
|
||||
val whenEntries = mutableListOf<WhenEntry>()
|
||||
whenExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
PROPERTY -> subjectVariable = declarationsConverter.convertPropertyDeclaration(it) as FirVariable<*>
|
||||
DESTRUCTURING_DECLARATION -> subjectExpression = getAsFirExpression(it)
|
||||
PROPERTY -> subjectVariable = (declarationsConverter.convertPropertyDeclaration(it) as FirVariable<*>).let { variable ->
|
||||
FirVariableImpl(
|
||||
session, null, variable.name, variable.returnTypeRef,
|
||||
isVar = false, initializer = variable.initializer
|
||||
)
|
||||
}
|
||||
DESTRUCTURING_DECLARATION -> subjectExpression =
|
||||
getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.getAsString()}")
|
||||
WHEN_ENTRY -> whenEntries += convertWhenEntry(it)
|
||||
else -> if (it.isExpression()) subjectExpression = getAsFirExpression(it)
|
||||
else -> if (it.isExpression()) subjectExpression =
|
||||
getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.getAsString()}")
|
||||
}
|
||||
}
|
||||
|
||||
subjectExpression = subjectVariable?.initializer ?: subjectExpression
|
||||
val hasSubject = subjectExpression != null
|
||||
val subject = FirWhenSubject()
|
||||
return FirWhenExpressionImpl(
|
||||
session,
|
||||
null,
|
||||
subjectExpression,
|
||||
subjectVariable
|
||||
).apply {
|
||||
return FirWhenExpressionImpl(session, null, subjectExpression, subjectVariable).apply {
|
||||
if (hasSubject) {
|
||||
subject.bind(this)
|
||||
}
|
||||
@@ -615,7 +629,7 @@ class ExpressionsConverter(
|
||||
*/
|
||||
private fun convertWhenEntry(whenEntry: LighterASTNode): WhenEntry {
|
||||
var isElse = false
|
||||
lateinit var firBlock: FirBlock
|
||||
var firBlock: FirBlock = FirEmptyExpressionBlock(session)
|
||||
val conditions = mutableListOf<FirExpression>()
|
||||
whenEntry.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
@@ -632,10 +646,10 @@ class ExpressionsConverter(
|
||||
}
|
||||
|
||||
private fun convertWhenConditionExpression(whenCondition: LighterASTNode): FirExpression {
|
||||
lateinit var firExpression: FirExpression
|
||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "No expression in condition with expression")
|
||||
whenCondition.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
|
||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "No expression in condition with expression")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -646,7 +660,7 @@ class ExpressionsConverter(
|
||||
|
||||
private fun convertWhenConditionInRange(whenCondition: LighterASTNode): FirExpression {
|
||||
var isNegate = false
|
||||
lateinit var firExpression: FirExpression
|
||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "No range in condition with range")
|
||||
whenCondition.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
NOT_IN -> isNegate = true
|
||||
@@ -680,12 +694,12 @@ class ExpressionsConverter(
|
||||
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitArrayAccessExpression
|
||||
*/
|
||||
private fun convertArrayAccessExpression(arrayAccess: LighterASTNode): FirFunctionCall {
|
||||
lateinit var firExpression: FirExpression
|
||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "No array expression")
|
||||
val indices: MutableList<FirExpression> = mutableListOf()
|
||||
arrayAccess.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
INDICES -> indices += convertIndices(it)
|
||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
|
||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "No array expression")
|
||||
}
|
||||
}
|
||||
return FirFunctionCallImpl(session, null).apply {
|
||||
@@ -701,7 +715,7 @@ class ExpressionsConverter(
|
||||
private fun convertCollectionLiteralExpresion(expression: LighterASTNode): FirExpression {
|
||||
val firExpressionList = mutableListOf<FirExpression>()
|
||||
expression.forEachChildren {
|
||||
if (it.isExpression()) firExpressionList += getAsFirExpression<FirExpression>(it)
|
||||
if (it.isExpression()) firExpressionList += getAsFirExpression<FirExpression>(it, "Incorrect collection literal argument")
|
||||
}
|
||||
|
||||
return FirArrayOfCallImpl(session, null).apply {
|
||||
@@ -715,7 +729,7 @@ class ExpressionsConverter(
|
||||
private fun convertIndices(indices: LighterASTNode): List<FirExpression> {
|
||||
val firExpressionList: MutableList<FirExpression> = mutableListOf()
|
||||
indices.forEachChildren {
|
||||
if (it.isExpression()) firExpressionList += getAsFirExpression<FirExpression>(it)
|
||||
if (it.isExpression()) firExpressionList += getAsFirExpression<FirExpression>(it, "Incorrect index expression")
|
||||
}
|
||||
|
||||
return firExpressionList
|
||||
@@ -738,17 +752,15 @@ class ExpressionsConverter(
|
||||
*/
|
||||
private fun convertDoWhile(doWhileLoop: LighterASTNode): FirElement {
|
||||
var block: LighterASTNode? = null
|
||||
var condition: FirExpression? = null
|
||||
var firCondition: FirExpression = FirErrorExpressionImpl(session, null, "No condition in do-while loop")
|
||||
doWhileLoop.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
BODY -> block = it
|
||||
CONDITION -> condition = convertCondition(it)
|
||||
CONDITION -> firCondition = getAsFirExpression(it, "No condition in do-while loop")
|
||||
}
|
||||
}
|
||||
|
||||
return FirDoWhileLoopImpl(
|
||||
session, null, condition ?: FirErrorExpressionImpl(session, null, "No condition in do-while loop")
|
||||
).configure { convertLoopBody(block) }
|
||||
return FirDoWhileLoopImpl(session, null, firCondition).configure { convertLoopBody(block) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -757,17 +769,15 @@ class ExpressionsConverter(
|
||||
*/
|
||||
private fun convertWhile(whileLoop: LighterASTNode): FirElement {
|
||||
var block: LighterASTNode? = null
|
||||
var condition: FirExpression? = null
|
||||
var firCondition: FirExpression = FirErrorExpressionImpl(session, null, "No condition in while loop")
|
||||
whileLoop.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
BODY -> block = it
|
||||
CONDITION -> condition = convertCondition(it)
|
||||
CONDITION -> firCondition = getAsFirExpression(it, "No condition in while loop")
|
||||
}
|
||||
}
|
||||
|
||||
return FirWhileLoopImpl(
|
||||
session, null, condition ?: FirErrorExpressionImpl(session, null, "No condition in while loop")
|
||||
).configure { convertLoopBody(block) }
|
||||
return FirWhileLoopImpl(session, null, firCondition).configure { convertLoopBody(block) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -781,7 +791,7 @@ class ExpressionsConverter(
|
||||
forLoop.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
VALUE_PARAMETER -> parameter = declarationsConverter.convertValueParameter(it)
|
||||
LOOP_RANGE -> convertCondition(it)?.apply { rangeExpression = this }
|
||||
LOOP_RANGE -> rangeExpression = getAsFirExpression(it, "No range in for loop")
|
||||
BODY -> blockNode = it
|
||||
}
|
||||
}
|
||||
@@ -873,7 +883,7 @@ class ExpressionsConverter(
|
||||
tryExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
BLOCK -> tryBlock = declarationsConverter.convertBlock(it)
|
||||
CATCH -> catchClauses += convertCatchClause(it)
|
||||
CATCH -> convertCatchClause(it)?.also { oneClause -> catchClauses += oneClause }
|
||||
FINALLY -> finallyBlock = convertFinally(it)
|
||||
}
|
||||
}
|
||||
@@ -888,12 +898,12 @@ class ExpressionsConverter(
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseTry
|
||||
*/
|
||||
private fun convertCatchClause(catchClause: LighterASTNode): Pair<ValueParameter?, FirBlock> {
|
||||
private fun convertCatchClause(catchClause: LighterASTNode): Pair<ValueParameter?, FirBlock>? {
|
||||
var valueParameter: ValueParameter? = null
|
||||
var blockNode: LighterASTNode? = null
|
||||
catchClause.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
VALUE_PARAMETER_LIST -> valueParameter = declarationsConverter.convertValueParameters(it).first()
|
||||
VALUE_PARAMETER_LIST -> valueParameter = declarationsConverter.convertValueParameters(it).firstOrNull() ?: return null
|
||||
BLOCK -> blockNode = it
|
||||
}
|
||||
}
|
||||
@@ -920,20 +930,18 @@ class ExpressionsConverter(
|
||||
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitIfExpression
|
||||
*/
|
||||
private fun convertIfExpression(ifExpression: LighterASTNode): FirExpression {
|
||||
var condition: FirExpression? = null
|
||||
var firCondition: FirExpression = FirErrorExpressionImpl(session, null, "If statement should have condition")
|
||||
var thenBlock: LighterASTNode? = null
|
||||
var elseBlock: LighterASTNode? = null
|
||||
ifExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
CONDITION -> condition = convertCondition(it)
|
||||
CONDITION -> firCondition = getAsFirExpression(it, "If statement should have condition")
|
||||
THEN -> thenBlock = it
|
||||
ELSE -> elseBlock = it
|
||||
}
|
||||
}
|
||||
|
||||
return FirWhenExpressionImpl(session, null).apply {
|
||||
val firCondition =
|
||||
condition ?: FirErrorExpressionImpl(this@ExpressionsConverter.session, null, "If statement should have condition")
|
||||
val trueBranch = convertLoopBody(thenBlock)
|
||||
branches += FirWhenBranchImpl(this@ExpressionsConverter.session, null, firCondition, trueBranch)
|
||||
val elseBranch = convertLoopBody(elseBlock)
|
||||
@@ -943,17 +951,6 @@ class ExpressionsConverter(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseCondition
|
||||
*/
|
||||
private fun convertCondition(condition: LighterASTNode): FirExpression? {
|
||||
condition.forEachChildren {
|
||||
if (it.isExpression()) return getAsFirExpression(it)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseJump
|
||||
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitBreakExpression
|
||||
@@ -997,16 +994,15 @@ class ExpressionsConverter(
|
||||
*/
|
||||
private fun convertReturn(returnExpression: LighterASTNode): FirExpression {
|
||||
var labelName: String? = null
|
||||
var firExpression: FirExpression? = null
|
||||
var firExpression: FirExpression = FirUnitExpression(session, null)
|
||||
returnExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
LABEL_QUALIFIER -> labelName = it.getAsString().replace("@", "")
|
||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
|
||||
LABEL_QUALIFIER -> labelName = it.getAsStringWithoutBacktick().replace("@", "")
|
||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "Incorrect return expression")
|
||||
}
|
||||
}
|
||||
|
||||
val result = firExpression ?: FirUnitExpression(session, null)
|
||||
return result.toReturn(labelName)
|
||||
return firExpression.toReturn(labelName)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1014,12 +1010,12 @@ class ExpressionsConverter(
|
||||
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitThrowExpression
|
||||
*/
|
||||
private fun convertThrow(throwExpression: LighterASTNode): FirExpression {
|
||||
var firExpression: FirExpression? = null
|
||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Nothing to throw")
|
||||
throwExpression.forEachChildren {
|
||||
if (it.isExpression()) firExpression = getAsFirExpression(it)
|
||||
if (it.isExpression()) firExpression = getAsFirExpression(it, "Nothing to throw")
|
||||
}
|
||||
|
||||
return FirThrowExpressionImpl(session, null, firExpression ?: FirErrorExpressionImpl(session, null, "Nothing to throw"))
|
||||
return FirThrowExpressionImpl(session, null, firExpression)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1077,14 +1073,14 @@ class ExpressionsConverter(
|
||||
private fun convertValueArgument(valueArgument: LighterASTNode): FirExpression {
|
||||
var identifier: String? = null
|
||||
var isSpread = false
|
||||
lateinit var firExpression: FirExpression
|
||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Argument is absent")
|
||||
valueArgument.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
VALUE_ARGUMENT_NAME -> identifier = it.getAsString()
|
||||
MUL -> isSpread = true
|
||||
STRING_TEMPLATE -> firExpression = convertStringTemplate(it)
|
||||
is KtConstantExpressionElementType -> firExpression = convertConstantExpression(it)
|
||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
|
||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "Argument is absent")
|
||||
}
|
||||
}
|
||||
return when {
|
||||
@@ -1097,15 +1093,16 @@ class ExpressionsConverter(
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.initializeLValue
|
||||
*/
|
||||
fun convertLValue(leftArgNode: LighterASTNode, container: FirModifiableQualifiedAccess<*>): FirReference {
|
||||
return when (leftArgNode.tokenType) {
|
||||
fun convertLValue(leftArgNode: LighterASTNode?, container: FirModifiableQualifiedAccess<*>): FirReference {
|
||||
return when (leftArgNode?.tokenType) {
|
||||
null -> FirErrorNamedReference(session, null, "Unsupported LValue: ${leftArgNode?.tokenType}")
|
||||
THIS_EXPRESSION -> convertThisExpression(leftArgNode).calleeReference
|
||||
REFERENCE_EXPRESSION -> FirSimpleNamedReference(session, null, leftArgNode.getAsString().nameAsSafeName())
|
||||
in qualifiedAccessTokens -> (getAsFirExpression(leftArgNode) as FirQualifiedAccess).let { firQualifiedAccess ->
|
||||
in qualifiedAccessTokens -> (getAsFirExpression<FirExpression>(leftArgNode) as? FirQualifiedAccess)?.let { firQualifiedAccess ->
|
||||
container.explicitReceiver = firQualifiedAccess.explicitReceiver
|
||||
container.safe = firQualifiedAccess.safe
|
||||
return@let firQualifiedAccess.calleeReference
|
||||
}
|
||||
} ?: FirErrorNamedReference(session, null, "Unsupported qualified LValue: ${leftArgNode.getAsString()}")
|
||||
PARENTHESIZED -> convertLValue(leftArgNode.getExpressionInParentheses(), container)
|
||||
else -> FirErrorNamedReference(session, null, "Unsupported LValue: ${leftArgNode.tokenType}")
|
||||
}
|
||||
|
||||
+13
-12
@@ -16,16 +16,14 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.pop
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ExpressionsConverter
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.pop
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.DestructuringDeclaration
|
||||
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.parsing.KotlinExpressionParsing
|
||||
@@ -42,16 +40,17 @@ fun String.getOperationSymbol(): IElementType {
|
||||
}
|
||||
|
||||
fun ExpressionsConverter.convertAssignment(
|
||||
leftArgNode: LighterASTNode,
|
||||
leftArgNode: LighterASTNode?,
|
||||
rightArgAsFir: FirExpression,
|
||||
operation: FirOperation
|
||||
): FirStatement {
|
||||
if (leftArgNode.tokenType == PARENTHESIZED) {
|
||||
if (leftArgNode != null && leftArgNode.tokenType == PARENTHESIZED) {
|
||||
return convertAssignment(leftArgNode.getExpressionInParentheses(), rightArgAsFir, operation)
|
||||
}
|
||||
if (leftArgNode.tokenType == ARRAY_ACCESS_EXPRESSION) {
|
||||
if (leftArgNode != null && leftArgNode.tokenType == ARRAY_ACCESS_EXPRESSION) {
|
||||
val arrayAccessFunctionCall = getAsFirExpression(leftArgNode) as FirFunctionCall
|
||||
val firArrayExpression = arrayAccessFunctionCall.explicitReceiver!!
|
||||
val firArrayExpression = arrayAccessFunctionCall.explicitReceiver
|
||||
?: FirErrorExpressionImpl(session, null, "No array expression")
|
||||
val arraySet = if (operation != FirOperation.ASSIGN) {
|
||||
FirArraySetCallImpl(session, null, rightArgAsFir, operation).apply {
|
||||
indexes += arrayAccessFunctionCall.arguments
|
||||
@@ -76,12 +75,14 @@ fun ExpressionsConverter.convertAssignment(
|
||||
}
|
||||
}
|
||||
if (operation != FirOperation.ASSIGN &&
|
||||
leftArgNode.tokenType != REFERENCE_EXPRESSION && leftArgNode.tokenType != THIS_EXPRESSION &&
|
||||
(leftArgNode.tokenType !in qualifiedAccessTokens || getSelectorType(leftArgNode.getChildrenAsArray()) != REFERENCE_EXPRESSION)
|
||||
leftArgNode?.tokenType != REFERENCE_EXPRESSION && leftArgNode?.tokenType != THIS_EXPRESSION &&
|
||||
(leftArgNode?.tokenType !in qualifiedAccessTokens || getSelectorType(leftArgNode.getChildrenAsArray()) != REFERENCE_EXPRESSION)
|
||||
) {
|
||||
return FirBlockImpl(session, null).apply {
|
||||
val name = Name.special("<complex-set>")
|
||||
statements += generateTemporaryVariable(this@convertAssignment.session, null, name, getAsFirExpression(leftArgNode))
|
||||
statements += generateTemporaryVariable(
|
||||
this@convertAssignment.session, null, name, getAsFirExpression(leftArgNode, "No LValue in assignment")
|
||||
)
|
||||
statements += FirVariableAssignmentImpl(this@convertAssignment.session, null, rightArgAsFir, operation).apply {
|
||||
lValue = FirSimpleNamedReference(this@convertAssignment.session, null, name)
|
||||
}
|
||||
@@ -104,7 +105,7 @@ fun ExpressionsConverter.generateIncrementOrDecrementBlock(
|
||||
return FirBlockImpl(session, null).apply {
|
||||
val tempName = Name.special("<unary>")
|
||||
val temporaryVariable = generateTemporaryVariable(
|
||||
this@generateIncrementOrDecrementBlock.session, null, tempName, getAsFirExpression(argument)
|
||||
this@generateIncrementOrDecrementBlock.session, null, tempName, getAsFirExpression(argument, "Incorrect expression inside inc/dec")
|
||||
)
|
||||
statements += temporaryVariable
|
||||
val resultName = Name.special("<unary-result>")
|
||||
|
||||
@@ -30,12 +30,16 @@ class ClassWrapper(
|
||||
val delegatedSuperTypeRef: FirTypeRef,
|
||||
val superTypeCallEntry: MutableList<FirExpression>
|
||||
) {
|
||||
fun isObjectLiteral(): Boolean {
|
||||
return className == SpecialNames.NO_NAME_PROVIDED && isObject()
|
||||
}
|
||||
|
||||
private fun isObject(): Boolean {
|
||||
return classKind == ClassKind.OBJECT
|
||||
}
|
||||
|
||||
private fun isSealed(): Boolean {
|
||||
return modifiers.getModality() == Modality.SEALED
|
||||
return modifiers.hasModality(Modality.SEALED)
|
||||
}
|
||||
|
||||
private fun isEnum(): Boolean {
|
||||
|
||||
+3
-11
@@ -16,18 +16,10 @@ import org.jetbrains.kotlin.fir.lightTree.converter.utils.generateDestructuringB
|
||||
data class DestructuringDeclaration(
|
||||
val isVar: Boolean,
|
||||
val entries: List<FirVariable<*>>,
|
||||
val initializer: FirExpression?
|
||||
val initializer: FirExpression
|
||||
) {
|
||||
fun toFirDestructingDeclaration(session: FirSession): FirExpression {
|
||||
val baseVariable = generateTemporaryVariable(
|
||||
session, null, "destruct",
|
||||
initializer ?: FirErrorExpressionImpl(session, null, "Destructuring declaration without initializer")
|
||||
)
|
||||
return generateDestructuringBlock(
|
||||
session,
|
||||
this,
|
||||
baseVariable,
|
||||
tmpVariable = true
|
||||
)
|
||||
val baseVariable = generateTemporaryVariable(session, null, "destruct", initializer)
|
||||
return generateDestructuringBlock(session, this, baseVariable, tmpVariable = true)
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,9 @@ import org.jetbrains.kotlin.fir.lightTree.converter.ClassNameUtil
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
|
||||
import org.jetbrains.kotlin.fir.references.FirPropertyFromParameterCallableReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
|
||||
|
||||
class ValueParameter(
|
||||
private val isVal: Boolean,
|
||||
@@ -31,7 +34,10 @@ class ValueParameter(
|
||||
|
||||
fun toFirProperty(): FirProperty {
|
||||
val name = this.firValueParameter.name
|
||||
val type = this.firValueParameter.returnTypeRef
|
||||
var type = this.firValueParameter.returnTypeRef
|
||||
if (type is FirImplicitTypeRef) {
|
||||
type = FirErrorTypeRefImpl(this.firValueParameter.session, null, "Incomplete code")
|
||||
}
|
||||
|
||||
return FirMemberPropertyImpl(
|
||||
this.firValueParameter.session,
|
||||
|
||||
@@ -64,9 +64,9 @@ data class WhenEntry(
|
||||
val condition = conditions.first()
|
||||
return when (condition) {
|
||||
is FirOperatorCallImpl -> condition.arguments.first()
|
||||
is FirFunctionCall -> condition.explicitReceiver!!
|
||||
is FirTypeOperatorCallImpl -> condition
|
||||
else -> FirErrorExpressionImpl(session, null, "Unsupported when condition: ${condition.javaClass}")
|
||||
//is FirFunctionCall -> condition.explicitReceiver!!
|
||||
//is FirTypeOperatorCallImpl -> condition
|
||||
else -> FirErrorExpressionImpl(session, null, "No expression in condition with expression")
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
-22
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.lightTree.fir.modifier
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirAbstractAnnotatedElement
|
||||
@@ -24,49 +25,49 @@ class Modifier(
|
||||
session: FirSession,
|
||||
psi: PsiElement? = null,
|
||||
|
||||
private var classModifier: ClassModifier? = null,
|
||||
private val classModifiers: MutableList<ClassModifier> = mutableListOf(),
|
||||
private val memberModifiers: MutableList<MemberModifier> = mutableListOf(),
|
||||
private var visibilityModifier: VisibilityModifier = VisibilityModifier.UNKNOWN,
|
||||
private val visibilityModifiers: MutableList<VisibilityModifier> = mutableListOf(),
|
||||
private val functionModifiers: MutableList<FunctionModifier> = mutableListOf(),
|
||||
private var propertyModifier: PropertyModifier? = null,
|
||||
private var inheritanceModifier: InheritanceModifier? = null,
|
||||
private var parameterModifier: ParameterModifier? = null,
|
||||
private var platformModifier: PlatformModifier? = null
|
||||
private val inheritanceModifiers: MutableList<InheritanceModifier> = mutableListOf(),
|
||||
private val parameterModifiers: MutableList<ParameterModifier> = mutableListOf(),
|
||||
private val platformModifiers: MutableList<PlatformModifier> = mutableListOf()
|
||||
) : FirAbstractAnnotatedElement(session, psi) {
|
||||
fun addModifier(modifier: LighterASTNode) {
|
||||
val tokenType = modifier.tokenType
|
||||
when {
|
||||
CLASS_MODIFIER.contains(tokenType) -> this.classModifier = ClassModifier.valueOf(modifier.toString().toUpperCase())
|
||||
CLASS_MODIFIER.contains(tokenType) -> this.classModifiers += ClassModifier.valueOf(modifier.toString().toUpperCase())
|
||||
MEMBER_MODIFIER.contains(tokenType) -> this.memberModifiers += MemberModifier.valueOf(modifier.toString().toUpperCase())
|
||||
VISIBILITY_MODIFIER.contains(tokenType) -> this.visibilityModifier =
|
||||
VISIBILITY_MODIFIER.contains(tokenType) -> this.visibilityModifiers +=
|
||||
VisibilityModifier.valueOf(modifier.toString().toUpperCase())
|
||||
FUNCTION_MODIFIER.contains(tokenType) -> this.functionModifiers += FunctionModifier.valueOf(modifier.toString().toUpperCase())
|
||||
PROPERTY_MODIFIER.contains(tokenType) -> this.propertyModifier = PropertyModifier.valueOf(modifier.toString().toUpperCase())
|
||||
INHERITANCE_MODIFIER.contains(tokenType) -> this.inheritanceModifier =
|
||||
INHERITANCE_MODIFIER.contains(tokenType) -> this.inheritanceModifiers +=
|
||||
InheritanceModifier.valueOf(modifier.toString().toUpperCase())
|
||||
PARAMETER_MODIFIER.contains(tokenType) -> this.parameterModifier = ParameterModifier.valueOf(modifier.toString().toUpperCase())
|
||||
PLATFORM_MODIFIER.contains(tokenType) -> this.platformModifier = PlatformModifier.valueOf(modifier.toString().toUpperCase())
|
||||
PARAMETER_MODIFIER.contains(tokenType) -> this.parameterModifiers += ParameterModifier.valueOf(modifier.toString().toUpperCase())
|
||||
PLATFORM_MODIFIER.contains(tokenType) -> this.platformModifiers += PlatformModifier.valueOf(modifier.toString().toUpperCase())
|
||||
}
|
||||
}
|
||||
|
||||
fun isEnum(): Boolean {
|
||||
return classModifier == ClassModifier.ENUM
|
||||
return classModifiers.contains(ClassModifier.ENUM)
|
||||
}
|
||||
|
||||
fun isAnnotation(): Boolean {
|
||||
return classModifier == ClassModifier.ANNOTATION
|
||||
return classModifiers.contains(ClassModifier.ANNOTATION)
|
||||
}
|
||||
|
||||
fun isDataClass(): Boolean {
|
||||
return classModifier == ClassModifier.DATA
|
||||
return classModifiers.contains(ClassModifier.DATA)
|
||||
}
|
||||
|
||||
fun isInner(): Boolean {
|
||||
return classModifier == ClassModifier.INNER
|
||||
return classModifiers.contains(ClassModifier.INNER)
|
||||
}
|
||||
|
||||
fun isCompanion(): Boolean {
|
||||
return classModifier == ClassModifier.COMPANION
|
||||
return classModifiers.contains(ClassModifier.COMPANION)
|
||||
}
|
||||
|
||||
fun hasOverride(): Boolean {
|
||||
@@ -78,7 +79,13 @@ class Modifier(
|
||||
}
|
||||
|
||||
fun getVisibility(): Visibility {
|
||||
return visibilityModifier.toVisibility()
|
||||
return when {
|
||||
visibilityModifiers.contains(VisibilityModifier.PRIVATE) -> Visibilities.PRIVATE
|
||||
visibilityModifiers.contains(VisibilityModifier.PUBLIC) -> Visibilities.PUBLIC
|
||||
visibilityModifiers.contains(VisibilityModifier.PROTECTED) -> Visibilities.PROTECTED
|
||||
visibilityModifiers.contains(VisibilityModifier.INTERNAL) -> Visibilities.INTERNAL
|
||||
else -> Visibilities.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
fun hasTailrec(): Boolean {
|
||||
@@ -109,27 +116,43 @@ class Modifier(
|
||||
return propertyModifier == PropertyModifier.CONST
|
||||
}
|
||||
|
||||
fun hasModality(modality: Modality): Boolean {
|
||||
return when {
|
||||
modality == Modality.FINAL && inheritanceModifiers.contains(InheritanceModifier.FINAL) -> true
|
||||
modality == Modality.SEALED && inheritanceModifiers.contains(InheritanceModifier.SEALED) -> true
|
||||
modality == Modality.ABSTRACT && inheritanceModifiers.contains(InheritanceModifier.ABSTRACT) -> true
|
||||
modality == Modality.OPEN && inheritanceModifiers.contains(InheritanceModifier.OPEN) -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
fun getModality(): Modality? {
|
||||
return inheritanceModifier?.toModality()
|
||||
return when {
|
||||
inheritanceModifiers.contains(InheritanceModifier.FINAL) -> Modality.FINAL
|
||||
inheritanceModifiers.contains(InheritanceModifier.SEALED) -> Modality.SEALED
|
||||
inheritanceModifiers.contains(InheritanceModifier.ABSTRACT) -> Modality.ABSTRACT
|
||||
inheritanceModifiers.contains(InheritanceModifier.OPEN) -> Modality.OPEN
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun hasVararg(): Boolean {
|
||||
return parameterModifier == ParameterModifier.VARARG
|
||||
return parameterModifiers.contains(ParameterModifier.VARARG)
|
||||
}
|
||||
|
||||
fun hasNoinline(): Boolean {
|
||||
return parameterModifier == ParameterModifier.NOINLINE
|
||||
return parameterModifiers.contains(ParameterModifier.NOINLINE)
|
||||
}
|
||||
|
||||
fun hasCrossinline(): Boolean {
|
||||
return parameterModifier == ParameterModifier.CROSSINLINE
|
||||
return parameterModifiers.contains(ParameterModifier.CROSSINLINE)
|
||||
}
|
||||
|
||||
fun hasExpect(): Boolean {
|
||||
return platformModifier == PlatformModifier.EXPECT
|
||||
return platformModifiers.contains(PlatformModifier.EXPECT) || platformModifiers.contains(PlatformModifier.HEADER)
|
||||
}
|
||||
|
||||
fun hasActual(): Boolean {
|
||||
return platformModifier == PlatformModifier.ACTUAL
|
||||
return platformModifiers.contains(PlatformModifier.ACTUAL) || platformModifiers.contains(PlatformModifier.IMPL)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ object ModifierSets {
|
||||
SEALED_KEYWORD
|
||||
)
|
||||
val PARAMETER_MODIFIER = TokenSet.create(VARARG_KEYWORD, NOINLINE_KEYWORD, CROSSINLINE_KEYWORD)
|
||||
val PLATFORM_MODIFIER = TokenSet.create(EXPECT_KEYWORD, ACTUAL_KEYWORD)
|
||||
val PLATFORM_MODIFIER = TokenSet.create(EXPECT_KEYWORD, ACTUAL_KEYWORD, HEADER_KEYWORD, IMPL_KEYWORD)
|
||||
val VARIANCE_MODIFIER = TokenSet.create(IN_KEYWORD, OUT_KEYWORD)
|
||||
val REIFICATION_MODIFIER = TokenSet.create(REIFIED_KEYWORD)
|
||||
}
|
||||
+15
-67
@@ -24,33 +24,11 @@ enum class MemberModifier {
|
||||
}
|
||||
|
||||
enum class VisibilityModifier {
|
||||
PUBLIC {
|
||||
override fun toVisibility(): Visibility {
|
||||
return Visibilities.PUBLIC
|
||||
}
|
||||
},
|
||||
PRIVATE {
|
||||
override fun toVisibility(): Visibility {
|
||||
return Visibilities.PRIVATE
|
||||
}
|
||||
},
|
||||
INTERNAL {
|
||||
override fun toVisibility(): Visibility {
|
||||
return Visibilities.INTERNAL
|
||||
}
|
||||
},
|
||||
PROTECTED {
|
||||
override fun toVisibility(): Visibility {
|
||||
return Visibilities.PROTECTED
|
||||
}
|
||||
},
|
||||
UNKNOWN {
|
||||
override fun toVisibility(): Visibility {
|
||||
return Visibilities.UNKNOWN
|
||||
}
|
||||
};
|
||||
|
||||
abstract fun toVisibility(): Visibility
|
||||
PUBLIC,
|
||||
PRIVATE,
|
||||
INTERNAL,
|
||||
PROTECTED,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
enum class FunctionModifier {
|
||||
@@ -67,28 +45,10 @@ enum class PropertyModifier {
|
||||
}
|
||||
|
||||
enum class InheritanceModifier {
|
||||
ABSTRACT {
|
||||
override fun toModality(): Modality {
|
||||
return Modality.ABSTRACT
|
||||
}
|
||||
},
|
||||
FINAL {
|
||||
override fun toModality(): Modality {
|
||||
return Modality.FINAL
|
||||
}
|
||||
},
|
||||
OPEN {
|
||||
override fun toModality(): Modality {
|
||||
return Modality.OPEN
|
||||
}
|
||||
},
|
||||
SEALED {
|
||||
override fun toModality(): Modality {
|
||||
return Modality.SEALED
|
||||
}
|
||||
};
|
||||
|
||||
abstract fun toModality(): Modality
|
||||
ABSTRACT,
|
||||
FINAL,
|
||||
OPEN,
|
||||
SEALED
|
||||
}
|
||||
|
||||
enum class ParameterModifier {
|
||||
@@ -99,27 +59,15 @@ enum class ParameterModifier {
|
||||
|
||||
enum class PlatformModifier {
|
||||
EXPECT,
|
||||
ACTUAL
|
||||
ACTUAL,
|
||||
HEADER,
|
||||
IMPL
|
||||
}
|
||||
|
||||
enum class VarianceModifier {
|
||||
IN {
|
||||
override fun toVariance(): Variance {
|
||||
return Variance.IN_VARIANCE
|
||||
}
|
||||
},
|
||||
OUT {
|
||||
override fun toVariance(): Variance {
|
||||
return Variance.OUT_VARIANCE
|
||||
}
|
||||
},
|
||||
INVARIANT {
|
||||
override fun toVariance(): Variance {
|
||||
return Variance.INVARIANT
|
||||
}
|
||||
};
|
||||
|
||||
abstract fun toVariance(): Variance
|
||||
IN,
|
||||
OUT,
|
||||
INVARIANT
|
||||
}
|
||||
|
||||
enum class ReificationModifier {
|
||||
|
||||
+4
@@ -22,4 +22,8 @@ class TypeModifier(
|
||||
KtTokens.SUSPEND_KEYWORD -> this.hasSuspend = true
|
||||
}
|
||||
}
|
||||
|
||||
fun hasNoAnnotations(): Boolean {
|
||||
return annotations.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -17,19 +17,24 @@ class TypeParameterModifier(
|
||||
session: FirSession,
|
||||
psi: PsiElement? = null,
|
||||
|
||||
private var varianceModifier: VarianceModifier = VarianceModifier.INVARIANT,
|
||||
private val varianceModifiers: MutableList<VarianceModifier> = mutableListOf(),
|
||||
private var reificationModifier: ReificationModifier? = null
|
||||
) : FirAbstractAnnotatedElement(session, psi) {
|
||||
fun addModifier(modifier: LighterASTNode) {
|
||||
val tokenType = modifier.tokenType
|
||||
when {
|
||||
VARIANCE_MODIFIER.contains(tokenType) -> this.varianceModifier = VarianceModifier.valueOf(modifier.toString().toUpperCase())
|
||||
REIFICATION_MODIFIER.contains(tokenType) -> this.reificationModifier = ReificationModifier.valueOf(modifier.toString().toUpperCase())
|
||||
VARIANCE_MODIFIER.contains(tokenType) -> this.varianceModifiers += VarianceModifier.valueOf(modifier.toString().toUpperCase())
|
||||
REIFICATION_MODIFIER.contains(tokenType) -> this.reificationModifier =
|
||||
ReificationModifier.valueOf(modifier.toString().toUpperCase())
|
||||
}
|
||||
}
|
||||
|
||||
fun getVariance(): Variance {
|
||||
return varianceModifier.toVariance()
|
||||
return when {
|
||||
varianceModifiers.contains(VarianceModifier.OUT) -> Variance.OUT_VARIANCE
|
||||
varianceModifiers.contains(VarianceModifier.IN) -> Variance.IN_VARIANCE
|
||||
else -> Variance.INVARIANT
|
||||
}
|
||||
}
|
||||
|
||||
fun hasReified(): Boolean {
|
||||
|
||||
+7
-3
@@ -16,16 +16,20 @@ class TypeProjectionModifier(
|
||||
session: FirSession,
|
||||
psi: PsiElement? = null,
|
||||
|
||||
private var varianceModifier: VarianceModifier = VarianceModifier.INVARIANT
|
||||
private val varianceModifiers: MutableList<VarianceModifier> = mutableListOf()
|
||||
) : FirAbstractAnnotatedElement(session, psi) {
|
||||
fun addModifier(modifier: LighterASTNode) {
|
||||
val tokenType = modifier.tokenType
|
||||
when {
|
||||
VARIANCE_MODIFIER.contains(tokenType) -> this.varianceModifier = VarianceModifier.valueOf(modifier.toString().toUpperCase())
|
||||
VARIANCE_MODIFIER.contains(tokenType) -> this.varianceModifiers += VarianceModifier.valueOf(modifier.toString().toUpperCase())
|
||||
}
|
||||
}
|
||||
|
||||
fun getVariance(): Variance {
|
||||
return varianceModifier.toVariance()
|
||||
return when {
|
||||
varianceModifiers.contains(VarianceModifier.IN) -> Variance.IN_VARIANCE
|
||||
varianceModifiers.contains(VarianceModifier.OUT) -> Variance.OUT_VARIANCE
|
||||
else -> Variance.INVARIANT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+33
-18
@@ -27,37 +27,56 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() {
|
||||
var counter = 0
|
||||
var errorCounter = 0
|
||||
|
||||
val onEachFile: (File) -> Unit = { file ->
|
||||
if (!compareFir(file)) errorCounter++
|
||||
counter++
|
||||
}
|
||||
println("BASE PATH: $path")
|
||||
if (!withTestData) {
|
||||
path.walkTopDown { file ->
|
||||
if (!compareFir(file)) errorCounter++
|
||||
counter++
|
||||
}
|
||||
path.walkTopDown(onEachFile)
|
||||
} else {
|
||||
path.walkTopDownWithTestData { file ->
|
||||
if (!compareFir(file)) errorCounter++
|
||||
counter++
|
||||
}
|
||||
path.walkTopDownWithTestData(onEachFile)
|
||||
}
|
||||
println("All scanned files: $counter")
|
||||
println("Files that aren't equal to FIR: $errorCounter")
|
||||
TestCase.assertEquals(0, errorCounter)
|
||||
}
|
||||
|
||||
private fun compareAll(stubMode: Boolean, path: String = System.getProperty("user.dir"), withTestData: Boolean = false) {
|
||||
private fun compareAll(stubMode: Boolean) {
|
||||
val lightTreeConverter = LightTree2Fir(stubMode, myProject)
|
||||
compareBase(path, withTestData) { file ->
|
||||
compareBase(System.getProperty("user.dir"), withTestData = false) { file ->
|
||||
val text = FileUtil.loadFile(file, CharsetToolkit.UTF8, true).trim()
|
||||
|
||||
//light tree
|
||||
val firFileFromLightTree = lightTreeConverter.buildFirFile(text, file.name)
|
||||
val treeFromLightTree = StringBuilder().also { FirRenderer(it).visitFile(firFileFromLightTree) }.toString()
|
||||
|
||||
//psi
|
||||
val ktFile = createPsiFile(FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.path)), text) as KtFile
|
||||
val firFileFromPsi = ktFile.toFirFile(stubMode)
|
||||
val treeFromPsi = StringBuilder().also { FirRenderer(it).visitFile(firFileFromPsi) }.toString()
|
||||
|
||||
//light tree
|
||||
val firFileFromLightTree = lightTreeConverter.buildFirFile(text, file.name)
|
||||
val treeFromLightTree = StringBuilder().also { FirRenderer(it).visitFile(firFileFromLightTree) }.toString()
|
||||
|
||||
return@compareBase treeFromLightTree == treeFromPsi
|
||||
}
|
||||
}
|
||||
|
||||
fun testCompareDiagnostics() {
|
||||
val lightTreeConverter = LightTree2Fir(false, myProject)
|
||||
compareBase("compiler/testData/diagnostics/tests", withTestData = true) { file ->
|
||||
val notEditedText = FileUtil.loadFile(file, CharsetToolkit.UTF8, true).trim()
|
||||
val text = notEditedText.replace("(<!>)|(<!.*?!>)".toRegex(), "").replaceAfter(".java", "")
|
||||
|
||||
//psi
|
||||
val ktFile = createPsiFile(FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.path)), text) as KtFile
|
||||
val firFileFromPsi = ktFile.toFirFile(stubMode = false)
|
||||
val treeFromPsi = StringBuilder().also { FirRenderer(it).visitFile(firFileFromPsi) }.toString()
|
||||
.replace("<Unsupported LValue.*?>".toRegex(), "<Unsupported LValue>")
|
||||
|
||||
//light tree
|
||||
val firFileFromLightTree = lightTreeConverter.buildFirFile(text, file.name)
|
||||
val treeFromLightTree = StringBuilder().also { FirRenderer(it).visitFile(firFileFromLightTree) }.toString()
|
||||
.replace("<Unsupported LValue.*?>".toRegex(), "<Unsupported LValue>")
|
||||
|
||||
return@compareBase treeFromLightTree == treeFromPsi
|
||||
}
|
||||
}
|
||||
@@ -366,8 +385,4 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() {
|
||||
visitAnonymousObject = true
|
||||
)
|
||||
}
|
||||
|
||||
fun testDiagnostics() {
|
||||
compareAll(false, "compiler/testData/diagnostics/tests", withTestData = true)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user