org.jetbrains.kotlin.contracts.model.MutableContextInfo.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2017 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.contracts.model
import org.jetbrains.kotlin.types.KotlinType
/**
* Collection of information about context.
*
* This class is pretty close semantically to DataFlowInfo, but
* supports broader variety of information (like, not just information
* about subtypes of a variable, but also about types that are definitely
* not subtypes of a variable).
*
* Also, it's abstracted away from PSI
*/
class MutableContextInfo private constructor(
val firedEffects: MutableList,
val subtypes: MutableMap>,
val notSubtypes: MutableMap>,
val equalValues: MutableMap>,
val notEqualValues: MutableMap>
) {
companion object {
val EMPTY: MutableContextInfo
get() = MutableContextInfo(
firedEffects = mutableListOf(),
subtypes = mutableMapOf(),
notSubtypes = mutableMapOf(),
equalValues = mutableMapOf(),
notEqualValues = mutableMapOf()
)
}
fun subtype(value: ESValue, type: KotlinType) = apply { subtypes.initAndAdd(value, type) }
fun notSubtype(value: ESValue, type: KotlinType) = apply { notSubtypes.initAndAdd(value, type) }
fun equal(left: ESValue, right: ESValue) = apply {
equalValues.initAndAdd(left, right)
equalValues.initAndAdd(right, left)
}
fun notEqual(left: ESValue, right: ESValue) = apply {
notEqualValues.initAndAdd(left, right)
notEqualValues.initAndAdd(right, left)
}
fun fire(effect: ESEffect) = apply { firedEffects += effect }
fun or(other: MutableContextInfo): MutableContextInfo = MutableContextInfo(
firedEffects = firedEffects.intersect(other.firedEffects).toMutableList(),
subtypes = subtypes.intersect(other.subtypes),
notSubtypes = notSubtypes.intersect(other.notSubtypes),
equalValues = equalValues.intersect(other.equalValues),
notEqualValues = notEqualValues.intersect(other.notEqualValues)
)
fun and(other: MutableContextInfo): MutableContextInfo = MutableContextInfo(
firedEffects = firedEffects.union(other.firedEffects).toMutableList(),
subtypes = subtypes.union(other.subtypes),
notSubtypes = notSubtypes.union(other.notSubtypes),
equalValues = equalValues.union(other.equalValues),
notEqualValues = notEqualValues.union(other.notEqualValues)
)
private fun MutableMap>.intersect(that: MutableMap>): MutableMap> {
val result = mutableMapOf>()
val allKeys = this.keys.intersect(that.keys)
allKeys.forEach {
val newValues = this[it]!!.intersect(that[it]!!)
if (newValues.isNotEmpty()) result[it] = newValues.toMutableSet()
}
return result
}
private fun Map>.union(that: Map>): MutableMap> {
val result = mutableMapOf>()
result.putAll(this)
that.entries.forEach { (thatKey, thatValue) ->
val oldValue = result[thatKey] ?: mutableSetOf()
oldValue.addAll(thatValue)
result[thatKey] = oldValue
}
return result
}
private fun MutableMap>.initAndAdd(key: ESValue, value: D) {
this.compute(key) { _, maybeValues ->
val setOfValues = maybeValues ?: mutableSetOf()
setOfValues.add(value)
setOfValues
}
}
fun print(): String = buildString {
val info = this@MutableContextInfo
fun Map>.printMapEntriesWithSeparator(separator: String) {
this.entries.filter { it.value.isNotEmpty() }.forEach { (key, value) ->
append(key.toString())
append(" $separator ")
appendLine(value.toString())
}
}
append("Fired effects: ")
append(info.firedEffects.joinToString(separator = ", "))
appendLine("")
subtypes.printMapEntriesWithSeparator("is")
notSubtypes.printMapEntriesWithSeparator("!is")
equalValues.printMapEntriesWithSeparator("==")
notEqualValues.printMapEntriesWithSeparator("!=")
this.toString()
}
}