Extract some information to separate Context class

This commit is contained in:
Ivan Cilcic
2019-07-30 23:20:53 +03:00
committed by Mikhail Glukhikh
parent cad0dbf087
commit c5547a2229
6 changed files with 102 additions and 86 deletions
@@ -12,6 +12,7 @@ import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.builder.BaseFirBuilder
import org.jetbrains.kotlin.fir.builder.Context
import org.jetbrains.kotlin.fir.builder.escapedStringToCharacter
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.lexer.KtToken
@@ -23,8 +24,9 @@ import org.jetbrains.kotlin.name.Name
open class BaseConverter(
session: FirSession,
private val tree: FlyweightCapableTreeStructure<LighterASTNode>
) : BaseFirBuilder<LighterASTNode>(session) {
private val tree: FlyweightCapableTreeStructure<LighterASTNode>,
context: Context = Context()
) : BaseFirBuilder<LighterASTNode>(session, context) {
protected val implicitType = FirImplicitTypeRefImpl(session, null)
override val LighterASTNode.elementType: IElementType
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.builder.Context
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.expressions.*
@@ -49,9 +50,10 @@ import org.jetbrains.kotlin.fir.builder.generateComponentFunctions
class DeclarationsConverter(
session: FirSession,
private val stubMode: Boolean,
tree: FlyweightCapableTreeStructure<LighterASTNode>
) : BaseConverter(session, tree) {
private val expressionConverter = ExpressionsConverter(session, stubMode, tree, this)
tree: FlyweightCapableTreeStructure<LighterASTNode>,
context: Context = Context()
) : BaseConverter(session, tree, context) {
private val expressionConverter = ExpressionsConverter(session, stubMode, tree, this, context)
/**
* [org.jetbrains.kotlin.parsing.KotlinParsing.parseFile]
@@ -66,11 +68,11 @@ class DeclarationsConverter(
val fileAnnotationList = mutableListOf<FirAnnotationCall>()
val importList = mutableListOf<FirImport>()
val firDeclarationList = mutableListOf<FirDeclaration>()
packageFqName = FqName.ROOT
context.packageFqName = FqName.ROOT
file.forEachChildren {
when (it.tokenType) {
FILE_ANNOTATION_LIST -> fileAnnotationList += convertFileAnnotationList(it)
PACKAGE_DIRECTIVE -> packageFqName = convertPackageName(it)
PACKAGE_DIRECTIVE -> context.packageFqName = convertPackageName(it)
IMPORT_LIST -> importList += convertImportDirectives(it)
CLASS -> firDeclarationList += convertClass(it)
FUN -> firDeclarationList += convertFunctionDeclaration(it)
@@ -84,7 +86,7 @@ class DeclarationsConverter(
session,
null,
fileName,
packageFqName
context.packageFqName
)
firFile.annotations += fileAnnotationList
firFile.imports += importList
@@ -368,7 +370,7 @@ class DeclarationsConverter(
val firClass = FirClassImpl(
session,
null,
FirClassSymbol(currentClassId),
FirClassSymbol(context.currentClassId),
className,
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
modifiers.getModality(),
@@ -413,8 +415,8 @@ class DeclarationsConverter(
//parse data class
if (modifiers.isDataClass() && firPrimaryConstructor != null) {
val zippedParameters = MutableList(properties.size) { null }.zip(properties)
zippedParameters.generateComponentFunctions(session, firClass, packageFqName, Companion.className)
zippedParameters.generateCopyFunction(session, null, firClass, packageFqName, Companion.className, firPrimaryConstructor)
zippedParameters.generateComponentFunctions(session, firClass, context.packageFqName, context.className)
zippedParameters.generateCopyFunction(session, null, firClass, context.packageFqName, context.className, firPrimaryConstructor)
// TODO: equals, hashCode, toString
}
@@ -499,7 +501,7 @@ class DeclarationsConverter(
val firEnumEntry = FirEnumEntryImpl(
session,
null,
FirClassSymbol(currentClassId),
FirClassSymbol(context.currentClassId),
enumEntryName
)
firEnumEntry.annotations += modifiers.annotations
@@ -657,12 +659,12 @@ class DeclarationsConverter(
constructorDelegationCall
)
firFunctions += firConstructor
context.firFunctions += firConstructor
firConstructor.annotations += modifiers.annotations
firConstructor.typeParameters += typeParametersFromSelfType(delegatedSelfTypeRef)
firConstructor.valueParameters += firValueParameters.map { it.firValueParameter }
firConstructor.body = convertFunctionBody(block, null)
firFunctions.removeLast()
context.firFunctions.removeLast()
return firConstructor
}
@@ -725,7 +727,7 @@ class DeclarationsConverter(
return@withChildClassName FirTypeAliasImpl(
session,
null,
FirTypeAliasSymbol(currentClassId),
FirTypeAliasSymbol(context.currentClassId),
typeAliasName,
modifiers.getVisibility(),
modifiers.hasExpect(),
@@ -886,7 +888,7 @@ class DeclarationsConverter(
modifiers.getVisibility(),
returnType ?: if (isGetter) propertyTypeRef else implicitUnitType
)
firFunctions += firAccessor
context.firFunctions += firAccessor
firAccessor.annotations += modifiers.annotations
if (!isGetter) {
@@ -894,7 +896,7 @@ class DeclarationsConverter(
}
firAccessor.body = convertFunctionBody(block, expression)
firFunctions.removeLast()
context.firFunctions.removeLast()
return firAccessor
}
@@ -991,7 +993,7 @@ class DeclarationsConverter(
)
}
firFunctions += firFunction
context.firFunctions += firFunction
firFunction.annotations += modifiers.annotations
if (firFunction is FirMemberFunctionImpl) {
@@ -1001,7 +1003,7 @@ class DeclarationsConverter(
valueParametersList?.let { firFunction.valueParameters += convertValueParameters(it).map { it.firValueParameter } }
firFunction.body = convertFunctionBody(block, expression)
firFunctions.removeLast()
context.firFunctions.removeLast()
return firFunction
}
@@ -1033,7 +1035,7 @@ class DeclarationsConverter(
}
return if (!stubMode) {
val blockTree = LightTree2Fir.buildLightTreeBlockExpression(block.asText)
return DeclarationsConverter(session, stubMode, blockTree).convertBlockExpression(blockTree.root)
return DeclarationsConverter(session, stubMode, blockTree, context).convertBlockExpression(blockTree.root)
} else {
FirSingleExpressionBlock(
session,
@@ -49,8 +49,9 @@ class ExpressionsConverter(
session: FirSession,
private val stubMode: Boolean,
tree: FlyweightCapableTreeStructure<LighterASTNode>,
private val declarationsConverter: DeclarationsConverter
) : BaseConverter(session, tree) {
private val declarationsConverter: DeclarationsConverter,
context: Context = Context()
) : BaseConverter(session, tree, context) {
inline fun <reified R : FirElement> LighterASTNode?.toFirExpression(errorReason: String = ""): R {
return this?.let { convertExpression(it, errorReason) } as? R ?: (FirErrorExpressionImpl(session, null, errorReason) as R)
@@ -66,7 +67,7 @@ class ExpressionsConverter(
return when (expression.tokenType) {
LAMBDA_EXPRESSION -> {
val lambdaTree = LightTree2Fir.buildLightTreeLambdaExpression(expression.asText)
ExpressionsConverter(session, stubMode, lambdaTree, declarationsConverter).convertLambdaExpression(lambdaTree.root)
ExpressionsConverter(session, stubMode, lambdaTree, declarationsConverter, context).convertLambdaExpression(lambdaTree.root)
}
BINARY_EXPRESSION -> convertBinaryExpression(expression)
BINARY_WITH_TYPE -> convertBinaryWithType(expression)
@@ -122,7 +123,7 @@ class ExpressionsConverter(
}
return FirAnonymousFunctionImpl(session, null, implicitType, implicitType).apply {
firFunctions += this
context.firFunctions += this
var destructuringBlock: FirExpression? = null
for (valueParameter in valueParameterList) {
val multiDeclaration = valueParameter.destructuringDeclaration
@@ -143,7 +144,7 @@ class ExpressionsConverter(
valueParameter.firValueParameter
}
}
label = firLabels.pop() ?: firFunctionCalls.lastOrNull()?.calleeReference?.name?.let {
label = context.firLabels.pop() ?: context.firFunctionCalls.lastOrNull()?.calleeReference?.name?.let {
FirLabelImpl(this@ExpressionsConverter.session, null, it.asString())
}
val bodyExpression = block?.let { declarationsConverter.convertBlockExpression(it) }
@@ -162,7 +163,7 @@ class ExpressionsConverter(
FirSingleExpressionBlock(this@ExpressionsConverter.session, bodyExpression.toReturn())
}
firFunctions.removeLast()
context.firFunctions.removeLast()
}
}
@@ -277,19 +278,19 @@ class ExpressionsConverter(
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitLabeledExpression
*/
private fun convertLabeledExpression(labeledExpression: LighterASTNode): FirElement {
val size = firLabels.size
val size = context.firLabels.size
var firExpression: FirElement? = null
labeledExpression.forEachChildren {
when (it.tokenType) {
LABEL_QUALIFIER -> firLabels += FirLabelImpl(session, null, it.toString().replace("@", ""))
LABEL_QUALIFIER -> context.firLabels += FirLabelImpl(session, null, it.toString().replace("@", ""))
BLOCK -> firExpression = declarationsConverter.convertBlock(it)
PROPERTY -> firExpression = declarationsConverter.convertPropertyDeclaration(it)
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
}
}
if (size != firLabels.size) {
firLabels.removeLast()
if (size != context.firLabels.size) {
context.firLabels.removeLast()
//println("Unused label: ${labeledExpression.getAsString()}")
}
return firExpression ?: FirErrorExpressionImpl(session, null, "Empty label")
@@ -460,10 +461,10 @@ class ExpressionsConverter(
else -> FirErrorNamedReference(this@ExpressionsConverter.session, null, "Call has no callee")
}
firFunctionCalls += this
context.firFunctionCalls += this
this.extractArgumentsFrom(valueArguments.flatMap { convertValueArguments(it) }, stubMode)
typeArguments += firTypeArguments
firFunctionCalls.removeLast()
context.firFunctionCalls.removeLast()
}
}
@@ -885,7 +886,7 @@ class ExpressionsConverter(
return (if (isBreak) FirBreakExpressionImpl(session, null) else FirContinueExpressionImpl(session, null)).apply {
target = FirLoopTarget(labelName)
val lastLoop = firLoops.lastOrNull()
val lastLoop = context.firLoops.lastOrNull()
if (labelName == null) {
if (lastLoop != null) {
target.bind(lastLoop)
@@ -893,7 +894,7 @@ class ExpressionsConverter(
target.bind(FirErrorLoop(this@ExpressionsConverter.session, null, "Cannot bind unlabeled jump to a loop"))
}
} else {
for (firLoop in firLoops.asReversed()) {
for (firLoop in context.firLoops.asReversed()) {
if (firLoop.label?.name == labelName) {
target.bind(firLoop)
return this
@@ -39,7 +39,7 @@ 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) {
abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context = Context()) {
protected val implicitUnitType = FirImplicitUnitTypeRef(session, null)
protected val implicitAnyType = FirImplicitAnyTypeRef(session, null)
@@ -56,41 +56,26 @@ abstract class BaseFirBuilder<T>(val session: FirSession) {
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)
context.className = context.className.child(name)
val t = l()
className = className.parent()
context.className = context.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)
context.className == FqName.ROOT -> CallableId(context.packageFqName, name)
else -> CallableId(context.packageFqName, context.className, name)
}
fun callableIdForClassConstructor() =
if (className == FqName.ROOT) CallableId(packageFqName, Name.special("<anonymous-init>"))
else CallableId(packageFqName, className, className.shortName())
if (context.className == FqName.ROOT) CallableId(context.packageFqName, Name.special("<anonymous-init>"))
else CallableId(context.packageFqName, context.className, context.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)
}
@@ -111,7 +96,7 @@ abstract class BaseFirBuilder<T>(val session: FirSession) {
this
).apply {
target = FirFunctionTarget(labelName)
val lastFunction = firFunctions.lastOrNull()
val lastFunction = context.firFunctions.lastOrNull()
if (labelName == null) {
if (lastFunction != null) {
target.bind(lastFunction)
@@ -119,7 +104,7 @@ abstract class BaseFirBuilder<T>(val session: FirSession) {
target.bind(FirErrorFunction(this@BaseFirBuilder.session, psi, "Cannot bind unlabeled return to a function"))
}
} else {
for (firFunction in firFunctions.asReversed()) {
for (firFunction in context.firFunctions.asReversed()) {
when (firFunction) {
is FirAnonymousFunction -> {
if (firFunction.label?.name == labelName) {
@@ -165,10 +150,10 @@ abstract class BaseFirBuilder<T>(val session: FirSession) {
}
fun FirAbstractLoop.configure(generateBlock: () -> FirBlock): FirAbstractLoop {
label = firLabels.pop()
firLoops += this
label = context.firLabels.pop()
context.firLoops += this
block = generateBlock()
firLoops.removeLast()
context.firLoops.removeLast()
return this
}
@@ -349,7 +334,7 @@ abstract class BaseFirBuilder<T>(val session: FirSession) {
}
}
fun FirModifiableQualifiedAccess<*>.initializeLValue(
private fun FirModifiableQualifiedAccess<*>.initializeLValue(
left: T?,
convertQualified: T.() -> FirQualifiedAccess?
): FirReference {
@@ -0,0 +1,24 @@
/*
* 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 org.jetbrains.kotlin.fir.FirLabel
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirLoop
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
class Context {
lateinit var packageFqName: FqName
var className: FqName = FqName.ROOT
val currentClassId get() = ClassId(packageFqName, className, false)
val firFunctions = mutableListOf<FirFunction>()
val firFunctionCalls = mutableListOf<FirFunctionCall>()
val firLabels = mutableListOf<FirLabel>()
val firLoops = mutableListOf<FirLoop>()
}
@@ -207,14 +207,14 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
returnTypeReference.toFirOrUnitType()
}
)
firFunctions += firAccessor
this@RawFirBuilder.context.firFunctions += firAccessor
extractAnnotationsTo(firAccessor)
extractValueParametersTo(firAccessor, propertyTypeRef)
if (!isGetter && firAccessor.valueParameters.isEmpty()) {
firAccessor.valueParameters += FirDefaultSetterValueParameter(session, this, propertyTypeRef)
}
firAccessor.body = this.buildFirBody()
firFunctions.removeLast()
this@RawFirBuilder.context.firFunctions.removeLast()
return firAccessor
}
@@ -394,8 +394,8 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
}
override fun visitKtFile(file: KtFile, data: Unit): FirElement {
packageFqName = file.packageFqName
val firFile = FirFileImpl(session, file, file.name, packageFqName)
context.packageFqName = file.packageFqName
val firFile = FirFileImpl(session, file, file.name, context.packageFqName)
for (annotationEntry in file.annotationEntries) {
firFile.annotations += annotationEntry.convert<FirAnnotationCall>()
}
@@ -418,7 +418,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
val firEnumEntry = FirEnumEntryImpl(
session,
enumEntry,
FirClassSymbol(currentClassId),
FirClassSymbol(context.currentClassId),
enumEntry.nameAsSafeName
)
enumEntry.extractAnnotationsTo(firEnumEntry)
@@ -451,7 +451,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
val firClass = FirClassImpl(
session,
classOrObject,
FirClassSymbol(currentClassId),
FirClassSymbol(context.currentClassId),
classOrObject.nameAsSafeName,
if (classOrObject.isLocal) Visibilities.LOCAL else classOrObject.visibility,
classOrObject.modality,
@@ -489,8 +489,10 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
val zippedParameters = classOrObject.primaryConstructorParameters.zip(
firClass.declarations.filterIsInstance<FirProperty>()
)
zippedParameters.generateComponentFunctions(session, firClass, packageFqName, className)
zippedParameters.generateCopyFunction(session, classOrObject, firClass, packageFqName, className, firPrimaryConstructor)
zippedParameters.generateComponentFunctions(session, firClass, context.packageFqName, context.className)
zippedParameters.generateCopyFunction(
session, classOrObject, firClass, context.packageFqName, context.className, firPrimaryConstructor
)
// TODO: equals, hashCode, toString
}
@@ -519,7 +521,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
val firTypeAlias = FirTypeAliasImpl(
session,
typeAlias,
FirTypeAliasSymbol(currentClassId),
FirTypeAliasSymbol(context.currentClassId),
typeAlias.nameAsSafeName,
typeAlias.visibility,
typeAlias.hasExpectModifier(),
@@ -564,7 +566,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
returnType
)
}
firFunctions += firFunction
context.firFunctions += firFunction
function.extractAnnotationsTo(firFunction)
if (firFunction is FirMemberFunctionImpl) {
function.extractTypeParametersTo(firFunction)
@@ -573,7 +575,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
firFunction.valueParameters += valueParameter.convert<FirValueParameter>()
}
firFunction.body = function.buildFirBody()
firFunctions.removeLast()
context.firFunctions.removeLast()
return firFunction
}
@@ -582,7 +584,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
val returnType = FirImplicitTypeRefImpl(literal)
val receiverType = FirImplicitTypeRefImpl(literal)
return FirAnonymousFunctionImpl(session, literal, returnType, receiverType).apply {
firFunctions += this
context.firFunctions += this
var destructuringBlock: FirExpression? = null
for (valueParameter in literal.valueParameters) {
val multiDeclaration = valueParameter.destructuringDeclaration
@@ -604,7 +606,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
valueParameter.toFirValueParameter(FirImplicitTypeRefImpl(psi))
}
}
label = firLabels.pop() ?: firFunctionCalls.lastOrNull()?.calleeReference?.name?.let {
label = context.firLabels.pop() ?: context.firFunctionCalls.lastOrNull()?.calleeReference?.name?.let {
FirLabelImpl(expression, it.asString())
}
val bodyExpression = literal.bodyExpression.toFirExpression("Lambda has no body")
@@ -622,7 +624,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
FirSingleExpressionBlock(bodyExpression.toReturn())
}
firFunctions.removeLast()
context.firFunctions.removeLast()
}
}
@@ -642,12 +644,12 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
delegatedSelfTypeRef,
getDelegationCall().convert(delegatedSuperTypeRef, delegatedSelfTypeRef, hasPrimaryConstructor)
)
firFunctions += firConstructor
this@RawFirBuilder.context.firFunctions += firConstructor
extractAnnotationsTo(firConstructor)
firConstructor.typeParameters += typeParametersFromSelfType(delegatedSelfTypeRef)
extractValueParametersTo(firConstructor)
firConstructor.body = buildFirBody()
firFunctions.removeLast()
this@RawFirBuilder.context.firFunctions.removeLast()
return firConstructor
}
@@ -1036,7 +1038,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
private fun FirLoopJump.bindLabel(expression: KtExpressionWithLabel): FirLoopJump {
val labelName = expression.getLabelName()
target = FirLoopTarget(labelName)
val lastLoop = firLoops.lastOrNull()
val lastLoop = context.firLoops.lastOrNull()
if (labelName == null) {
if (lastLoop != null) {
target.bind(lastLoop)
@@ -1044,7 +1046,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
target.bind(FirErrorLoop(psi, "Cannot bind unlabeled jump to a loop"))
}
} else {
for (firLoop in firLoops.asReversed()) {
for (firLoop in context.firLoops.asReversed()) {
if (firLoop.label?.name == labelName) {
target.bind(firLoop)
return this
@@ -1178,12 +1180,12 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
}
}
this.calleeReference = calleeReference
firFunctionCalls += this
context.firFunctionCalls += this
expression.extractArgumentsTo(this)
for (typeArgument in expression.typeArguments) {
typeArguments += typeArgument.convert<FirTypeProjection>()
}
firFunctionCalls.removeLast()
context.firFunctionCalls.removeLast()
}
}
@@ -1229,13 +1231,13 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
override fun visitLabeledExpression(expression: KtLabeledExpression, data: Unit): FirElement {
val labelName = expression.getLabelName()
val size = firLabels.size
val size = context.firLabels.size
if (labelName != null) {
firLabels += FirLabelImpl(expression, labelName)
context.firLabels += FirLabelImpl(expression, labelName)
}
val result = expression.baseExpression?.accept(this, data) ?: FirErrorExpressionImpl(expression, "Empty label")
if (size != firLabels.size) {
firLabels.removeLast()
if (size != context.firLabels.size) {
context.firLabels.removeLast()
println("Unused label: ${expression.text}")
}
return result