[FIR] Add ability to rewrite attributes in FirDeclarationAttributes
This commit is contained in:
+7
-5
@@ -18,8 +18,12 @@ class FirDeclarationAttributes : AttributeArrayOwner<FirDeclarationDataKey, Any>
|
|||||||
override val typeRegistry: TypeRegistry<FirDeclarationDataKey, Any>
|
override val typeRegistry: TypeRegistry<FirDeclarationDataKey, Any>
|
||||||
get() = FirDeclarationDataRegistry
|
get() = FirDeclarationDataRegistry
|
||||||
|
|
||||||
internal operator fun set(key: KClass<out FirDeclarationDataKey>, value: Any) {
|
internal operator fun set(key: KClass<out FirDeclarationDataKey>, value: Any?) {
|
||||||
registerComponent(key, value)
|
if (value == null) {
|
||||||
|
removeComponent(key)
|
||||||
|
} else {
|
||||||
|
registerComponent(key, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,9 +48,7 @@ object FirDeclarationDataRegistry : TypeRegistry<FirDeclarationDataKey, Any>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setValue(thisRef: FirDeclaration, property: KProperty<*>, value: V?) {
|
override fun setValue(thisRef: FirDeclaration, property: KProperty<*>, value: V?) {
|
||||||
if (value != null) {
|
thisRef.attributes[key] = value
|
||||||
thisRef.attributes[key] = value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ internal class OneElementArrayMap<T : Any>(val value: T, val index: Int) : Array
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ArrayMapImpl<T : Any> : ArrayMap<T>() {
|
internal class ArrayMapImpl<T : 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
|
||||||
@@ -56,13 +56,28 @@ internal class ArrayMapImpl<T : Any> : ArrayMap<T>() {
|
|||||||
|
|
||||||
override operator fun set(index: Int, value: T) {
|
override operator fun set(index: Int, value: T) {
|
||||||
ensureCapacity(index)
|
ensureCapacity(index)
|
||||||
|
if (data[index] == null) {
|
||||||
|
size++
|
||||||
|
}
|
||||||
data[index] = value
|
data[index] = value
|
||||||
|
|
||||||
size++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override operator fun get(index: Int): T? {
|
override operator fun get(index: Int): T? {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return data.getOrNull(index) as T?
|
return data.getOrNull(index) as T?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun remove(index: Int) {
|
||||||
|
if (data[index] != null) {
|
||||||
|
size--
|
||||||
|
}
|
||||||
|
data[index] = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun entries(): List<Entry<T>> {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return data.mapIndexedNotNull { index, value -> if (value != null) Entry(index, value as T) else null }
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Entry<T>(override val key: Int, override val value: T) : Map.Entry<Int, T>
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,9 @@ import kotlin.reflect.KClass
|
|||||||
* depending on array map fullness
|
* depending on array map fullness
|
||||||
* [AttributeArrayOwner] can be used in classes with many instances,
|
* [AttributeArrayOwner] can be used in classes with many instances,
|
||||||
* like user data for Fir elements or attributes for cone types
|
* like user data for Fir elements or attributes for cone types
|
||||||
|
*
|
||||||
|
* Note that you can remove attributes from [AttributeArrayOwner] despite
|
||||||
|
* from components in [ComponentArrayOwner]
|
||||||
*/
|
*/
|
||||||
abstract class AttributeArrayOwner<K : Any, T : Any> : AbstractArrayMapOwner<K, T>() {
|
abstract class AttributeArrayOwner<K : Any, T : Any> : AbstractArrayMapOwner<K, T>() {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@@ -36,4 +39,21 @@ abstract class AttributeArrayOwner<K : Any, T : Any> : AbstractArrayMapOwner<K,
|
|||||||
|
|
||||||
arrayMap[id] = value
|
arrayMap[id] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun removeComponent(tClass: KClass<out K>) {
|
||||||
|
val id = typeRegistry.getId(tClass)
|
||||||
|
if (arrayMap[id] == null) return
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
when (arrayMap.size) {
|
||||||
|
1 -> arrayMap = EmptyArrayMap as ArrayMap<T>
|
||||||
|
else -> {
|
||||||
|
val map = arrayMap as ArrayMapImpl<T>
|
||||||
|
map.remove(id)
|
||||||
|
if (map.size == 1) {
|
||||||
|
val (index, value) = map.entries().first()
|
||||||
|
arrayMap = OneElementArrayMap(value, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user