[Workspace Model] EntityData should calculate PersistentId if TypedEntity has it

GitOrigin-RevId: d0b3d356ce71b194e34c1c2bc22175c80e96f1f7
This commit is contained in:
Alex Plate
2020-05-09 05:25:10 +00:00
committed by intellij-monorepo-bot
parent c0af13dcab
commit e57ddfb4e3
6 changed files with 53 additions and 29 deletions
@@ -8,12 +8,14 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
internal class PNamedSampleEntityData : PEntityData<PNamedSampleEntity>() {
internal class PNamedSampleEntityData : PEntityData.WithCalculatablePersistentId<PNamedSampleEntity>() {
lateinit var name: String
lateinit var next: PSampleEntityId
override fun createEntity(snapshot: TypedEntityStorage): PNamedSampleEntity {
return PNamedSampleEntity(name, next).also { addMetaData(it, snapshot) }
}
override fun persistentId(): PSampleEntityId = PSampleEntityId(name)
}
internal class PNamedSampleEntity(
@@ -42,7 +44,7 @@ internal data class PChildEntityId(val childName: String,
get() = childName
}
internal class PChildWithPersistentIdEntityData : PEntityData<PChildWithPersistentIdEntity>() {
internal class PChildWithPersistentIdEntityData : PEntityData.WithPersistentId<PChildWithPersistentIdEntity>() {
lateinit var parent: PNamedSampleEntity
lateinit var childName: String
override fun createEntity(snapshot: TypedEntityStorage): PChildWithPersistentIdEntity {
@@ -1,15 +1,20 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.workspace.api.pstorage
import com.intellij.workspace.api.*
import com.intellij.workspace.api.EntitySource
import com.intellij.workspace.api.TypedEntityStorage
import com.intellij.workspace.api.TypedEntityStorageBuilder
import com.intellij.workspace.api.TypedEntityWithPersistentId
import org.junit.Assert
import org.junit.Test
internal class PPersistentIdEntityData : PEntityData<PPersistentIdEntity>() {
internal class PPersistentIdEntityData : PEntityData.WithCalculatablePersistentId<PPersistentIdEntity>() {
lateinit var data: String
override fun createEntity(snapshot: TypedEntityStorage): PPersistentIdEntity {
return PPersistentIdEntity(data).also { addMetaData(it, snapshot) }
}
override fun persistentId(): PSampleEntityId = PSampleEntityId(data)
}
internal class PPersistentIdEntity(val data: String) : TypedEntityWithPersistentId, PTypedEntity() {
@@ -19,11 +19,13 @@ internal data class NameId(private val name: String) : PersistentEntityId<NamedE
}
@Suppress("unused")
internal class NamedEntityData : PEntityData<NamedEntity>() {
internal class NamedEntityData : PEntityData.WithCalculatablePersistentId<NamedEntity>() {
lateinit var name: String
override fun createEntity(snapshot: TypedEntityStorage): NamedEntity {
return NamedEntity(name).also { addMetaData(it, snapshot) }
}
override fun persistentId(): PersistentEntityId<*> = NameId(name)
}
internal class NamedEntity(
@@ -15,7 +15,7 @@ import java.io.Serializable
*/
@Suppress("unused")
class ModuleEntityData : PEntityData<ModuleEntity>(), PSoftLinkable {
class ModuleEntityData : PEntityData.WithCalculatablePersistentId<ModuleEntity>(), PSoftLinkable {
lateinit var name: String
var type: String? = null
lateinit var dependencies: List<ModuleDependencyItem>
@@ -65,6 +65,8 @@ class ModuleEntityData : PEntityData<ModuleEntity>(), PSoftLinkable {
override fun createEntity(snapshot: TypedEntityStorage): ModuleEntity = ModuleEntity(name, type, dependencies.toList()).also {
addMetaData(it, snapshot)
}
override fun persistentId(): ModuleId = ModuleId(name)
}
class ModuleEntity(
@@ -325,7 +327,7 @@ sealed class LibraryTableId : Serializable {
}
@Suppress("unused")
class LibraryEntityData : PEntityData<LibraryEntity>(), PSoftLinkable {
class LibraryEntityData : PEntityData.WithCalculatablePersistentId<LibraryEntity>(), PSoftLinkable {
lateinit var tableId: LibraryTableId
lateinit var name: String
lateinit var roots: List<LibraryRoot>
@@ -350,6 +352,8 @@ class LibraryEntityData : PEntityData<LibraryEntity>(), PSoftLinkable {
override fun createEntity(snapshot: TypedEntityStorage): LibraryEntity {
return LibraryEntity(tableId, name, roots.toList(), excludedRoots.toList()).also { addMetaData(it, snapshot) }
}
override fun persistentId(): LibraryId = LibraryId(name, tableId)
}
open class LibraryEntity(
@@ -450,7 +454,7 @@ val ModuleEntity.externalSystemOptions: ExternalSystemModuleOptionsEntity?
get() = referrers(ExternalSystemModuleOptionsEntity::module).firstOrNull()
@Suppress("unused")
class FacetEntityData : PEntityData<FacetEntity>() {
class FacetEntityData : PEntityData.WithPersistentId<FacetEntity>() {
lateinit var name: String
lateinit var facetType: String
var configurationXmlTag: String? = null
@@ -490,7 +494,7 @@ data class ArtifactId(val name: String) : PersistentEntityId<ArtifactEntity>() {
}
@Suppress("unused")
class ArtifactEntityData : PEntityData<ArtifactEntity>() {
class ArtifactEntityData : PEntityData.WithCalculatablePersistentId<ArtifactEntity>() {
lateinit var name: String
lateinit var artifactType: String
var includeInProjectBuild: Boolean = false
@@ -499,6 +503,8 @@ class ArtifactEntityData : PEntityData<ArtifactEntity>() {
override fun createEntity(snapshot: TypedEntityStorage): ArtifactEntity {
return ArtifactEntity(name, artifactType, includeInProjectBuild, outputUrl).also { addMetaData(it, snapshot) }
}
override fun persistentId(): ArtifactId = ArtifactId(name)
}
class ArtifactEntity(
@@ -6,7 +6,6 @@ import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty1
import kotlin.reflect.KType
import kotlin.reflect.full.memberProperties
abstract class PTypedEntity : ReferableTypedEntity, Any() {
@@ -150,6 +149,24 @@ abstract class PEntityData<E : TypedEntity>: Cloneable {
.mapNotNull { it.get(this)?.hashCode() }
.fold(31) { acc, i -> acc * 17 + i }
}
/**
* Temporally solution.
* Get persistent Id without creating of TypedEntity. Should be in sync with TypedEntityWithPersistentId.
* But it doesn't everywhere. E.g. FacetEntity where we should resolve module before creating persistent id.
*/
abstract class WithCalculatablePersistentId<E : TypedEntity> : PEntityData<E>() {
abstract fun persistentId(): PersistentEntityId<*>
}
abstract class WithPersistentId<E : TypedEntity> : PEntityData<E>() {
}
}
fun PEntityData<*>.persistentId(snapshot: TypedEntityStorage): PersistentEntityId<*>? = when (this) {
is PEntityData.WithCalculatablePersistentId -> this.persistentId()
is PEntityData.WithPersistentId -> (this.createEntity(snapshot) as TypedEntityWithPersistentId).persistentId()
else -> null
}
class EntityDataDelegation<A : PModifiableTypedEntity<*>, B> : ReadWriteProperty<A, B> {
@@ -158,7 +158,7 @@ internal class PEntityStorageBuilder(
// Restore links to soft references
if (cloned is PSoftLinkable) {
for (link in cloned.getLinks()) {
softLinks.put(link, cloned.createPid())
softLinks.put(link, replaceToPid)
}
}
@@ -205,8 +205,7 @@ internal class PEntityStorageBuilder(
val id = newEntity.createPid()
val existingEntityData = entityDataById(id)
val existingEntity = existingEntityData?.createEntity(this)
val beforePersistentId = if (existingEntity is TypedEntityWithPersistentId) existingEntity.persistentId() else null
val beforePersistentId = existingEntityData?.persistentId(this)
val beforeSoftLinks = if (existingEntityData is PSoftLinkable) existingEntityData.getLinks() else null
/// Replace entity data. id should not be changed
@@ -257,10 +256,9 @@ internal class PEntityStorageBuilder(
private fun <T : TypedEntity> updateSoftReferences(beforePersistentId: PersistentEntityId<*>?,
beforeSoftLinks: List<PersistentEntityId<*>>?,
copiedData: PEntityData<T>) {
val updatedEntity = copiedData.createEntity(this)
val pid = (updatedEntity as PTypedEntity).id
val pid = copiedData.createPid()
if (beforePersistentId != null) {
val afterPersistentId = (updatedEntity as TypedEntityWithPersistentId).persistentId()
val afterPersistentId = copiedData.persistentId(this) ?: error("Persistent id expected")
if (beforePersistentId != afterPersistentId) {
val updatedIds = mutableListOf(beforePersistentId to afterPersistentId)
while (updatedIds.isNotEmpty()) {
@@ -415,23 +413,15 @@ internal class PEntityStorageBuilder(
}
private fun PEntityData<*>.identificator(storage: AbstractPEntityStorage): Any {
val entity = this.createEntity(storage)
return if (entity is TypedEntityWithPersistentId) {
entity.persistentId()
}
else {
this.hashCode()
}
return this.persistentId(storage) ?: this.hashCode()
}
private fun ArrayListMultimap<Any, PEntityData<out TypedEntity>>.find(entity: PEntityData<out TypedEntity>,
storage: AbstractPEntityStorage): PEntityData<out TypedEntity>? {
val possibleValues = this[entity.identificator(storage)]
return if (entity.hasPersistentId()) {
possibleValues.find {
(it.createEntity(this@PEntityStorageBuilder) as TypedEntityWithPersistentId).persistentId() ==
(entity.createEntity(this@PEntityStorageBuilder) as TypedEntityWithPersistentId).persistentId()
}
val persistentId = entity.persistentId(storage)
return if (persistentId != null) {
possibleValues.find { it.persistentId(this@PEntityStorageBuilder) == persistentId }
}
else {
possibleValues.find { it == entity }
@@ -753,7 +743,9 @@ internal class PEntityStorageBuilder(
// TODO: 27.03.2020 Here should be consistency check
val res = HashMap<TypedEntity, TypedEntity>()
replaceMap.forEach { (oldId, newId) ->
res[diff.entityDataByIdOrDie(oldId).createEntity(diff)] = this.entityDataByIdOrDie(newId).createEntity(this)
if (oldId != newId) {
res[diff.entityDataByIdOrDie(oldId).createEntity(diff)] = this.entityDataByIdOrDie(newId).createEntity(this)
}
}
return res
}