From 7bf2838b682c8618b9349d7b28f4630e454408a7 Mon Sep 17 00:00:00 2001 From: Sergei Vorobyov Date: Fri, 10 Mar 2023 21:34:24 +0100 Subject: [PATCH] IDEA-313062 removed usage of kotlin sequence builder inside prefix tree removed usages of FList GitOrigin-RevId: 630fba859a3e5004ce26c1d90edce47d0f5e3377 --- .../changes/AsyncFilesChangesListener.kt | 2 +- .../project/manage/SourceFolderManagerImpl.kt | 5 +- .../intellij/util/containers/OptionalKt.kt | 17 +- .../containers/prefix/map/PrefixTreeMap.kt | 30 +--- .../prefix/map/PrefixTreeMapImpl.kt | 116 ++++--------- .../containers/prefix/map/PrefixTreeNode.kt | 161 ++++++++++-------- .../containers/prefix/set/PrefixTreeSet.kt | 8 - .../prefix/set/PrefixTreeSetImpl.kt | 18 +- .../plugins/gradle/util/GradleTasksUtil.kt | 2 +- 9 files changed, 139 insertions(+), 220 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/autoimport/changes/AsyncFilesChangesListener.kt b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/autoimport/changes/AsyncFilesChangesListener.kt index b3494149710a..ea8bf576d632 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/autoimport/changes/AsyncFilesChangesListener.kt +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/autoimport/changes/AsyncFilesChangesListener.kt @@ -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()) { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt index 47f4a0854b4b..8155ae9e21e8 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/SourceFolderManagerImpl.kt @@ -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()) + }) } } diff --git a/platform/util/base/src/com/intellij/util/containers/OptionalKt.kt b/platform/util/base/src/com/intellij/util/containers/OptionalKt.kt index c9094a6a3cb3..b9a917209e89 100644 --- a/platform/util/base/src/com/intellij/util/containers/OptionalKt.kt +++ b/platform/util/base/src/com/intellij/util/containers/OptionalKt.kt @@ -18,12 +18,6 @@ internal class OptionalKt 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 private constructor( throw NoSuchElementException("No value present") } - fun getOrNull(): T? { - if (isPresent) { - return get() - } - return null - } - companion object { val EMPTY = OptionalKt(false, null) @@ -54,6 +41,10 @@ internal class OptionalKt private constructor( return EMPTY } + fun OptionalKt.getOrNull(): T? { + return getOrDefault(null) + } + fun OptionalKt.getOrDefault(defaultValue: T): T { if (isPresent) { return get() diff --git a/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeMap.kt b/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeMap.kt index 92d501596ab0..de43477bf116 100644 --- a/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeMap.kt +++ b/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeMap.kt @@ -9,12 +9,6 @@ import org.jetbrains.annotations.ApiStatus @ApiStatus.NonExtendable interface PrefixTreeMap : Map { - fun getKeySequence(): Sequence - - fun getValueSequence(): Sequence - - fun getEntrySequence(): Sequence> - /** * Returns descendant keys for [key]. * @@ -25,13 +19,7 @@ interface PrefixTreeMap : Map { fun getDescendantValues(key: Key): List - fun getDescendantEntries(key: Key): Map - - fun getDescendantKeySequence(key: Key): Sequence - - fun getDescendantValueSequence(key: Key): Sequence - - fun getDescendantEntrySequence(key: Key): Sequence> + fun getDescendantEntries(key: Key): Set> /** * Returns ancestor elements for [key]. @@ -43,13 +31,7 @@ interface PrefixTreeMap : Map { fun getAncestorValues(key: Key): List - fun getAncestorEntries(key: Key): Map - - fun getAncestorKeySequence(key: Key): Sequence - - fun getAncestorValueSequence(key: Key): Sequence - - fun getAncestorEntrySequence(key: Key): Sequence> + fun getAncestorEntries(key: Key): Set> /** * Returns root keys in this map. @@ -61,11 +43,5 @@ interface PrefixTreeMap : Map { fun getRootValues(): List - fun getRootEntries(): Map - - fun getRootKeySequence(): Sequence - - fun getRootValueSequence(): Sequence - - fun getRootEntrySequence(): Sequence> + fun getRootEntries(): Set> } \ No newline at end of file diff --git a/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeMapImpl.kt b/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeMapImpl.kt index 3722d623b8f5..83e7e2d70a14 100644 --- a/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeMapImpl.kt +++ b/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeMapImpl.kt @@ -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( get() = root.getSize() override val keys: Set - get() = getKeySequence().toSet() + get() = root.getValues().toKeySet() override val values: Collection - get() = getValueSequence().toList() + get() = root.getValues().toValueList() override val entries: Set> - get() = root.getEntrySequence().toEntrySet() - - override fun getKeySequence(): Sequence { - return root.getEntrySequence().toKeySequence() - } - - override fun getValueSequence(): Sequence { - return root.getEntrySequence().toValueSequence() - } - - override fun getEntrySequence(): Sequence> { - 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) { - getEntrySequence().forEach { action.accept(it.first, it.second) } + root.getValues().forEach { action.accept(it.first, it.second) } } override fun getDescendantKeys(key: Key): Set { - return getDescendantKeySequence(key).toSet() + return root.getDescendantValues(key.toList()).toKeySet() } override fun getDescendantValues(key: Key): List { - return getDescendantValueSequence(key).toList() + return root.getDescendantValues(key.toList()).toValueList() } - override fun getDescendantEntries(key: Key): Map { - return getDescendantEntrySequence(key).toMap() - } - - override fun getDescendantKeySequence(key: Key): Sequence { - return root.getDescendantEntrySequence(key.asPrefixKey()).toKeySequence() - } - - override fun getDescendantValueSequence(key: Key): Sequence { - return root.getDescendantEntrySequence(key.asPrefixKey()).toValueSequence() - } - - override fun getDescendantEntrySequence(key: Key): Sequence> { - return root.getDescendantEntrySequence(key.asPrefixKey()).toEntrySequence() + override fun getDescendantEntries(key: Key): Set> { + return root.getDescendantValues(key.toList()).toEntrySet() } override fun getAncestorKeys(key: Key): Set { - return getAncestorKeySequence(key).toSet() + return root.getAncestorValues(key.toList()).toKeySet() } override fun getAncestorValues(key: Key): List { - return getAncestorValueSequence(key).toList() + return root.getAncestorValues(key.toList()).toValueList() } - override fun getAncestorEntries(key: Key): Map { - return getAncestorEntrySequence(key).toMap() - } - - override fun getAncestorKeySequence(key: Key): Sequence { - return root.getAncestorEntrySequence(key.asPrefixKey()).toKeySequence() - } - - override fun getAncestorValueSequence(key: Key): Sequence { - return root.getAncestorEntrySequence(key.asPrefixKey()).toValueSequence() - } - - override fun getAncestorEntrySequence(key: Key): Sequence> { - return root.getAncestorEntrySequence(key.asPrefixKey()).toEntrySequence() + override fun getAncestorEntries(key: Key): Set> { + return root.getAncestorValues(key.toList()).toEntrySet() } override fun getRootKeys(): Set { - return getRootKeySequence().toSet() + return root.getRootValues().toKeySet() } override fun getRootValues(): List { - return getRootValueSequence().toList() + return root.getRootValues().toValueList() } - override fun getRootEntries(): Map { - return getRootEntrySequence().toMap() + override fun getRootEntries(): Set> { + return root.getRootValues().toEntrySet() } - override fun getRootKeySequence(): Sequence { - return root.getRootEntrySequence().toKeySequence() + private fun Key.toList(): List { + return convertor.convertToList(this) } - override fun getRootValueSequence(): Sequence { - return root.getRootEntrySequence().toValueSequence() + private fun OptionalKt>.getOrNull(): Value? { + return map { it.second }.getOrNull() } - override fun getRootEntrySequence(): Sequence> { - return root.getRootEntrySequence().toEntrySequence() + private fun OptionalKt>.getOrDefault(defaultValue: Value): Value { + return map { it.second }.getOrDefault(defaultValue) } - private fun Key.asPrefixKey(): FList { - return FList.createFromReversed(convertor.convertToList(this).asReversed()) + private fun List>.toKeySet(): Set { + return mapTo(LinkedHashSet()) { it.first } } - private fun OptionalKt>.toValue(): OptionalKt { + private fun List>.toValueList(): List { return map { it.second } } - private fun Sequence, Pair>>.toKeySequence(): Sequence { - return map { it.second.first } - } - - private fun Sequence, Pair>>.toValueSequence(): Sequence { - return map { it.second.second } - } - - private fun Sequence, Pair>>.toEntrySequence(): Sequence> { - return map { it.second } - } - - private fun Sequence, Pair>>.toEntrySet(): Set> { - return mapTo(LinkedHashSet()) { it.second.toEntry() } + private fun List>.toEntrySet(): Set> { + return mapTo(LinkedHashSet()) { it.toEntry() } } private fun Pair.toEntry(): Map.Entry { diff --git a/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeNode.kt b/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeNode.kt index f967475ee9ce..16e86d4f1655 100644 --- a/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeNode.kt +++ b/platform/util/base/src/com/intellij/util/containers/prefix/map/PrefixTreeNode.kt @@ -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 { return size } - fun findValue(key: FList): OptionalKt { + fun getValue(key: List): OptionalKt { return findNode(key)?.state ?: OptionalKt.EMPTY } - fun setValue(key: FList, value: Value): OptionalKt { - if (key.isEmpty()) { + fun setValue(key: List, value: Value): OptionalKt { + return setValue(0, key, value) + } + + fun removeValue(key: List): OptionalKt { + return removeValue(0, key) + } + + private fun setValue(index: Int, key: List, value: Value): OptionalKt { + 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 { } 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): OptionalKt { - if (key.isEmpty()) { + private fun removeValue(index: Int, key: List): OptionalKt { + 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 { } 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 { return previousState } - fun containsKey(key: FList): Boolean { - if (key.isEmpty()) { - return state.isPresent() - } - val child = children[key.head] ?: return false - return child.containsKey(key.tail) + fun containsKey(key: List): Boolean { + val node = findNode(key) ?: return false + return node.state.isPresent() } - fun findNode(key: FList): PrefixTreeNode? { - if (key.isEmpty()) { - return this - } - val child = children[key.head] ?: return null - return child.findNode(key.tail) - } - - fun getEntrySequence(): Sequence, Value>> { - return sequence { - state.ifPresent { - yield(FList.emptyList() to it) + fun getValues(): List { + val result = ArrayList() + 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): List { + val result = ArrayList() + traverseNode(key) { state -> + if (state.isPresent()) { + result.add(state.get()) + } + } + return result + } + + fun getDescendantValues(key: List): List { + val node = findNode(key) ?: return emptyList() + val result = ArrayList() + for (value in node.getValues()) { + result.add(value) + } + return result + } + + fun getRootValues(): List { + val result = ArrayList() + 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): PrefixTreeNode? { + return traverseNode(key) {} + } + + private fun traverseNode(key: List, process: (OptionalKt) -> Unit): PrefixTreeNode? { + 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) -> TraverseDecision) { + val queue = ArrayDeque>() + 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): Sequence, Value>> { - return sequence { - state.ifPresent { - yield(FList.emptyList() 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): Sequence, Value>> { - val node = findNode(key) ?: return emptySequence() - return sequence { - for ((keyPostfix, value) in node.getEntrySequence()) { - yield(key + keyPostfix to value) - } - } - } - - fun getRootEntrySequence(): Sequence, Value>> { - state.ifPresent { - return sequenceOf(FList.emptyList() 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 } } \ No newline at end of file diff --git a/platform/util/base/src/com/intellij/util/containers/prefix/set/PrefixTreeSet.kt b/platform/util/base/src/com/intellij/util/containers/prefix/set/PrefixTreeSet.kt index be9f53dea84b..930ac0777765 100644 --- a/platform/util/base/src/com/intellij/util/containers/prefix/set/PrefixTreeSet.kt +++ b/platform/util/base/src/com/intellij/util/containers/prefix/set/PrefixTreeSet.kt @@ -15,8 +15,6 @@ import org.jetbrains.annotations.ApiStatus @ApiStatus.NonExtendable interface PrefixTreeSet : Set { - fun asSequence(): Sequence - /** * Returns descendant elements for [element]. * @@ -25,8 +23,6 @@ interface PrefixTreeSet : Set { */ fun getDescendants(element: Key): Set - fun getDescendantSequence(element: Key): Sequence - /** * Returns ancestor elements for [element]. * @@ -35,8 +31,6 @@ interface PrefixTreeSet : Set { */ fun getAncestors(element: Key): Set - fun getAncestorSequence(element: Key): Sequence - /** * Returns root elements in this set. * @@ -44,6 +38,4 @@ interface PrefixTreeSet : Set { * Then root elements are `[a,b,c]` and `[a,f,g]`. */ fun getRoots(): Set - - fun getRootSequence(): Sequence } \ No newline at end of file diff --git a/platform/util/base/src/com/intellij/util/containers/prefix/set/PrefixTreeSetImpl.kt b/platform/util/base/src/com/intellij/util/containers/prefix/set/PrefixTreeSetImpl.kt index ecb34a1c4ede..080c611ddc41 100644 --- a/platform/util/base/src/com/intellij/util/containers/prefix/set/PrefixTreeSetImpl.kt +++ b/platform/util/base/src/com/intellij/util/containers/prefix/set/PrefixTreeSetImpl.kt @@ -14,10 +14,6 @@ internal class PrefixTreeSetImpl( override val size: Int get() = map.size - override fun asSequence(): Sequence { - return map.getKeySequence() - } - override fun isEmpty(): Boolean { return map.isEmpty() } @@ -34,26 +30,14 @@ internal class PrefixTreeSetImpl( return map.getDescendantKeys(element) } - override fun getDescendantSequence(element: Key): Sequence { - return map.getDescendantKeySequence(element) - } - override fun getAncestors(element: Key): Set { return map.getAncestorKeys(element) } - override fun getAncestorSequence(element: Key): Sequence { - return map.getAncestorKeySequence(element) - } - override fun getRoots(): Set { return map.getRootKeys() } - override fun getRootSequence(): Sequence { - return map.getRootKeySequence() - } - override fun add(element: Key) { map[element] = null } @@ -63,6 +47,6 @@ internal class PrefixTreeSetImpl( } override fun iterator(): Iterator { - return asSequence().iterator() + return map.keys.iterator() } } \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleTasksUtil.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleTasksUtil.kt index b53f10fec4bd..1c02f4cac90e 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleTasksUtil.kt +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleTasksUtil.kt @@ -56,7 +56,7 @@ private fun getGradleTaskNodesMap(project: Project): Map