From febdcab3b6ad23a1cc29c1d3f3c2a9d3a86c7949 Mon Sep 17 00:00:00 2001 From: Alex Plate Date: Thu, 4 Jun 2020 20:47:03 +0300 Subject: [PATCH] [Workspace Model] Add more modifications for entities GitOrigin-RevId: b95bb1ca4a33df9e4eb05d955f32ba3e2d3fb7ee --- .../storage/impl/references/OneToMany.kt | 9 +- .../storage/entities/ChildrenAndParents.kt | 3 + .../propertyBased/EntityManipulations.kt | 114 ++++++++++++++---- 3 files changed, 98 insertions(+), 28 deletions(-) diff --git a/platform/workspaceModel/storage/src/com/intellij/workspaceModel/storage/impl/references/OneToMany.kt b/platform/workspaceModel/storage/src/com/intellij/workspaceModel/storage/impl/references/OneToMany.kt index d3f71621a1d9..2018869205ce 100644 --- a/platform/workspaceModel/storage/src/com/intellij/workspaceModel/storage/impl/references/OneToMany.kt +++ b/platform/workspaceModel/storage/src/com/intellij/workspaceModel/storage/impl/references/OneToMany.kt @@ -1,13 +1,8 @@ // 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.workspaceModel.storage.impl.references -import com.intellij.workspaceModel.storage.impl.ConnectionId -import com.intellij.workspaceModel.storage.impl.ConnectionId.ConnectionType.ONE_TO_MANY import com.intellij.workspaceModel.storage.impl.* -import com.intellij.workspaceModel.storage.impl.extractOneToManyChildren -import com.intellij.workspaceModel.storage.impl.extractOneToManyParent -import com.intellij.workspaceModel.storage.impl.updateOneToManyChildrenOfParent -import com.intellij.workspaceModel.storage.impl.updateOneToManyParentOfChild +import com.intellij.workspaceModel.storage.impl.ConnectionId.ConnectionType.ONE_TO_MANY import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty @@ -49,7 +44,7 @@ class ManyToOne private constructor() { } } -sealed class MutableOneToMany>( +class MutableOneToMany>( private val parentClass: Class, private val childClass: Class, private val isParentInChildNullable: Boolean diff --git a/platform/workspaceModel/storage/tests/testSrc/com/intellij/workspaceModel/storage/entities/ChildrenAndParents.kt b/platform/workspaceModel/storage/tests/testSrc/com/intellij/workspaceModel/storage/entities/ChildrenAndParents.kt index b24d15531a76..012b8aab526d 100644 --- a/platform/workspaceModel/storage/tests/testSrc/com/intellij/workspaceModel/storage/entities/ChildrenAndParents.kt +++ b/platform/workspaceModel/storage/tests/testSrc/com/intellij/workspaceModel/storage/entities/ChildrenAndParents.kt @@ -11,6 +11,7 @@ import com.intellij.workspaceModel.storage.impl.WorkspaceEntityBase import com.intellij.workspaceModel.storage.impl.WorkspaceEntityData import com.intellij.workspaceModel.storage.impl.references.ManyToOne import com.intellij.workspaceModel.storage.impl.references.MutableManyToOne +import com.intellij.workspaceModel.storage.impl.references.MutableOneToMany import com.intellij.workspaceModel.storage.impl.references.OneToMany // ------------------- Parent Entity -------------------------------- @@ -35,6 +36,8 @@ internal class ParentEntity( internal class ModifiableParentEntity : ModifiableWorkspaceEntityBase() { var parentProperty: String by EntityDataDelegation() + var children: Sequence by MutableOneToMany(ParentEntity::class.java, ChildEntity::class.java, false) + var optionalChildren: Sequence by MutableOneToMany(ParentEntity::class.java, ChildWithOptionalParentEntity::class.java, true) } internal fun WorkspaceEntityStorageBuilder.addParentEntity(parentProperty: String = "parent", source: EntitySource = MySource) = diff --git a/platform/workspaceModel/storage/tests/testSrc/com/intellij/workspaceModel/storage/propertyBased/EntityManipulations.kt b/platform/workspaceModel/storage/tests/testSrc/com/intellij/workspaceModel/storage/propertyBased/EntityManipulations.kt index 71904510dfb1..496951888752 100644 --- a/platform/workspaceModel/storage/tests/testSrc/com/intellij/workspaceModel/storage/propertyBased/EntityManipulations.kt +++ b/platform/workspaceModel/storage/tests/testSrc/com/intellij/workspaceModel/storage/propertyBased/EntityManipulations.kt @@ -97,7 +97,10 @@ private object ChildWithOptionalParentManipulation : EntityManipulation { return object : AddEntity(storage, "ChildWithOptionalDependency") { override fun makeEntity(source: EntitySource, someProperty: String, env: ImperativeCommand.Environment): WorkspaceEntity? { val classId = ParentEntity::class.java.toClassId() - val parentId = env.generateValue(EntityIdOfFamilyGenerator.create(storage, classId), "Select parent for child: %s") + val parentId = env.generateValue(Generator.anyOf( + Generator.constant(null), + EntityIdOfFamilyGenerator.create(storage, classId) + ), "Select parent for child: %s") val parentEntity = parentId?.let { storage.entityDataByIdOrDie(it).createEntity(storage) as ParentEntity } return storage.addChildWithOptionalParentEntity(parentEntity, someProperty, source) } @@ -124,10 +127,8 @@ private object ChildEntityManipulation : EntityManipulation { override fun addManipulation(storage: WorkspaceEntityStorageBuilderImpl): AddEntity { return object : AddEntity(storage, "Child") { override fun makeEntity(source: EntitySource, someProperty: String, env: ImperativeCommand.Environment): WorkspaceEntity? { - val classId = ParentEntity::class.java.toClassId() - val parentId = env.generateValue(EntityIdOfFamilyGenerator.create(storage, classId), "Select parent for child: %s") ?: return null - return storage.addChildEntity(storage.entityDataByIdOrDie(parentId).createEntity(storage) as ParentEntity, someProperty, null, - source) + val parent = selectParent(storage, env) ?: return null + return storage.addChildEntity(parent, someProperty, null, source) } } } @@ -135,16 +136,30 @@ private object ChildEntityManipulation : EntityManipulation { override fun modifyManipulation(storage: WorkspaceEntityStorageBuilderImpl): ModifyEntity { return object : ModifyEntity(storage, "Child", ChildEntity::class.java.toClassId()) { override fun modifyEntity(entity: ChildEntity, someProperty: String, env: ImperativeCommand.Environment): Boolean { - val selectedModification = env.generateValue(Generator.integers(0, 0), null) - val modification: ModifiableChildEntity.() -> Unit = when (selectedModification) { - 0 -> { -> childProperty = env.generateValue(randomNames, "Change childProperty to %s") } - else -> error("Undefined modification") - } + + val modification = env.generateValue(Generator.sampledFrom Unit>( + // Change child property + { childProperty = env.generateValue(randomNames, "Change childProperty to %s") }, + + // Change parent of child + { + val newParent = selectParent(storage, env) ?: return@sampledFrom + parent = newParent + env.logMessage("Set new parent for child: $newParent") + } + ), null) + storage.modifyEntity(ModifiableChildEntity::class.java, entity, modification) return true } } } + + private fun selectParent(storage: WorkspaceEntityStorageBuilderImpl, env: ImperativeCommand.Environment): ParentEntity? { + val classId = ParentEntity::class.java.toClassId() + val parentId = env.generateValue(EntityIdOfFamilyGenerator.create(storage, classId), "Select parent for child: %s") ?: return null + return storage.entityDataByIdOrDie(parentId).createEntity(storage) as ParentEntity + } } private object ParentEntityManipulation : EntityManipulation { @@ -159,16 +174,52 @@ private object ParentEntityManipulation : EntityManipulation { override fun modifyManipulation(storage: WorkspaceEntityStorageBuilderImpl): ModifyEntity { return object : ModifyEntity(storage, "Parent", ParentEntity::class.java.toClassId()) { override fun modifyEntity(entity: ParentEntity, someProperty: String, env: ImperativeCommand.Environment): Boolean { - val selectedModification = env.generateValue(Generator.integers(0, 0), null) - val modification: ModifiableParentEntity.() -> Unit = when (selectedModification) { - 0 -> { -> parentProperty = env.generateValue(randomNames, "Change parentProperty to %s") } - else -> error("Undefined modification") - } + + val modification = env.generateValue(Generator.sampledFrom Unit>( + // Change parent property + { parentProperty = env.generateValue(randomNames, "Change parentProperty to %s") }, + + // Swap children + { + val childrenList = children.toList() + if (childrenList.size > 2) { + val index1 = env.generateValue(Generator.integers(0, childrenList.lastIndex), null) + val index2 = env.generateValue(Generator.integers(0, childrenList.lastIndex), null) + env.logMessage( + "Change children. Swap 2 elements: idx1: $index1, idx2: $index2, value1: ${childrenList[index1]}, value2: ${childrenList[index2]}") + children = children.toMutableList().also { it.swap(index1, index2) }.asSequence() + } + }, + + // Modify nullable children + { + val removeValue = env.generateValue(Generator.booleans(), null) + if (removeValue) { + if (optionalChildren.any()) { + val childrenList = optionalChildren.toMutableList() + val i = env.generateValue(Generator.integers(0, childrenList.lastIndex), null) + env.logMessage("Remove item from optionalChildren. Index: $i, Element ${childrenList[i]}") + childrenList.removeAt(i) + optionalChildren = childrenList.asSequence() + } + } + else { + // TODO: 04.06.2020 Add children adding + } + } + ), null) + storage.modifyEntity(ModifiableParentEntity::class.java, entity, modification) return true } } } + + private fun MutableList.swap(index1: Int, index2: Int) { + val tmp = this[index1] + this[index1] = this[index2] + this[index2] = tmp + } } private object SampleEntityManipulation : EntityManipulation { @@ -183,12 +234,33 @@ private object SampleEntityManipulation : EntityManipulation { override fun modifyManipulation(storage: WorkspaceEntityStorageBuilderImpl): ModifyEntity { return object : ModifyEntity(storage, "Sample", SampleEntity::class.java.toClassId()) { override fun modifyEntity(entity: SampleEntity, someProperty: String, env: ImperativeCommand.Environment): Boolean { - val selectedModification = env.generateValue(Generator.integers(0, 1), null) - val modification: ModifiableSampleEntity.() -> Unit = when (selectedModification) { - 0 -> { -> booleanProperty = env.generateValue(Generator.booleans(), "Change booleanProperty to %s") } - 1 -> { -> stringProperty = env.generateValue(randomNames, "Change stringProperty to %s") } - else -> error("Undefined modification") - } + + // Select modification + val modification = env.generateValue(Generator.sampledFrom Unit>( + + // Change booleanProperty + { booleanProperty = env.generateValue(Generator.booleans(), "Change booleanProperty to %s") }, + + // Change stringProperty + { stringProperty = env.generateValue(randomNames, "Change stringProperty to %s") }, + + // Change stringListProperty + { + val removeValue = env.generateValue(Generator.booleans(), null) + if (removeValue) { + if (stringListProperty.isNotEmpty()) { + val i = env.generateValue(Generator.integers(0, stringListProperty.lastIndex), null) + env.logMessage("Remove item from stringListProperty. Index: $i, Element ${stringListProperty[i]}") + stringListProperty = stringListProperty.toMutableList().also { it.removeAt(i) } + } + } + else { + val newElement = env.generateValue(randomNames, "Adding new element to stringListProperty: %s") + stringListProperty = stringListProperty + newElement + } + } + ), null) + storage.modifyEntity(ModifiableSampleEntity::class.java, entity, modification) return true }