[FIR] Implement builders for leaf nodes of FIR tree
This commit is contained in:
@@ -3,6 +3,7 @@ import tasks.WriteCopyrightToFile
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
application
|
||||
}
|
||||
|
||||
val runtimeOnly by configurations
|
||||
@@ -32,6 +33,10 @@ val writeCopyright by task<WriteCopyrightToFile> {
|
||||
commented = true
|
||||
}
|
||||
|
||||
application {
|
||||
mainClassName = "org.jetbrains.kotlin.fir.tree.generator.MainKt"
|
||||
}
|
||||
|
||||
val processResources by tasks
|
||||
processResources.dependsOn(writeCopyright)
|
||||
|
||||
|
||||
+335
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.AbstractBuilderConfigurator
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeImplementationConfigurator
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Element
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Field
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.LeafBuilder
|
||||
import org.jetbrains.kotlin.fir.tree.generator.util.traverseParents
|
||||
|
||||
object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTreeBuilder) {
|
||||
fun configureBuilders() = with(firTreeBuilder) {
|
||||
val annotationContainerBuilder by builder {
|
||||
fields from annotationContainer
|
||||
}
|
||||
|
||||
val expressionBuilder by builder {
|
||||
fields from expression
|
||||
}
|
||||
|
||||
val typeParametersOwnerBuilder by builder {
|
||||
fields from typeParametersOwner
|
||||
}
|
||||
|
||||
val classBuilder by builder {
|
||||
parents += annotationContainerBuilder
|
||||
fields from klass without listOf("symbol", "resolvePhase")
|
||||
}
|
||||
|
||||
val regularClassBuilder by builder("AbstractFirRegularClassBuilder") {
|
||||
parents += classBuilder
|
||||
parents += typeParametersOwnerBuilder
|
||||
fields from regularClass
|
||||
}
|
||||
|
||||
val qualifiedAccessBuilder by builder {
|
||||
fields from qualifiedAccess without "calleeReference"
|
||||
}
|
||||
|
||||
val callBuilder by builder {
|
||||
fields from call
|
||||
}
|
||||
|
||||
val loopBuilder by builder {
|
||||
fields from loop
|
||||
}
|
||||
|
||||
val functionBuilder by builder {
|
||||
parents += annotationContainerBuilder
|
||||
fields from function without listOf("symbol", "resolvePhase", "controlFlowGraphReference", "receiverTypeRef")
|
||||
}
|
||||
|
||||
val loopJumpBuilder by builder {
|
||||
fields from loopJump without "typeRef"
|
||||
}
|
||||
|
||||
val abstractConstructorBuilder by builder {
|
||||
parents += functionBuilder
|
||||
fields from constructor without "isPrimary"
|
||||
}
|
||||
|
||||
for (constructorType in listOf("FirPrimaryConstructor", "FirConstructorImpl")) {
|
||||
builder(constructor, constructorType) {
|
||||
parents += abstractConstructorBuilder
|
||||
defaultNull("delegatedConstructor")
|
||||
defaultNull("body")
|
||||
}
|
||||
}
|
||||
|
||||
builder(constructor, "FirConstructorImpl") {
|
||||
openBuilder()
|
||||
}
|
||||
|
||||
builder(field) {
|
||||
default("resolvePhase", "FirResolvePhase.DECLARATIONS")
|
||||
openBuilder()
|
||||
}
|
||||
|
||||
builder(regularClass) {
|
||||
parents += regularClassBuilder
|
||||
defaultNull("companionObject")
|
||||
openBuilder()
|
||||
}
|
||||
|
||||
builder(sealedClass) {
|
||||
parents += regularClassBuilder
|
||||
defaultNull("companionObject")
|
||||
}
|
||||
|
||||
builder(anonymousObject) {
|
||||
parents += classBuilder
|
||||
}
|
||||
|
||||
builder(typeAlias) {
|
||||
parents += typeParametersOwnerBuilder
|
||||
}
|
||||
|
||||
builder(annotationCall) {
|
||||
parents += callBuilder
|
||||
}
|
||||
|
||||
builder(arrayOfCall) {
|
||||
parents += callBuilder
|
||||
}
|
||||
|
||||
builder(arraySetCall) {
|
||||
parents += qualifiedAccessBuilder
|
||||
defaultFalse("safe")
|
||||
defaultNoReceivers()
|
||||
}
|
||||
|
||||
builder(callableReferenceAccess) {
|
||||
parents += qualifiedAccessBuilder
|
||||
defaultNull("explicitReceiver")
|
||||
defaultNoReceivers()
|
||||
defaultFalse("safe")
|
||||
}
|
||||
|
||||
builder(componentCall) {
|
||||
parents += callBuilder
|
||||
}
|
||||
|
||||
builder(whileLoop) {
|
||||
parents += loopBuilder
|
||||
defaultNull("label")
|
||||
}
|
||||
|
||||
builder(doWhileLoop) {
|
||||
parents += loopBuilder
|
||||
defaultNull("label")
|
||||
}
|
||||
|
||||
builder(errorLoop) {
|
||||
defaultNull("label")
|
||||
}
|
||||
|
||||
builder(delegatedConstructorCall) {
|
||||
parents += callBuilder
|
||||
}
|
||||
|
||||
builder(functionCall) {
|
||||
parents += qualifiedAccessBuilder
|
||||
parents += callBuilder
|
||||
defaultFalse("safe")
|
||||
defaultNoReceivers()
|
||||
openBuilder()
|
||||
}
|
||||
|
||||
builder(qualifiedAccessExpression) {
|
||||
parents += qualifiedAccessBuilder
|
||||
defaultFalse("safe")
|
||||
defaultNoReceivers()
|
||||
}
|
||||
|
||||
builder(getClassCall) {
|
||||
parents += callBuilder
|
||||
}
|
||||
|
||||
builder(property) {
|
||||
parents += typeParametersOwnerBuilder
|
||||
defaultNull("getter", "setter", "containerSource", "delegateFieldSymbol")
|
||||
default("resolvePhase", "FirResolvePhase.RAW_FIR")
|
||||
}
|
||||
|
||||
builder(operatorCall) {
|
||||
parents += callBuilder
|
||||
}
|
||||
|
||||
builder(typeOperatorCall) {
|
||||
parents += callBuilder
|
||||
}
|
||||
|
||||
builder(stringConcatenationCall) {
|
||||
parents += callBuilder
|
||||
}
|
||||
|
||||
builder(thisReceiverExpression) {
|
||||
parents += qualifiedAccessBuilder
|
||||
}
|
||||
|
||||
builder(variableAssignment) {
|
||||
parents += qualifiedAccessBuilder
|
||||
defaultNoReceivers()
|
||||
}
|
||||
|
||||
builder(anonymousFunction) {
|
||||
parents += functionBuilder
|
||||
defaultNull("invocationKind", "label", "body")
|
||||
default("controlFlowGraphReference", "FirEmptyControlFlowGraphReference")
|
||||
useTypes(emptyCfgReferenceType)
|
||||
}
|
||||
|
||||
builder(propertyAccessor) {
|
||||
parents += functionBuilder
|
||||
defaultNull("body")
|
||||
}
|
||||
|
||||
builder(whenExpression) {
|
||||
defaultFalse("isExhaustive")
|
||||
default("calleeReference", "FirStubReference")
|
||||
useTypes(stubReferenceType)
|
||||
}
|
||||
|
||||
builder(resolvedTypeRef) {
|
||||
defaultNull("delegatedTypeRef")
|
||||
}
|
||||
|
||||
builder(breakExpression) {
|
||||
parents += loopJumpBuilder
|
||||
}
|
||||
|
||||
builder(continueExpression) {
|
||||
parents += loopJumpBuilder
|
||||
}
|
||||
|
||||
builder(valueParameter, type = "FirValueParameterImpl") {
|
||||
openBuilder()
|
||||
}
|
||||
|
||||
builder(valueParameter, type = "FirDefaultSetterValueParameter") {
|
||||
defaultNull("defaultValue", "initializer", "delegate", "receiverTypeRef", "delegateFieldSymbol", "getter", "setter")
|
||||
defaultFalse("isCrossinline", "isNoinline", "isVararg", "isVar")
|
||||
defaultTrue("isVal")
|
||||
}
|
||||
|
||||
builder(simpleFunction) {
|
||||
parents += functionBuilder
|
||||
parents += typeParametersOwnerBuilder
|
||||
defaultNull("body")
|
||||
openBuilder()
|
||||
}
|
||||
|
||||
builder(tryExpression) {
|
||||
default("calleeReference", "FirStubReference")
|
||||
useTypes(stubReferenceType)
|
||||
}
|
||||
|
||||
builder(checkNotNullCall) {
|
||||
default("calleeReference", "FirStubReference")
|
||||
useTypes(stubReferenceType)
|
||||
}
|
||||
|
||||
val elementsWithDefaultTypeRef = listOf(
|
||||
thisReceiverExpression,
|
||||
callableReferenceAccess,
|
||||
anonymousObject,
|
||||
qualifiedAccessExpression,
|
||||
functionCall,
|
||||
anonymousFunction,
|
||||
whenExpression,
|
||||
tryExpression,
|
||||
checkNotNullCall,
|
||||
resolvedQualifier,
|
||||
resolvedReifiedParameterReference,
|
||||
expression to "FirExpressionStub",
|
||||
varargArgumentsExpression
|
||||
)
|
||||
elementsWithDefaultTypeRef.forEach {
|
||||
val (element, name) = when (it) {
|
||||
is Pair<*, *> -> it.first as Element to it.second as String
|
||||
is Element -> it to null
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
builder(element, name) {
|
||||
default("typeRef", "FirImplicitTypeRefImpl(null)")
|
||||
useTypes(implicitTypeRefType)
|
||||
}
|
||||
}
|
||||
|
||||
noBuilder(constExpression)
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
findImplementationsWithElementInParents(annotationContainer) {
|
||||
it.type !in setOf("FirDelegatedTypeRefImpl", "FirImplicitTypeRefImpl")
|
||||
}.forEach {
|
||||
it.builder?.parents?.add(annotationContainerBuilder)
|
||||
}
|
||||
|
||||
findImplementationsWithElementInParents(expression).forEach {
|
||||
it.builder?.parents?.add(expressionBuilder)
|
||||
}
|
||||
|
||||
configureFieldInAllLeafBuilders(
|
||||
field = "resolvePhase",
|
||||
fieldPredicate = { it.defaultValueInImplementation == null }
|
||||
) {
|
||||
default(it, "FirResolvePhase.RAW_FIR")
|
||||
}
|
||||
|
||||
configureFieldInAllLeafBuilders(
|
||||
field = "containerSource"
|
||||
) {
|
||||
defaultNull(it)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun findImplementationsWithElementInParents(
|
||||
element: Element,
|
||||
implementationPredicate: (Implementation) -> Boolean = { true }
|
||||
): Collection<Implementation> {
|
||||
return FirTreeBuilder.elements.flatMap { it.allImplementations }.mapNotNullTo(mutableSetOf()) {
|
||||
if (!implementationPredicate(it)) return@mapNotNullTo null
|
||||
var hasAnnotations = false
|
||||
if (it.element == element) return@mapNotNullTo null
|
||||
it.element.traverseParents {
|
||||
if (it == element) {
|
||||
hasAnnotations = true
|
||||
}
|
||||
}
|
||||
it.takeIf { hasAnnotations }
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureFieldInAllLeafBuilders(
|
||||
field: String,
|
||||
builderPredicate: ((LeafBuilder) -> Boolean)? = null,
|
||||
fieldPredicate: ((Field) -> Boolean)? = null,
|
||||
init: LeafBuilderConfigurationContext.(field: String) -> Unit
|
||||
) {
|
||||
val builders = FirTreeBuilder.elements.flatMap { it.allImplementations }.mapNotNull { it.builder }
|
||||
for (builder in builders) {
|
||||
if (builderPredicate != null && !builderPredicate(builder)) continue
|
||||
if (!builder.allFields.any { it.name == field }) continue
|
||||
if (fieldPredicate != null && !fieldPredicate(builder[field])) continue
|
||||
LeafBuilderConfigurationContext(builder).init(field)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+60
-132
@@ -32,21 +32,23 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
}
|
||||
|
||||
impl(constructor) {
|
||||
kind = OpenClass
|
||||
parents += modifiableConstructor
|
||||
defaultNull("delegatedConstructor")
|
||||
defaultNull("body")
|
||||
|
||||
default("isPrimary") {
|
||||
value = "false"
|
||||
withGetter = true
|
||||
}
|
||||
|
||||
defaultFalse("isPrimary", withGetter = true)
|
||||
default("typeParameters") {
|
||||
needAcceptAndTransform = false
|
||||
}
|
||||
}
|
||||
|
||||
impl(constructor, "FirPrimaryConstructor") {
|
||||
parents += modifiableConstructor
|
||||
|
||||
defaultTrue("isPrimary", withGetter = true)
|
||||
default("typeParameters") {
|
||||
needAcceptAndTransform = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
noImpl(declarationStatus)
|
||||
noImpl(resolvedDeclarationStatus)
|
||||
|
||||
@@ -59,8 +61,9 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
|
||||
val regularClassConfig: ImplementationContext.() -> Unit = {
|
||||
parents += modifiableRegularClass
|
||||
defaultNull("companionObject")
|
||||
defaultFalse("hasLazyNestedClassifiers", withGetter = true)
|
||||
}
|
||||
|
||||
impl(regularClass, "FirClassImpl", regularClassConfig)
|
||||
|
||||
impl(sealedClass, config = regularClassConfig)
|
||||
@@ -69,7 +72,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
parents += modifiableClass.withArg(anonymousObject)
|
||||
}
|
||||
|
||||
|
||||
impl(typeAlias) {
|
||||
parents += modifiableTypeParametersOwner
|
||||
}
|
||||
@@ -100,14 +102,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
}
|
||||
}
|
||||
|
||||
impl(breakExpression) {
|
||||
lateinit("target")
|
||||
}
|
||||
|
||||
impl(continueExpression) {
|
||||
lateinit("target")
|
||||
}
|
||||
|
||||
impl(annotationCall) {
|
||||
parents += callWithArgumentList
|
||||
default("typeRef") {
|
||||
@@ -126,7 +120,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
|
||||
impl(arraySetCall) {
|
||||
parents += modifiableQualifiedAccess
|
||||
lateinit("calleeReference")
|
||||
default("arguments") {
|
||||
value = "indexes + rValue"
|
||||
withGetter = true
|
||||
@@ -135,16 +128,10 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
value = "calleeReference"
|
||||
customSetter = "calleeReference = value"
|
||||
}
|
||||
default("safe", "false")
|
||||
defaultNoReceivers()
|
||||
}
|
||||
|
||||
impl(callableReferenceAccess) {
|
||||
parents += modifiableQualifiedAccess
|
||||
defaultNull("explicitReceiver")
|
||||
default("safe", "false")
|
||||
defaultNoReceivers()
|
||||
lateinit("calleeReference")
|
||||
}
|
||||
|
||||
impl(componentCall) {
|
||||
@@ -161,20 +148,17 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
}
|
||||
default("calleeReference", "FirSimpleNamedReference(source, Name.identifier(\"component\$componentIndex\"), null)")
|
||||
useTypes(simpleNamedReferenceType, nameType, noReceiverExpressionType)
|
||||
optInToInternals()
|
||||
}
|
||||
|
||||
val abstractLoop = impl(loop, "FirAbstractLoop")
|
||||
|
||||
impl(whileLoop) {
|
||||
parents += abstractLoop
|
||||
defaultNull("label")
|
||||
lateinit("block")
|
||||
}
|
||||
|
||||
impl(doWhileLoop) {
|
||||
parents += abstractLoop
|
||||
defaultNull("label")
|
||||
lateinit("block")
|
||||
}
|
||||
|
||||
impl(delegatedConstructorCall) {
|
||||
@@ -190,46 +174,41 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
useTypes(explicitThisReferenceType, explicitSuperReferenceType)
|
||||
}
|
||||
|
||||
impl(expression, "FirElseIfTrueCondition") {
|
||||
val elseIfTrueCondition = impl(expression, "FirElseIfTrueCondition") {
|
||||
default("typeRef", "FirImplicitBooleanTypeRef(source)")
|
||||
useTypes(implicitBooleanTypeRefType)
|
||||
publicImplementation()
|
||||
}
|
||||
|
||||
impl(block)
|
||||
|
||||
val emptyExpressionBlock = impl(block, "FirEmptyExpressionBlock") {
|
||||
noSource()
|
||||
defaultEmptyList("statements")
|
||||
defaultEmptyList("annotations")
|
||||
publicImplementation()
|
||||
}
|
||||
|
||||
impl(errorLoop) {
|
||||
default("block", "FirEmptyExpressionBlock()")
|
||||
default("condition", "FirErrorExpressionImpl(source, diagnostic)")
|
||||
defaultNull("label")
|
||||
useTypes(emptyExpressionBlock)
|
||||
}
|
||||
|
||||
impl(expression, "FirExpressionStub")
|
||||
impl(expression, "FirExpressionStub") {
|
||||
publicImplementation()
|
||||
}
|
||||
|
||||
impl(functionCall) {
|
||||
parents += modifiableQualifiedAccess
|
||||
parents += callWithArgumentList
|
||||
defaultFalse("safe")
|
||||
lateinit("calleeReference")
|
||||
defaultNoReceivers()
|
||||
kind = OpenClass
|
||||
}
|
||||
|
||||
impl(qualifiedAccessExpression) {
|
||||
parents += modifiableQualifiedAccess
|
||||
defaultFalse("safe")
|
||||
lateinit("calleeReference")
|
||||
defaultNoReceivers()
|
||||
}
|
||||
|
||||
impl(checkNotNullCall) {
|
||||
default("calleeReference", "FirStubReference()")
|
||||
useTypes(stubReferenceType)
|
||||
}
|
||||
|
||||
noImpl(expressionWithSmartcast)
|
||||
|
||||
@@ -252,11 +231,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -266,10 +240,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
withGetter = true
|
||||
}
|
||||
|
||||
default("resolvePhase") {
|
||||
value = "FirResolvePhase.DECLARATIONS"
|
||||
}
|
||||
|
||||
defaultNull("delegateFieldSymbol", "receiverTypeRef", "initializer", "delegate", "getter", "setter", withGetter = true)
|
||||
}
|
||||
|
||||
@@ -337,7 +307,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
impl(resolvedReifiedParameterReference)
|
||||
|
||||
impl(returnExpression) {
|
||||
lateinit("target")
|
||||
default("typeRef", "FirImplicitNothingTypeRef(source)")
|
||||
useTypes(implicitNothingTypeRefType)
|
||||
}
|
||||
@@ -362,20 +331,14 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
defaultNoReceivers()
|
||||
}
|
||||
|
||||
impl(tryExpression) {
|
||||
default("calleeReference", "FirStubReference()")
|
||||
useTypes(stubReferenceType)
|
||||
}
|
||||
|
||||
impl(expression, "FirUnitExpression") {
|
||||
default("typeRef", "FirImplicitUnitTypeRef(source)")
|
||||
useTypes(implicitUnitTypeRefType)
|
||||
publicImplementation()
|
||||
}
|
||||
|
||||
impl(variableAssignment) {
|
||||
parents += modifiableQualifiedAccess
|
||||
lateinit("calleeReference")
|
||||
defaultNoReceivers()
|
||||
|
||||
default("lValue") {
|
||||
value = "calleeReference"
|
||||
@@ -387,7 +350,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
|
||||
impl(anonymousFunction) {
|
||||
parents += modifiableFunction.withArg(anonymousFunction)
|
||||
defaultNull("invocationKind", "label", "body")
|
||||
default("resolvePhase", "FirResolvePhase.DECLARATIONS")
|
||||
}
|
||||
|
||||
@@ -401,18 +363,11 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
value = "!isGetter"
|
||||
withGetter = true
|
||||
}
|
||||
defaultNull("body")
|
||||
default("contractDescription", "FirEmptyContractDescription")
|
||||
useTypes(modalityType, emptyContractDescriptionType)
|
||||
kind = OpenClass
|
||||
}
|
||||
|
||||
impl(whenExpression) {
|
||||
default("calleeReference", "FirStubReference()")
|
||||
defaultFalse("isExhaustive")
|
||||
useTypes(stubReferenceType)
|
||||
}
|
||||
|
||||
impl(whenSubjectExpression) {
|
||||
default("typeRef") {
|
||||
value = "whenSubject.whenExpression.subject!!.typeRef"
|
||||
@@ -421,7 +376,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
}
|
||||
|
||||
impl(wrappedDelegateExpression) {
|
||||
lateinit("delegateProvider")
|
||||
default("typeRef") {
|
||||
delegate = "expression"
|
||||
}
|
||||
@@ -433,6 +387,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
|
||||
impl(resolvedNamedReference, "FirPropertyFromParameterResolvedNamedReference") {
|
||||
defaultNull("candidateSymbol", withGetter = true)
|
||||
publicImplementation()
|
||||
}
|
||||
|
||||
impl(resolvedCallableReference) {
|
||||
@@ -479,13 +434,10 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
|
||||
impl(controlFlowGraphReference, "FirEmptyControlFlowGraphReference") {
|
||||
noSource()
|
||||
kind = Object
|
||||
}
|
||||
|
||||
impl(resolvedTypeRef) {
|
||||
default("delegatedTypeRef") {
|
||||
value = "null"
|
||||
}
|
||||
}
|
||||
impl(resolvedTypeRef)
|
||||
|
||||
val errorTypeRefImpl = impl(errorTypeRef) {
|
||||
default("type", "ConeClassErrorType(diagnostic.reason)")
|
||||
@@ -493,9 +445,16 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
value = "null"
|
||||
withGetter = true
|
||||
}
|
||||
default("annotations", "mutableListOf()")
|
||||
useTypes(coneClassErrorTypeType)
|
||||
}
|
||||
|
||||
impl(errorExpression) {
|
||||
defaultEmptyList("annotations")
|
||||
default("typeRef", "FirErrorTypeRefImpl(source, diagnostic)")
|
||||
useTypes(errorTypeRefImpl)
|
||||
}
|
||||
|
||||
impl(resolvedFunctionTypeRef) {
|
||||
default("delegatedTypeRef") {
|
||||
value = "null"
|
||||
@@ -521,6 +480,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
value = "null"
|
||||
withGetter = true
|
||||
}
|
||||
kind = Object
|
||||
}
|
||||
|
||||
impl(errorNamedReference) {
|
||||
@@ -533,9 +493,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
noSource()
|
||||
}
|
||||
|
||||
val abstractLoopJump = impl(loopJump, "FirAbstractLoopJump") {
|
||||
lateinit("target")
|
||||
}
|
||||
val abstractLoopJump = impl(loopJump, "FirAbstractLoopJump") {}
|
||||
|
||||
impl(breakExpression) {
|
||||
parents += abstractLoopJump
|
||||
@@ -552,23 +510,19 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
impl(valueParameter) {
|
||||
kind = OpenClass
|
||||
parents += modifiableVariable.withArg(valueParameter)
|
||||
defaultTrue("isVal", true)
|
||||
defaultTrue("isVal", withGetter = 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")
|
||||
default("contractDescription", "FirEmptyContractDescription")
|
||||
useTypes(emptyContractDescriptionType)
|
||||
}
|
||||
@@ -582,67 +536,41 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
}
|
||||
|
||||
noImpl(userTypeRef)
|
||||
|
||||
// impl(delegatedConstructorCall) {
|
||||
// defaultTrue("safe", withGetter = true)
|
||||
// listOf("dispatchReceiver", "extensionReceiver", "explicitReceiver").forEach {
|
||||
// default(it) {
|
||||
// value = "FirNoReceiverExpression"
|
||||
// withGetter = true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
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()")
|
||||
configureFieldInAllImplementations(
|
||||
field = "controlFlowGraphReference",
|
||||
implementationPredicate = { it.type != "FirAnonymousFunctionImpl"}
|
||||
) {
|
||||
default(it, "FirEmptyControlFlowGraphReference")
|
||||
useTypes(emptyCfgReferenceType)
|
||||
}
|
||||
|
||||
val implementationWithConfigurableTypeRef = listOf(
|
||||
"FirDelegatedTypeRefImpl",
|
||||
"FirTypeProjectionWithVarianceImpl",
|
||||
"FirCallableReferenceAccessImpl",
|
||||
"FirThisReceiverExpressionImpl",
|
||||
"FirAnonymousObjectImpl",
|
||||
"FirQualifiedAccessExpressionImpl",
|
||||
"FirFunctionCallImpl",
|
||||
"FirAnonymousFunctionImpl",
|
||||
"FirWhenExpressionImpl",
|
||||
"FirTryExpressionImpl",
|
||||
"FirCheckNotNullCallImpl",
|
||||
"FirResolvedQualifierImpl",
|
||||
"FirResolvedReifiedParameterReferenceImpl",
|
||||
"FirExpressionStub",
|
||||
"FirVarargArgumentsExpressionImpl",
|
||||
)
|
||||
configureFieldInAllImplementations(
|
||||
field = "typeRef",
|
||||
implementationPredicate = { it.type !in listOf("FirDelegatedTypeRefImpl", "FirTypeProjectionWithVarianceImpl") },
|
||||
fieldPredicate = { it.defaultValue == null }
|
||||
implementationPredicate = { it.type !in implementationWithConfigurableTypeRef },
|
||||
fieldPredicate = { it.defaultValueInImplementation == 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -11,15 +11,19 @@ import java.io.File
|
||||
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val generationPath = args.firstOrNull()?.let { File(it) }
|
||||
?: File("compiler/fir/tree/gen").absoluteFile
|
||||
// val generationPath = args.firstOrNull()?.let { File(it) }
|
||||
// ?: File("/home/demiurg/Programming/kotlin/kotlin/compiler/fir/tree/gen").absoluteFile
|
||||
val generationPath = File("/home/demiurg/Programming/kotlin/kotlin/compiler/fir/tree/gen").absoluteFile
|
||||
|
||||
NodeConfigurator.configureFields()
|
||||
detectBaseTransformerTypes(FirTreeBuilder)
|
||||
ImplementationConfigurator.configureImplementations()
|
||||
configureInterfacesAndAbstractClasses(FirTreeBuilder)
|
||||
BuilderConfigurator.configureBuilders()
|
||||
removePreviousGeneratedFiles(generationPath)
|
||||
printElements(FirTreeBuilder, generationPath)
|
||||
// printFieldUsageTable(FirTreeBuilder)
|
||||
// printHierarchyGraph(FirTreeBuilder)
|
||||
}
|
||||
|
||||
// FirTreeBuilder.constExpression.fields.first()
|
||||
+3
-2
@@ -218,6 +218,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
+name
|
||||
+symbol("FirRegularClassSymbol")
|
||||
+field("companionObject", regularClass, nullable = true)
|
||||
+booleanField("hasLazyNestedClassifiers")
|
||||
+superTypeRefs(withReplace = true)
|
||||
}
|
||||
|
||||
@@ -267,7 +268,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
}
|
||||
|
||||
contractDescriptionOwner.configure {
|
||||
+field(contractDescription).withTransform()
|
||||
+field(contractDescription, withReplace = true).withTransform()
|
||||
}
|
||||
|
||||
property.configure {
|
||||
@@ -431,7 +432,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
+field("packageFqName", fqNameType)
|
||||
+field("relativeClassFqName", fqNameType, nullable = true)
|
||||
+field("classId", classIdType, nullable = true)
|
||||
+booleanField("safe")
|
||||
+booleanField("safe", withReplace = true)
|
||||
+typeArguments.withTransform()
|
||||
}
|
||||
|
||||
|
||||
@@ -67,3 +67,5 @@ val effectDeclarationType = type("fir.contracts.description", "ConeEffectDeclara
|
||||
val emptyContractDescriptionType = generatedType("contracts.impl", "FirEmptyContractDescription")
|
||||
val firDiagnosticType = generatedType("diagnostics", "FirDiagnostic")
|
||||
|
||||
val dslBuilderAnnotationType = generatedType("builder", "FirBuilderDsl")
|
||||
val firImplementationDetailType = generatedType("FirImplementationDetail")
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.*
|
||||
import org.jetbrains.kotlin.fir.tree.generator.noReceiverExpressionType
|
||||
import org.jetbrains.kotlin.fir.tree.generator.printer.call
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
abstract class AbstractBuilderConfigurator<T : AbstractFirTreeBuilder>(val firTreeBuilder: T) {
|
||||
abstract class BuilderConfigurationContext {
|
||||
abstract val builder: Builder
|
||||
|
||||
private fun getField(name: String): FieldWithDefault {
|
||||
return builder[name]
|
||||
}
|
||||
|
||||
fun useTypes(vararg types: Importable) {
|
||||
types.forEach { builder.usedTypes += it }
|
||||
}
|
||||
|
||||
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) {
|
||||
default(field) {
|
||||
value = "true"
|
||||
}
|
||||
}
|
||||
|
||||
fun defaultFalse(vararg fields: String) {
|
||||
for (field in fields) {
|
||||
default(field) {
|
||||
value = "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun defaultNull(vararg fields: String) {
|
||||
for (field in fields) {
|
||||
default(field) {
|
||||
value = "null"
|
||||
}
|
||||
require(getField(field).nullable) {
|
||||
"$field is not nullable field"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun default(field: String, init: DefaultValueContext.() -> Unit) {
|
||||
DefaultValueContext(getField(field)).apply(init).applyConfiguration()
|
||||
}
|
||||
|
||||
inner class DefaultValueContext(private val field: FieldWithDefault) {
|
||||
var value: String? = null
|
||||
|
||||
fun applyConfiguration() {
|
||||
if (value != null) field.defaultValueInBuilder = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class IntermediateBuilderConfigurationContext(override val builder: IntermediateBuilder) : BuilderConfigurationContext() {
|
||||
inner class Fields {
|
||||
// fields from <element>
|
||||
infix fun from(element: Element): ExceptConfigurator {
|
||||
builder.fields += element.allFields.map {
|
||||
FieldWithDefault(it.copy())
|
||||
}
|
||||
builder.packageName = "${element.packageName}.builder"
|
||||
builder.materializedElement = element
|
||||
return ExceptConfigurator()
|
||||
}
|
||||
|
||||
inner class Helper(val fieldName: String) {
|
||||
infix fun from(element: Element) {
|
||||
val field = element[fieldName] ?: throw IllegalArgumentException("Element $element doesn't have field $fieldName")
|
||||
builder.fields += FieldWithDefault(field)
|
||||
}
|
||||
}
|
||||
|
||||
// fields has <field> from <element>
|
||||
infix fun has(name: String): Helper = Helper(name)
|
||||
}
|
||||
|
||||
inner class ExceptConfigurator {
|
||||
infix fun without(name: String) {
|
||||
without(listOf(name))
|
||||
}
|
||||
|
||||
infix fun without(names: List<String>) {
|
||||
builder.fields.removeAll { it.name in names }
|
||||
}
|
||||
}
|
||||
|
||||
val fields = Fields()
|
||||
val parents: MutableList<IntermediateBuilder> get() = builder.parents
|
||||
|
||||
var materializedElement: Element
|
||||
get() = throw IllegalArgumentException()
|
||||
set(value) {
|
||||
builder.materializedElement = value
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inner class IntermediateBuilderDelegateProvider(
|
||||
private val name: String?,
|
||||
private val block: IntermediateBuilderConfigurationContext.() -> Unit
|
||||
) {
|
||||
lateinit var builder: IntermediateBuilder
|
||||
|
||||
operator fun provideDelegate(
|
||||
thisRef: Nothing?,
|
||||
prop: KProperty<*>
|
||||
): ReadOnlyProperty<Nothing?, IntermediateBuilder> {
|
||||
val name = name ?: "Fir${prop.name.capitalize()}"
|
||||
builder = IntermediateBuilder(name).apply {
|
||||
firTreeBuilder.intermediateBuilders += this
|
||||
IntermediateBuilderConfigurationContext(this).block()
|
||||
}
|
||||
return DummyDelegate(builder)
|
||||
}
|
||||
|
||||
private inner class DummyDelegate(val builder: IntermediateBuilder) : ReadOnlyProperty<Nothing?, IntermediateBuilder> {
|
||||
override fun getValue(thisRef: Nothing?, property: KProperty<*>): IntermediateBuilder {
|
||||
return builder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class LeafBuilderConfigurationContext(override val builder: LeafBuilder) : BuilderConfigurationContext() {
|
||||
val parents: MutableList<IntermediateBuilder> get() = builder.parents
|
||||
|
||||
fun openBuilder() {
|
||||
builder.isOpen = true
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(name: String? = null, block: IntermediateBuilderConfigurationContext.() -> Unit): IntermediateBuilderDelegateProvider {
|
||||
return IntermediateBuilderDelegateProvider(name, block)
|
||||
}
|
||||
|
||||
fun builder(element: Element, type: String? = null, init: LeafBuilderConfigurationContext.() -> Unit) {
|
||||
val implementation = element.extractImplementation(type)
|
||||
val builder = implementation.builder
|
||||
requireNotNull(builder)
|
||||
LeafBuilderConfigurationContext(builder).apply(init)
|
||||
}
|
||||
|
||||
private fun Element.extractImplementation(type: String?): Implementation {
|
||||
return if (type == null) {
|
||||
allImplementations.filter { it.kind?.hasLeafBuilder == true }.singleOrNull() ?: this@AbstractBuilderConfigurator.run {
|
||||
val message = buildString {
|
||||
appendln("${this@extractImplementation} has multiple implementations:")
|
||||
for (implementation in allImplementations) {
|
||||
appendln(" - ${implementation.type}")
|
||||
}
|
||||
appendln("Please specify implementation is needed")
|
||||
}
|
||||
throw IllegalArgumentException(message)
|
||||
}
|
||||
} else {
|
||||
allImplementations.firstOrNull { it.type == type } ?: this@AbstractBuilderConfigurator.run {
|
||||
val message = buildString {
|
||||
appendln("${this@extractImplementation} has not implementation $type. Existing implementations:")
|
||||
for (implementation in allImplementations) {
|
||||
appendln(" - ${implementation.type}")
|
||||
}
|
||||
appendln("Please specify implementation is needed")
|
||||
}
|
||||
throw IllegalArgumentException(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun noBuilder(element: Element, type: String? = null) {
|
||||
val implementation = element.extractImplementation(type)
|
||||
implementation.builder = null
|
||||
}
|
||||
}
|
||||
+2
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.tree.generator.context
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Element
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.IntermediateBuilder
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Type
|
||||
import org.jetbrains.kotlin.fir.tree.generator.printer.BASE_PACKAGE
|
||||
import kotlin.reflect.KClass
|
||||
@@ -23,6 +24,7 @@ abstract class AbstractFirTreeBuilder {
|
||||
}
|
||||
|
||||
val elements = mutableListOf(baseFirElement)
|
||||
val intermediateBuilders = mutableListOf<IntermediateBuilder>()
|
||||
|
||||
protected fun element(name: String, kind: Element.Kind, vararg dependencies: Element, init: Element.() -> Unit = {}): Element =
|
||||
Element(name, kind).apply(init).also {
|
||||
|
||||
+12
-12
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.tree.generator.context
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.*
|
||||
import org.jetbrains.kotlin.fir.tree.generator.noReceiverExpressionType
|
||||
import org.jetbrains.kotlin.fir.tree.generator.printer.call
|
||||
@@ -89,17 +90,16 @@ abstract class AbstractFirTreeImplementationConfigurator {
|
||||
|
||||
fun Implementation.withArg(argument: Importable): ImplementationWithArg = ImplementationWithArg(this, argument)
|
||||
|
||||
fun useTypes(vararg types: Importable) {
|
||||
types.forEach { implementation.usedTypes += it }
|
||||
fun optInToInternals() {
|
||||
implementation.requiresOptIn = true
|
||||
}
|
||||
|
||||
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 publicImplementation() {
|
||||
implementation.isPublic = true
|
||||
}
|
||||
|
||||
fun useTypes(vararg types: Importable) {
|
||||
types.forEach { implementation.usedTypes += it }
|
||||
}
|
||||
|
||||
fun isMutable(vararg fields: String) {
|
||||
@@ -151,7 +151,7 @@ abstract class AbstractFirTreeImplementationConfigurator {
|
||||
}
|
||||
|
||||
fun noSource() {
|
||||
defaultNull("source")
|
||||
defaultNull("source", withGetter = true)
|
||||
}
|
||||
|
||||
fun defaultEmptyList(field: String) {
|
||||
@@ -218,11 +218,11 @@ abstract class AbstractFirTreeImplementationConfigurator {
|
||||
isMutable?.let { field.isMutable = it }
|
||||
field.needAcceptAndTransform = needAcceptAndTransform
|
||||
when {
|
||||
value != null -> field.defaultValue = value
|
||||
value != null -> field.defaultValueInImplementation = value
|
||||
delegate != null -> {
|
||||
val actualDelegateField = getField(delegate!!)
|
||||
val name = delegateCall ?: field.name
|
||||
field.defaultValue = "${actualDelegateField.name}${actualDelegateField.call()}$name"
|
||||
field.defaultValueInImplementation = "${actualDelegateField.name}${actualDelegateField.call()}$name"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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
|
||||
|
||||
private const val DEFAULT_BUILDER_PACKAGE = "org.jetbrains.kotlin.fir.tree.builder"
|
||||
|
||||
sealed class Builder : FieldContainer, Importable {
|
||||
val parents: MutableList<IntermediateBuilder> = mutableListOf()
|
||||
val usedTypes: MutableList<Importable> = mutableListOf()
|
||||
abstract override val allFields: List<FieldWithDefault>
|
||||
abstract val uselessFields: List<FieldWithDefault>
|
||||
|
||||
abstract override val packageName: String
|
||||
|
||||
override fun get(fieldName: String): FieldWithDefault {
|
||||
return allFields.firstOrNull { it.name == fieldName }
|
||||
?: throw IllegalArgumentException("Builder $type doesn't contains field $fieldName")
|
||||
}
|
||||
|
||||
private val fieldsFromParentIndex: Map<String, Boolean> by lazy {
|
||||
mutableMapOf<String, Boolean>().apply {
|
||||
for (field in allFields + uselessFields) {
|
||||
this[field.name] = parents.any { field.name in it.allFields.map { it.name } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isFromParent(field: Field): Boolean = fieldsFromParentIndex.getValue(field.name)
|
||||
}
|
||||
|
||||
class LeafBuilder(val implementation: Implementation) : Builder() {
|
||||
override val type: String
|
||||
get() = if (implementation.name != null) {
|
||||
"${implementation.name}Builder"
|
||||
} else {
|
||||
"${implementation.element.type}Builder"
|
||||
}
|
||||
|
||||
override val allFields: List<FieldWithDefault> by lazy { implementation.fieldsWithoutDefault }
|
||||
|
||||
override val uselessFields: List<FieldWithDefault> by lazy {
|
||||
val fieldsFromParents = parents.flatMap { it.allFields }.distinct()
|
||||
val fieldsFromImplementation = implementation.allFields
|
||||
(fieldsFromImplementation - allFields).filter { it in fieldsFromParents }
|
||||
}
|
||||
|
||||
override val packageName: String = implementation.packageName.replace(".impl", ".builder")
|
||||
var isOpen: Boolean = false
|
||||
}
|
||||
|
||||
class IntermediateBuilder(override val type: String) : Builder() {
|
||||
val fields: MutableList<FieldWithDefault> = mutableListOf()
|
||||
var materializedElement: Element? = null
|
||||
|
||||
override val allFields: List<FieldWithDefault> by lazy {
|
||||
mutableSetOf<FieldWithDefault>().apply {
|
||||
parents.forEach { this += it.allFields }
|
||||
this += fields
|
||||
}.toList()
|
||||
}
|
||||
|
||||
override val uselessFields: List<FieldWithDefault> = emptyList()
|
||||
override var packageName: String = DEFAULT_BUILDER_PACKAGE
|
||||
}
|
||||
+20
-10
@@ -17,7 +17,7 @@ sealed class Field : Importable {
|
||||
var fromParent: Boolean = false
|
||||
open var needsSeparateTransform: Boolean = false
|
||||
|
||||
open val defaultValue: String? get() = null
|
||||
open val defaultValueInImplementation: String? get() = null
|
||||
abstract var isMutable: Boolean
|
||||
open var isMutableInInterface: Boolean = false
|
||||
open val withGetter: Boolean get() = false
|
||||
@@ -30,11 +30,13 @@ sealed class Field : Importable {
|
||||
}
|
||||
|
||||
protected fun updateFieldsInCopy(copy: Field) {
|
||||
copy.arguments.clear()
|
||||
copy.arguments.addAll(arguments)
|
||||
copy.needsSeparateTransform = needsSeparateTransform
|
||||
if (copy !is FieldWithDefault) {
|
||||
copy.arguments.clear()
|
||||
copy.arguments.addAll(arguments)
|
||||
copy.needsSeparateTransform = needsSeparateTransform
|
||||
copy.isMutable = isMutable
|
||||
}
|
||||
copy.fromParent = fromParent
|
||||
copy.isMutable = isMutable
|
||||
}
|
||||
|
||||
protected abstract fun internalCopy(): Field
|
||||
@@ -72,21 +74,23 @@ class FieldWithDefault(val origin: Field) : Field() {
|
||||
override val arguments: MutableList<Importable>
|
||||
get() = origin.arguments
|
||||
|
||||
override var defaultValue: String? = origin.defaultValue
|
||||
override val fullQualifiedName: String?
|
||||
get() = origin.fullQualifiedName
|
||||
|
||||
override var defaultValueInImplementation: String? = origin.defaultValueInImplementation
|
||||
var defaultValueInBuilder: String? = null
|
||||
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.defaultValueInImplementation = defaultValueInImplementation
|
||||
it.isMutable = isMutable
|
||||
it.withGetter = withGetter
|
||||
it.isLateinit = isLateinit
|
||||
it.fromDelegate = fromDelegate
|
||||
it.needAcceptAndTransform = needAcceptAndTransform
|
||||
}
|
||||
@@ -136,6 +140,12 @@ class FirField(
|
||||
override val nullable: Boolean,
|
||||
override val withReplace: Boolean
|
||||
) : Field() {
|
||||
init {
|
||||
if (element is ElementWithArguments) {
|
||||
arguments += element.typeArguments.map { Type(null, it.name) }
|
||||
}
|
||||
}
|
||||
|
||||
override val type: String get() = element.type
|
||||
override val packageName: String? get() = element.packageName
|
||||
override val isFirType: Boolean = true
|
||||
@@ -159,7 +169,7 @@ class FieldList(
|
||||
val baseType: Importable,
|
||||
override val withReplace: Boolean
|
||||
) : Field() {
|
||||
override val defaultValue: String? get() = if (isMutable) "mutableListOf()" else "emptyListOf()"
|
||||
override var defaultValueInImplementation: String? = null
|
||||
override val packageName: String? get() = baseType.packageName
|
||||
override val fullQualifiedName: String? get() = baseType.fullQualifiedName
|
||||
override val type: String = "List<${baseType.typeWithArguments}>"
|
||||
|
||||
+28
-6
@@ -5,6 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.tree.generator.model
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
|
||||
class ImplementationWithArg(
|
||||
val implementation: Implementation,
|
||||
val argument: Importable?
|
||||
@@ -23,10 +27,25 @@ class Implementation(val element: Element, val name: String?) : FieldContainer,
|
||||
FieldWithDefault(it)
|
||||
}
|
||||
override var kind: Kind? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (kind != Kind.FinalClass) {
|
||||
isPublic = true
|
||||
}
|
||||
if (value?.hasLeafBuilder == true) {
|
||||
builder = builder ?: LeafBuilder(this)
|
||||
} else {
|
||||
builder = null
|
||||
}
|
||||
}
|
||||
|
||||
override val packageName = element.packageName + ".impl"
|
||||
val usedTypes = mutableListOf<Importable>()
|
||||
|
||||
var isPublic = false
|
||||
var requiresOptIn = false
|
||||
var builder: LeafBuilder? = null
|
||||
|
||||
init {
|
||||
if (isDefault) {
|
||||
element.defaultImplementation = this
|
||||
@@ -55,11 +74,14 @@ class Implementation(val element: Element, val name: String?) : FieldContainer,
|
||||
}
|
||||
}
|
||||
|
||||
enum class Kind(val title: String) {
|
||||
Interface("interface"),
|
||||
FinalClass("class"),
|
||||
OpenClass("open class"),
|
||||
AbstractClass("abstract class"),
|
||||
Object("object")
|
||||
val fieldsWithoutDefault by lazy { allFields.filter { it.defaultValueInImplementation == null } }
|
||||
val fieldsWithDefault by lazy { allFields.filter { it.defaultValueInImplementation != null } }
|
||||
|
||||
enum class Kind(val title: String, val hasLeafBuilder: Boolean) {
|
||||
Interface("interface", false),
|
||||
FinalClass("class", true),
|
||||
OpenClass("open class", true),
|
||||
AbstractClass("abstract class", false),
|
||||
Object("object", false)
|
||||
}
|
||||
}
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.printer
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.*
|
||||
import java.io.File
|
||||
|
||||
fun Builder.generateCode(generationPath: File) {
|
||||
val dir = generationPath.resolve(packageName.replace(".", "/"))
|
||||
dir.mkdirs()
|
||||
val file = File(dir, "$type.kt")
|
||||
file.useSmartPrinter {
|
||||
printCopyright()
|
||||
println("package $packageName")
|
||||
println()
|
||||
val imports = collectImports()
|
||||
imports.forEach { println("import $it") }
|
||||
if (imports.isNotEmpty()) {
|
||||
println()
|
||||
}
|
||||
printGeneratedMessage()
|
||||
printBuilder(this@generateCode)
|
||||
}
|
||||
}
|
||||
|
||||
private fun SmartPrinter.printBuilder(builder: Builder) {
|
||||
if (builder is LeafBuilder && builder.allFields.isEmpty()) {
|
||||
printDslBuildFunction(builder, false)
|
||||
return
|
||||
}
|
||||
|
||||
println("@FirBuilderDsl")
|
||||
when (builder) {
|
||||
is IntermediateBuilder -> print("interface ")
|
||||
is LeafBuilder -> {
|
||||
if (builder.isOpen) {
|
||||
print("open ")
|
||||
}
|
||||
print("class ")
|
||||
}
|
||||
}
|
||||
print(builder.typeWithArguments)
|
||||
if (builder.parents.isNotEmpty()) {
|
||||
print(builder.parents.joinToString(separator = ", ", prefix = " : ") { it.type })
|
||||
}
|
||||
var hasRequiredFields = false
|
||||
println(" {")
|
||||
withIndent {
|
||||
var needNewLine = false
|
||||
for (field in builder.allFields) {
|
||||
val (newLine, requiredFields) = printFieldInBuilder(field, builder, fieldIsUseless = false)
|
||||
needNewLine = newLine
|
||||
hasRequiredFields = hasRequiredFields || requiredFields
|
||||
}
|
||||
val hasBackingFields = builder.allFields.any { it.nullable }
|
||||
if (needNewLine) {
|
||||
println()
|
||||
}
|
||||
val buildType = when (builder) {
|
||||
is LeafBuilder -> builder.implementation.element.typeWithArguments
|
||||
is IntermediateBuilder -> builder.materializedElement!!.typeWithArguments.replace(Regex("<.>"), "<*>")
|
||||
}
|
||||
if (builder is LeafBuilder && builder.implementation.isPublic) {
|
||||
println("@UseExperimental(FirImplementationDetail::class)")
|
||||
}
|
||||
if (builder.parents.isNotEmpty()) {
|
||||
print("override ")
|
||||
}
|
||||
print("fun build(): $buildType")
|
||||
if (builder is LeafBuilder) {
|
||||
println(" {")
|
||||
withIndent {
|
||||
println("return ${builder.implementation.type}(")
|
||||
withIndent {
|
||||
for (field in builder.allFields) {
|
||||
val name = field.name
|
||||
println(name, ",")
|
||||
}
|
||||
}
|
||||
println(")")
|
||||
}
|
||||
println("}")
|
||||
if (hasBackingFields) {
|
||||
println()
|
||||
}
|
||||
} else {
|
||||
println()
|
||||
}
|
||||
|
||||
if (builder is LeafBuilder) {
|
||||
// for (field in builder.allFields) {
|
||||
// printBackingFieldIfNeeded(field)
|
||||
// }
|
||||
|
||||
val hasUselessFields = builder.uselessFields.isNotEmpty()
|
||||
if (hasUselessFields) {
|
||||
println()
|
||||
builder.uselessFields.forEachIndexed { index, field ->
|
||||
if (index > 0) {
|
||||
println()
|
||||
}
|
||||
printFieldInBuilder(field, builder, fieldIsUseless = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println("}")
|
||||
if (builder is LeafBuilder) {
|
||||
println()
|
||||
printDslBuildFunction(builder, hasRequiredFields)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val String.nullable: String get() = if (endsWith("?")) this else "$this?"
|
||||
private fun FieldWithDefault.needBackingField(fieldIsUseless: Boolean) = !nullable && origin !is FieldList && if (fieldIsUseless) {
|
||||
defaultValueInImplementation == null
|
||||
} else {
|
||||
defaultValueInBuilder == null
|
||||
}
|
||||
|
||||
private fun FieldWithDefault.needNotNullDelegate(fieldIsUseless: Boolean) = needBackingField(fieldIsUseless) && (type == "Boolean" || type == "Int")
|
||||
|
||||
|
||||
private fun SmartPrinter.printFieldInBuilder(field: FieldWithDefault, builder: Builder, fieldIsUseless: Boolean): Pair<Boolean, Boolean> {
|
||||
if (field.withGetter && !fieldIsUseless) return false to false
|
||||
if (field.origin is FieldList) {
|
||||
printFieldListInBuilder(field.origin, builder, fieldIsUseless)
|
||||
return true to false
|
||||
}
|
||||
val name = field.name
|
||||
val type = field.typeWithArguments
|
||||
val defaultValue = if (fieldIsUseless)
|
||||
field.defaultValueInImplementation.also { requireNotNull(it) }
|
||||
else
|
||||
field.defaultValueInBuilder
|
||||
|
||||
printDeprecationOnUselessFieldIfNeeded(field, builder, fieldIsUseless)
|
||||
printModifiers(builder, field, fieldIsUseless)
|
||||
print("var $name: $type")
|
||||
var hasRequiredFields = false
|
||||
val needNewLine = when {
|
||||
fieldIsUseless -> {
|
||||
println()
|
||||
withIndent {
|
||||
println("get() = throw IllegalStateException()")
|
||||
println("set(value) {")
|
||||
withIndent {
|
||||
println("throw IllegalStateException()")
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
builder is IntermediateBuilder -> {
|
||||
println()
|
||||
false
|
||||
}
|
||||
field.needNotNullDelegate(fieldIsUseless) -> {
|
||||
println(" by kotlin.properties.Delegates.notNull<${field.type}>()")
|
||||
hasRequiredFields = true
|
||||
true
|
||||
}
|
||||
|
||||
field.needBackingField(fieldIsUseless) -> {
|
||||
// println()
|
||||
// withIndent {
|
||||
// println("get() = _$name ?: throw IllegalArgumentException(\"$name should be initialized\")")
|
||||
// println("set(value) {")
|
||||
// withIndent {
|
||||
// println("_$name = value")
|
||||
// }
|
||||
// println("}")
|
||||
// println()
|
||||
// }
|
||||
// false
|
||||
println()
|
||||
hasRequiredFields = true
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
println(" = $defaultValue")
|
||||
true
|
||||
}
|
||||
}
|
||||
return needNewLine to hasRequiredFields
|
||||
}
|
||||
|
||||
private fun SmartPrinter.printDeprecationOnUselessFieldIfNeeded(field: Field, builder: Builder, fieldIsUseless: Boolean) {
|
||||
if (fieldIsUseless) {
|
||||
println("@Deprecated(\"Modification of '${field.name}' has no impact for ${builder.type}\", level = DeprecationLevel.HIDDEN)")
|
||||
}
|
||||
}
|
||||
|
||||
private fun SmartPrinter.printFieldListInBuilder(field: FieldList, builder: Builder, fieldIsUseless: Boolean) {
|
||||
printDeprecationOnUselessFieldIfNeeded(field, builder, fieldIsUseless)
|
||||
printModifiers(builder, field, fieldIsUseless)
|
||||
print("val ${field.name}: ${field.mutableType}")
|
||||
if (builder is LeafBuilder) {
|
||||
print(" = mutableListOf()")
|
||||
}
|
||||
println()
|
||||
}
|
||||
|
||||
private fun SmartPrinter.printModifiers(builder: Builder, field: Field, fieldIsUseless: Boolean) {
|
||||
if (builder is IntermediateBuilder) {
|
||||
print("abstract ")
|
||||
}
|
||||
if (builder.isFromParent(field)) {
|
||||
print("override ")
|
||||
} else if (builder is LeafBuilder && builder.isOpen) {
|
||||
print("open ")
|
||||
}
|
||||
if (builder is LeafBuilder && field is FieldWithDefault && field.needBackingField(fieldIsUseless) && !fieldIsUseless && !field.needNotNullDelegate(fieldIsUseless)) {
|
||||
print("lateinit ")
|
||||
}
|
||||
}
|
||||
|
||||
private fun SmartPrinter.printDslBuildFunction(
|
||||
builder: LeafBuilder,
|
||||
hasRequiredFields: Boolean
|
||||
) {
|
||||
val isEmpty = builder.allFields.isEmpty()
|
||||
if (!isEmpty) {
|
||||
println("@UseExperimental(ExperimentalContracts::class)")
|
||||
print("inline ")
|
||||
} else if(builder.implementation.isPublic) {
|
||||
println("@UseExperimental(FirImplementationDetail::class)")
|
||||
}
|
||||
print("fun ")
|
||||
builder.implementation.element.typeArguments.takeIf { it.isNotEmpty() }?.let {
|
||||
print(it.joinToString(separator = ", ", prefix = "<", postfix = "> ") { it.name })
|
||||
}
|
||||
val builderType = builder.typeWithArguments
|
||||
val name = builder.implementation.name?.replaceFirst("Fir", "") ?: builder.implementation.element.name
|
||||
print("build${name}(")
|
||||
if (!isEmpty) {
|
||||
print("init: $builderType.() -> Unit")
|
||||
if (!hasRequiredFields) {
|
||||
print(" = {}")
|
||||
}
|
||||
}
|
||||
println("): ${builder.implementation.element.typeWithArguments} {")
|
||||
withIndent {
|
||||
if (!isEmpty) {
|
||||
println("contract {")
|
||||
withIndent {
|
||||
println("callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)")
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
print("return ")
|
||||
if (isEmpty) {
|
||||
println("${builder.implementation.type}()")
|
||||
} else {
|
||||
println("$builderType().apply(init).build()")
|
||||
}
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
+2
-11
@@ -22,23 +22,14 @@ fun SmartPrinter.printField(field: Field, isImplementation: Boolean, override: B
|
||||
}
|
||||
|
||||
fun SmartPrinter.printFieldWithDefaultInImplementation(field: Field) {
|
||||
val defaultValue = field.defaultValue
|
||||
val defaultValue = field.defaultValueInImplementation
|
||||
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(" ")
|
||||
}
|
||||
print(" ${field.name}: ${field.mutableType} ")
|
||||
if (field.withGetter) {
|
||||
if (field.customSetter != null) {
|
||||
println()
|
||||
|
||||
+10
-4
@@ -45,10 +45,14 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
|
||||
}
|
||||
|
||||
with(implementation) {
|
||||
if (requiresOptIn) {
|
||||
println("@UseExperimental(FirImplementationDetail::class)")
|
||||
}
|
||||
if (!isPublic) {
|
||||
print("internal ")
|
||||
}
|
||||
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 }
|
||||
|
||||
val isInterface = kind == Implementation.Kind.Interface
|
||||
val isAbstract = kind == Implementation.Kind.AbstractClass
|
||||
@@ -60,11 +64,13 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
|
||||
}
|
||||
|
||||
if (!isInterface && !isAbstract && fieldsWithoutDefault.isNotEmpty()) {
|
||||
if (isPublic) {
|
||||
print(" @FirImplementationDetail constructor")
|
||||
}
|
||||
println("(")
|
||||
withIndent {
|
||||
fieldsWithoutDefault.forEachIndexed { i, field ->
|
||||
val end = if (i == fieldsWithoutDefault.size - 1) "" else ","
|
||||
printField(field, isImplementation = true, override = true, end = end)
|
||||
printField(field, isImplementation = true, override = true, end = ",")
|
||||
}
|
||||
}
|
||||
print(")")
|
||||
|
||||
+2
@@ -29,6 +29,8 @@ val GENERATED_MESSAGE = """
|
||||
fun printElements(builder: AbstractFirTreeBuilder, generationPath: File) {
|
||||
builder.elements.forEach { it.generateCode(generationPath) }
|
||||
builder.elements.flatMap { it.allImplementations }.forEach { it.generateCode(generationPath) }
|
||||
builder.elements.flatMap { it.allImplementations }.mapNotNull { it.builder }.forEach { it.generateCode(generationPath) }
|
||||
builder.intermediateBuilders.forEach { it.generateCode(generationPath) }
|
||||
|
||||
printVisitor(builder.elements, generationPath)
|
||||
printVisitorVoid(builder.elements, generationPath)
|
||||
|
||||
+39
-9
@@ -7,20 +7,40 @@ package org.jetbrains.kotlin.fir.tree.generator.printer
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.compositeTransformResultType
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
|
||||
import org.jetbrains.kotlin.fir.tree.generator.firImplementationDetailType
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.*
|
||||
import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType
|
||||
|
||||
enum class ImportKind(val postfix: String) {
|
||||
Element(""), Implementation(".impl"), Builder(".builder")
|
||||
}
|
||||
|
||||
fun Implementation.collectImports(): List<String> {
|
||||
fun Builder.collectImports(): List<String> {
|
||||
val parents = parents.mapNotNull { it.fullQualifiedName }
|
||||
val builderDsl = "org.jetbrains.kotlin.fir.builder.FirBuilderDsl"
|
||||
return when (this) {
|
||||
is LeafBuilder -> implementation.collectImports(
|
||||
parents,
|
||||
ImportKind.Builder,
|
||||
) + implementation.fullQualifiedName!! + usedTypes.mapNotNull { it.fullQualifiedName } + builderDsl + "kotlin.contracts.*"
|
||||
is IntermediateBuilder -> {
|
||||
val fqns = parents + allFields.mapNotNull { it.fullQualifiedName } + allFields.flatMap {
|
||||
it.arguments.mapNotNull { it.fullQualifiedName }
|
||||
} + (materializedElement?.fullQualifiedName ?: throw IllegalStateException(type)) + builderDsl
|
||||
fqns.filterRedundantImports(packageName, ImportKind.Builder)
|
||||
}
|
||||
}.sorted()
|
||||
}
|
||||
|
||||
fun Implementation.collectImports(base: List<String> = emptyList(), kind: ImportKind = ImportKind.Implementation): List<String> {
|
||||
return element.collectImportsInternal(
|
||||
listOf(
|
||||
element.fullQualifiedName,
|
||||
)
|
||||
base + listOf(element.fullQualifiedName)
|
||||
+ usedTypes.mapNotNull { it.fullQualifiedName } + parents.mapNotNull { it.fullQualifiedName }
|
||||
+ listOfNotNull(
|
||||
pureAbstractElementType.fullQualifiedName?.takeIf { needPureAbstractElement },
|
||||
firImplementationDetailType.fullQualifiedName?.takeIf { isPublic || requiresOptIn },
|
||||
),
|
||||
isImpl = true,
|
||||
kind,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -36,20 +56,28 @@ fun Element.collectImports(): List<String> {
|
||||
}
|
||||
return collectImportsInternal(
|
||||
baseTypes,
|
||||
isImpl = false,
|
||||
ImportKind.Element,
|
||||
)
|
||||
}
|
||||
|
||||
private fun Element.collectImportsInternal(base: List<String>, isImpl: Boolean): List<String> {
|
||||
private fun Element.collectImportsInternal(base: List<String>, kind: ImportKind): 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 ->
|
||||
return fqns.filterRedundantImports(packageName, kind)
|
||||
}
|
||||
|
||||
private fun List<String>.filterRedundantImports(
|
||||
packageName: String,
|
||||
kind: ImportKind,
|
||||
): List<String> {
|
||||
val realPackageName = "$packageName.${kind.postfix}"
|
||||
return filter { fqn ->
|
||||
fqn.dropLastWhile { it != '.' } != realPackageName
|
||||
}.distinct().sorted() + "$VISITOR_PACKAGE.*"
|
||||
}
|
||||
|
||||
|
||||
val KindOwner.needPureAbstractElement: Boolean
|
||||
get() = (kind != Implementation.Kind.Interface) && !allParents.any { it.kind == Implementation.Kind.AbstractClass }
|
||||
|
||||
@@ -104,6 +132,8 @@ val Importable.typeWithArguments: String
|
||||
is Field -> type + generics + if (nullable) "?" else ""
|
||||
is Type -> type + generics
|
||||
is ImplementationWithArg -> type + generics
|
||||
is LeafBuilder -> type + implementation.element.generics
|
||||
is IntermediateBuilder -> type
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user