[FIR] Add replaceCalleeReference to all FirResolvable

Also improve tree generator: now it generates abstract overrides
  for `replace` functions and correctly generates replace for fields
  with overriden type
This commit is contained in:
Dmitriy Novozhilov
2020-04-15 13:28:36 +03:00
parent fa1e5f9593
commit 276754260a
86 changed files with 419 additions and 29 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.tree.generator
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.annotations
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.arguments
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.body
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
@@ -62,7 +63,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
}
resolvable.configure {
+field("calleeReference", reference).withTransform()
+calleeReference.withTransform()
}
diagnosticHolder.configure {
@@ -440,7 +441,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
}
callableReferenceAccess.configure {
+field("calleeReference", namedReference)
+field("calleeReference", namedReference, withReplace = true).withTransform()
}
getClassCall.configure {
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.tree.generator.model
import org.jetbrains.kotlin.fir.tree.generator.printer.BASE_PACKAGE
import org.jetbrains.kotlin.fir.tree.generator.printer.typeWithArguments
import org.jetbrains.kotlin.fir.tree.generator.util.set
interface KindOwner : Importable {
var kind: Implementation.Kind?
@@ -31,6 +32,7 @@ interface AbstractElement : FieldContainer, KindOwner {
val allFirFields: List<Field>
val defaultImplementation: Implementation?
val customImplementations: List<Implementation>
val overridenFields: Map<Field, Map<Importable, Boolean>>
override val allParents: List<KindOwner> get() = parents
}
@@ -60,10 +62,10 @@ class Element(val name: String, kind: Kind) : AbstractElement {
override var doesNotNeedImplementation: Boolean = false
override val needTransformOtherChildren: Boolean get() = _needTransformOtherChildren || parents.any { it.needTransformOtherChildren }
override val overridenFields: MutableMap<Field, MutableMap<Importable, Boolean>> = mutableMapOf()
override val allImplementations: List<Implementation> by lazy {
if (doesNotNeedImplementation) {
emptyList<Implementation>()
emptyList()
} else {
val implementations = customImplementations.toMutableList()
defaultImplementation?.let { implementations += it }
@@ -74,13 +76,23 @@ class Element(val name: String, kind: Kind) : AbstractElement {
override val allFields: List<Field> by lazy {
val result = LinkedHashSet<Field>()
result.addAll(fields.toList().asReversed())
for (field in parentFields.asReversed()) {
val overrides = !result.add(field)
result.forEach { overridenFields[it, it] = false }
for (parentField in parentFields.asReversed()) {
val overrides = !result.add(parentField)
if (overrides) {
val existingField = result.first { it == field }
val existingField = result.first { it == parentField }
existingField.fromParent = true
existingField.needsSeparateTransform = existingField.needsSeparateTransform || field.needsSeparateTransform
existingField.needTransformInOtherChildren = existingField.needTransformInOtherChildren || field.needTransformInOtherChildren
existingField.needsSeparateTransform = existingField.needsSeparateTransform || parentField.needsSeparateTransform
existingField.needTransformInOtherChildren = existingField.needTransformInOtherChildren || parentField.needTransformInOtherChildren
existingField.withReplace = parentField.withReplace || existingField.withReplace
if (parentField.type != existingField.type && parentField.withReplace) {
existingField.overridenTypes += parentField
overridenFields[existingField, parentField] = false
} else {
overridenFields[existingField, parentField] = true
}
} else {
overridenFields[parentField, parentField] = true
}
}
result.toList().asReversed()
@@ -160,4 +172,4 @@ class TypeArgumentWithMultipleUpperBounds(name: String, override val upperBounds
override fun toString(): String {
return name
}
}
}
@@ -11,7 +11,7 @@ sealed class Field : Importable {
abstract val name: String
open val arguments = mutableListOf<Importable>()
abstract val nullable: Boolean
abstract val withReplace: Boolean
open var withReplace: Boolean = false
abstract val isFirType: Boolean
var fromParent: Boolean = false
@@ -22,10 +22,11 @@ sealed class Field : Importable {
abstract var isMutable: Boolean
open var isMutableInInterface: Boolean = false
open val withGetter: Boolean get() = false
open val isLateinit: Boolean get() = false
open val customSetter: String? get() = null
open val fromDelegate: Boolean get() = false
open val overridenTypes: MutableSet<Importable> = mutableSetOf()
fun copy(): Field = internalCopy().also {
updateFieldsInCopy(it)
}
@@ -37,6 +38,7 @@ sealed class Field : Importable {
copy.needsSeparateTransform = needsSeparateTransform
copy.needTransformInOtherChildren = needTransformInOtherChildren
copy.isMutable = isMutable
copy.overridenTypes += overridenTypes
}
copy.fromParent = fromParent
}
@@ -66,7 +68,9 @@ class FieldWithDefault(val origin: Field) : Field() {
override val name: String get() = origin.name
override val type: String get() = origin.type
override val nullable: Boolean get() = origin.nullable
override val withReplace: Boolean get() = origin.withReplace
override var withReplace: Boolean
get() = origin.withReplace
set(_) {}
override val packageName: String? get() = origin.packageName
override val isFirType: Boolean get() = origin.isFirType
override var needsSeparateTransform: Boolean
@@ -91,6 +95,8 @@ class FieldWithDefault(val origin: Field) : Field() {
override var customSetter: String? = null
override var fromDelegate: Boolean = false
var needAcceptAndTransform: Boolean = true
override val overridenTypes: MutableSet<Importable>
get() = origin.overridenTypes
override fun internalCopy(): Field {
return FieldWithDefault(origin).also {
@@ -109,7 +115,7 @@ class SimpleField(
override val packageName: String?,
val customType: Importable? = null,
override val nullable: Boolean,
override val withReplace: Boolean
override var withReplace: Boolean
) : Field() {
override val isFirType: Boolean = false
override val fullQualifiedName: String?
@@ -144,7 +150,7 @@ class FirField(
override val name: String,
val element: AbstractElement,
override val nullable: Boolean,
override val withReplace: Boolean
override var withReplace: Boolean
) : Field() {
init {
if (element is ElementWithArguments) {
@@ -173,7 +179,7 @@ class FirField(
class FieldList(
override val name: String,
val baseType: Importable,
override val withReplace: Boolean
override var withReplace: Boolean
) : Field() {
override var defaultValueInImplementation: String? = null
override val packageName: String? get() = baseType.packageName
@@ -6,9 +6,9 @@
package org.jetbrains.kotlin.fir.tree.generator.printer
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.Element
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation
import org.jetbrains.kotlin.fir.tree.generator.model.*
import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType
import org.jetbrains.kotlin.fir.tree.generator.util.get
import java.io.File
@@ -84,11 +84,18 @@ fun SmartPrinter.printElement(element: Element) {
override()
println("fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visit$name(this, data)")
fields.filter { it.withReplace }.forEach {
fun Field.replaceDeclaration(override: Boolean, overridenType: Importable? = null) {
println()
abstract()
if (it.fromParent) print("override ")
println(it.replaceFunctionDeclaration())
if (override) print("override ")
println(replaceFunctionDeclaration(overridenType))
}
allFields.filter { it.withReplace }.forEach {
it.replaceDeclaration(overridenFields[it, it])
for (overridenType in it.overridenTypes) {
it.replaceDeclaration(true, overridenType)
}
}
for (field in allFields) {
@@ -302,22 +302,30 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
}
}
for (field in allFields.filter { it.withReplace }) {
fun generateReplace(field: Field, overridenType: Importable? = null, body: () -> Unit) {
println()
abstract()
print("override ${field.replaceFunctionDeclaration()}")
print("override ${field.replaceFunctionDeclaration(overridenType)}")
if (isInterface || isAbstract) {
println()
continue
return
}
print(" {")
if (!field.isMutable) {
println("}")
continue
return
}
println()
withIndent {
val newValue = "new${field.name.capitalize()}"
body()
}
println("}")
}
for (field in allFields.filter { it.withReplace }) {
val capitalizedFieldName = field.name.capitalize()
val newValue = "new$capitalizedFieldName"
generateReplace(field) {
when {
field.withGetter -> {}
@@ -331,7 +339,13 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
}
}
}
println("}")
for (overridenType in field.overridenTypes) {
generateReplace(field, overridenType) {
println("require($newValue is ${field.typeWithArguments})")
println("replace$capitalizedFieldName($newValue)")
}
}
}
}
println("}")
@@ -62,6 +62,7 @@ fun Element.collectImports(): List<String> {
private fun Element.collectImportsInternal(base: List<String>, kind: ImportKind): List<String> {
val fqns = base + allFields.mapNotNull { it.fullQualifiedName } +
allFields.flatMap { it.overridenTypes.mapNotNull { it.fullQualifiedName } } +
allFields.flatMap { it.arguments.mapNotNull { it.fullQualifiedName } } +
typeArguments.flatMap { it.upperBounds.mapNotNull { it.fullQualifiedName } }
return fqns.filterRedundantImports(packageName, kind)
@@ -93,9 +94,10 @@ fun transformFunctionDeclaration(transformName: String, returnType: String): Str
return "fun <D> transform$transformName(transformer: FirTransformer<D>, data: D): $returnType"
}
fun Field.replaceFunctionDeclaration(): String {
fun Field.replaceFunctionDeclaration(overridenType: Importable? = null): String {
val capName = name.capitalize()
return "fun replace$capName(new$capName: $typeWithArguments)"
val type = overridenType?.typeWithArguments ?: typeWithArguments
return "fun replace$capName(new$capName: $type)"
}
val Field.mutableType: String
@@ -11,3 +11,13 @@ fun Element.traverseParents(block: (Element) -> Unit) {
block(this)
parents.forEach { it.traverseParents(block) }
}
operator fun <K, V, U> MutableMap<K, MutableMap<V, U>>.set(k1: K, k2: V, value: U) {
this.putIfAbsent(k1, mutableMapOf())
val map = getValue(k1)
map[k2] = value
}
operator fun <K, V, U> Map<K, Map<V, U>>.get(k1: K, k2: V): U {
return getValue(k1).getValue(k2)
}