diff --git a/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/ConsistencyChecker.kt b/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/ConsistencyChecker.kt index 9c65320554a5..e08c26237646 100644 --- a/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/ConsistencyChecker.kt +++ b/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/ConsistencyChecker.kt @@ -35,6 +35,8 @@ internal fun AbstractEntityStorage.assertConsistency() { if (!connectionId.isParentNullable) { checkStrongConnection(this, map.keys, connectionId.childClass, connectionId.parentClass, connectionId) } + + map.assertConsistency() } refs.oneToOneContainer.forEach { (connectionId, map) -> diff --git a/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/RefsTable.kt b/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/RefsTable.kt index 8fed795e9459..0eba087e0d28 100644 --- a/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/RefsTable.kt +++ b/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/RefsTable.kt @@ -439,7 +439,8 @@ internal class MutableRefsTable( val copiedMap = getOneToManyMutableMap(connectionId) // Check if the reference already exists. This is needed to make fewer operations and not to break children ordering - if (copiedMap.get(childId.arrayId) == parentId.id.arrayId) return emptyList() + val existingParent = copiedMap.get(childId.arrayId) + if (existingParent != NonNegativeIntIntBiMap.DEFAULT_RETURN_VALUE && existingParent == parentId.id.arrayId) return emptyList() val removedParent = copiedMap.removeKey(childId.arrayId) val removedChildren = copiedMap.putAll(intArrayOf(childId.arrayId), parentId.id.arrayId) diff --git a/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/containers/NonNegativeIntIntBiMap.kt b/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/containers/NonNegativeIntIntBiMap.kt index dcc715d87470..d6887b6d7ac2 100644 --- a/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/containers/NonNegativeIntIntBiMap.kt +++ b/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/containers/NonNegativeIntIntBiMap.kt @@ -110,7 +110,7 @@ internal sealed class NonNegativeIntIntBiMap { get() = key2Value.keys inline fun forEachKey(crossinline action: (Int, Int) -> Unit) { - Int2IntMaps.fastForEach(`access$key2Value`, Consumer { action(it.intKey, it.intValue) }) + Int2IntMaps.fastForEach(key2Value, Consumer { action(it.intKey, it.intValue) }) } fun containsKey(key: Int) = key2Value.containsKey(key) @@ -139,10 +139,9 @@ internal sealed class NonNegativeIntIntBiMap { return result } - @Suppress("PropertyName") - @PublishedApi - internal val `access$key2Value`: Int2IntMap - get() = key2Value + internal fun assertConsistency() { + assert(key2Value.defaultReturnValue() == DEFAULT_RETURN_VALUE) + } companion object { internal const val DEFAULT_RETURN_VALUE = -1 diff --git a/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/serialization/registration/StorageRegistrar.kt b/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/serialization/registration/StorageRegistrar.kt index eb8ce92028f2..a99175b1b678 100644 --- a/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/serialization/registration/StorageRegistrar.kt +++ b/platform/workspace/storage/src/com/intellij/platform/workspace/storage/impl/serialization/registration/StorageRegistrar.kt @@ -147,7 +147,12 @@ internal class StorageClassesRegistrar( kryo.register(HashBiMap::class.java).instantiator = ObjectInstantiator { HashBiMap.create() } kryo.register(LinkedHashSet::class.java).instantiator = ObjectInstantiator { LinkedHashSet() } kryo.register(LinkedBidirectionalMap::class.java).instantiator = ObjectInstantiator { LinkedBidirectionalMap() } - kryo.register(Int2IntOpenHashMap::class.java).instantiator = ObjectInstantiator { Int2IntOpenHashMap() } + kryo.register(Int2IntOpenHashMap::class.java).instantiator = ObjectInstantiator { + // We set -1 as a default return value because it's used in all Int2IntOpenHashMap in WM. But it would be better + // to wrap "Int2IntOpenHashMap with default -1" with some helper class to avoid possible issues + // if in some place we'll use this map with different default return value + Int2IntOpenHashMap().also { it.defaultReturnValue(-1) } + } @Suppress("SSBasedInspection") kryo.register(ObjectOpenHashSet::class.java).instantiator = ObjectInstantiator { ObjectOpenHashSet() } @Suppress("SSBasedInspection")