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.utils.AttributeArrayOwner
import org.jetbrains.kotlin.fir.utils.Protected
import org.jetbrains.kotlin.fir.utils.TypeRegistry
import org.jetbrains.kotlin.fir.utils.isEmpty
import org.jetbrains.kotlin.utils.addIfNotNull
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KClass

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

    abstract override fun toString(): String

    abstract val key: KClass
}

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

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

        val Empty: ConeAttributes = ConeAttributes(emptyList())
        internal val WithFlexibleNullability: ConeAttributes = ConeAttributes(listOf(CompilerConeAttributes.FlexibleNullability))

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

    init {
        for (attribute in attributes) {
            registerComponent(attribute.key, attribute)
        }
        assert(!hasEnhancedNullability || !hasFlexibleNullability) {
            "It doesn't make sense to have @EnhancedNullability and @FlexibleNullability at the same time."
        }
    }

    val hasEnhancedNullability: Boolean
        get() = enhancedNullability != null

    val hasFlexibleNullability: Boolean
        get() = flexibleNullability != null

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

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

    override fun iterator(): Iterator> {
        return arrayMap.iterator()
    }

    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 = when {
                a == null -> b?.op(a)
                else -> a.op(b)
            }
            attributes.addIfNotNull(res)
        }
        return create(attributes)
    }

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

    private fun isEmpty(): Boolean {
        return arrayMap.isEmpty()
    }
}

private fun ConeAttributes.intersectUnless(other: ConeAttributes, predicate: (ConeAttributes) -> Boolean): ConeAttributes =
    if (predicate.invoke(this)) this else intersect(other)

fun ConeAttributes.withFlexible(): ConeAttributes =
    intersect(ConeAttributes.WithFlexibleNullability)

fun ConeAttributes.withFlexibleUnless(predicate: (ConeAttributes) -> Boolean): ConeAttributes =
    intersectUnless(ConeAttributes.WithFlexibleNullability, predicate)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy