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 set(index: Int, value: T)
abstract operator fun get(index: Int): T? abstract operator fun get(index: Int): T?
abstract fun copy(): ArrayMap<T>
} }
fun ArrayMap<*>.isEmpty(): Boolean = size == 0 fun ArrayMap<*>.isEmpty(): Boolean = size == 0
@@ -27,6 +29,8 @@ internal object EmptyArrayMap : ArrayMap<Nothing>() {
return null return null
} }
override fun copy(): ArrayMap<Nothing> = this
override fun iterator(): Iterator<Nothing> { override fun iterator(): Iterator<Nothing> {
return object : Iterator<Nothing> { return object : Iterator<Nothing> {
override fun hasNext(): Boolean = false 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 return if (index == this.index) value else null
} }
override fun copy(): ArrayMap<T> = OneElementArrayMap(value, index)
override fun iterator(): Iterator<T> { override fun iterator(): Iterator<T> {
return object : Iterator<T> { return object : Iterator<T> {
private var notVisited = true 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 { companion object {
private const val DEFAULT_SIZE = 20 private const val DEFAULT_SIZE = 20
private const val INCREASE_K = 2 private const val INCREASE_K = 2
} }
constructor() : this(arrayOfNulls<Any>(DEFAULT_SIZE))
override var size: Int = 0 override var size: Int = 0
private set private set
private var data = arrayOfNulls<Any>(DEFAULT_SIZE)
private fun ensureCapacity(index: Int) { private fun ensureCapacity(index: Int) {
if (data.size <= index) { if (data.size <= index) {
data = data.copyOf(data.size * INCREASE_K) data = data.copyOf(data.size * INCREASE_K)
@@ -97,6 +107,8 @@ internal class ArrayMapImpl<T : Any> : ArrayMap<T>() {
return data.getOrNull(index) as T? return data.getOrNull(index) as T?
} }
override fun copy(): ArrayMap<T> = ArrayMapImpl(data.copyOf())
override fun iterator(): Iterator<T> { override fun iterator(): Iterator<T> {
return object : AbstractIterator<T>() { return object : AbstractIterator<T>() {
private var index = -1 private var index = -1
@@ -17,11 +17,15 @@ import kotlin.reflect.KClass
* from components in [ComponentArrayOwner] * from components in [ComponentArrayOwner]
*/ */
@OptIn(Protected::class) @OptIn(Protected::class)
abstract class AttributeArrayOwner<K : Any, T : Any> : AbstractArrayMapOwner<K, T>() { abstract class AttributeArrayOwner<K : Any, T : Any> protected constructor(
@Suppress("UNCHECKED_CAST") arrayMap: ArrayMap<T>
final override var arrayMap: ArrayMap<T> = EmptyArrayMap as ArrayMap<T> ) : AbstractArrayMapOwner<K, T>() {
final override var arrayMap: ArrayMap<T> = arrayMap
private set private set
@Suppress("UNCHECKED_CAST")
constructor() : this(EmptyArrayMap as ArrayMap<T>)
final override fun registerComponent(tClass: KClass<out K>, value: T) { final override fun registerComponent(tClass: KClass<out K>, value: T) {
val id = typeRegistry.getId(tClass) val id = typeRegistry.getId(tClass)
when (arrayMap.size) { when (arrayMap.size) {
@@ -101,7 +101,7 @@ inline fun buildConstructorCopy(original: FirConstructor, init: FirConstructorBu
copyBuilder.session = original.session copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes copyBuilder.attributes = original.attributes.copy()
copyBuilder.returnTypeRef = original.returnTypeRef copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.receiverTypeRef = original.receiverTypeRef copyBuilder.receiverTypeRef = original.receiverTypeRef
copyBuilder.typeParameters.addAll(original.typeParameters) copyBuilder.typeParameters.addAll(original.typeParameters)
@@ -98,7 +98,7 @@ inline fun buildPropertyAccessorCopy(original: FirPropertyAccessor, init: FirPro
copyBuilder.session = original.session copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes copyBuilder.attributes = original.attributes.copy()
copyBuilder.returnTypeRef = original.returnTypeRef copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.valueParameters.addAll(original.valueParameters) copyBuilder.valueParameters.addAll(original.valueParameters)
copyBuilder.body = original.body copyBuilder.body = original.body
@@ -106,7 +106,7 @@ inline fun buildPropertyCopy(original: FirProperty, init: FirPropertyBuilder.()
copyBuilder.session = original.session copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes copyBuilder.attributes = original.attributes.copy()
copyBuilder.returnTypeRef = original.returnTypeRef copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.receiverTypeRef = original.receiverTypeRef copyBuilder.receiverTypeRef = original.receiverTypeRef
copyBuilder.name = original.name copyBuilder.name = original.name
@@ -101,7 +101,7 @@ inline fun buildSimpleFunctionCopy(original: FirSimpleFunction, init: FirSimpleF
copyBuilder.session = original.session copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes copyBuilder.attributes = original.attributes.copy()
copyBuilder.returnTypeRef = original.returnTypeRef copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.receiverTypeRef = original.receiverTypeRef copyBuilder.receiverTypeRef = original.receiverTypeRef
copyBuilder.valueParameters.addAll(original.valueParameters) copyBuilder.valueParameters.addAll(original.valueParameters)
@@ -86,7 +86,7 @@ inline fun buildValueParameterCopy(original: FirValueParameter, init: FirValuePa
copyBuilder.session = original.session copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin copyBuilder.origin = original.origin
copyBuilder.attributes = original.attributes copyBuilder.attributes = original.attributes.copy()
copyBuilder.returnTypeRef = original.returnTypeRef copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.name = original.name copyBuilder.name = original.name
copyBuilder.symbol = original.symbol copyBuilder.symbol = original.symbol
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.declarations 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.AttributeArrayOwner
import org.jetbrains.kotlin.fir.utils.NullableArrayMapAccessor import org.jetbrains.kotlin.fir.utils.NullableArrayMapAccessor
import org.jetbrains.kotlin.fir.utils.TypeRegistry import org.jetbrains.kotlin.fir.utils.TypeRegistry
@@ -14,10 +15,13 @@ import kotlin.reflect.KProperty
abstract class FirDeclarationDataKey abstract class FirDeclarationDataKey
class FirDeclarationAttributes : AttributeArrayOwner<FirDeclarationDataKey, Any>() { class FirDeclarationAttributes : AttributeArrayOwner<FirDeclarationDataKey, Any> {
override val typeRegistry: TypeRegistry<FirDeclarationDataKey, Any> override val typeRegistry: TypeRegistry<FirDeclarationDataKey, Any>
get() = FirDeclarationDataRegistry get() = FirDeclarationDataRegistry
constructor() : super()
private constructor(arrayMap: ArrayMap<Any>) : super(arrayMap)
internal operator fun set(key: KClass<out FirDeclarationDataKey>, value: Any?) { internal operator fun set(key: KClass<out FirDeclarationDataKey>, value: Any?) {
if (value == null) { if (value == null) {
removeComponent(key) removeComponent(key)
@@ -25,6 +29,8 @@ class FirDeclarationAttributes : AttributeArrayOwner<FirDeclarationDataKey, Any>
registerComponent(key, value) registerComponent(key, value)
} }
} }
fun copy(): FirDeclarationAttributes = FirDeclarationAttributes(arrayMap.copy())
} }
/* /*
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.tree.generator.printer 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 org.jetbrains.kotlin.fir.tree.generator.model.*
import java.io.File import java.io.File
@@ -294,8 +295,9 @@ private fun SmartPrinter.printDslBuildCopyFunction(
println("}") println("}")
println("val copyBuilder = $builderType()") println("val copyBuilder = $builderType()")
for (field in builder.allFields) { for (field in builder.allFields) {
when (field.origin) { when {
is FieldList -> println("copyBuilder.${field.name}.addAll(original.${field.name})") 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}") else -> println("copyBuilder.${field.name} = original.${field.name}")
} }
} }