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.openapi.util.Ref
|
||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||||
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
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.fir.types.impl.*
|
||||||
import org.jetbrains.kotlin.lexer.KtToken
|
import org.jetbrains.kotlin.lexer.KtToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
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.isExpression
|
||||||
|
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
open class BaseConverter(
|
open class BaseConverter(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
private val tree: FlyweightCapableTreeStructure<LighterASTNode>
|
private val tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||||
) {
|
) : BaseFirBuilder<LighterASTNode>(session) {
|
||||||
protected val implicitUnitType = FirImplicitUnitTypeRef(session, null)
|
|
||||||
protected val implicitAnyType = FirImplicitAnyTypeRef(session, null)
|
|
||||||
protected val implicitEnumType = FirImplicitEnumTypeRef(session, null)
|
|
||||||
protected val implicitAnnotationType = FirImplicitAnnotationTypeRef(session, null)
|
|
||||||
protected val implicitType = FirImplicitTypeRefImpl(session, null)
|
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? {
|
fun LighterASTNode.getParent(): LighterASTNode? {
|
||||||
return tree.getParent(this)
|
return tree.getParent(this)
|
||||||
}
|
}
|
||||||
@@ -38,7 +90,7 @@ open class BaseConverter(
|
|||||||
} ?: listOf()
|
} ?: listOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun LighterASTNode?.getChildrenAsArray(): Array<LighterASTNode?> {
|
fun LighterASTNode?.getChildrenAsArray(): Array<out LighterASTNode?> {
|
||||||
if (this == null) return arrayOf()
|
if (this == null) return arrayOf()
|
||||||
|
|
||||||
val kidsRef = Ref<Array<LighterASTNode?>>()
|
val kidsRef = Ref<Array<LighterASTNode?>>()
|
||||||
@@ -46,14 +98,6 @@ open class BaseConverter(
|
|||||||
return kidsRef.get()
|
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) {
|
protected inline fun LighterASTNode.forEachChildren(vararg skipTokens: KtToken, f: (LighterASTNode) -> Unit) {
|
||||||
val kidsArray = this.getChildrenAsArray()
|
val kidsArray = this.getChildrenAsArray()
|
||||||
for (kid in kidsArray) {
|
for (kid in kidsArray) {
|
||||||
|
|||||||
-213
@@ -62,10 +62,6 @@ object ConverterUtil {
|
|||||||
return this.toString().replace("`", "")
|
return this.toString().replace("`", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun LighterASTNode.getAsString(): String {
|
|
||||||
return this.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LighterASTNode.isExpression(): Boolean {
|
fun LighterASTNode.isExpression(): Boolean {
|
||||||
return when (this.tokenType) {
|
return when (this.tokenType) {
|
||||||
is KtNodeType,
|
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>) {
|
fun FirTypeParameterContainer.joinTypeParameters(typeConstraints: List<TypeConstraint>) {
|
||||||
typeConstraints.forEach { typeConstraint ->
|
typeConstraints.forEach { typeConstraint ->
|
||||||
this.typeParameters.forEach { typeParameter ->
|
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 {
|
fun <T : FirCallWithArgumentList> T.extractArgumentsFrom(container: List<FirExpression>, stubMode: Boolean): T {
|
||||||
if (!stubMode || this is FirAnnotationCall) {
|
if (!stubMode || this is FirAnnotationCall) {
|
||||||
this.arguments += container
|
this.arguments += container
|
||||||
@@ -176,152 +112,3 @@ object ConverterUtil {
|
|||||||
return false
|
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.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom
|
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString
|
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringWithoutBacktick
|
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringWithoutBacktick
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression
|
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.joinTypeParameters
|
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.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.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.*
|
||||||
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
|
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
|
||||||
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeModifier
|
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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
|
import org.jetbrains.kotlin.fir.builder.generateCopyFunction
|
||||||
|
import org.jetbrains.kotlin.fir.builder.generateComponentFunctions
|
||||||
|
|
||||||
class DeclarationsConverter(
|
class DeclarationsConverter(
|
||||||
private val session: FirSession,
|
session: FirSession,
|
||||||
private val stubMode: Boolean,
|
private val stubMode: Boolean,
|
||||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||||
) : BaseConverter(session, tree) {
|
) : BaseConverter(session, tree) {
|
||||||
@@ -70,11 +66,11 @@ class DeclarationsConverter(
|
|||||||
val fileAnnotationList = mutableListOf<FirAnnotationCall>()
|
val fileAnnotationList = mutableListOf<FirAnnotationCall>()
|
||||||
val importList = mutableListOf<FirImport>()
|
val importList = mutableListOf<FirImport>()
|
||||||
val firDeclarationList = mutableListOf<FirDeclaration>()
|
val firDeclarationList = mutableListOf<FirDeclaration>()
|
||||||
ClassNameUtil.packageFqName = FqName.ROOT
|
packageFqName = FqName.ROOT
|
||||||
file.forEachChildren {
|
file.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
FILE_ANNOTATION_LIST -> fileAnnotationList += convertFileAnnotationList(it)
|
FILE_ANNOTATION_LIST -> fileAnnotationList += convertFileAnnotationList(it)
|
||||||
PACKAGE_DIRECTIVE -> ClassNameUtil.packageFqName = convertPackageName(it)
|
PACKAGE_DIRECTIVE -> packageFqName = convertPackageName(it)
|
||||||
IMPORT_LIST -> importList += convertImportDirectives(it)
|
IMPORT_LIST -> importList += convertImportDirectives(it)
|
||||||
CLASS -> firDeclarationList += convertClass(it)
|
CLASS -> firDeclarationList += convertClass(it)
|
||||||
FUN -> firDeclarationList += convertFunctionDeclaration(it)
|
FUN -> firDeclarationList += convertFunctionDeclaration(it)
|
||||||
@@ -88,7 +84,7 @@ class DeclarationsConverter(
|
|||||||
session,
|
session,
|
||||||
null,
|
null,
|
||||||
fileName,
|
fileName,
|
||||||
ClassNameUtil.packageFqName
|
packageFqName
|
||||||
)
|
)
|
||||||
firFile.annotations += fileAnnotationList
|
firFile.annotations += fileAnnotationList
|
||||||
firFile.imports += importList
|
firFile.imports += importList
|
||||||
@@ -141,7 +137,7 @@ class DeclarationsConverter(
|
|||||||
private fun convertImportAlias(importAlias: LighterASTNode): String? {
|
private fun convertImportAlias(importAlias: LighterASTNode): String? {
|
||||||
importAlias.forEachChildren {
|
importAlias.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
IDENTIFIER -> return it.getAsString()
|
IDENTIFIER -> return it.asText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +153,7 @@ class DeclarationsConverter(
|
|||||||
var aliasName: String? = null
|
var aliasName: String? = null
|
||||||
importDirective.forEachChildren {
|
importDirective.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
DOT_QUALIFIED_EXPRESSION, REFERENCE_EXPRESSION -> importedFqName = FqName(it.getAsString())
|
DOT_QUALIFIED_EXPRESSION, REFERENCE_EXPRESSION -> importedFqName = FqName(it.asText)
|
||||||
MUL -> isAllUnder = true
|
MUL -> isAllUnder = true
|
||||||
IMPORT_ALIAS -> aliasName = convertImportAlias(it)
|
IMPORT_ALIAS -> aliasName = convertImportAlias(it)
|
||||||
}
|
}
|
||||||
@@ -337,7 +333,7 @@ class DeclarationsConverter(
|
|||||||
CLASS_KEYWORD -> classKind = ClassKind.CLASS
|
CLASS_KEYWORD -> classKind = ClassKind.CLASS
|
||||||
INTERFACE_KEYWORD -> classKind = ClassKind.INTERFACE
|
INTERFACE_KEYWORD -> classKind = ClassKind.INTERFACE
|
||||||
OBJECT_KEYWORD -> classKind = ClassKind.OBJECT
|
OBJECT_KEYWORD -> classKind = ClassKind.OBJECT
|
||||||
IDENTIFIER -> identifier = it.getAsString()
|
IDENTIFIER -> identifier = it.asText
|
||||||
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
||||||
PRIMARY_CONSTRUCTOR -> primaryConstructor = it
|
PRIMARY_CONSTRUCTOR -> primaryConstructor = it
|
||||||
SUPER_TYPE_LIST -> convertDelegationSpecifiers(it).apply {
|
SUPER_TYPE_LIST -> convertDelegationSpecifiers(it).apply {
|
||||||
@@ -368,11 +364,11 @@ class DeclarationsConverter(
|
|||||||
superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef }
|
superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef }
|
||||||
val isLocal = isClassLocal(classNode) { getParent() }
|
val isLocal = isClassLocal(classNode) { getParent() }
|
||||||
|
|
||||||
return ClassNameUtil.withChildClassName(className) {
|
return withChildClassName(className) {
|
||||||
val firClass = FirClassImpl(
|
val firClass = FirClassImpl(
|
||||||
session,
|
session,
|
||||||
null,
|
null,
|
||||||
FirClassSymbol(ClassNameUtil.currentClassId),
|
FirClassSymbol(currentClassId),
|
||||||
className,
|
className,
|
||||||
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
|
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
|
||||||
modifiers.getModality(),
|
modifiers.getModality(),
|
||||||
@@ -393,7 +389,7 @@ class DeclarationsConverter(
|
|||||||
session, className, modifiers, classKind,
|
session, className, modifiers, classKind,
|
||||||
primaryConstructor != null,
|
primaryConstructor != null,
|
||||||
classBody.getChildNodesByType(SECONDARY_CONSTRUCTOR).isNotEmpty(),
|
classBody.getChildNodesByType(SECONDARY_CONSTRUCTOR).isNotEmpty(),
|
||||||
toDelegatedSelfType(firClass), delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef, superTypeCallEntry
|
null.toDelegatedSelfType(firClass), delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef, superTypeCallEntry
|
||||||
)
|
)
|
||||||
//parse primary constructor
|
//parse primary constructor
|
||||||
val primaryConstructorWrapper = convertPrimaryConstructor(primaryConstructor, classWrapper)
|
val primaryConstructorWrapper = convertPrimaryConstructor(primaryConstructor, classWrapper)
|
||||||
@@ -405,7 +401,7 @@ class DeclarationsConverter(
|
|||||||
//parse properties
|
//parse properties
|
||||||
properties += primaryConstructorWrapper.valueParameters
|
properties += primaryConstructorWrapper.valueParameters
|
||||||
.filter { it.hasValOrVar() }
|
.filter { it.hasValOrVar() }
|
||||||
.map { it.toFirProperty() }
|
.map { it.toFirProperty(callableIdForName(it.firValueParameter.name)) }
|
||||||
firClass.addDeclarations(properties)
|
firClass.addDeclarations(properties)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,8 +412,9 @@ class DeclarationsConverter(
|
|||||||
|
|
||||||
//parse data class
|
//parse data class
|
||||||
if (modifiers.isDataClass() && firPrimaryConstructor != null) {
|
if (modifiers.isDataClass() && firPrimaryConstructor != null) {
|
||||||
generateComponentFunctions(session, firClass, properties)
|
val zippedParameters = MutableList(properties.size) { null }.zip(properties)
|
||||||
generateCopyFunction(session, firClass, firPrimaryConstructor, properties)
|
zippedParameters.generateComponentFunctions(session, firClass, packageFqName, Companion.className)
|
||||||
|
zippedParameters.generateCopyFunction(session, null, firClass, packageFqName, Companion.className, firPrimaryConstructor)
|
||||||
// TODO: equals, hashCode, toString
|
// TODO: equals, hashCode, toString
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,7 +485,7 @@ class DeclarationsConverter(
|
|||||||
enumEntry.forEachChildren {
|
enumEntry.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||||
IDENTIFIER -> identifier = it.getAsString()
|
IDENTIFIER -> identifier = it.asText
|
||||||
INITIALIZER_LIST -> {
|
INITIALIZER_LIST -> {
|
||||||
hasInitializerList = true
|
hasInitializerList = true
|
||||||
enumSuperTypeCallEntry += convertInitializerList(it)
|
enumSuperTypeCallEntry += convertInitializerList(it)
|
||||||
@@ -498,11 +495,11 @@ class DeclarationsConverter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val enumEntryName = identifier.nameAsSafeName()
|
val enumEntryName = identifier.nameAsSafeName()
|
||||||
return ClassNameUtil.withChildClassName(enumEntryName) {
|
return withChildClassName(enumEntryName) {
|
||||||
val firEnumEntry = FirEnumEntryImpl(
|
val firEnumEntry = FirEnumEntryImpl(
|
||||||
session,
|
session,
|
||||||
null,
|
null,
|
||||||
FirClassSymbol(ClassNameUtil.currentClassId),
|
FirClassSymbol(currentClassId),
|
||||||
enumEntryName
|
enumEntryName
|
||||||
)
|
)
|
||||||
firEnumEntry.annotations += modifiers.annotations
|
firEnumEntry.annotations += modifiers.annotations
|
||||||
@@ -517,7 +514,7 @@ class DeclarationsConverter(
|
|||||||
session, enumEntryName, modifiers, ClassKind.ENUM_ENTRY,
|
session, enumEntryName, modifiers, ClassKind.ENUM_ENTRY,
|
||||||
hasPrimaryConstructor = true,
|
hasPrimaryConstructor = true,
|
||||||
hasSecondaryConstructor = classBodyNode.getChildNodesByType(SECONDARY_CONSTRUCTOR).isNotEmpty(),
|
hasSecondaryConstructor = classBodyNode.getChildNodesByType(SECONDARY_CONSTRUCTOR).isNotEmpty(),
|
||||||
delegatedSelfTypeRef = toDelegatedSelfType(firEnumEntry),
|
delegatedSelfTypeRef = null.toDelegatedSelfType(firEnumEntry),
|
||||||
delegatedSuperTypeRef = if (hasInitializerList) classWrapper.getFirUserTypeFromClassName() else defaultDelegatedSuperTypeRef,
|
delegatedSuperTypeRef = if (hasInitializerList) classWrapper.getFirUserTypeFromClassName() else defaultDelegatedSuperTypeRef,
|
||||||
superTypeCallEntry = enumSuperTypeCallEntry
|
superTypeCallEntry = enumSuperTypeCallEntry
|
||||||
)
|
)
|
||||||
@@ -594,7 +591,7 @@ class DeclarationsConverter(
|
|||||||
FirPrimaryConstructorImpl(
|
FirPrimaryConstructorImpl(
|
||||||
session,
|
session,
|
||||||
null,
|
null,
|
||||||
FirConstructorSymbol(ClassNameUtil.callableIdForClassConstructor()),
|
FirConstructorSymbol(callableIdForClassConstructor()),
|
||||||
if (primaryConstructor != null) modifiers.getVisibility() else defaultVisibility,
|
if (primaryConstructor != null) modifiers.getVisibility() else defaultVisibility,
|
||||||
modifiers.hasExpect(),
|
modifiers.hasExpect(),
|
||||||
modifiers.hasActual(),
|
modifiers.hasActual(),
|
||||||
@@ -602,7 +599,7 @@ class DeclarationsConverter(
|
|||||||
firDelegatedCall
|
firDelegatedCall
|
||||||
).apply {
|
).apply {
|
||||||
annotations += modifiers.annotations
|
annotations += modifiers.annotations
|
||||||
this.typeParameters += ConverterUtil.typeParametersFromSelfType(classWrapper.delegatedSelfTypeRef)
|
this.typeParameters += typeParametersFromSelfType(classWrapper.delegatedSelfTypeRef)
|
||||||
this.valueParameters += valueParameters.map { it.firValueParameter }
|
this.valueParameters += valueParameters.map { it.firValueParameter }
|
||||||
}, valueParameters
|
}, valueParameters
|
||||||
)
|
)
|
||||||
@@ -652,7 +649,7 @@ class DeclarationsConverter(
|
|||||||
val firConstructor = FirConstructorImpl(
|
val firConstructor = FirConstructorImpl(
|
||||||
session,
|
session,
|
||||||
null,
|
null,
|
||||||
FirConstructorSymbol(ClassNameUtil.callableIdForClassConstructor()),
|
FirConstructorSymbol(callableIdForClassConstructor()),
|
||||||
modifiers.getVisibility(),
|
modifiers.getVisibility(),
|
||||||
modifiers.hasExpect(),
|
modifiers.hasExpect(),
|
||||||
modifiers.hasActual(),
|
modifiers.hasActual(),
|
||||||
@@ -660,12 +657,12 @@ class DeclarationsConverter(
|
|||||||
constructorDelegationCall
|
constructorDelegationCall
|
||||||
)
|
)
|
||||||
|
|
||||||
FunctionUtil.firFunctions += firConstructor
|
firFunctions += firConstructor
|
||||||
firConstructor.annotations += modifiers.annotations
|
firConstructor.annotations += modifiers.annotations
|
||||||
firConstructor.typeParameters += ConverterUtil.typeParametersFromSelfType(delegatedSelfTypeRef)
|
firConstructor.typeParameters += typeParametersFromSelfType(delegatedSelfTypeRef)
|
||||||
firConstructor.valueParameters += firValueParameters.map { it.firValueParameter }
|
firConstructor.valueParameters += firValueParameters.map { it.firValueParameter }
|
||||||
firConstructor.body = convertFunctionBody(block, null)
|
firConstructor.body = convertFunctionBody(block, null)
|
||||||
FunctionUtil.firFunctions.removeLast()
|
firFunctions.removeLast()
|
||||||
return firConstructor
|
return firConstructor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -681,12 +678,12 @@ class DeclarationsConverter(
|
|||||||
val firValueArguments = mutableListOf<FirExpression>()
|
val firValueArguments = mutableListOf<FirExpression>()
|
||||||
constructorDelegationCall.forEachChildren {
|
constructorDelegationCall.forEachChildren {
|
||||||
when (it.tokenType) {
|
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)
|
VALUE_ARGUMENT_LIST -> firValueArguments += expressionConverter.convertValueArguments(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val isImplicit = constructorDelegationCall.getAsString().isEmpty()
|
val isImplicit = constructorDelegationCall.asText.isEmpty()
|
||||||
val isThis = (isImplicit && classWrapper.hasPrimaryConstructor) || thisKeywordPresent
|
val isThis = (isImplicit && classWrapper.hasPrimaryConstructor) || thisKeywordPresent
|
||||||
val delegatedType =
|
val delegatedType =
|
||||||
if (classWrapper.isObjectLiteral() || classWrapper.isInterface()) when {
|
if (classWrapper.isObjectLiteral() || classWrapper.isInterface()) when {
|
||||||
@@ -717,18 +714,18 @@ class DeclarationsConverter(
|
|||||||
typeAlias.forEachChildren {
|
typeAlias.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||||
IDENTIFIER -> identifier = it.getAsString()
|
IDENTIFIER -> identifier = it.asText
|
||||||
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
||||||
TYPE_REFERENCE -> firType = convertType(it)
|
TYPE_REFERENCE -> firType = convertType(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val typeAliasName = identifier.nameAsSafeName()
|
val typeAliasName = identifier.nameAsSafeName()
|
||||||
return ClassNameUtil.withChildClassName(typeAliasName) {
|
return withChildClassName(typeAliasName) {
|
||||||
return@withChildClassName FirTypeAliasImpl(
|
return@withChildClassName FirTypeAliasImpl(
|
||||||
session,
|
session,
|
||||||
null,
|
null,
|
||||||
FirTypeAliasSymbol(ClassNameUtil.currentClassId),
|
FirTypeAliasSymbol(currentClassId),
|
||||||
typeAliasName,
|
typeAliasName,
|
||||||
modifiers.getVisibility(),
|
modifiers.getVisibility(),
|
||||||
modifiers.hasExpect(),
|
modifiers.hasExpect(),
|
||||||
@@ -760,7 +757,7 @@ class DeclarationsConverter(
|
|||||||
property.forEachChildren {
|
property.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||||
IDENTIFIER -> identifier = it.getAsString()
|
IDENTIFIER -> identifier = it.asText
|
||||||
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
||||||
COLON -> isReturnType = true
|
COLON -> isReturnType = true
|
||||||
TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it)
|
TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it)
|
||||||
@@ -795,7 +792,7 @@ class DeclarationsConverter(
|
|||||||
FirMemberPropertyImpl(
|
FirMemberPropertyImpl(
|
||||||
session,
|
session,
|
||||||
null,
|
null,
|
||||||
FirPropertySymbol(ClassNameUtil.callableIdForName(propertyName)),
|
FirPropertySymbol(callableIdForName(propertyName)),
|
||||||
propertyName,
|
propertyName,
|
||||||
modifiers.getVisibility(),
|
modifiers.getVisibility(),
|
||||||
modifiers.getModality(),
|
modifiers.getModality(),
|
||||||
@@ -848,7 +845,7 @@ class DeclarationsConverter(
|
|||||||
entry.forEachChildren {
|
entry.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||||
IDENTIFIER -> identifier = it.getAsString()
|
IDENTIFIER -> identifier = it.asText
|
||||||
TYPE_REFERENCE -> firType = convertType(it)
|
TYPE_REFERENCE -> firType = convertType(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -871,7 +868,7 @@ class DeclarationsConverter(
|
|||||||
var block: LighterASTNode? = null
|
var block: LighterASTNode? = null
|
||||||
var expression: LighterASTNode? = null
|
var expression: LighterASTNode? = null
|
||||||
getterOrSetter.forEachChildren {
|
getterOrSetter.forEachChildren {
|
||||||
if (it.getAsString() == "set") isGetter = false
|
if (it.asText == "set") isGetter = false
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
SET_KEYWORD -> isGetter = false
|
SET_KEYWORD -> isGetter = false
|
||||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||||
@@ -889,7 +886,7 @@ class DeclarationsConverter(
|
|||||||
modifiers.getVisibility(),
|
modifiers.getVisibility(),
|
||||||
returnType ?: if (isGetter) propertyTypeRef else implicitUnitType
|
returnType ?: if (isGetter) propertyTypeRef else implicitUnitType
|
||||||
)
|
)
|
||||||
FunctionUtil.firFunctions += firAccessor
|
firFunctions += firAccessor
|
||||||
firAccessor.annotations += modifiers.annotations
|
firAccessor.annotations += modifiers.annotations
|
||||||
|
|
||||||
if (!isGetter) {
|
if (!isGetter) {
|
||||||
@@ -897,7 +894,7 @@ class DeclarationsConverter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
firAccessor.body = convertFunctionBody(block, expression)
|
firAccessor.body = convertFunctionBody(block, expression)
|
||||||
FunctionUtil.firFunctions.removeLast()
|
firFunctions.removeLast()
|
||||||
return firAccessor
|
return firAccessor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -949,7 +946,7 @@ class DeclarationsConverter(
|
|||||||
functionDeclaration.forEachChildren {
|
functionDeclaration.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||||
IDENTIFIER -> identifier = it.getAsString()
|
IDENTIFIER -> identifier = it.asText
|
||||||
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
TYPE_PARAMETER_LIST -> firTypeParameters += convertTypeParameters(it)
|
||||||
VALUE_PARAMETER_LIST -> valueParametersList = it //must convert later, because it can contains "return"
|
VALUE_PARAMETER_LIST -> valueParametersList = it //must convert later, because it can contains "return"
|
||||||
COLON -> isReturnType = true
|
COLON -> isReturnType = true
|
||||||
@@ -976,7 +973,7 @@ class DeclarationsConverter(
|
|||||||
FirMemberFunctionImpl(
|
FirMemberFunctionImpl(
|
||||||
session,
|
session,
|
||||||
null,
|
null,
|
||||||
FirNamedFunctionSymbol(ClassNameUtil.callableIdForName(functionName, isLocal)),
|
FirNamedFunctionSymbol(callableIdForName(functionName, isLocal)),
|
||||||
functionName,
|
functionName,
|
||||||
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
|
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
|
||||||
modifiers.getModality(),
|
modifiers.getModality(),
|
||||||
@@ -994,7 +991,7 @@ class DeclarationsConverter(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionUtil.firFunctions += firFunction
|
firFunctions += firFunction
|
||||||
firFunction.annotations += modifiers.annotations
|
firFunction.annotations += modifiers.annotations
|
||||||
|
|
||||||
if (firFunction is FirMemberFunctionImpl) {
|
if (firFunction is FirMemberFunctionImpl) {
|
||||||
@@ -1004,7 +1001,7 @@ class DeclarationsConverter(
|
|||||||
|
|
||||||
valueParametersList?.let { firFunction.valueParameters += convertValueParameters(it).map { it.firValueParameter } }
|
valueParametersList?.let { firFunction.valueParameters += convertValueParameters(it).map { it.firValueParameter } }
|
||||||
firFunction.body = convertFunctionBody(block, expression)
|
firFunction.body = convertFunctionBody(block, expression)
|
||||||
FunctionUtil.firFunctions.removeLast()
|
firFunctions.removeLast()
|
||||||
return firFunction
|
return firFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1035,7 +1032,7 @@ class DeclarationsConverter(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
return if (!stubMode) {
|
return if (!stubMode) {
|
||||||
val blockTree = LightTree2Fir.buildLightTreeBlockExpression(block.getAsString())
|
val blockTree = LightTree2Fir.buildLightTreeBlockExpression(block.asText)
|
||||||
return DeclarationsConverter(session, stubMode, blockTree).convertBlockExpression(blockTree.root)
|
return DeclarationsConverter(session, stubMode, blockTree).convertBlockExpression(blockTree.root)
|
||||||
} else {
|
} else {
|
||||||
FirSingleExpressionBlock(
|
FirSingleExpressionBlock(
|
||||||
@@ -1084,7 +1081,7 @@ class DeclarationsConverter(
|
|||||||
val firValueArguments = mutableListOf<FirExpression>()
|
val firValueArguments = mutableListOf<FirExpression>()
|
||||||
constructorInvocation.forEachChildren {
|
constructorInvocation.forEachChildren {
|
||||||
when (it.tokenType) {
|
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)
|
VALUE_ARGUMENT_LIST -> firValueArguments += expressionConverter.convertValueArguments(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1149,7 +1146,7 @@ class DeclarationsConverter(
|
|||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
//annotations will be saved later, on mapping stage with type parameters
|
//annotations will be saved later, on mapping stage with type parameters
|
||||||
ANNOTATION, ANNOTATION_ENTRY -> annotations += convertAnnotation(it)
|
ANNOTATION, ANNOTATION_ENTRY -> annotations += convertAnnotation(it)
|
||||||
REFERENCE_EXPRESSION -> identifier = it.getAsString()
|
REFERENCE_EXPRESSION -> identifier = it.asText
|
||||||
TYPE_REFERENCE -> firType = convertType(it)
|
TYPE_REFERENCE -> firType = convertType(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1167,7 +1164,7 @@ class DeclarationsConverter(
|
|||||||
typeParameter.forEachChildren {
|
typeParameter.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
MODIFIER_LIST -> typeParameterModifiers = convertTypeParameterModifiers(it)
|
MODIFIER_LIST -> typeParameterModifiers = convertTypeParameterModifiers(it)
|
||||||
IDENTIFIER -> identifier = it.getAsString()
|
IDENTIFIER -> identifier = it.asText
|
||||||
TYPE_REFERENCE -> firType = convertType(it)
|
TYPE_REFERENCE -> firType = convertType(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1190,7 +1187,7 @@ class DeclarationsConverter(
|
|||||||
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeRef
|
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseTypeRef
|
||||||
*/
|
*/
|
||||||
fun convertType(type: LighterASTNode): FirTypeRef {
|
fun convertType(type: LighterASTNode): FirTypeRef {
|
||||||
if (type.getAsString().isEmpty()) {
|
if (type.asText.isEmpty()) {
|
||||||
return FirErrorTypeRefImpl(session, null, "Unwrapped type is null")
|
return FirErrorTypeRefImpl(session, null, "Unwrapped type is null")
|
||||||
}
|
}
|
||||||
var typeModifiers = TypeModifier(session) //TODO what with suspend?
|
var typeModifiers = TypeModifier(session) //TODO what with suspend?
|
||||||
@@ -1254,7 +1251,7 @@ class DeclarationsConverter(
|
|||||||
userType.forEachChildren {
|
userType.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
USER_TYPE -> simpleFirUserType = convertUserType(it) as? FirUserTypeRef //simple user type
|
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)
|
TYPE_ARGUMENT_LIST -> firTypeArguments += convertTypeArguments(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1363,7 +1360,7 @@ class DeclarationsConverter(
|
|||||||
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
MODIFIER_LIST -> modifiers = convertModifierList(it)
|
||||||
VAL_KEYWORD -> isVal = true
|
VAL_KEYWORD -> isVal = true
|
||||||
VAR_KEYWORD -> isVar = true
|
VAR_KEYWORD -> isVar = true
|
||||||
IDENTIFIER -> identifier = it.getAsString()
|
IDENTIFIER -> identifier = it.asText
|
||||||
TYPE_REFERENCE -> firType = convertType(it)
|
TYPE_REFERENCE -> firType = convertType(it)
|
||||||
DESTRUCTURING_DECLARATION -> destructuringDeclaration = convertDestructingDeclaration(it)
|
DESTRUCTURING_DECLARATION -> destructuringDeclaration = convertDestructingDeclaration(it)
|
||||||
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it, "Should have default value")
|
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.labels.FirLabelImpl
|
||||||
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom
|
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString
|
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringWithoutBacktick
|
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringWithoutBacktick
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression
|
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
|
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toReturn
|
import org.jetbrains.kotlin.fir.lightTree.converter.utils.bangBangToWhen
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.pop
|
import org.jetbrains.kotlin.fir.lightTree.converter.utils.generateDestructuringBlock
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
|
import org.jetbrains.kotlin.fir.lightTree.converter.utils.getOperationSymbol
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.utils.*
|
import org.jetbrains.kotlin.fir.lightTree.converter.utils.qualifiedAccessTokens
|
||||||
import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter
|
import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter
|
||||||
import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry
|
import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry
|
||||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
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.FirTypeProjection
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
|
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.lexer.KtTokens.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.psi.KtForExpression
|
import org.jetbrains.kotlin.psi.KtForExpression
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
|
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.types.expressions.OperatorConventions
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
class ExpressionsConverter(
|
class ExpressionsConverter(
|
||||||
val session: FirSession,
|
session: FirSession,
|
||||||
private val stubMode: Boolean,
|
private val stubMode: Boolean,
|
||||||
tree: FlyweightCapableTreeStructure<LighterASTNode>,
|
tree: FlyweightCapableTreeStructure<LighterASTNode>,
|
||||||
private val declarationsConverter: DeclarationsConverter
|
private val declarationsConverter: DeclarationsConverter
|
||||||
) : BaseConverter(session, tree) {
|
) : 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 {
|
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)
|
return expression?.let { convertExpression(it, errorReason) } as? R ?: (FirErrorExpressionImpl(session, null, errorReason) as R)
|
||||||
}
|
}
|
||||||
@@ -64,7 +65,7 @@ class ExpressionsConverter(
|
|||||||
if (!stubMode) {
|
if (!stubMode) {
|
||||||
return when (expression.tokenType) {
|
return when (expression.tokenType) {
|
||||||
LAMBDA_EXPRESSION -> {
|
LAMBDA_EXPRESSION -> {
|
||||||
val lambdaTree = LightTree2Fir.buildLightTreeLambdaExpression(expression.getAsString())
|
val lambdaTree = LightTree2Fir.buildLightTreeLambdaExpression(expression.asText)
|
||||||
ExpressionsConverter(session, stubMode, lambdaTree, declarationsConverter).convertLambdaExpression(lambdaTree.root)
|
ExpressionsConverter(session, stubMode, lambdaTree, declarationsConverter).convertLambdaExpression(lambdaTree.root)
|
||||||
}
|
}
|
||||||
BINARY_EXPRESSION -> convertBinaryExpression(expression)
|
BINARY_EXPRESSION -> convertBinaryExpression(expression)
|
||||||
@@ -121,7 +122,7 @@ class ExpressionsConverter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return FirAnonymousFunctionImpl(session, null, implicitType, implicitType).apply {
|
return FirAnonymousFunctionImpl(session, null, implicitType, implicitType).apply {
|
||||||
FunctionUtil.firFunctions += this
|
firFunctions += this
|
||||||
var destructuringBlock: FirExpression? = null
|
var destructuringBlock: FirExpression? = null
|
||||||
for (valueParameter in valueParameterList) {
|
for (valueParameter in valueParameterList) {
|
||||||
val multiDeclaration = valueParameter.destructuringDeclaration
|
val multiDeclaration = valueParameter.destructuringDeclaration
|
||||||
@@ -142,11 +143,11 @@ class ExpressionsConverter(
|
|||||||
valueParameter.firValueParameter
|
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())
|
FirLabelImpl(this@ExpressionsConverter.session, null, it.asString())
|
||||||
}
|
}
|
||||||
val bodyExpression = block?.let { declarationsConverter.convertBlockExpression(it) }
|
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) {
|
body = if (bodyExpression is FirBlockImpl) {
|
||||||
if (bodyExpression.statements.isEmpty()) {
|
if (bodyExpression.statements.isEmpty()) {
|
||||||
bodyExpression.statements.add(FirUnitExpression(this@ExpressionsConverter.session, null))
|
bodyExpression.statements.add(FirUnitExpression(this@ExpressionsConverter.session, null))
|
||||||
@@ -161,7 +162,7 @@ class ExpressionsConverter(
|
|||||||
FirSingleExpressionBlock(this@ExpressionsConverter.session, bodyExpression.toReturn())
|
FirSingleExpressionBlock(this@ExpressionsConverter.session, bodyExpression.toReturn())
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionUtil.firFunctions.removeLast()
|
firFunctions.removeLast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +179,7 @@ class ExpressionsConverter(
|
|||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
OPERATION_REFERENCE -> {
|
OPERATION_REFERENCE -> {
|
||||||
isLeftArgument = false
|
isLeftArgument = false
|
||||||
operationTokenName = it.getAsString()
|
operationTokenName = it.asText
|
||||||
}
|
}
|
||||||
else -> if (it.isExpression()) {
|
else -> if (it.isExpression()) {
|
||||||
if (isLeftArgument) {
|
if (isLeftArgument) {
|
||||||
@@ -218,7 +219,7 @@ class ExpressionsConverter(
|
|||||||
} else {
|
} else {
|
||||||
val firOperation = operationToken.toFirOperation()
|
val firOperation = operationToken.toFirOperation()
|
||||||
if (firOperation in FirOperation.ASSIGNMENTS) {
|
if (firOperation in FirOperation.ASSIGNMENTS) {
|
||||||
return convertAssignment(leftArgNode, rightArgAsFir, firOperation)
|
return leftArgNode.generateAssignment(null, rightArgAsFir, firOperation) { toFirExpression() }
|
||||||
} else {
|
} else {
|
||||||
FirOperatorCallImpl(session, null, firOperation).apply {
|
FirOperatorCallImpl(session, null, firOperation).apply {
|
||||||
arguments += getAsFirExpression<FirExpression>(leftArgNode, "No left operand")
|
arguments += getAsFirExpression<FirExpression>(leftArgNode, "No left operand")
|
||||||
@@ -238,7 +239,7 @@ class ExpressionsConverter(
|
|||||||
lateinit var firType: FirTypeRef
|
lateinit var firType: FirTypeRef
|
||||||
binaryExpression.forEachChildren {
|
binaryExpression.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
OPERATION_REFERENCE -> operationTokenName = it.getAsString()
|
OPERATION_REFERENCE -> operationTokenName = it.asText
|
||||||
TYPE_REFERENCE -> firType = declarationsConverter.convertType(it)
|
TYPE_REFERENCE -> firType = declarationsConverter.convertType(it)
|
||||||
else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it, "No left operand")
|
else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it, "No left operand")
|
||||||
}
|
}
|
||||||
@@ -259,7 +260,7 @@ class ExpressionsConverter(
|
|||||||
lateinit var firType: FirTypeRef
|
lateinit var firType: FirTypeRef
|
||||||
isExpression.forEachChildren {
|
isExpression.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
OPERATION_REFERENCE -> operationTokenName = it.getAsString()
|
OPERATION_REFERENCE -> operationTokenName = it.asText
|
||||||
TYPE_REFERENCE -> firType = declarationsConverter.convertType(it)
|
TYPE_REFERENCE -> firType = declarationsConverter.convertType(it)
|
||||||
else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it, "No left operand")
|
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
|
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitLabeledExpression
|
||||||
*/
|
*/
|
||||||
private fun convertLabeledExpression(labeledExpression: LighterASTNode): FirElement {
|
private fun convertLabeledExpression(labeledExpression: LighterASTNode): FirElement {
|
||||||
val size = FunctionUtil.firLabels.size
|
val size = firLabels.size
|
||||||
var firExpression: FirElement? = null
|
var firExpression: FirElement? = null
|
||||||
labeledExpression.forEachChildren {
|
labeledExpression.forEachChildren {
|
||||||
when (it.tokenType) {
|
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)
|
BLOCK -> firExpression = declarationsConverter.convertBlock(it)
|
||||||
PROPERTY -> firExpression = declarationsConverter.convertPropertyDeclaration(it)
|
PROPERTY -> firExpression = declarationsConverter.convertPropertyDeclaration(it)
|
||||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
|
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size != FunctionUtil.firLabels.size) {
|
if (size != firLabels.size) {
|
||||||
FunctionUtil.firLabels.removeLast()
|
firLabels.removeLast()
|
||||||
//println("Unused label: ${labeledExpression.getAsString()}")
|
//println("Unused label: ${labeledExpression.getAsString()}")
|
||||||
}
|
}
|
||||||
return firExpression ?: FirErrorExpressionImpl(session, null, "Empty label")
|
return firExpression ?: FirErrorExpressionImpl(session, null, "Empty label")
|
||||||
@@ -304,7 +305,7 @@ class ExpressionsConverter(
|
|||||||
var argument: LighterASTNode? = null
|
var argument: LighterASTNode? = null
|
||||||
unaryExpression.forEachChildren {
|
unaryExpression.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
OPERATION_REFERENCE -> operationTokenName = it.getAsString()
|
OPERATION_REFERENCE -> operationTokenName = it.asText
|
||||||
else -> if (it.isExpression()) argument = it
|
else -> if (it.isExpression()) argument = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -318,10 +319,11 @@ class ExpressionsConverter(
|
|||||||
return if (conventionCallName != null) {
|
return if (conventionCallName != null) {
|
||||||
if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) {
|
if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) {
|
||||||
return generateIncrementOrDecrementBlock(
|
return generateIncrementOrDecrementBlock(
|
||||||
|
null,
|
||||||
argument,
|
argument,
|
||||||
callName = conventionCallName,
|
callName = conventionCallName,
|
||||||
prefix = unaryExpression.tokenType == PREFIX_EXPRESSION
|
prefix = unaryExpression.tokenType == PREFIX_EXPRESSION
|
||||||
)
|
) { toFirExpression() }
|
||||||
}
|
}
|
||||||
FirFunctionCallImpl(session, null).apply {
|
FirFunctionCallImpl(session, null).apply {
|
||||||
calleeReference = FirSimpleNamedReference(this@ExpressionsConverter.session, null, conventionCallName)
|
calleeReference = FirSimpleNamedReference(this@ExpressionsConverter.session, null, conventionCallName)
|
||||||
@@ -440,7 +442,7 @@ class ExpressionsConverter(
|
|||||||
var additionalArgument: FirExpression? = null
|
var additionalArgument: FirExpression? = null
|
||||||
callSuffix.forEachChildren {
|
callSuffix.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
REFERENCE_EXPRESSION -> name = it.getAsString()
|
REFERENCE_EXPRESSION -> name = it.asText
|
||||||
TYPE_ARGUMENT_LIST -> firTypeArguments += declarationsConverter.convertTypeArguments(it)
|
TYPE_ARGUMENT_LIST -> firTypeArguments += declarationsConverter.convertTypeArguments(it)
|
||||||
VALUE_ARGUMENT_LIST, LAMBDA_ARGUMENT -> valueArguments += it
|
VALUE_ARGUMENT_LIST, LAMBDA_ARGUMENT -> valueArguments += it
|
||||||
else -> if (it.tokenType != TokenType.ERROR_ELEMENT) additionalArgument =
|
else -> if (it.tokenType != TokenType.ERROR_ELEMENT) additionalArgument =
|
||||||
@@ -458,119 +460,33 @@ class ExpressionsConverter(
|
|||||||
else -> FirErrorNamedReference(this@ExpressionsConverter.session, null, "Call has no callee")
|
else -> FirErrorNamedReference(this@ExpressionsConverter.session, null, "Call has no callee")
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionUtil.firFunctionCalls += this
|
firFunctionCalls += this
|
||||||
this.extractArgumentsFrom(valueArguments.flatMap { convertValueArguments(it) }, stubMode)
|
this.extractArgumentsFrom(valueArguments.flatMap { convertValueArguments(it) }, stubMode)
|
||||||
typeArguments += firTypeArguments
|
typeArguments += firTypeArguments
|
||||||
FunctionUtil.firFunctionCalls.removeLast()
|
firFunctionCalls.removeLast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseStringTemplate
|
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseStringTemplate
|
||||||
* @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.toInterpolatingCall
|
|
||||||
*/
|
*/
|
||||||
private fun convertStringTemplate(stringTemplate: LighterASTNode): FirExpression {
|
private fun convertStringTemplate(stringTemplate: LighterASTNode): FirExpression {
|
||||||
val sb = StringBuilder()
|
return stringTemplate.getChildrenAsArray().toInterpolatingCall(null) { convertShortOrLongStringTemplate(it) }
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertShortOrLongStringTemplate(shortOrLongString: LighterASTNode): FirExpression {
|
private fun LighterASTNode?.convertShortOrLongStringTemplate(errorReason: String): FirExpression {
|
||||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Incorrect template argument")
|
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, errorReason)
|
||||||
shortOrLongString.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) {
|
this?.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) {
|
||||||
firExpression = getAsFirExpression(it, "Incorrect template argument")
|
firExpression = getAsFirExpression(it, errorReason)
|
||||||
}
|
}
|
||||||
return firExpression
|
return firExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseLiteralConstant
|
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseLiteralConstant
|
||||||
* @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.generateConstantExpressionByLiteral
|
|
||||||
*/
|
*/
|
||||||
private fun convertConstantExpression(constantExpression: LighterASTNode): FirExpression {
|
private fun convertConstantExpression(constantExpression: LighterASTNode): FirExpression {
|
||||||
val type = constantExpression.tokenType
|
return generateConstantExpressionByLiteral(constantExpression)
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -590,10 +506,10 @@ class ExpressionsConverter(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
DESTRUCTURING_DECLARATION -> subjectExpression =
|
DESTRUCTURING_DECLARATION -> subjectExpression =
|
||||||
getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.getAsString()}")
|
getAsFirExpression(it, "Incorrect when subject expression: ${whenExpression.asText}")
|
||||||
WHEN_ENTRY -> whenEntries += convertWhenEntry(it)
|
WHEN_ENTRY -> whenEntries += convertWhenEntry(it)
|
||||||
else -> if (it.isExpression()) subjectExpression =
|
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 {
|
private fun convertSimpleNameExpression(referenceExpression: LighterASTNode): FirQualifiedAccessExpression {
|
||||||
return FirQualifiedAccessExpressionImpl(session, null).apply {
|
return FirQualifiedAccessExpressionImpl(session, null).apply {
|
||||||
calleeReference =
|
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) {
|
when (it.tokenType) {
|
||||||
CONTINUE_KEYWORD -> isBreak = false
|
CONTINUE_KEYWORD -> isBreak = false
|
||||||
//BREAK -> isBreak = true
|
//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 {
|
return (if (isBreak) FirBreakExpressionImpl(session, null) else FirContinueExpressionImpl(session, null)).apply {
|
||||||
target = FirLoopTarget(labelName)
|
target = FirLoopTarget(labelName)
|
||||||
val lastLoop = FunctionUtil.firLoops.lastOrNull()
|
val lastLoop = firLoops.lastOrNull()
|
||||||
if (labelName == null) {
|
if (labelName == null) {
|
||||||
if (lastLoop != null) {
|
if (lastLoop != null) {
|
||||||
target.bind(lastLoop)
|
target.bind(lastLoop)
|
||||||
@@ -977,7 +893,7 @@ class ExpressionsConverter(
|
|||||||
target.bind(FirErrorLoop(this@ExpressionsConverter.session, null, "Cannot bind unlabeled jump to a loop"))
|
target.bind(FirErrorLoop(this@ExpressionsConverter.session, null, "Cannot bind unlabeled jump to a loop"))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (firLoop in FunctionUtil.firLoops.asReversed()) {
|
for (firLoop in firLoops.asReversed()) {
|
||||||
if (firLoop.label?.name == labelName) {
|
if (firLoop.label?.name == labelName) {
|
||||||
target.bind(firLoop)
|
target.bind(firLoop)
|
||||||
return this
|
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
|
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitThisExpression
|
||||||
*/
|
*/
|
||||||
private fun convertThisExpression(thisExpression: LighterASTNode): FirQualifiedAccessExpression {
|
private fun convertThisExpression(thisExpression: LighterASTNode): FirQualifiedAccessExpression {
|
||||||
var label: String? = null
|
val label: String? = thisExpression.getLabelName()
|
||||||
thisExpression.forEachChildren {
|
|
||||||
when (it.tokenType) {
|
|
||||||
LABEL_QUALIFIER -> label = it.getAsString().replaceFirst("@", "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FirQualifiedAccessExpressionImpl(session, null).apply {
|
return FirQualifiedAccessExpressionImpl(session, null).apply {
|
||||||
calleeReference = FirExplicitThisReference(this@ExpressionsConverter.session, null, label)
|
calleeReference = FirExplicitThisReference(this@ExpressionsConverter.session, null, label)
|
||||||
@@ -1076,7 +987,7 @@ class ExpressionsConverter(
|
|||||||
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Argument is absent")
|
var firExpression: FirExpression = FirErrorExpressionImpl(session, null, "Argument is absent")
|
||||||
valueArgument.forEachChildren {
|
valueArgument.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
VALUE_ARGUMENT_NAME -> identifier = it.getAsString()
|
VALUE_ARGUMENT_NAME -> identifier = it.asText
|
||||||
MUL -> isSpread = true
|
MUL -> isSpread = true
|
||||||
STRING_TEMPLATE -> firExpression = convertStringTemplate(it)
|
STRING_TEMPLATE -> firExpression = convertStringTemplate(it)
|
||||||
is KtConstantExpressionElementType -> firExpression = convertConstantExpression(it)
|
is KtConstantExpressionElementType -> firExpression = convertConstantExpression(it)
|
||||||
@@ -1089,22 +1000,4 @@ class ExpressionsConverter(
|
|||||||
else -> firExpression
|
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
|
package org.jetbrains.kotlin.fir.lightTree.converter.utils
|
||||||
|
|
||||||
import com.intellij.lang.LighterASTNode
|
|
||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import com.intellij.psi.tree.TokenSet
|
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.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.declarations.impl.FirVariableImpl
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.*
|
import org.jetbrains.kotlin.fir.expressions.FirVariable
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString
|
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
|
import org.jetbrains.kotlin.fir.expressions.impl.FirBlockImpl
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.ExpressionsConverter
|
import org.jetbrains.kotlin.fir.expressions.impl.FirComponentCallImpl
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil
|
import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.pop
|
import org.jetbrains.kotlin.fir.expressions.impl.FirThrowExpressionImpl
|
||||||
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
|
|
||||||
import org.jetbrains.kotlin.fir.lightTree.fir.DestructuringDeclaration
|
import org.jetbrains.kotlin.fir.lightTree.fir.DestructuringDeclaration
|
||||||
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
|
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||||
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
import org.jetbrains.kotlin.lexer.KtTokens.AS_SAFE
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.lexer.KtTokens.IDENTIFIER
|
||||||
import org.jetbrains.kotlin.parsing.KotlinExpressionParsing
|
import org.jetbrains.kotlin.parsing.KotlinExpressionParsing
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
|
||||||
|
|
||||||
val qualifiedAccessTokens = TokenSet.create(DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION)
|
val qualifiedAccessTokens = TokenSet.create(DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION)
|
||||||
|
|
||||||
@@ -39,118 +39,6 @@ fun String.getOperationSymbol(): IElementType {
|
|||||||
return IDENTIFIER
|
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(
|
fun generateDestructuringBlock(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
multiDeclaration: DestructuringDeclaration,
|
multiDeclaration: DestructuringDeclaration,
|
||||||
@@ -186,23 +74,3 @@ fun bangBangToWhen(session: FirSession, baseExpression: FirExpression): FirWhenE
|
|||||||
), "bangbang", null
|
), "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.FirBlock
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
|
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.lightTree.fir.modifier.Modifier
|
||||||
import org.jetbrains.kotlin.fir.references.FirPropertyFromParameterCallableReference
|
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.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
@@ -32,7 +32,7 @@ class ValueParameter(
|
|||||||
return isVal || isVar
|
return isVal || isVar
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toFirProperty(): FirProperty {
|
fun toFirProperty(callableId: CallableId): FirProperty {
|
||||||
val name = this.firValueParameter.name
|
val name = this.firValueParameter.name
|
||||||
var type = this.firValueParameter.returnTypeRef
|
var type = this.firValueParameter.returnTypeRef
|
||||||
if (type is FirImplicitTypeRef) {
|
if (type is FirImplicitTypeRef) {
|
||||||
@@ -42,7 +42,7 @@ class ValueParameter(
|
|||||||
return FirMemberPropertyImpl(
|
return FirMemberPropertyImpl(
|
||||||
this.firValueParameter.session,
|
this.firValueParameter.session,
|
||||||
null,
|
null,
|
||||||
FirPropertySymbol(ClassNameUtil.callableIdForName(name)),
|
FirPropertySymbol(callableId),
|
||||||
name,
|
name,
|
||||||
modifiers.getVisibility(),
|
modifiers.getVisibility(),
|
||||||
modifiers.getModality(),
|
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
|
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? {
|
fun IElementType.toBinaryName(): Name? {
|
||||||
return OperatorConventions.BINARY_OPERATION_NAMES[this]
|
return OperatorConventions.BINARY_OPERATION_NAMES[this]
|
||||||
}
|
}
|
||||||
@@ -281,53 +234,6 @@ internal fun Array<KtWhenCondition>.toFirWhenCondition(
|
|||||||
return firCondition!!
|
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(
|
fun FirExpression.generateContainsOperation(
|
||||||
argument: FirExpression,
|
argument: FirExpression,
|
||||||
inverted: Boolean,
|
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 =
|
fun generateAccessExpression(psi: PsiElement?, name: Name): FirQualifiedAccessExpression =
|
||||||
FirQualifiedAccessExpressionImpl(psi).apply {
|
FirQualifiedAccessExpressionImpl(psi).apply {
|
||||||
calleeReference = FirSimpleNamedReference(psi, name)
|
calleeReference = FirSimpleNamedReference(psi, name)
|
||||||
@@ -472,164 +299,3 @@ fun generateTemporaryVariable(
|
|||||||
fun generateTemporaryVariable(
|
fun generateTemporaryVariable(
|
||||||
session: FirSession, psi: PsiElement?, specialName: String, initializer: FirExpression
|
session: FirSession, psi: PsiElement?, specialName: String, initializer: FirExpression
|
||||||
): FirVariable<*> = generateTemporaryVariable(session, psi, Name.special("<$specialName>"), initializer)
|
): 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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||||
|
|
||||||
internal fun KtClassOrObject.generateComponentFunctions(
|
fun List<Pair<KtParameter?, FirProperty>>.generateComponentFunctions(
|
||||||
session: FirSession, firClass: FirClassImpl, packageFqName: FqName, classFqName: FqName
|
session: FirSession, firClass: FirClassImpl, packageFqName: FqName, classFqName: FqName
|
||||||
) {
|
) {
|
||||||
var componentIndex = 1
|
var componentIndex = 1
|
||||||
val zippedParameters =
|
for ((ktParameter, firProperty) in this) {
|
||||||
primaryConstructorParameters.zip(firClass.declarations.filterIsInstance<FirProperty>())
|
if (!firProperty.isVal && !firProperty.isVar) continue
|
||||||
for ((ktParameter, firProperty) in zippedParameters) {
|
|
||||||
if (!ktParameter.hasValOrVar()) continue
|
|
||||||
val name = Name.identifier("component$componentIndex")
|
val name = Name.identifier("component$componentIndex")
|
||||||
componentIndex++
|
componentIndex++
|
||||||
val symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, name))
|
val symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, name))
|
||||||
@@ -52,7 +51,7 @@ internal fun KtClassOrObject.generateComponentFunctions(
|
|||||||
FirReturnExpressionImpl(
|
FirReturnExpressionImpl(
|
||||||
ktParameter,
|
ktParameter,
|
||||||
FirQualifiedAccessExpressionImpl(ktParameter).apply {
|
FirQualifiedAccessExpressionImpl(ktParameter).apply {
|
||||||
val parameterName = ktParameter.nameAsSafeName
|
val parameterName = firProperty.name
|
||||||
calleeReference = FirResolvedCallableReferenceImpl(
|
calleeReference = FirResolvedCallableReferenceImpl(
|
||||||
ktParameter,
|
ktParameter,
|
||||||
parameterName, firProperty.symbol
|
parameterName, firProperty.symbol
|
||||||
@@ -70,15 +69,14 @@ internal fun KtClassOrObject.generateComponentFunctions(
|
|||||||
|
|
||||||
private val copyName = Name.identifier("copy")
|
private val copyName = Name.identifier("copy")
|
||||||
|
|
||||||
internal fun KtClassOrObject.generateCopyFunction(
|
fun List<Pair<KtParameter?, FirProperty>>.generateCopyFunction(
|
||||||
session: FirSession, firClass: FirClassImpl, packageFqName: FqName, classFqName: FqName,
|
session: FirSession, classOrObject: KtClassOrObject?, firClass: FirClassImpl, packageFqName: FqName, classFqName: FqName,
|
||||||
firPrimaryConstructor: FirConstructor,
|
firPrimaryConstructor: FirConstructor
|
||||||
toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef
|
|
||||||
) {
|
) {
|
||||||
val symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, copyName))
|
val symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, copyName))
|
||||||
firClass.addDeclaration(
|
firClass.addDeclaration(
|
||||||
FirMemberFunctionImpl(
|
FirMemberFunctionImpl(
|
||||||
session, this, symbol, copyName,
|
session, classOrObject, symbol, copyName,
|
||||||
Visibilities.PUBLIC, Modality.FINAL,
|
Visibilities.PUBLIC, Modality.FINAL,
|
||||||
isExpect = false, isActual = false,
|
isExpect = false, isActual = false,
|
||||||
isOverride = false, isOperator = false,
|
isOverride = false, isOperator = false,
|
||||||
@@ -88,13 +86,11 @@ internal fun KtClassOrObject.generateCopyFunction(
|
|||||||
returnTypeRef = firPrimaryConstructor.returnTypeRef//FirImplicitTypeRefImpl(session, this)
|
returnTypeRef = firPrimaryConstructor.returnTypeRef//FirImplicitTypeRefImpl(session, this)
|
||||||
).apply {
|
).apply {
|
||||||
val copyFunction = this
|
val copyFunction = this
|
||||||
val zippedParameters =
|
for ((ktParameter, firProperty) in this@generateCopyFunction) {
|
||||||
primaryConstructorParameters.zip(firClass.declarations.filterIsInstance<FirProperty>())
|
val name = firProperty.name
|
||||||
for ((ktParameter, firProperty) in zippedParameters) {
|
|
||||||
val name = ktParameter.nameAsSafeName
|
|
||||||
valueParameters += FirValueParameterImpl(
|
valueParameters += FirValueParameterImpl(
|
||||||
session, ktParameter, name,
|
session, ktParameter, name,
|
||||||
ktParameter.typeReference.toFirOrErrorTypeRef(),
|
firProperty.returnTypeRef,
|
||||||
FirQualifiedAccessExpressionImpl(ktParameter).apply {
|
FirQualifiedAccessExpressionImpl(ktParameter).apply {
|
||||||
calleeReference = FirResolvedCallableReferenceImpl(ktParameter, name, firProperty.symbol)
|
calleeReference = FirResolvedCallableReferenceImpl(ktParameter, name, firProperty.symbol)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.builder
|
package org.jetbrains.kotlin.fir.builder
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
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.types.expressions.OperatorConventions
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder<PsiElement>(session) {
|
||||||
|
|
||||||
private val implicitUnitType = FirImplicitUnitTypeRef(null)
|
|
||||||
|
|
||||||
private val implicitAnyType = FirImplicitAnyTypeRef(null)
|
|
||||||
|
|
||||||
private val implicitEnumType = FirImplicitEnumTypeRef(null)
|
|
||||||
|
|
||||||
private val implicitAnnotationType = FirImplicitAnnotationTypeRef(null)
|
|
||||||
|
|
||||||
fun buildFirFile(file: KtFile): FirFile {
|
fun buildFirFile(file: KtFile): FirFile {
|
||||||
return file.accept(Visitor(), Unit) as 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
|
private val KtModifierListOwner.visibility: Visibility
|
||||||
get() = with(modifierList) {
|
get() = with(modifierList) {
|
||||||
when {
|
when {
|
||||||
@@ -126,38 +147,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
|||||||
FirSingleExpressionBlock(convert())
|
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? =
|
private fun KtDeclarationWithBody.buildFirBody(): FirBlock? =
|
||||||
when {
|
when {
|
||||||
!hasBody() ->
|
!hasBody() ->
|
||||||
@@ -404,8 +393,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
|||||||
return firConstructor
|
return firConstructor
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var packageFqName: FqName
|
|
||||||
|
|
||||||
override fun visitKtFile(file: KtFile, data: Unit): FirElement {
|
override fun visitKtFile(file: KtFile, data: Unit): FirElement {
|
||||||
packageFqName = file.packageFqName
|
packageFqName = file.packageFqName
|
||||||
val firFile = FirFileImpl(session, file, file.name, packageFqName)
|
val firFile = FirFileImpl(session, file, file.name, packageFqName)
|
||||||
@@ -426,29 +413,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
|||||||
return firFile
|
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 {
|
override fun visitEnumEntry(enumEntry: KtEnumEntry, data: Unit): FirElement {
|
||||||
return withChildClassName(enumEntry.nameAsSafeName) {
|
return withChildClassName(enumEntry.nameAsSafeName) {
|
||||||
val firEnumEntry = FirEnumEntryImpl(
|
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 {
|
override fun visitClassOrObject(classOrObject: KtClassOrObject, data: Unit): FirElement {
|
||||||
return withChildClassName(classOrObject.nameAsSafeName) {
|
return withChildClassName(classOrObject.nameAsSafeName) {
|
||||||
|
|
||||||
@@ -544,10 +486,11 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (classOrObject.hasModifier(DATA_KEYWORD) && firPrimaryConstructor != null) {
|
if (classOrObject.hasModifier(DATA_KEYWORD) && firPrimaryConstructor != null) {
|
||||||
classOrObject.generateComponentFunctions(session, firClass, packageFqName, className)
|
val zippedParameters = classOrObject.primaryConstructorParameters.zip(
|
||||||
classOrObject.generateCopyFunction(session, firClass, packageFqName, className, firPrimaryConstructor) {
|
firClass.declarations.filterIsInstance<FirProperty>()
|
||||||
toFirOrErrorType()
|
)
|
||||||
}
|
zippedParameters.generateComponentFunctions(session, firClass, packageFqName, className)
|
||||||
|
zippedParameters.generateCopyFunction(session, classOrObject, firClass, packageFqName, className, firPrimaryConstructor)
|
||||||
// TODO: equals, hashCode, toString
|
// 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 {
|
override fun visitNamedFunction(function: KtNamedFunction, data: Unit): FirElement {
|
||||||
val typeReference = function.typeReference
|
val typeReference = function.typeReference
|
||||||
val returnType = if (function.hasBlockBody()) {
|
val returnType = if (function.hasBlockBody()) {
|
||||||
@@ -722,13 +651,6 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
|||||||
return firConstructor
|
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(
|
private fun KtConstructorDelegationCall.convert(
|
||||||
delegatedSuperTypeRef: FirTypeRef?,
|
delegatedSuperTypeRef: FirTypeRef?,
|
||||||
delegatedSelfTypeRef: FirTypeRef,
|
delegatedSelfTypeRef: FirTypeRef,
|
||||||
@@ -956,7 +878,9 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
|||||||
generateConstantExpressionByLiteral(expression)
|
generateConstantExpressionByLiteral(expression)
|
||||||
|
|
||||||
override fun visitStringTemplateExpression(expression: KtStringTemplateExpression, data: Unit): FirElement {
|
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 {
|
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 {
|
override fun visitDoWhileExpression(expression: KtDoWhileExpression, data: Unit): FirElement {
|
||||||
return FirDoWhileLoopImpl(
|
return FirDoWhileLoopImpl(
|
||||||
expression, expression.condition.toFirExpression("No condition in do-while loop")
|
expression, expression.condition.toFirExpression("No condition in do-while loop")
|
||||||
@@ -1187,8 +1101,8 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
|||||||
} else {
|
} else {
|
||||||
val firOperation = operationToken.toFirOperation()
|
val firOperation = operationToken.toFirOperation()
|
||||||
if (firOperation in FirOperation.ASSIGNMENTS) {
|
if (firOperation in FirOperation.ASSIGNMENTS) {
|
||||||
return expression.left.generateAssignment(session, expression, rightArgument, firOperation) {
|
return expression.left.generateAssignment(expression, rightArgument, firOperation) {
|
||||||
toFirExpression("Incorrect expression in assignment: ${expression.text}")
|
(this as KtExpression).toFirExpression("Incorrect expression in assignment: ${expression.text}")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FirOperatorCallImpl(expression, firOperation).apply {
|
FirOperatorCallImpl(expression, firOperation).apply {
|
||||||
@@ -1227,10 +1141,10 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
|||||||
return if (conventionCallName != null) {
|
return if (conventionCallName != null) {
|
||||||
if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) {
|
if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) {
|
||||||
return generateIncrementOrDecrementBlock(
|
return generateIncrementOrDecrementBlock(
|
||||||
session, expression, argument,
|
expression, argument,
|
||||||
callName = conventionCallName,
|
callName = conventionCallName,
|
||||||
prefix = expression is KtPrefixExpression
|
prefix = expression is KtPrefixExpression
|
||||||
) { toFirExpression("Incorrect expression inside inc/dec") }
|
) { (this as KtExpression).toFirExpression("Incorrect expression inside inc/dec") }
|
||||||
}
|
}
|
||||||
FirFunctionCallImpl(expression).apply {
|
FirFunctionCallImpl(expression).apply {
|
||||||
calleeReference = FirSimpleNamedReference(
|
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 {
|
override fun visitCallExpression(expression: KtCallExpression, data: Unit): FirElement {
|
||||||
val calleeExpression = expression.calleeExpression
|
val calleeExpression = expression.calleeExpression
|
||||||
return FirFunctionCallImpl(expression).apply {
|
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")
|
return expression.expression?.accept(this, data) ?: FirErrorExpressionImpl(expression, "Empty parentheses")
|
||||||
}
|
}
|
||||||
|
|
||||||
private val firLabels = mutableListOf<FirLabel>()
|
|
||||||
|
|
||||||
override fun visitLabeledExpression(expression: KtLabeledExpression, data: Unit): FirElement {
|
override fun visitLabeledExpression(expression: KtLabeledExpression, data: Unit): FirElement {
|
||||||
val labelName = expression.getLabelName()
|
val labelName = expression.getLabelName()
|
||||||
val size = firLabels.size
|
val size = firLabels.size
|
||||||
|
|||||||
Reference in New Issue
Block a user