[FIR] Add FIR tree generator
This commit is contained in:
@@ -16,6 +16,10 @@ runtimeOnly.extendsFrom(compileOnly)
|
||||
|
||||
dependencies {
|
||||
compile(project(":compiler:psi"))
|
||||
compile(project(":compiler:frontend.common"))
|
||||
compile(project(":core:descriptors"))
|
||||
compile(project(":compiler:fir:cones"))
|
||||
compile(project(":compiler:ir.tree"))
|
||||
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
|
||||
compileOnly(intellijDep()) {
|
||||
@@ -25,6 +29,7 @@ dependencies {
|
||||
Platform[192].orHigher {
|
||||
runtimeOnly(intellijCoreDep()) { includeJars("jdom") }
|
||||
}
|
||||
implementation(kotlin("reflect"))
|
||||
}
|
||||
|
||||
val writeCopyright by task<WriteCopyrightToFile> {
|
||||
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.annotationCall
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.block
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.controlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.declaration
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.declarationStatus
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.expression
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.reference
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.typeParameter
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.typeProjection
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.typeRef
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FirTreeBuilder.valueParameter
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.type
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.*
|
||||
|
||||
object FieldSets {
|
||||
val calleeReference = field("calleeReference", reference)
|
||||
|
||||
val receivers = fieldSet(
|
||||
field("explicitReceiver", expression, nullable = true).withTransform(),
|
||||
field("dispatchReceiver", expression).withTransform(),
|
||||
field("extensionReceiver", expression).withTransform()
|
||||
)
|
||||
|
||||
val typeArguments =
|
||||
fieldList("typeArguments", typeProjection)
|
||||
|
||||
val arguments =
|
||||
fieldList("arguments", expression)
|
||||
|
||||
val declarations = fieldList(declaration)
|
||||
|
||||
val annotations =
|
||||
fieldList("annotations", annotationCall)
|
||||
|
||||
fun symbolWithPackage(packageName: String?, symbolClassName: String, argument: String? = null): Field {
|
||||
return field("symbol", type(packageName, symbolClassName), argument)
|
||||
}
|
||||
|
||||
fun symbol(symbolClassName: String, argument: String? = null): Field =
|
||||
symbolWithPackage("fir.symbols.impl", symbolClassName, argument)
|
||||
|
||||
fun body(nullable: Boolean = false) =
|
||||
field("body", block, nullable)
|
||||
|
||||
val returnTypeRef =
|
||||
field("returnTypeRef", typeRef)
|
||||
|
||||
val typeRefField =
|
||||
field(typeRef, withReplace = true)
|
||||
|
||||
fun receiverTypeRef(nullable: Boolean = false) = field("receiverTypeRef", typeRef, nullable)
|
||||
|
||||
val valueParameters = fieldList(valueParameter)
|
||||
|
||||
val typeParameters = fieldList(typeParameter)
|
||||
|
||||
val name = field(nameType)
|
||||
|
||||
val initializer = field("initializer", expression, nullable = true)
|
||||
|
||||
fun superTypeRefs(withReplace: Boolean = false) = fieldList("superTypeRefs", typeRef, withReplace)
|
||||
|
||||
val classKind = field(classKindType)
|
||||
|
||||
val status = field("status", declarationStatus)
|
||||
|
||||
val controlFlowGraphReferenceField = field("controlFlowGraphReference", controlFlowGraphReference)
|
||||
|
||||
val visibility = field(visibilityType)
|
||||
|
||||
val modality = field(modalityType, nullable = true)
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Element.Kind.*
|
||||
|
||||
object FirTreeBuilder : AbstractFirTreeBuilder() {
|
||||
val annotationContainer = element("AnnotationContainer", Other)
|
||||
val typeRef = element("TypeRef", TypeRef, annotationContainer)
|
||||
val reference = element("Reference", Reference)
|
||||
val label = element("Label", Other)
|
||||
val import = element("Import", Declaration)
|
||||
val resolvedImport = element("ResolvedImport", Declaration, import)
|
||||
val symbolOwner = element("SymbolOwner", Other)
|
||||
val resolvable = element("Resolvable", Expression)
|
||||
|
||||
val controlFlowGraphOwner = element("ControlFlowGraphOwner", Other)
|
||||
val targetElement = element("TargetElement", Other)
|
||||
|
||||
val declarationStatus = element("DeclarationStatus", Declaration)
|
||||
val resolvedDeclarationStatus = element("ResolvedDeclarationStatus", Declaration, declarationStatus)
|
||||
|
||||
val statement = element("Statement", Expression, annotationContainer)
|
||||
val expression = element("Expression", Expression, statement)
|
||||
val declaration = element("Declaration", Declaration)
|
||||
val anonymousInitializer = element("AnonymousInitializer", Declaration, declaration)
|
||||
val typedDeclaration = element("TypedDeclaration", Declaration, declaration, annotationContainer)
|
||||
val callableDeclaration = element("CallableDeclaration", Declaration, typedDeclaration, symbolOwner)
|
||||
val namedDeclaration = element("NamedDeclaration", Declaration, declaration)
|
||||
val typeParameter = element("TypeParameter", Declaration, namedDeclaration, symbolOwner, annotationContainer)
|
||||
val typeParametersOwner = element("TypeParametersOwner", Declaration)
|
||||
val memberDeclaration = element("MemberDeclaration", Declaration, namedDeclaration, annotationContainer)
|
||||
val callableMemberDeclaration = element("CallableMemberDeclaration", Declaration, callableDeclaration, memberDeclaration)
|
||||
|
||||
val variable = element("Variable", Declaration, callableDeclaration, namedDeclaration, statement)
|
||||
val valueParameter = element("ValueParameter", Declaration, variable)
|
||||
val property = element("Property", Declaration, variable, controlFlowGraphOwner, typeParametersOwner, callableMemberDeclaration)
|
||||
val field = element("Field", Declaration, variable, callableMemberDeclaration) // TODO: add noImpl
|
||||
val klass = element("Class", Declaration, declaration, statement, annotationContainer)
|
||||
val classLikeDeclaration = element("ClassLikeDeclaration", Declaration, statement, memberDeclaration, symbolOwner, typeParametersOwner)
|
||||
val regularClass = element("RegularClass", Declaration, namedDeclaration, classLikeDeclaration, klass)
|
||||
val typeAlias = element("TypeAlias", Declaration, classLikeDeclaration)
|
||||
val enumEntry = element("EnumEntry", Declaration, regularClass)
|
||||
|
||||
val function = element("Function", Declaration, callableDeclaration, controlFlowGraphOwner, targetElement, annotationContainer, typeParametersOwner, statement)
|
||||
|
||||
val memberFunction = element("MemberFunction", Declaration, function, callableMemberDeclaration)
|
||||
val simpleFunction = element("SimpleFunction", Declaration, memberFunction)
|
||||
val propertyAccessor = element("PropertyAccessor", Declaration, function)
|
||||
val constructor = element("Constructor", Declaration, memberFunction)
|
||||
val file = element("File", Declaration, annotationContainer, declaration)
|
||||
|
||||
val anonymousFunction = element("AnonymousFunction", Declaration, function, expression)
|
||||
val anonymousObject = element("AnonymousObject", Declaration, klass, expression)
|
||||
|
||||
val loop = element("Loop", Expression, statement, targetElement, annotationContainer)
|
||||
val doWhileLoop = element("DoWhileLoop", Expression, loop)
|
||||
val whileLoop = element("WhileLoop", Expression, loop)
|
||||
|
||||
val block = element("Block", Expression, expression)
|
||||
val binaryLogicExpression = element("BinaryLogicExpression", Expression, expression)
|
||||
val jump = element("Jump", Expression, expression)
|
||||
val loopJump = element("LoopJump", Expression, jump)
|
||||
val breakExpression = element("BreakExpression", Expression, loopJump)
|
||||
val continueExpression = element("ContinueExpression", Expression, loopJump)
|
||||
val catchClause = element("Catch", Expression)
|
||||
val tryExpression = element("TryExpression", Expression, expression, resolvable)
|
||||
val constExpression = element("ConstExpression", Expression, expression)
|
||||
val typeProjection = element("TypeProjection", TypeRef)
|
||||
val starProjection = element("StarProjection", TypeRef, typeProjection)
|
||||
val typeProjectionWithVariance = element("TypeProjectionWithVariance", TypeRef, typeProjection)
|
||||
val call = element("Call", Expression, statement) // TODO: may smth like `CallWithArguments` or `ElementWithArguments`?
|
||||
val annotationCall = element("AnnotationCall", Expression, expression, call)
|
||||
val operatorCall = element("OperatorCall", Expression, expression, call)
|
||||
val typeOperatorCall = element("TypeOperatorCall", Expression, expression, call)
|
||||
val whenExpression = element("WhenExpression", Expression, expression, resolvable)
|
||||
val whenBranch = element("WhenBranch", Expression)
|
||||
val delegatedConstructorCall = element("DelegatedConstructorCall", Expression, call)
|
||||
val qualifiedAccessWithoutCallee = element("QualifiedAccessWithoutCallee", Expression, statement)
|
||||
val qualifiedAccess = element("QualifiedAccess", Expression, qualifiedAccessWithoutCallee, resolvable)
|
||||
|
||||
val arrayOfCall = element("ArrayOfCall", Expression, expression, call)
|
||||
val arraySetCall = element("ArraySetCall", Expression, qualifiedAccess, call)
|
||||
val classReferenceExpression = element("ClassReferenceExpression", Expression, expression)
|
||||
val errorExpression = element("ErrorExpression", Expression, expression)
|
||||
val errorFunction = element("ErrorFunction", Declaration, function)
|
||||
val qualifiedAccessExpression = element("QualifiedAccessExpression", Expression, expression, qualifiedAccess)
|
||||
val functionCall = element("FunctionCall", Expression, qualifiedAccessExpression, call)
|
||||
val componentCall = element("ComponentCall", Expression, functionCall)
|
||||
val callableReferenceAccess = element("CallableReferenceAccess", Expression, qualifiedAccessExpression)
|
||||
val thisReceiverExpression = element("ThisReceiverExpression", Expression, qualifiedAccessExpression)
|
||||
val expressionWithSmartcast = element("ExpressionWithSmartcast", Expression, qualifiedAccessExpression)
|
||||
val getClassCall = element("GetClassCall", Expression, expression, call)
|
||||
val wrappedExpression = element("WrappedExpression", Expression, expression)
|
||||
val wrappedArgumentExpression = element("WrappedArgumentExpression", Expression, wrappedExpression)
|
||||
val lambdaArgumentExpression = element("LambdaArgumentExpression", Expression, wrappedArgumentExpression)
|
||||
val spreadArgumentExpression = element("SpreadArgumentExpression", Expression, wrappedArgumentExpression)
|
||||
val namedArgumentExpression = element("NamedArgumentExpression", Expression, wrappedArgumentExpression)
|
||||
|
||||
val resolvedQualifier = element("ResolvedQualifier", Expression, expression)
|
||||
val returnExpression = element("ReturnExpression", Expression, jump)
|
||||
val stringConcatenationCall = element("StringConcatenationCall", Expression, call, expression)
|
||||
val throwExpression = element("ThrowExpression", Expression, expression)
|
||||
val variableAssignment = element("VariableAssignment", Expression, qualifiedAccess)
|
||||
val whenSubjectExpression = element("WhenSubjectExpression", Expression, expression)
|
||||
|
||||
val wrappedDelegateExpression = element("WrappedDelegateExpression", Expression, wrappedExpression)
|
||||
|
||||
val namedReference = element("NamedReference", Reference, reference)
|
||||
val errorNamedReference = element("ErrorNamedReference", Reference, namedReference)
|
||||
val superReference = element("SuperReference", Reference, reference)
|
||||
val thisReference = element("ThisReference", Reference, reference)
|
||||
val controlFlowGraphReference = element("ControlFlowGraphReference", Reference, reference)
|
||||
|
||||
val resolvedCallableReference = element("ResolvedCallableReference", Reference, namedReference)
|
||||
val delegateFieldReference = element("DelegateFieldReference", Reference, resolvedCallableReference)
|
||||
val backingFieldReference = element("BackingFieldReference", Reference, resolvedCallableReference)
|
||||
|
||||
val resolvedTypeRef = element("ResolvedTypeRef", TypeRef, typeRef)
|
||||
val errorTypeRef = element("ErrorTypeRef", TypeRef, resolvedTypeRef)
|
||||
val delegatedTypeRef = element("DelegatedTypeRef", TypeRef, typeRef)
|
||||
val typeRefWithNullability = element("TypeRefWithNullability", TypeRef, typeRef)
|
||||
val userTypeRef = element("UserTypeRef", TypeRef, typeRefWithNullability)
|
||||
val dynamicTypeRef = element("DynamicTypeRef", TypeRef, typeRefWithNullability)
|
||||
val functionTypeRef = element("FunctionTypeRef", TypeRef, typeRefWithNullability)
|
||||
val resolvedFunctionTypeRef = element("ResolvedFunctionTypeRef", TypeRef, resolvedTypeRef, functionTypeRef)
|
||||
val implicitTypeRef = element("ImplicitTypeRef", TypeRef, typeRef)
|
||||
}
|
||||
+625
@@ -0,0 +1,625 @@
|
||||
/*
|
||||
* Copyright 2000-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
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeImplementationConfigurator
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind.*
|
||||
|
||||
object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() {
|
||||
private lateinit var abstractAnnotatedElement: Implementation
|
||||
|
||||
fun configureImplementations() {
|
||||
configure()
|
||||
generateDefaultImplementations(FirTreeBuilder)
|
||||
configureAllImplementations()
|
||||
}
|
||||
|
||||
private fun configure() = with(FirTreeBuilder) {
|
||||
val callWithArgumentList = impl(call, "FirCallWithArgumentList") {
|
||||
kind = Interface
|
||||
}
|
||||
|
||||
abstractAnnotatedElement = impl(annotationContainer, "FirAbstractAnnotatedElement") {
|
||||
kind = Interface
|
||||
}
|
||||
|
||||
val modifiableTypeParametersOwner = impl(typeParametersOwner, "FirModifiableTypeParametersOwner") {
|
||||
kind = Interface
|
||||
}
|
||||
|
||||
val modifiableConstructor = impl(constructor, "FirModifiableConstructor") {
|
||||
kind = Interface
|
||||
parents += modifiableTypeParametersOwner
|
||||
}
|
||||
|
||||
impl(constructor) {
|
||||
kind = OpenClass
|
||||
parents += modifiableConstructor
|
||||
defaultNull("delegatedConstructor")
|
||||
defaultNull("body")
|
||||
default("name", "Name.special(\"<init>\")")
|
||||
|
||||
default("isPrimary") {
|
||||
value = "false"
|
||||
withGetter = true
|
||||
}
|
||||
|
||||
default("typeParameters") {
|
||||
needAcceptAndTransform = false
|
||||
}
|
||||
}
|
||||
|
||||
noImpl(declarationStatus)
|
||||
noImpl(resolvedDeclarationStatus)
|
||||
noImpl(field)
|
||||
|
||||
val modifiableClass = impl(klass, "FirModifiableClass") {
|
||||
kind = Interface
|
||||
}
|
||||
|
||||
impl(regularClass, "FirClassImpl") {
|
||||
parents += modifiableClass
|
||||
parents += modifiableTypeParametersOwner
|
||||
defaultNull("companionObject")
|
||||
defaultSupertypesComputationStatus()
|
||||
}
|
||||
|
||||
impl(anonymousObject) {
|
||||
parents += modifiableClass
|
||||
default("classKind") {
|
||||
value = "ClassKind.OBJECT"
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
|
||||
impl(enumEntry) {
|
||||
parents += modifiableClass
|
||||
parents += modifiableTypeParametersOwner
|
||||
default("status", "FirDeclarationStatusImpl(Visibilities.UNKNOWN, Modality.FINAL)")
|
||||
default("classKind") {
|
||||
value = "ClassKind.ENUM_ENTRY"
|
||||
withGetter = true
|
||||
}
|
||||
default("companionObject") {
|
||||
value = "null"
|
||||
withGetter = true
|
||||
}
|
||||
default("typeRef", "session.builtinTypes.enumType")
|
||||
defaultSupertypesComputationStatus()
|
||||
useTypes(visibilitiesType, modalityType)
|
||||
}
|
||||
|
||||
impl(typeAlias) {
|
||||
parents += modifiableTypeParametersOwner
|
||||
defaultSupertypesComputationStatus()
|
||||
}
|
||||
|
||||
impl(import)
|
||||
|
||||
impl(resolvedImport) {
|
||||
delegateFields(listOf("aliasName", "importedFqName", "isAllUnder"), "delegate")
|
||||
|
||||
default("psi") {
|
||||
delegate = "delegate"
|
||||
}
|
||||
|
||||
default("resolvedClassId") {
|
||||
delegate = "relativeClassName"
|
||||
delegateCall = "let { ClassId(packageFqName, it, false) }"
|
||||
withGetter = true
|
||||
}
|
||||
|
||||
default("importedName") {
|
||||
delegate = "importedFqName"
|
||||
delegateCall = "shortName()"
|
||||
withGetter = true
|
||||
}
|
||||
|
||||
default("delegate") {
|
||||
needAcceptAndTransform = false
|
||||
}
|
||||
}
|
||||
|
||||
impl(breakExpression) {
|
||||
lateinit("target")
|
||||
}
|
||||
|
||||
impl(continueExpression) {
|
||||
lateinit("target")
|
||||
}
|
||||
|
||||
impl(annotationCall) {
|
||||
parents += callWithArgumentList
|
||||
default("typeRef") {
|
||||
value = "annotationTypeRef"
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
|
||||
impl(arrayOfCall) {
|
||||
parents += callWithArgumentList
|
||||
}
|
||||
|
||||
val modifiableQualifiedAccess = impl(qualifiedAccessWithoutCallee, "FirModifiableQualifiedAccess") {
|
||||
kind = Interface
|
||||
isMutable("safe")
|
||||
}
|
||||
|
||||
impl(arraySetCall) {
|
||||
parents += modifiableQualifiedAccess
|
||||
lateinit("calleeReference")
|
||||
default("arguments") {
|
||||
value = "indexes + rValue"
|
||||
withGetter = true
|
||||
}
|
||||
default("lValue") {
|
||||
value = "calleeReference"
|
||||
customSetter = "calleeReference = value"
|
||||
}
|
||||
default("safe", "false")
|
||||
defaultNoReceivers()
|
||||
}
|
||||
|
||||
impl(callableReferenceAccess) {
|
||||
parents += modifiableQualifiedAccess
|
||||
defaultNull("explicitReceiver")
|
||||
default("safe", "false")
|
||||
defaultNoReceivers()
|
||||
lateinit("calleeReference")
|
||||
}
|
||||
|
||||
impl(componentCall) {
|
||||
parents += callWithArgumentList // modifiableQualifiedAccess
|
||||
default("safe") {
|
||||
value = "false"
|
||||
withGetter = true
|
||||
}
|
||||
listOf("dispatchReceiver", "extensionReceiver").forEach {
|
||||
default(it) {
|
||||
value = "FirNoReceiverExpression"
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
default("calleeReference", "FirSimpleNamedReference(psi, Name.identifier(\"component\$componentIndex\"), null)")
|
||||
useTypes(simpleNamedReferenceType, nameType, noReceiverExpressionType)
|
||||
}
|
||||
|
||||
val abstractLoop = impl(loop, "FirAbstractLoop") {
|
||||
kind = Interface
|
||||
}
|
||||
|
||||
impl(whileLoop) {
|
||||
parents += abstractLoop
|
||||
defaultNull("label")
|
||||
lateinit("block")
|
||||
}
|
||||
|
||||
impl(doWhileLoop) {
|
||||
parents += abstractLoop
|
||||
defaultNull("label")
|
||||
lateinit("block")
|
||||
}
|
||||
|
||||
impl(delegatedConstructorCall) {
|
||||
parents += callWithArgumentList
|
||||
default(
|
||||
"calleeReference",
|
||||
"if (isThis) FirExplicitThisReference(psi, null) else FirExplicitSuperReference(psi, constructedTypeRef)"
|
||||
)
|
||||
default("isSuper") {
|
||||
value = "!isThis"
|
||||
withGetter = true
|
||||
}
|
||||
useTypes(explicitThisReferenceType, explicitSuperReferenceType)
|
||||
}
|
||||
|
||||
impl(expression, "FirElseIfTrueCondition") {
|
||||
default("typeRef", "FirImplicitBooleanTypeRef(psi)")
|
||||
useTypes(implicitBooleanTypeRefType)
|
||||
}
|
||||
|
||||
impl(block) {
|
||||
}
|
||||
|
||||
val emptyExpressionBlock = impl(block, "FirEmptyExpressionBlock") {
|
||||
// TODO: make statements immutable
|
||||
defaultNull("psi")
|
||||
}
|
||||
|
||||
impl(errorExpression)
|
||||
|
||||
impl(loop, "FirErrorLoop") {
|
||||
default("block", "FirEmptyExpressionBlock()")
|
||||
default("condition", "FirErrorExpressionImpl(psi, \"error loop\")")
|
||||
defaultNull("label")
|
||||
useTypes(emptyExpressionBlock)
|
||||
}
|
||||
|
||||
impl(expression, "FirExpressionStub")
|
||||
|
||||
impl(functionCall) {
|
||||
parents += modifiableQualifiedAccess
|
||||
parents += callWithArgumentList
|
||||
defaultFalse("safe")
|
||||
lateinit("calleeReference")
|
||||
defaultNoReceivers()
|
||||
}
|
||||
|
||||
impl(qualifiedAccessExpression) {
|
||||
parents += modifiableQualifiedAccess
|
||||
defaultFalse("safe")
|
||||
lateinit("calleeReference")
|
||||
defaultNoReceivers()
|
||||
}
|
||||
|
||||
noImpl(expressionWithSmartcast)
|
||||
|
||||
impl(getClassCall) {
|
||||
parents += callWithArgumentList
|
||||
default("argument") {
|
||||
value = "arguments.first()"
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
|
||||
val modifiableVariable = impl(variable, "FirModifiableVariable") {
|
||||
kind = Interface
|
||||
}
|
||||
|
||||
impl(property) {
|
||||
parents += modifiableVariable.withArg(property)
|
||||
parents += modifiableTypeParametersOwner
|
||||
default("isVal") {
|
||||
value = "!isVar"
|
||||
withGetter = true
|
||||
}
|
||||
|
||||
default("backingFieldSymbol", "FirBackingFieldSymbol(symbol.callableId)")
|
||||
default("delegateFieldSymbol", "delegate?.let { FirDelegateFieldSymbol(symbol.callableId) }")
|
||||
defaultNull("getter", "setter")
|
||||
default("resolvePhase") {
|
||||
value = "if (isLocal) FirResolvePhase.DECLARATIONS else FirResolvePhase.RAW_FIR"
|
||||
}
|
||||
useTypes(backingFieldSymbolType, delegateFieldSymbolType)
|
||||
}
|
||||
|
||||
impl(namedArgumentExpression) {
|
||||
default("typeRef") {
|
||||
delegate = "expression"
|
||||
}
|
||||
}
|
||||
|
||||
impl(lambdaArgumentExpression) {
|
||||
default("isSpread") {
|
||||
value = "false"
|
||||
withGetter = true
|
||||
}
|
||||
default("typeRef") {
|
||||
delegate = "expression"
|
||||
}
|
||||
}
|
||||
|
||||
impl(spreadArgumentExpression) {
|
||||
default("isSpread") {
|
||||
value = "true"
|
||||
withGetter = true
|
||||
}
|
||||
default("typeRef") {
|
||||
delegate = "expression"
|
||||
}
|
||||
}
|
||||
|
||||
impl(operatorCall) {
|
||||
parents += callWithArgumentList
|
||||
default("typeRef", """
|
||||
|if (operation in FirOperation.BOOLEANS) {
|
||||
| FirImplicitBooleanTypeRef(null)
|
||||
| } else {
|
||||
| FirImplicitTypeRefImpl(null)
|
||||
| }
|
||||
""".trimMargin())
|
||||
|
||||
useTypes(implicitTypeRefType, implicitBooleanTypeRefType)
|
||||
}
|
||||
|
||||
impl(typeOperatorCall) {
|
||||
parents += callWithArgumentList
|
||||
}
|
||||
|
||||
impl(resolvedQualifier) {
|
||||
isMutable("packageFqName", "relativeClassFqName")
|
||||
default("classId") {
|
||||
value = """
|
||||
|relativeClassFqName?.let {
|
||||
| ClassId(packageFqName, it, false)
|
||||
|}
|
||||
""".trimMargin()
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
|
||||
impl(returnExpression) {
|
||||
lateinit("target")
|
||||
default("typeRef", "FirImplicitNothingTypeRef(psi)")
|
||||
useTypes(implicitNothingTypeRefType)
|
||||
}
|
||||
|
||||
impl(stringConcatenationCall) {
|
||||
parents += callWithArgumentList
|
||||
default("typeRef", "FirImplicitStringTypeRef(psi)")
|
||||
useTypes(implicitStringTypeRefType)
|
||||
}
|
||||
|
||||
impl(throwExpression) {
|
||||
default("typeRef", "FirImplicitNothingTypeRef(psi)")
|
||||
useTypes(implicitNothingTypeRefType)
|
||||
}
|
||||
|
||||
impl(thisReceiverExpression) {
|
||||
parents += modifiableQualifiedAccess
|
||||
default("safe") {
|
||||
value = "false"
|
||||
withGetter = true
|
||||
}
|
||||
defaultNoReceivers()
|
||||
}
|
||||
|
||||
impl(tryExpression) {
|
||||
default("calleeReference", "FirStubReference()")
|
||||
useTypes(stubReferenceType)
|
||||
}
|
||||
|
||||
impl(expression, "FirUnitExpression") {
|
||||
default("typeRef", "FirImplicitUnitTypeRef(psi)")
|
||||
useTypes(implicitUnitTypeRefType)
|
||||
}
|
||||
|
||||
impl(variableAssignment) {
|
||||
parents += modifiableQualifiedAccess
|
||||
isMutable("operation")
|
||||
lateinit("calleeReference")
|
||||
defaultNoReceivers()
|
||||
|
||||
default("lValue") {
|
||||
value = "calleeReference"
|
||||
customSetter = "calleeReference = value"
|
||||
}
|
||||
}
|
||||
|
||||
val modifiableFunction = impl(function, "FirModifiableFunction") {
|
||||
kind = Interface
|
||||
}
|
||||
|
||||
impl(anonymousFunction) {
|
||||
parents += modifiableFunction.withArg(anonymousFunction)
|
||||
defaultNull("invocationKind", "label", "body")
|
||||
default("resolvePhase", "FirResolvePhase.DECLARATIONS")
|
||||
}
|
||||
|
||||
impl(propertyAccessor) {
|
||||
parents += modifiableFunction.withArg(propertyAccessor)
|
||||
default("receiverTypeRef") {
|
||||
value = "null"
|
||||
withGetter = true
|
||||
}
|
||||
default("isSetter") {
|
||||
value = "!isGetter"
|
||||
withGetter = true
|
||||
}
|
||||
defaultNull("body")
|
||||
useTypes(modalityType)
|
||||
kind = OpenClass
|
||||
}
|
||||
|
||||
impl(whenExpression) {
|
||||
default("calleeReference", "FirStubReference()")
|
||||
useTypes(stubReferenceType)
|
||||
}
|
||||
|
||||
impl(whenSubjectExpression) {
|
||||
default("typeRef") {
|
||||
value = "whenSubject.whenExpression.subject!!.typeRef"
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
|
||||
impl(wrappedDelegateExpression) {
|
||||
lateinit("delegateProvider")
|
||||
default("typeRef") {
|
||||
delegate = "expression"
|
||||
}
|
||||
}
|
||||
|
||||
impl(resolvedCallableReference) {
|
||||
defaultNull("candidateSymbol", withGetter = true)
|
||||
}
|
||||
|
||||
impl(resolvedCallableReference, "FirPropertyFromParameterCallableReference") {
|
||||
defaultNull("candidateSymbol", withGetter = true)
|
||||
}
|
||||
|
||||
impl(namedReference, "FirSimpleNamedReference") {
|
||||
kind = OpenClass
|
||||
}
|
||||
|
||||
impl(delegateFieldReference) {
|
||||
default("name") {
|
||||
value = "Name.identifier(\"\\\$delegate\")"
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
|
||||
impl(backingFieldReference) {
|
||||
default("name") {
|
||||
value = "Name.identifier(\"\\\$field\")"
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
|
||||
impl(thisReference, "FirExplicitThisReference") {
|
||||
default("boundSymbol") {
|
||||
value = "null"
|
||||
isMutable = true
|
||||
}
|
||||
}
|
||||
|
||||
impl(thisReference, "FirImplicitThisReference") {
|
||||
defaultNull("psi")
|
||||
default("labelName") {
|
||||
value = "null"
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
|
||||
impl(superReference, "FirExplicitSuperReference")
|
||||
|
||||
impl(controlFlowGraphReference, "FirEmptyControlFlowGraphReference") {
|
||||
noPsi()
|
||||
}
|
||||
|
||||
impl(resolvedTypeRef)
|
||||
|
||||
val errorTypeRefImpl = impl(errorTypeRef) {
|
||||
default("type", "ConeClassErrorType(reason)")
|
||||
useTypes(coneClassErrorTypeType)
|
||||
}
|
||||
|
||||
impl(errorFunction) {
|
||||
defaultNull("receiverTypeRef", "body", withGetter = true)
|
||||
default("returnTypeRef", "FirErrorTypeRefImpl(null, reason)")
|
||||
useTypes(errorTypeRefImpl)
|
||||
}
|
||||
|
||||
impl(functionTypeRef)
|
||||
impl(implicitTypeRef) {
|
||||
defaultEmptyList("annotations")
|
||||
}
|
||||
|
||||
impl(implicitTypeRef, "FirComputingImplicitTypeRef") {
|
||||
kind = Object
|
||||
defaultNull("psi", withGetter = true)
|
||||
}
|
||||
|
||||
impl(reference, "FirStubReference") {
|
||||
default("psi") {
|
||||
value = "null"
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
|
||||
impl(errorNamedReference) {
|
||||
default("name", "Name.special(\"<\$errorReason>\")")
|
||||
defaultNull("candidateSymbol", withGetter = true)
|
||||
}
|
||||
|
||||
impl(typeProjection, "FirTypePlaceholderProjection") {
|
||||
kind = Object
|
||||
defaultNull("psi")
|
||||
}
|
||||
|
||||
val abstractLoopJump = impl(loopJump, "FirAbstractLoopJump") {
|
||||
kind = Interface
|
||||
lateinit("target")
|
||||
}
|
||||
|
||||
impl(breakExpression) {
|
||||
parents += abstractLoopJump
|
||||
default("typeRef", "FirImplicitNothingTypeRef(psi)")
|
||||
useTypes(implicitNothingTypeRefType)
|
||||
}
|
||||
|
||||
impl(continueExpression) {
|
||||
parents += abstractLoopJump
|
||||
default("typeRef", "FirImplicitNothingTypeRef(psi)")
|
||||
useTypes(implicitNothingTypeRefType)
|
||||
}
|
||||
|
||||
impl(valueParameter) {
|
||||
kind = OpenClass
|
||||
parents += modifiableVariable.withArg(valueParameter)
|
||||
defaultTrue("isVal", true)
|
||||
defaultFalse("isVar", withGetter = true)
|
||||
defaultNull("getter", "setter", "initializer", "delegate", "receiverTypeRef", "delegateFieldSymbol", withGetter = true)
|
||||
}
|
||||
|
||||
impl(valueParameter, "FirDefaultSetterValueParameter") {
|
||||
default("name", "Name.identifier(\"value\")")
|
||||
defaultNull("defaultValue", "initializer", "delegate", "receiverTypeRef", "delegateFieldSymbol", "getter", "setter")
|
||||
defaultFalse("isCrossinline", "isNoinline", "isVararg", "isVar")
|
||||
defaultTrue("isVal")
|
||||
}
|
||||
|
||||
impl(simpleFunction) {
|
||||
kind = OpenClass
|
||||
parents += modifiableFunction.withArg(simpleFunction)
|
||||
parents += modifiableTypeParametersOwner
|
||||
defaultNull("body")
|
||||
}
|
||||
|
||||
impl(delegatedTypeRef) {
|
||||
listOf("psi", "annotations").forEach {
|
||||
default(it) {
|
||||
delegate = "typeRef"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
noImpl(userTypeRef)
|
||||
}
|
||||
|
||||
private fun findImplementationsWithAnnotations(implementationPredicate: (Implementation) -> Boolean): Collection<Implementation> {
|
||||
return FirTreeBuilder.elements.flatMap { it.allImplementations }.mapNotNullTo(mutableSetOf()) {
|
||||
if (!implementationPredicate(it)) return@mapNotNullTo null
|
||||
var hasAnnotations = false
|
||||
if (it.element == FirTreeBuilder.annotationContainer) return@mapNotNullTo null
|
||||
it.element.traverseParents {
|
||||
if (it == FirTreeBuilder.annotationContainer) {
|
||||
hasAnnotations = true
|
||||
}
|
||||
}
|
||||
it.takeIf { hasAnnotations }
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureAllImplementations() {
|
||||
configureFieldInAllImplementations("controlFlowGraphReference") {
|
||||
default(it, "FirEmptyControlFlowGraphReference()")
|
||||
useTypes(emptyCfgReferenceType)
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations(
|
||||
field = "typeRef",
|
||||
implementationPredicate = { it.type !in listOf("FirDelegatedTypeRefImpl", "FirTypeProjectionWithVarianceImpl") },
|
||||
fieldPredicate = { it.defaultValue == null }
|
||||
) {
|
||||
default(it, "FirImplicitTypeRefImpl(null)")
|
||||
useTypes(implicitTypeRefType)
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations(
|
||||
field = "resolvePhase",
|
||||
fieldPredicate = { it.defaultValue == null }
|
||||
) {
|
||||
default(it, "FirResolvePhase.RAW_FIR")
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations(
|
||||
field = "containerSource"
|
||||
) {
|
||||
default(it) {
|
||||
value = "null"
|
||||
isMutable = true
|
||||
}
|
||||
}
|
||||
|
||||
findImplementationsWithAnnotations {
|
||||
it.type !in setOf("FirDelegatedTypeRefImpl", "FirImplicitTypeRefImpl")
|
||||
}.forEach {
|
||||
it.addParent(abstractAnnotatedElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.*
|
||||
import java.io.File
|
||||
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val generationPath = args.firstOrNull()?.let { if (!it.endsWith("/")) "$it/" else it }
|
||||
if (generationPath == null) {
|
||||
println("Not enough arguments")
|
||||
return
|
||||
}
|
||||
|
||||
NodeConfigurator.configureFields()
|
||||
detectBaseTransformerTypes(FirTreeBuilder)
|
||||
ImplementationConfigurator.configureImplementations()
|
||||
removePreviousGeneratedFiles(generationPath)
|
||||
printElements(FirTreeBuilder, generationPath)
|
||||
// printTable(FirTreeBuilder)
|
||||
}
|
||||
|
||||
fun Element.traverseParents(block: (Element) -> Unit) {
|
||||
block(this)
|
||||
parents.forEach { it.traverseParents(block) }
|
||||
}
|
||||
|
||||
private fun detectBaseTransformerTypes(builder: AbstractFirTreeBuilder) {
|
||||
val usedAsFieldType = mutableMapOf<AbstractElement, Boolean>().withDefault { false }
|
||||
for (element in builder.elements) {
|
||||
for (field in element.allFirFields) {
|
||||
val fieldElement = when (field) {
|
||||
is FirField -> field.element
|
||||
is FieldList -> field.baseType as Element
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
usedAsFieldType[fieldElement] = true
|
||||
}
|
||||
}
|
||||
|
||||
for (element in builder.elements) {
|
||||
element.traverseParents {
|
||||
if (usedAsFieldType.getValue(it)) {
|
||||
element.baseTransformerType = it
|
||||
return@traverseParents
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun removePreviousGeneratedFiles(generationPath: String) {
|
||||
File(generationPath).walkTopDown().forEach {
|
||||
if (it.isFile && it.readText().contains(GENERATED_MESSAGE)) {
|
||||
it.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun printTable(builder: AbstractFirTreeBuilder) {
|
||||
val elements = builder.elements.filter { it.allImplementations.isNotEmpty() }
|
||||
val fields = elements.flatMapTo(mutableSetOf()) { it.allFields }
|
||||
|
||||
val mapping = mutableMapOf<Element, Set<Field>>()
|
||||
val fieldsCount = mutableMapOf<Field, Int>()
|
||||
for (element in elements) {
|
||||
val containingFields = mutableSetOf<Field>()
|
||||
for (field in fields) {
|
||||
if (field in element.allFields) {
|
||||
containingFields += field
|
||||
fieldsCount[field] = fieldsCount.getOrDefault(field, 0) + 1
|
||||
}
|
||||
}
|
||||
mapping[element] = containingFields
|
||||
}
|
||||
|
||||
val sortedFields = fields.sortedByDescending { fieldsCount[it] }
|
||||
File("compiler/fir/tree/table.csv").printWriter().use { printer ->
|
||||
with(printer) {
|
||||
val delim = ","
|
||||
print(delim)
|
||||
println(sortedFields.joinToString(delim) { "${it.name}:${fieldsCount.getValue(it)}" })
|
||||
for (element in elements) {
|
||||
print(element.name + delim)
|
||||
val containingFields = mapping.getValue(element)
|
||||
println(sortedFields.joinToString(delim) { if (it in containingFields) "+" else "-" })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+517
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
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
|
||||
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
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.receivers
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.returnTypeRef
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.status
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.superTypeRefs
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.symbol
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.symbolWithPackage
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.typeArguments
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.typeParameters
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.typeRefField
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.valueParameters
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.visibility
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFieldConfigurator
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.type
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.*
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
|
||||
object NodeConfigurator : AbstractFieldConfigurator() {
|
||||
fun configureFields() = with(FirTreeBuilder) {
|
||||
AbstractFirTreeBuilder.baseFirElement.configure {
|
||||
+field("psi", psiElementType, nullable = true)
|
||||
}
|
||||
|
||||
annotationContainer.configure {
|
||||
+annotations
|
||||
}
|
||||
|
||||
symbolOwner.configure {
|
||||
withArg("E", symbolOwner, declaration)
|
||||
+symbolWithPackage("fir.symbols", "AbstractFirBasedSymbol", "E")
|
||||
}
|
||||
|
||||
controlFlowGraphOwner.configure {
|
||||
+controlFlowGraphReferenceField.withTransform()
|
||||
}
|
||||
|
||||
typeParametersOwner.configure {
|
||||
+typeParameters
|
||||
}
|
||||
|
||||
resolvable.configure {
|
||||
+field("calleeReference", reference).withTransform()
|
||||
}
|
||||
|
||||
declaration.configure {
|
||||
+field("session", firSessionType)
|
||||
+field("resolvePhase", resolvePhaseType, withReplace = true).apply { isMutable = true }
|
||||
}
|
||||
|
||||
typedDeclaration.configure {
|
||||
+field("returnTypeRef", typeRef).withTransform()
|
||||
}
|
||||
|
||||
callableDeclaration.configure {
|
||||
withArg("F", "FirCallableDeclaration<F>")
|
||||
parentArg(symbolOwner, "E", "F")
|
||||
+field("receiverTypeRef", typeRef, nullable = true)
|
||||
+symbol("FirCallableSymbol", "F")
|
||||
}
|
||||
|
||||
callableMemberDeclaration.configure {
|
||||
withArg("F", "FirCallableMemberDeclaration<F>")
|
||||
parentArg(callableDeclaration, "F", "F")
|
||||
+field("containerSource", type(DeserializedContainerSource::class), nullable = true)
|
||||
}
|
||||
|
||||
namedDeclaration.configure {
|
||||
+name
|
||||
}
|
||||
|
||||
function.configure {
|
||||
withArg("F", "FirFunction<F>")
|
||||
parentArg(callableDeclaration, "F", "F")
|
||||
+symbol("FirFunctionSymbol", "F")
|
||||
+valueParameters.withTransform()
|
||||
+body(nullable = true)
|
||||
}
|
||||
|
||||
errorFunction.configure {
|
||||
parentArg(function, "F", errorFunction)
|
||||
+stringField("reason")
|
||||
+symbol("FirErrorFunctionSymbol")
|
||||
}
|
||||
|
||||
memberDeclaration.configure {
|
||||
+typeParameters
|
||||
+status
|
||||
}
|
||||
|
||||
expression.configure {
|
||||
+typeRefField
|
||||
+annotations
|
||||
}
|
||||
|
||||
call.configure {
|
||||
+arguments.withTransform()
|
||||
}
|
||||
|
||||
block.configure {
|
||||
+fieldList(statement)
|
||||
+typeRefField
|
||||
}
|
||||
|
||||
binaryLogicExpression.configure {
|
||||
+field("leftOperand", expression).withTransform()
|
||||
+field("rightOperand", expression).withTransform()
|
||||
+field("kind", operationKindType)
|
||||
needTransformOtherChildren()
|
||||
}
|
||||
|
||||
jump.configure {
|
||||
withArg("E", targetElement)
|
||||
+field("target", jumpTargetType.withArgs("E"))
|
||||
}
|
||||
|
||||
loopJump.configure {
|
||||
parentArg(jump, "E", loop)
|
||||
}
|
||||
|
||||
returnExpression.configure {
|
||||
parentArg(jump, "E", function.withArgs("F" to "*"))
|
||||
+field("result", expression)
|
||||
}
|
||||
|
||||
label.configure {
|
||||
+stringField("name")
|
||||
}
|
||||
|
||||
loop.configure {
|
||||
+field(block).withTransform()
|
||||
+field("condition", expression).withTransform()
|
||||
+field(label, nullable = true)
|
||||
needTransformOtherChildren()
|
||||
}
|
||||
|
||||
whileLoop.configure {
|
||||
+field("condition", expression).withTransform()
|
||||
+field(block).withTransform()
|
||||
}
|
||||
|
||||
catchClause.configure {
|
||||
+field("parameter", valueParameter).withTransform()
|
||||
+field(block).withTransform()
|
||||
needTransformOtherChildren()
|
||||
}
|
||||
|
||||
tryExpression.configure {
|
||||
+field("tryBlock", block).withTransform()
|
||||
+fieldList("catches", catchClause).withTransform()
|
||||
+field("finallyBlock", block, nullable = true).withTransform()
|
||||
needTransformOtherChildren()
|
||||
}
|
||||
|
||||
qualifiedAccessWithoutCallee.configure {
|
||||
+booleanField("safe")
|
||||
+receivers
|
||||
}
|
||||
|
||||
constExpression.configure {
|
||||
withArg("T")
|
||||
+field("kind", constKindType.withArgs("T"))
|
||||
+field("value", "T", null)
|
||||
}
|
||||
|
||||
functionCall.configure {
|
||||
+typeArguments
|
||||
+field("calleeReference", namedReference)
|
||||
}
|
||||
|
||||
operatorCall.configure {
|
||||
+field("operation", operationType)
|
||||
}
|
||||
|
||||
typeOperatorCall.configure {
|
||||
+field("operation", operationType)
|
||||
+field("conversionTypeRef", typeRef)
|
||||
}
|
||||
|
||||
whenBranch.configure {
|
||||
+field("condition", expression).withTransform()
|
||||
+field("result", block).withTransform()
|
||||
needTransformOtherChildren()
|
||||
}
|
||||
|
||||
klass.configure {
|
||||
+classKind
|
||||
+superTypeRefs(withReplace = true)
|
||||
+declarations
|
||||
+annotations
|
||||
}
|
||||
|
||||
classLikeDeclaration.configure {
|
||||
withArg("F", "FirClassLikeDeclaration<F>")
|
||||
parentArg(symbolOwner, "F", "F")
|
||||
+field("supertypesComputationStatus", type("fir.declarations", "SupertypesComputationStatus"), withReplace = true).apply { isMutable = true }
|
||||
+symbol("FirClassLikeSymbol", "F")
|
||||
}
|
||||
|
||||
regularClass.configure {
|
||||
parentArg(classLikeDeclaration, "F", regularClass)
|
||||
+symbol("FirClassSymbol")
|
||||
+field("companionObject", regularClass, nullable = true)
|
||||
+superTypeRefs(withReplace = true)
|
||||
}
|
||||
|
||||
typeAlias.configure {
|
||||
parentArg(classLikeDeclaration, "F", typeAlias)
|
||||
+symbol("FirTypeAliasSymbol")
|
||||
+field("expandedTypeRef", typeRef, withReplace = true)
|
||||
+annotations
|
||||
}
|
||||
|
||||
enumEntry.configure {
|
||||
+arguments.withTransform()
|
||||
+field(typeRef)
|
||||
}
|
||||
|
||||
anonymousFunction.configure {
|
||||
parentArg(function, "F", anonymousFunction)
|
||||
+symbol("FirAnonymousFunctionSymbol")
|
||||
+field(label, nullable = true)
|
||||
+field(invocationKindType, nullable = true, withReplace = true).apply {
|
||||
isMutable = true
|
||||
}
|
||||
}
|
||||
|
||||
typeParameter.configure {
|
||||
parentArg(symbolOwner, "F", typeParameter)
|
||||
+symbol("FirTypeParameterSymbol")
|
||||
+field(varianceType)
|
||||
+booleanField("isReified")
|
||||
+fieldList("bounds", typeRef)
|
||||
+annotations
|
||||
}
|
||||
|
||||
memberFunction.configure {
|
||||
withArg("F", memberFunction)
|
||||
parentArg(function, "F", "F")
|
||||
parentArg(callableMemberDeclaration, "F", "F")
|
||||
+symbol("FirFunctionSymbol", "F")
|
||||
+annotations
|
||||
}
|
||||
|
||||
simpleFunction.configure {
|
||||
parentArg(memberFunction, "F", simpleFunction)
|
||||
}
|
||||
|
||||
property.configure {
|
||||
parentArg(variable, "F", property)
|
||||
parentArg(callableMemberDeclaration, "F", property)
|
||||
+symbol("FirPropertySymbol")
|
||||
+field("backingFieldSymbol", backingFieldSymbolType)
|
||||
+booleanField("isLocal")
|
||||
+typeParameters
|
||||
+status
|
||||
}
|
||||
|
||||
propertyAccessor.configure {
|
||||
parentArg(function, "F", propertyAccessor)
|
||||
+symbol("FirPropertyAccessorSymbol")
|
||||
+booleanField("isGetter")
|
||||
+booleanField("isSetter")
|
||||
+status
|
||||
+annotations
|
||||
}
|
||||
|
||||
declarationStatus.configure {
|
||||
+visibility
|
||||
+modality
|
||||
generateBooleanFields(
|
||||
"expect", "actual", "override", "operator", "infix", "inline", "tailRec",
|
||||
"external", "const", "lateInit", "inner", "companion", "data", "suspend", "static"
|
||||
)
|
||||
}
|
||||
|
||||
constructor.configure {
|
||||
parentArg(memberFunction, "F", constructor)
|
||||
+symbol("FirConstructorSymbol")
|
||||
+field("delegatedConstructor", delegatedConstructorCall, nullable = true)
|
||||
+booleanField("isPrimary")
|
||||
}
|
||||
|
||||
delegatedConstructorCall.configure {
|
||||
+field("constructedTypeRef", typeRef)
|
||||
generateBooleanFields("this", "super")
|
||||
+calleeReference.withTransform()
|
||||
}
|
||||
|
||||
valueParameter.configure {
|
||||
parentArg(variable, "F", valueParameter)
|
||||
+field("defaultValue", expression, nullable = true)
|
||||
generateBooleanFields("crossinline", "noinline", "vararg")
|
||||
}
|
||||
|
||||
variable.configure {
|
||||
withArg("F", variable)
|
||||
parentArg(callableDeclaration, "F", "F")
|
||||
+symbol("FirVariableSymbol", "F")
|
||||
+initializer
|
||||
+field("delegate", expression, nullable = true)
|
||||
+field("delegateFieldSymbol", delegateFieldSymbolType, "F", nullable = true)
|
||||
generateBooleanFields("var", "val")
|
||||
+field("getter", propertyAccessor, nullable = true).withTransform()
|
||||
+field("setter", propertyAccessor, nullable = true).withTransform()
|
||||
+annotations
|
||||
needTransformOtherChildren()
|
||||
}
|
||||
|
||||
field.configure {
|
||||
parentArg(variable, "F", field)
|
||||
parentArg(callableMemberDeclaration, "F", field)
|
||||
}
|
||||
|
||||
anonymousInitializer.configure {
|
||||
+body(nullable = true)
|
||||
}
|
||||
|
||||
file.configure {
|
||||
+fieldList(import)
|
||||
+declarations
|
||||
+stringField("name")
|
||||
+field("packageFqName", fqNameType)
|
||||
}
|
||||
|
||||
import.configure {
|
||||
+field("importedFqName", fqNameType, nullable = true)
|
||||
+booleanField("isAllUnder")
|
||||
+field("aliasName", nameType, nullable = true)
|
||||
}
|
||||
|
||||
resolvedImport.configure {
|
||||
+field("delegate", import)
|
||||
+field("packageFqName", fqNameType)
|
||||
+field("relativeClassName", fqNameType, nullable = true)
|
||||
+field("resolvedClassId", classIdType, nullable = true)
|
||||
+field(
|
||||
"importedName",
|
||||
nameType,
|
||||
nullable = true
|
||||
)
|
||||
}
|
||||
|
||||
annotationCall.configure {
|
||||
+field("useSiteTarget", annotationUseSiteTargetType, nullable = true)
|
||||
+field("annotationTypeRef", typeRef)
|
||||
}
|
||||
|
||||
arraySetCall.configure {
|
||||
+field("rValue", expression).withTransform()
|
||||
+field("operation", operationType)
|
||||
+field("lValue", reference)
|
||||
+fieldList("indexes", expression).withTransform()
|
||||
}
|
||||
|
||||
classReferenceExpression.configure {
|
||||
+field("classTypeRef", typeRef)
|
||||
}
|
||||
|
||||
componentCall.configure {
|
||||
+field("explicitReceiver", expression)
|
||||
+intField("componentIndex")
|
||||
}
|
||||
|
||||
errorExpression.configure {
|
||||
+stringField("reason")
|
||||
}
|
||||
|
||||
expressionWithSmartcast.configure {
|
||||
+field("originalExpression", qualifiedAccessExpression)
|
||||
+field("typesFromSmartcast", "Collection<ConeKotlinType>", null, customType = coneKotlinTypeType)
|
||||
+field("originalType", typeRef)
|
||||
}
|
||||
|
||||
getClassCall.configure {
|
||||
+field("argument", expression)
|
||||
}
|
||||
|
||||
wrappedArgumentExpression.configure {
|
||||
+booleanField("isSpread")
|
||||
}
|
||||
|
||||
namedArgumentExpression.configure {
|
||||
+name
|
||||
}
|
||||
|
||||
resolvedQualifier.configure {
|
||||
+field("packageFqName", fqNameType)
|
||||
+field("relativeClassFqName", fqNameType, nullable = true)
|
||||
+field("classId", classIdType, nullable = true)
|
||||
}
|
||||
|
||||
stringConcatenationCall.configure {
|
||||
}
|
||||
|
||||
throwExpression.configure {
|
||||
+field("exception", expression)
|
||||
}
|
||||
|
||||
variableAssignment.configure {
|
||||
+field("lValue", reference)
|
||||
+field("rValue", expression).withTransform()
|
||||
+field("operation", operationType)
|
||||
}
|
||||
|
||||
whenSubjectExpression.configure {
|
||||
+field("whenSubject", whenSubjectType)
|
||||
}
|
||||
|
||||
wrappedExpression.configure {
|
||||
+field(expression)
|
||||
}
|
||||
|
||||
wrappedDelegateExpression.configure {
|
||||
+field("delegateProvider", expression)
|
||||
}
|
||||
|
||||
namedReference.configure {
|
||||
+name
|
||||
+field("candidateSymbol", abstractFirBasedSymbolType, "*", nullable = true)
|
||||
}
|
||||
|
||||
resolvedCallableReference.configure {
|
||||
+field("resolvedSymbol", abstractFirBasedSymbolType, "*")
|
||||
}
|
||||
|
||||
delegateFieldReference.configure {
|
||||
+field("resolvedSymbol", delegateFieldSymbolType.withArgs("*"))
|
||||
}
|
||||
|
||||
backingFieldReference.configure {
|
||||
+field("resolvedSymbol", backingFieldSymbolType)
|
||||
}
|
||||
|
||||
superReference.configure {
|
||||
+field("superTypeRef", typeRef, withReplace = true)
|
||||
}
|
||||
|
||||
thisReference.configure {
|
||||
+stringField("labelName", nullable = true)
|
||||
+field("boundSymbol", abstractFirBasedSymbolType, "*", nullable = true, withReplace = true)
|
||||
}
|
||||
|
||||
typeRef.configure {
|
||||
+annotations
|
||||
}
|
||||
|
||||
resolvedTypeRef.configure {
|
||||
+field("type", coneKotlinTypeType)
|
||||
}
|
||||
|
||||
errorTypeRef.configure {
|
||||
+stringField("reason")
|
||||
}
|
||||
|
||||
delegatedTypeRef.configure {
|
||||
+field("delegate", expression, nullable = true)
|
||||
+field(typeRef)
|
||||
}
|
||||
|
||||
typeRefWithNullability.configure {
|
||||
+booleanField("isMarkedNullable")
|
||||
}
|
||||
|
||||
userTypeRef.configure {
|
||||
+fieldList("qualifier", firQualifierPartType)
|
||||
}
|
||||
|
||||
functionTypeRef.configure {
|
||||
+field("receiverTypeRef", typeRef, nullable = true)
|
||||
+valueParameters
|
||||
+returnTypeRef
|
||||
}
|
||||
|
||||
thisReceiverExpression.configure {
|
||||
+field("calleeReference", thisReference)
|
||||
}
|
||||
|
||||
whenExpression.configure {
|
||||
+field("subject", expression, nullable = true).withTransform()
|
||||
+field("subjectVariable", variable.withArgs("F" to "*"), nullable = true)
|
||||
+fieldList("branches", whenBranch).withTransform()
|
||||
needTransformOtherChildren()
|
||||
}
|
||||
|
||||
typeProjectionWithVariance.configure {
|
||||
+field(typeRef)
|
||||
+field(varianceType)
|
||||
}
|
||||
|
||||
errorNamedReference.configure {
|
||||
+stringField("errorReason")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Element.withArgs(vararg replacements: Pair<String, String>): AbstractElement {
|
||||
val replaceMap = replacements.toMap()
|
||||
val newArguments = typeArguments.map { replaceMap[it.name]?.let { SimpleTypeArgument(it, null) } ?: it }
|
||||
return ElementWithArguments(this, newArguments)
|
||||
}
|
||||
+725
@@ -0,0 +1,725 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.*
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
|
||||
val COPYRIGHT = """
|
||||
/*
|
||||
* Copyright 2010-${GregorianCalendar()[Calendar.YEAR]} 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.
|
||||
*/
|
||||
""".trimIndent()
|
||||
|
||||
const val BASE_PACKAGE = "org.jetbrains.kotlin.fir"
|
||||
//const val BASE_PATH = "compiler/fir/tree/src/"
|
||||
private const val VISITOR_PACKAGE = "org.jetbrains.kotlin.fir.visitors"
|
||||
private const val INDENT = " "
|
||||
val GENERATED_MESSAGE = """
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
""".trimIndent()
|
||||
|
||||
fun printElements(builder: AbstractFirTreeBuilder, generationPath: String) {
|
||||
builder.elements.forEach { it.generateCode(generationPath) }
|
||||
builder.elements.flatMap { it.allImplementations }.forEach { it.generateCode(generationPath) }
|
||||
|
||||
printVisitor(builder.elements, generationPath)
|
||||
printVisitorVoid(builder.elements, generationPath)
|
||||
printTransformer(builder.elements, generationPath)
|
||||
}
|
||||
|
||||
fun PrintWriter.printCopyright() {
|
||||
println(COPYRIGHT)
|
||||
println()
|
||||
}
|
||||
|
||||
fun PrintWriter.printGeneratedMessage() {
|
||||
println(GENERATED_MESSAGE)
|
||||
println()
|
||||
}
|
||||
|
||||
fun printVisitor(elements: List<Element>, generationPath: String) {
|
||||
val dir = File(generationPath + VISITOR_PACKAGE.replace(".", "/"))
|
||||
dir.mkdirs()
|
||||
File(dir, "FirVisitor.kt").printWriter().use { printer ->
|
||||
with(printer) {
|
||||
printCopyright()
|
||||
println("package $VISITOR_PACKAGE")
|
||||
println()
|
||||
elements.forEach { println("import ${it.fullQualifiedName}") }
|
||||
println()
|
||||
printGeneratedMessage()
|
||||
|
||||
println("abstract class FirVisitor<out R, in D> {")
|
||||
|
||||
indent()
|
||||
println("abstract fun visitElement(element: FirElement, data: D): R")
|
||||
println()
|
||||
for (element in elements) {
|
||||
if (element == AbstractFirTreeBuilder.baseFirElement) continue
|
||||
with(element) {
|
||||
indent()
|
||||
val varName = safeDecapitalizedName
|
||||
println("open fun ${typeParameters}visit$name($varName: $typeWithArguments, data: D): R${multipleUpperBoundsList()} = visitElement($varName, data)")
|
||||
println()
|
||||
}
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun printVisitorVoid(elements: List<Element>, generationPath: String) {
|
||||
val dir = File(generationPath + VISITOR_PACKAGE.replace(".", "/"))
|
||||
dir.mkdirs()
|
||||
File(dir, "FirVisitorVoid.kt").printWriter().use { printer ->
|
||||
with(printer) {
|
||||
printCopyright()
|
||||
println("package $VISITOR_PACKAGE")
|
||||
println()
|
||||
elements.forEach { println("import ${it.fullQualifiedName}") }
|
||||
println()
|
||||
printGeneratedMessage()
|
||||
|
||||
println("abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {")
|
||||
|
||||
indent()
|
||||
println("abstract fun visitElement(element: FirElement)")
|
||||
println()
|
||||
for (element in elements) {
|
||||
if (element == AbstractFirTreeBuilder.baseFirElement) continue
|
||||
with(element) {
|
||||
indent()
|
||||
val varName = safeDecapitalizedName
|
||||
println("open fun ${typeParameters}visit$name($varName: $typeWithArguments)${multipleUpperBoundsList()}{")
|
||||
indent(2)
|
||||
println("visitElement($varName)")
|
||||
indent()
|
||||
println("}")
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
for (element in elements) {
|
||||
with(element) {
|
||||
indent()
|
||||
val varName = safeDecapitalizedName
|
||||
println("final override fun ${typeParameters}visit$name($varName: $typeWithArguments, data: Nothing?)${multipleUpperBoundsList()}{")
|
||||
indent(2)
|
||||
println("visit$name($varName)")
|
||||
indent()
|
||||
println("}")
|
||||
println()
|
||||
}
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Element.generateCode(generationPath: String) {
|
||||
val dir = File(generationPath + packageName.replace(".", "/"))
|
||||
dir.mkdirs()
|
||||
val file = File(dir, "$type.kt")
|
||||
file.printWriter().use { printer ->
|
||||
with(printer) {
|
||||
printCopyright()
|
||||
println("package $packageName")
|
||||
println()
|
||||
val imports = collectImports()
|
||||
imports.forEach { println("import $it") }
|
||||
if (imports.isNotEmpty()) {
|
||||
println()
|
||||
}
|
||||
printGeneratedMessage()
|
||||
printElement(this@generateCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Implementation.generateCode(generationPath: String) {
|
||||
val dir = File(generationPath + packageName.replace(".", "/"))
|
||||
dir.mkdirs()
|
||||
val file = File(dir, "$type.kt")
|
||||
file.printWriter().use { printer ->
|
||||
with(printer) {
|
||||
printCopyright()
|
||||
println("package $packageName")
|
||||
println()
|
||||
val imports = collectImports()
|
||||
imports.forEach { println("import $it") }
|
||||
if (imports.isNotEmpty()) {
|
||||
println()
|
||||
}
|
||||
printGeneratedMessage()
|
||||
printImplementation(this@generateCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Implementation.collectImports(): List<String> {
|
||||
return element.collectImportsInternal(
|
||||
listOf(element.fullQualifiedName) + usedTypes.mapNotNull { it.fullQualifiedName } + parents.mapNotNull { it.fullQualifiedName },
|
||||
isImpl = true
|
||||
)
|
||||
}
|
||||
|
||||
fun Element.collectImports(): List<String> {
|
||||
val baseTypes = parents.mapTo(mutableListOf()) { it.fullQualifiedName }
|
||||
baseTypes += parentsArguments.values.flatMap { it.values }.mapNotNull { it.fullQualifiedName }
|
||||
val isBaseFirElement = this == AbstractFirTreeBuilder.baseFirElement
|
||||
if (isBaseFirElement) {
|
||||
baseTypes += compositeTransformResultType.fullQualifiedName!!
|
||||
}
|
||||
return collectImportsInternal(
|
||||
baseTypes,
|
||||
isImpl = false
|
||||
)
|
||||
}
|
||||
|
||||
fun Element.collectImportsInternal(base: List<String>, isImpl: Boolean): List<String> {
|
||||
val fqns = base + allFields.mapNotNull { it.fullQualifiedName } +
|
||||
allFields.flatMap { it.arguments.mapNotNull { it.fullQualifiedName } } +
|
||||
typeArguments.flatMap { it.upperBounds.mapNotNull { it.fullQualifiedName } }
|
||||
val realPackageName = if (isImpl) "$packageName.impl." else "$packageName."
|
||||
return fqns.filter { fqn ->
|
||||
fqn.dropLastWhile { it != '.' } != realPackageName
|
||||
}.distinct().sorted() + "$VISITOR_PACKAGE.*"
|
||||
}
|
||||
|
||||
val Field.isVal: Boolean get() = this is FieldList || (this is FieldWithDefault && origin is FieldList) || !isMutable
|
||||
|
||||
fun PrintWriter.printFieldWithDefaultInImplementation(field: Field) {
|
||||
val defaultValue = field.defaultValue
|
||||
indent()
|
||||
print("override ")
|
||||
if (field.isLateinit) {
|
||||
print("lateinit ")
|
||||
}
|
||||
if (field.isVal) {
|
||||
print("val")
|
||||
} else {
|
||||
print("var")
|
||||
}
|
||||
print(" ${field.name}: ${field.mutableType}")
|
||||
if (field.isLateinit) {
|
||||
println()
|
||||
return
|
||||
} else {
|
||||
print(" ")
|
||||
}
|
||||
if (field.withGetter) {
|
||||
if (field.customSetter != null) {
|
||||
println()
|
||||
indent(2)
|
||||
}
|
||||
print("get() ")
|
||||
}
|
||||
requireNotNull(defaultValue) {
|
||||
"No default value for $field"
|
||||
}
|
||||
println("= $defaultValue")
|
||||
field.customSetter?.let {
|
||||
indent(2)
|
||||
println("set(value) {")
|
||||
indent(3)
|
||||
println(it)
|
||||
indent(2)
|
||||
println("}")
|
||||
}
|
||||
}
|
||||
|
||||
fun PrintWriter.printImplementation(implementation: Implementation) {
|
||||
fun Field.transform() {
|
||||
when (this) {
|
||||
is FieldWithDefault -> origin.transform()
|
||||
|
||||
is FirField ->
|
||||
println("$name = ${name}${call()}transformSingle(transformer, data)")
|
||||
|
||||
is FieldList -> {
|
||||
println("${name}.transformInplace(transformer, data)")
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
|
||||
with(implementation) {
|
||||
print("${kind.title} $type")
|
||||
print(element.typeParameters)
|
||||
val fieldsWithoutDefault = allFields.filter { it.defaultValue == null && !it.isLateinit }
|
||||
val fieldsWithDefault = allFields.filter { it.defaultValue != null || it.isLateinit }
|
||||
|
||||
if (kind != Implementation.Kind.Interface && fieldsWithoutDefault.isNotEmpty()) {
|
||||
println("(")
|
||||
fieldsWithoutDefault.forEachIndexed { i, field ->
|
||||
val end = if (i == fieldsWithoutDefault.size - 1) "" else ","
|
||||
printField(field, isImplementation = true, override = true, end = end)
|
||||
}
|
||||
print(")")
|
||||
}
|
||||
|
||||
print(" : ${element.typeWithArguments}")
|
||||
parents.forEach {
|
||||
print(", ${it.typeWithArguments}")
|
||||
}
|
||||
println(" {")
|
||||
|
||||
if (kind == Implementation.Kind.Interface) {
|
||||
allFields.forEach { printField(it, isImplementation = true, override = true, end = "") }
|
||||
} else {
|
||||
fieldsWithDefault.forEach {
|
||||
printFieldWithDefaultInImplementation(it)
|
||||
}
|
||||
if (fieldsWithDefault.isNotEmpty()) {
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
element.allFields.filter { it.type.contains("Symbol") }
|
||||
.takeIf { it.isNotEmpty() && kind != Implementation.Kind.Interface && !element.type.contains("Reference")}
|
||||
?.let { symbolFields ->
|
||||
indent(1)
|
||||
println("init {")
|
||||
for (symbolField in symbolFields) {
|
||||
indent(2)
|
||||
println("${symbolField.name}${symbolField.call()}bind(this)")
|
||||
}
|
||||
indent(1)
|
||||
println("}")
|
||||
println()
|
||||
}
|
||||
|
||||
indent(1)
|
||||
print("override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {")
|
||||
|
||||
fun Field.acceptString(): String = "${name}${call()}accept(visitor, data)"
|
||||
|
||||
if (element.allFirFields.isNotEmpty()) {
|
||||
println()
|
||||
for (field in allFields.filter { it.isFirType }) {
|
||||
if (field.withGetter || !field.needAcceptAndTransform) continue
|
||||
when (field.name) {
|
||||
"explicitReceiver" -> {
|
||||
val explicitReceiver = implementation["explicitReceiver"]!!
|
||||
val dispatchReceiver = implementation["dispatchReceiver"]!!
|
||||
val extensionReceiver = implementation["extensionReceiver"]!!
|
||||
println("""
|
||||
| ${explicitReceiver.acceptString()}
|
||||
| if (dispatchReceiver !== explicitReceiver) {
|
||||
| ${dispatchReceiver.acceptString()}
|
||||
| }
|
||||
| if (extensionReceiver !== explicitReceiver && extensionReceiver !== dispatchReceiver) {
|
||||
| ${extensionReceiver.acceptString()}
|
||||
| }
|
||||
""".trimMargin())
|
||||
}
|
||||
|
||||
"dispatchReceiver", "extensionReceiver", "subjectVariable" -> {}
|
||||
"companionObject" -> {}
|
||||
|
||||
else -> {
|
||||
if (type == "FirClassImpl" && field.name == "declarations") {
|
||||
indent(2)
|
||||
println("(declarations.firstOrNull { it is FirConstructorImpl } as? FirConstructorImpl)?.typeParameters?.forEach { it.accept(visitor, data) }")
|
||||
}
|
||||
if (type == "FirWhenExpressionImpl" && field.name == "subject") {
|
||||
println(
|
||||
"""
|
||||
| if (subjectVariable != null) {
|
||||
| subjectVariable.accept(visitor, data)
|
||||
| } else {
|
||||
| subject?.accept(visitor, data)
|
||||
| }
|
||||
""".trimMargin()
|
||||
)
|
||||
} else {
|
||||
indent(2)
|
||||
when (field.origin) {
|
||||
is FirField -> {
|
||||
println(field.acceptString())
|
||||
}
|
||||
|
||||
is FieldList -> {
|
||||
println("${field.name}.forEach { it.accept(visitor, data) }")
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
indent()
|
||||
}
|
||||
println("}")
|
||||
println()
|
||||
|
||||
indent()
|
||||
println("override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): $typeWithArguments {")
|
||||
for (field in allFields) {
|
||||
when {
|
||||
!field.isMutable || !field.isFirType || field.withGetter || !field.needAcceptAndTransform -> {}
|
||||
field.name == "explicitReceiver" -> {
|
||||
val explicitReceiver = implementation["explicitReceiver"]!!
|
||||
val dispatchReceiver = implementation["dispatchReceiver"]!!
|
||||
val extensionReceiver = implementation["extensionReceiver"]!!
|
||||
if (explicitReceiver.isMutable) {
|
||||
indent(2)
|
||||
println("explicitReceiver = explicitReceiver${explicitReceiver.call()}transformSingle(transformer, data)")
|
||||
}
|
||||
if (dispatchReceiver.isMutable) {
|
||||
println("""
|
||||
| if (dispatchReceiver !== explicitReceiver) {
|
||||
| dispatchReceiver = dispatchReceiver.transformSingle(transformer, data)
|
||||
| }
|
||||
""".trimMargin())
|
||||
}
|
||||
if (extensionReceiver.isMutable) {
|
||||
println("""
|
||||
| if (extensionReceiver !== explicitReceiver && extensionReceiver !== dispatchReceiver) {
|
||||
| extensionReceiver = extensionReceiver.transformSingle(transformer, data)
|
||||
| }
|
||||
""".trimMargin())
|
||||
}
|
||||
}
|
||||
field.name in setOf("dispatchReceiver", "extensionReceiver") -> {}
|
||||
type == "FirClassImpl" && field.name == "declarations" -> {
|
||||
indent(2)
|
||||
println("(declarations.firstOrNull { it is FirConstructorImpl } as? FirConstructorImpl)?.typeParameters?.transformInplace(transformer, data)")
|
||||
indent(2)
|
||||
println("declarations.transformInplace(transformer, data)")
|
||||
}
|
||||
field.name == "companionObject" -> {
|
||||
indent(2)
|
||||
println("companionObject = declarations.asSequence().filterIsInstance<FirRegularClass>().firstOrNull { it.status.isCompanion }")
|
||||
}
|
||||
field.needsSeparateTransform -> {
|
||||
indent(2)
|
||||
println("transform${field.name.capitalize()}(transformer, data)")
|
||||
}
|
||||
!element.needTransformOtherChildren -> {
|
||||
indent(2)
|
||||
field.transform()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
if (element.needTransformOtherChildren) {
|
||||
indent(2)
|
||||
println("transformOtherChildren(transformer, data)")
|
||||
}
|
||||
indent(2)
|
||||
println("return this")
|
||||
indent()
|
||||
println("}")
|
||||
|
||||
for (field in allFields) {
|
||||
if (!field.needsSeparateTransform) continue
|
||||
println()
|
||||
indent()
|
||||
print("override ${field.transformFunctionDeclaration(typeWithArguments)} {")
|
||||
println()
|
||||
if (field.isMutable && field.isFirType) {
|
||||
// TODO: replace with smth normal
|
||||
if (type == "FirWhenExpressionImpl" && field.name == "subject") {
|
||||
println("""
|
||||
| if (subjectVariable != null) {
|
||||
| subjectVariable = subjectVariable?.transformSingle(transformer, data)
|
||||
| } else {
|
||||
| subject = subject?.transformSingle(transformer, data)
|
||||
| }
|
||||
""".trimMargin())
|
||||
} else {
|
||||
indent(2)
|
||||
field.transform()
|
||||
}
|
||||
}
|
||||
indent(2)
|
||||
println("return this")
|
||||
indent()
|
||||
println("}")
|
||||
}
|
||||
|
||||
if (element.needTransformOtherChildren) {
|
||||
println()
|
||||
indent()
|
||||
println("override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): $typeWithArguments {")
|
||||
for (field in allFields) {
|
||||
if (!field.isMutable || !field.isFirType || field.name == "subjectVariable") continue
|
||||
if (!field.needsSeparateTransform) {
|
||||
indent(2)
|
||||
field.transform()
|
||||
}
|
||||
}
|
||||
indent(2)
|
||||
println("return this")
|
||||
indent()
|
||||
println("}")
|
||||
}
|
||||
|
||||
for (field in allFields.filter { it.withReplace }) {
|
||||
println()
|
||||
indent()
|
||||
print("override ${field.replaceFunctionDeclaration()} {")
|
||||
if (!field.isMutable) {
|
||||
println("}")
|
||||
continue
|
||||
}
|
||||
println()
|
||||
indent(2)
|
||||
val newValue = "new${field.name.capitalize()}"
|
||||
when {
|
||||
field.withGetter -> {
|
||||
}
|
||||
|
||||
field.origin is FieldList -> {
|
||||
println("${field.name}.clear()")
|
||||
indent(2)
|
||||
println("${field.name}.addAll($newValue)")
|
||||
}
|
||||
|
||||
else -> {
|
||||
println("${field.name} = $newValue")
|
||||
}
|
||||
}
|
||||
indent()
|
||||
println("}")
|
||||
}
|
||||
|
||||
print("}")
|
||||
}
|
||||
}
|
||||
|
||||
fun Field.transformFunctionDeclaration(returnType: String): String {
|
||||
return transformFunctionDeclaration(name.capitalize(), returnType)
|
||||
}
|
||||
|
||||
fun transformFunctionDeclaration(transformName: String, returnType: String): String {
|
||||
return "fun <D> transform$transformName(transformer: FirTransformer<D>, data: D): $returnType"
|
||||
}
|
||||
|
||||
fun Field.replaceFunctionDeclaration(): String {
|
||||
val capName = name.capitalize()
|
||||
return "fun replace$capName(new$capName: $typeWithArgumentsWithoutNullablity)"
|
||||
}
|
||||
|
||||
fun printTransformer(elements: List<Element>, generationPath: String) {
|
||||
val dir = File(generationPath + VISITOR_PACKAGE.replace(".", "/"))
|
||||
dir.mkdirs()
|
||||
File(dir, "FirTransformer.kt").printWriter().use { printer ->
|
||||
with(printer) {
|
||||
printCopyright()
|
||||
println("package $VISITOR_PACKAGE")
|
||||
println()
|
||||
elements.forEach { println("import ${it.fullQualifiedName}") }
|
||||
println("import ${compositeTransformResultType.fullQualifiedName}")
|
||||
println()
|
||||
printGeneratedMessage()
|
||||
|
||||
println("abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirElement>, D>() {")
|
||||
println()
|
||||
indent()
|
||||
println("abstract fun <E : FirElement> transformElement(element: E, data: D): CompositeTransformResult<E>")
|
||||
println()
|
||||
for (element in elements) {
|
||||
if (element == AbstractFirTreeBuilder.baseFirElement) continue
|
||||
indent()
|
||||
val varName = element.safeDecapitalizedName
|
||||
print("open fun ")
|
||||
element.typeParameters.takeIf { it.isNotBlank() }?.let { print(it) }
|
||||
println("transform${element.name}($varName: ${element.typeWithArguments}, data: D): CompositeTransformResult<${element.transformerType.typeWithArguments}>${element.multipleUpperBoundsList()}{")
|
||||
indent(2)
|
||||
println("return transformElement($varName, data)")
|
||||
indent()
|
||||
println("}")
|
||||
println()
|
||||
}
|
||||
|
||||
for (element in elements) {
|
||||
indent()
|
||||
val varName = element.safeDecapitalizedName
|
||||
print("final override fun ")
|
||||
element.typeParameters.takeIf { it.isNotBlank() }?.let { print(it) }
|
||||
|
||||
println("visit${element.name}($varName: ${element.typeWithArguments}, data: D): CompositeTransformResult<${element.transformerType.typeWithArguments}>${element.multipleUpperBoundsList()}{")
|
||||
indent(2)
|
||||
println("return transform${element.name}($varName, data)")
|
||||
indent()
|
||||
println("}")
|
||||
println()
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun PrintWriter.printField(field: Field, isImplementation: Boolean, override: Boolean, end: String) {
|
||||
indent()
|
||||
if (override) {
|
||||
print("override ")
|
||||
}
|
||||
if (!isImplementation || field.isVal) {
|
||||
print("val")
|
||||
} else {
|
||||
print("var")
|
||||
}
|
||||
val type = if (isImplementation) field.mutableType else field.typeWithArguments
|
||||
println(" ${field.name}: $type$end")
|
||||
}
|
||||
|
||||
val Field.mutableType: String get() = when (this) {
|
||||
is FieldList -> if (isMutable) "Mutable$typeWithArguments" else typeWithArguments
|
||||
is FieldWithDefault -> if (isMutable) origin.mutableType else typeWithArguments
|
||||
else -> typeWithArguments
|
||||
}
|
||||
|
||||
fun Field.call(): String = if (nullable) "?." else "."
|
||||
|
||||
fun Element.multipleUpperBoundsList(): String {
|
||||
return typeArguments.filterIsInstance<TypeArgumentWithMultipleUpperBounds>().takeIf { it.isNotEmpty() }?.let { arguments ->
|
||||
val upperBoundsList = arguments.joinToString(", ", postfix = " ") { argument ->
|
||||
argument.upperBounds.joinToString(", ") { upperBound -> "${argument.name} : ${upperBound.typeWithArguments}" }
|
||||
}
|
||||
" where $upperBoundsList"
|
||||
} ?: " "
|
||||
}
|
||||
|
||||
fun PrintWriter.printElement(element: Element) {
|
||||
fun Element.override() {
|
||||
indent()
|
||||
if (this != AbstractFirTreeBuilder.baseFirElement) {
|
||||
print("override ")
|
||||
}
|
||||
}
|
||||
|
||||
with(element) {
|
||||
print("interface $type")
|
||||
if (typeArguments.isNotEmpty()) {
|
||||
print(typeArguments.joinToString(", ", "<", ">") { it.toString() })
|
||||
}
|
||||
if (parents.isNotEmpty()) {
|
||||
print(" : ")
|
||||
print(parents.joinToString(", ") {
|
||||
var result = it.type
|
||||
parentsArguments[it]?.let { arguments ->
|
||||
result += arguments.values.joinToString(", ", "<", ">") { it.typeWithArguments }
|
||||
}
|
||||
result
|
||||
})
|
||||
}
|
||||
print(multipleUpperBoundsList())
|
||||
println("{")
|
||||
allFields.forEach {
|
||||
printField(it, isImplementation = false, override = it.fromParent, end = "")
|
||||
}
|
||||
if (allFields.isNotEmpty()) {
|
||||
println()
|
||||
}
|
||||
|
||||
override()
|
||||
println("fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visit$name(this, data)")
|
||||
|
||||
fields.filter { it.withReplace }.forEach {
|
||||
println()
|
||||
indent()
|
||||
if (it.fromParent) print("override ")
|
||||
println(it.replaceFunctionDeclaration())
|
||||
}
|
||||
|
||||
for (field in allFields) {
|
||||
if (!field.needsSeparateTransform) continue
|
||||
println()
|
||||
indent()
|
||||
if (field.fromParent) {
|
||||
print("override ")
|
||||
}
|
||||
println(field.transformFunctionDeclaration(typeWithArguments))
|
||||
}
|
||||
if (needTransformOtherChildren) {
|
||||
println()
|
||||
indent()
|
||||
if (element.parents.any { it.needTransformOtherChildren }) {
|
||||
print("override ")
|
||||
}
|
||||
println(transformFunctionDeclaration("OtherChildren", typeWithArguments))
|
||||
}
|
||||
|
||||
if (element == AbstractFirTreeBuilder.baseFirElement) {
|
||||
println()
|
||||
indent()
|
||||
println("fun accept(visitor: FirVisitorVoid) = accept(visitor, null)")
|
||||
println()
|
||||
indent()
|
||||
println("fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D)")
|
||||
println()
|
||||
indent()
|
||||
println("fun acceptChildren(visitor: FirVisitorVoid) = acceptChildren(visitor, null)")
|
||||
println()
|
||||
indent()
|
||||
println("@Suppress(\"UNCHECKED_CAST\")")
|
||||
indent()
|
||||
println("fun <E : FirElement, D> transform(visitor: FirTransformer<D>, data: D): CompositeTransformResult<E> =")
|
||||
indent(2)
|
||||
println("accept(visitor, data) as CompositeTransformResult<E>")
|
||||
println()
|
||||
indent()
|
||||
println("fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement")
|
||||
}
|
||||
print("}")
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------- Helpers ---------------------------------------
|
||||
|
||||
fun PrintWriter.indent(n: Int = 1) {
|
||||
print(INDENT.repeat(n))
|
||||
}
|
||||
|
||||
val Element.safeDecapitalizedName: String get() = if (name == "Class") "klass" else name.decapitalize()
|
||||
|
||||
val Importable.typeWithArguments: String
|
||||
get() = when (this) {
|
||||
is AbstractElement -> type + generics
|
||||
is Implementation -> type + element.generics
|
||||
is FirField -> element.typeWithArguments + if (nullable) "?" else ""
|
||||
is Field -> type + generics + if (nullable) "?" else ""
|
||||
is Type -> type + generics
|
||||
is ImplementationWithArg -> type + generics
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
val Importable.typeWithArgumentsWithoutNullablity: String get() = typeWithArguments.dropLastWhile { it == '?' }
|
||||
|
||||
val ImplementationWithArg.generics: String
|
||||
get() = argument?.let { "<${it.type}>" } ?: ""
|
||||
|
||||
val AbstractElement.generics: String
|
||||
get() = typeArguments.takeIf { it.isNotEmpty() }
|
||||
?.let { it.joinToString(", ", "<", ">") { it.name } }
|
||||
?: ""
|
||||
|
||||
val Field.generics: String
|
||||
get() = arguments.takeIf { it.isNotEmpty() }
|
||||
?.let { it.joinToString(", ", "<", ">") { it.typeWithArguments } }
|
||||
?: ""
|
||||
|
||||
val Element.typeParameters: String
|
||||
get() = typeArguments.takeIf { it.isNotEmpty() }
|
||||
?.joinToString(", ", "<", "> ")
|
||||
?: ""
|
||||
|
||||
val Type.generics: String
|
||||
get() = arguments.takeIf { it.isNotEmpty() }?.joinToString(",", "<", ">") ?: ""
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.generatedType
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.type
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
val psiElementType = type(PsiElement::class)
|
||||
val jumpTargetType = type("fir", "FirTarget")
|
||||
val constKindType = type(IrConstKind::class)
|
||||
val operationType = type("fir.expressions", "FirOperation")
|
||||
val classKindType = type(ClassKind::class)
|
||||
val invocationKindType = type(InvocationKind::class)
|
||||
val varianceType = type(Variance::class)
|
||||
val nameType = type(Name::class)
|
||||
val visibilityType = type(Visibility::class)
|
||||
val visibilitiesType = type(Visibilities::class)
|
||||
val modalityType = type(Modality::class)
|
||||
val fqNameType = type(FqName::class)
|
||||
val classIdType = type(ClassId::class)
|
||||
val annotationUseSiteTargetType = type(AnnotationUseSiteTarget::class)
|
||||
val operationKindType = type("fir.expressions", "LogicOperationKind")
|
||||
val coneKotlinTypeType = type(ConeKotlinType::class)
|
||||
val whenSubjectType = type("fir", "FirWhenSubject")
|
||||
val firSessionType = type("fir", "FirSession")
|
||||
val emptyCfgReferenceType = generatedType("references.impl", "FirEmptyControlFlowGraphReference")
|
||||
val noReceiverExpressionType = generatedType("expressions.impl", "FirNoReceiverExpression")
|
||||
val implicitTypeRefType = generatedType("types.impl", "FirImplicitTypeRefImpl")
|
||||
val firQualifierPartType = type("fir.types", "FirQualifierPart")
|
||||
val coneClassErrorTypeType = type(ConeClassErrorType::class)
|
||||
val simpleNamedReferenceType = generatedType("references.impl", "FirSimpleNamedReference")
|
||||
val explicitThisReferenceType = generatedType("references.impl", "FirExplicitThisReference")
|
||||
val explicitSuperReferenceType = generatedType("references.impl", "FirExplicitSuperReference")
|
||||
val implicitBooleanTypeRefType = generatedType("types.impl", "FirImplicitBooleanTypeRef")
|
||||
val implicitNothingTypeRefType = generatedType("types.impl", "FirImplicitNothingTypeRef")
|
||||
val implicitStringTypeRefType = generatedType("types.impl", "FirImplicitStringTypeRef")
|
||||
val implicitUnitTypeRefType = generatedType("types.impl", "FirImplicitUnitTypeRef")
|
||||
val resolvePhaseType = type("fir.declarations", "FirResolvePhase")
|
||||
val stubReferenceType = generatedType("references.impl", "FirStubReference")
|
||||
val compositeTransformResultType = type("fir.visitors", "CompositeTransformResult")
|
||||
|
||||
val abstractFirBasedSymbolType = type("fir.symbols", "AbstractFirBasedSymbol")
|
||||
val backingFieldSymbolType = type("fir.symbols.impl", "FirBackingFieldSymbol")
|
||||
val delegateFieldSymbolType = type("fir.symbols.impl", "FirDelegateFieldSymbol")
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.context
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.*
|
||||
|
||||
abstract class AbstractFieldConfigurator {
|
||||
inner class ConfigureContext(val element: Element) {
|
||||
operator fun FieldSet.unaryPlus() {
|
||||
element.fields.addAll(this.map { it.copy() })
|
||||
}
|
||||
|
||||
operator fun Field.unaryPlus() {
|
||||
val doesNotContains = element.fields.add(this.copy())
|
||||
require(doesNotContains) {
|
||||
"$element already contains field $this}"
|
||||
}
|
||||
}
|
||||
|
||||
fun generateBooleanFields(vararg names: String) {
|
||||
names.forEach {
|
||||
+booleanField("is${it.capitalize()}")
|
||||
}
|
||||
}
|
||||
|
||||
fun withArg(name: String, vararg upperBounds: String) {
|
||||
withArg(name, upperBounds.map { Type(null, it) })
|
||||
}
|
||||
|
||||
fun withArg(name: String, upperBound: Importable, vararg upperBounds: Importable) {
|
||||
val allUpperBounds = mutableListOf(upperBound).apply { this += upperBounds }
|
||||
withArg(name, allUpperBounds)
|
||||
}
|
||||
|
||||
private fun withArg(name: String, upperBounds: List<Importable>) {
|
||||
element.typeArguments += when (upperBounds.size) {
|
||||
in 0..1 -> SimpleTypeArgument(name, upperBounds.firstOrNull())
|
||||
else -> TypeArgumentWithMultipleUpperBounds(name, upperBounds.toList())
|
||||
}
|
||||
}
|
||||
|
||||
fun parentArg(parent: Element, argument: String, type: String) {
|
||||
parentArg(parent, Type(null, argument), Type(null, type))
|
||||
}
|
||||
|
||||
fun parentArg(parent: Element, argument: String, type: Importable) {
|
||||
parentArg(parent, Type(null, argument), type)
|
||||
}
|
||||
|
||||
fun parentArg(parent: Element, argument: Importable, type: Importable) {
|
||||
require(parent in element.parents) {
|
||||
"$parent is not parent of $element"
|
||||
}
|
||||
val argMap = element.parentsArguments.getOrPut(parent) { mutableMapOf() }
|
||||
require(argument !in argMap) {
|
||||
"Argument $argument already defined for parent $parent of $element"
|
||||
}
|
||||
argMap[argument] = type
|
||||
}
|
||||
|
||||
fun Type.withArgs(vararg args: Importable): Pair<Type, List<Importable>> {
|
||||
return this to args.toList()
|
||||
}
|
||||
|
||||
fun Type.withArgs(vararg args: String): Pair<Type, List<Importable>> {
|
||||
return this to args.map { Type(null, it) }
|
||||
}
|
||||
|
||||
fun needTransformOtherChildren() {
|
||||
element._needTransformOtherChildren = true
|
||||
}
|
||||
}
|
||||
|
||||
inline fun Element.configure(block: ConfigureContext.() -> Unit) {
|
||||
ConfigureContext(this).block()
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.context
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.BASE_PACKAGE
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Element
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Type
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
abstract class AbstractFirTreeBuilder {
|
||||
companion object {
|
||||
val baseFirElement = Element(
|
||||
"Element",
|
||||
Element.Kind.Other
|
||||
)
|
||||
|
||||
const val string = "String"
|
||||
const val boolean = "Boolean"
|
||||
const val int = "Int"
|
||||
}
|
||||
|
||||
val elements = mutableListOf(baseFirElement)
|
||||
|
||||
protected fun element(name: String, kind: Element.Kind, vararg dependencies: Element, init: Element.() -> Unit = {}): Element =
|
||||
Element(name, kind).apply(init).also {
|
||||
if (dependencies.isEmpty()) {
|
||||
it.parents.add(baseFirElement)
|
||||
}
|
||||
it.parents.addAll(dependencies)
|
||||
elements += it
|
||||
}
|
||||
}
|
||||
|
||||
fun generatedType(type: String): Type = generatedType("", type)
|
||||
|
||||
fun generatedType(packageName: String, type: String): Type {
|
||||
val realPackage = BASE_PACKAGE + if (packageName.isNotBlank()) ".$packageName" else ""
|
||||
return type(realPackage, type, exactPackage = true)
|
||||
}
|
||||
|
||||
fun type(packageName: String?, type: String, exactPackage: Boolean = false): Type {
|
||||
val realPackage = if (exactPackage) packageName else packageName?.let { "org.jetbrains.kotlin.$it" }
|
||||
return Type(realPackage, type)
|
||||
}
|
||||
|
||||
fun type(type: String): Type = type(null, type)
|
||||
|
||||
fun type(klass: KClass<*>): Type {
|
||||
val fqn = klass.qualifiedName!!
|
||||
val name = klass.simpleName!!
|
||||
return type(fqn.dropLast(name.length + 1), name, exactPackage = true)
|
||||
}
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 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.context
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.call
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.*
|
||||
import org.jetbrains.kotlin.fir.tree.generator.noReceiverExpressionType
|
||||
|
||||
abstract class AbstractFirTreeImplementationConfigurator {
|
||||
private val elementsWithImpl = mutableSetOf<Element>()
|
||||
|
||||
fun noImpl(element: Element) {
|
||||
element.doesNotNeedImplementation = true
|
||||
}
|
||||
|
||||
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)
|
||||
implementation.updateMutabilityAccordingParents()
|
||||
elementsWithImpl += element
|
||||
return implementation
|
||||
}
|
||||
|
||||
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.parents)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
inner class ParentsHolder {
|
||||
operator fun plusAssign(parent: Implementation) {
|
||||
implementation.addParent(parent)
|
||||
}
|
||||
|
||||
operator fun plusAssign(parent: ImplementationWithArg) {
|
||||
implementation.addParent(parent.implementation, parent.argument)
|
||||
parent.argument?.let { useTypes(it) }
|
||||
}
|
||||
}
|
||||
|
||||
val parents = ParentsHolder()
|
||||
|
||||
fun Implementation.withArg(argument: Importable): ImplementationWithArg = ImplementationWithArg(this, argument)
|
||||
|
||||
fun useTypes(vararg types: Importable) {
|
||||
types.forEach { implementation.usedTypes += it }
|
||||
}
|
||||
|
||||
fun lateinit(vararg fields: String) {
|
||||
for (fieldName in fields) {
|
||||
val field = getField(fieldName)
|
||||
require(field.origin !is FieldList)
|
||||
field.isLateinit = true
|
||||
field.isMutable = true
|
||||
}
|
||||
}
|
||||
|
||||
fun isMutable(vararg fields: String) {
|
||||
fields.forEach {
|
||||
val field = getField(it)
|
||||
field.isMutable = true
|
||||
}
|
||||
}
|
||||
|
||||
fun defaultNoReceivers() {
|
||||
defaultNull("explicitReceiver")
|
||||
default("dispatchReceiver", "FirNoReceiverExpression")
|
||||
default("extensionReceiver", "FirNoReceiverExpression")
|
||||
useTypes(noReceiverExpressionType)
|
||||
}
|
||||
|
||||
fun default(field: String, value: String) {
|
||||
default(field) {
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
|
||||
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 noPsi() {
|
||||
defaultNull("psi")
|
||||
}
|
||||
|
||||
fun defaultEmptyList(field: String) {
|
||||
require(getField(field).origin is FieldList) {
|
||||
"$field is list field"
|
||||
}
|
||||
default(field) {
|
||||
value = "emptyList()"
|
||||
withGetter = true
|
||||
}
|
||||
}
|
||||
|
||||
fun defaultSupertypesComputationStatus() {
|
||||
default("supertypesComputationStatus", "SupertypesComputationStatus.NOT_COMPUTED")
|
||||
}
|
||||
|
||||
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: Implementation.Kind
|
||||
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
|
||||
|
||||
fun applyConfiguration() {
|
||||
field.withGetter = withGetter
|
||||
field.customSetter = customSetter
|
||||
isMutable?.let { field.isMutable = it }
|
||||
field.needAcceptAndTransform = needAcceptAndTransform
|
||||
when {
|
||||
value != null -> field.defaultValue = value
|
||||
delegate != null -> {
|
||||
val actualDelegateField = getField(delegate!!)
|
||||
val name = delegateCall ?: field.name
|
||||
field.defaultValue = "${actualDelegateField.name}${actualDelegateField.call()}$name"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.model
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.BASE_PACKAGE
|
||||
import org.jetbrains.kotlin.fir.tree.generator.typeWithArguments
|
||||
|
||||
interface FieldContainer {
|
||||
val allFields: List<Field>
|
||||
operator fun get(fieldName: String): Field?
|
||||
}
|
||||
|
||||
interface AbstractElement : FieldContainer, Importable {
|
||||
val fields: Set<Field>
|
||||
val parents: List<AbstractElement>
|
||||
val typeArguments: List<TypeArgument>
|
||||
val parentsArguments: Map<AbstractElement, Map<Importable, Importable>>
|
||||
val baseTransformerType: AbstractElement?
|
||||
val transformerType: AbstractElement
|
||||
val doesNotNeedImplementation: Boolean
|
||||
val needTransformOtherChildren: Boolean
|
||||
val allImplementations: List<Implementation>
|
||||
val allFirFields: List<Field>
|
||||
val defaultImplementation: Implementation?
|
||||
val customImplementations: List<Implementation>
|
||||
}
|
||||
|
||||
class Element(val name: String, kind: Kind) : AbstractElement {
|
||||
override val fields = mutableSetOf<Field>()
|
||||
override val type: String = "Fir$name"
|
||||
override val packageName: String = BASE_PACKAGE + kind.packageName.let { if (it.isBlank()) it else "." + it }
|
||||
override val fullQualifiedName: String get() = super.fullQualifiedName!!
|
||||
override val parents = mutableListOf<Element>()
|
||||
override var defaultImplementation: Implementation? = null
|
||||
override val customImplementations = mutableListOf<Implementation>()
|
||||
override val typeArguments = mutableListOf<TypeArgument>()
|
||||
override val parentsArguments = mutableMapOf<AbstractElement, MutableMap<Importable, Importable>>()
|
||||
var _needTransformOtherChildren: Boolean = false
|
||||
|
||||
override var baseTransformerType: Element? = null
|
||||
override val transformerType: Element get() = baseTransformerType ?: this
|
||||
|
||||
override var doesNotNeedImplementation: Boolean = false
|
||||
|
||||
override val needTransformOtherChildren: Boolean get() = _needTransformOtherChildren || parents.any { it.needTransformOtherChildren }
|
||||
|
||||
override val allImplementations: List<Implementation> by lazy {
|
||||
if (doesNotNeedImplementation) {
|
||||
emptyList<Implementation>()
|
||||
} else {
|
||||
val implementations = customImplementations.toMutableList()
|
||||
defaultImplementation?.let { implementations += it }
|
||||
implementations
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
if (overrides) {
|
||||
val existingField = result.first { it == field }
|
||||
if (field.name != "symbol" && field.type == existingField.type) println("Duplicate [element: $this, field: $field]")
|
||||
existingField.fromParent = true
|
||||
existingField.needsSeparateTransform = existingField.needsSeparateTransform || field.needsSeparateTransform
|
||||
}
|
||||
}
|
||||
result.toList().asReversed()
|
||||
}
|
||||
|
||||
val parentFields: List<Field> by lazy {
|
||||
val result = LinkedHashSet<Field>()
|
||||
parents.forEach { parent ->
|
||||
val fields = parent.allFields.map { field ->
|
||||
val copy = (field as? SimpleField)?.let { simpleField ->
|
||||
parentsArguments[parent]?.get(Type(null, simpleField.type))?.let {
|
||||
simpleField.replaceType(Type(it.packageName, it.type))
|
||||
}
|
||||
} ?: field.copy()
|
||||
copy.apply {
|
||||
arguments.replaceAll {
|
||||
parentsArguments[parent]?.get(it) ?: it
|
||||
}
|
||||
fromParent = true
|
||||
}
|
||||
}
|
||||
result.addAll(fields)
|
||||
}
|
||||
result.toList()
|
||||
}
|
||||
|
||||
override val allFirFields: List<Field> by lazy {
|
||||
allFields.filter { it.isFirType }
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return typeWithArguments
|
||||
}
|
||||
|
||||
override fun get(fieldName: String): Field? {
|
||||
return allFields.firstOrNull { it.name == fieldName }
|
||||
}
|
||||
|
||||
enum class Kind(val packageName: String) {
|
||||
Expression("expressions"),
|
||||
Declaration("declarations"),
|
||||
Reference("references"),
|
||||
TypeRef("types"),
|
||||
Other("")
|
||||
}
|
||||
}
|
||||
|
||||
class ElementWithArguments(val element: Element, override val typeArguments: List<TypeArgument>) : AbstractElement by element {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return element.equals(other)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return element.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class TypeArgument(val name: String) {
|
||||
abstract val upperBounds: List<Importable>
|
||||
}
|
||||
|
||||
class SimpleTypeArgument(name: String, val upperBound: Importable?) : TypeArgument(name) {
|
||||
override val upperBounds: List<Importable> = listOfNotNull(upperBound)
|
||||
|
||||
override fun toString(): String {
|
||||
var result = name
|
||||
if (upperBound != null) {
|
||||
result += " : ${upperBound.typeWithArguments}"
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class TypeArgumentWithMultipleUpperBounds(name: String, override val upperBounds: List<Importable>) : TypeArgument(name) {
|
||||
override fun toString(): String {
|
||||
return name
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.model
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.type
|
||||
import org.jetbrains.kotlin.fir.tree.generator.typeWithArguments
|
||||
|
||||
// ----------- Simple field -----------
|
||||
|
||||
fun field(name: String, type: String, packageName: String?, customType: Importable? = null, nullable: Boolean = false, withReplace: Boolean = false): Field {
|
||||
return SimpleField(name, type, packageName, customType, nullable, withReplace)
|
||||
}
|
||||
|
||||
fun field(name: String, type: Type, nullable: Boolean = false, withReplace: Boolean = false): Field {
|
||||
return SimpleField(name, type.typeWithArguments, type.packageName, null, nullable, withReplace)
|
||||
}
|
||||
|
||||
fun field(name: String, typeWithArgs: Pair<Type, List<Importable>>, nullable: Boolean = false, withReplace: Boolean = false): Field {
|
||||
val (type, args) = typeWithArgs
|
||||
return SimpleField(name, type.typeWithArguments, type.packageName, null, nullable, withReplace).apply {
|
||||
arguments += args
|
||||
}
|
||||
}
|
||||
|
||||
fun field(type: Type, nullable: Boolean = false, withReplace: Boolean = false): Field {
|
||||
return SimpleField(type.type.decapitalize(), type.typeWithArguments, type.packageName, null, nullable, withReplace)
|
||||
}
|
||||
|
||||
fun booleanField(name: String): Field {
|
||||
return field(name, AbstractFirTreeBuilder.boolean, null)
|
||||
}
|
||||
|
||||
fun stringField(name: String, nullable: Boolean = false): Field {
|
||||
return field(name, AbstractFirTreeBuilder.string, null, null, nullable)
|
||||
}
|
||||
|
||||
fun intField(name: String): Field {
|
||||
return field(name, AbstractFirTreeBuilder.int, null)
|
||||
}
|
||||
|
||||
// ----------- Fir field -----------
|
||||
|
||||
fun field(name: String, type: Type, argument: String? = null, nullable: Boolean = false, withReplace: Boolean = false): Field {
|
||||
return if (argument == null) {
|
||||
field(name, type, nullable, withReplace)
|
||||
} else {
|
||||
field(name, type to listOf(type(argument)), nullable, withReplace)
|
||||
}
|
||||
}
|
||||
|
||||
fun field(name: String, element: AbstractElement, nullable: Boolean = false, withReplace: Boolean = false): Field {
|
||||
return FirField(name, element, nullable, withReplace)
|
||||
}
|
||||
|
||||
fun field(element: Element, nullable: Boolean = false, withReplace: Boolean = false): Field {
|
||||
return FirField(element.name.decapitalize(), element, nullable, withReplace)
|
||||
}
|
||||
|
||||
// ----------- Field list -----------
|
||||
|
||||
fun fieldList(name: String, type: Importable, withReplace: Boolean = false): Field {
|
||||
return FieldList(name, type, withReplace)
|
||||
}
|
||||
|
||||
fun fieldList(element: Element, withReplace: Boolean = false): Field {
|
||||
return FieldList(element.name.decapitalize() + "s", element, withReplace)
|
||||
}
|
||||
|
||||
// ----------- Field set -----------
|
||||
|
||||
typealias FieldSet = List<Field>
|
||||
|
||||
fun fieldSet(vararg fields: Field): FieldSet {
|
||||
return fields.toList()
|
||||
}
|
||||
|
||||
@JvmName("foo")
|
||||
infix fun FieldSet.with(sets: List<FieldSet>): FieldSet {
|
||||
return sets.flatten()
|
||||
}
|
||||
|
||||
infix fun FieldSet.with(set: FieldSet): FieldSet {
|
||||
return this + set
|
||||
}
|
||||
|
||||
fun Field.withTransform(): Field = copy().apply { needsSeparateTransform = true }
|
||||
|
||||
fun FieldSet.withTransform(): FieldSet = this.map { it.withTransform() }
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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.model
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.typeWithArguments
|
||||
|
||||
sealed class Field : Importable {
|
||||
abstract val name: String
|
||||
open val arguments = mutableListOf<Importable>()
|
||||
abstract val nullable: Boolean
|
||||
abstract val withReplace: Boolean
|
||||
abstract val isFirType: Boolean
|
||||
|
||||
var fromParent: Boolean = false
|
||||
open var needsSeparateTransform: Boolean = false
|
||||
|
||||
open val defaultValue: String? get() = null
|
||||
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
|
||||
|
||||
fun copy(): Field = internalCopy().also {
|
||||
updateFieldsInCopy(it)
|
||||
}
|
||||
|
||||
protected fun updateFieldsInCopy(copy: Field) {
|
||||
copy.arguments.clear()
|
||||
copy.arguments.addAll(arguments)
|
||||
copy.needsSeparateTransform = needsSeparateTransform
|
||||
copy.fromParent = fromParent
|
||||
copy.isMutable = isMutable
|
||||
}
|
||||
|
||||
protected abstract fun internalCopy(): Field
|
||||
|
||||
override fun toString(): String {
|
||||
return name
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null) return false
|
||||
if (javaClass != other.javaClass) return false
|
||||
other as Field
|
||||
return name == other.name
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return name.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
// ----------- Field with default -----------
|
||||
|
||||
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 val packageName: String? get() = origin.packageName
|
||||
override val isFirType: Boolean get() = origin.isFirType
|
||||
override var needsSeparateTransform: Boolean
|
||||
get() = origin.needsSeparateTransform
|
||||
set(_) {}
|
||||
|
||||
override val arguments: MutableList<Importable>
|
||||
get() = origin.arguments
|
||||
|
||||
override var defaultValue: String? = origin.defaultValue
|
||||
override var isMutable: Boolean = origin.isMutable
|
||||
override var isMutableInInterface: Boolean = origin.isMutableInInterface
|
||||
override var withGetter: Boolean = false
|
||||
override var isLateinit: Boolean = false
|
||||
override var customSetter: String? = null
|
||||
override var fromDelegate: Boolean = false
|
||||
var needAcceptAndTransform: Boolean = true
|
||||
|
||||
override fun internalCopy(): Field {
|
||||
return FieldWithDefault(origin).also {
|
||||
it.defaultValue = defaultValue
|
||||
it.isMutable = isMutable
|
||||
it.withGetter = withGetter
|
||||
it.isLateinit = isLateinit
|
||||
it.fromDelegate = fromDelegate
|
||||
it.needAcceptAndTransform = needAcceptAndTransform
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class SimpleField(
|
||||
override val name: String,
|
||||
override val type: String,
|
||||
override val packageName: String?,
|
||||
val customType: Importable? = null,
|
||||
override val nullable: Boolean,
|
||||
override val withReplace: Boolean
|
||||
) : Field() {
|
||||
override val isFirType: Boolean = false
|
||||
override val fullQualifiedName: String?
|
||||
get() = customType?.fullQualifiedName ?: super.fullQualifiedName
|
||||
|
||||
override var isMutable: Boolean = false
|
||||
|
||||
override fun internalCopy(): Field {
|
||||
return SimpleField(
|
||||
name,
|
||||
type,
|
||||
packageName,
|
||||
customType,
|
||||
nullable,
|
||||
withReplace
|
||||
)
|
||||
}
|
||||
|
||||
fun replaceType(newType: Type) = SimpleField(
|
||||
name,
|
||||
newType.type,
|
||||
newType.packageName,
|
||||
customType,
|
||||
nullable,
|
||||
withReplace
|
||||
).also {
|
||||
updateFieldsInCopy(it)
|
||||
}
|
||||
}
|
||||
|
||||
class FirField(
|
||||
override val name: String,
|
||||
val element: AbstractElement,
|
||||
override val nullable: Boolean,
|
||||
override val withReplace: Boolean
|
||||
) : Field() {
|
||||
override val type: String get() = element.type
|
||||
override val packageName: String? get() = element.packageName
|
||||
override val isFirType: Boolean = true
|
||||
|
||||
override var isMutable: Boolean = true
|
||||
|
||||
override fun internalCopy(): Field {
|
||||
return FirField(
|
||||
name,
|
||||
element,
|
||||
nullable,
|
||||
withReplace
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------- Field list -----------
|
||||
|
||||
class FieldList(
|
||||
override val name: String,
|
||||
val baseType: Importable,
|
||||
override val withReplace: Boolean
|
||||
) : Field() {
|
||||
override val defaultValue: String? get() = if (isMutable) "mutableListOf()" else "emptyListOf()"
|
||||
override val packageName: String? get() = baseType.packageName
|
||||
override val fullQualifiedName: String? get() = baseType.fullQualifiedName
|
||||
override val type: String = "List<${baseType.typeWithArguments}>"
|
||||
|
||||
override val nullable: Boolean
|
||||
get() = false
|
||||
|
||||
override var isMutable: Boolean = true
|
||||
|
||||
override fun internalCopy(): Field {
|
||||
return FieldList(
|
||||
name,
|
||||
baseType,
|
||||
withReplace
|
||||
)
|
||||
}
|
||||
|
||||
override val isFirType: Boolean = baseType is Element
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.model
|
||||
|
||||
class ImplementationWithArg(
|
||||
val implementation: Implementation,
|
||||
val argument: Importable?
|
||||
) : Importable by implementation, FieldContainer by implementation {
|
||||
val element: Element get() = implementation.element
|
||||
}
|
||||
|
||||
class Implementation(val element: Element, val name: String?) : Importable, FieldContainer {
|
||||
private val _parents = mutableListOf<ImplementationWithArg>()
|
||||
val parents: List<ImplementationWithArg> get() = _parents
|
||||
|
||||
val isDefault = name == null
|
||||
override val type = name ?: element.type + "Impl"
|
||||
override val allFields = element.allFields.toMutableList().mapTo(mutableListOf()) {
|
||||
FieldWithDefault(it)
|
||||
}
|
||||
var kind: Kind = Kind.FinalClass
|
||||
|
||||
override val packageName = element.packageName + ".impl"
|
||||
val usedTypes = mutableListOf<Importable>()
|
||||
|
||||
init {
|
||||
if (isDefault) {
|
||||
element.defaultImplementation = this
|
||||
} else {
|
||||
element.customImplementations += this
|
||||
}
|
||||
}
|
||||
|
||||
fun addParent(parent: Implementation, arg: Importable? = null) {
|
||||
_parents += ImplementationWithArg(parent, arg)
|
||||
}
|
||||
|
||||
override fun get(fieldName: String): FieldWithDefault? {
|
||||
return allFields.firstOrNull { it.name == fieldName }
|
||||
}
|
||||
|
||||
fun updateMutabilityAccordingParents() {
|
||||
for (parent in parents) {
|
||||
for (field in allFields) {
|
||||
val fieldFromParent = parent[field.name] ?: continue
|
||||
field.isMutable = field.isMutable || fieldFromParent.isMutable
|
||||
if (field.isMutable && field.customSetter == null) {
|
||||
field.withGetter = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class Kind(val title: String) {
|
||||
Interface("interface"),
|
||||
FinalClass("class"),
|
||||
OpenClass("open class"),
|
||||
AbstractClass("abstract class"),
|
||||
Object("object")
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* 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.model
|
||||
|
||||
interface Importable {
|
||||
val type: String
|
||||
val packageName: String?
|
||||
val fullQualifiedName: String? get() = packageName?.let { "$it.${type.replace(Regex("<.+>"), "")}" }
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* 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.model
|
||||
|
||||
data class Type(override val packageName: String?, override val type: String) : Importable {
|
||||
val arguments = mutableListOf<String>()
|
||||
}
|
||||
Reference in New Issue
Block a user