IDEA-313062 removed usage of kotlin sequence builder inside prefix tree

removed usages of FList

GitOrigin-RevId: 630fba859a3e5004ce26c1d90edce47d0f5e3377
This commit is contained in:
Sergei Vorobyov
2023-03-13 16:18:35 +00:00
committed by intellij-monorepo-bot
parent f02efddf74
commit 7bf2838b68
9 changed files with 139 additions and 220 deletions
@@ -34,7 +34,7 @@ class AsyncFilesChangesListener(
filesProvider.supply(parentDisposable) { filesToWatch ->
val index = CanonicalPathPrefixTreeFactory.createSet(filesToWatch)
val updatedWatchedFiles = updatedFilesSnapshot.flatMap { (path, modificationData) ->
index.getDescendantSequence(path)
index.getDescendants(path)
.map { it to modificationData }
}
if (updatedWatchedFiles.isNotEmpty()) {
@@ -257,7 +257,7 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage
override fun getState(): SourceFolderManagerState {
synchronized(mutex) {
return SourceFolderManagerState(sourceFolders.getValueSequence()
return SourceFolderManagerState(sourceFolders.values
.mapNotNull { model ->
val modelTypeName = dictionary.entries.find { it.value == model.type }?.key
?: return@mapNotNull null
@@ -266,8 +266,7 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage
modelTypeName,
model.packagePrefix,
model.generated)
}
.toList())
})
}
}
@@ -18,12 +18,6 @@ internal class OptionalKt<out T : Any?> private constructor(
return !isPresent
}
inline fun ifPresent(action: (T) -> Unit) {
if (isPresent()) {
action(get())
}
}
fun get(): T {
@Suppress("UNCHECKED_CAST")
if (isPresent) {
@@ -32,13 +26,6 @@ internal class OptionalKt<out T : Any?> private constructor(
throw NoSuchElementException("No value present")
}
fun getOrNull(): T? {
if (isPresent) {
return get()
}
return null
}
companion object {
val EMPTY = OptionalKt<Nothing>(false, null)
@@ -54,6 +41,10 @@ internal class OptionalKt<out T : Any?> private constructor(
return EMPTY
}
fun <T> OptionalKt<T>.getOrNull(): T? {
return getOrDefault(null)
}
fun <T> OptionalKt<T>.getOrDefault(defaultValue: T): T {
if (isPresent) {
return get()
@@ -9,12 +9,6 @@ import org.jetbrains.annotations.ApiStatus
@ApiStatus.NonExtendable
interface PrefixTreeMap<Key, Value> : Map<Key, Value> {
fun getKeySequence(): Sequence<Key>
fun getValueSequence(): Sequence<Value>
fun getEntrySequence(): Sequence<Pair<Key, Value>>
/**
* Returns descendant keys for [key].
*
@@ -25,13 +19,7 @@ interface PrefixTreeMap<Key, Value> : Map<Key, Value> {
fun getDescendantValues(key: Key): List<Value>
fun getDescendantEntries(key: Key): Map<Key, Value>
fun getDescendantKeySequence(key: Key): Sequence<Key>
fun getDescendantValueSequence(key: Key): Sequence<Value>
fun getDescendantEntrySequence(key: Key): Sequence<Pair<Key, Value>>
fun getDescendantEntries(key: Key): Set<Map.Entry<Key, Value>>
/**
* Returns ancestor elements for [key].
@@ -43,13 +31,7 @@ interface PrefixTreeMap<Key, Value> : Map<Key, Value> {
fun getAncestorValues(key: Key): List<Value>
fun getAncestorEntries(key: Key): Map<Key, Value>
fun getAncestorKeySequence(key: Key): Sequence<Key>
fun getAncestorValueSequence(key: Key): Sequence<Value>
fun getAncestorEntrySequence(key: Key): Sequence<Pair<Key, Value>>
fun getAncestorEntries(key: Key): Set<Map.Entry<Key, Value>>
/**
* Returns root keys in this map.
@@ -61,11 +43,5 @@ interface PrefixTreeMap<Key, Value> : Map<Key, Value> {
fun getRootValues(): List<Value>
fun getRootEntries(): Map<Key, Value>
fun getRootKeySequence(): Sequence<Key>
fun getRootValueSequence(): Sequence<Value>
fun getRootEntrySequence(): Sequence<Pair<Key, Value>>
fun getRootEntries(): Set<Map.Entry<Key, Value>>
}
@@ -1,9 +1,9 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.containers.prefix.map
import com.intellij.util.containers.FList
import com.intellij.util.containers.OptionalKt
import com.intellij.util.containers.OptionalKt.Companion.getOrDefault
import com.intellij.util.containers.OptionalKt.Companion.getOrNull
import com.intellij.util.containers.OptionalKt.Companion.map
import com.intellij.util.containers.prefix.factory.PrefixTreeFactory
import org.jetbrains.annotations.ApiStatus
@@ -20,152 +20,104 @@ internal class PrefixTreeMapImpl<Key, KeyElement, Value>(
get() = root.getSize()
override val keys: Set<Key>
get() = getKeySequence().toSet()
get() = root.getValues().toKeySet()
override val values: Collection<Value>
get() = getValueSequence().toList()
get() = root.getValues().toValueList()
override val entries: Set<Map.Entry<Key, Value>>
get() = root.getEntrySequence().toEntrySet()
override fun getKeySequence(): Sequence<Key> {
return root.getEntrySequence().toKeySequence()
}
override fun getValueSequence(): Sequence<Value> {
return root.getEntrySequence().toValueSequence()
}
override fun getEntrySequence(): Sequence<Pair<Key, Value>> {
return root.getEntrySequence().toEntrySequence()
}
get() = root.getValues().toEntrySet()
override fun isEmpty(): Boolean {
return root.isEmpty()
}
override fun get(key: Key): Value? {
return root.findValue(key.asPrefixKey()).toValue().getOrNull()
return root.getValue(key.toList()).getOrNull()
}
override fun getOrDefault(key: Key, defaultValue: Value): Value {
return root.findValue(key.asPrefixKey()).toValue().getOrDefault(defaultValue)
return root.getValue(key.toList()).getOrDefault(defaultValue)
}
override fun set(key: Key, value: Value): Value? {
return root.setValue(key.asPrefixKey(), key to value).toValue().getOrNull()
return root.setValue(key.toList(), key to value).getOrNull()
}
override fun remove(key: Key): Value? {
return root.removeValue(key.asPrefixKey()).toValue().getOrNull()
return root.removeValue(key.toList()).getOrNull()
}
override fun containsKey(key: Key): Boolean {
return root.containsKey(key.asPrefixKey())
return root.containsKey(key.toList())
}
override fun containsValue(value: Value): Boolean {
return getValueSequence().any { it == value }
return root.getValues().any { it.second == value }
}
override fun forEach(action: BiConsumer<in Key, in Value>) {
getEntrySequence().forEach { action.accept(it.first, it.second) }
root.getValues().forEach { action.accept(it.first, it.second) }
}
override fun getDescendantKeys(key: Key): Set<Key> {
return getDescendantKeySequence(key).toSet()
return root.getDescendantValues(key.toList()).toKeySet()
}
override fun getDescendantValues(key: Key): List<Value> {
return getDescendantValueSequence(key).toList()
return root.getDescendantValues(key.toList()).toValueList()
}
override fun getDescendantEntries(key: Key): Map<Key, Value> {
return getDescendantEntrySequence(key).toMap()
}
override fun getDescendantKeySequence(key: Key): Sequence<Key> {
return root.getDescendantEntrySequence(key.asPrefixKey()).toKeySequence()
}
override fun getDescendantValueSequence(key: Key): Sequence<Value> {
return root.getDescendantEntrySequence(key.asPrefixKey()).toValueSequence()
}
override fun getDescendantEntrySequence(key: Key): Sequence<Pair<Key, Value>> {
return root.getDescendantEntrySequence(key.asPrefixKey()).toEntrySequence()
override fun getDescendantEntries(key: Key): Set<Map.Entry<Key, Value>> {
return root.getDescendantValues(key.toList()).toEntrySet()
}
override fun getAncestorKeys(key: Key): Set<Key> {
return getAncestorKeySequence(key).toSet()
return root.getAncestorValues(key.toList()).toKeySet()
}
override fun getAncestorValues(key: Key): List<Value> {
return getAncestorValueSequence(key).toList()
return root.getAncestorValues(key.toList()).toValueList()
}
override fun getAncestorEntries(key: Key): Map<Key, Value> {
return getAncestorEntrySequence(key).toMap()
}
override fun getAncestorKeySequence(key: Key): Sequence<Key> {
return root.getAncestorEntrySequence(key.asPrefixKey()).toKeySequence()
}
override fun getAncestorValueSequence(key: Key): Sequence<Value> {
return root.getAncestorEntrySequence(key.asPrefixKey()).toValueSequence()
}
override fun getAncestorEntrySequence(key: Key): Sequence<Pair<Key, Value>> {
return root.getAncestorEntrySequence(key.asPrefixKey()).toEntrySequence()
override fun getAncestorEntries(key: Key): Set<Map.Entry<Key, Value>> {
return root.getAncestorValues(key.toList()).toEntrySet()
}
override fun getRootKeys(): Set<Key> {
return getRootKeySequence().toSet()
return root.getRootValues().toKeySet()
}
override fun getRootValues(): List<Value> {
return getRootValueSequence().toList()
return root.getRootValues().toValueList()
}
override fun getRootEntries(): Map<Key, Value> {
return getRootEntrySequence().toMap()
override fun getRootEntries(): Set<Map.Entry<Key, Value>> {
return root.getRootValues().toEntrySet()
}
override fun getRootKeySequence(): Sequence<Key> {
return root.getRootEntrySequence().toKeySequence()
private fun Key.toList(): List<KeyElement> {
return convertor.convertToList(this)
}
override fun getRootValueSequence(): Sequence<Value> {
return root.getRootEntrySequence().toValueSequence()
private fun OptionalKt<Pair<Key, Value>>.getOrNull(): Value? {
return map { it.second }.getOrNull()
}
override fun getRootEntrySequence(): Sequence<Pair<Key, Value>> {
return root.getRootEntrySequence().toEntrySequence()
private fun OptionalKt<Pair<Key, Value>>.getOrDefault(defaultValue: Value): Value {
return map { it.second }.getOrDefault(defaultValue)
}
private fun Key.asPrefixKey(): FList<KeyElement> {
return FList.createFromReversed(convertor.convertToList(this).asReversed())
private fun List<Pair<Key, Value>>.toKeySet(): Set<Key> {
return mapTo(LinkedHashSet()) { it.first }
}
private fun OptionalKt<Pair<Key, Value>>.toValue(): OptionalKt<Value> {
private fun List<Pair<Key, Value>>.toValueList(): List<Value> {
return map { it.second }
}
private fun Sequence<Pair<List<KeyElement>, Pair<Key, Value>>>.toKeySequence(): Sequence<Key> {
return map { it.second.first }
}
private fun Sequence<Pair<List<KeyElement>, Pair<Key, Value>>>.toValueSequence(): Sequence<Value> {
return map { it.second.second }
}
private fun Sequence<Pair<List<KeyElement>, Pair<Key, Value>>>.toEntrySequence(): Sequence<Pair<Key, Value>> {
return map { it.second }
}
private fun Sequence<Pair<List<KeyElement>, Pair<Key, Value>>>.toEntrySet(): Set<Map.Entry<Key, Value>> {
return mapTo(LinkedHashSet()) { it.second.toEntry() }
private fun List<Pair<Key, Value>>.toEntrySet(): Set<Map.Entry<Key, Value>> {
return mapTo(LinkedHashSet()) { it.toEntry() }
}
private fun Pair<Key, Value>.toEntry(): Map.Entry<Key, Value> {
@@ -1,7 +1,6 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.containers.prefix.map
import com.intellij.util.containers.FList
import com.intellij.util.containers.OptionalKt
import org.jetbrains.annotations.ApiStatus
import java.util.LinkedHashMap
@@ -27,12 +26,21 @@ internal class PrefixTreeNode<Key, Value> {
return size
}
fun findValue(key: FList<Key>): OptionalKt<Value> {
fun getValue(key: List<Key>): OptionalKt<Value> {
return findNode(key)?.state ?: OptionalKt.EMPTY
}
fun setValue(key: FList<Key>, value: Value): OptionalKt<Value> {
if (key.isEmpty()) {
fun setValue(key: List<Key>, value: Value): OptionalKt<Value> {
return setValue(0, key, value)
}
fun removeValue(key: List<Key>): OptionalKt<Value> {
return removeValue(0, key)
}
private fun setValue(index: Int, key: List<Key>, value: Value): OptionalKt<Value> {
require(index >= 0 && index <= key.size) { "Index $index out of bound [0, " + key.size + "]" }
if (index == key.size) {
val previousState = state
state = OptionalKt.of(value)
if (!previousState.isPresent()) {
@@ -40,16 +48,17 @@ internal class PrefixTreeNode<Key, Value> {
}
return previousState
}
val childNode = children.getOrPut(key.head) { PrefixTreeNode() }
val previousState = childNode.setValue(key.tail, value)
val childNode = children.getOrPut(key[index]) { PrefixTreeNode() }
val previousState = childNode.setValue(index + 1, key, value)
if (!previousState.isPresent()) {
size += 1
}
return previousState
}
fun removeValue(key: FList<Key>): OptionalKt<Value> {
if (key.isEmpty()) {
private fun removeValue(index: Int, key: List<Key>): OptionalKt<Value> {
require(index >= 0 && index <= key.size) { "Index $index out of bound [0, " + key.size + "]" }
if (index == key.size) {
val previousState = state
state = OptionalKt.EMPTY
if (previousState.isPresent()) {
@@ -57,10 +66,10 @@ internal class PrefixTreeNode<Key, Value> {
}
return previousState
}
val childNode = children[key.head] ?: return OptionalKt.EMPTY
val previousState = childNode.removeValue(key.tail)
val childNode = children[key[index]] ?: return OptionalKt.EMPTY
val previousState = childNode.removeValue(index + 1, key)
if (childNode.isEmpty()) {
children.remove(key.head)
children.remove(key[index])
}
if (previousState.isPresent()) {
size -= 1
@@ -68,69 +77,85 @@ internal class PrefixTreeNode<Key, Value> {
return previousState
}
fun containsKey(key: FList<Key>): Boolean {
if (key.isEmpty()) {
return state.isPresent()
}
val child = children[key.head] ?: return false
return child.containsKey(key.tail)
fun containsKey(key: List<Key>): Boolean {
val node = findNode(key) ?: return false
return node.state.isPresent()
}
fun findNode(key: FList<Key>): PrefixTreeNode<Key, Value>? {
if (key.isEmpty()) {
return this
}
val child = children[key.head] ?: return null
return child.findNode(key.tail)
}
fun getEntrySequence(): Sequence<Pair<FList<Key>, Value>> {
return sequence {
state.ifPresent {
yield(FList.emptyList<Key>() to it)
fun getValues(): List<Value> {
val result = ArrayList<Value>()
traverseTree { state ->
if (state.isPresent()) {
result.add(state.get())
}
for ((keyPrefix, child) in children) {
for ((key, value) in child.getEntrySequence()) {
yield(key.prepend(keyPrefix) to value)
TraverseDecision.CONTINUE
}
return result
}
fun getAncestorValues(key: List<Key>): List<Value> {
val result = ArrayList<Value>()
traverseNode(key) { state ->
if (state.isPresent()) {
result.add(state.get())
}
}
return result
}
fun getDescendantValues(key: List<Key>): List<Value> {
val node = findNode(key) ?: return emptyList()
val result = ArrayList<Value>()
for (value in node.getValues()) {
result.add(value)
}
return result
}
fun getRootValues(): List<Value> {
val result = ArrayList<Value>()
traverseTree { state ->
if (state.isPresent()) {
result.add(state.get())
}
when (state.isPresent()) {
true -> TraverseDecision.DO_NOT_GO_DEEPER
else -> TraverseDecision.CONTINUE
}
}
return result
}
private fun findNode(key: List<Key>): PrefixTreeNode<Key, Value>? {
return traverseNode(key) {}
}
private fun traverseNode(key: List<Key>, process: (OptionalKt<Value>) -> Unit): PrefixTreeNode<Key, Value>? {
var node = this
process(node.state)
for (keyElement in key) {
node = node.children[keyElement] ?: return null
process(node.state)
}
return node
}
private fun traverseTree(process: (OptionalKt<Value>) -> TraverseDecision) {
val queue = ArrayDeque<PrefixTreeNode<Key, Value>>()
queue.addLast(this)
while (queue.isNotEmpty()) {
val node = queue.removeFirst()
when (process(node.state)) {
TraverseDecision.STOP -> break
TraverseDecision.DO_NOT_GO_DEEPER -> continue
TraverseDecision.CONTINUE -> {
for (child in node.children.values) {
queue.add(child)
}
}
}
}
}
fun getAncestorEntrySequence(key: FList<Key>): Sequence<Pair<FList<Key>, Value>> {
return sequence {
state.ifPresent {
yield(FList.emptyList<Key>() to it)
}
if (key.isEmpty()) {
return@sequence
}
val childNode = children[key.head] ?: return@sequence
for ((keyPostfix, value) in childNode.getAncestorEntrySequence(key.tail)) {
yield(keyPostfix.prepend(key.head) to value)
}
}
}
fun getDescendantEntrySequence(key: FList<Key>): Sequence<Pair<List<Key>, Value>> {
val node = findNode(key) ?: return emptySequence()
return sequence {
for ((keyPostfix, value) in node.getEntrySequence()) {
yield(key + keyPostfix to value)
}
}
}
fun getRootEntrySequence(): Sequence<Pair<FList<Key>, Value>> {
state.ifPresent {
return sequenceOf(FList.emptyList<Key>() to it)
}
return sequence {
for ((key, childNode) in children) {
for ((keyPostfix, value) in childNode.getRootEntrySequence()) {
yield(keyPostfix.prepend(key) to value)
}
}
}
}
private enum class TraverseDecision { CONTINUE, STOP, DO_NOT_GO_DEEPER }
}
@@ -15,8 +15,6 @@ import org.jetbrains.annotations.ApiStatus
@ApiStatus.NonExtendable
interface PrefixTreeSet<Key> : Set<Key> {
fun asSequence(): Sequence<Key>
/**
* Returns descendant elements for [element].
*
@@ -25,8 +23,6 @@ interface PrefixTreeSet<Key> : Set<Key> {
*/
fun getDescendants(element: Key): Set<Key>
fun getDescendantSequence(element: Key): Sequence<Key>
/**
* Returns ancestor elements for [element].
*
@@ -35,8 +31,6 @@ interface PrefixTreeSet<Key> : Set<Key> {
*/
fun getAncestors(element: Key): Set<Key>
fun getAncestorSequence(element: Key): Sequence<Key>
/**
* Returns root elements in this set.
*
@@ -44,6 +38,4 @@ interface PrefixTreeSet<Key> : Set<Key> {
* Then root elements are `[a,b,c]` and `[a,f,g]`.
*/
fun getRoots(): Set<Key>
fun getRootSequence(): Sequence<Key>
}
@@ -14,10 +14,6 @@ internal class PrefixTreeSetImpl<Key, KeyElement>(
override val size: Int
get() = map.size
override fun asSequence(): Sequence<Key> {
return map.getKeySequence()
}
override fun isEmpty(): Boolean {
return map.isEmpty()
}
@@ -34,26 +30,14 @@ internal class PrefixTreeSetImpl<Key, KeyElement>(
return map.getDescendantKeys(element)
}
override fun getDescendantSequence(element: Key): Sequence<Key> {
return map.getDescendantKeySequence(element)
}
override fun getAncestors(element: Key): Set<Key> {
return map.getAncestorKeys(element)
}
override fun getAncestorSequence(element: Key): Sequence<Key> {
return map.getAncestorKeySequence(element)
}
override fun getRoots(): Set<Key> {
return map.getRootKeys()
}
override fun getRootSequence(): Sequence<Key> {
return map.getRootKeySequence()
}
override fun add(element: Key) {
map[element] = null
}
@@ -63,6 +47,6 @@ internal class PrefixTreeSetImpl<Key, KeyElement>(
}
override fun iterator(): Iterator<Key> {
return asSequence().iterator()
return map.keys.iterator()
}
}
@@ -56,7 +56,7 @@ private fun getGradleTaskNodesMap(project: Project): Map<String, MultiMap<String
for ((gradlePath, externalModulePath) in modulePaths) {
val moduleTasks = tasks.computeIfAbsent(externalModulePath) { MultiMap.createOrderedSet() }
for (childModulePath in modulePaths.getDescendantKeySequence(gradlePath)) {
for (childModulePath in modulePaths.getDescendantKeys(gradlePath)) {
moduleTasks.putValues(childModulePath, projectTasks.get(childModulePath))
}
}