All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.fir.types.ConeAttributes.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * 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.types

import org.jetbrains.kotlin.fir.util.ConeTypeRegistry
import org.jetbrains.kotlin.types.model.AnnotationMarker
import org.jetbrains.kotlin.util.AttributeArrayOwner
import org.jetbrains.kotlin.util.TypeRegistry
import org.jetbrains.kotlin.utils.addIfNotNull
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KClass

abstract class ConeAttribute> : AnnotationMarker {
    abstract fun union(other: @UnsafeVariance T?): T?
    abstract fun intersect(other: @UnsafeVariance T?): T?

    /*
     * This function is used to decide how multiple attributes should be united in presence of typealiases:
     * typealias B = @SomeAttribute(1) A
     * typealias C = @SomeAttribute(2) B
     *
     * For determining attribute value of expanded type of C we should add @SomeAttribute(2) to @SomeAttribute(1)
     *
     * This function must be symmetrical: a.add(b) == b.add(a)
     */
    abstract fun add(other: @UnsafeVariance T?): T?
    abstract fun isSubtypeOf(other: @UnsafeVariance T?): Boolean

    abstract override fun toString(): String

    abstract val key: KClass
}

typealias ConeAttributeKey = KClass>

class ConeAttributes private constructor(attributes: List>) : AttributeArrayOwner, ConeAttribute<*>>(),
    Iterable> {

    companion object : ConeTypeRegistry, ConeAttribute<*>>() {
        inline fun > attributeAccessor(): ReadOnlyProperty {
            @Suppress("UNCHECKED_CAST")
            return generateNullableAccessor, T>(T::class) as ReadOnlyProperty
        }

        val Empty: ConeAttributes = ConeAttributes(emptyList())
        val WithExtensionFunctionType: ConeAttributes = ConeAttributes(listOf(CompilerConeAttributes.ExtensionFunctionType))

        private val predefinedAttributes: Map, ConeAttributes> = mapOf(
            CompilerConeAttributes.EnhancedNullability.predefined()
        )

        private fun ConeAttribute<*>.predefined(): Pair, ConeAttributes> = this to ConeAttributes(this)

        fun create(attributes: List>): ConeAttributes {
            return if (attributes.isEmpty()) {
                Empty
            } else {
                ConeAttributes(attributes)
            }
        }
    }

    private constructor(attribute: ConeAttribute<*>) : this(listOf(attribute))

    init {
        for (attribute in attributes) {
            registerComponent(attribute.key, attribute)
        }
    }

    fun union(other: ConeAttributes): ConeAttributes {
        return perform(other) { this.union(it) }
    }

    fun intersect(other: ConeAttributes): ConeAttributes {
        return perform(other) { this.intersect(it) }
    }

    fun add(other: ConeAttributes): ConeAttributes {
        return perform(other) { this.add(it) }
    }

    operator fun contains(attribute: ConeAttribute<*>): Boolean {
        return contains(attribute.key)
    }

    operator fun contains(attributeKey: KClass>): Boolean {
        val index = getId(attributeKey)
        return arrayMap[index] != null
    }

    @OptIn(ExperimentalStdlibApi::class)
    operator fun plus(attribute: ConeAttribute<*>): ConeAttributes {
        if (attribute in this) return this
        if (isEmpty()) return predefinedAttributes[attribute] ?: ConeAttributes(attribute)
        val newAttributes = buildList {
            addAll(this)
            add(attribute)
        }
        return ConeAttributes(newAttributes)
    }

    fun remove(attribute: ConeAttribute<*>): ConeAttributes {
        if (isEmpty()) return this
        val attributes = arrayMap.filter { it != attribute }
        if (attributes.size == arrayMap.size) return this
        return create(attributes)
    }

    private inline fun perform(other: ConeAttributes, op: ConeAttribute<*>.(ConeAttribute<*>?) -> ConeAttribute<*>?): ConeAttributes {
        if (this.isEmpty() && other.isEmpty()) return this
        val attributes = mutableListOf>()
        for (index in indices) {
            val a = arrayMap[index]
            val b = other.arrayMap[index]
            val res = if (a == null) b?.op(a) else a.op(b)
            attributes.addIfNotNull(res)
        }
        return create(attributes)
    }

    override val typeRegistry: TypeRegistry, ConeAttribute<*>>
        get() = Companion
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy