FIR: Copy attributes when copying declaration

Otherwise they share FirDeclarationAttributes instance that might lead
to problems when modifying only one of them
This commit is contained in:
Denis Zharkov
2020-10-23 12:10:18 +03:00
parent 52c6aebec2
commit ecb89a66be
9 changed files with 40 additions and 16 deletions
@@ -10,6 +10,8 @@ sealed class ArrayMap<T : Any> : Iterable<T> {
abstract operator fun set(index: Int, value: T)
abstract operator fun get(index: Int): T?
abstract fun copy(): ArrayMap<T>
}
fun ArrayMap<*>.isEmpty(): Boolean = size == 0
@@ -27,6 +29,8 @@ internal object EmptyArrayMap : ArrayMap<Nothing>() {
return null
}
override fun copy(): ArrayMap<Nothing> = this
override fun iterator(): Iterator<Nothing> {
return object : Iterator<Nothing> {
override fun hasNext(): Boolean = false
@@ -48,6 +52,8 @@ internal class OneElementArrayMap<T : Any>(val value: T, val index: Int) : Array
return if (index == this.index) value else null
}
override fun copy(): ArrayMap<T> = OneElementArrayMap(value, index)
override fun iterator(): Iterator<T> {
return object : Iterator<T> {
private var notVisited = true
@@ -68,16 +74,20 @@ internal class OneElementArrayMap<T : Any>(val value: T, val index: Int) : Array
}
}
internal class ArrayMapImpl<T : Any> : ArrayMap<T>() {
internal class ArrayMapImpl<T : Any> private constructor(
private var data: Array<Any?>
) : ArrayMap<T>() {
companion object {
private const val DEFAULT_SIZE = 20
private const val INCREASE_K = 2
}
constructor() : this(arrayOfNulls<Any>(DEFAULT_SIZE))
override var size: Int = 0
private set
private var data = arrayOfNulls<Any>(DEFAULT_SIZE)
private fun ensureCapacity(index: Int) {
if (data.size <= index) {
data = data.copyOf(data.size * INCREASE_K)
@@ -97,6 +107,8 @@ internal class ArrayMapImpl<T : Any> : ArrayMap<T>() {
return data.getOrNull(index) as T?
}
override fun copy(): ArrayMap<T> = ArrayMapImpl(data.copyOf())
override fun iterator(): Iterator<T> {
return object : AbstractIterator<T>() {
private var index = -1
@@ -128,4 +140,4 @@ internal class ArrayMapImpl<T : Any> : ArrayMap<T>() {
}
data class Entry<T>(override val key: Int, override val value: T) : Map.Entry<Int, T>
}
}
@@ -17,11 +17,15 @@ import kotlin.reflect.KClass
* from components in [ComponentArrayOwner]
*/
@OptIn(Protected::class)
abstract class AttributeArrayOwner<K : Any, T : Any> : AbstractArrayMapOwner<K, T>() {
@Suppress("UNCHECKED_CAST")
final override var arrayMap: ArrayMap<T> = EmptyArrayMap as ArrayMap<T>
abstract class AttributeArrayOwner<K : Any, T : Any> protected constructor(
arrayMap: ArrayMap<T>
) : AbstractArrayMapOwner<K, T>() {
final override var arrayMap: ArrayMap<T> = arrayMap
private set
@Suppress("UNCHECKED_CAST")
constructor() : this(EmptyArrayMap as ArrayMap<T>)
final override fun registerComponent(tClass: KClass<out K>, value: T) {
val id = typeRegistry.getId(tClass)
when (arrayMap.size) {
@@ -61,4 +65,4 @@ abstract class AttributeArrayOwner<K : Any, T : Any> : AbstractArrayMapOwner<K,
}
}
}
}
}
@@ -101,7 +101,7 @@ inline fun buildConstructorCopy(original: FirConstructor, init: FirConstructorBu
copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes
copyBuilder.attributes = original.attributes.copy()
copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.receiverTypeRef = original.receiverTypeRef
copyBuilder.typeParameters.addAll(original.typeParameters)
@@ -98,7 +98,7 @@ inline fun buildPropertyAccessorCopy(original: FirPropertyAccessor, init: FirPro
copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes
copyBuilder.attributes = original.attributes.copy()
copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.valueParameters.addAll(original.valueParameters)
copyBuilder.body = original.body
@@ -106,7 +106,7 @@ inline fun buildPropertyCopy(original: FirProperty, init: FirPropertyBuilder.()
copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes
copyBuilder.attributes = original.attributes.copy()
copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.receiverTypeRef = original.receiverTypeRef
copyBuilder.name = original.name
@@ -101,7 +101,7 @@ inline fun buildSimpleFunctionCopy(original: FirSimpleFunction, init: FirSimpleF
copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes
copyBuilder.attributes = original.attributes.copy()
copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.receiverTypeRef = original.receiverTypeRef
copyBuilder.valueParameters.addAll(original.valueParameters)
@@ -86,7 +86,7 @@ inline fun buildValueParameterCopy(original: FirValueParameter, init: FirValuePa
copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes
copyBuilder.attributes = original.attributes.copy()
copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.name = original.name
copyBuilder.symbol = original.symbol
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.fir.utils.ArrayMap
import org.jetbrains.kotlin.fir.utils.AttributeArrayOwner
import org.jetbrains.kotlin.fir.utils.NullableArrayMapAccessor
import org.jetbrains.kotlin.fir.utils.TypeRegistry
@@ -14,10 +15,13 @@ import kotlin.reflect.KProperty
abstract class FirDeclarationDataKey
class FirDeclarationAttributes : AttributeArrayOwner<FirDeclarationDataKey, Any>() {
class FirDeclarationAttributes : AttributeArrayOwner<FirDeclarationDataKey, Any> {
override val typeRegistry: TypeRegistry<FirDeclarationDataKey, Any>
get() = FirDeclarationDataRegistry
constructor() : super()
private constructor(arrayMap: ArrayMap<Any>) : super(arrayMap)
internal operator fun set(key: KClass<out FirDeclarationDataKey>, value: Any?) {
if (value == null) {
removeComponent(key)
@@ -25,6 +29,8 @@ class FirDeclarationAttributes : AttributeArrayOwner<FirDeclarationDataKey, Any>
registerComponent(key, value)
}
}
fun copy(): FirDeclarationAttributes = FirDeclarationAttributes(arrayMap.copy())
}
/*
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.tree.generator.printer
import org.jetbrains.kotlin.fir.tree.generator.declarationAttributesType
import org.jetbrains.kotlin.fir.tree.generator.model.*
import java.io.File
@@ -294,12 +295,13 @@ private fun SmartPrinter.printDslBuildCopyFunction(
println("}")
println("val copyBuilder = $builderType()")
for (field in builder.allFields) {
when (field.origin) {
is FieldList -> println("copyBuilder.${field.name}.addAll(original.${field.name})")
when {
field.origin is FieldList -> println("copyBuilder.${field.name}.addAll(original.${field.name})")
field.type == declarationAttributesType.type -> println("copyBuilder.${field.name} = original.${field.name}.copy()")
else -> println("copyBuilder.${field.name} = original.${field.name}")
}
}
println("return copyBuilder.apply(init).build()")
}
println("}")
}
}