FIR: Simplify FirQualifiedAccess hiearchy

Mostly, it's getting rid of FirQualifiedAccessWithoutCallee and FirModifiableQualifiedAccess
The latter was only used during FIR building to set explicit receiver
that might be done by replace call on explicit receiver

The problem with replaceExplicitReceiver is that for FirComponentCall
explicitReceiver should be not null, so it's needed to perform those tricks
at the generatot
This commit is contained in:
Denis Zharkov
2020-08-21 14:29:14 +03:00
parent e6837a5b8c
commit cb6fbc329a
39 changed files with 159 additions and 222 deletions
@@ -24,7 +24,7 @@ object FieldSets {
val calleeReference = field("calleeReference", reference, withReplace = true)
val receivers = fieldSet(
field("explicitReceiver", expression, nullable = true).withTransform(),
field("explicitReceiver", expression, nullable = true, withReplace = true).withTransform(),
field("dispatchReceiver", expression).withTransform(),
field("extensionReceiver", expression).withTransform()
)
@@ -83,4 +83,4 @@ object FieldSets {
val modality = field(modalityType, nullable = true)
val scopeProvider = field("scopeProvider", firScopeProviderType)
}
}
@@ -90,8 +90,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val equalityOperatorCall = element("EqualityOperatorCall", Expression, expression, call)
val whenExpression = element("WhenExpression", Expression, expression, resolvable)
val whenBranch = element("WhenBranch", Expression)
val qualifiedAccessWithoutCallee = element("QualifiedAccessWithoutCallee", Expression, statement)
val qualifiedAccess = element("QualifiedAccess", Expression, qualifiedAccessWithoutCallee, resolvable)
val qualifiedAccess = element("QualifiedAccess", Expression, resolvable, statement)
val checkNotNullCall = element("CheckNotNullCall", Expression, expression, call, resolvable)
val elvisExpression = element("ElvisExpression", Expression, expression, resolvable)
@@ -74,11 +74,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(arrayOfCall)
val modifiableQualifiedAccess = impl(qualifiedAccessWithoutCallee, "FirModifiableQualifiedAccess") {}
impl(callableReferenceAccess) {
parents += modifiableQualifiedAccess
}
impl(callableReferenceAccess)
impl(componentCall) {
default("calleeReference", "FirSimpleNamedReference(source, Name.identifier(\"component\$componentIndex\"), null)")
@@ -128,14 +124,10 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
}
impl(functionCall) {
parents += modifiableQualifiedAccess
kind = OpenClass
}
impl(qualifiedAccessExpression) {
parents += modifiableQualifiedAccess
}
impl(qualifiedAccessExpression)
noImpl(expressionWithSmartcast)
@@ -269,7 +261,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
}
impl(thisReceiverExpression) {
parents += modifiableQualifiedAccess
defaultNoReceivers()
}
@@ -280,8 +271,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
}
impl(variableAssignment) {
parents += modifiableQualifiedAccess
default("lValue") {
value = "calleeReference"
customSetter = "calleeReference = value"
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.fir.tree.generator.FieldSets.calleeReference
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.classKind
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.controlFlowGraphReferenceField
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.declarations
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.effectiveVisibility
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.initializer
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.modality
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.name
@@ -192,7 +191,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("rhs", expression).withTransform()
}
qualifiedAccessWithoutCallee.configure {
qualifiedAccess.configure {
+typeArguments.withTransform()
+receivers
}
@@ -354,6 +353,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
delegatedConstructorCall.configure {
+field("constructedTypeRef", typeRef, withReplace = true)
+field("dispatchReceiver", expression).withTransform()
+field("calleeReference", reference, withReplace = true)
generateBooleanFields("this", "super")
}
@@ -33,6 +33,7 @@ interface AbstractElement : FieldContainer, KindOwner {
val defaultImplementation: Implementation?
val customImplementations: List<Implementation>
val overridenFields: Map<Field, Map<Importable, Boolean>>
val useNullableForReplace: Set<Field>
override val allParents: List<KindOwner> get() = parents
}
@@ -63,6 +64,7 @@ class Element(val name: String, kind: Kind) : AbstractElement {
override val needTransformOtherChildren: Boolean get() = _needTransformOtherChildren || parents.any { it.needTransformOtherChildren }
override val overridenFields: MutableMap<Field, MutableMap<Importable, Boolean>> = mutableMapOf()
override val useNullableForReplace: MutableSet<Field> = mutableSetOf()
override val allImplementations: List<Implementation> by lazy {
if (doesNotNeedImplementation) {
emptyList()
@@ -90,6 +92,9 @@ class Element(val name: String, kind: Kind) : AbstractElement {
overridenFields[existingField, parentField] = false
} else {
overridenFields[existingField, parentField] = true
if (parentField.nullable != existingField.nullable) {
existingField.useNullableForReplace = true
}
}
} else {
overridenFields[parentField, parentField] = true
@@ -174,4 +179,4 @@ class TypeArgumentWithMultipleUpperBounds(name: String, override val upperBounds
}
}
data class ArbitraryImportable(override val packageName: String, override val type: String) : Importable
data class ArbitraryImportable(override val packageName: String, override val type: String) : Importable
@@ -26,6 +26,7 @@ sealed class Field : Importable {
open val fromDelegate: Boolean get() = false
open val overridenTypes: MutableSet<Importable> = mutableSetOf()
open var useNullableForReplace: Boolean = false
fun copy(): Field = internalCopy().also {
updateFieldsInCopy(it)
@@ -39,6 +40,7 @@ sealed class Field : Importable {
copy.needTransformInOtherChildren = needTransformInOtherChildren
copy.isMutable = isMutable
copy.overridenTypes += overridenTypes
copy.useNullableForReplace = useNullableForReplace
}
copy.fromParent = fromParent
}
@@ -98,6 +100,10 @@ class FieldWithDefault(val origin: Field) : Field() {
override val overridenTypes: MutableSet<Importable>
get() = origin.overridenTypes
override var useNullableForReplace: Boolean
get() = origin.useNullableForReplace
set(_) {}
override fun internalCopy(): Field {
return FieldWithDefault(origin).also {
it.defaultValueInImplementation = defaultValueInImplementation
@@ -84,15 +84,15 @@ fun SmartPrinter.printElement(element: Element) {
override()
println("fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visit$name(this, data)")
fun Field.replaceDeclaration(override: Boolean, overridenType: Importable? = null) {
fun Field.replaceDeclaration(override: Boolean, overridenType: Importable? = null, forceNullable: Boolean = false) {
println()
abstract()
if (override) print("override ")
println(replaceFunctionDeclaration(overridenType))
println(replaceFunctionDeclaration(overridenType, forceNullable))
}
allFields.filter { it.withReplace }.forEach {
it.replaceDeclaration(overridenFields[it, it])
it.replaceDeclaration(overridenFields[it, it], forceNullable = it.useNullableForReplace)
for (overridenType in it.overridenTypes) {
it.replaceDeclaration(true, overridenType)
}
@@ -303,10 +303,15 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
}
}
fun generateReplace(field: Field, overridenType: Importable? = null, body: () -> Unit) {
fun generateReplace(
field: Field,
overridenType: Importable? = null,
forceNullable: Boolean = false,
body: () -> Unit,
) {
println()
abstract()
print("override ${field.replaceFunctionDeclaration(overridenType)}")
print("override ${field.replaceFunctionDeclaration(overridenType, forceNullable)}")
if (isInterface || isAbstract) {
println()
return
@@ -326,7 +331,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
for (field in allFields.filter { it.withReplace }) {
val capitalizedFieldName = field.name.capitalize()
val newValue = "new$capitalizedFieldName"
generateReplace(field) {
generateReplace(field, forceNullable = field.useNullableForReplace) {
when {
field.withGetter -> {}
@@ -336,6 +341,9 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
}
else -> {
if (field.useNullableForReplace) {
println("require($newValue != null)")
}
println("${field.name} = $newValue")
}
}
@@ -96,10 +96,13 @@ fun transformFunctionDeclaration(transformName: String, returnType: String): Str
return "fun <D> transform$transformName(transformer: FirTransformer<D>, data: D): $returnType"
}
fun Field.replaceFunctionDeclaration(overridenType: Importable? = null): String {
fun Field.replaceFunctionDeclaration(overridenType: Importable? = null, forceNullable: Boolean = false): String {
val capName = name.capitalize()
val type = overridenType?.typeWithArguments ?: typeWithArguments
return "fun replace$capName(new$capName: $type)"
val typeWithNullable = if (forceNullable && !type.endsWith("?")) "$type?" else type
return "fun replace$capName(new$capName: $typeWithNullable)"
}
val Field.mutableType: String