[FIR][tree] replace FirDeclaration.resolvePhase -> resolveState

Lazy resolve state represents the lazy resolve
state of the current declaration
It can be either resolved or be in a process of resolve

^KT-56543
This commit is contained in:
Dmitrii Gridin
2023-03-28 12:04:29 +02:00
committed by Space Team
parent 77e1bc6f9e
commit faeafbbe29
196 changed files with 3918 additions and 3654 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.tree.generator
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractBuilderConfigurator
import org.jetbrains.kotlin.fir.tree.generator.model.*
import org.jetbrains.kotlin.fir.tree.generator.printer.invisibleField
import org.jetbrains.kotlin.fir.tree.generator.util.traverseParents
object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTreeBuilder) {
@@ -34,7 +35,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
val classBuilder by builder {
parents += declarationBuilder
parents += annotationContainerBuilder
fields from klass without listOf("symbol", "resolvePhase", "controlFlowGraphReference")
fields from klass without listOf("symbol", "resolvePhase", "resolveState", "controlFlowGraphReference")
}
builder(regularClass) {
@@ -63,6 +64,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
fields from function without listOf(
"symbol",
"resolvePhase",
"resolveState",
"controlFlowGraphReference",
"receiverParameter",
"typeParameters",
@@ -439,6 +441,14 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
default(it, "FirResolvePhase.RAW_FIR")
}
configureFieldInAllLeafBuilders(
field = "resolveState",
fieldPredicate = { it.invisibleField },
builderPredicate = { it.wantsCopy },
) {
useTypes(resolvePhaseExtensionImport)
}
configureFieldInAllLeafBuilders(
field = "containerSource"
) {
@@ -30,9 +30,9 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val contextReceiver by element(Declaration)
val elementWithResolvePhase by element(Other)
val fileAnnotationsContainer by element(Other, elementWithResolvePhase, annotationContainer)
val declaration by sealedElement(Declaration, elementWithResolvePhase, annotationContainer)
val elementWithResolveState by element(Other)
val fileAnnotationsContainer by element(Other, elementWithResolveState, annotationContainer)
val declaration by sealedElement(Declaration, elementWithResolveState, annotationContainer)
val typeParameterRefsOwner by sealedElement(Declaration)
val typeParametersOwner by sealedElement(Declaration, typeParameterRefsOwner)
val memberDeclaration by sealedElement(Declaration, declaration, typeParameterRefsOwner)
@@ -355,7 +355,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
}
impl(anonymousFunction) {
default("resolvePhase", "FirResolvePhase.DECLARATIONS")
}
noImpl(anonymousFunctionExpression)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 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.
*/
@@ -75,9 +75,15 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("labelNameFromTypeRef", nameType, nullable = true)
}
elementWithResolveState.configure {
+field("resolvePhase", resolvePhaseType).apply { isParameter = true; }
+field("resolveState", resolveStateType).apply {
isMutable = true; isVolatile = true; isFinal = true; isLateinit = true
customInitializationCall = "resolvePhase.asResolveState()"
arbitraryImportables += phaseAsResolveStateExtentionImport
optInAnnotation = resolveStateAccessImport
}
elementWithResolvePhase.configure {
+field("resolvePhase", resolvePhaseType, withReplace = true).apply { isMutable = true; isVolatile = true }
+field("moduleData", firModuleDataType)
shouldBeAbstractClass()
}
@@ -119,11 +125,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
errorFunction.configure {
+symbol("FirErrorFunctionSymbol")
+typeParameters
}
memberDeclaration.configure {
+status.withTransform()
+status.withTransform().withReplace()
}
expression.configure {
@@ -63,6 +63,7 @@ val implicitNothingTypeRefType = generatedType("types.impl", "FirImplicitNothing
val implicitStringTypeRefType = generatedType("types.impl", "FirImplicitStringTypeRef", firType = true)
val implicitUnitTypeRefType = generatedType("types.impl", "FirImplicitUnitTypeRef", firType = true)
val resolvePhaseType = type("fir.declarations", "FirResolvePhase")
val resolveStateType = type("fir.declarations", "FirResolveState")
val propertyBodyResolveStateType = type("fir.declarations", "FirPropertyBodyResolveState")
val stubReferenceType = generatedType("references.impl", "FirStubReference", firType = true)
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2023 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.model.ArbitraryImportable
val phaseAsResolveStateExtentionImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "asResolveState")
val resolvePhaseExtensionImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "resolvePhase")
val resolveStateAccessImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "ResolveStateAccess")
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 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.
*/
@@ -12,6 +12,9 @@ sealed class Field : Importable {
open val arguments = mutableListOf<Importable>()
abstract val nullable: Boolean
abstract var isVolatile: Boolean
abstract var isFinal: Boolean
abstract var isLateinit: Boolean
abstract var isParameter: Boolean
open var withReplace: Boolean = false
abstract val isFirType: Boolean
@@ -19,6 +22,9 @@ sealed class Field : Importable {
open var needsSeparateTransform: Boolean = false
var parentHasSeparateTransform: Boolean = true
open var needTransformInOtherChildren: Boolean = false
open var customInitializationCall: String? = null
open val arbitraryImportables: MutableList<Importable> = mutableListOf()
open var optInAnnotation: ArbitraryImportable? = null
open val defaultValueInImplementation: String? get() = null
abstract var isMutable: Boolean
@@ -46,7 +52,10 @@ sealed class Field : Importable {
copy.needTransformInOtherChildren = needTransformInOtherChildren
copy.isMutable = isMutable
copy.overridenTypes += overridenTypes
copy.arbitraryImportables += arbitraryImportables
copy.useNullableForReplace = useNullableForReplace
copy.customInitializationCall = customInitializationCall
copy.optInAnnotation = optInAnnotation
}
copy.fromParent = fromParent
copy.parentHasSeparateTransform = parentHasSeparateTransform
@@ -97,6 +106,26 @@ class FieldWithDefault(val origin: Field) : Field() {
override val fullQualifiedName: String?
get() = origin.fullQualifiedName
override var isFinal: Boolean
get() = origin.isFinal
set(_) {}
override var isLateinit: Boolean
get() = origin.isLateinit
set(_) {}
override var isParameter: Boolean
get() = origin.isParameter
set(_) {}
override var customInitializationCall: String?
get() = origin.customInitializationCall
set(_) {}
override var optInAnnotation: ArbitraryImportable?
get() = origin.optInAnnotation
set(_) {}
override var defaultValueInImplementation: String? = origin.defaultValueInImplementation
var defaultValueInBuilder: String? = null
override var isMutable: Boolean = origin.isMutable
@@ -109,6 +138,9 @@ class FieldWithDefault(val origin: Field) : Field() {
override val overridenTypes: MutableSet<Importable>
get() = origin.overridenTypes
override val arbitraryImportables: MutableList<Importable>
get() = origin.arbitraryImportables
override var useNullableForReplace: Boolean
get() = origin.useNullableForReplace
set(_) {}
@@ -131,7 +163,10 @@ class SimpleField(
val customType: Importable? = null,
override val nullable: Boolean,
override var withReplace: Boolean,
override var isVolatile: Boolean = false
override var isVolatile: Boolean = false,
override var isFinal: Boolean = false,
override var isLateinit: Boolean = false,
override var isParameter: Boolean = false,
) : Field() {
override val isFirType: Boolean = false
override val fullQualifiedName: String?
@@ -142,26 +177,32 @@ class SimpleField(
override fun internalCopy(): Field {
return SimpleField(
name,
type,
packageName,
customType,
nullable,
withReplace,
isVolatile
name = name,
type = type,
packageName = packageName,
customType = customType,
nullable = nullable,
withReplace = withReplace,
isVolatile = isVolatile,
isFinal = isFinal,
isLateinit = isLateinit,
isParameter = isParameter,
).apply {
withBindThis = this@SimpleField.withBindThis
}
}
fun replaceType(newType: Type) = SimpleField(
name,
newType.type,
newType.packageName,
customType,
nullable,
withReplace,
isVolatile
name = name,
type = newType.type,
packageName = newType.packageName,
customType = customType,
nullable = nullable,
withReplace = withReplace,
isVolatile = isVolatile,
isFinal = isFinal,
isLateinit = isLateinit,
isParameter = isParameter
).also {
it.withBindThis = withBindThis
updateFieldsInCopy(it)
@@ -172,7 +213,7 @@ class FirField(
override val name: String,
val element: AbstractElement,
override val nullable: Boolean,
override var withReplace: Boolean
override var withReplace: Boolean,
) : Field() {
init {
if (element is ElementWithArguments) {
@@ -182,11 +223,14 @@ class FirField(
override val type: String get() = element.type
override var isVolatile: Boolean = false
override var isFinal: Boolean = false
override val packageName: String? get() = element.packageName
override val isFirType: Boolean = true
override var isMutable: Boolean = true
override var isMutableOrEmpty: Boolean = false
override var isLateinit: Boolean = false
override var isParameter: Boolean = false
override fun internalCopy(): Field {
return FirField(
@@ -217,8 +261,11 @@ class FieldList(
get() = false
override var isVolatile: Boolean = false
override var isFinal: Boolean = false
override var isMutable: Boolean = true
override var isMutableOrEmpty: Boolean = useMutableOrEmpty
override var isLateinit: Boolean = false
override var isParameter: Boolean = false
override fun internalCopy(): Field {
return FieldList(
@@ -82,6 +82,7 @@ private fun SmartPrinter.printBuilder(builder: Builder) {
println("return ${builder.implementation.type}(")
withIndent {
for (field in builder.allFields) {
if (field.invisibleField) continue
val name = field.name
print(name)
if (field.isMutableOrEmpty) print(".toMutableOrEmpty()")
@@ -127,19 +128,21 @@ private fun SmartPrinter.printBuilder(builder: Builder) {
}
}
internal val Field.invisibleField: Boolean get() = customInitializationCall != null
private val String.nullable: String get() = if (endsWith("?")) this else "$this?"
private fun FieldWithDefault.needBackingField(fieldIsUseless: Boolean) = (!nullable || notNull) && origin !is FieldList && if (fieldIsUseless) {
defaultValueInImplementation == null
} else {
defaultValueInBuilder == null
}
private fun FieldWithDefault.needBackingField(fieldIsUseless: Boolean) =
(!nullable || notNull) && 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.withGetter && !fieldIsUseless || field.invisibleField) return false to false
if (field.origin is FieldList) {
printFieldListInBuilder(field.origin, builder, fieldIsUseless)
return true to false
@@ -303,6 +306,7 @@ private fun SmartPrinter.printDslBuildCopyFunction(
println("val copyBuilder = $builderType()")
for (field in builder.allFields) {
when {
field.invisibleField -> {}
field.origin is FieldList -> println("copyBuilder.${field.name}.addAll(original.${field.name})")
field.type == declarationAttributesType.type -> println("copyBuilder.${field.name} = original.${field.name}.copy()")
field.notNull -> println("original.${field.name}?.let { copyBuilder.${field.name} = it }")
@@ -1,18 +1,19 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 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.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.*
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.Kind
import org.jetbrains.kotlin.fir.tree.generator.model.Importable
import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType
import org.jetbrains.kotlin.fir.tree.generator.util.get
import org.jetbrains.kotlin.util.SmartPrinter
import org.jetbrains.kotlin.util.withIndent
import java.io.File
fun Element.generateCode(generationPath: File): GeneratedFile {
@@ -76,9 +77,12 @@ fun SmartPrinter.printElement(element: Element) {
print(multipleUpperBoundsList())
println("{")
withIndent {
allFields.forEach {
abstract()
printField(it, isImplementation = false, override = it.fromParent, end = "")
allFields.forEach { field ->
if (field.isFinal && field.fromParent || field.isParameter) return@forEach
if (!field.isFinal) {
abstract()
}
printField(field, isImplementation = false, override = field.fromParent, end = "")
}
if (allFields.isNotEmpty()) {
println()
@@ -1,26 +1,33 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 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.Field
import org.jetbrains.kotlin.fir.tree.generator.model.SimpleField
import org.jetbrains.kotlin.util.SmartPrinter
fun SmartPrinter.printField(field: Field, isImplementation: Boolean, override: Boolean, end: String, notNull: Boolean = false) {
if (isImplementation && !field.isVal && field.isVolatile) {
if (!field.isVal && field.isVolatile) {
println("@Volatile")
}
field.optInAnnotation?.let {
println("@${it.type}")
}
if (override) {
print("override ")
}
if (!isImplementation || field.isVal) {
print("val")
} else {
if (field.isLateinit) {
print("lateinit ")
}
if (isImplementation && !field.isVal || field.isFinal && field.isMutable) {
print("var")
} else {
print("val")
}
val type = if (isImplementation) field.getMutableType(notNull = notNull) else field.getTypeWithArguments(notNull = notNull)
println(" ${field.name}: $type$end")
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 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.
*/
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind
import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType
import org.jetbrains.kotlin.util.SmartPrinter
import org.jetbrains.kotlin.util.withIndent
import java.io.File
fun Implementation.generateCode(generationPath: File): GeneratedFile {
@@ -75,9 +74,12 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
}
println("(")
withIndent {
fieldsWithoutDefault.forEachIndexed { _, field ->
printField(field, isImplementation = true, override = true, end = ",", notNull = field.notNull)
if (field.isParameter) {
println("${field.name}: ${field.typeWithArguments},")
} else if (!field.isFinal) {
printField(field, isImplementation = true, override = true, end = ",", notNull = field.notNull)
}
}
}
print(")")
@@ -106,7 +108,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
}
element.allFields.filter {
val bindingCalls = element.allFields.filter {
it.withBindThis && it.type.contains("Symbol") && it !is FieldList && it.name != "companionObjectSymbol"
}.takeIf {
it.isNotEmpty() && !isInterface && !isAbstract &&
@@ -114,12 +116,23 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
&& !element.type.contains("ResolvedQualifier")
&& !element.type.endsWith("Ref")
&& !element.type.endsWith("AnnotationsContainer")
}?.let { symbolFields ->
}.orEmpty()
val customCalls = fieldsWithoutDefault.filter { it.customInitializationCall != null }
if (bindingCalls.isNotEmpty() || customCalls.isNotEmpty()) {
println("init {")
for (symbolField in symbolFields) {
withIndent {
withIndent {
for (symbolField in bindingCalls) {
println("${symbolField.name}${symbolField.call()}bind(this)")
}
for (customCall in customCalls) {
customCall.optInAnnotation?.let {
println("@OptIn(${it.type}::class)")
}
println("${customCall.name} = ${customCall.customInitializationCall}")
}
}
println("}")
println()
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 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.
*/
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.tree.generator.model.*
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind
import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType
import java.io.File
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
class GeneratedFile(val file: File, val newText: String)
@@ -27,9 +28,19 @@ fun Builder.collectImports(): List<String> {
ImportKind.Builder,
) + implementation.fullQualifiedName!! + usedTypes.mapNotNull { it.fullQualifiedName } + builderDsl + "kotlin.contracts.*"
is IntermediateBuilder -> {
val fqns = parents + usedTypes.mapNotNull { it.fullQualifiedName } + allFields.mapNotNull { it.fullQualifiedName } + allFields.flatMap {
it.arguments.mapNotNull { it.fullQualifiedName }
} + (materializedElement?.fullQualifiedName ?: throw IllegalStateException(type)) + builderDsl
val fqns = buildList {
addAll(parents)
usedTypes.mapNotNullTo(this) { it.fullQualifiedName }
for (field in allFields) {
if (field.invisibleField) continue
field.fullQualifiedName?.let(this::add)
field.arguments.mapNotNullTo(this) { it.fullQualifiedName }
}
add(materializedElement?.fullQualifiedName ?: throw IllegalStateException(type))
add(builderDsl)
}
fqns.filterRedundantImports(packageName, ImportKind.Builder)
}
}.sorted()
@@ -64,22 +75,26 @@ fun Element.collectImports(): List<String> {
private fun Element.collectImportsInternal(base: List<String>, kind: ImportKind): List<String> {
val fqns = base + allFields.mapNotNull { it.fullQualifiedName } +
allFields.flatMap { it.overridenTypes.mapNotNull { it.fullQualifiedName } } +
allFields.flatMap { it.overridenTypes.mapNotNull { it.fullQualifiedName } + it.arbitraryImportables.mapNotNull { it.fullQualifiedName } } +
allFields.flatMap { it.arguments.mapNotNull { it.fullQualifiedName } } +
typeArguments.flatMap { it.upperBounds.mapNotNull { it.fullQualifiedName } }
val result = fqns.filterRedundantImports(packageName, kind) +
if (allFields.any { it is FieldList && it.isMutableOrEmpty }) {
when (kind) {
ImportKind.Implementation -> listOf(
"org.jetbrains.kotlin.fir.MutableOrEmptyList",
"org.jetbrains.kotlin.fir.builder.toMutableOrEmpty"
)
ImportKind.Builder -> listOf("org.jetbrains.kotlin.fir.builder.toMutableOrEmpty")
else -> emptyList()
}
} else {
emptyList()
}
val result = fqns.filterRedundantImports(packageName, kind).toMutableList()
if (allFields.any { it is FieldList && it.isMutableOrEmpty }) {
result += when (kind) {
ImportKind.Implementation -> listOf(
"org.jetbrains.kotlin.fir.MutableOrEmptyList",
"org.jetbrains.kotlin.fir.builder.toMutableOrEmpty"
)
ImportKind.Builder -> listOf("org.jetbrains.kotlin.fir.builder.toMutableOrEmpty")
else -> emptyList()
}
}
allFields.mapNotNull { it.optInAnnotation?.fullQualifiedName }.distinct().ifNotEmpty {
result += this
}
if (allFields.any { it.name == "source" && it.withReplace }) {
return (result + "org.jetbrains.kotlin.fir.FirImplementationDetail").distinct()
}