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

org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2015 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jetbrains.kotlin.resolve.calls.smartcasts

import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.JetType

/**
 * This class describes an arbitrary object which has some value in data flow analysis.
 * In general case it's some r-value.
 */
class DataFlowValue(val id: Any?, val type: JetType, val kind: DataFlowValue.Kind, val immanentNullability: Nullability) {

    enum class Kind(private val name: String) {
        // Smart casts are completely safe
        STABLE_VALUE("stable"),
        // Smart casts are safe but possible changes in loops / closures ahead must be taken into account
        PREDICTABLE_VARIABLE("predictable"),
        // Smart casts are not safe
        UNPREDICTABLE_VARIABLE("unpredictable"),
        OTHER("other");

        override fun toString() = name

        fun isStable() = this == STABLE_VALUE
    }

    /**
     * Both stable values and predictable local variables are considered "predictable".
     * Predictable means here we do not expect some sudden change of their values,
     * like accessing mutable properties in another thread, so smart casts can be used safely.
     */
    val isPredictable = (kind == Kind.STABLE_VALUE || kind == Kind.PREDICTABLE_VARIABLE)
        @JvmName("isPredictable") get

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is DataFlowValue) return false

        if (kind.isStable() != other.kind.isStable()) return false
        if (id != other.id) return false
        if (type != other.type) return false

        return true
    }

    override fun toString(): String {
        return kind.toString() + (id?.toString()) + " " + immanentNullability
    }

    override fun hashCode(): Int {
        var result = if (kind.isStable()) 1 else 0
        result = 31 * result + (type?.hashCode() ?: 0)
        result = 31 * result + (id?.hashCode() ?: 0)
        return result
    }

    companion object {

        val NULL  = DataFlowValue(Object(), KotlinBuiltIns.getInstance().nullableNothingType, Kind.OTHER, Nullability.NULL)
        val ERROR = DataFlowValue(Object(), ErrorUtils.createErrorType("Error type for data flow"), Kind.OTHER, Nullability.IMPOSSIBLE)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy