[FIR generator] Extract the Implementation class to a common module

We want to use it to generate implementation classes for other
trees, just like we already do with elements (see `AbstractElement`).
This commit is contained in:
Sergej Jaskiewicz
2023-11-17 20:37:00 +01:00
committed by Space Team
parent 85cff98a38
commit 91b5a71f1a
27 changed files with 749 additions and 479 deletions
@@ -10,13 +10,8 @@ import org.jetbrains.kotlin.generators.tree.ImplementationKind.Object
import org.jetbrains.kotlin.generators.tree.ImplementationKind.OpenClass
object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() {
fun configureImplementations() {
configure()
generateDefaultImplementations(FirTreeBuilder)
configureAllImplementations()
}
private fun configure() = with(FirTreeBuilder) {
override fun configure() = with(FirTreeBuilder) {
impl(constructor) {
defaultFalse("isPrimary", withGetter = true)
}
@@ -87,7 +82,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
value = "annotationTypeRef.coneTypeOrNull"
withGetter = true
}
useTypes(coneTypeOrNullImport)
additionalImports(coneTypeOrNullImport)
}
impl(annotation) {
@@ -117,7 +112,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(componentCall) {
default("calleeReference", "FirSimpleNamedReference(source, Name.identifier(\"component\$componentIndex\"))")
useTypes(simpleNamedReferenceType, nameType)
additionalImports(simpleNamedReferenceType, nameType)
optInToInternals()
}
@@ -130,7 +125,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
value = "!isThis"
withGetter = true
}
useTypes(explicitThisReferenceType, explicitSuperReferenceType)
additionalImports(explicitThisReferenceType, explicitSuperReferenceType)
}
impl(multiDelegatedConstructorCall) {
@@ -204,7 +199,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(expression, "FirElseIfTrueCondition") {
defaultBuiltInType("Boolean")
useTypes(implicitBooleanTypeRefType)
additionalImports(implicitBooleanTypeRefType)
publicImplementation()
}
@@ -241,7 +236,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(errorLoop) {
default("block", "FirEmptyExpressionBlock()")
default("condition", "FirErrorExpressionImpl(source, MutableOrEmptyList.empty(), ConeStubDiagnostic(diagnostic), null, null)")
useTypes(emptyExpressionBlock, coneStubDiagnosticType)
additionalImports(emptyExpressionBlock, coneStubDiagnosticType)
}
impl(expression, "FirExpressionStub") {
@@ -291,7 +286,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
withGetter = true
}
useTypes(backingFieldSymbolType, delegateFieldSymbolType)
additionalImports(backingFieldSymbolType, delegateFieldSymbolType)
}
impl(errorProperty) {
@@ -306,7 +301,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
withGetter = true
)
default("returnTypeRef", "FirErrorTypeRefImpl(null, MutableOrEmptyList.empty(), null, null, diagnostic)")
useTypes(errorTypeRefImplType)
additionalImports(errorTypeRefImplType)
}
impl(field) {
@@ -357,7 +352,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(comparisonExpression) {
default("coneTypeOrNull", "StandardClassIds.Boolean.constructClassLikeType()")
useTypes(standardClassIdsType, constructClassLikeTypeImport)
additionalImports(standardClassIdsType, constructClassLikeTypeImport)
}
impl(typeOperatorCall) {
@@ -370,7 +365,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(equalityOperatorCall) {
default("coneTypeOrNull", "StandardClassIds.Boolean.constructClassLikeType()")
useTypes(standardClassIdsType, constructClassLikeTypeImport)
additionalImports(standardClassIdsType, constructClassLikeTypeImport)
}
impl(resolvedQualifier) {
@@ -382,17 +377,17 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(returnExpression) {
defaultBuiltInType("Nothing")
useTypes(implicitNothingTypeRefType)
additionalImports(implicitNothingTypeRefType)
}
impl(stringConcatenationCall) {
defaultBuiltInType("String")
useTypes(implicitStringTypeRefType)
additionalImports(implicitStringTypeRefType)
}
impl(throwExpression) {
defaultBuiltInType("Nothing")
useTypes(implicitNothingTypeRefType)
additionalImports(implicitNothingTypeRefType)
}
impl(thisReceiverExpression) {
@@ -401,7 +396,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(expression, "FirUnitExpression") {
defaultBuiltInType("Unit")
useTypes(implicitUnitTypeRefType)
additionalImports(implicitUnitTypeRefType)
publicImplementation()
}
@@ -419,7 +414,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
value = "!isGetter"
withGetter = true
}
useTypes(modalityType)
additionalImports(modalityType)
kind = OpenClass
}
@@ -432,12 +427,12 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
value = "whenRef.value.subject?.coneTypeOrNull ?: StandardClassIds.Unit.constructClassLikeType()"
withGetter = true
}
useTypes(whenExpression, standardClassIdsType, constructClassLikeTypeImport)
useTypes(standardClassIdsType, constructClassLikeTypeImport)
additionalImports(whenExpression, standardClassIdsType, constructClassLikeTypeImport)
additionalImports(standardClassIdsType, constructClassLikeTypeImport)
}
impl(desugaredAssignmentValueReferenceExpression) {
useTypes(expression)
additionalImports(expression)
}
impl(wrappedDelegateExpression) {
@@ -450,7 +445,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
noSource()
default("coneTypeOrNull") {
value = "enumClassId.toLookupTag().constructClassType(emptyArray(), false)"
useTypes(toLookupTagImport, constructClassTypeImport)
additionalImports(toLookupTagImport, constructClassTypeImport)
}
}
@@ -462,7 +457,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
default("source") {
value = "originalExpression.source?.fakeElement(KtFakeSourceElementKind.SmartCastExpression)"
}
useTypes(fakeElementImport, fakeSourceElementKindImport)
additionalImports(fakeElementImport, fakeSourceElementKindImport)
}
impl(resolvedNamedReference)
@@ -528,18 +523,18 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(errorExpression) {
default("coneTypeOrNull", "ConeErrorType(ConeStubDiagnostic(diagnostic))")
useTypes(coneErrorTypeType, coneStubDiagnosticType)
additionalImports(coneErrorTypeType, coneStubDiagnosticType)
}
impl(qualifiedErrorAccessExpression) {
default("coneTypeOrNull", "ConeErrorType(ConeStubDiagnostic(diagnostic))")
useTypes(coneErrorTypeType, coneStubDiagnosticType)
additionalImports(coneErrorTypeType, coneStubDiagnosticType)
}
impl(errorFunction) {
defaultNull("receiverParameter", "body", withGetter = true)
default("returnTypeRef", "FirErrorTypeRefImpl(null, MutableOrEmptyList.empty(), null, null, diagnostic)")
useTypes(errorTypeRefImplType)
additionalImports(errorTypeRefImplType)
}
impl(functionTypeRef)
@@ -561,12 +556,12 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(breakExpression) {
defaultBuiltInType("Nothing")
useTypes(implicitNothingTypeRefType)
additionalImports(implicitNothingTypeRefType)
}
impl(continueExpression) {
defaultBuiltInType("Nothing")
useTypes(implicitNothingTypeRefType)
additionalImports(implicitNothingTypeRefType)
}
impl(valueParameter) {
@@ -582,11 +577,11 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(simpleFunction)
impl(safeCallExpression) {
useTypes(checkedSafeCallSubject)
additionalImports(checkedSafeCallSubject)
}
impl(checkedSafeCallSubject) {
useTypes(expression)
additionalImports(expression)
}
impl(resolvedQualifier) {
@@ -603,7 +598,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
// If this `FirResolvedQualifier` is a receiver expression of some other qualified access, the value is updated in
// `FirCallResolver` according to the resolution result.
default("resolvedToCompanionObject", "(symbol?.fir as? FirRegularClass)?.companionObjectSymbol != null")
useTypes(regularClass)
additionalImports(regularClass)
}
impl(errorResolvedQualifier) {
@@ -637,7 +632,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
implementationPredicate = { it.typeName in implementationsWithoutStatusAndTypeParameters }
) {
default(it, "FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS")
useTypes(resolvedDeclarationStatusImplType)
additionalImports(resolvedDeclarationStatusImplType)
}
configureFieldInAllImplementations(
@@ -645,11 +640,11 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
implementationPredicate = { it.typeName in implementationsWithoutStatusAndTypeParameters }
) {
defaultEmptyList(it)
useTypes(resolvedDeclarationStatusImplType)
additionalImports(resolvedDeclarationStatusImplType)
}
}
private fun configureAllImplementations() {
override fun configureAllImplementations() {
configureFieldInAllImplementations(
field = "controlFlowGraphReference",
implementationPredicate = { it.typeName != "FirAnonymousFunctionImpl" }
@@ -688,7 +683,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
fieldPredicate = { it.defaultValueInImplementation == null }
) {
default(it, "FirImplicitTypeRefImplWithoutSource")
useTypes(firImplicitTypeWithoutSourceType)
additionalImports(firImplicitTypeWithoutSourceType)
}
configureFieldInAllImplementations(
@@ -697,7 +692,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
fieldPredicate = { it.defaultValueInImplementation == null }
) {
default(it, "FirImplicitTypeRefImplWithoutSource")
useTypes(firImplicitTypeWithoutSourceType)
additionalImports(firImplicitTypeWithoutSourceType)
}
}
@@ -7,10 +7,10 @@ package org.jetbrains.kotlin.fir.tree.generator
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.printer.generateElements
import org.jetbrains.kotlin.fir.tree.generator.util.FirInterfaceAndAbstractClassConfigurator
import org.jetbrains.kotlin.generators.tree.InterfaceAndAbstractClassConfigurator
import org.jetbrains.kotlin.generators.tree.Model
import org.jetbrains.kotlin.generators.tree.detectBaseTransformerTypes
import org.jetbrains.kotlin.generators.tree.addPureAbstractElement
import org.jetbrains.kotlin.generators.tree.detectBaseTransformerTypes
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil.collectPreviouslyGeneratedFiles
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil.removeExtraFilesFromPreviousGeneration
@@ -24,8 +24,9 @@ fun main(args: Array<String>) {
NodeConfigurator.configureFields()
val model = Model(FirTreeBuilder.elements, AbstractFirTreeBuilder.baseFirElement)
detectBaseTransformerTypes(model)
ImplementationConfigurator.configureImplementations()
FirInterfaceAndAbstractClassConfigurator(FirTreeBuilder).configureInterfacesAndAbstractClasses()
ImplementationConfigurator.configureImplementations(model)
InterfaceAndAbstractClassConfigurator((model.elements + model.elements.flatMap { it.allImplementations }))
.configureInterfacesAndAbstractClasses()
addPureAbstractElement(FirTreeBuilder.elements, pureAbstractElementType)
BuilderConfigurator.configureBuilders()
val previouslyGeneratedFiles = collectPreviouslyGeneratedFiles(generationPath)
@@ -33,4 +34,3 @@ fun main(args: Array<String>) {
generatedFiles.forEach { GeneratorsFileUtil.writeFileIfContentChanged(it.file, it.newText, logNotChanged = false) }
removeExtraFilesFromPreviousGeneration(previouslyGeneratedFiles, generatedFiles.map { it.file })
}
@@ -6,223 +6,29 @@
package org.jetbrains.kotlin.fir.tree.generator.context
import org.jetbrains.kotlin.fir.tree.generator.constructClassLikeTypeImport
import org.jetbrains.kotlin.fir.tree.generator.model.*
import org.jetbrains.kotlin.fir.tree.generator.printer.call
import org.jetbrains.kotlin.fir.tree.generator.model.Element
import org.jetbrains.kotlin.fir.tree.generator.model.FieldWithDefault
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation
import org.jetbrains.kotlin.fir.tree.generator.standardClassIdsType
import org.jetbrains.kotlin.generators.tree.ImplementationKind
import org.jetbrains.kotlin.generators.tree.Importable
import org.jetbrains.kotlin.generators.tree.config.AbstractImplementationConfigurator
abstract class AbstractFirTreeImplementationConfigurator {
private val elementsWithImpl = mutableSetOf<Element>()
abstract class AbstractFirTreeImplementationConfigurator : AbstractImplementationConfigurator<Implementation, Element, FieldWithDefault>() {
fun noImpl(element: Element) {
element.doesNotNeedImplementation = true
final override fun createImplementation(element: Element, name: String?) = Implementation(element, name)
protected fun ImplementationContext.defaultNoReceivers() {
defaultNull("explicitReceiver", "dispatchReceiver", "extensionReceiver")
}
fun impl(element: Element, name: String? = null, config: ImplementationContext.() -> Unit = {}): Implementation {
val implementation = if (name == null) {
element.defaultImplementation
} else {
element.customImplementations.firstOrNull { it.name == name }
} ?: Implementation(element, name)
val context = ImplementationContext(implementation)
context.apply(config)
elementsWithImpl += element
return implementation
protected fun ImplementationContext.defaultBuiltInType(type: String) {
default("coneTypeOrNull") {
value = "StandardClassIds.$type.constructClassLikeType()"
isMutable = false
}
additionalImports(standardClassIdsType, constructClassLikeTypeImport)
}
protected fun generateDefaultImplementations(builder: AbstractFirTreeBuilder) {
collectLeafsWithoutImplementation(builder).forEach {
impl(it)
}
}
protected fun configureFieldInAllImplementations(
field: String,
implementationPredicate: ((Implementation) -> Boolean)? = null,
fieldPredicate: ((Field) -> Boolean)? = null,
init: ImplementationContext.(field: String) -> Unit
) {
for (element in elementsWithImpl) {
for (implementation in element.allImplementations) {
if (implementationPredicate != null && !implementationPredicate(implementation)) continue
if (!implementation.allFields.any { it.name == field }) continue
if (fieldPredicate != null && !fieldPredicate(implementation.getField(field))) continue
ImplementationContext(implementation).init(field)
}
}
}
private fun collectLeafsWithoutImplementation(builder: AbstractFirTreeBuilder): Set<Element> {
val elements = builder.elements.toMutableSet()
builder.elements.forEach {
elements.removeAll(it.elementParents.map { it.element }.toSet())
}
elements.removeAll(elementsWithImpl)
return elements
}
private fun Implementation.getField(name: String): FieldWithDefault {
val result = allFields.firstOrNull { it.name == name }
requireNotNull(result) {
"Field \"$name\" not found in fields of ${element}\nExisting fields:\n" +
allFields.joinToString(separator = "\n ", prefix = " ") { it.name }
}
return result
}
inner class ImplementationContext(private val implementation: Implementation) {
private fun getField(name: String): FieldWithDefault {
return implementation.getField(name)
}
fun optInToInternals() {
implementation.requiresOptIn = true
}
fun publicImplementation() {
implementation.isPublic = true
}
fun useTypes(vararg types: Importable) {
types.forEach { implementation.usedTypes += it }
}
fun isMutable(vararg fields: String) {
fields.forEach {
val field = getField(it)
field.isMutable = true
}
}
fun defaultNoReceivers() {
defaultNull("explicitReceiver", "dispatchReceiver", "extensionReceiver")
}
fun default(field: String, value: String) {
default(field) {
this.value = value
}
}
fun defaultBuiltInType(type: String) {
default("coneTypeOrNull") {
value = "StandardClassIds.$type.constructClassLikeType()"
isMutable = false
}
useTypes(standardClassIdsType, constructClassLikeTypeImport)
}
fun defaultTrue(field: String, withGetter: Boolean = false) {
default(field) {
value = "true"
this.withGetter = withGetter
}
}
fun defaultFalse(vararg fields: String, withGetter: Boolean = false) {
for (field in fields) {
default(field) {
value = "false"
this.withGetter = withGetter
}
}
}
fun defaultNull(vararg fields: String, withGetter: Boolean = false) {
for (field in fields) {
default(field) {
value = "null"
this.withGetter = withGetter
}
require(getField(field).nullable) {
"$field is not nullable field"
}
}
}
fun noSource() {
defaultNull("source", withGetter = true)
}
fun defaultEmptyList(field: String) {
require(getField(field).origin is FieldList) {
"$field is list field"
}
default(field) {
value = "emptyList()"
withGetter = true
}
}
fun default(field: String, init: DefaultValueContext.() -> Unit) {
DefaultValueContext(getField(field)).apply(init).applyConfiguration()
}
fun delegateFields(fields: List<String>, delegate: String) {
for (field in fields) {
default(field) {
this.delegate = delegate
}
}
}
var kind: ImplementationKind?
get() = implementation.kind
set(value) {
implementation.kind = value
}
inner class DefaultValueContext(private val field: FieldWithDefault) {
var value: String? = null
var delegate: String? = null
set(value) {
field = value
if (value != null) {
withGetter = true
}
}
var delegateCall: String? = null
var isMutable: Boolean? = null
var withGetter: Boolean = false
set(value) {
field = value
if (value) {
isMutable = customSetter != null
}
}
var customSetter: String? = null
set(value) {
field = value
isMutable = true
withGetter = true
}
var needAcceptAndTransform: Boolean = true
var notNull: Boolean = false
fun applyConfiguration() {
field.withGetter = withGetter
field.customSetter = customSetter
isMutable?.let { field.isMutable = it }
field.needAcceptAndTransform = needAcceptAndTransform
if (notNull) {
field.notNull = true
}
when {
value != null -> field.defaultValueInImplementation = value
delegate != null -> {
val actualDelegateField = getField(delegate!!)
val name = delegateCall ?: field.name
field.defaultValueInImplementation = "${actualDelegateField.name}${actualDelegateField.call()}$name"
}
}
}
}
protected fun ImplementationContext.noSource() {
defaultNull("source", withGetter = true)
}
}
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.ElementOrRef as GenericElementOrRef
import org.jetbrains.kotlin.generators.tree.ElementRef as GenericElementRef
class Element(name: String, override val propertyName: String, kind: Kind) : AbstractElement<Element, Field>(name) {
class Element(name: String, override val propertyName: String, kind: Kind) : AbstractElement<Element, Field, Implementation>(name) {
companion object {
private val allowedKinds = setOf(
ImplementationKind.Interface,
@@ -41,9 +41,6 @@ class Element(name: String, override val propertyName: String, kind: Kind) : Abs
override val otherParents = mutableListOf<ClassRef<*>>()
var defaultImplementation: Implementation? = null
val customImplementations = mutableListOf<Implementation>()
override val params = mutableListOf<TypeVariable>()
override var kind: ImplementationKind? = null
@@ -76,18 +73,7 @@ class Element(name: String, override val propertyName: String, kind: Kind) : Abs
override val visitorParameterName: String
get() = safeDecapitalizedName
var doesNotNeedImplementation: Boolean = false
val needTransformOtherChildren: Boolean get() = _needTransformOtherChildren || elementParents.any { it.element.needTransformOtherChildren }
val allImplementations: List<Implementation> by lazy {
if (doesNotNeedImplementation) {
emptyList()
} else {
val implementations = customImplementations.toMutableList()
defaultImplementation?.let { implementations += it }
implementations
}
}
override fun toString(): String {
return with(ImportCollector("")) { render() }
@@ -104,6 +90,6 @@ class Element(name: String, override val propertyName: String, kind: Kind) : Abs
}
}
typealias ElementRef = GenericElementRef<Element, Field>
typealias ElementRef = GenericElementRef<Element>
typealias ElementOrRef = GenericElementOrRef<Element, Field>
typealias ElementOrRef = GenericElementOrRef<Element>
@@ -31,8 +31,6 @@ sealed class Field : AbstractField<Field>() {
abstract override var isFinal: Boolean
abstract override var isLateinit: Boolean
abstract override var isParameter: Boolean
abstract override var isMutable: Boolean
@@ -69,7 +67,7 @@ sealed class Field : AbstractField<Field>() {
// ----------- Field with default -----------
class FieldWithDefault(val origin: Field) : Field() {
class FieldWithDefault(override val origin: Field) : Field(), AbstractFieldWithDefaultValue<Field> {
override val name: String get() = origin.name
override val typeRef: TypeRefWithNullability get() = origin.typeRef
override var isVolatile: Boolean = origin.isVolatile
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.fir.tree.generator.model
import org.jetbrains.kotlin.generators.tree.*
class Implementation(val element: Element, val name: String?) : FieldContainer<FieldWithDefault>, ImplementationKindOwner {
override val allParents: List<ImplementationKindOwner> get() = listOf(element)
val isDefault = name == null
override val typeName = name ?: (element.typeName + "Impl")
class Implementation(element: Element, name: String?) : AbstractImplementation<Implementation, Element, FieldWithDefault>(element, name) {
override val allFields = element.allFields.toMutableList().mapTo(mutableListOf()) {
FieldWithDefault(it)
@@ -28,49 +25,7 @@ class Implementation(val element: Element, val name: String?) : FieldContainer<F
}
}
context(ImportCollector)
override fun renderTo(appendable: Appendable) {
addImport(this)
appendable.append(this.typeName)
if (element.params.isNotEmpty()) {
element.params.joinTo(appendable, prefix = "<", postfix = ">") { it.name }
}
}
override fun substitute(map: TypeParameterSubstitutionMap) = this
override val packageName = element.packageName + ".impl"
val usedTypes = mutableListOf<Importable>()
var isPublic = false
var requiresOptIn = false
var builder: LeafBuilder? = null
init {
if (isDefault) {
element.defaultImplementation = this
} else {
element.customImplementations += this
}
}
override val hasAcceptChildrenMethod: Boolean
get() {
val isInterface = kind == ImplementationKind.Interface || kind == ImplementationKind.SealedInterface
val isAbstract = kind == ImplementationKind.AbstractClass || kind == ImplementationKind.SealedClass
return !isInterface && !isAbstract
}
override val hasTransformChildrenMethod: Boolean
get() = true
override fun get(fieldName: String): FieldWithDefault? {
return allFields.firstOrNull { it.name == fieldName }
}
val fieldsWithoutDefault by lazy { allFields.filter { it.defaultValueInImplementation == null } }
val fieldsWithDefault by lazy { allFields.filter { it.defaultValueInImplementation != null } }
}
val ImplementationKind.hasLeafBuilder: Boolean
@@ -25,10 +25,10 @@ fun Implementation.generateCode(generationPath: File): GeneratedFile =
fileSuppressions = listOf("DuplicatedCode", "unused"),
) {
addAllImports(usedTypes)
printImplementation(this@generateCode)
ImplementationPrinter(this).printImplementation(this@generateCode)
}
private class ImplementationFieldPrinter(printer: SmartPrinter) : AbstractFieldPrinter<Field>(printer) {
private class ImplementationFieldPrinter(printer: SmartPrinter) : AbstractFieldPrinter<FieldWithDefault>(printer) {
private fun Field.isMutableOrEmptyIfList(): Boolean = when (this) {
is FieldList -> isMutableOrEmptyList
@@ -36,91 +36,44 @@ private class ImplementationFieldPrinter(printer: SmartPrinter) : AbstractFieldP
else -> true
}
override fun forceMutable(field: Field): Boolean = field.isMutable && field.isMutableOrEmptyIfList()
override fun forceMutable(field: FieldWithDefault): Boolean = field.isMutable && field.isMutableOrEmptyIfList()
override fun actualTypeOfField(field: Field) = field.getMutableType()
override fun actualTypeOfField(field: FieldWithDefault) = field.getMutableType()
}
context(ImportCollector)
fun SmartPrinter.printImplementation(implementation: Implementation) {
fun Field.transform() {
when (this) {
is FieldWithDefault -> origin.transform()
private class ImplementationPrinter(
printer: SmartPrinter
) : AbstractImplementationPrinter<Implementation, Element, FieldWithDefault>(printer) {
is FirField ->
println("$name = ${name}${call()}transform(transformer, data)")
override val implementationOptInAnnotation: ClassRef<*>
get() = firImplementationDetailType
is FieldList -> {
addImport(transformInPlaceImport)
println("${name}.transformInplace(transformer, data)")
}
else -> throw IllegalStateException()
}
}
override val pureAbstractElementType: ClassRef<*>
get() = org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType
with(implementation) {
buildSet {
if (requiresOptIn) {
add(firImplementationDetailType)
}
override fun makeFieldPrinter(printer: SmartPrinter) = ImplementationFieldPrinter(printer)
for (field in fieldsWithoutDefault) {
field.optInAnnotation?.let {
add(it)
context(ImportCollector)
override fun SmartPrinter.printAdditionalMethods(implementation: Implementation) {
fun Field.transform() {
when (this) {
is FieldWithDefault -> origin.transform()
is FirField ->
println("$name = ${name}${call()}transform(transformer, data)")
is FieldList -> {
addImport(transformInPlaceImport)
println("${name}.transformInplace(transformer, data)")
}
else -> throw IllegalStateException()
}
}.ifNotEmpty {
println("@OptIn(${joinToString { "${it.render()}::class" }})")
}
if (!isPublic) {
print("internal ")
}
print("${kind!!.title} ${this.typeName}")
print(element.params.typeParameters(end = " "))
val isInterface = kind == ImplementationKind.Interface || kind == ImplementationKind.SealedInterface
val isAbstract = kind == ImplementationKind.AbstractClass || kind == ImplementationKind.SealedClass
val fieldPrinter = ImplementationFieldPrinter(this@printImplementation)
if (!isInterface && !isAbstract && fieldsWithoutDefault.isNotEmpty()) {
if (isPublic) {
print(" @${firImplementationDetailType.render()} constructor")
}
println("(")
withIndent {
fieldsWithoutDefault.forEachIndexed { _, field ->
if (field.isParameter) {
print("${field.name}: ${field.typeRef.render()}")
if (field.nullable) print("?")
println(",")
} else if (!field.isFinal) {
fieldPrinter.printField(field, override = true, inConstructor = true)
}
}
}
print(")")
}
print(" : ")
if (needPureAbstractElement) {
print("${pureAbstractElementType.render()}(), ")
}
print(allParents.joinToString { "${it.render()}${it.kind.braces()}" })
printBlock {
if (isInterface || isAbstract) {
allFields.forEach {
fieldPrinter.printField(it, override = true, modality = Modality.ABSTRACT.takeIf { isAbstract })
}
} else {
fieldsWithDefault.forEach {
fieldPrinter.printField(it, override = true)
}
}
with(implementation) {
val isInterface = kind == ImplementationKind.Interface || kind == ImplementationKind.SealedInterface
val isAbstract = kind == ImplementationKind.AbstractClass || kind == ImplementationKind.SealedClass
val bindingCalls = element.allFields.filter {
it.withBindThis && it.hasSymbolType && it !is FieldList && it.name != "companionObjectSymbol"
}.takeIf {
@@ -199,7 +152,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
}
is FieldList -> {
println("${field.name}.forEach { it.accept(visitor, data) }")
println(field.name, field.call(), "forEach { it.accept(visitor, data) }")
}
else -> throw IllegalStateException()
@@ -88,6 +88,4 @@ fun Field.getMutableType(forBuilder: Boolean = false): TypeRefWithNullability =
else -> typeRef
}
fun Field.call(): String = if (nullable) "?." else "."
val Element.safeDecapitalizedName: String get() = if (name == "Class") "klass" else name.replaceFirstChar(Char::lowercaseChar)
@@ -1,19 +0,0 @@
/*
* 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.tree.generator.util
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation
import org.jetbrains.kotlin.generators.tree.ImplementationKindOwner
import org.jetbrains.kotlin.generators.tree.InterfaceAndAbstractClassConfigurator
internal class FirInterfaceAndAbstractClassConfigurator(builder: AbstractFirTreeBuilder) : InterfaceAndAbstractClassConfigurator(
elements = (builder.elements + builder.elements.flatMap { it.allImplementations })
) {
override fun shouldBeFinalClass(element: ImplementationKindOwner, allParents: Set<ImplementationKindOwner>): Boolean =
element is Implementation && element !in allParents
}
@@ -18,7 +18,7 @@ class Element(
name: String,
override val propertyName: String,
category: Category,
) : AbstractElement<Element, Field>(name) {
) : AbstractElement<Element, Field, Nothing>(name) {
enum class Category(private val packageDir: String, val defaultVisitorParam: String) {
Expression("expressions", "expression"),
@@ -136,8 +136,8 @@ class Element(
}
}
typealias ElementRef = GenericElementRef<Element, Field>
typealias ElementOrRef = GenericElementOrRef<Element, Field>
typealias ElementRef = GenericElementRef<Element>
typealias ElementOrRef = GenericElementOrRef<Element>
sealed class Field(
override val name: String,
@@ -179,9 +179,6 @@ sealed class Field(
override val isFinal: Boolean
get() = defaultValueInImplementation != null
override val isLateinit: Boolean
get() = false
override val isParameter: Boolean
get() = false
@@ -75,14 +75,11 @@ private class ElementPrinter(printer: SmartPrinter) : AbstractElementPrinter<Ele
if (!element.isRootElement) {
printBlock {
for (child in element.walkableChildren) {
print(child.name)
if (child.nullable) {
print("?")
}
print(child.name, child.call())
when (child) {
is SingleField -> println(".accept(visitor, data)")
is SingleField -> println("accept(visitor, data)")
is ListField -> {
print(".forEach { it")
print("forEach { it")
if (child.baseType.nullable) {
print("?")
}
@@ -109,12 +106,9 @@ private class ElementPrinter(printer: SmartPrinter) : AbstractElementPrinter<Ele
print(child.name)
when (child) {
is SingleField -> {
print(" = ", child.name)
if (child.nullable) {
print("?")
}
print(".transform(transformer, data)")
val elementRef = child.typeRef as GenericElementRef<*, *>
print(" = ", child.name, child.call())
print("transform(transformer, data)")
val elementRef = child.typeRef as GenericElementRef<*>
if (!elementRef.element.hasTransformMethod) {
print(" as ", elementRef.render())
}
@@ -122,15 +116,13 @@ private class ElementPrinter(printer: SmartPrinter) : AbstractElementPrinter<Ele
}
is ListField -> {
if (child.isMutable) {
print(" = ", child.name)
if (child.nullable) {
print("?")
}
print(" = ", child.name, child.call())
addImport(transformIfNeeded)
println(".transformIfNeeded(transformer, data)")
println("transformIfNeeded(transformer, data)")
} else {
addImport(transformInPlace)
println(".transformInPlace(transformer, data)")
print(child.call())
println("transformInPlace(transformer, data)")
}
}
}