Rewrite RawFirBuilder and its utils to be able to reuse it in LightTree converter
This commit is contained in:
committed by
Mikhail Glukhikh
parent
084bad4c25
commit
cad0dbf087
+58
-14
@@ -9,23 +9,75 @@ import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.builder.BaseFirBuilder
|
||||
import org.jetbrains.kotlin.fir.builder.escapedStringToCharacter
|
||||
import org.jetbrains.kotlin.fir.types.impl.*
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
open class BaseConverter(
|
||||
session: FirSession,
|
||||
private val tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
) {
|
||||
protected val implicitUnitType = FirImplicitUnitTypeRef(session, null)
|
||||
protected val implicitAnyType = FirImplicitAnyTypeRef(session, null)
|
||||
protected val implicitEnumType = FirImplicitEnumTypeRef(session, null)
|
||||
protected val implicitAnnotationType = FirImplicitAnnotationTypeRef(session, null)
|
||||
) : BaseFirBuilder<LighterASTNode>(session) {
|
||||
protected val implicitType = FirImplicitTypeRefImpl(session, null)
|
||||
|
||||
override val LighterASTNode.elementType: IElementType
|
||||
get() = this.tokenType
|
||||
|
||||
override val LighterASTNode.asText: String
|
||||
get() = this.toString()
|
||||
|
||||
override val LighterASTNode.unescapedValue: String
|
||||
get() {
|
||||
val escape = this.asText
|
||||
return escapedStringToCharacter(escape)?.toString()
|
||||
?: escape.replace("\\", "").replace("u", "\\u")
|
||||
}
|
||||
|
||||
override fun LighterASTNode.getReferencedNameAsName(): Name {
|
||||
return this.asText.nameAsSafeName()
|
||||
}
|
||||
|
||||
override fun LighterASTNode.getLabelName(): String? {
|
||||
this.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
KtNodeTypes.LABEL_QUALIFIER -> return it.asText.replaceFirst("@", "")
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun LighterASTNode.getExpressionInParentheses(): LighterASTNode? {
|
||||
this.forEachChildren {
|
||||
if (it.isExpression()) return it
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun LighterASTNode.getChildNodeByType(type: IElementType): LighterASTNode? {
|
||||
return this.getChildNodesByType(type).firstOrNull()
|
||||
}
|
||||
|
||||
override val LighterASTNode?.selectorExpression: LighterASTNode?
|
||||
get() {
|
||||
var isSelector = false
|
||||
this?.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
DOT, SAFE_ACCESS -> isSelector = true
|
||||
else -> if (isSelector) return it
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun LighterASTNode.getParent(): LighterASTNode? {
|
||||
return tree.getParent(this)
|
||||
}
|
||||
@@ -38,7 +90,7 @@ open class BaseConverter(
|
||||
} ?: listOf()
|
||||
}
|
||||
|
||||
fun LighterASTNode?.getChildrenAsArray(): Array<LighterASTNode?> {
|
||||
fun LighterASTNode?.getChildrenAsArray(): Array<out LighterASTNode?> {
|
||||
if (this == null) return arrayOf()
|
||||
|
||||
val kidsRef = Ref<Array<LighterASTNode?>>()
|
||||
@@ -46,14 +98,6 @@ open class BaseConverter(
|
||||
return kidsRef.get()
|
||||
}
|
||||
|
||||
fun LighterASTNode.getExpressionInParentheses(): LighterASTNode? {
|
||||
this.forEachChildren {
|
||||
if (it.isExpression()) return it
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
protected inline fun LighterASTNode.forEachChildren(vararg skipTokens: KtToken, f: (LighterASTNode) -> Unit) {
|
||||
val kidsArray = this.getChildrenAsArray()
|
||||
for (kid in kidsArray) {
|
||||
|
||||
-213
@@ -62,10 +62,6 @@ object ConverterUtil {
|
||||
return this.toString().replace("`", "")
|
||||
}
|
||||
|
||||
fun LighterASTNode.getAsString(): String {
|
||||
return this.toString()
|
||||
}
|
||||
|
||||
fun LighterASTNode.isExpression(): Boolean {
|
||||
return when (this.tokenType) {
|
||||
is KtNodeType,
|
||||
@@ -76,59 +72,6 @@ object ConverterUtil {
|
||||
}
|
||||
}
|
||||
|
||||
fun toDelegatedSelfType(firClass: FirRegularClass): FirTypeRef {
|
||||
val typeParameters = firClass.typeParameters.map {
|
||||
FirTypeParameterImpl(firClass.session, it.psi, FirTypeParameterSymbol(), it.name, Variance.INVARIANT, false).apply {
|
||||
this.bounds += it.bounds
|
||||
}
|
||||
}
|
||||
return FirResolvedTypeRefImpl(
|
||||
firClass.session,
|
||||
null,
|
||||
ConeClassTypeImpl(
|
||||
firClass.symbol.toLookupTag(),
|
||||
typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun FirExpression.toReturn(labelName: String? = null): FirReturnExpression {
|
||||
return FirReturnExpressionImpl(
|
||||
session,
|
||||
null,
|
||||
this
|
||||
).apply {
|
||||
target = FirFunctionTarget(labelName)
|
||||
val lastFunction = FunctionUtil.firFunctions.lastOrNull()
|
||||
if (labelName == null) {
|
||||
if (lastFunction != null) {
|
||||
target.bind(lastFunction)
|
||||
} else {
|
||||
target.bind(FirErrorFunction(session, psi, "Cannot bind unlabeled return to a function"))
|
||||
}
|
||||
} else {
|
||||
for (firFunction in FunctionUtil.firFunctions.asReversed()) {
|
||||
when (firFunction) {
|
||||
is FirAnonymousFunction -> {
|
||||
if (firFunction.label?.name == labelName) {
|
||||
target.bind(firFunction)
|
||||
return@apply
|
||||
}
|
||||
}
|
||||
is FirNamedFunction -> {
|
||||
if (firFunction.name.asString() == labelName) {
|
||||
target.bind(firFunction)
|
||||
return@apply
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
target.bind(FirErrorFunction(session, psi, "Cannot bind label $labelName to a function"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun FirTypeParameterContainer.joinTypeParameters(typeConstraints: List<TypeConstraint>) {
|
||||
typeConstraints.forEach { typeConstraint ->
|
||||
this.typeParameters.forEach { typeParameter ->
|
||||
@@ -141,13 +84,6 @@ object ConverterUtil {
|
||||
}
|
||||
}
|
||||
|
||||
fun typeParametersFromSelfType(delegatedSelfTypeRef: FirTypeRef): List<FirTypeParameter> {
|
||||
return delegatedSelfTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||
?.typeArguments
|
||||
?.map { ((it as ConeTypeParameterType).lookupTag.symbol as FirTypeParameterSymbol).fir }
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
fun <T : FirCallWithArgumentList> T.extractArgumentsFrom(container: List<FirExpression>, stubMode: Boolean): T {
|
||||
if (!stubMode || this is FirAnnotationCall) {
|
||||
this.arguments += container
|
||||
@@ -176,152 +112,3 @@ object ConverterUtil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
object ClassNameUtil {
|
||||
lateinit var packageFqName: FqName
|
||||
|
||||
inline fun <T> withChildClassName(name: Name, l: () -> T): T {
|
||||
className = className.child(name)
|
||||
val t = l()
|
||||
className = className.parent()
|
||||
return t
|
||||
}
|
||||
|
||||
val currentClassId
|
||||
get() = ClassId(
|
||||
packageFqName,
|
||||
className, false
|
||||
)
|
||||
|
||||
fun callableIdForName(name: Name, local: Boolean = false) =
|
||||
when {
|
||||
local -> CallableId(name)
|
||||
className == FqName.ROOT -> CallableId(packageFqName, name)
|
||||
else -> CallableId(
|
||||
packageFqName,
|
||||
className, name
|
||||
)
|
||||
}
|
||||
|
||||
fun callableIdForClassConstructor() =
|
||||
if (className == FqName.ROOT) CallableId(packageFqName, Name.special("<anonymous-init>"))
|
||||
else CallableId(
|
||||
packageFqName,
|
||||
className, className.shortName()
|
||||
)
|
||||
|
||||
var className: FqName = FqName.ROOT
|
||||
}
|
||||
|
||||
object FunctionUtil {
|
||||
val firFunctions = mutableListOf<FirFunction>()
|
||||
val firFunctionCalls = mutableListOf<FirFunctionCall>()
|
||||
val firLabels = mutableListOf<FirLabel>()
|
||||
val firLoops = mutableListOf<FirLoop>()
|
||||
|
||||
fun <T> MutableList<T>.removeLast() {
|
||||
removeAt(size - 1)
|
||||
}
|
||||
|
||||
fun <T> MutableList<T>.pop(): T? {
|
||||
val result = lastOrNull()
|
||||
if (result != null) {
|
||||
removeAt(size - 1)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
object DataClassUtil {
|
||||
fun generateComponentFunctions(
|
||||
session: FirSession, firClass: FirClassImpl, properties: List<FirProperty>
|
||||
) {
|
||||
var componentIndex = 1
|
||||
for (property in properties) {
|
||||
if (!property.isVal && !property.isVar) continue
|
||||
val name = Name.identifier("component$componentIndex")
|
||||
componentIndex++
|
||||
val symbol = FirNamedFunctionSymbol(
|
||||
CallableId(
|
||||
ClassNameUtil.packageFqName,
|
||||
ClassNameUtil.className,
|
||||
name
|
||||
)
|
||||
)
|
||||
firClass.addDeclaration(
|
||||
FirMemberFunctionImpl(
|
||||
session, null, symbol, name,
|
||||
Visibilities.PUBLIC, Modality.FINAL,
|
||||
isExpect = false, isActual = false,
|
||||
isOverride = false, isOperator = false,
|
||||
isInfix = false, isInline = false,
|
||||
isTailRec = false, isExternal = false,
|
||||
isSuspend = false, receiverTypeRef = null,
|
||||
returnTypeRef = FirImplicitTypeRefImpl(session, null)
|
||||
).apply {
|
||||
val componentFunction = this
|
||||
body = FirSingleExpressionBlock(
|
||||
session,
|
||||
FirReturnExpressionImpl(
|
||||
session, null,
|
||||
FirQualifiedAccessExpressionImpl(session, null).apply {
|
||||
val parameterName = property.name
|
||||
calleeReference = FirResolvedCallableReferenceImpl(
|
||||
session, null,
|
||||
parameterName, property.symbol
|
||||
)
|
||||
}
|
||||
).apply {
|
||||
target = FirFunctionTarget(null)
|
||||
target.bind(componentFunction)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val copyName = Name.identifier("copy")
|
||||
|
||||
fun generateCopyFunction(
|
||||
session: FirSession, firClass: FirClassImpl,
|
||||
firPrimaryConstructor: FirConstructor,
|
||||
properties: List<FirProperty>
|
||||
) {
|
||||
val symbol = FirNamedFunctionSymbol(
|
||||
CallableId(
|
||||
ClassNameUtil.packageFqName,
|
||||
ClassNameUtil.className,
|
||||
copyName
|
||||
)
|
||||
)
|
||||
firClass.addDeclaration(
|
||||
FirMemberFunctionImpl(
|
||||
session, null, symbol, copyName,
|
||||
Visibilities.PUBLIC, Modality.FINAL,
|
||||
isExpect = false, isActual = false,
|
||||
isOverride = false, isOperator = false,
|
||||
isInfix = false, isInline = false,
|
||||
isTailRec = false, isExternal = false,
|
||||
isSuspend = false, receiverTypeRef = null,
|
||||
returnTypeRef = firPrimaryConstructor.returnTypeRef//FirImplicitTypeRefImpl(session, this)
|
||||
).apply {
|
||||
val copyFunction = this
|
||||
for (property in properties) {
|
||||
val name = property.name
|
||||
valueParameters += FirValueParameterImpl(
|
||||
session, null, name,
|
||||
property.returnTypeRef,
|
||||
FirQualifiedAccessExpressionImpl(session, null).apply {
|
||||
calleeReference = FirResolvedCallableReferenceImpl(session, null, name, property.symbol)
|
||||
},
|
||||
isCrossinline = false, isNoinline = false, isVararg = false
|
||||
)
|
||||
}
|
||||
|
||||
body = FirEmptyExpressionBlock(session)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+48
-51
@@ -22,17 +22,11 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringWithoutBacktick
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.joinTypeParameters
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toDelegatedSelfType
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toReturn
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isClassLocal
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.DataClassUtil.generateComponentFunctions
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.DataClassUtil.generateCopyFunction
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.*
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeModifier
|
||||
@@ -49,9 +43,11 @@ import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.fir.builder.generateCopyFunction
|
||||
import org.jetbrains.kotlin.fir.builder.generateComponentFunctions
|
||||
|
||||
class DeclarationsConverter(
|
||||
private val session: FirSession,
|
||||
session: FirSession,
|
||||
private val stubMode: Boolean,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
) : BaseConverter(session, tree) {
|
||||
@@ -70,11 +66,11 @@ class DeclarationsConverter(
|
||||
val fileAnnotationList = mutableListOf<FirAnnotationCall>()
|
||||
val importList = mutableListOf<FirImport>()
|
||||
val firDeclarationList = mutableListOf<FirDeclaration>()
|
||||
ClassNameUtil.packageFqName = FqName.ROOT
|
||||
packageFqName = FqName.ROOT
|
||||
file.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
FILE_ANNOTATION_LIST -> fileAnnotationList += convertFileAnnotationList(it)
|
||||
PACKAGE_DIRECTIVE -> ClassNameUtil.packageFqName = convertPackageName(it)
|
||||
PACKAGE_DIRECTIVE -> packageFqName = convertPackageName(it)
|
||||
IMPORT_LIST -> importList += convertImportDirectives(it)
|
||||
CLASS -> firDeclarationList += convertClass(it)
|
||||
FUN -> firDeclarationList += convertFunctionDeclaration(it)
|
||||
@@ -88,7 +84,7 @@ class DeclarationsConverter(
|
||||
session,
|
||||
null,
|
||||
fileName,
|
||||
ClassNameUtil.packageFqName
|
||||
packageFqName
|
||||
)
|
||||
firFile.annotations += fileAnnotationList
|
||||
firFile.imports += importList
|
||||
@@ -141,7 +137,7 @@ class DeclarationsConverter(
|
||||
private fun convertImportAlias(importAlias: LighterASTNode): String? {
|
||||
importAlias.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
IDENTIFIER -> return it.getAsString()
|
||||
IDENTIFIER -> return it.asText
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +153,7 @@ class DeclarationsConverter(
|
||||
var aliasName: String? = null
|
||||
importDirective.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
DOT_QUALIFIED_EXPRESSION, REFERENCE_EXPRESSION -> importedFqName = FqName(it.getAsString())
|
||||
DOT_QUALIFIED_EXPRESSION, REFERENCE_EXPRESSION -> importedFqName = FqName(it.asText)
|
||||
MUL -> isAllUnder = true
|
||||
IMPORT_ALIAS -> aliasName = convertImportAlias(it)
|
||||
}
|
||||
@@ -337,7 +333,7 @@ class DeclarationsConverter(
|
||||
CLASS_KEYWORD -> classKind = ClassKind.CLASS
|
||||
INTERFACE_KEYWORD -> classKind = ClassKind.INTERFACE
|
||||
OBJECT_KEYWORD -> classKind = ClassKind.OBJECT
|
||||
IDENTIFIER -> identifier = it.getAsString()
|
||||
IDENTIFIER -> identifier = it.asText
|
||||
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
||||
PRIMARY_CONSTRUCTOR -> primaryConstructor = it
|
||||
SUPER_TYPE_LIST -> convertDelegationSpecifiers(it).apply {
|
||||
@@ -368,11 +364,11 @@ class DeclarationsConverter(
|
||||
superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef }
|
||||
val isLocal = isClassLocal(classNode) { getParent() }
|
||||
|
||||
return ClassNameUtil.withChildClassName(className) {
|
||||
return withChildClassName(className) {
|
||||
val firClass = FirClassImpl(
|
||||
session,
|
||||
null,
|
||||
FirClassSymbol(ClassNameUtil.currentClassId),
|
||||
FirClassSymbol(currentClassId),
|
||||
className,
|
||||
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
|
||||
modifiers.getModality(),
|
||||
@@ -393,7 +389,7 @@ class DeclarationsConverter(
|
||||
session, className, modifiers, classKind,
|
||||
primaryConstructor != null,
|
||||
classBody.getChildNodesByType(SECONDARY_CONSTRUCTOR).isNotEmpty(),
|
||||
toDelegatedSelfType(firClass), delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef, superTypeCallEntry
|
||||
null.toDelegatedSelfType(firClass), delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef, superTypeCallEntry
|
||||
)
|
||||
//parse primary constructor
|
||||
val primaryConstructorWrapper = convertPrimaryConstructor(primaryConstructor, classWrapper)
|
||||
@@ -405,7 +401,7 @@ class DeclarationsConverter(
|
||||
//parse properties
|
||||
properties += primaryConstructorWrapper.valueParameters
|
||||
.filter { it.hasValOrVar() }
|
||||
.map { it.toFirProperty() }
|
||||
.map { it.toFirProperty(callableIdForName(it.firValueParameter.name)) }
|
||||
firClass.addDeclarations(properties)
|
||||
}
|
||||
|
||||
@@ -416,8 +412,9 @@ class DeclarationsConverter(
|
||||
|
||||
//parse data class
|
||||
if (modifiers.isDataClass() && firPrimaryConstructor != null) {
|
||||
generateComponentFunctions(session, firClass, properties)
|
||||
generateCopyFunction(session, firClass, firPrimaryConstructor, properties)
|
||||
val zippedParameters = MutableList(properties.size) { null }.zip(properties)
|
||||
zippedParameters.generateComponentFunctions(session, firClass, packageFqName, Companion.className)
|
||||
zippedParameters.generateCopyFunction(session, null, firClass, packageFqName, Companion.className, firPrimaryConstructor)
|
||||
// TODO: equals, hashCode, toString
|
||||
}
|
||||
|
||||
@@ -488,7 +485,7 @@ class DeclarationsConverter(
|
||||
enumEntry.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||
IDENTIFIER -> identifier = it.getAsString()
|
||||
IDENTIFIER -> identifier = it.asText
|
||||
INITIALIZER_LIST -> {
|
||||
hasInitializerList = true
|
||||
enumSuperTypeCallEntry += convertInitializerList(it)
|
||||
@@ -498,11 +495,11 @@ class DeclarationsConverter(
|
||||
}
|
||||
|
||||
val enumEntryName = identifier.nameAsSafeName()
|
||||
return ClassNameUtil.withChildClassName(enumEntryName) {
|
||||
return withChildClassName(enumEntryName) {
|
||||
val firEnumEntry = FirEnumEntryImpl(
|
||||
session,
|
||||
null,
|
||||
FirClassSymbol(ClassNameUtil.currentClassId),
|
||||
FirClassSymbol(currentClassId),
|
||||
enumEntryName
|
||||
)
|
||||
firEnumEntry.annotations += modifiers.annotations
|
||||
@@ -517,7 +514,7 @@ class DeclarationsConverter(
|
||||
session, enumEntryName, modifiers, ClassKind.ENUM_ENTRY,
|
||||
hasPrimaryConstructor = true,
|
||||
hasSecondaryConstructor = classBodyNode.getChildNodesByType(SECONDARY_CONSTRUCTOR).isNotEmpty(),
|
||||
delegatedSelfTypeRef = toDelegatedSelfType(firEnumEntry),
|
||||
delegatedSelfTypeRef = null.toDelegatedSelfType(firEnumEntry),
|
||||
delegatedSuperTypeRef = if (hasInitializerList) classWrapper.getFirUserTypeFromClassName() else defaultDelegatedSuperTypeRef,
|
||||
superTypeCallEntry = enumSuperTypeCallEntry
|
||||
)
|
||||
@@ -594,7 +591,7 @@ class DeclarationsConverter(
|
||||
FirPrimaryConstructorImpl(
|
||||
session,
|
||||
null,
|
||||
FirConstructorSymbol(ClassNameUtil.callableIdForClassConstructor()),
|
||||
FirConstructorSymbol(callableIdForClassConstructor()),
|
||||
if (primaryConstructor != null) modifiers.getVisibility() else defaultVisibility,
|
||||
modifiers.hasExpect(),
|
||||
modifiers.hasActual(),
|
||||
@@ -602,7 +599,7 @@ class DeclarationsConverter(
|
||||
firDelegatedCall
|
||||
).apply {
|
||||
annotations += modifiers.annotations
|
||||
this.typeParameters += ConverterUtil.typeParametersFromSelfType(classWrapper.delegatedSelfTypeRef)
|
||||
this.typeParameters += typeParametersFromSelfType(classWrapper.delegatedSelfTypeRef)
|
||||
this.valueParameters += valueParameters.map { it.firValueParameter }
|
||||
}, valueParameters
|
||||
)
|
||||
@@ -652,7 +649,7 @@ class DeclarationsConverter(
|
||||
val firConstructor = FirConstructorImpl(
|
||||
session,
|
||||
null,
|
||||
FirConstructorSymbol(ClassNameUtil.callableIdForClassConstructor()),
|
||||
FirConstructorSymbol(callableIdForClassConstructor()),
|
||||
modifiers.getVisibility(),
|
||||
modifiers.hasExpect(),
|
||||
modifiers.hasActual(),
|
||||
@@ -660,12 +657,12 @@ class DeclarationsConverter(
|
||||
constructorDelegationCall
|
||||
)
|
||||
|
||||
FunctionUtil.firFunctions += firConstructor
|
||||
firFunctions += firConstructor
|
||||
firConstructor.annotations += modifiers.annotations
|
||||
firConstructor.typeParameters += ConverterUtil.typeParametersFromSelfType(delegatedSelfTypeRef)
|
||||
firConstructor.typeParameters += typeParametersFromSelfType(delegatedSelfTypeRef)
|
||||
firConstructor.valueParameters += firValueParameters.map { it.firValueParameter }
|
||||
firConstructor.body = convertFunctionBody(block, null)
|
||||
FunctionUtil.firFunctions.removeLast()
|
||||
firFunctions.removeLast()
|
||||
return firConstructor
|
||||
}
|
||||
|
||||
@@ -681,12 +678,12 @@ class DeclarationsConverter(
|
||||
val firValueArguments = mutableListOf<FirExpression>()
|
||||
constructorDelegationCall.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
CONSTRUCTOR_DELEGATION_REFERENCE -> if (it.getAsString() == "this") thisKeywordPresent = true
|
||||
CONSTRUCTOR_DELEGATION_REFERENCE -> if (it.asText == "this") thisKeywordPresent = true
|
||||
VALUE_ARGUMENT_LIST -> firValueArguments += expressionConverter.convertValueArguments(it)
|
||||
}
|
||||
}
|
||||
|
||||
val isImplicit = constructorDelegationCall.getAsString().isEmpty()
|
||||
val isImplicit = constructorDelegationCall.asText.isEmpty()
|
||||
val isThis = (isImplicit && classWrapper.hasPrimaryConstructor) || thisKeywordPresent
|
||||
val delegatedType =
|
||||
if (classWrapper.isObjectLiteral() || classWrapper.isInterface()) when {
|
||||
@@ -717,18 +714,18 @@ class DeclarationsConverter(
|
||||
typeAlias.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||
IDENTIFIER -> identifier = it.getAsString()
|
||||
IDENTIFIER -> identifier = it.asText
|
||||
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
||||
TYPE_REFERENCE -> firType = convertType(it)
|
||||
}
|
||||
}
|
||||
|
||||
val typeAliasName = identifier.nameAsSafeName()
|
||||
return ClassNameUtil.withChildClassName(typeAliasName) {
|
||||
return withChildClassName(typeAliasName) {
|
||||
return@withChildClassName FirTypeAliasImpl(
|
||||
session,
|
||||
null,
|
||||
FirTypeAliasSymbol(ClassNameUtil.currentClassId),
|
||||
FirTypeAliasSymbol(currentClassId),
|
||||
typeAliasName,
|
||||
modifiers.getVisibility(),
|
||||
modifiers.hasExpect(),
|
||||
@@ -760,7 +757,7 @@ class DeclarationsConverter(
|
||||
property.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||
IDENTIFIER -> identifier = it.getAsString()
|
||||
IDENTIFIER -> identifier = it.asText
|
||||
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
||||
COLON -> isReturnType = true
|
||||
TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it)
|
||||
@@ -795,7 +792,7 @@ class DeclarationsConverter(
|
||||
FirMemberPropertyImpl(
|
||||
session,
|
||||
null,
|
||||
FirPropertySymbol(ClassNameUtil.callableIdForName(propertyName)),
|
||||
FirPropertySymbol(callableIdForName(propertyName)),
|
||||
propertyName,
|
||||
modifiers.getVisibility(),
|
||||
modifiers.getModality(),
|
||||
@@ -848,7 +845,7 @@ class DeclarationsConverter(
|
||||
entry.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||
IDENTIFIER -> identifier = it.getAsString()
|
||||
IDENTIFIER -> identifier = it.asText
|
||||
TYPE_REFERENCE -> firType = convertType(it)
|
||||
}
|
||||
}
|
||||
@@ -871,7 +868,7 @@ class DeclarationsConverter(
|
||||
var block: LighterASTNode? = null
|
||||
var expression: LighterASTNode? = null
|
||||
getterOrSetter.forEachChildren {
|
||||
if (it.getAsString() == "set") isGetter = false
|
||||
if (it.asText == "set") isGetter = false
|
||||
when (it.tokenType) {
|
||||
SET_KEYWORD -> isGetter = false
|
||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||
@@ -889,7 +886,7 @@ class DeclarationsConverter(
|
||||
modifiers.getVisibility(),
|
||||
returnType ?: if (isGetter) propertyTypeRef else implicitUnitType
|
||||
)
|
||||
FunctionUtil.firFunctions += firAccessor
|
||||
firFunctions += firAccessor
|
||||
firAccessor.annotations += modifiers.annotations
|
||||
|
||||
if (!isGetter) {
|
||||
@@ -897,7 +894,7 @@ class DeclarationsConverter(
|
||||
}
|
||||
|
||||
firAccessor.body = convertFunctionBody(block, expression)
|
||||
FunctionUtil.firFunctions.removeLast()
|
||||
firFunctions.removeLast()
|
||||
return firAccessor
|
||||
}
|
||||
|
||||
@@ -949,7 +946,7 @@ class DeclarationsConverter(
|
||||
functionDeclaration.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||
IDENTIFIER -> identifier = it.getAsString()
|
||||
IDENTIFIER -> identifier = it.asText
|
||||
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
||||
VALUE_PARAMETER_LIST -> valueParametersList = it //must convert later, because it can contains "return"
|
||||
COLON -> isReturnType = true
|
||||
@@ -976,7 +973,7 @@ class DeclarationsConverter(
|
||||
FirMemberFunctionImpl(
|
||||
session,
|
||||
null,
|
||||
FirNamedFunctionSymbol(ClassNameUtil.callableIdForName(functionName, isLocal)),
|
||||
FirNamedFunctionSymbol(callableIdForName(functionName, isLocal)),
|
||||
functionName,
|
||||
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
|
||||
modifiers.getModality(),
|
||||
@@ -994,7 +991,7 @@ class DeclarationsConverter(
|
||||
)
|
||||
}
|
||||
|
||||
FunctionUtil.firFunctions += firFunction
|
||||
firFunctions += firFunction
|
||||
firFunction.annotations += modifiers.annotations
|
||||
|
||||
if (firFunction is FirMemberFunctionImpl) {
|
||||
@@ -1004,7 +1001,7 @@ class DeclarationsConverter(
|
||||
|
||||
valueParametersList?.let { firFunction.valueParameters += convertValueParameters(it).map { it.firValueParameter } }
|
||||
firFunction.body = convertFunctionBody(block, expression)
|
||||
FunctionUtil.firFunctions.removeLast()
|
||||
firFunctions.removeLast()
|
||||
return firFunction
|
||||
}
|
||||
|
||||
@@ -1035,7 +1032,7 @@ class DeclarationsConverter(
|
||||
)
|
||||
}
|
||||
return if (!stubMode) {
|
||||
val blockTree = LightTree2Fir.buildLightTreeBlockExpression(block.getAsString())
|
||||
val blockTree = LightTree2Fir.buildLightTreeBlockExpression(block.asText)
|
||||
return DeclarationsConverter(session, stubMode, blockTree).convertBlockExpression(blockTree.root)
|
||||
} else {
|
||||
FirSingleExpressionBlock(
|
||||
@@ -1084,7 +1081,7 @@ class DeclarationsConverter(
|
||||
val firValueArguments = mutableListOf<FirExpression>()
|
||||
constructorInvocation.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
CONSTRUCTOR_CALLEE -> if (it.getAsString().isNotEmpty()) firTypeRef = convertType(it) //is empty in enum entry constructor
|
||||
CONSTRUCTOR_CALLEE -> if (it.asText.isNotEmpty()) firTypeRef = convertType(it) //is empty in enum entry constructor
|
||||
VALUE_ARGUMENT_LIST -> firValueArguments += expressionConverter.convertValueArguments(it)
|
||||
}
|
||||
}
|
||||
@@ -1149,7 +1146,7 @@ class DeclarationsConverter(
|
||||
when (it.tokenType) {
|
||||
//annotations will be saved later, on mapping stage with type parameters
|
||||
ANNOTATION, ANNOTATION_ENTRY -> annotations += convertAnnotation(it)
|
||||
REFERENCE_EXPRESSION -> identifier = it.getAsString()
|
||||
REFERENCE_EXPRESSION -> identifier = it.asText
|
||||
TYPE_REFERENCE -> firType = convertType(it)
|
||||
}
|
||||
}
|
||||
@@ -1167,7 +1164,7 @@ class DeclarationsConverter(
|
||||
typeParameter.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
MODIFIER_LIST -> typeParameterModifiers = convertTypeParameterModifiers(it)
|
||||
IDENTIFIER -> identifier = it.getAsString()
|
||||
IDENTIFIER -> identifier = it.asText
|
||||
TYPE_REFERENCE -> firType = convertType(it)
|
||||
}
|
||||
}
|
||||
@@ -1190,7 +1187,7 @@ class DeclarationsConverter(
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeRef
|
||||
*/
|
||||
fun convertType(type: LighterASTNode): FirTypeRef {
|
||||
if (type.getAsString().isEmpty()) {
|
||||
if (type.asText.isEmpty()) {
|
||||
return FirErrorTypeRefImpl(session, null, "Unwrapped type is null")
|
||||
}
|
||||
var typeModifiers = TypeModifier(session) //TODO what with suspend?
|
||||
@@ -1254,7 +1251,7 @@ class DeclarationsConverter(
|
||||
userType.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
USER_TYPE -> simpleFirUserType = convertUserType(it) as? FirUserTypeRef //simple user type
|
||||
REFERENCE_EXPRESSION -> identifier = it.getAsString()
|
||||
REFERENCE_EXPRESSION -> identifier = it.asText
|
||||
TYPE_ARGUMENT_LIST -> firTypeArguments += convertTypeArguments(it)
|
||||
}
|
||||
}
|
||||
@@ -1363,7 +1360,7 @@ class DeclarationsConverter(
|
||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||
VAL_KEYWORD -> isVal = true
|
||||
VAR_KEYWORD -> isVar = true
|
||||
IDENTIFIER -> identifier = it.getAsString()
|
||||
IDENTIFIER -> identifier = it.asText
|
||||
TYPE_REFERENCE -> firType = convertType(it)
|
||||
DESTRUCTURING_DECLARATION -> destructuringDeclaration = convertDestructingDeclaration(it)
|
||||
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it, "Should have default value")
|
||||
|
||||
+43
-150
@@ -21,14 +21,13 @@ import org.jetbrains.kotlin.fir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.fir.labels.FirLabelImpl
|
||||
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringWithoutBacktick
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toReturn
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.pop
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.utils.*
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.utils.bangBangToWhen
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.utils.generateDestructuringBlock
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.utils.getOperationSymbol
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.utils.qualifiedAccessTokens
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
@@ -38,23 +37,25 @@ import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.*
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class ExpressionsConverter(
|
||||
val session: FirSession,
|
||||
session: FirSession,
|
||||
private val stubMode: Boolean,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>,
|
||||
private val declarationsConverter: DeclarationsConverter
|
||||
) : BaseConverter(session, tree) {
|
||||
|
||||
inline fun <reified R : FirElement> LighterASTNode?.toFirExpression(errorReason: String = ""): R {
|
||||
return this?.let { convertExpression(it, errorReason) } as? R ?: (FirErrorExpressionImpl(session, null, errorReason) as R)
|
||||
}
|
||||
|
||||
inline fun <reified R : FirElement> getAsFirExpression(expression: LighterASTNode?, errorReason: String = ""): R {
|
||||
return expression?.let { convertExpression(it, errorReason) } as? R ?: (FirErrorExpressionImpl(session, null, errorReason) as R)
|
||||
}
|
||||
@@ -64,7 +65,7 @@ class ExpressionsConverter(
|
||||
if (!stubMode) {
|
||||
return when (expression.tokenType) {
|
||||
LAMBDA_EXPRESSION -> {
|
||||
val lambdaTree = LightTree2Fir.buildLightTreeLambdaExpression(expression.getAsString())
|
||||
val lambdaTree = LightTree2Fir.buildLightTreeLambdaExpression(expression.asText)
|
||||
ExpressionsConverter(session, stubMode, lambdaTree, declarationsConverter).convertLambdaExpression(lambdaTree.root)
|
||||
}
|
||||
BINARY_EXPRESSION -> convertBinaryExpression(expression)
|
||||
@@ -121,7 +122,7 @@ class ExpressionsConverter(
|
||||
}
|
||||
|
||||
return FirAnonymousFunctionImpl(session, null, implicitType, implicitType).apply {
|
||||
FunctionUtil.firFunctions += this
|
||||
firFunctions += this
|
||||
var destructuringBlock: FirExpression? = null
|
||||
for (valueParameter in valueParameterList) {
|
||||
val multiDeclaration = valueParameter.destructuringDeclaration
|
||||
@@ -142,11 +143,11 @@ class ExpressionsConverter(
|
||||
valueParameter.firValueParameter
|
||||
}
|
||||
}
|
||||
label = FunctionUtil.firLabels.pop() ?: FunctionUtil.firFunctionCalls.lastOrNull()?.calleeReference?.name?.let {
|
||||
label = firLabels.pop() ?: firFunctionCalls.lastOrNull()?.calleeReference?.name?.let {
|
||||
FirLabelImpl(this@ExpressionsConverter.session, null, it.asString())
|
||||
}
|
||||
val bodyExpression = block?.let { declarationsConverter.convertBlockExpression(it) }
|
||||
?: FirErrorExpressionImpl(session, null, "Lambda has no body")
|
||||
?: FirErrorExpressionImpl(this@ExpressionsConverter.session, null, "Lambda has no body")
|
||||
body = if (bodyExpression is FirBlockImpl) {
|
||||
if (bodyExpression.statements.isEmpty()) {
|
||||
bodyExpression.statements.add(FirUnitExpression(this@ExpressionsConverter.session, null))
|
||||
@@ -161,7 +162,7 @@ class ExpressionsConverter(
|
||||
FirSingleExpressionBlock(this@ExpressionsConverter.session, bodyExpression.toReturn())
|
||||
}
|
||||
|
||||
FunctionUtil.firFunctions.removeLast()
|
||||
firFunctions.removeLast()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +179,7 @@ class ExpressionsConverter(
|
||||
when (it.tokenType) {
|
||||
OPERATION_REFERENCE -> {
|
||||
isLeftArgument = false
|
||||
operationTokenName = it.getAsString()
|
||||
operationTokenName = it.asText
|
||||
}
|
||||
else -> if (it.isExpression()) {
|
||||
if (isLeftArgument) {
|
||||
@@ -218,7 +219,7 @@ class ExpressionsConverter(
|
||||
} else {
|
||||
val firOperation = operationToken.toFirOperation()
|
||||
if (firOperation in FirOperation.ASSIGNMENTS) {
|
||||
return convertAssignment(leftArgNode, rightArgAsFir, firOperation)
|
||||
return leftArgNode.generateAssignment(null, rightArgAsFir, firOperation) { toFirExpression() }
|
||||
} else {
|
||||
FirOperatorCallImpl(session, null, firOperation).apply {
|
||||
arguments += getAsFirExpression<FirExpression>(leftArgNode, "No left operand")
|
||||
@@ -238,7 +239,7 @@ class ExpressionsConverter(
|
||||
lateinit var firType: FirTypeRef
|
||||
binaryExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
OPERATION_REFERENCE -> operationTokenName = it.getAsString()
|
||||
OPERATION_REFERENCE -> operationTokenName = it.asText
|
||||
TYPE_REFERENCE -> firType = declarationsConverter.convertType(it)
|
||||
else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it, "No left operand")
|
||||
}
|
||||
@@ -259,7 +260,7 @@ class ExpressionsConverter(
|
||||
lateinit var firType: FirTypeRef
|
||||
isExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
OPERATION_REFERENCE -> operationTokenName = it.getAsString()
|
||||
OPERATION_REFERENCE -> operationTokenName = it.asText
|
||||
TYPE_REFERENCE -> firType = declarationsConverter.convertType(it)
|
||||
else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it, "No left operand")
|
||||
}
|
||||
@@ -276,19 +277,19 @@ class ExpressionsConverter(
|
||||
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitLabeledExpression
|
||||
*/
|
||||
private fun convertLabeledExpression(labeledExpression: LighterASTNode): FirElement {
|
||||
val size = FunctionUtil.firLabels.size
|
||||
val size = firLabels.size
|
||||
var firExpression: FirElement? = null
|
||||
labeledExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
LABEL_QUALIFIER -> FunctionUtil.firLabels += FirLabelImpl(session, null, it.toString().replace("@", ""))
|
||||
LABEL_QUALIFIER -> firLabels += FirLabelImpl(session, null, it.toString().replace("@", ""))
|
||||
BLOCK -> firExpression = declarationsConverter.convertBlock(it)
|
||||
PROPERTY -> firExpression = declarationsConverter.convertPropertyDeclaration(it)
|
||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
|
||||
}
|
||||
}
|
||||
|
||||
if (size != FunctionUtil.firLabels.size) {
|
||||
FunctionUtil.firLabels.removeLast()
|
||||
if (size != firLabels.size) {
|
||||
firLabels.removeLast()
|
||||
//println("Unused label: ${labeledExpression.getAsString()}")
|
||||
}
|
||||
return firExpression ?: FirErrorExpressionImpl(session, null, "Empty label")
|
||||
@@ -304,7 +305,7 @@ class ExpressionsConverter(
|
||||
var argument: LighterASTNode? = null
|
||||
unaryExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
OPERATION_REFERENCE -> operationTokenName = it.getAsString()
|
||||
OPERATION_REFERENCE -> operationTokenName = it.asText
|
||||
else -> if (it.isExpression()) argument = it
|
||||
}
|
||||
}
|
||||
@@ -318,10 +319,11 @@ class ExpressionsConverter(
|
||||
return if (conventionCallName != null) {
|
||||
if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) {
|
||||
return generateIncrementOrDecrementBlock(
|
||||
null,
|
||||
argument,
|
||||
callName = conventionCallName,
|
||||
prefix = unaryExpression.tokenType == PREFIX_EXPRESSION
|
||||
)
|
||||
) { toFirExpression() }
|
||||
}
|
||||
FirFunctionCallImpl(session, null).apply {
|
||||
calleeReference = FirSimpleNamedReference(this@ExpressionsConverter.session, null, conventionCallName)
|
||||
@@ -440,7 +442,7 @@ class ExpressionsConverter(
|
||||
var additionalArgument: FirExpression? = null
|
||||
callSuffix.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
REFERENCE_EXPRESSION -> name = it.getAsString()
|
||||
REFERENCE_EXPRESSION -> name = it.asText
|
||||
TYPE_ARGUMENT_LIST -> firTypeArguments += declarationsConverter.convertTypeArguments(it)
|
||||
VALUE_ARGUMENT_LIST, LAMBDA_ARGUMENT -> valueArguments += it
|
||||
else -> if (it.tokenType != TokenType.ERROR_ELEMENT) additionalArgument =
|
||||
@@ -458,119 +460,33 @@ class ExpressionsConverter(
|
||||
else -> FirErrorNamedReference(this@ExpressionsConverter.session, null, "Call has no callee")
|
||||
}
|
||||
|
||||
FunctionUtil.firFunctionCalls += this
|
||||
firFunctionCalls += this
|
||||
this.extractArgumentsFrom(valueArguments.flatMap { convertValueArguments(it) }, stubMode)
|
||||
typeArguments += firTypeArguments
|
||||
FunctionUtil.firFunctionCalls.removeLast()
|
||||
firFunctionCalls.removeLast()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseStringTemplate
|
||||
* @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.toInterpolatingCall
|
||||
*/
|
||||
private fun convertStringTemplate(stringTemplate: LighterASTNode): FirExpression {
|
||||
val sb = StringBuilder()
|
||||
var hasExpressions = false
|
||||
var result: FirExpression? = null
|
||||
var callCreated = false
|
||||
stringTemplate.forEachChildren(OPEN_QUOTE, CLOSING_QUOTE) {
|
||||
val nextArgument = when (it.tokenType) {
|
||||
LITERAL_STRING_TEMPLATE_ENTRY -> {
|
||||
sb.append(it.getAsString())
|
||||
FirConstExpressionImpl(session, null, IrConstKind.String, it.getAsString())
|
||||
}
|
||||
ESCAPE_STRING_TEMPLATE_ENTRY -> {
|
||||
val escape = it.getAsString()
|
||||
val unescaped = escapedStringToCharacter(escape)?.toString()
|
||||
?: escape.replace("\\", "").replace("u", "\\u")
|
||||
sb.append(unescaped)
|
||||
FirConstExpressionImpl(session, null, IrConstKind.String, unescaped)
|
||||
}
|
||||
SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> {
|
||||
hasExpressions = true
|
||||
convertShortOrLongStringTemplate(it)
|
||||
}
|
||||
else -> {
|
||||
hasExpressions = true
|
||||
FirErrorExpressionImpl(session, null, "Incorrect template entry: ${it.getAsString()}")
|
||||
}
|
||||
}
|
||||
result = when {
|
||||
result == null -> nextArgument
|
||||
callCreated && result is FirStringConcatenationCallImpl -> (result as FirStringConcatenationCallImpl).apply {
|
||||
//TODO smart cast to FirStringConcatenationCallImpl isn't working
|
||||
arguments += nextArgument
|
||||
}
|
||||
else -> {
|
||||
callCreated = true
|
||||
FirStringConcatenationCallImpl(session, null).apply {
|
||||
arguments += result!!
|
||||
arguments += nextArgument
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return if (hasExpressions) result!! else FirConstExpressionImpl(session, null, IrConstKind.String, sb.toString())
|
||||
return stringTemplate.getChildrenAsArray().toInterpolatingCall(null) { convertShortOrLongStringTemplate(it) }
|
||||
}
|
||||
|
||||
private fun convertShortOrLongStringTemplate(shortOrLongString: LighterASTNode): FirExpression {
|
||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Incorrect template argument")
|
||||
shortOrLongString.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) {
|
||||
firExpression = getAsFirExpression(it, "Incorrect template argument")
|
||||
private fun LighterASTNode?.convertShortOrLongStringTemplate(errorReason: String): FirExpression {
|
||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, errorReason)
|
||||
this?.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) {
|
||||
firExpression = getAsFirExpression(it, errorReason)
|
||||
}
|
||||
return firExpression
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseLiteralConstant
|
||||
* @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.generateConstantExpressionByLiteral
|
||||
*/
|
||||
private fun convertConstantExpression(constantExpression: LighterASTNode): FirExpression {
|
||||
val type = constantExpression.tokenType
|
||||
val text: String = constantExpression.getAsString()
|
||||
val convertedText: Any? = when (type) {
|
||||
INTEGER_CONSTANT, FLOAT_CONSTANT -> parseNumericLiteral(text, type)
|
||||
BOOLEAN_CONSTANT -> parseBoolean(text)
|
||||
else -> null
|
||||
}
|
||||
|
||||
return when (type) {
|
||||
INTEGER_CONSTANT ->
|
||||
if (convertedText is Long &&
|
||||
(hasLongSuffix(text) || hasUnsignedLongSuffix(text) || hasUnsignedSuffix(text) ||
|
||||
convertedText > Int.MAX_VALUE || convertedText < Int.MIN_VALUE)
|
||||
) {
|
||||
FirConstExpressionImpl(
|
||||
session, null, IrConstKind.Long, convertedText, "Incorrect long: $text"
|
||||
)
|
||||
} else if (convertedText is Number) {
|
||||
// TODO: support byte / short
|
||||
FirConstExpressionImpl(session, null, IrConstKind.Int, convertedText.toInt(), "Incorrect int: $text")
|
||||
} else {
|
||||
FirErrorExpressionImpl(session, null, reason = "Incorrect constant expression: $text")
|
||||
}
|
||||
FLOAT_CONSTANT ->
|
||||
if (convertedText is Float) {
|
||||
FirConstExpressionImpl(
|
||||
session, null, IrConstKind.Float, convertedText, "Incorrect float: $text"
|
||||
)
|
||||
} else {
|
||||
FirConstExpressionImpl(
|
||||
session, null, IrConstKind.Double, convertedText as Double, "Incorrect double: $text"
|
||||
)
|
||||
}
|
||||
CHARACTER_CONSTANT ->
|
||||
FirConstExpressionImpl(
|
||||
session, null, IrConstKind.Char, text.parseCharacter(), "Incorrect character: $text"
|
||||
)
|
||||
BOOLEAN_CONSTANT ->
|
||||
FirConstExpressionImpl(session, null, IrConstKind.Boolean, convertedText as Boolean)
|
||||
NULL ->
|
||||
FirConstExpressionImpl(session, null, IrConstKind.Null, null)
|
||||
else ->
|
||||
throw AssertionError("Unknown literal type: $type, $text")
|
||||
}
|
||||
return generateConstantExpressionByLiteral(constantExpression)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -590,10 +506,10 @@ class ExpressionsConverter(
|
||||
)
|
||||
}
|
||||
DESTRUCTURING_DECLARATION -> subjectExpression =
|
||||
getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.getAsString()}")
|
||||
getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.asText}")
|
||||
WHEN_ENTRY -> whenEntries += convertWhenEntry(it)
|
||||
else -> if (it.isExpression()) subjectExpression =
|
||||
getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.getAsString()}")
|
||||
getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.asText}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -742,7 +658,7 @@ class ExpressionsConverter(
|
||||
private fun convertSimpleNameExpression(referenceExpression: LighterASTNode): FirQualifiedAccessExpression {
|
||||
return FirQualifiedAccessExpressionImpl(session, null).apply {
|
||||
calleeReference =
|
||||
FirSimpleNamedReference(this@ExpressionsConverter.session, null, referenceExpression.getAsString().nameAsSafeName())
|
||||
FirSimpleNamedReference(this@ExpressionsConverter.session, null, referenceExpression.asText.nameAsSafeName())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -963,13 +879,13 @@ class ExpressionsConverter(
|
||||
when (it.tokenType) {
|
||||
CONTINUE_KEYWORD -> isBreak = false
|
||||
//BREAK -> isBreak = true
|
||||
LABEL_QUALIFIER -> labelName = it.getAsString().replace("@", "")
|
||||
LABEL_QUALIFIER -> labelName = it.asText.replace("@", "")
|
||||
}
|
||||
}
|
||||
|
||||
return (if (isBreak) FirBreakExpressionImpl(session, null) else FirContinueExpressionImpl(session, null)).apply {
|
||||
target = FirLoopTarget(labelName)
|
||||
val lastLoop = FunctionUtil.firLoops.lastOrNull()
|
||||
val lastLoop = firLoops.lastOrNull()
|
||||
if (labelName == null) {
|
||||
if (lastLoop != null) {
|
||||
target.bind(lastLoop)
|
||||
@@ -977,7 +893,7 @@ class ExpressionsConverter(
|
||||
target.bind(FirErrorLoop(this@ExpressionsConverter.session, null, "Cannot bind unlabeled jump to a loop"))
|
||||
}
|
||||
} else {
|
||||
for (firLoop in FunctionUtil.firLoops.asReversed()) {
|
||||
for (firLoop in firLoops.asReversed()) {
|
||||
if (firLoop.label?.name == labelName) {
|
||||
target.bind(firLoop)
|
||||
return this
|
||||
@@ -1002,7 +918,7 @@ class ExpressionsConverter(
|
||||
}
|
||||
}
|
||||
|
||||
return firExpression.toReturn(labelName)
|
||||
return firExpression.toReturn(labelName = labelName)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1023,12 +939,7 @@ class ExpressionsConverter(
|
||||
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitThisExpression
|
||||
*/
|
||||
private fun convertThisExpression(thisExpression: LighterASTNode): FirQualifiedAccessExpression {
|
||||
var label: String? = null
|
||||
thisExpression.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
LABEL_QUALIFIER -> label = it.getAsString().replaceFirst("@", "")
|
||||
}
|
||||
}
|
||||
val label: String? = thisExpression.getLabelName()
|
||||
|
||||
return FirQualifiedAccessExpressionImpl(session, null).apply {
|
||||
calleeReference = FirExplicitThisReference(this@ExpressionsConverter.session, null, label)
|
||||
@@ -1076,7 +987,7 @@ class ExpressionsConverter(
|
||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Argument is absent")
|
||||
valueArgument.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
VALUE_ARGUMENT_NAME -> identifier = it.getAsString()
|
||||
VALUE_ARGUMENT_NAME -> identifier = it.asText
|
||||
MUL -> isSpread = true
|
||||
STRING_TEMPLATE -> firExpression = convertStringTemplate(it)
|
||||
is KtConstantExpressionElementType -> firExpression = convertConstantExpression(it)
|
||||
@@ -1089,22 +1000,4 @@ class ExpressionsConverter(
|
||||
else -> firExpression
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.initializeLValue
|
||||
*/
|
||||
fun convertLValue(leftArgNode: LighterASTNode?, container: FirModifiableQualifiedAccess<*>): FirReference {
|
||||
return when (leftArgNode?.tokenType) {
|
||||
null -> FirErrorNamedReference(session, null, "Unsupported LValue: ${leftArgNode?.tokenType}")
|
||||
THIS_EXPRESSION -> convertThisExpression(leftArgNode).calleeReference
|
||||
REFERENCE_EXPRESSION -> FirSimpleNamedReference(session, null, leftArgNode.getAsString().nameAsSafeName())
|
||||
in qualifiedAccessTokens -> (getAsFirExpression<FirExpression>(leftArgNode) as? FirQualifiedAccess)?.let { firQualifiedAccess ->
|
||||
container.explicitReceiver = firQualifiedAccess.explicitReceiver
|
||||
container.safe = firQualifiedAccess.safe
|
||||
return@let firQualifiedAccess.calleeReference
|
||||
} ?: FirErrorNamedReference(session, null, "Unsupported qualified LValue: ${leftArgNode.getAsString()}")
|
||||
PARENTHESIZED -> convertLValue(leftArgNode.getExpressionInParentheses(), container)
|
||||
else -> FirErrorNamedReference(session, null, "Unsupported LValue: ${leftArgNode.tokenType}")
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-146
@@ -5,29 +5,29 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.lightTree.converter.utils
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import org.jetbrains.kotlin.KtNodeTypes.*
|
||||
import org.jetbrains.kotlin.KtNodeTypes.DOT_QUALIFIED_EXPRESSION
|
||||
import org.jetbrains.kotlin.KtNodeTypes.SAFE_ACCESS_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.builder.*
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.builder.generateNotNullOrOther
|
||||
import org.jetbrains.kotlin.fir.builder.generateResolvedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirVariableImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ExpressionsConverter
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.pop
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariable
|
||||
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirBlockImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirComponentCallImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirThrowExpressionImpl
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.DestructuringDeclaration
|
||||
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.AS_SAFE
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.IDENTIFIER
|
||||
import org.jetbrains.kotlin.parsing.KotlinExpressionParsing
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
val qualifiedAccessTokens = TokenSet.create(DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION)
|
||||
|
||||
@@ -39,118 +39,6 @@ fun String.getOperationSymbol(): IElementType {
|
||||
return IDENTIFIER
|
||||
}
|
||||
|
||||
fun ExpressionsConverter.convertAssignment(
|
||||
leftArgNode: LighterASTNode?,
|
||||
rightArgAsFir: FirExpression,
|
||||
operation: FirOperation
|
||||
): FirStatement {
|
||||
if (leftArgNode != null && leftArgNode.tokenType == PARENTHESIZED) {
|
||||
return convertAssignment(leftArgNode.getExpressionInParentheses(), rightArgAsFir, operation)
|
||||
}
|
||||
if (leftArgNode != null && leftArgNode.tokenType == ARRAY_ACCESS_EXPRESSION) {
|
||||
val arrayAccessFunctionCall = getAsFirExpression(leftArgNode) as FirFunctionCall
|
||||
val firArrayExpression = arrayAccessFunctionCall.explicitReceiver
|
||||
?: FirErrorExpressionImpl(session, null, "No array expression")
|
||||
val arraySet = if (operation != FirOperation.ASSIGN) {
|
||||
FirArraySetCallImpl(session, null, rightArgAsFir, operation).apply {
|
||||
indexes += arrayAccessFunctionCall.arguments
|
||||
}
|
||||
} else {
|
||||
return FirFunctionCallImpl(session, null).apply {
|
||||
calleeReference = FirSimpleNamedReference(this@convertAssignment.session, null, OperatorNameConventions.SET)
|
||||
explicitReceiver = firArrayExpression
|
||||
arguments += arrayAccessFunctionCall.arguments
|
||||
arguments += rightArgAsFir
|
||||
}
|
||||
}
|
||||
if (leftArgNode.getChildNodesByType(REFERENCE_EXPRESSION).isNotEmpty()) {
|
||||
return arraySet.apply {
|
||||
lValue = (firArrayExpression as FirQualifiedAccess).calleeReference
|
||||
}
|
||||
}
|
||||
return FirBlockImpl(this@convertAssignment.session, null).apply {
|
||||
val name = Name.special("<array-set>")
|
||||
statements += generateTemporaryVariable(this@convertAssignment.session, null, name, firArrayExpression)
|
||||
statements += arraySet.apply { lValue = FirSimpleNamedReference(this@convertAssignment.session, null, name) }
|
||||
}
|
||||
}
|
||||
if (operation != FirOperation.ASSIGN &&
|
||||
leftArgNode?.tokenType != REFERENCE_EXPRESSION && leftArgNode?.tokenType != THIS_EXPRESSION &&
|
||||
(leftArgNode?.tokenType !in qualifiedAccessTokens || getSelectorType(leftArgNode.getChildrenAsArray()) != REFERENCE_EXPRESSION)
|
||||
) {
|
||||
return FirBlockImpl(session, null).apply {
|
||||
val name = Name.special("<complex-set>")
|
||||
statements += generateTemporaryVariable(
|
||||
this@convertAssignment.session, null, name, getAsFirExpression(leftArgNode, "No LValue in assignment")
|
||||
)
|
||||
statements += FirVariableAssignmentImpl(this@convertAssignment.session, null, rightArgAsFir, operation).apply {
|
||||
lValue = FirSimpleNamedReference(this@convertAssignment.session, null, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return FirVariableAssignmentImpl(session, null, rightArgAsFir, operation).apply {
|
||||
lValue = convertLValue(leftArgNode, this)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun ExpressionsConverter.generateIncrementOrDecrementBlock(
|
||||
argument: LighterASTNode?,
|
||||
callName: Name,
|
||||
prefix: Boolean
|
||||
): FirExpression {
|
||||
if (argument == null) {
|
||||
return FirErrorExpressionImpl(session, null, "Inc/dec without operand")
|
||||
}
|
||||
return FirBlockImpl(session, null).apply {
|
||||
val tempName = Name.special("<unary>")
|
||||
val temporaryVariable = generateTemporaryVariable(
|
||||
this@generateIncrementOrDecrementBlock.session, null, tempName, getAsFirExpression(argument, "Incorrect expression inside inc/dec")
|
||||
)
|
||||
statements += temporaryVariable
|
||||
val resultName = Name.special("<unary-result>")
|
||||
val resultInitializer = FirFunctionCallImpl(this@generateIncrementOrDecrementBlock.session, null).apply {
|
||||
this.calleeReference = FirSimpleNamedReference(this@generateIncrementOrDecrementBlock.session, null, callName)
|
||||
this.explicitReceiver = generateResolvedAccessExpression(
|
||||
this@generateIncrementOrDecrementBlock.session, null, temporaryVariable
|
||||
)
|
||||
}
|
||||
val resultVar = generateTemporaryVariable(this@generateIncrementOrDecrementBlock.session, null, resultName, resultInitializer)
|
||||
val assignment = convertAssignment(
|
||||
argument,
|
||||
if (prefix && argument.tokenType != REFERENCE_EXPRESSION)
|
||||
generateResolvedAccessExpression(this@generateIncrementOrDecrementBlock.session, null, resultVar)
|
||||
else
|
||||
resultInitializer,
|
||||
FirOperation.ASSIGN
|
||||
)
|
||||
|
||||
fun appendAssignment() {
|
||||
if (assignment is FirBlock) {
|
||||
statements += assignment.statements
|
||||
} else {
|
||||
statements += assignment
|
||||
}
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
if (argument.tokenType != REFERENCE_EXPRESSION) {
|
||||
statements += resultVar
|
||||
appendAssignment()
|
||||
statements += generateResolvedAccessExpression(this@generateIncrementOrDecrementBlock.session, null, resultVar)
|
||||
} else {
|
||||
appendAssignment()
|
||||
statements += generateAccessExpression(
|
||||
this@generateIncrementOrDecrementBlock.session, null, argument.getAsString().nameAsSafeName()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
appendAssignment()
|
||||
statements += generateResolvedAccessExpression(this@generateIncrementOrDecrementBlock.session, null, temporaryVariable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generateDestructuringBlock(
|
||||
session: FirSession,
|
||||
multiDeclaration: DestructuringDeclaration,
|
||||
@@ -186,23 +74,3 @@ fun bangBangToWhen(session: FirSession, baseExpression: FirExpression): FirWhenE
|
||||
), "bangbang", null
|
||||
)
|
||||
}
|
||||
|
||||
private fun getSelectorType(qualifiedAccessChildren: Array<LighterASTNode?>): IElementType? {
|
||||
var isSelector = false
|
||||
qualifiedAccessChildren.forEach {
|
||||
if (it == null) return null
|
||||
when (it.tokenType) {
|
||||
DOT, SAFE_ACCESS -> isSelector = true
|
||||
else -> if (isSelector) return it.tokenType
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun FirAbstractLoop.configure(generateBlock: () -> FirBlock): FirAbstractLoop {
|
||||
label = FunctionUtil.firLabels.pop()
|
||||
FunctionUtil.firLoops += this
|
||||
block = generateBlock()
|
||||
FunctionUtil.firLoops.removeLast()
|
||||
return this
|
||||
}
|
||||
@@ -13,9 +13,9 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirMemberPropertyImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
|
||||
import org.jetbrains.kotlin.fir.lightTree.converter.ClassNameUtil
|
||||
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
|
||||
import org.jetbrains.kotlin.fir.references.FirPropertyFromParameterCallableReference
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
@@ -32,7 +32,7 @@ class ValueParameter(
|
||||
return isVal || isVar
|
||||
}
|
||||
|
||||
fun toFirProperty(): FirProperty {
|
||||
fun toFirProperty(callableId: CallableId): FirProperty {
|
||||
val name = this.firValueParameter.name
|
||||
var type = this.firValueParameter.returnTypeRef
|
||||
if (type is FirImplicitTypeRef) {
|
||||
@@ -42,7 +42,7 @@ class ValueParameter(
|
||||
return FirMemberPropertyImpl(
|
||||
this.firValueParameter.session,
|
||||
null,
|
||||
FirPropertySymbol(ClassNameUtil.callableIdForName(name)),
|
||||
FirPropertySymbol(callableId),
|
||||
name,
|
||||
modifiers.getVisibility(),
|
||||
modifiers.getModality(),
|
||||
|
||||
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.builder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.KtNodeTypes.*
|
||||
import org.jetbrains.kotlin.fir.FirFunctionTarget
|
||||
import org.jetbrains.kotlin.fir.FirLabel
|
||||
import org.jetbrains.kotlin.fir.FirReference
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirExplicitThisReference
|
||||
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.fir.types.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.CLOSING_QUOTE
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.*
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
//T can be either PsiElement, or LighterASTNode
|
||||
abstract class BaseFirBuilder<T>(val session: FirSession) {
|
||||
|
||||
protected val implicitUnitType = FirImplicitUnitTypeRef(session, null)
|
||||
protected val implicitAnyType = FirImplicitAnyTypeRef(session, null)
|
||||
protected val implicitEnumType = FirImplicitEnumTypeRef(session, null)
|
||||
protected val implicitAnnotationType = FirImplicitAnnotationTypeRef(session, null)
|
||||
|
||||
abstract val T.elementType: IElementType
|
||||
abstract val T.asText: String
|
||||
abstract val T.unescapedValue: String
|
||||
abstract fun T.getReferencedNameAsName(): Name
|
||||
abstract fun T.getLabelName(): String?
|
||||
abstract fun T.getExpressionInParentheses(): T?
|
||||
abstract fun T.getChildNodeByType(type: IElementType): T?
|
||||
abstract val T?.selectorExpression: T?
|
||||
|
||||
/**** Class name utils ****/
|
||||
// var packageFqName: FqName = FqName.ROOT
|
||||
// var className: FqName = FqName.ROOT
|
||||
// val currentClassId get() = ClassId(packageFqName, className, false)
|
||||
|
||||
inline fun <T> withChildClassName(name: Name, l: () -> T): T {
|
||||
className = className.child(name)
|
||||
val t = l()
|
||||
className = className.parent()
|
||||
return t
|
||||
}
|
||||
|
||||
fun callableIdForName(name: Name, local: Boolean = false) =
|
||||
when {
|
||||
local -> CallableId(name)
|
||||
className == FqName.ROOT -> CallableId(packageFqName, name)
|
||||
else -> CallableId(packageFqName, className, name)
|
||||
}
|
||||
|
||||
fun callableIdForClassConstructor() =
|
||||
if (className == FqName.ROOT) CallableId(packageFqName, Name.special("<anonymous-init>"))
|
||||
else CallableId(packageFqName, className, className.shortName())
|
||||
|
||||
|
||||
/**** Function utils ****/
|
||||
companion object {
|
||||
val firFunctions = mutableListOf<FirFunction>()
|
||||
val firFunctionCalls = mutableListOf<FirFunctionCall>()
|
||||
val firLabels = mutableListOf<FirLabel>()
|
||||
val firLoops = mutableListOf<FirLoop>()
|
||||
|
||||
lateinit var packageFqName: FqName
|
||||
var className: FqName = FqName.ROOT
|
||||
val currentClassId get() = ClassId(packageFqName, className, false)
|
||||
}
|
||||
|
||||
fun <T> MutableList<T>.removeLast() {
|
||||
removeAt(size - 1)
|
||||
}
|
||||
|
||||
fun <T> MutableList<T>.pop(): T? {
|
||||
val result = lastOrNull()
|
||||
if (result != null) {
|
||||
removeAt(size - 1)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**** Common utils ****/
|
||||
fun FirExpression.toReturn(basePsi: PsiElement? = psi, labelName: String? = null): FirReturnExpression {
|
||||
return FirReturnExpressionImpl(
|
||||
this@BaseFirBuilder.session,
|
||||
basePsi,
|
||||
this
|
||||
).apply {
|
||||
target = FirFunctionTarget(labelName)
|
||||
val lastFunction = firFunctions.lastOrNull()
|
||||
if (labelName == null) {
|
||||
if (lastFunction != null) {
|
||||
target.bind(lastFunction)
|
||||
} else {
|
||||
target.bind(FirErrorFunction(this@BaseFirBuilder.session, psi, "Cannot bind unlabeled return to a function"))
|
||||
}
|
||||
} else {
|
||||
for (firFunction in firFunctions.asReversed()) {
|
||||
when (firFunction) {
|
||||
is FirAnonymousFunction -> {
|
||||
if (firFunction.label?.name == labelName) {
|
||||
target.bind(firFunction)
|
||||
return@apply
|
||||
}
|
||||
}
|
||||
is FirNamedFunction -> {
|
||||
if (firFunction.name.asString() == labelName) {
|
||||
target.bind(firFunction)
|
||||
return@apply
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
target.bind(FirErrorFunction(this@BaseFirBuilder.session, psi, "Cannot bind label $labelName to a function"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun KtClassOrObject?.toDelegatedSelfType(firClass: FirRegularClass): FirTypeRef {
|
||||
val typeParameters = firClass.typeParameters.map {
|
||||
FirTypeParameterImpl(session, it.psi, FirTypeParameterSymbol(), it.name, Variance.INVARIANT, false).apply {
|
||||
this.bounds += it.bounds
|
||||
}
|
||||
}
|
||||
return FirResolvedTypeRefImpl(
|
||||
session,
|
||||
this,
|
||||
ConeClassTypeImpl(
|
||||
firClass.symbol.toLookupTag(),
|
||||
typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun typeParametersFromSelfType(delegatedSelfTypeRef: FirTypeRef): List<FirTypeParameter> {
|
||||
return delegatedSelfTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||
?.typeArguments
|
||||
?.map { ((it as ConeTypeParameterType).lookupTag.symbol as FirTypeParameterSymbol).fir }
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
fun FirAbstractLoop.configure(generateBlock: () -> FirBlock): FirAbstractLoop {
|
||||
label = firLabels.pop()
|
||||
firLoops += this
|
||||
block = generateBlock()
|
||||
firLoops.removeLast()
|
||||
return this
|
||||
}
|
||||
|
||||
/**** Conversion utils ****/
|
||||
private fun <T> T.getPsiOrNull(): PsiElement? {
|
||||
return if (this is PsiElement) this else null
|
||||
}
|
||||
|
||||
fun generateConstantExpressionByLiteral(expression: T): FirExpression {
|
||||
val type = expression.elementType
|
||||
val text: String = expression.asText
|
||||
val convertedText: Any? = when (type) {
|
||||
INTEGER_CONSTANT, FLOAT_CONSTANT -> parseNumericLiteral(text, type)
|
||||
BOOLEAN_CONSTANT -> parseBoolean(text)
|
||||
else -> null
|
||||
}
|
||||
return when (type) {
|
||||
INTEGER_CONSTANT ->
|
||||
if (convertedText is Long &&
|
||||
(hasLongSuffix(text) || hasUnsignedLongSuffix(text) || hasUnsignedSuffix(text) ||
|
||||
convertedText > Int.MAX_VALUE || convertedText < Int.MIN_VALUE)
|
||||
) {
|
||||
FirConstExpressionImpl(
|
||||
session, expression.getPsiOrNull(), IrConstKind.Long, convertedText, "Incorrect long: $text"
|
||||
)
|
||||
} else if (convertedText is Number) {
|
||||
// TODO: support byte / short
|
||||
FirConstExpressionImpl(session, expression.getPsiOrNull(), IrConstKind.Int, convertedText.toInt(), "Incorrect int: $text")
|
||||
} else {
|
||||
FirErrorExpressionImpl(session, expression.getPsiOrNull(), reason = "Incorrect constant expression: $text")
|
||||
}
|
||||
FLOAT_CONSTANT ->
|
||||
if (convertedText is Float) {
|
||||
FirConstExpressionImpl(
|
||||
session, expression.getPsiOrNull(), IrConstKind.Float, convertedText, "Incorrect float: $text"
|
||||
)
|
||||
} else {
|
||||
FirConstExpressionImpl(
|
||||
session, expression.getPsiOrNull(), IrConstKind.Double, convertedText as Double, "Incorrect double: $text"
|
||||
)
|
||||
}
|
||||
CHARACTER_CONSTANT ->
|
||||
FirConstExpressionImpl(
|
||||
session, expression.getPsiOrNull(), IrConstKind.Char, text.parseCharacter(), "Incorrect character: $text"
|
||||
)
|
||||
BOOLEAN_CONSTANT ->
|
||||
FirConstExpressionImpl(session, expression.getPsiOrNull(), IrConstKind.Boolean, convertedText as Boolean)
|
||||
NULL ->
|
||||
FirConstExpressionImpl(session, expression.getPsiOrNull(), IrConstKind.Null, null)
|
||||
else ->
|
||||
throw AssertionError("Unknown literal type: $type, $text")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun Array<out T?>.toInterpolatingCall(
|
||||
base: KtStringTemplateExpression?,
|
||||
convertTemplateEntry: T?.(String) -> FirExpression
|
||||
): FirExpression {
|
||||
val sb = StringBuilder()
|
||||
var hasExpressions = false
|
||||
var result: FirExpression? = null
|
||||
var callCreated = false
|
||||
L@ for (entry in this) {
|
||||
if (entry == null) continue
|
||||
val nextArgument = when (entry.elementType) {
|
||||
OPEN_QUOTE, CLOSING_QUOTE -> continue@L
|
||||
LITERAL_STRING_TEMPLATE_ENTRY -> {
|
||||
sb.append(entry.asText)
|
||||
FirConstExpressionImpl(session, entry.getPsiOrNull(), IrConstKind.String, entry.asText)
|
||||
}
|
||||
ESCAPE_STRING_TEMPLATE_ENTRY -> {
|
||||
sb.append(entry.unescapedValue)
|
||||
FirConstExpressionImpl(session, entry.getPsiOrNull(), IrConstKind.String, entry.unescapedValue)
|
||||
}
|
||||
SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> {
|
||||
hasExpressions = true
|
||||
entry.convertTemplateEntry("Incorrect template argument")
|
||||
}
|
||||
else -> {
|
||||
hasExpressions = true
|
||||
FirErrorExpressionImpl(
|
||||
session, entry.getPsiOrNull(), "Incorrect template entry: ${entry.asText}"
|
||||
)
|
||||
}
|
||||
}
|
||||
result = when {
|
||||
result == null -> nextArgument
|
||||
callCreated && result is FirStringConcatenationCallImpl -> result.apply {
|
||||
arguments += nextArgument
|
||||
}
|
||||
else -> {
|
||||
callCreated = true
|
||||
FirStringConcatenationCallImpl(session, base).apply {
|
||||
arguments += result!!
|
||||
arguments += nextArgument
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return if (hasExpressions) result!! else FirConstExpressionImpl(session, base, IrConstKind.String, sb.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* given:
|
||||
* argument++
|
||||
*
|
||||
* result:
|
||||
* {
|
||||
* val <unary> = argument
|
||||
* argument = <unary>.inc()
|
||||
* ^<unary>
|
||||
* }
|
||||
*
|
||||
* given:
|
||||
* ++argument
|
||||
*
|
||||
* result:
|
||||
* {
|
||||
* val <unary> = argument
|
||||
* argument = <unary>.inc()
|
||||
* ^argument
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
// TODO: Refactor, support receiver capturing in case of a.b
|
||||
fun generateIncrementOrDecrementBlock(
|
||||
baseExpression: KtUnaryExpression?,
|
||||
argument: T?,
|
||||
callName: Name,
|
||||
prefix: Boolean,
|
||||
convert: T.() -> FirExpression
|
||||
): FirExpression {
|
||||
if (argument == null) {
|
||||
return FirErrorExpressionImpl(session, argument, "Inc/dec without operand")
|
||||
}
|
||||
return FirBlockImpl(session, baseExpression).apply {
|
||||
val tempName = Name.special("<unary>")
|
||||
val temporaryVariable = generateTemporaryVariable(this@BaseFirBuilder.session, baseExpression, tempName, argument.convert())
|
||||
statements += temporaryVariable
|
||||
val resultName = Name.special("<unary-result>")
|
||||
val resultInitializer = FirFunctionCallImpl(this@BaseFirBuilder.session, baseExpression).apply {
|
||||
this.calleeReference = FirSimpleNamedReference(this@BaseFirBuilder.session, baseExpression?.operationReference, callName)
|
||||
this.explicitReceiver = generateResolvedAccessExpression(this@BaseFirBuilder.session, baseExpression, temporaryVariable)
|
||||
}
|
||||
val resultVar = generateTemporaryVariable(this@BaseFirBuilder.session, baseExpression, resultName, resultInitializer)
|
||||
val assignment = argument.generateAssignment(
|
||||
baseExpression,
|
||||
if (prefix && argument.elementType != REFERENCE_EXPRESSION)
|
||||
generateResolvedAccessExpression(this@BaseFirBuilder.session, baseExpression, resultVar)
|
||||
else
|
||||
resultInitializer,
|
||||
FirOperation.ASSIGN, convert
|
||||
)
|
||||
|
||||
fun appendAssignment() {
|
||||
if (assignment is FirBlock) {
|
||||
statements += assignment.statements
|
||||
} else {
|
||||
statements += assignment
|
||||
}
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
if (argument.elementType != REFERENCE_EXPRESSION) {
|
||||
statements += resultVar
|
||||
appendAssignment()
|
||||
statements += generateResolvedAccessExpression(this@BaseFirBuilder.session, baseExpression, resultVar)
|
||||
} else {
|
||||
appendAssignment()
|
||||
statements += generateAccessExpression(this@BaseFirBuilder.session, baseExpression, argument.getReferencedNameAsName())
|
||||
}
|
||||
} else {
|
||||
appendAssignment()
|
||||
statements += generateResolvedAccessExpression(this@BaseFirBuilder.session, baseExpression, temporaryVariable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun FirModifiableQualifiedAccess<*>.initializeLValue(
|
||||
left: T?,
|
||||
convertQualified: T.() -> FirQualifiedAccess?
|
||||
): FirReference {
|
||||
val tokenType = left?.elementType
|
||||
if (left != null) {
|
||||
when (tokenType) {
|
||||
REFERENCE_EXPRESSION -> {
|
||||
return FirSimpleNamedReference(this@BaseFirBuilder.session, left.getPsiOrNull(), left.getReferencedNameAsName())
|
||||
}
|
||||
THIS_EXPRESSION -> {
|
||||
return FirExplicitThisReference(this@BaseFirBuilder.session, left.getPsiOrNull(), left.getLabelName())
|
||||
}
|
||||
DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION -> {
|
||||
val firMemberAccess = left.convertQualified()
|
||||
return if (firMemberAccess != null) {
|
||||
explicitReceiver = firMemberAccess.explicitReceiver
|
||||
safe = firMemberAccess.safe
|
||||
firMemberAccess.calleeReference
|
||||
} else {
|
||||
FirErrorNamedReference(
|
||||
this@BaseFirBuilder.session, left.getPsiOrNull(), "Unsupported qualified LValue: ${left.asText}"
|
||||
)
|
||||
}
|
||||
}
|
||||
PARENTHESIZED -> {
|
||||
return initializeLValue(left.getExpressionInParentheses(), convertQualified)
|
||||
}
|
||||
}
|
||||
}
|
||||
return FirErrorNamedReference(this@BaseFirBuilder.session, left.getPsiOrNull(), "Unsupported LValue: $tokenType")
|
||||
}
|
||||
|
||||
fun T?.generateAssignment(
|
||||
psi: PsiElement?,
|
||||
value: FirExpression,
|
||||
operation: FirOperation,
|
||||
convert: T.() -> FirExpression
|
||||
): FirStatement {
|
||||
val tokenType = this?.elementType
|
||||
if (tokenType == PARENTHESIZED) {
|
||||
return this!!.getExpressionInParentheses().generateAssignment(psi, value, operation, convert)
|
||||
}
|
||||
if (tokenType == ARRAY_ACCESS_EXPRESSION) {
|
||||
val firArrayAccess = this!!.convert() as FirFunctionCallImpl
|
||||
val arraySet = if (operation != FirOperation.ASSIGN) {
|
||||
FirArraySetCallImpl(session, psi, value, operation).apply {
|
||||
indexes += firArrayAccess.arguments
|
||||
}
|
||||
} else {
|
||||
return firArrayAccess.apply {
|
||||
calleeReference = FirSimpleNamedReference(this@BaseFirBuilder.session, psi, OperatorNameConventions.SET)
|
||||
arguments += value
|
||||
}
|
||||
}
|
||||
val arrayExpression = this.getChildNodeByType(REFERENCE_EXPRESSION)
|
||||
if (arrayExpression != null) {
|
||||
return arraySet.apply {
|
||||
lValue = initializeLValue(arrayExpression) { convert() as? FirQualifiedAccess }
|
||||
}
|
||||
}
|
||||
return FirBlockImpl(session, arrayExpression).apply {
|
||||
val name = Name.special("<array-set>")
|
||||
statements += generateTemporaryVariable(
|
||||
this@BaseFirBuilder.session, this@generateAssignment.getPsiOrNull(), name, firArrayAccess.explicitReceiver!!
|
||||
)
|
||||
statements += arraySet.apply { lValue = FirSimpleNamedReference(this@BaseFirBuilder.session, arrayExpression, name) }
|
||||
}
|
||||
}
|
||||
if (operation != FirOperation.ASSIGN &&
|
||||
tokenType != REFERENCE_EXPRESSION && tokenType != THIS_EXPRESSION &&
|
||||
((tokenType != DOT_QUALIFIED_EXPRESSION && tokenType != SAFE_ACCESS_EXPRESSION) || this.selectorExpression?.elementType != REFERENCE_EXPRESSION)
|
||||
) {
|
||||
return FirBlockImpl(session, this.getPsiOrNull()).apply {
|
||||
val name = Name.special("<complex-set>")
|
||||
statements += generateTemporaryVariable(
|
||||
this@BaseFirBuilder.session, this@generateAssignment.getPsiOrNull(), name,
|
||||
this@generateAssignment?.convert()
|
||||
?: FirErrorExpressionImpl(this@BaseFirBuilder.session, this.getPsiOrNull(), "No LValue in assignment")
|
||||
)
|
||||
statements += FirVariableAssignmentImpl(this@BaseFirBuilder.session, psi, value, operation).apply {
|
||||
lValue = FirSimpleNamedReference(this@BaseFirBuilder.session, this.getPsiOrNull(), name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return FirVariableAssignmentImpl(session, psi, value, operation).apply {
|
||||
lValue = initializeLValue(this@generateAssignment) { convert() as? FirQualifiedAccess }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,53 +102,6 @@ internal fun translateEscape(c: Char): Char? =
|
||||
else -> null
|
||||
}
|
||||
|
||||
internal fun generateConstantExpressionByLiteral(expression: KtConstantExpression): FirExpression {
|
||||
val type = expression.node.elementType
|
||||
val text: String = expression.text
|
||||
val convertedText: Any? = when (type) {
|
||||
KtNodeTypes.INTEGER_CONSTANT, KtNodeTypes.FLOAT_CONSTANT -> parseNumericLiteral(text, type)
|
||||
KtNodeTypes.BOOLEAN_CONSTANT -> parseBoolean(text)
|
||||
else -> null
|
||||
}
|
||||
return when (type) {
|
||||
KtNodeTypes.INTEGER_CONSTANT ->
|
||||
if (convertedText is Long &&
|
||||
(hasLongSuffix(text) || hasUnsignedLongSuffix(text) || hasUnsignedSuffix(text) ||
|
||||
convertedText > Int.MAX_VALUE || convertedText < Int.MIN_VALUE)
|
||||
) {
|
||||
FirConstExpressionImpl(
|
||||
expression, IrConstKind.Long, convertedText, "Incorrect long: $text"
|
||||
)
|
||||
} else if (convertedText is Number) {
|
||||
// TODO: support byte / short
|
||||
FirConstExpressionImpl(expression, IrConstKind.Int, convertedText.toInt(), "Incorrect int: $text")
|
||||
} else {
|
||||
FirErrorExpressionImpl(expression, reason = "Incorrect constant expression: $text")
|
||||
}
|
||||
KtNodeTypes.FLOAT_CONSTANT ->
|
||||
if (convertedText is Float) {
|
||||
FirConstExpressionImpl(
|
||||
expression, IrConstKind.Float, convertedText, "Incorrect float: $text"
|
||||
)
|
||||
} else {
|
||||
FirConstExpressionImpl(
|
||||
expression, IrConstKind.Double, convertedText as Double, "Incorrect double: $text"
|
||||
)
|
||||
}
|
||||
KtNodeTypes.CHARACTER_CONSTANT ->
|
||||
FirConstExpressionImpl(
|
||||
expression, IrConstKind.Char, text.parseCharacter(), "Incorrect character: $text"
|
||||
)
|
||||
KtNodeTypes.BOOLEAN_CONSTANT ->
|
||||
FirConstExpressionImpl(expression, IrConstKind.Boolean, convertedText as Boolean)
|
||||
KtNodeTypes.NULL ->
|
||||
FirConstExpressionImpl(expression, IrConstKind.Null, null)
|
||||
else ->
|
||||
throw AssertionError("Unknown literal type: $type, $text")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun IElementType.toBinaryName(): Name? {
|
||||
return OperatorConventions.BINARY_OPERATION_NAMES[this]
|
||||
}
|
||||
@@ -281,53 +234,6 @@ internal fun Array<KtWhenCondition>.toFirWhenCondition(
|
||||
return firCondition!!
|
||||
}
|
||||
|
||||
internal fun Array<KtStringTemplateEntry>.toInterpolatingCall(
|
||||
base: KtStringTemplateExpression,
|
||||
convert: KtExpression?.(String) -> FirExpression
|
||||
): FirExpression {
|
||||
val sb = StringBuilder()
|
||||
var hasExpressions = false
|
||||
var result: FirExpression? = null
|
||||
var callCreated = false
|
||||
for (entry in this) {
|
||||
val nextArgument = when (entry) {
|
||||
is KtLiteralStringTemplateEntry -> {
|
||||
sb.append(entry.text)
|
||||
FirConstExpressionImpl(entry, IrConstKind.String, entry.text)
|
||||
}
|
||||
is KtEscapeStringTemplateEntry -> {
|
||||
sb.append(entry.unescapedValue)
|
||||
FirConstExpressionImpl(entry, IrConstKind.String, entry.unescapedValue)
|
||||
}
|
||||
is KtStringTemplateEntryWithExpression -> {
|
||||
val innerExpression = entry.expression
|
||||
hasExpressions = true
|
||||
innerExpression.convert("Incorrect template argument")
|
||||
}
|
||||
else -> {
|
||||
hasExpressions = true
|
||||
FirErrorExpressionImpl(
|
||||
entry, "Incorrect template entry: ${entry.text}"
|
||||
)
|
||||
}
|
||||
}
|
||||
result = when {
|
||||
result == null -> nextArgument
|
||||
callCreated && result is FirStringConcatenationCallImpl -> result.apply {
|
||||
arguments += nextArgument
|
||||
}
|
||||
else -> {
|
||||
callCreated = true
|
||||
FirStringConcatenationCallImpl(base).apply {
|
||||
arguments += result!!
|
||||
arguments += nextArgument
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return if (hasExpressions) result!! else FirConstExpressionImpl(base, IrConstKind.String, sb.toString())
|
||||
}
|
||||
|
||||
fun FirExpression.generateContainsOperation(
|
||||
argument: FirExpression,
|
||||
inverted: Boolean,
|
||||
@@ -346,85 +252,6 @@ fun FirExpression.generateContainsOperation(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* given:
|
||||
* argument++
|
||||
*
|
||||
* result:
|
||||
* {
|
||||
* val <unary> = argument
|
||||
* argument = <unary>.inc()
|
||||
* ^<unary>
|
||||
* }
|
||||
*
|
||||
* given:
|
||||
* ++argument
|
||||
*
|
||||
* result:
|
||||
* {
|
||||
* val <unary> = argument
|
||||
* argument = <unary>.inc()
|
||||
* ^argument
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
// TODO: Refactor, support receiver capturing in case of a.b
|
||||
internal fun generateIncrementOrDecrementBlock(
|
||||
session: FirSession,
|
||||
baseExpression: KtUnaryExpression,
|
||||
argument: KtExpression?,
|
||||
callName: Name,
|
||||
prefix: Boolean,
|
||||
convert: KtExpression.() -> FirExpression
|
||||
): FirExpression {
|
||||
if (argument == null) {
|
||||
return FirErrorExpressionImpl(argument, "Inc/dec without operand")
|
||||
}
|
||||
return FirBlockImpl(baseExpression).apply {
|
||||
val tempName = Name.special("<unary>")
|
||||
val temporaryVariable = generateTemporaryVariable(session, baseExpression, tempName, argument.convert())
|
||||
statements += temporaryVariable
|
||||
val resultName = Name.special("<unary-result>")
|
||||
val resultInitializer = FirFunctionCallImpl(baseExpression).apply {
|
||||
this.calleeReference = FirSimpleNamedReference(baseExpression.operationReference, callName)
|
||||
this.explicitReceiver = generateResolvedAccessExpression(baseExpression, temporaryVariable)
|
||||
}
|
||||
val resultVar = generateTemporaryVariable(session, baseExpression, resultName, resultInitializer)
|
||||
val assignment = argument.generateAssignment(
|
||||
session, baseExpression,
|
||||
if (prefix && argument !is KtSimpleNameExpression)
|
||||
generateResolvedAccessExpression(baseExpression, resultVar)
|
||||
else
|
||||
resultInitializer,
|
||||
FirOperation.ASSIGN, convert
|
||||
)
|
||||
|
||||
fun appendAssignment() {
|
||||
if (assignment is FirBlock) {
|
||||
statements += assignment.statements
|
||||
} else {
|
||||
statements += assignment
|
||||
}
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
if (argument !is KtSimpleNameExpression) {
|
||||
statements += resultVar
|
||||
appendAssignment()
|
||||
statements += generateResolvedAccessExpression(baseExpression, resultVar)
|
||||
} else {
|
||||
appendAssignment()
|
||||
statements += generateAccessExpression(baseExpression, argument.getReferencedNameAsName())
|
||||
}
|
||||
} else {
|
||||
appendAssignment()
|
||||
statements += generateResolvedAccessExpression(baseExpression, temporaryVariable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generateAccessExpression(psi: PsiElement?, name: Name): FirQualifiedAccessExpression =
|
||||
FirQualifiedAccessExpressionImpl(psi).apply {
|
||||
calleeReference = FirSimpleNamedReference(psi, name)
|
||||
@@ -472,164 +299,3 @@ fun generateTemporaryVariable(
|
||||
fun generateTemporaryVariable(
|
||||
session: FirSession, psi: PsiElement?, specialName: String, initializer: FirExpression
|
||||
): FirVariable<*> = generateTemporaryVariable(session, psi, Name.special("<$specialName>"), initializer)
|
||||
|
||||
private fun FirModifiableQualifiedAccess<*>.initializeLValue(
|
||||
left: KtExpression?,
|
||||
convertQualified: KtQualifiedExpression.() -> FirQualifiedAccess?
|
||||
): FirReference {
|
||||
return when (left) {
|
||||
is KtSimpleNameExpression -> {
|
||||
FirSimpleNamedReference(left, left.getReferencedNameAsName())
|
||||
}
|
||||
is KtThisExpression -> {
|
||||
FirExplicitThisReference(left, left.getLabelName())
|
||||
}
|
||||
is KtQualifiedExpression -> {
|
||||
val firMemberAccess = left.convertQualified()
|
||||
if (firMemberAccess != null) {
|
||||
explicitReceiver = firMemberAccess.explicitReceiver
|
||||
safe = firMemberAccess.safe
|
||||
firMemberAccess.calleeReference
|
||||
} else {
|
||||
FirErrorNamedReference(left, "Unsupported qualified LValue: ${left.text}")
|
||||
}
|
||||
}
|
||||
is KtParenthesizedExpression -> {
|
||||
initializeLValue(left.expression, convertQualified)
|
||||
}
|
||||
else -> {
|
||||
FirErrorNamedReference(left, "Unsupported LValue: ${left?.javaClass}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun KtExpression?.generateAssignment(
|
||||
session: FirSession,
|
||||
psi: PsiElement?,
|
||||
value: FirExpression,
|
||||
operation: FirOperation,
|
||||
convert: KtExpression.() -> FirExpression
|
||||
): FirStatement {
|
||||
if (this is KtParenthesizedExpression) {
|
||||
return expression.generateAssignment(session, psi, value, operation, convert)
|
||||
}
|
||||
if (this is KtArrayAccessExpression) {
|
||||
val arrayExpression = this.arrayExpression
|
||||
val firArrayExpression = arrayExpression?.convert() ?: FirErrorExpressionImpl(arrayExpression, "No array expression")
|
||||
val arraySet = if (operation != FirOperation.ASSIGN) {
|
||||
FirArraySetCallImpl(psi, value, operation).apply {
|
||||
for (indexExpression in indexExpressions) {
|
||||
indexes += indexExpression.convert()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return FirFunctionCallImpl(psi).apply {
|
||||
calleeReference = FirSimpleNamedReference(psi, OperatorNameConventions.SET)
|
||||
explicitReceiver = firArrayExpression
|
||||
for (indexExpression in indexExpressions) {
|
||||
arguments += indexExpression.convert()
|
||||
}
|
||||
arguments += value
|
||||
}
|
||||
}
|
||||
if (arrayExpression is KtSimpleNameExpression) {
|
||||
return arraySet.apply {
|
||||
lValue = initializeLValue(arrayExpression) { convert() as? FirQualifiedAccess }
|
||||
}
|
||||
}
|
||||
return FirBlockImpl(arrayExpression).apply {
|
||||
val name = Name.special("<array-set>")
|
||||
statements += generateTemporaryVariable(session, this@generateAssignment, name, firArrayExpression)
|
||||
statements += arraySet.apply { lValue = FirSimpleNamedReference(arrayExpression, name) }
|
||||
}
|
||||
}
|
||||
if (operation != FirOperation.ASSIGN &&
|
||||
this !is KtSimpleNameExpression && this !is KtThisExpression &&
|
||||
(this !is KtQualifiedExpression || selectorExpression !is KtSimpleNameExpression)
|
||||
) {
|
||||
return FirBlockImpl(this).apply {
|
||||
val name = Name.special("<complex-set>")
|
||||
statements += generateTemporaryVariable(
|
||||
session, this@generateAssignment, name,
|
||||
this@generateAssignment?.convert() ?: FirErrorExpressionImpl(this@generateAssignment, "No LValue in assignment")
|
||||
)
|
||||
statements += FirVariableAssignmentImpl(psi, value, operation).apply {
|
||||
lValue = FirSimpleNamedReference(this@generateAssignment, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return FirVariableAssignmentImpl(psi, value, operation).apply {
|
||||
lValue = initializeLValue(this@generateAssignment) { convert() as? FirQualifiedAccess }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun FirModifiableAccessorsOwner.generateAccessorsByDelegate(session: FirSession, member: Boolean, stubMode: Boolean) {
|
||||
val variable = this as FirVariable<*>
|
||||
val delegateFieldSymbol = delegateFieldSymbol ?: return
|
||||
val delegate = delegate as? FirWrappedDelegateExpressionImpl ?: return
|
||||
fun delegateAccess() = FirQualifiedAccessExpressionImpl(null).apply {
|
||||
calleeReference = FirDelegateFieldReferenceImpl(null, delegateFieldSymbol)
|
||||
}
|
||||
|
||||
fun thisRef() =
|
||||
if (member) FirQualifiedAccessExpressionImpl(null).apply {
|
||||
calleeReference = FirExplicitThisReference(null, null)
|
||||
}
|
||||
else FirConstExpressionImpl(null, IrConstKind.Null, null)
|
||||
|
||||
fun propertyRef() = FirCallableReferenceAccessImpl(null).apply {
|
||||
calleeReference = FirResolvedCallableReferenceImpl(null, variable.name, variable.symbol)
|
||||
typeRef = FirImplicitKPropertyTypeRef(null, ConeStarProjection)
|
||||
}
|
||||
|
||||
delegate.delegateProvider = if (stubMode) FirExpressionStub(null) else FirFunctionCallImpl(null).apply {
|
||||
explicitReceiver = delegate.expression
|
||||
calleeReference = FirSimpleNamedReference(null, PROVIDE_DELEGATE)
|
||||
arguments += thisRef()
|
||||
arguments += propertyRef()
|
||||
}
|
||||
if (stubMode) return
|
||||
getter = (getter as? FirPropertyAccessorImpl)
|
||||
?: FirPropertyAccessorImpl(session, null, true, Visibilities.UNKNOWN, FirImplicitTypeRefImpl(null)).apply Accessor@{
|
||||
body = FirSingleExpressionBlock(
|
||||
FirReturnExpressionImpl(
|
||||
null,
|
||||
FirFunctionCallImpl(null).apply {
|
||||
explicitReceiver = delegateAccess()
|
||||
calleeReference = FirSimpleNamedReference(null, GET_VALUE)
|
||||
arguments += thisRef()
|
||||
arguments += propertyRef()
|
||||
}
|
||||
).apply {
|
||||
target = FirFunctionTarget(null)
|
||||
target.bind(this@Accessor)
|
||||
}
|
||||
)
|
||||
}
|
||||
setter = (setter as? FirPropertyAccessorImpl)
|
||||
?: FirPropertyAccessorImpl(session, null, false, Visibilities.UNKNOWN, FirImplicitUnitTypeRef(null)).apply {
|
||||
val parameter = FirValueParameterImpl(
|
||||
session, null, DELEGATED_SETTER_PARAM,
|
||||
FirImplicitTypeRefImpl(null),
|
||||
defaultValue = null, isCrossinline = false,
|
||||
isNoinline = false, isVararg = false
|
||||
)
|
||||
valueParameters += parameter
|
||||
body = FirSingleExpressionBlock(
|
||||
FirFunctionCallImpl(null).apply {
|
||||
explicitReceiver = delegateAccess()
|
||||
calleeReference = FirSimpleNamedReference(null, SET_VALUE)
|
||||
arguments += thisRef()
|
||||
arguments += propertyRef()
|
||||
arguments += FirQualifiedAccessExpressionImpl(null).apply {
|
||||
calleeReference = FirResolvedCallableReferenceImpl(psi, DELEGATED_SETTER_PARAM, parameter.symbol)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val GET_VALUE = Name.identifier("getValue")
|
||||
private val SET_VALUE = Name.identifier("setValue")
|
||||
private val PROVIDE_DELEGATE = Name.identifier("provideDelegate")
|
||||
private val DELEGATED_SETTER_PARAM = Name.special("<set-?>")
|
||||
@@ -23,16 +23,15 @@ import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
|
||||
internal fun KtClassOrObject.generateComponentFunctions(
|
||||
fun List<Pair<KtParameter?, FirProperty>>.generateComponentFunctions(
|
||||
session: FirSession, firClass: FirClassImpl, packageFqName: FqName, classFqName: FqName
|
||||
) {
|
||||
var componentIndex = 1
|
||||
val zippedParameters =
|
||||
primaryConstructorParameters.zip(firClass.declarations.filterIsInstance<FirProperty>())
|
||||
for ((ktParameter, firProperty) in zippedParameters) {
|
||||
if (!ktParameter.hasValOrVar()) continue
|
||||
for ((ktParameter, firProperty) in this) {
|
||||
if (!firProperty.isVal && !firProperty.isVar) continue
|
||||
val name = Name.identifier("component$componentIndex")
|
||||
componentIndex++
|
||||
val symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, name))
|
||||
@@ -52,7 +51,7 @@ internal fun KtClassOrObject.generateComponentFunctions(
|
||||
FirReturnExpressionImpl(
|
||||
ktParameter,
|
||||
FirQualifiedAccessExpressionImpl(ktParameter).apply {
|
||||
val parameterName = ktParameter.nameAsSafeName
|
||||
val parameterName = firProperty.name
|
||||
calleeReference = FirResolvedCallableReferenceImpl(
|
||||
ktParameter,
|
||||
parameterName, firProperty.symbol
|
||||
@@ -70,15 +69,14 @@ internal fun KtClassOrObject.generateComponentFunctions(
|
||||
|
||||
private val copyName = Name.identifier("copy")
|
||||
|
||||
internal fun KtClassOrObject.generateCopyFunction(
|
||||
session: FirSession, firClass: FirClassImpl, packageFqName: FqName, classFqName: FqName,
|
||||
firPrimaryConstructor: FirConstructor,
|
||||
toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef
|
||||
fun List<Pair<KtParameter?, FirProperty>>.generateCopyFunction(
|
||||
session: FirSession, classOrObject: KtClassOrObject?, firClass: FirClassImpl, packageFqName: FqName, classFqName: FqName,
|
||||
firPrimaryConstructor: FirConstructor
|
||||
) {
|
||||
val symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, copyName))
|
||||
firClass.addDeclaration(
|
||||
FirMemberFunctionImpl(
|
||||
session, this, symbol, copyName,
|
||||
session, classOrObject, symbol, copyName,
|
||||
Visibilities.PUBLIC, Modality.FINAL,
|
||||
isExpect = false, isActual = false,
|
||||
isOverride = false, isOperator = false,
|
||||
@@ -88,13 +86,11 @@ internal fun KtClassOrObject.generateCopyFunction(
|
||||
returnTypeRef = firPrimaryConstructor.returnTypeRef//FirImplicitTypeRefImpl(session, this)
|
||||
).apply {
|
||||
val copyFunction = this
|
||||
val zippedParameters =
|
||||
primaryConstructorParameters.zip(firClass.declarations.filterIsInstance<FirProperty>())
|
||||
for ((ktParameter, firProperty) in zippedParameters) {
|
||||
val name = ktParameter.nameAsSafeName
|
||||
for ((ktParameter, firProperty) in this@generateCopyFunction) {
|
||||
val name = firProperty.name
|
||||
valueParameters += FirValueParameterImpl(
|
||||
session, ktParameter, name,
|
||||
ktParameter.typeReference.toFirOrErrorTypeRef(),
|
||||
firProperty.returnTypeRef,
|
||||
FirQualifiedAccessExpressionImpl(ktParameter).apply {
|
||||
calleeReference = FirResolvedCallableReferenceImpl(ktParameter, name, firProperty.symbol)
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.builder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
@@ -33,20 +34,40 @@ import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
|
||||
private val implicitUnitType = FirImplicitUnitTypeRef(null)
|
||||
|
||||
private val implicitAnyType = FirImplicitAnyTypeRef(null)
|
||||
|
||||
private val implicitEnumType = FirImplicitEnumTypeRef(null)
|
||||
|
||||
private val implicitAnnotationType = FirImplicitAnnotationTypeRef(null)
|
||||
class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder<PsiElement>(session) {
|
||||
|
||||
fun buildFirFile(file: KtFile): FirFile {
|
||||
return file.accept(Visitor(), Unit) as FirFile
|
||||
}
|
||||
|
||||
override val PsiElement.elementType: IElementType
|
||||
get() = node.elementType
|
||||
|
||||
override val PsiElement.asText: String
|
||||
get() = text
|
||||
|
||||
override val PsiElement.unescapedValue: String
|
||||
get() = (this as KtEscapeStringTemplateEntry).unescapedValue
|
||||
|
||||
override fun PsiElement.getChildNodeByType(type: IElementType): PsiElement? {
|
||||
return children.firstOrNull { it.node.elementType == type }
|
||||
}
|
||||
|
||||
override fun PsiElement.getReferencedNameAsName(): Name {
|
||||
return (this as KtSimpleNameExpression).getReferencedNameAsName()
|
||||
}
|
||||
|
||||
override fun PsiElement.getLabelName(): String? {
|
||||
return (this as KtExpressionWithLabel).getLabelName()
|
||||
}
|
||||
|
||||
override fun PsiElement.getExpressionInParentheses(): PsiElement? {
|
||||
return (this as KtParenthesizedExpression).expression
|
||||
}
|
||||
|
||||
override val PsiElement?.selectorExpression: PsiElement?
|
||||
get() = (this as? KtQualifiedExpression)?.selectorExpression
|
||||
|
||||
private val KtModifierListOwner.visibility: Visibility
|
||||
get() = with(modifierList) {
|
||||
when {
|
||||
@@ -126,38 +147,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
FirSingleExpressionBlock(convert())
|
||||
}
|
||||
|
||||
private fun FirExpression.toReturn(basePsi: PsiElement? = psi, labelName: String? = null): FirReturnExpression {
|
||||
return FirReturnExpressionImpl(basePsi, this).apply {
|
||||
target = FirFunctionTarget(labelName)
|
||||
val lastFunction = firFunctions.lastOrNull()
|
||||
if (labelName == null) {
|
||||
if (lastFunction != null) {
|
||||
target.bind(lastFunction)
|
||||
} else {
|
||||
target.bind(FirErrorFunction(this@RawFirBuilder.session, psi, "Cannot bind unlabeled return to a function"))
|
||||
}
|
||||
} else {
|
||||
for (firFunction in firFunctions.asReversed()) {
|
||||
when (firFunction) {
|
||||
is FirAnonymousFunction -> {
|
||||
if (firFunction.label?.name == labelName) {
|
||||
target.bind(firFunction)
|
||||
return@apply
|
||||
}
|
||||
}
|
||||
is FirNamedFunction -> {
|
||||
if (firFunction.name.asString() == labelName) {
|
||||
target.bind(firFunction)
|
||||
return@apply
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
target.bind(FirErrorFunction(this@RawFirBuilder.session, psi, "Cannot bind label $labelName to a function"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtDeclarationWithBody.buildFirBody(): FirBlock? =
|
||||
when {
|
||||
!hasBody() ->
|
||||
@@ -404,8 +393,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
return firConstructor
|
||||
}
|
||||
|
||||
lateinit var packageFqName: FqName
|
||||
|
||||
override fun visitKtFile(file: KtFile, data: Unit): FirElement {
|
||||
packageFqName = file.packageFqName
|
||||
val firFile = FirFileImpl(session, file, file.name, packageFqName)
|
||||
@@ -426,29 +413,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
return firFile
|
||||
}
|
||||
|
||||
private fun KtClassOrObject.toDelegatedSelfType(firClass: FirRegularClass): FirTypeRef {
|
||||
val typeParameters = firClass.typeParameters.map {
|
||||
FirTypeParameterImpl(session, it.psi, FirTypeParameterSymbol(), it.name, Variance.INVARIANT, false).apply {
|
||||
this.bounds += it.bounds
|
||||
addDefaultBoundIfNecessary()
|
||||
}
|
||||
}
|
||||
return FirResolvedTypeRefImpl(
|
||||
this,
|
||||
ConeClassTypeImpl(
|
||||
firClass.symbol.toLookupTag(),
|
||||
typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun FirTypeParameterImpl.addDefaultBoundIfNecessary() {
|
||||
if (bounds.isEmpty()) {
|
||||
bounds += FirImplicitNullableAnyTypeRef(null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(enumEntry: KtEnumEntry, data: Unit): FirElement {
|
||||
return withChildClassName(enumEntry.nameAsSafeName) {
|
||||
val firEnumEntry = FirEnumEntryImpl(
|
||||
@@ -471,28 +435,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <T> withChildClassName(name: Name, l: () -> T): T {
|
||||
className = className.child(name)
|
||||
val t = l()
|
||||
className = className.parent()
|
||||
return t
|
||||
}
|
||||
|
||||
val currentClassId get() = ClassId(packageFqName, className, false)
|
||||
|
||||
fun callableIdForName(name: Name, local: Boolean = false) =
|
||||
when {
|
||||
local -> CallableId(name)
|
||||
className == FqName.ROOT -> CallableId(packageFqName, name)
|
||||
else -> CallableId(packageFqName, className, name)
|
||||
}
|
||||
|
||||
fun callableIdForClassConstructor() =
|
||||
if (className == FqName.ROOT) CallableId(packageFqName, Name.special("<anonymous-init>"))
|
||||
else CallableId(packageFqName, className, className.shortName())
|
||||
|
||||
var className: FqName = FqName.ROOT
|
||||
|
||||
override fun visitClassOrObject(classOrObject: KtClassOrObject, data: Unit): FirElement {
|
||||
return withChildClassName(classOrObject.nameAsSafeName) {
|
||||
|
||||
@@ -544,10 +486,11 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
}
|
||||
|
||||
if (classOrObject.hasModifier(DATA_KEYWORD) && firPrimaryConstructor != null) {
|
||||
classOrObject.generateComponentFunctions(session, firClass, packageFqName, className)
|
||||
classOrObject.generateCopyFunction(session, firClass, packageFqName, className, firPrimaryConstructor) {
|
||||
toFirOrErrorType()
|
||||
}
|
||||
val zippedParameters = classOrObject.primaryConstructorParameters.zip(
|
||||
firClass.declarations.filterIsInstance<FirProperty>()
|
||||
)
|
||||
zippedParameters.generateComponentFunctions(session, firClass, packageFqName, className)
|
||||
zippedParameters.generateCopyFunction(session, classOrObject, firClass, packageFqName, className, firPrimaryConstructor)
|
||||
// TODO: equals, hashCode, toString
|
||||
}
|
||||
|
||||
@@ -589,20 +532,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
private val firFunctions = mutableListOf<FirFunction>()
|
||||
|
||||
private fun <T> MutableList<T>.removeLast() {
|
||||
removeAt(size - 1)
|
||||
}
|
||||
|
||||
private fun <T> MutableList<T>.pop(): T? {
|
||||
val result = lastOrNull()
|
||||
if (result != null) {
|
||||
removeAt(size - 1)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun visitNamedFunction(function: KtNamedFunction, data: Unit): FirElement {
|
||||
val typeReference = function.typeReference
|
||||
val returnType = if (function.hasBlockBody()) {
|
||||
@@ -722,13 +651,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
return firConstructor
|
||||
}
|
||||
|
||||
private fun typeParametersFromSelfType(delegatedSelfTypeRef: FirTypeRef): List<FirTypeParameter> {
|
||||
return delegatedSelfTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||
?.typeArguments
|
||||
?.map { ((it as ConeTypeParameterType).lookupTag.symbol as FirTypeParameterSymbol).fir }
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
private fun KtConstructorDelegationCall.convert(
|
||||
delegatedSuperTypeRef: FirTypeRef?,
|
||||
delegatedSelfTypeRef: FirTypeRef,
|
||||
@@ -956,7 +878,9 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
generateConstantExpressionByLiteral(expression)
|
||||
|
||||
override fun visitStringTemplateExpression(expression: KtStringTemplateExpression, data: Unit): FirElement {
|
||||
return expression.entries.toInterpolatingCall(expression) { toFirExpression(it) }
|
||||
return expression.entries.toInterpolatingCall(expression) {
|
||||
(this as KtStringTemplateEntryWithExpression).expression.toFirExpression(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitReturnExpression(expression: KtReturnExpression, data: Unit): FirElement {
|
||||
@@ -1037,16 +961,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
private val firLoops = mutableListOf<FirLoop>()
|
||||
|
||||
private fun FirAbstractLoop.configure(generateBlock: () -> FirBlock): FirAbstractLoop {
|
||||
label = firLabels.pop()
|
||||
firLoops += this
|
||||
block = generateBlock()
|
||||
firLoops.removeLast()
|
||||
return this
|
||||
}
|
||||
|
||||
override fun visitDoWhileExpression(expression: KtDoWhileExpression, data: Unit): FirElement {
|
||||
return FirDoWhileLoopImpl(
|
||||
expression, expression.condition.toFirExpression("No condition in do-while loop")
|
||||
@@ -1187,8 +1101,8 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
} else {
|
||||
val firOperation = operationToken.toFirOperation()
|
||||
if (firOperation in FirOperation.ASSIGNMENTS) {
|
||||
return expression.left.generateAssignment(session, expression, rightArgument, firOperation) {
|
||||
toFirExpression("Incorrect expression in assignment: ${expression.text}")
|
||||
return expression.left.generateAssignment(expression, rightArgument, firOperation) {
|
||||
(this as KtExpression).toFirExpression("Incorrect expression in assignment: ${expression.text}")
|
||||
}
|
||||
} else {
|
||||
FirOperatorCallImpl(expression, firOperation).apply {
|
||||
@@ -1227,10 +1141,10 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
return if (conventionCallName != null) {
|
||||
if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) {
|
||||
return generateIncrementOrDecrementBlock(
|
||||
session, expression, argument,
|
||||
expression, argument,
|
||||
callName = conventionCallName,
|
||||
prefix = expression is KtPrefixExpression
|
||||
) { toFirExpression("Incorrect expression inside inc/dec") }
|
||||
) { (this as KtExpression).toFirExpression("Incorrect expression inside inc/dec") }
|
||||
}
|
||||
FirFunctionCallImpl(expression).apply {
|
||||
calleeReference = FirSimpleNamedReference(
|
||||
@@ -1246,8 +1160,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
private val firFunctionCalls = mutableListOf<FirFunctionCall>()
|
||||
|
||||
override fun visitCallExpression(expression: KtCallExpression, data: Unit): FirElement {
|
||||
val calleeExpression = expression.calleeExpression
|
||||
return FirFunctionCallImpl(expression).apply {
|
||||
@@ -1315,8 +1227,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
return expression.expression?.accept(this, data) ?: FirErrorExpressionImpl(expression, "Empty parentheses")
|
||||
}
|
||||
|
||||
private val firLabels = mutableListOf<FirLabel>()
|
||||
|
||||
override fun visitLabeledExpression(expression: KtLabeledExpression, data: Unit): FirElement {
|
||||
val labelName = expression.getLabelName()
|
||||
val size = firLabels.size
|
||||
|
||||
Reference in New Issue
Block a user