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