[IR generator] Simplify computation of walkable children
Don't require to specify them explicitly via `isChild` in IR generator, instead test the field type whether it is an element.
This commit is contained in:
committed by
Space Team
parent
ad4e97154f
commit
5f04bc8a27
+79
-68
@@ -105,6 +105,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+descriptor("DeclarationDescriptor")
|
||||
+field("origin", type(Packages.declarations, "IrDeclarationOrigin"))
|
||||
+field("parent", declarationParent) {
|
||||
needAcceptAndTransform = false
|
||||
skipInIrFactory()
|
||||
}
|
||||
+factory
|
||||
@@ -237,7 +238,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
TODO: consider dropping [$name] if it isn't used by any known plugin.
|
||||
""".trimIndent()
|
||||
}
|
||||
+field("defaultValue", expressionBody, nullable = true, isChild = true)
|
||||
+field("defaultValue", expressionBody, nullable = true)
|
||||
}
|
||||
val `class`: Element by element(Declaration) {
|
||||
parent(declarationBase)
|
||||
@@ -285,7 +286,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+listField("superTypes", irTypeType, mutability = Var) {
|
||||
skipInIrFactory()
|
||||
}
|
||||
+field("thisReceiver", valueParameter, nullable = true, isChild = true)
|
||||
+field("thisReceiver", valueParameter, nullable = true)
|
||||
+field(
|
||||
"valueClassRepresentation",
|
||||
type<ValueClassRepresentation<*>>().withArgs(type(Packages.types, "IrSimpleType")),
|
||||
@@ -316,10 +317,12 @@ object IrTree : AbstractTreeBuilder() {
|
||||
""".trimIndent()
|
||||
|
||||
+field("attributeOwnerId", attributeContainer) {
|
||||
needAcceptAndTransform = false
|
||||
skipInIrFactory()
|
||||
}
|
||||
// null <=> this element wasn't inlined
|
||||
+field("originalBeforeInline", attributeContainer, nullable = true) {
|
||||
needAcceptAndTransform = false
|
||||
skipInIrFactory()
|
||||
}
|
||||
}
|
||||
@@ -331,14 +334,14 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+field("isStatic", boolean) {
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
+field("body", blockBody, isChild = true)
|
||||
+field("body", blockBody)
|
||||
}
|
||||
val declarationContainer: Element by element(Declaration) {
|
||||
ownsChildren = false
|
||||
|
||||
parent(declarationParent)
|
||||
|
||||
+listField("declarations", declaration, mutability = MutableList, isChild = true) {
|
||||
+listField("declarations", declaration, mutability = MutableList) {
|
||||
kDoc = """
|
||||
Accessing list of declaration may trigger lazy declaration list computation for lazy class,
|
||||
which requires computation of fake-overrides for this class. So it's unsafe to access it
|
||||
@@ -354,7 +357,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(declaration)
|
||||
parent(declarationParent)
|
||||
|
||||
+listField("typeParameters", typeParameter, mutability = Var, isChild = true)
|
||||
+listField("typeParameters", typeParameter, mutability = Var)
|
||||
}
|
||||
val typeParameter: Element by element(Declaration) {
|
||||
needTransformMethod()
|
||||
@@ -394,14 +397,14 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+field("isInline", boolean)
|
||||
+field("isExpect", boolean)
|
||||
+field("returnType", irTypeType)
|
||||
+field("dispatchReceiverParameter", valueParameter, nullable = true, isChild = true)
|
||||
+field("extensionReceiverParameter", valueParameter, nullable = true, isChild = true)
|
||||
+listField("valueParameters", valueParameter, mutability = Var, isChild = true)
|
||||
+field("dispatchReceiverParameter", valueParameter, nullable = true)
|
||||
+field("extensionReceiverParameter", valueParameter, nullable = true)
|
||||
+listField("valueParameters", valueParameter, mutability = Var)
|
||||
// The first `contextReceiverParametersCount` value parameters are context receivers.
|
||||
+field("contextReceiverParametersCount", int) {
|
||||
skipInIrFactory()
|
||||
}
|
||||
+field("body", body, nullable = true, isChild = true)
|
||||
+field("body", body, nullable = true)
|
||||
}
|
||||
val constructor: Element by element(Declaration) {
|
||||
parent(function)
|
||||
@@ -416,8 +419,8 @@ object IrTree : AbstractTreeBuilder() {
|
||||
|
||||
+descriptor("ClassDescriptor")
|
||||
+symbol(enumEntrySymbolType)
|
||||
+field("initializerExpression", expressionBody, nullable = true, isChild = true)
|
||||
+field("correspondingClass", `class`, nullable = true, isChild = true)
|
||||
+field("initializerExpression", expressionBody, nullable = true)
|
||||
+field("correspondingClass", `class`, nullable = true)
|
||||
}
|
||||
val errorDeclaration: Element by element(Declaration) {
|
||||
parent(declarationBase)
|
||||
@@ -453,7 +456,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+field("type", irTypeType)
|
||||
+field("isFinal", boolean)
|
||||
+field("isStatic", boolean)
|
||||
+field("initializer", expressionBody, nullable = true, isChild = true)
|
||||
+field("initializer", expressionBody, nullable = true)
|
||||
+field("correspondingPropertySymbol", propertySymbolType, nullable = true) {
|
||||
skipInIrFactory()
|
||||
}
|
||||
@@ -468,9 +471,9 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+symbol(localDelegatedPropertySymbolType)
|
||||
+field("type", irTypeType)
|
||||
+field("isVar", boolean)
|
||||
+field("delegate", variable, isChild = true)
|
||||
+field("getter", simpleFunction, isChild = true)
|
||||
+field("setter", simpleFunction, nullable = true, isChild = true)
|
||||
+field("delegate", variable)
|
||||
+field("getter", simpleFunction)
|
||||
+field("setter", simpleFunction, nullable = true)
|
||||
}
|
||||
val moduleFragment: Element by element(Declaration) {
|
||||
needTransformMethod()
|
||||
@@ -482,7 +485,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
}
|
||||
+field("name", type<Name>(), mutable = false)
|
||||
+field("irBuiltins", type(Packages.tree, "IrBuiltIns"), mutable = false)
|
||||
+listField("files", file, mutability = MutableList, isChild = true)
|
||||
+listField("files", file, mutability = MutableList)
|
||||
usedTypes += ArbitraryImportable(Packages.tree, "UNDEFINED_OFFSET")
|
||||
+field("startOffset", int, mutable = false) {
|
||||
baseGetter = "UNDEFINED_OFFSET"
|
||||
@@ -511,9 +514,9 @@ object IrTree : AbstractTreeBuilder() {
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
+isFakeOverrideField()
|
||||
+field("backingField", field, nullable = true, isChild = true)
|
||||
+field("getter", simpleFunction, nullable = true, isChild = true)
|
||||
+field("setter", simpleFunction, nullable = true, isChild = true)
|
||||
+field("backingField", field, nullable = true)
|
||||
+field("getter", simpleFunction, nullable = true)
|
||||
+field("setter", simpleFunction, nullable = true)
|
||||
}
|
||||
|
||||
private fun isFakeOverrideField() = field("isFakeOverride", boolean) {
|
||||
@@ -534,18 +537,20 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+symbol(scriptSymbolType)
|
||||
// NOTE: is the result of the FE conversion, because there script interpreted as a class and has receiver
|
||||
// TODO: consider removing from here and handle appropriately in the lowering
|
||||
+field("thisReceiver", valueParameter, isChild = true, nullable = true) // K1
|
||||
+field("thisReceiver", valueParameter, nullable = true) // K1
|
||||
+field("baseClass", irTypeType, nullable = true) // K1
|
||||
+listField("explicitCallParameters", variable, mutability = Var, isChild = true)
|
||||
+listField("implicitReceiversParameters", valueParameter, mutability = Var, isChild = true)
|
||||
+listField("explicitCallParameters", variable, mutability = Var)
|
||||
+listField("implicitReceiversParameters", valueParameter, mutability = Var)
|
||||
+listField("providedProperties", propertySymbolType, mutability = Var)
|
||||
+listField("providedPropertiesParameters", valueParameter, mutability = Var, isChild = true)
|
||||
+listField("providedPropertiesParameters", valueParameter, mutability = Var)
|
||||
+field("resultProperty", propertySymbolType, nullable = true)
|
||||
+field("earlierScriptsParameter", valueParameter, nullable = true, isChild = true)
|
||||
+field("earlierScriptsParameter", valueParameter, nullable = true)
|
||||
+listField("importedScripts", scriptSymbolType, mutability = Var, nullable = true)
|
||||
+listField("earlierScripts", scriptSymbolType, mutability = Var, nullable = true)
|
||||
+field("targetClass", classSymbolType, nullable = true)
|
||||
+field("constructor", constructor, nullable = true) // K1
|
||||
+field("constructor", constructor, nullable = true) { // K1
|
||||
needAcceptAndTransform = false
|
||||
}
|
||||
}
|
||||
val simpleFunction: Element by element(Declaration) {
|
||||
isLeaf = true
|
||||
@@ -586,7 +591,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+field("isVar", boolean)
|
||||
+field("isConst", boolean)
|
||||
+field("isLateinit", boolean)
|
||||
+field("initializer", expression, nullable = true, isChild = true)
|
||||
+field("initializer", expression, nullable = true)
|
||||
}
|
||||
val packageFragment: Element by element(Declaration) {
|
||||
ownsChildren = false
|
||||
@@ -636,7 +641,9 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(metadataSourceOwner)
|
||||
|
||||
+symbol(fileSymbolType)
|
||||
+field("module", moduleFragment)
|
||||
+field("module", moduleFragment) {
|
||||
needAcceptAndTransform = false
|
||||
}
|
||||
+field("fileEntry", type(Packages.tree, "IrFileEntry"))
|
||||
}
|
||||
|
||||
@@ -649,10 +656,12 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(attributeContainer)
|
||||
|
||||
+field("attributeOwnerId", attributeContainer) {
|
||||
needAcceptAndTransform = false
|
||||
baseDefaultValue = "this"
|
||||
skipInIrFactory()
|
||||
}
|
||||
+field("originalBeforeInline", attributeContainer, nullable = true) {
|
||||
needAcceptAndTransform = false
|
||||
baseDefaultValue = "null"
|
||||
skipInIrFactory()
|
||||
}
|
||||
@@ -661,7 +670,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
val statementContainer: Element by element(Expression) {
|
||||
ownsChildren = false
|
||||
|
||||
+listField("statements", statement, mutability = MutableList, isChild = true)
|
||||
+listField("statements", statement, mutability = MutableList)
|
||||
}
|
||||
val body: Element by element(Expression) {
|
||||
needTransformMethod()
|
||||
@@ -677,7 +686,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(body)
|
||||
|
||||
+factory
|
||||
+field("expression", expression, isChild = true) {
|
||||
+field("expression", expression) {
|
||||
useFieldInIrFactory()
|
||||
}
|
||||
}
|
||||
@@ -703,15 +712,15 @@ object IrTree : AbstractTreeBuilder() {
|
||||
|
||||
parent(declarationReference)
|
||||
|
||||
+field("dispatchReceiver", expression, nullable = true, isChild = true) {
|
||||
+field("dispatchReceiver", expression, nullable = true) {
|
||||
baseDefaultValue = "null"
|
||||
}
|
||||
+field("extensionReceiver", expression, nullable = true, isChild = true) {
|
||||
+field("extensionReceiver", expression, nullable = true) {
|
||||
baseDefaultValue = "null"
|
||||
}
|
||||
+symbol(s)
|
||||
+field("origin", statementOriginType, nullable = true)
|
||||
+listField("valueArguments", expression.copy(nullable = true), mutability = Array, isChild = true) {
|
||||
+listField("valueArguments", expression.copy(nullable = true), mutability = Array) {
|
||||
visibility = Visibility.PROTECTED
|
||||
}
|
||||
+listField("typeArguments", irTypeType.copy(nullable = true), mutability = Array) {
|
||||
@@ -831,7 +840,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(statementContainer)
|
||||
|
||||
+field("origin", statementOriginType, nullable = true)
|
||||
+listField("statements", statement, mutability = MutableList, isChild = true) {
|
||||
+listField("statements", statement, mutability = MutableList) {
|
||||
baseDefaultValue = "ArrayList(2)"
|
||||
}
|
||||
}
|
||||
@@ -870,7 +879,9 @@ object IrTree : AbstractTreeBuilder() {
|
||||
|
||||
parent(expression)
|
||||
|
||||
+field("loop", loop)
|
||||
+field("loop", loop) {
|
||||
needAcceptAndTransform = false
|
||||
}
|
||||
+field("label", string, nullable = true) {
|
||||
baseDefaultValue = "null"
|
||||
}
|
||||
@@ -959,19 +970,19 @@ object IrTree : AbstractTreeBuilder() {
|
||||
val constantPrimitive: Element by element(Expression) {
|
||||
parent(constantValue)
|
||||
|
||||
+field("value", const.withArgs("T" to TypeRef.Star), isChild = true)
|
||||
+field("value", const.withArgs("T" to TypeRef.Star))
|
||||
}
|
||||
val constantObject: Element by element(Expression) {
|
||||
parent(constantValue)
|
||||
|
||||
+field("constructor", constructorSymbolType)
|
||||
+listField("valueArguments", constantValue, mutability = MutableList, isChild = true)
|
||||
+listField("valueArguments", constantValue, mutability = MutableList)
|
||||
+listField("typeArguments", irTypeType, mutability = MutableList)
|
||||
}
|
||||
val constantArray: Element by element(Expression) {
|
||||
parent(constantValue)
|
||||
|
||||
+listField("elements", constantValue, mutability = MutableList, isChild = true)
|
||||
+listField("elements", constantValue, mutability = MutableList)
|
||||
}
|
||||
val delegatingConstructorCall: Element by element(Expression) {
|
||||
parent(functionAccessExpression)
|
||||
@@ -985,14 +996,14 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(dynamicExpression)
|
||||
|
||||
+field("operator", type(Packages.exprs, "IrDynamicOperator"))
|
||||
+field("receiver", expression, isChild = true)
|
||||
+listField("arguments", expression, mutability = MutableList, isChild = true)
|
||||
+field("receiver", expression)
|
||||
+listField("arguments", expression, mutability = MutableList)
|
||||
}
|
||||
val dynamicMemberExpression: Element by element(Expression) {
|
||||
parent(dynamicExpression)
|
||||
|
||||
+field("memberName", string)
|
||||
+field("receiver", expression, isChild = true)
|
||||
+field("receiver", expression)
|
||||
}
|
||||
val enumConstructorCall: Element by element(Expression) {
|
||||
parent(functionAccessExpression)
|
||||
@@ -1009,8 +1020,8 @@ object IrTree : AbstractTreeBuilder() {
|
||||
val errorCallExpression: Element by element(Expression) {
|
||||
parent(errorExpression)
|
||||
|
||||
+field("explicitReceiver", expression, nullable = true, isChild = true)
|
||||
+listField("arguments", expression, mutability = MutableList, isChild = true)
|
||||
+field("explicitReceiver", expression, nullable = true)
|
||||
+listField("arguments", expression, mutability = MutableList)
|
||||
}
|
||||
val fieldAccessExpression: Element by element(Expression) {
|
||||
nameInVisitorMethod = "FieldAccess"
|
||||
@@ -1020,7 +1031,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
|
||||
+symbol(fieldSymbolType, mutable = true)
|
||||
+field("superQualifierSymbol", classSymbolType, nullable = true)
|
||||
+field("receiver", expression, nullable = true, isChild = true) {
|
||||
+field("receiver", expression, nullable = true) {
|
||||
baseDefaultValue = "null"
|
||||
}
|
||||
+field("origin", statementOriginType, nullable = true)
|
||||
@@ -1031,7 +1042,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
val setField: Element by element(Expression) {
|
||||
parent(fieldAccessExpression)
|
||||
|
||||
+field("value", expression, isChild = true)
|
||||
+field("value", expression)
|
||||
}
|
||||
val functionExpression: Element by element(Expression) {
|
||||
transformerReturnType = rootElement
|
||||
@@ -1039,12 +1050,12 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(expression)
|
||||
|
||||
+field("origin", statementOriginType)
|
||||
+field("function", simpleFunction, isChild = true)
|
||||
+field("function", simpleFunction)
|
||||
}
|
||||
val getClass: Element by element(Expression) {
|
||||
parent(expression)
|
||||
|
||||
+field("argument", expression, isChild = true)
|
||||
+field("argument", expression)
|
||||
}
|
||||
val instanceInitializerCall: Element by element(Expression) {
|
||||
parent(expression)
|
||||
@@ -1058,10 +1069,10 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(expression)
|
||||
|
||||
+field("origin", statementOriginType, nullable = true)
|
||||
+field("body", expression, nullable = true, isChild = true) {
|
||||
+field("body", expression, nullable = true) {
|
||||
baseDefaultValue = "null"
|
||||
}
|
||||
+field("condition", expression, isChild = true)
|
||||
+field("condition", expression)
|
||||
+field("label", string, nullable = true) {
|
||||
baseDefaultValue = "null"
|
||||
}
|
||||
@@ -1080,48 +1091,48 @@ object IrTree : AbstractTreeBuilder() {
|
||||
val `return`: Element by element(Expression) {
|
||||
parent(expression)
|
||||
|
||||
+field("value", expression, isChild = true)
|
||||
+field("value", expression)
|
||||
+field("returnTargetSymbol", returnTargetSymbolType)
|
||||
}
|
||||
val stringConcatenation: Element by element(Expression) {
|
||||
parent(expression)
|
||||
|
||||
+listField("arguments", expression, mutability = MutableList, isChild = true)
|
||||
+listField("arguments", expression, mutability = MutableList)
|
||||
}
|
||||
val suspensionPoint: Element by element(Expression) {
|
||||
parent(expression)
|
||||
|
||||
+field("suspensionPointIdParameter", variable, isChild = true)
|
||||
+field("result", expression, isChild = true)
|
||||
+field("resumeResult", expression, isChild = true)
|
||||
+field("suspensionPointIdParameter", variable)
|
||||
+field("result", expression)
|
||||
+field("resumeResult", expression)
|
||||
}
|
||||
val suspendableExpression: Element by element(Expression) {
|
||||
parent(expression)
|
||||
|
||||
+field("suspensionPointId", expression, isChild = true)
|
||||
+field("result", expression, isChild = true)
|
||||
+field("suspensionPointId", expression)
|
||||
+field("result", expression)
|
||||
}
|
||||
val `throw`: Element by element(Expression) {
|
||||
parent(expression)
|
||||
|
||||
+field("value", expression, isChild = true)
|
||||
+field("value", expression)
|
||||
}
|
||||
val `try`: Element by element(Expression) {
|
||||
visitorParameterName = "aTry"
|
||||
|
||||
parent(expression)
|
||||
|
||||
+field("tryResult", expression, isChild = true)
|
||||
+listField("catches", catch, mutability = MutableList, isChild = true)
|
||||
+field("finallyExpression", expression, nullable = true, isChild = true)
|
||||
+field("tryResult", expression)
|
||||
+listField("catches", catch, mutability = MutableList)
|
||||
+field("finallyExpression", expression, nullable = true)
|
||||
}
|
||||
val catch: Element by element(Expression) {
|
||||
visitorParameterName = "aCatch"
|
||||
needTransformMethod()
|
||||
transformByChildren = true
|
||||
|
||||
+field("catchParameter", variable, isChild = true)
|
||||
+field("result", expression, isChild = true)
|
||||
+field("catchParameter", variable)
|
||||
+field("result", expression)
|
||||
}
|
||||
val typeOperatorCall: Element by element(Expression) {
|
||||
nameInVisitorMethod = "TypeOperator"
|
||||
@@ -1129,7 +1140,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(expression)
|
||||
|
||||
+field("operator", type(Packages.exprs, "IrTypeOperator"))
|
||||
+field("argument", expression, isChild = true)
|
||||
+field("argument", expression)
|
||||
+field("typeOperand", irTypeType)
|
||||
}
|
||||
val valueAccessExpression: Element by element(Expression) {
|
||||
@@ -1146,14 +1157,14 @@ object IrTree : AbstractTreeBuilder() {
|
||||
val setValue: Element by element(Expression) {
|
||||
parent(valueAccessExpression)
|
||||
|
||||
+field("value", expression, isChild = true)
|
||||
+field("value", expression)
|
||||
}
|
||||
val varargElement: Element by element(Expression)
|
||||
val vararg: Element by element(Expression) {
|
||||
parent(expression)
|
||||
|
||||
+field("varargElementType", irTypeType)
|
||||
+listField("elements", varargElement, mutability = MutableList, isChild = true)
|
||||
+listField("elements", varargElement, mutability = MutableList)
|
||||
}
|
||||
val spreadElement: Element by element(Expression) {
|
||||
visitorParameterName = "spread"
|
||||
@@ -1162,13 +1173,13 @@ object IrTree : AbstractTreeBuilder() {
|
||||
|
||||
parent(varargElement)
|
||||
|
||||
+field("expression", expression, isChild = true)
|
||||
+field("expression", expression)
|
||||
}
|
||||
val `when`: Element by element(Expression) {
|
||||
parent(expression)
|
||||
|
||||
+field("origin", statementOriginType, nullable = true)
|
||||
+listField("branches", branch, mutability = MutableList, isChild = true)
|
||||
+listField("branches", branch, mutability = MutableList)
|
||||
}
|
||||
val branch: Element by element(Expression) {
|
||||
visitorParameterName = "branch"
|
||||
@@ -1176,8 +1187,8 @@ object IrTree : AbstractTreeBuilder() {
|
||||
needTransformMethod()
|
||||
transformByChildren = true
|
||||
|
||||
+field("condition", expression, isChild = true)
|
||||
+field("result", expression, isChild = true)
|
||||
+field("condition", expression)
|
||||
+field("result", expression)
|
||||
}
|
||||
val elseBranch: Element by element(Expression) {
|
||||
visitorParameterName = "branch"
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.generators.tree.addPureAbstractElement
|
||||
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil
|
||||
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil.collectPreviouslyGeneratedFiles
|
||||
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil.removeExtraFilesFromPreviousGeneration
|
||||
import org.jetbrains.kotlin.ir.generator.model.addWalkableChildren
|
||||
import org.jetbrains.kotlin.ir.generator.model.markLeaves
|
||||
import org.jetbrains.kotlin.ir.generator.print.*
|
||||
import java.io.File
|
||||
@@ -28,7 +27,6 @@ fun main(args: Array<String>) {
|
||||
InterfaceAndAbstractClassConfigurator(model.elements).configureInterfacesAndAbstractClasses()
|
||||
addPureAbstractElement(model.elements, elementBaseType)
|
||||
markLeaves(model.elements)
|
||||
addWalkableChildren(model.elements)
|
||||
|
||||
val previouslyGeneratedFiles = collectPreviouslyGeneratedFiles(generationPath)
|
||||
val generatedFiles = sequence {
|
||||
|
||||
+6
-19
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.generator.config
|
||||
|
||||
import org.jetbrains.kotlin.generators.tree.*
|
||||
import org.jetbrains.kotlin.ir.generator.model.*
|
||||
import org.jetbrains.kotlin.ir.generator.model.ElementOrRef
|
||||
import org.jetbrains.kotlin.ir.generator.model.ElementRef
|
||||
import org.jetbrains.kotlin.ir.generator.model.ListField
|
||||
import org.jetbrains.kotlin.ir.generator.model.Model
|
||||
@@ -14,7 +15,6 @@ import org.jetbrains.kotlin.types.Variance
|
||||
import kotlin.properties.PropertyDelegateProvider
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
import org.jetbrains.kotlin.generators.tree.ElementOrRef as GenericElementOrRef
|
||||
|
||||
abstract class AbstractTreeBuilder {
|
||||
private val configurationCallbacks = mutableListOf<() -> Element>()
|
||||
@@ -22,11 +22,11 @@ abstract class AbstractTreeBuilder {
|
||||
abstract val rootElement: Element
|
||||
|
||||
protected fun Field.skipInIrFactory() {
|
||||
useInIrFactoryStrategy = Field.UseFieldAsParameterInIrFactoryStrategy.No
|
||||
customUseInIrFactoryStrategy = Field.UseFieldAsParameterInIrFactoryStrategy.No
|
||||
}
|
||||
|
||||
protected fun Field.useFieldInIrFactory(defaultValue: String? = null) {
|
||||
useInIrFactoryStrategy = Field.UseFieldAsParameterInIrFactoryStrategy.Yes(defaultValue)
|
||||
customUseInIrFactoryStrategy = Field.UseFieldAsParameterInIrFactoryStrategy.Yes(defaultValue)
|
||||
}
|
||||
|
||||
fun element(category: Element.Category, name: String? = null, initializer: Element.() -> Unit = {}): ElementDelegate {
|
||||
@@ -75,22 +75,18 @@ abstract class AbstractTreeBuilder {
|
||||
type: TypeRefWithNullability,
|
||||
nullable: Boolean = false,
|
||||
mutable: Boolean = true,
|
||||
isChild: Boolean = false,
|
||||
initializer: SingleField.() -> Unit = {}
|
||||
): SingleField {
|
||||
checkChildType(isChild, type, name)
|
||||
return SingleField(name, type.copy(nullable), mutable, isChild).apply(initializer)
|
||||
return SingleField(name, type.copy(nullable), mutable).apply(initializer)
|
||||
}
|
||||
|
||||
protected fun listField(
|
||||
name: String,
|
||||
elementType: TypeRef,
|
||||
baseType: TypeRef,
|
||||
nullable: Boolean = false,
|
||||
mutability: ListField.Mutability,
|
||||
isChild: Boolean = false,
|
||||
initializer: ListField.() -> Unit = {}
|
||||
): ListField {
|
||||
checkChildType(isChild, elementType, name)
|
||||
val listType = when (mutability) {
|
||||
ListField.Mutability.MutableList -> StandardTypes.mutableList
|
||||
ListField.Mutability.Array -> StandardTypes.array
|
||||
@@ -98,22 +94,13 @@ abstract class AbstractTreeBuilder {
|
||||
}
|
||||
return ListField(
|
||||
name = name,
|
||||
baseType = elementType,
|
||||
baseType = baseType,
|
||||
listType = listType,
|
||||
isNullable = nullable,
|
||||
mutable = mutability == ListField.Mutability.Var,
|
||||
isChild = isChild,
|
||||
).apply(initializer)
|
||||
}
|
||||
|
||||
private fun checkChildType(isChild: Boolean, type: TypeRef?, name: String) {
|
||||
if (isChild) {
|
||||
require(type == null || type is GenericElementOrRef<*, *>) {
|
||||
"Field $name is a child field but has non-element type $type"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun build(): Model {
|
||||
val elements = configurationCallbacks.map { it() }
|
||||
return Model(elements, rootElement)
|
||||
|
||||
+28
-16
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.generator.BASE_PACKAGE
|
||||
import org.jetbrains.kotlin.ir.generator.IrTree
|
||||
import org.jetbrains.kotlin.ir.generator.elementBaseType
|
||||
import org.jetbrains.kotlin.utils.SmartPrinter
|
||||
import org.jetbrains.kotlin.utils.topologicalSort
|
||||
import org.jetbrains.kotlin.generators.tree.ElementOrRef as GenericElementOrRef
|
||||
import org.jetbrains.kotlin.generators.tree.ElementRef as GenericElementRef
|
||||
|
||||
@@ -90,8 +89,7 @@ class Element(
|
||||
*/
|
||||
var isLeaf = false
|
||||
|
||||
var childrenOrderOverride: List<String>? = null
|
||||
override var walkableChildren: List<Field> = emptyList()
|
||||
override var childrenOrderOverride: List<String>? = null
|
||||
|
||||
override var visitorParameterName = category.defaultVisitorParam
|
||||
|
||||
@@ -104,10 +102,19 @@ class Element(
|
||||
override var hasTransformMethod = false
|
||||
|
||||
override val hasAcceptChildrenMethod: Boolean
|
||||
get() = ownsChildren && (isRootElement || walkableChildren.isNotEmpty())
|
||||
get() = hasAcceptOrTransformChildrenMethod(Element::walkableChildren)
|
||||
|
||||
override val hasTransformChildrenMethod: Boolean
|
||||
get() = ownsChildren && (isRootElement || transformableChildren.isNotEmpty())
|
||||
get() = hasAcceptOrTransformChildrenMethod(Element::transformableChildren)
|
||||
|
||||
private fun hasAcceptOrTransformChildrenMethod(walkableOrTransformableChildren: Element.() -> List<Field>): Boolean {
|
||||
if (!ownsChildren) return false
|
||||
if (!isRootElement && walkableOrTransformableChildren().isEmpty()) return false
|
||||
val atLeastOneParentHasAcceptOrTransformChildrenMethod = traverseParentsUntil { parent ->
|
||||
parent != this && parent.hasAcceptOrTransformChildrenMethod(walkableOrTransformableChildren) && !parent.isRootElement
|
||||
}
|
||||
return !atLeastOneParentHasAcceptOrTransformChildrenMethod
|
||||
}
|
||||
|
||||
var transformByChildren = false
|
||||
var ownsChildren = true // If false, acceptChildren/transformChildren will NOT be generated.
|
||||
@@ -135,7 +142,6 @@ typealias ElementOrRef = GenericElementOrRef<Element, Field>
|
||||
sealed class Field(
|
||||
override val name: String,
|
||||
override var isMutable: Boolean,
|
||||
val isChild: Boolean,
|
||||
) : AbstractField<Field>() {
|
||||
var baseDefaultValue: String? = null
|
||||
var baseGetter: String? = null
|
||||
@@ -147,8 +153,15 @@ sealed class Field(
|
||||
data class Yes(val defaultValue: String?) : UseFieldAsParameterInIrFactoryStrategy()
|
||||
}
|
||||
|
||||
var useInIrFactoryStrategy =
|
||||
if (isChild) UseFieldAsParameterInIrFactoryStrategy.No else UseFieldAsParameterInIrFactoryStrategy.Yes(null)
|
||||
var customUseInIrFactoryStrategy: UseFieldAsParameterInIrFactoryStrategy? = null
|
||||
|
||||
val useInIrFactoryStrategy: UseFieldAsParameterInIrFactoryStrategy
|
||||
get() = customUseInIrFactoryStrategy
|
||||
?: if (needAcceptAndTransform && containsElement) {
|
||||
UseFieldAsParameterInIrFactoryStrategy.No
|
||||
} else {
|
||||
UseFieldAsParameterInIrFactoryStrategy.Yes(null)
|
||||
}
|
||||
|
||||
override val withGetter: Boolean
|
||||
get() = baseGetter != null
|
||||
@@ -175,12 +188,13 @@ sealed class Field(
|
||||
override fun copy() = internalCopy().also(::updateFieldsInCopy)
|
||||
|
||||
protected fun updateFieldsInCopy(copy: Field) {
|
||||
copy.needAcceptAndTransform = needAcceptAndTransform
|
||||
copy.useInBaseTransformerDetection = useInBaseTransformerDetection
|
||||
copy.isMutable = isMutable
|
||||
copy.optInAnnotation = optInAnnotation
|
||||
copy.baseDefaultValue = baseDefaultValue
|
||||
copy.baseGetter = baseGetter
|
||||
copy.useInIrFactoryStrategy = useInIrFactoryStrategy
|
||||
copy.customUseInIrFactoryStrategy = customUseInIrFactoryStrategy
|
||||
copy.fromParent = fromParent
|
||||
copy.customSetter = customSetter
|
||||
copy.visibility = visibility
|
||||
@@ -195,13 +209,12 @@ class SingleField(
|
||||
name: String,
|
||||
override var typeRef: TypeRefWithNullability,
|
||||
mutable: Boolean,
|
||||
isChild: Boolean,
|
||||
) : Field(name, mutable, isChild) {
|
||||
) : Field(name, mutable) {
|
||||
|
||||
override fun replaceType(newType: TypeRefWithNullability) =
|
||||
SingleField(name, newType, isMutable, isChild).also(::updateFieldsInCopy)
|
||||
SingleField(name, newType, isMutable).also(::updateFieldsInCopy)
|
||||
|
||||
override fun internalCopy() = SingleField(name, typeRef, isMutable, isChild)
|
||||
override fun internalCopy() = SingleField(name, typeRef, isMutable)
|
||||
}
|
||||
|
||||
class ListField(
|
||||
@@ -210,15 +223,14 @@ class ListField(
|
||||
private val isNullable: Boolean,
|
||||
override val listType: ClassRef<PositionTypeParameterRef>,
|
||||
mutable: Boolean,
|
||||
isChild: Boolean,
|
||||
) : Field(name, mutable, isChild), AbstractListField {
|
||||
) : Field(name, mutable), AbstractListField {
|
||||
|
||||
override val typeRef: ClassRef<PositionTypeParameterRef>
|
||||
get() = listType.withArgs(baseType).copy(isNullable)
|
||||
|
||||
override fun replaceType(newType: TypeRefWithNullability) = copy()
|
||||
|
||||
override fun internalCopy() = ListField(name, baseType, isNullable, listType, isMutable, isChild)
|
||||
override fun internalCopy() = ListField(name, baseType, isNullable, listType, isMutable)
|
||||
|
||||
enum class Mutability {
|
||||
Var,
|
||||
|
||||
-52
@@ -5,8 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.generator.model
|
||||
|
||||
import org.jetbrains.kotlin.generators.tree.*
|
||||
|
||||
typealias Model = org.jetbrains.kotlin.generators.tree.Model<Element>
|
||||
|
||||
internal fun markLeaves(elements: List<Element>) {
|
||||
@@ -24,53 +22,3 @@ internal fun markLeaves(elements: List<Element>) {
|
||||
el.isLeaf = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun addWalkableChildren(elements: List<Element>) {
|
||||
for (element in elements) {
|
||||
val walkableChildren = mutableMapOf<String, Field>()
|
||||
|
||||
fun visitParents(visited: Element) {
|
||||
for (parent in visited.elementParents) {
|
||||
if (!parent.element.ownsChildren) {
|
||||
for (field in parent.element.fields) {
|
||||
if (field.isChild) {
|
||||
walkableChildren[field.name] = field
|
||||
}
|
||||
}
|
||||
|
||||
visitParents(parent.element)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitParents(element)
|
||||
|
||||
element.fields.filter { it.isChild }.associateByTo(walkableChildren) { it.name }
|
||||
|
||||
element.walkableChildren = reorderIfNecessary(walkableChildren.values.toList(), element.childrenOrderOverride)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reorderIfNecessary(fields: List<Field>, order: List<String>?): List<Field> =
|
||||
if (order == null) fields else fields.sortedBy {
|
||||
val position = order.indexOf(it.name)
|
||||
if (position < 0) order.size else position
|
||||
}
|
||||
|
||||
private fun iterateElementsParentFirst(elements: List<Element>) = sequence {
|
||||
val pending = elements.sortedBy { it.elementParents.size }.toMutableSet()
|
||||
pendingLoop@ while (pending.isNotEmpty()) {
|
||||
val iter = pending.iterator()
|
||||
while (iter.hasNext()) {
|
||||
val element = iter.next()
|
||||
if (element.elementParents.none { it.element in pending }) {
|
||||
yield(element)
|
||||
iter.remove()
|
||||
continue@pendingLoop
|
||||
}
|
||||
}
|
||||
|
||||
error("Cannot find next element to process")
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -26,11 +26,19 @@ interface FieldContainer<out Field : AbstractField<*>> {
|
||||
val hasTransformChildrenMethod: Boolean
|
||||
get() = false
|
||||
|
||||
/**
|
||||
* Allows to override the order in which the specified children will be visited in `acceptChildren`/`transformChildren` methods.
|
||||
*/
|
||||
val childrenOrderOverride: List<String>?
|
||||
get() = null
|
||||
|
||||
/**
|
||||
* The fields on which to run the visitor in generated `acceptChildren` methods.
|
||||
*/
|
||||
val walkableChildren: List<Field>
|
||||
get() = allFields.filter { it.containsElement && !it.withGetter && it.needAcceptAndTransform }
|
||||
get() = allFields
|
||||
.filter { it.containsElement && !it.withGetter && it.needAcceptAndTransform }
|
||||
.reorderFieldsIfNecessary(childrenOrderOverride)
|
||||
|
||||
/**
|
||||
* The fields on which to run the transformer in generated `transformChildren` methods.
|
||||
|
||||
@@ -5,9 +5,26 @@
|
||||
|
||||
package org.jetbrains.kotlin.generators.tree
|
||||
|
||||
/**
|
||||
* Runs [block] on this element and all its parents recursively.
|
||||
*/
|
||||
fun <Element : AbstractElement<Element, *>> Element.traverseParents(block: (Element) -> Unit) {
|
||||
block(this)
|
||||
elementParents.forEach { it.element.traverseParents(block) }
|
||||
traverseParentsUntil { block(it); false }
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs [block] on this element and all its parents recursively.
|
||||
*
|
||||
* If [block] returns `true` at any point, aborts iteration and returns `true`.
|
||||
*
|
||||
* If [block] always returns `false`, visits all the parents and returns `false`.
|
||||
*/
|
||||
fun <Element : AbstractElement<Element, *>> Element.traverseParentsUntil(block: (Element) -> Boolean): Boolean {
|
||||
if (block(this)) return true
|
||||
for (parent in elementParents) {
|
||||
if (parent.element.traverseParentsUntil(block)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,4 +63,14 @@ operator fun <K, V, U> MutableMap<K, MutableMap<V, U>>.set(k1: K, k2: V, value:
|
||||
|
||||
operator fun <K, V, U> Map<K, Map<V, U>>.get(k1: K, k2: V): U {
|
||||
return getValue(k1).getValue(k2)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <Field : AbstractField<*>> List<Field>.reorderFieldsIfNecessary(order: List<String>?): List<Field> =
|
||||
if (order == null) {
|
||||
this
|
||||
} else {
|
||||
sortedBy {
|
||||
val position = order.indexOf(it.name)
|
||||
if (position < 0) order.size else position
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user