[workspace model] IJPL-844 Remove WorkspaceEntityData.symbolicId usage from the code

GitOrigin-RevId: 6890e2cbaf8cd93b164e4bbbedb95e96f392a254
This commit is contained in:
Mikhail Mazurkevich
2024-03-27 13:49:09 +00:00
committed by intellij-monorepo-bot
parent d15d074bc9
commit eb0b39784d
7 changed files with 43 additions and 34 deletions
@@ -5,6 +5,7 @@ import com.google.common.collect.HashBiMap
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.diagnostic.trace
import com.intellij.platform.workspace.storage.WorkspaceEntity
import com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId
import com.intellij.platform.workspace.storage.impl.exceptions.ApplyChangesFromException
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
import java.util.*
@@ -195,7 +196,7 @@ internal class ApplyChangesFromOperation(val target: MutableEntityStorageImpl, v
target.indexes.updateIndices(sourceEntityId.id, newTargetEntityData, diff)
val newEntityId = newTargetEntityData.createEntityId()
val oldSymbolicId = target.entityDataById(newEntityId)?.symbolicId()
val oldSymbolicId = (target.entityDataById(newEntityId)?.createEntity(target) as? WorkspaceEntityWithSymbolicId)?.symbolicId
/// Replace entity data. id should not be changed
target.entitiesByType.replaceById(newTargetEntityData, sourceEntityId.id.clazz)
@@ -414,7 +415,7 @@ internal class ApplyChangesFromOperation(val target: MutableEntityStorageImpl, v
}
private fun checkSymbolicId(entityData: WorkspaceEntityData<out WorkspaceEntity>, newEntityId: EntityId?) {
val newSymbolicId = entityData.symbolicId()
val newSymbolicId = (entityData.createEntity(diff) as? WorkspaceEntityWithSymbolicId)?.symbolicId
if (newSymbolicId != null) {
val existingIds = target.indexes.symbolicIdIndex.getIdsByEntry(newSymbolicId)
if (existingIds != null) {
@@ -16,7 +16,7 @@ public fun EntityStorage.assertConsistency() {
internal fun AbstractEntityStorage.assertConsistency() {
AbstractEntityStorage.LOG.trace { "Checking consistency of $this" }
entitiesByType.assertConsistency()
entitiesByType.assertConsistency(this)
// Rules:
// 1) Refs should not have links without a corresponding entity
// 1.1) For abstract containers: EntityId has the class of ConnectionId
@@ -670,9 +670,4 @@ public abstract class WorkspaceEntityData<E : WorkspaceEntity> : Cloneable, Seri
public abstract class WithCalculableSymbolicId<E : WorkspaceEntity> : WorkspaceEntityData<E>() {
public abstract fun symbolicId(): SymbolicEntityId<*>
}
}
internal fun WorkspaceEntityData<*>.symbolicId(): SymbolicEntityId<*>? = when (this) {
is WorkspaceEntityData.WithCalculableSymbolicId -> this.symbolicId()
else -> null
}
}
@@ -2,9 +2,12 @@
package com.intellij.platform.workspace.storage.impl
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.platform.workspace.storage.EntityStorage
import com.intellij.platform.workspace.storage.SymbolicEntityId
import com.intellij.platform.workspace.storage.WorkspaceEntity
import com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
internal open class ImmutableEntitiesBarrel internal constructor(
override val entityFamilies: List<ImmutableEntityFamily<out WorkspaceEntity>?>
@@ -117,7 +120,8 @@ internal sealed class EntitiesBarrel {
fun size() = entityFamilies.size
fun assertConsistency() {
@OptIn(EntityStorageInstrumentationApi::class)
fun assertConsistency(storage: EntityStorageInstrumentation) {
val symbolicIds = HashSet<SymbolicEntityId<*>>()
entityFamilies.forEachIndexed { i, family ->
if (family == null) return@forEachIndexed
@@ -135,7 +139,7 @@ internal sealed class EntitiesBarrel {
// Assert unique of persistent id
if (hasSymbolicId) {
val symbolicId = entityData.symbolicId()
val symbolicId = (entityData.createEntity(storage) as? WorkspaceEntityWithSymbolicId)?.symbolicId
assert(symbolicId != null) { "Symbolic id expected for $clazz" }
assert(symbolicId !in symbolicIds) { "Duplicated symbolic ids: $symbolicId" }
symbolicIds.add(symbolicId!!)
@@ -270,9 +270,11 @@ internal class MutableEntityStorageImpl(
lockWrite()
val newEntityData = entity.getEntityData()
val immutableEntity = newEntityData.createEntity(this)
val symbolicId = (immutableEntity as? WorkspaceEntityWithSymbolicId)?.symbolicId
// Check for persistent id uniqueness
assertUniqueSymbolicId(newEntityData)
assertUniqueSymbolicId(newEntityData, symbolicId)
entitiesByType.add(newEntityData, entity.getEntityClass().toClassId())
@@ -280,24 +282,24 @@ internal class MutableEntityStorageImpl(
changeLog.addAddEvent(newEntityData.createEntityId(), newEntityData)
// Update indexes
indexes.entityAdded(newEntityData)
indexes.entityAdded(newEntityData, symbolicId)
}
finally {
unlockWrite()
}
}
private fun <T : WorkspaceEntity> assertUniqueSymbolicId(pEntityData: WorkspaceEntityData<T>) {
pEntityData.symbolicId()?.let { symbolicId ->
val ids = indexes.symbolicIdIndex.getIdsByEntry(symbolicId)
if (ids != null) {
// Oh, oh. This symbolic id exists already
// Fallback strategy: remove existing entity with all it's references
val existingEntityData = entityDataByIdOrDie(ids)
val existingEntity = existingEntityData.createEntity(this)
removeEntity(existingEntity)
LOG.error(
"""
private fun <T : WorkspaceEntity> assertUniqueSymbolicId(pEntityData: WorkspaceEntityData<T>, symbolicId: SymbolicEntityId<*>?) {
if (symbolicId == null) return
val ids = indexes.symbolicIdIndex.getIdsByEntry(symbolicId)
if (ids != null) {
// Oh, oh. This symbolic id exists already
// Fallback strategy: remove existing entity with all it's references
val existingEntityData = entityDataByIdOrDie(ids)
val existingEntity = existingEntityData.createEntity(this)
removeEntity(existingEntity)
LOG.error(
"""
addEntity: symbolic id already exists. Replacing entity with the new one.
Symbolic id: $symbolicId
@@ -306,8 +308,7 @@ internal class MutableEntityStorageImpl(
Broken consistency: $brokenConsistency
""".trimIndent(), SymbolicIdAlreadyExistsException(symbolicId)
)
}
)
}
}
@@ -339,7 +340,8 @@ internal class MutableEntityStorageImpl(
// Check for persistent id uniqueness
if (beforeSymbolicId != null) {
val newSymbolicId = copiedData.symbolicId()
val immutableEntity = modifiableEntity.getEntityData().createEntity(this)
val newSymbolicId = if (immutableEntity is WorkspaceEntityWithSymbolicId) immutableEntity.symbolicId else null
if (newSymbolicId != null) {
val ids = indexes.symbolicIdIndex.getIdsByEntry(newSymbolicId)
if (beforeSymbolicId != newSymbolicId && ids != null) {
@@ -107,18 +107,21 @@ internal open class StorageIndexes(
}
*/
@OptIn(EntityStorageInstrumentationApi::class)
private fun assertSymbolicIdIndex(storage: AbstractEntityStorage) {
var expectedSize = 0
storage.entitiesByType.entityFamilies.forEachIndexed { i, family ->
if (family == null) return@forEachIndexed
if (family.entities.firstOrNull { it != null }?.symbolicId() == null) return@forEachIndexed
val entityData = family.entities.firstOrNull { it != null }?.createEntity(storage) as? WorkspaceEntityWithSymbolicId
if (entityData?.symbolicId == null) return@forEachIndexed
var mutableId = createEntityId(0, i)
family.entities.forEach { data ->
if (data == null) return@forEach
mutableId = mutableId.copy(arrayId = data.id)
val expectedSymbolicId = symbolicIdIndex.getEntryById(mutableId)
assert(expectedSymbolicId == data.symbolicId()) { "Entity $data isn't found in persistent id index. SymbolicId: ${data.symbolicId()}, Id: $mutableId. Expected entity source: $expectedSymbolicId" }
val symbolicId = (data.createEntity(storage) as? WorkspaceEntityWithSymbolicId)?.symbolicId
assert(expectedSymbolicId == symbolicId) { "Entity $data isn't found in persistent id index. SymbolicId: $symbolicId, Id: $mutableId. Expected entity source: $expectedSymbolicId" }
expectedSize++
}
}
@@ -155,7 +158,7 @@ internal class MutableStorageIndexes(
override val externalMappings: MutableMap<ExternalMappingKey<*>, MutableExternalEntityMappingImpl<*>>
) : StorageIndexes(softLinks, virtualFileIndex, entitySourceIndex, symbolicIdIndex, externalMappings) {
fun <T : WorkspaceEntity> entityAdded(entityData: WorkspaceEntityData<T>) {
fun <T : WorkspaceEntity> entityAdded(entityData: WorkspaceEntityData<T>, symbolicId: SymbolicEntityId<*>?) {
val pid = entityData.createEntityId()
// Update soft links index
@@ -166,7 +169,7 @@ internal class MutableStorageIndexes(
val entitySource = entityData.entitySource
entitySourceIndex.index(pid, entitySource)
entityData.symbolicId()?.let { symbolicId ->
if (symbolicId != null) {
symbolicIdIndex.index(pid, symbolicId)
}
@@ -266,7 +269,7 @@ internal class MutableStorageIndexes(
for (entityId in idsWithSoftRef) {
val originalEntityData = builder.getOriginalEntityData(entityId) as WorkspaceEntityData<WorkspaceEntity>
val entity = builder.entitiesByType.getEntityDataForModification(entityId) as WorkspaceEntityData<WorkspaceEntity>
val editingBeforeSymbolicId = entity.symbolicId()
val editingBeforeSymbolicId = (entity.createEntity(builder) as? WorkspaceEntityWithSymbolicId)?.symbolicId
(entity as SoftLinkable).updateLink(beforeSymbolicId, newSymbolicId)
// Add an entry to changelog
@@ -4,6 +4,8 @@ package com.intellij.platform.workspace.storage.impl
import com.intellij.platform.workspace.storage.EntityStorage
import com.intellij.platform.workspace.storage.MutableEntityStorage
import com.intellij.platform.workspace.storage.WorkspaceEntity
import com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
import com.intellij.platform.workspace.storage.instrumentation.Modification
// Just a wrapper for entity id in THIS store
@@ -36,11 +38,12 @@ internal fun loadClassByName(name: String, classLoader: ClassLoader): Class<*> {
* This function checks if we try to add an entity as a child to itself.
* It can't verify a circular dependency, and it's performed via a third entity
*/
@OptIn(EntityStorageInstrumentationApi::class)
internal fun checkCircularDependency(connectionId: ConnectionId, childId: Int, parentId: Int, storage: AbstractEntityStorage) {
if (connectionId.parentClass == connectionId.childClass && childId == parentId) {
val parentEntityId = createEntityId(parentId, connectionId.parentClass)
val entityData = storage.entityDataByIdOrDie(parentEntityId)
val entityPresentation = entityData.symbolicId()?.toString() ?: entityData.toString()
val entityPresentation = (entityData.createEntity(storage) as? WorkspaceEntityWithSymbolicId)?.symbolicId?.toString() ?: entityData.toString()
error("""Trying to make a circular dependency in entities by setting an entity as a child of itself.
|Entity class: ${connectionId.parentClass.findWorkspaceEntity()}
|Entity: $entityPresentation
@@ -52,10 +55,11 @@ internal fun checkCircularDependency(connectionId: ConnectionId, childId: Int, p
* This function checks if we try to add an entity as a child to itself.
* It can't verify a circular dependency, and it's performed via a third entity
*/
@OptIn(EntityStorageInstrumentationApi::class)
internal fun checkCircularDependency(childId: EntityId, parentId: EntityId, storage: AbstractEntityStorage) {
if (childId == parentId) {
val entityData = storage.entityDataByIdOrDie(parentId)
val entityPresentation = entityData.symbolicId()?.toString() ?: entityData.toString()
val entityPresentation = (entityData.createEntity(storage) as? WorkspaceEntityWithSymbolicId)?.symbolicId?.toString() ?: entityData.toString()
error("""Trying to make a circular dependency in entities by setting an entity as a child of itself.
|Entity class: ${parentId.clazz.findWorkspaceEntity()}
|Entity: $entityPresentation