mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[workspace model] IJPL-156449 Workspace code generator for K2
- IJPL-172502 k1/k2 split - three-way super search in K2; sort supers (also in K1) - address star imports (also in K1) - sort properties (also in K1) - @Child target test - add Map property in tests - fix test imports - WorkspaceModelDefaults Merge-request: IJ-MR-151255 Merged-by: Kirill Bochkarev <podockonnik@gmail.com> GitOrigin-RevId: 20d498af5e2d2ccdf374a368ad78ab72c1914620
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f729f90d00
commit
afe181d93e
Generated
+2
@@ -356,6 +356,8 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.themes/intellij.devkit.themes.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.themes/intellij.devkit.themes.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.uiDesigner/intellij.devkit.uiDesigner.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.uiDesigner/intellij.devkit.uiDesigner.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.workspaceModel/intellij.devkit.workspaceModel.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.workspaceModel/intellij.devkit.workspaceModel.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.workspaceModel/k1/intellij.devkit.workspaceModel.k1.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.workspaceModel/k1/intellij.devkit.workspaceModel.k1.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.workspaceModel/k2/intellij.devkit.workspaceModel.k2.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.workspaceModel/k2/intellij.devkit.workspaceModel.k2.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/intellij.devkit.workspaceModel/tests/intellij.devkit.workspaceModel.tests.iml" filepath="$PROJECT_DIR$/plugins/devkit/intellij.devkit.workspaceModel/tests/intellij.devkit.workspaceModel.tests.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/env-files-support/intellij.dotenv.iml" filepath="$PROJECT_DIR$/plugins/env-files-support/intellij.dotenv.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/env-files-support/java/intellij.dotenv.java.iml" filepath="$PROJECT_DIR$/plugins/env-files-support/java/intellij.dotenv.java.iml" />
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="5" platform="JVM 17" allPlatforms="JVM [17]" useProjectSettings="false">
|
||||
<compilerSettings>
|
||||
<option name="additionalArguments" value="-Xjvm-default=all -opt-in=com.intellij.openapi.util.IntellijInternalApi -opt-in=org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction -opt-in=org.jetbrains.kotlin.analysis.api.KaIdeApi -opt-in=org.jetbrains.kotlin.analysis.api.KaNonPublicApi -opt-in=org.jetbrains.kotlin.idea.base.util.K1ModeProjectStructureApi" />
|
||||
<option name="additionalArguments" value="-Xjvm-default=all -opt-in=com.intellij.openapi.util.IntellijInternalApi -opt-in=org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction -opt-in=org.jetbrains.kotlin.analysis.api.KaIdeApi -opt-in=org.jetbrains.kotlin.analysis.api.KaNonPublicApi -opt-in=org.jetbrains.kotlin.analysis.api.permissions.KaAllowProhibitedAnalyzeFromWriteAction" />
|
||||
</compilerSettings>
|
||||
<compilerArguments>
|
||||
<stringArguments>
|
||||
@@ -24,38 +24,38 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="kotlin-stdlib" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="kotlinc.kotlin-compiler-common" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="kotlinc.kotlin-jps-common" level="project" />
|
||||
<orderEntry type="library" name="kotlinx-collections-immutable" level="project" />
|
||||
<orderEntry type="library" name="workspace-model-codegen" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.core" />
|
||||
<orderEntry type="module" module-name="intellij.platform.editor.ui" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util" />
|
||||
<orderEntry type="module" module-name="intellij.platform.projectModel" />
|
||||
<orderEntry type="library" name="kotlin-stdlib" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="kotlinc.kotlin-compiler-common" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.analysis" />
|
||||
<orderEntry type="module" module-name="intellij.java.psi.impl" />
|
||||
<orderEntry type="library" name="kotlinx-collections-immutable" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide" />
|
||||
<orderEntry type="module" module-name="intellij.platform.lang.core" />
|
||||
<orderEntry type="module" module-name="intellij.platform.indexing" />
|
||||
<orderEntry type="module" module-name="kotlin.base.indices" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
||||
<orderEntry type="module" module-name="kotlin.base.project-structure" />
|
||||
<orderEntry type="module" module-name="kotlin.base.fe10.analysis" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="kotlinc.kotlin-compiler-fe10" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.core" />
|
||||
<orderEntry type="module" module-name="intellij.java.ui" />
|
||||
<orderEntry type="module" module-name="intellij.java.aetherDependencyResolver" />
|
||||
<orderEntry type="module" module-name="intellij.java" />
|
||||
<orderEntry type="library" name="workspace-model-codegen" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util.classLoader" />
|
||||
<orderEntry type="module" module-name="kotlin.base.facet" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="kotlinc.kotlin-jps-common" level="project" />
|
||||
<orderEntry type="module" module-name="kotlin.base.indices" />
|
||||
<orderEntry type="module" module-name="kotlin.base.project-structure" />
|
||||
<orderEntry type="module" module-name="kotlin.formatter.minimal" />
|
||||
<orderEntry type="module" module-name="kotlin.base.plugin" />
|
||||
<orderEntry type="library" name="kotlinx-serialization-core" level="project" />
|
||||
<orderEntry type="library" name="kotlinx-serialization-json" level="project" />
|
||||
<orderEntry type="library" name="kotlin-reflect" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.backend.workspace" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util.progress" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core" />
|
||||
</component>
|
||||
</module>
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="com.intellij.devkit.workspaceModel.k1" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" packagePrefix="com.intellij.devkit.workspaceModel.k1" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="intellij.platform.workspace.storage" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.workspaceModel" />
|
||||
<orderEntry type="module" module-name="intellij.java.psi" />
|
||||
<orderEntry type="module" module-name="kotlin.base.fe10.analysis" />
|
||||
<orderEntry type="module" module-name="intellij.java.indexing" />
|
||||
<orderEntry type="module" module-name="kotlin.base.project-structure" />
|
||||
<orderEntry type="library" name="kotlin-stdlib" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="kotlinc.kotlin-compiler-common" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="kotlinc.kotlin-compiler-fe10" level="project" />
|
||||
<orderEntry type="library" name="workspace-model-codegen" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.java.psi.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core" />
|
||||
<orderEntry type="module" module-name="kotlin.base.plugin" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.plugin.k1" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.workspaceModel.tests" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.test-framework" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.tests-common" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.base.test" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<idea-plugin package="com.intellij.devkit.workspaceModel.k1">
|
||||
|
||||
<dependencies>
|
||||
<plugin id="com.intellij.modules.kotlin.k1"/>
|
||||
<module name="intellij.devkit.workspaceModel"/>
|
||||
</dependencies>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<applicationService serviceInterface="com.intellij.devkit.workspaceModel.metaModel.WorkspaceMetaModelProvider"
|
||||
serviceImplementation="com.intellij.devkit.workspaceModel.k1.metaModel.WorkspaceMetaModelProviderImpl"
|
||||
/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
+32
-38
@@ -1,11 +1,13 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.metaModel.impl.extensions
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k1.metaModel
|
||||
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.*
|
||||
import com.intellij.devkit.workspaceModel.metaModel.WorkspaceModelDefaults
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.CompiledObjModuleImpl
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.ObjAnnotationImpl
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.ObjClassImpl
|
||||
import com.intellij.psi.CommonClassNames
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.Obj
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
@@ -22,39 +24,31 @@ import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
|
||||
|
||||
private val moduleAbstractTypesClassIds: List<ClassId> = listOf(
|
||||
ClassId.topLevel(StandardNames.ENTITY_SOURCE),
|
||||
ClassId.topLevel(StandardNames.SYMBOLIC_ENTITY_ID)
|
||||
WorkspaceModelDefaults.ENTITY_SOURCE.classId,
|
||||
WorkspaceModelDefaults.SYMBOLIC_ENTITY_ID.classId
|
||||
)
|
||||
|
||||
private val entitiesSuperclassFqn = StandardNames.WORKSPACE_ENTITY
|
||||
private val entitiesSuperclassFqn: FqName = WorkspaceModelDefaults.WORKSPACE_ENTITY.fqName
|
||||
|
||||
internal val blobClasses: List<FqName> = arrayListOf(
|
||||
StandardNames.VIRTUAL_FILE_URL,
|
||||
StandardNames.ENTITY_POINTER
|
||||
private val blobClasses: List<FqName> = arrayListOf(
|
||||
WorkspaceModelDefaults.VIRTUAL_FILE_URL.fqName,
|
||||
WorkspaceModelDefaults.ENTITY_POINTER.fqName
|
||||
)
|
||||
|
||||
|
||||
internal val ModuleDescriptor.moduleAbstractTypes: List<ClassDescriptor>
|
||||
get() = moduleAbstractTypesClassIds.mapNotNull { findClassAcrossModuleDependencies(it) }
|
||||
|
||||
internal fun ClassDescriptor.inheritors(
|
||||
javaPsiFacade: JavaPsiFacade, scope: GlobalSearchScope
|
||||
javaPsiFacade: JavaPsiFacade, scope: GlobalSearchScope,
|
||||
): List<ClassDescriptor> {
|
||||
val psiClass = javaPsiFacade.findClass(fqNameSafe.asString(), scope) ?: return emptyList()
|
||||
return psiClass.inheritors(scope).map { it.getJavaClassDescriptor()!! }
|
||||
val inheritors = ClassInheritorsSearch.search(psiClass, scope, true, true, false)
|
||||
.filterNot { it.qualifiedName == null }
|
||||
.sortedBy { it.qualifiedName } // Sorting is needed for consistency in case of regeneration
|
||||
return inheritors.map { it.getJavaClassDescriptor()!! }
|
||||
}
|
||||
|
||||
private fun PsiClass.inheritors(scope: SearchScope): List<PsiClass> {
|
||||
val inheritors = ClassInheritorsSearch.search(this, scope, true, true, false).asIterable().filterNot { it.isAnonymous }
|
||||
return inheritors.sortedBy { it.qualifiedName } //Sorting is needed for consistency in case of regeneration
|
||||
}
|
||||
|
||||
private val PsiClass.isAnonymous: Boolean
|
||||
get() = qualifiedName == null
|
||||
|
||||
|
||||
internal val ClassifierDescriptor.javaClassFqn: String
|
||||
get() {
|
||||
val nameWithoutPackage = fqNameSafe.asString()
|
||||
@@ -73,7 +67,7 @@ internal val ClassDescriptor.superTypesJavaFqns: List<String>
|
||||
get() = defaultType.supertypes()
|
||||
.mapNotNull { it.constructor.declarationDescriptor?.javaClassFqn }
|
||||
.withoutStandardTypes()
|
||||
|
||||
.sorted()
|
||||
|
||||
internal val ClassDescriptor.isObject: Boolean
|
||||
get() = kind == ClassKind.OBJECT
|
||||
@@ -96,11 +90,11 @@ internal val ClassDescriptor.isAbstractClassOrInterface: Boolean
|
||||
get() = !isFinalClass
|
||||
|
||||
internal val ClassDescriptor.isEntityInterface: Boolean
|
||||
get() = DescriptorUtils.isInterface(this) && defaultType.isSubclassOf(entitiesSuperclassFqn) // If this is `WorkspaceEntity` interface we need to check it
|
||||
// If this is `WorkspaceEntity` interface, we need to check it
|
||||
get() = DescriptorUtils.isInterface(this) && defaultType.isSubclassOf(entitiesSuperclassFqn)
|
||||
|
||||
internal val ClassDescriptor.isEntityBuilderInterface: Boolean
|
||||
get() = isEntityInterface && name.identifier == "Builder" //todo improve
|
||||
|
||||
get() = isEntityInterface && name.identifier == "Builder" // TODO: improve
|
||||
|
||||
private fun KotlinType.isSubclassOf(superClassName: FqName): Boolean {
|
||||
return constructor.declarationDescriptor?.fqNameSafe == superClassName || constructor.supertypes.any {
|
||||
@@ -108,32 +102,32 @@ private fun KotlinType.isSubclassOf(superClassName: FqName): Boolean {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun createObjTypeStub(interfaceDescriptor: ClassDescriptor, module: CompiledObjModuleImpl): ObjClassImpl<Obj> {
|
||||
val openness = when {
|
||||
interfaceDescriptor.isAnnotatedBy(StandardNames.ABSTRACT_ANNOTATION) -> ObjClass.Openness.abstract
|
||||
interfaceDescriptor.isAnnotatedBy(StandardNames.OPEN_ANNOTATION) -> ObjClass.Openness.open
|
||||
interfaceDescriptor.isAnnotatedBy(WorkspaceModelDefaults.ABSTRACT_ANNOTATION.fqName) -> ObjClass.Openness.abstract
|
||||
interfaceDescriptor.isAnnotatedBy(WorkspaceModelDefaults.OPEN_ANNOTATION.fqName) -> ObjClass.Openness.open
|
||||
else -> ObjClass.Openness.final
|
||||
}
|
||||
val propertyAnnotations = interfaceDescriptor.annotations
|
||||
.mapNotNull { it.fqName }
|
||||
.map { ObjAnnotationImpl(it.asString(), it.pathSegments().map { segment -> segment.asString() }) }
|
||||
return ObjClassImpl(module, interfaceDescriptor.name.identifier, openness, interfaceDescriptor.source, propertyAnnotations)
|
||||
.mapNotNull { it.fqName }
|
||||
.map { ObjAnnotationImpl(it.asString(), it.pathSegments().map { segment -> segment.asString() }) }
|
||||
return ObjClassImpl(module, interfaceDescriptor.name.identifier, openness, interfaceDescriptor.source.getPsi(), propertyAnnotations)
|
||||
}
|
||||
|
||||
internal fun computeKind(property: PropertyDescriptor): ObjProperty.ValueKind {
|
||||
val getter = property.getter ?: return ObjProperty.ValueKind.Plain
|
||||
internal fun PropertyDescriptor.computeKind(): ObjProperty.ValueKind {
|
||||
val getter = getter ?: return ObjProperty.ValueKind.Plain
|
||||
if (!getter.hasBody()) return ObjProperty.ValueKind.Plain
|
||||
val declaration = getter.source.getPsi() as? KtDeclarationWithBody ?: return ObjProperty.ValueKind.Plain
|
||||
val getterText = (declaration.bodyExpression ?: declaration.bodyBlockExpression)?.text
|
||||
return when {
|
||||
getterText == null -> ObjProperty.ValueKind.Plain
|
||||
getter.isAnnotatedBy(StandardNames.DEFAULT_ANNOTATION) -> ObjProperty.ValueKind.WithDefault(getterText)
|
||||
getter.isAnnotatedBy(WorkspaceModelDefaults.DEFAULT_ANNOTATION.fqName) -> ObjProperty.ValueKind.WithDefault(getterText)
|
||||
else -> ObjProperty.ValueKind.Computable(getterText)
|
||||
}
|
||||
}
|
||||
|
||||
private val standardTypes = setOf(Any::class.qualifiedName, CommonClassNames.JAVA_LANG_OBJECT, CommonClassNames.JAVA_LANG_ENUM)
|
||||
|
||||
private fun Iterable<String>.withoutStandardTypes(): List<String> {
|
||||
return filterNot { standardTypes.contains(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k1.metaModel
|
||||
|
||||
import com.intellij.psi.CommonClassNames
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
internal object ObjTypeConverter {
|
||||
private val javaPrimitiveTypes = mapOf(
|
||||
CommonClassNames.JAVA_LANG_BOOLEAN to ValueType.Boolean,
|
||||
CommonClassNames.JAVA_LANG_BYTE to ValueType.Byte,
|
||||
CommonClassNames.JAVA_LANG_SHORT to ValueType.Short,
|
||||
CommonClassNames.JAVA_LANG_INTEGER to ValueType.Int,
|
||||
CommonClassNames.JAVA_LANG_LONG to ValueType.Long,
|
||||
CommonClassNames.JAVA_LANG_FLOAT to ValueType.Float,
|
||||
CommonClassNames.JAVA_LANG_DOUBLE to ValueType.Double,
|
||||
CommonClassNames.JAVA_LANG_CHARACTER to ValueType.Char,
|
||||
CommonClassNames.JAVA_LANG_STRING to ValueType.String,
|
||||
)
|
||||
|
||||
private val kotlinPrimitiveTypes = mapOf(
|
||||
"kotlin.Boolean" to ValueType.Boolean,
|
||||
"kotlin.Byte" to ValueType.Byte,
|
||||
"kotlin.Short" to ValueType.Short,
|
||||
"kotlin.Int" to ValueType.Int,
|
||||
"kotlin.Long" to ValueType.Long,
|
||||
"kotlin.Float" to ValueType.Float,
|
||||
"kotlin.Double" to ValueType.Double,
|
||||
"kotlin.UByte" to ValueType.UByte,
|
||||
"kotlin.UShort" to ValueType.UShort,
|
||||
"kotlin.UInt" to ValueType.UInt,
|
||||
"kotlin.ULong" to ValueType.ULong,
|
||||
"kotlin.Char" to ValueType.Char,
|
||||
"kotlin.String" to ValueType.String,
|
||||
)
|
||||
|
||||
operator fun get(fqName: FqName): ValueType.Primitive<*>? =
|
||||
kotlinPrimitiveTypes[fqName.asString()] ?: javaPrimitiveTypes[fqName.asString()]
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k1.metaModel
|
||||
|
||||
import com.intellij.devkit.workspaceModel.metaModel.WorkspaceModelDefaults
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.CompiledObjModule
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
internal fun Annotated.isAnnotatedBy(fqName: FqName) = annotations.hasAnnotation(fqName)
|
||||
|
||||
internal val FqName.isCollection: Boolean
|
||||
get() = isList || isSet || isMap
|
||||
|
||||
internal val FqName.isList: Boolean
|
||||
get() = this == WorkspaceModelDefaults.LIST_INTERFACE.fqName
|
||||
|
||||
internal val FqName.isSet: Boolean
|
||||
get() = this == WorkspaceModelDefaults.SET_INTERFACE.fqName
|
||||
|
||||
internal val FqName.isMap: Boolean
|
||||
get() = this == WorkspaceModelDefaults.MAP_INTERFACE.fqName
|
||||
|
||||
internal data class CompiledObjModuleAndK1Module(
|
||||
val compiledObjModule: CompiledObjModule,
|
||||
val kotlinModule: ModuleDescriptor,
|
||||
)
|
||||
|
||||
internal infix fun CompiledObjModule.and(moduleDescriptor: ModuleDescriptor) = CompiledObjModuleAndK1Module(this, moduleDescriptor)
|
||||
+68
-125
@@ -1,24 +1,17 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.metaModel.impl
|
||||
package com.intellij.devkit.workspaceModel.k1.metaModel
|
||||
|
||||
import com.intellij.devkit.workspaceModel.metaModel.IncorrectObjInterfaceException
|
||||
import com.intellij.devkit.workspaceModel.metaModel.WorkspaceMetaModelProvider
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.extensions.*
|
||||
import com.intellij.devkit.workspaceModel.metaModel.WorkspaceModelDefaults
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.*
|
||||
import com.intellij.devkit.workspaceModel.metaModel.unsupportedType
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
import com.intellij.platform.workspace.storage.annotations.Abstract
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.annotations.Default
|
||||
import com.intellij.platform.workspace.storage.annotations.Open
|
||||
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
|
||||
import com.intellij.psi.CommonClassNames
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.*
|
||||
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
import org.jetbrains.kotlin.idea.base.projectStructure.productionSourceInfo
|
||||
import org.jetbrains.kotlin.idea.base.projectStructure.testSourceInfo
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -26,42 +19,46 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal class WorkspaceMetaModelProviderImpl(
|
||||
internal class WorkspaceMetaModelBuilder(
|
||||
private val processAbstractTypes: Boolean,
|
||||
project: Project
|
||||
): WorkspaceMetaModelProvider {
|
||||
private val objModuleByName = ConcurrentHashMap<String, Pair<CompiledObjModule, ModuleDescriptor>>()
|
||||
project: Project,
|
||||
) {
|
||||
private val objModuleByName = ConcurrentHashMap<String, CompiledObjModuleAndK1Module>()
|
||||
private val javaPsiFacade = JavaPsiFacade.getInstance(project)
|
||||
private val allScope = GlobalSearchScope.allScope(project)
|
||||
|
||||
override fun getObjModule(packageName: String, module: Module, isTestSourceFolder: Boolean): CompiledObjModule {
|
||||
val sourceInfo = if (!isTestSourceFolder) {
|
||||
fun getObjModule(packageName: String, module: Module, isTestSourceFolder: Boolean): CompiledObjModule {
|
||||
val sourceInfo = if (!isTestSourceFolder) {
|
||||
module.productionSourceInfo
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
module.testSourceInfo
|
||||
} ?: error("No production sources in ${module.name}")
|
||||
val resolutionFacade = KotlinCacheService.getInstance(module.project).getResolutionFacadeByModuleInfo(sourceInfo, sourceInfo.platform)!!
|
||||
val resolutionFacade = KotlinCacheService.getInstance(module.project).getResolutionFacadeByModuleInfo(sourceInfo, sourceInfo.platform)
|
||||
val moduleDescriptor = resolutionFacade.moduleDescriptor
|
||||
return getObjModule(packageName, moduleDescriptor)
|
||||
}
|
||||
|
||||
private fun getObjModule(packageName: String, moduleDescriptor: ModuleDescriptor): CompiledObjModule {
|
||||
val cached = objModuleByName[packageName]
|
||||
if (cached != null && cached.second == moduleDescriptor) return cached.first
|
||||
if (cached != null && cached.kotlinModule == moduleDescriptor) return cached.compiledObjModule
|
||||
val packageViewDescriptor = moduleDescriptor.getPackage(FqName(packageName))
|
||||
val objModuleStub = createObjModuleStub(moduleDescriptor, packageViewDescriptor, packageName)
|
||||
val result = registerObjModuleContent(packageViewDescriptor, objModuleStub, moduleDescriptor)
|
||||
objModuleByName[packageName] = result to moduleDescriptor
|
||||
return result
|
||||
val compiledObjModule = registerObjModuleContent(packageViewDescriptor, objModuleStub, moduleDescriptor)
|
||||
objModuleByName[packageName] = compiledObjModule and moduleDescriptor
|
||||
return compiledObjModule
|
||||
}
|
||||
|
||||
private fun registerObjModuleContent(packageViewDescriptor: PackageViewDescriptor,
|
||||
objModuleStub: ObjModuleStub,
|
||||
moduleDescriptor: ModuleDescriptor): CompiledObjModule {
|
||||
private fun registerObjModuleContent(
|
||||
packageViewDescriptor: PackageViewDescriptor,
|
||||
objModuleStub: ObjModuleStub,
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
): CompiledObjModule {
|
||||
val extensionProperties = packageViewDescriptor.fragments.flatMap { fragment ->
|
||||
fragment.getMemberScope().getContributedDescriptors(DescriptorKindFilter.VARIABLES)
|
||||
.filterIsInstance<PropertyDescriptor>()
|
||||
@@ -69,14 +66,16 @@ internal class WorkspaceMetaModelProviderImpl(
|
||||
.filter { it.module == moduleDescriptor }
|
||||
}
|
||||
val externalProperties = extensionProperties.mapNotNull { property ->
|
||||
val receiver = property.extensionReceiverParameter?.value?.type?.constructor?.declarationDescriptor as? ClassDescriptor
|
||||
receiver?.let { property to receiver }
|
||||
}.filter { it.second.isEntityInterface && !it.second.isEntityBuilderInterface }
|
||||
val receiver = property.extensionReceiverParameter?.value?.type?.constructor?.declarationDescriptor as? ClassDescriptor
|
||||
receiver?.let { property to receiver }
|
||||
}.filter { it.second.isEntityInterface && !it.second.isEntityBuilderInterface }
|
||||
return objModuleStub.registerContent(externalProperties)
|
||||
}
|
||||
|
||||
private fun createObjModuleStub(moduleDescriptor: ModuleDescriptor,
|
||||
packageViewDescriptor: PackageViewDescriptor, packageName: String): ObjModuleStub {
|
||||
private fun createObjModuleStub(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
packageViewDescriptor: PackageViewDescriptor, packageName: String,
|
||||
): ObjModuleStub {
|
||||
val entityInterfaces = packageViewDescriptor.fragments.flatMap { fragment ->
|
||||
fragment.getMemberScope().getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)
|
||||
.filterIsInstance<ClassDescriptor>()
|
||||
@@ -99,10 +98,12 @@ internal class WorkspaceMetaModelProviderImpl(
|
||||
return objModule.types.find { it.name == entityInterfaceName } ?: error("Cannot find $entityInterfaceName in $objModule")
|
||||
}
|
||||
|
||||
private inner class ObjModuleStub(val module: CompiledObjModuleImpl,
|
||||
val types: List<Pair<ClassDescriptor, ObjClassImpl<Obj>>>,
|
||||
val moduleAbstractTypes: List<ClassDescriptor>,
|
||||
val moduleDescriptor: ModuleDescriptor) {
|
||||
private inner class ObjModuleStub(
|
||||
val module: CompiledObjModuleImpl,
|
||||
val types: List<Pair<ClassDescriptor, ObjClassImpl<Obj>>>,
|
||||
val moduleAbstractTypes: List<ClassDescriptor>,
|
||||
val moduleDescriptor: ModuleDescriptor,
|
||||
) {
|
||||
fun registerContent(extProperties: List<Pair<PropertyDescriptor, ClassDescriptor>>): CompiledObjModule {
|
||||
var extPropertyId = 0
|
||||
for ((classDescriptor, objType) in types) {
|
||||
@@ -111,10 +112,11 @@ internal class WorkspaceMetaModelProviderImpl(
|
||||
.filter { it.kind.isReal }
|
||||
.filter { it.module == moduleDescriptor }
|
||||
for ((propertyId, property) in properties.withIndex()) {
|
||||
val kind = computeKind(property)
|
||||
val kind = property.computeKind()
|
||||
if (kind !is ObjProperty.ValueKind.Computable ||
|
||||
// We can't simply skip all `Computable` because some of them are SymbolicIds
|
||||
property.overriddenDescriptors.isNotEmpty()) {
|
||||
property.overriddenDescriptors.isNotEmpty()
|
||||
) {
|
||||
objType.addField(createOwnProperty(property, propertyId, objType))
|
||||
}
|
||||
}
|
||||
@@ -151,14 +153,16 @@ internal class WorkspaceMetaModelProviderImpl(
|
||||
}
|
||||
|
||||
|
||||
private fun createOwnProperty(property: PropertyDescriptor, propertyId: Int,
|
||||
receiver: ObjClassImpl<Obj>): OwnProperty<Obj, *> {
|
||||
val valueType = convertType(property.type, hashMapOf(), property.isAnnotatedBy (StandardNames.CHILD_ANNOTATION))
|
||||
private fun createOwnProperty(
|
||||
property: PropertyDescriptor, propertyId: Int,
|
||||
receiver: ObjClassImpl<Obj>,
|
||||
): OwnProperty<Obj, *> {
|
||||
val valueType = convertType(property.type, hashMapOf(), property.isAnnotatedBy(WorkspaceModelDefaults.CHILD_ANNOTATION.fqName))
|
||||
return OwnPropertyImpl(
|
||||
receiver, property.name.identifier, valueType, computeKind(property),
|
||||
property.isAnnotatedBy(StandardNames.OPEN_ANNOTATION), property.isVar,
|
||||
receiver, property.name.identifier, valueType, property.computeKind(),
|
||||
property.isAnnotatedBy(WorkspaceModelDefaults.OPEN_ANNOTATION.fqName), property.isVar,
|
||||
false, false, propertyId,
|
||||
property.isAnnotatedBy(StandardNames.EQUALS_BY_ANNOTATION), property.source
|
||||
property.isAnnotatedBy(WorkspaceModelDefaults.EQUALS_BY_ANNOTATION.fqName), property.source.getPsi()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -170,13 +174,17 @@ internal class WorkspaceMetaModelProviderImpl(
|
||||
?: emptyList()
|
||||
return ExtPropertyImpl(
|
||||
findObjClass(receiverClass), extProperty.name.identifier, valueType,
|
||||
computeKind(extProperty), extProperty.isAnnotatedBy(StandardNames.OPEN_ANNOTATION),
|
||||
extProperty.isVar, false, module, extPropertyId, propertyAnnotations, extProperty.source
|
||||
extProperty.computeKind(), extProperty.isAnnotatedBy(WorkspaceModelDefaults.OPEN_ANNOTATION.fqName),
|
||||
extProperty.isVar, false, module, extPropertyId, propertyAnnotations, extProperty.source.getPsi()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private fun convertType(type: KotlinType, knownTypes: MutableMap<String, ValueType.Blob<*>>, hasChildAnnotation: Boolean): ValueType<*> {
|
||||
private fun convertType(
|
||||
type: KotlinType,
|
||||
knownTypes: MutableMap<String, ValueType.Blob<*>>,
|
||||
hasChildAnnotation: Boolean,
|
||||
): ValueType<*> {
|
||||
if (type.isMarkedNullable) {
|
||||
return ValueType.Optional(convertType(type.makeNotNullable(), knownTypes, hasChildAnnotation))
|
||||
}
|
||||
@@ -185,7 +193,7 @@ internal class WorkspaceMetaModelProviderImpl(
|
||||
if (descriptor is ClassDescriptor) {
|
||||
val fqName = descriptor.fqNameSafe
|
||||
|
||||
val primitive = ObjTypeConverter.findPrimitive(fqName)
|
||||
val primitive = ObjTypeConverter[fqName]
|
||||
if (primitive != null) return primitive
|
||||
|
||||
if (fqName.isCollection) {
|
||||
@@ -199,7 +207,8 @@ internal class WorkspaceMetaModelProviderImpl(
|
||||
}
|
||||
|
||||
if (descriptor.isEntityInterface) {
|
||||
return ValueType.ObjRef(type.isAnnotatedBy(StandardNames.CHILD_ANNOTATION) || hasChildAnnotation, //todo leave only one target for @Child annotation
|
||||
return ValueType.ObjRef(type.isAnnotatedBy(
|
||||
WorkspaceModelDefaults.CHILD_ANNOTATION.fqName) || hasChildAnnotation, //todo leave only one target for @Child annotation
|
||||
findObjClass(descriptor))
|
||||
}
|
||||
return descriptor.toValueType(knownTypes, processAbstractTypes)
|
||||
@@ -208,7 +217,10 @@ internal class WorkspaceMetaModelProviderImpl(
|
||||
return unsupportedType(type.toString())
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.toValueType(knownTypes: MutableMap<String, ValueType.Blob<*>>, processAbstractTypes: Boolean): ValueType.JvmClass<*> {
|
||||
private fun ClassDescriptor.toValueType(
|
||||
knownTypes: MutableMap<String, ValueType.Blob<*>>,
|
||||
processAbstractTypes: Boolean,
|
||||
): ValueType.JvmClass<*> {
|
||||
val javaClassFqn = javaClassFqn
|
||||
val superTypes = superTypesJavaFqns
|
||||
|
||||
@@ -243,16 +255,21 @@ internal class WorkspaceMetaModelProviderImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun createProperties(descriptor: ClassDescriptor, knownTypes: MutableMap<String, ValueType.Blob<*>>): List<ValueType.ClassProperty<*>> {
|
||||
private fun createProperties(
|
||||
descriptor: ClassDescriptor,
|
||||
knownTypes: MutableMap<String, ValueType.Blob<*>>,
|
||||
): List<ValueType.ClassProperty<*>> {
|
||||
return descriptor.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.VARIABLES)
|
||||
.filterIsInstance<PropertyDescriptor>()
|
||||
.sortedBy { it.name.identifier }
|
||||
.map { ValueType.ClassProperty(it.name.identifier, convertType(it.type, knownTypes, false)) }
|
||||
}
|
||||
|
||||
|
||||
private fun findObjClass(descriptor: ClassDescriptor): ObjClass<*> {
|
||||
if (descriptor.packageOrDie.asString() == module.name) {
|
||||
return types.find { it.first.typeConstructor == descriptor.typeConstructor }?.second ?: error("Cannot find ${descriptor.fqNameSafe} in $module")
|
||||
return types.find { it.first.typeConstructor == descriptor.typeConstructor }?.second ?: error(
|
||||
"Cannot find ${descriptor.fqNameSafe} in $module")
|
||||
}
|
||||
return getObjClass(descriptor)
|
||||
}
|
||||
@@ -262,77 +279,3 @@ internal class WorkspaceMetaModelProviderImpl(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun Annotated.isAnnotatedBy(fqName: FqName) = annotations.hasAnnotation(fqName)
|
||||
|
||||
|
||||
private val FqName.isCollection: Boolean
|
||||
get() = isList || isSet || isMap
|
||||
|
||||
private val FqName.isList: Boolean
|
||||
get() = this == StandardNames.LIST_INTERFACE
|
||||
|
||||
private val FqName.isSet: Boolean
|
||||
get() = this == StandardNames.SET_INTERFACE
|
||||
|
||||
private val FqName.isMap: Boolean
|
||||
get() = this == StandardNames.MAP_INTERFACE
|
||||
|
||||
|
||||
private object ObjTypeConverter {
|
||||
private val javaPrimitiveTypes = mapOf(
|
||||
CommonClassNames.JAVA_LANG_BOOLEAN to ValueType.Boolean,
|
||||
CommonClassNames.JAVA_LANG_BYTE to ValueType.Byte,
|
||||
CommonClassNames.JAVA_LANG_SHORT to ValueType.Short,
|
||||
CommonClassNames.JAVA_LANG_INTEGER to ValueType.Int,
|
||||
CommonClassNames.JAVA_LANG_LONG to ValueType.Long,
|
||||
CommonClassNames.JAVA_LANG_FLOAT to ValueType.Float,
|
||||
CommonClassNames.JAVA_LANG_DOUBLE to ValueType.Double,
|
||||
CommonClassNames.JAVA_LANG_CHARACTER to ValueType.Char,
|
||||
CommonClassNames.JAVA_LANG_STRING to ValueType.String,
|
||||
)
|
||||
|
||||
private val kotlinPrimitiveTypes = mapOf(
|
||||
"kotlin.Boolean" to ValueType.Boolean,
|
||||
"kotlin.Byte" to ValueType.Byte,
|
||||
"kotlin.Short" to ValueType.Short,
|
||||
"kotlin.Int" to ValueType.Int,
|
||||
"kotlin.Long" to ValueType.Long,
|
||||
"kotlin.Float" to ValueType.Float,
|
||||
"kotlin.Double" to ValueType.Double,
|
||||
"kotlin.UByte" to ValueType.UByte,
|
||||
"kotlin.UShort" to ValueType.UShort,
|
||||
"kotlin.UInt" to ValueType.UInt,
|
||||
"kotlin.ULong" to ValueType.ULong,
|
||||
"kotlin.Char" to ValueType.Char,
|
||||
"kotlin.String" to ValueType.String,
|
||||
)
|
||||
|
||||
fun findPrimitive(fqName: FqName): ValueType.Primitive<*>? =
|
||||
kotlinPrimitiveTypes[fqName.asString()] ?: javaPrimitiveTypes[fqName.asString()]
|
||||
}
|
||||
|
||||
internal object StandardNames {
|
||||
val DEFAULT_ANNOTATION = FqName(Default::class.qualifiedName!!)
|
||||
val OPEN_ANNOTATION = FqName(Open::class.qualifiedName!!)
|
||||
val ABSTRACT_ANNOTATION = FqName(Abstract::class.qualifiedName!!)
|
||||
val CHILD_ANNOTATION = FqName(Child::class.qualifiedName!!)
|
||||
val EQUALS_BY_ANNOTATION = FqName(EqualsBy::class.qualifiedName!!)
|
||||
val LIST_INTERFACE = FqName(List::class.qualifiedName!!)
|
||||
val SET_INTERFACE = FqName(Set::class.qualifiedName!!)
|
||||
val MAP_INTERFACE = FqName(Map::class.qualifiedName!!)
|
||||
|
||||
val WORKSPACE_ENTITY = FqName(WorkspaceEntity::class.qualifiedName!!)
|
||||
val ENTITY_SOURCE = FqName(EntitySource::class.qualifiedName!!)
|
||||
val VIRTUAL_FILE_URL = FqName(VirtualFileUrl::class.qualifiedName!!)
|
||||
val SYMBOLIC_ENTITY_ID = FqName(SymbolicEntityId::class.qualifiedName!!)
|
||||
val ENTITY_POINTER = FqName(EntityPointer::class.qualifiedName!!)
|
||||
}
|
||||
|
||||
internal val standardTypes = setOf(Any::class.qualifiedName, CommonClassNames.JAVA_LANG_OBJECT, CommonClassNames.JAVA_LANG_ENUM)
|
||||
|
||||
|
||||
private fun unsupportedType(type: String?): ValueType<*> {
|
||||
throw IncorrectObjInterfaceException("Unsupported type '$type'")
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k1.metaModel
|
||||
|
||||
import com.intellij.devkit.workspaceModel.metaModel.WorkspaceMetaModelProvider
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.CompiledObjModule
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
|
||||
internal class WorkspaceMetaModelProviderImpl : WorkspaceMetaModelProvider {
|
||||
|
||||
override fun loadObjModules(
|
||||
ktClasses: HashMap<String, KtClass>,
|
||||
module: Module,
|
||||
processAbstractTypes: Boolean,
|
||||
isTestSourceFolder: Boolean,
|
||||
): List<CompiledObjModule> {
|
||||
val packages = ktClasses.values.mapTo(LinkedHashSet()) { it.containingKtFile.packageFqName.asString() }
|
||||
|
||||
val metaModelProvider = WorkspaceMetaModelBuilder(
|
||||
processAbstractTypes = processAbstractTypes,
|
||||
module.project
|
||||
)
|
||||
return packages.filter { it != "" }.map { metaModelProvider.getObjModule(it, module, isTestSourceFolder) }
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k1
|
||||
|
||||
import com.intellij.devkit.workspaceModel.AbstractAllIntellijEntitiesGenerationTest
|
||||
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode
|
||||
|
||||
class AllIntellijEntitiesGenerationTest : AbstractAllIntellijEntitiesGenerationTest() {
|
||||
override val pluginMode: KotlinPluginMode
|
||||
get() = KotlinPluginMode.K1
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k1
|
||||
|
||||
import com.intellij.devkit.workspaceModel.AbstractEntityCodeGenTest
|
||||
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode
|
||||
|
||||
class EntityCodeGenTest : AbstractEntityCodeGenTest() {
|
||||
override val pluginMode: KotlinPluginMode
|
||||
get() = KotlinPluginMode.K1
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="5" platform="JVM 17" allPlatforms="JVM [17]" useProjectSettings="false">
|
||||
<compilerSettings>
|
||||
<option name="additionalArguments" value="-Xjvm-default=all -opt-in=com.intellij.openapi.util.IntellijInternalApi -opt-in=org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction -opt-in=org.jetbrains.kotlin.analysis.api.KaIdeApi -opt-in=org.jetbrains.kotlin.analysis.api.KaNonPublicApi -opt-in=org.jetbrains.kotlin.analysis.api.permissions.KaAllowProhibitedAnalyzeFromWriteAction" />
|
||||
</compilerSettings>
|
||||
<compilerArguments>
|
||||
<stringArguments>
|
||||
<stringArg name="jvmTarget" arg="17" />
|
||||
<stringArg name="apiVersion" arg="2.0" />
|
||||
<stringArg name="languageVersion" arg="2.0" />
|
||||
</stringArguments>
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="com.intellij.devkit.workspaceModel.k2" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" packagePrefix="com.intellij.devkit.workspaceModel.k2" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.workspaceModel" />
|
||||
<orderEntry type="module" module-name="kotlin.base.indices" />
|
||||
<orderEntry type="module" module-name="kotlin.base.project-structure" />
|
||||
<orderEntry type="module" module-name="intellij.java.indexing" />
|
||||
<orderEntry type="module" module-name="intellij.platform.workspace.storage" />
|
||||
<orderEntry type="library" name="kotlin-stdlib" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="kotlinc.analysis-api" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="kotlinc.kotlin-compiler-common" level="project" />
|
||||
<orderEntry type="library" name="workspace-model-codegen" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core.impl" />
|
||||
<orderEntry type="module" module-name="intellij.java" />
|
||||
<orderEntry type="module" module-name="kotlin.base.psi" />
|
||||
<orderEntry type="module" module-name="intellij.devkit.workspaceModel.tests" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.test-framework" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.base.plugin" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.tests-common" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.plugin.k2" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.base.test" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<idea-plugin package="com.intellij.devkit.workspaceModel.k2">
|
||||
|
||||
<dependencies>
|
||||
<plugin id="com.intellij.modules.kotlin.k2"/>
|
||||
<module name="intellij.devkit.workspaceModel"/>
|
||||
</dependencies>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<applicationService serviceInterface="com.intellij.devkit.workspaceModel.metaModel.WorkspaceMetaModelProvider"
|
||||
serviceImplementation="com.intellij.devkit.workspaceModel.k2.metaModel.WorkspaceMetaModelProviderImpl"
|
||||
/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,143 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k2.metaModel
|
||||
|
||||
import com.intellij.devkit.workspaceModel.metaModel.WorkspaceModelDefaults
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.CompiledObjModuleImpl
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.ObjAnnotationImpl
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.ObjClassImpl
|
||||
import com.intellij.psi.CommonClassNames
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.Obj
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjClass
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ObjProperty
|
||||
import org.jetbrains.kotlin.analysis.api.KaSession
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotated
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.analysis.api.types.symbol
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
|
||||
internal fun KaAnnotated.isAnnotatedBy(classId: ClassId) = annotations.contains(classId)
|
||||
|
||||
private val moduleAbstractTypesClassIds: List<ClassId> = listOf(
|
||||
WorkspaceModelDefaults.ENTITY_SOURCE.classId,
|
||||
WorkspaceModelDefaults.SYMBOLIC_ENTITY_ID.classId,
|
||||
)
|
||||
|
||||
internal fun KaSession.inheritors(
|
||||
classSymbol: KaClassSymbol, javaPsiFacade: JavaPsiFacade, scope: GlobalSearchScope,
|
||||
): List<KtClassOrObject> {
|
||||
// can be rewritten using org.jetbrains.kotlin.idea.searching.inheritors.KotlinSearchUtilKt.findAllInheritors
|
||||
val psiClass = javaPsiFacade.findClass(classSymbol.javaClassFqn, scope) ?: return emptyList()
|
||||
return ClassInheritorsSearch.search(psiClass, scope, true, true, false)
|
||||
.filterNot { it.isAnonymous }
|
||||
.sortedBy { it.qualifiedName } // Sorting is needed for consistency in case of regeneration
|
||||
.mapNotNull {
|
||||
KotlinFullClassNameIndex[it.qualifiedName!!, it.project, scope].firstOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
private val standardTypes = setOf(Any::class.qualifiedName, CommonClassNames.JAVA_LANG_OBJECT, CommonClassNames.JAVA_LANG_ENUM)
|
||||
|
||||
internal fun KaSession.superTypesJavaFqns(
|
||||
classSymbol: KaClassSymbol, javaPsiFacade: JavaPsiFacade, scope: GlobalSearchScope,
|
||||
): List<String> {
|
||||
// FIXME: There's definitely smth wrong with AA
|
||||
val kaSuperTypes1 = classSymbol.defaultType.allSupertypes
|
||||
.mapNotNull { it.expandedSymbol?.javaClassFqn }
|
||||
.toList()
|
||||
val kaSuperTypes2 = classSymbol.superTypes.flatMap { listOf(it) + it.allSupertypes }
|
||||
.mapNotNull { it.expandedSymbol?.javaClassFqn }
|
||||
.toList()
|
||||
val psiSuperTypes = javaPsiFacade.findClass(classSymbol.javaClassFqn, scope)?.supers?.mapNotNull { it.qualifiedName }
|
||||
?: emptyList()
|
||||
val mergedSuperTypes = (psiSuperTypes + kaSuperTypes1 + kaSuperTypes2).distinct()
|
||||
return mergedSuperTypes.withoutStandardTypes().sorted()
|
||||
}
|
||||
|
||||
// TODO: merge with above?
|
||||
internal val KaClassSymbol.superTypesJavaFqns: List<String>
|
||||
get() = superTypes.mapNotNull { it.symbol?.javaClassFqn }.withoutStandardTypes().sorted()
|
||||
|
||||
private val PsiClass.isAnonymous: Boolean
|
||||
get() = qualifiedName == null
|
||||
|
||||
internal val KaClassLikeSymbol.javaClassFqn: String
|
||||
get() {
|
||||
val nameWithoutPackage = classId?.asSingleFqName()?.asString()
|
||||
?.substringAfter("$packageName.")
|
||||
?.replace(".", "$")
|
||||
return "$packageName.$nameWithoutPackage"
|
||||
}
|
||||
|
||||
internal val KaClassLikeSymbol.packageName: String
|
||||
get() = packageOrDie.asString()
|
||||
|
||||
internal val KaClassLikeSymbol.packageOrDie: FqName
|
||||
get() = classId?.packageFqName ?: error("$name has no package")
|
||||
|
||||
internal fun KaSession.getPackageSymbol(classSymbol: KaClassSymbol): KaPackageSymbol? =
|
||||
classSymbol.classId?.packageFqName?.let { findPackage(it) }
|
||||
|
||||
private val blobClasses: List<ClassId> = arrayListOf(
|
||||
WorkspaceModelDefaults.VIRTUAL_FILE_URL.classId,
|
||||
WorkspaceModelDefaults.ENTITY_POINTER.classId,
|
||||
)
|
||||
|
||||
internal fun KaSession.isBlob(classSymbol: KaClassSymbol): Boolean {
|
||||
val classId = classSymbol.classId ?: return false
|
||||
return blobClasses.any { blobClass -> classSymbol.defaultType.isSubtypeOf(blobClass) } ||
|
||||
classId in moduleAbstractTypesClassIds ||
|
||||
classId.packageFqName.asString().startsWith("java.") ||
|
||||
classId.packageFqName.asString().startsWith("kotlin.")
|
||||
}
|
||||
|
||||
private fun Iterable<String>.withoutStandardTypes(): List<String> {
|
||||
return filterNot { standardTypes.contains(it) }
|
||||
}
|
||||
|
||||
internal fun KaSession.moduleAbstractTypes(): List<KaClassSymbol> {
|
||||
return moduleAbstractTypesClassIds.mapNotNull { classId -> findClass(classId) }
|
||||
}
|
||||
|
||||
internal fun KaSession.isEntityInterface(classSymbol: KaClassSymbol): Boolean =
|
||||
classSymbol.classKind == KaClassKind.INTERFACE && classSymbol.defaultType.isSubtypeOf(WorkspaceModelDefaults.WORKSPACE_ENTITY.classId)
|
||||
|
||||
internal fun KaSession.isEntityBuilderInterface(classSymbol: KaClassSymbol): Boolean =
|
||||
isEntityInterface(classSymbol) && classSymbol.name?.identifier == "Builder" // TODO: improve
|
||||
|
||||
internal fun KaSession.computeKind(property: KaPropertySymbol): ObjProperty.ValueKind {
|
||||
val getter = property.getter ?: return ObjProperty.ValueKind.Plain
|
||||
if (!getter.hasBody) return ObjProperty.ValueKind.Plain
|
||||
val declaration = getter.psi as? KtDeclarationWithBody ?: return ObjProperty.ValueKind.Plain
|
||||
val getterText = (declaration.bodyExpression ?: declaration.bodyBlockExpression)?.text
|
||||
return when {
|
||||
getterText == null -> ObjProperty.ValueKind.Plain
|
||||
getter.isAnnotatedBy(WorkspaceModelDefaults.DEFAULT_ANNOTATION.classId) -> ObjProperty.ValueKind.WithDefault(getterText)
|
||||
else -> ObjProperty.ValueKind.Computable(getterText)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun KaSession.createObjTypeStub(symbol: KaClassSymbol, module: CompiledObjModuleImpl): ObjClassImpl<Obj> {
|
||||
val openness = when {
|
||||
symbol.isAnnotatedBy(WorkspaceModelDefaults.ABSTRACT_ANNOTATION.classId) -> ObjClass.Openness.abstract
|
||||
symbol.isAnnotatedBy(WorkspaceModelDefaults.OPEN_ANNOTATION.classId) -> ObjClass.Openness.open
|
||||
else -> ObjClass.Openness.final
|
||||
}
|
||||
|
||||
val propertyAnnotations = symbol.annotations
|
||||
.mapNotNull { it.classId?.asSingleFqName() }
|
||||
.map { ObjAnnotationImpl(it.asString(), it.pathSegments().map { segment -> segment.asString() }) }
|
||||
|
||||
return ObjClassImpl(module, symbol.name?.identifier!!, openness, symbol.sourcePsi(), propertyAnnotations)
|
||||
}
|
||||
|
||||
internal fun KaSession.isChild(kaType: KaAnnotated) =
|
||||
kaType.isAnnotatedBy(WorkspaceModelDefaults.CHILD_ANNOTATION.classId)
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k2.metaModel
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
import org.jetbrains.kotlin.analysis.api.components.DefaultTypeClassIds
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
internal object ObjTypeConverter {
|
||||
private val kotlinDefaultTypeToValueType = mapOf(
|
||||
DefaultTypeClassIds.BOOLEAN to ValueType.Boolean,
|
||||
DefaultTypeClassIds.BYTE to ValueType.Byte,
|
||||
DefaultTypeClassIds.SHORT to ValueType.Short,
|
||||
DefaultTypeClassIds.INT to ValueType.Int,
|
||||
DefaultTypeClassIds.LONG to ValueType.Long,
|
||||
DefaultTypeClassIds.FLOAT to ValueType.Float,
|
||||
DefaultTypeClassIds.DOUBLE to ValueType.Double,
|
||||
DefaultTypeClassIds.CHAR to ValueType.Char,
|
||||
DefaultTypeClassIds.STRING to ValueType.String,
|
||||
StandardNames.FqNames.uByte to ValueType.UByte,
|
||||
StandardNames.FqNames.uShort to ValueType.UShort,
|
||||
StandardNames.FqNames.uInt to ValueType.UInt,
|
||||
StandardNames.FqNames.uLong to ValueType.ULong,
|
||||
)
|
||||
|
||||
operator fun get(classId: ClassId?): ValueType.Primitive<*>? = classId?.let { kotlinDefaultTypeToValueType[it] }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k2.metaModel
|
||||
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.CompiledObjModule
|
||||
import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
|
||||
|
||||
internal data class CompiledObjModuleAndK2Module(val compiledObjModule: CompiledObjModule, val kotlinModule: KaModule)
|
||||
|
||||
internal infix fun CompiledObjModule.and(kaModule: KaModule) = CompiledObjModuleAndK2Module(this, kaModule)
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k2.metaModel
|
||||
|
||||
import com.intellij.devkit.workspaceModel.metaModel.IncorrectObjInterfaceException
|
||||
import com.intellij.devkit.workspaceModel.metaModel.WorkspaceModelDefaults
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.*
|
||||
import com.intellij.devkit.workspaceModel.metaModel.unsupportedType
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.util.concurrency.annotations.RequiresReadLock
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.*
|
||||
import org.jetbrains.kotlin.analysis.api.KaSession
|
||||
import org.jetbrains.kotlin.analysis.api.analyze
|
||||
import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.analysis.api.types.KaClassType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KaType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KaTypeNullability
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinExactPackagesIndex
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal class WorkspaceMetaModelBuilder(
|
||||
private val processAbstractTypes: Boolean,
|
||||
private val project: Project,
|
||||
) {
|
||||
private val objModuleByName = ConcurrentHashMap<String, CompiledObjModuleAndK2Module>()
|
||||
private val javaPsiFacade = JavaPsiFacade.getInstance(project)
|
||||
private val allProjectScope = GlobalSearchScope.allScope(project)
|
||||
|
||||
@RequiresReadLock
|
||||
fun getObjModule(
|
||||
packageName: String,
|
||||
kaModule: KaModule,
|
||||
): CompiledObjModule = analyze(kaModule) {
|
||||
val ktFile = KotlinExactPackagesIndex.get(packageName, project, kaModule.contentScope).firstOrNull()
|
||||
?: error("Cannot find any files with package $packageName in module ${kaModule}")
|
||||
val packageSymbol = findPackage(ktFile.packageFqName) ?: error("Could not find package $packageName in module ${kaModule}")
|
||||
getObjModule(packageName, packageSymbol, kaModule)
|
||||
}
|
||||
|
||||
private fun KaSession.getObjModule(
|
||||
packageName: String,
|
||||
packageSymbol: KaPackageSymbol,
|
||||
kaModule: KaModule,
|
||||
): CompiledObjModule {
|
||||
val cached = objModuleByName[packageName]
|
||||
if (cached != null && cached.kotlinModule == kaModule) return cached.compiledObjModule
|
||||
val objModuleStub = createObjModuleStub(packageName, packageSymbol, kaModule)
|
||||
val compiledObjModule = registerObjModuleContent(packageSymbol, objModuleStub, kaModule)
|
||||
objModuleByName[packageName] = compiledObjModule and kaModule
|
||||
return compiledObjModule
|
||||
}
|
||||
|
||||
private fun KaSession.registerObjModuleContent(
|
||||
packageSymbol: KaPackageSymbol,
|
||||
objModuleStub: ObjModuleStub,
|
||||
kaModule: KaModule,
|
||||
): CompiledObjModule {
|
||||
val extensionProperties = packageSymbol.packageScope.callables
|
||||
.filterIsInstance<KaPropertySymbol>()
|
||||
.filter { it.isExtension }
|
||||
.filter { it.containingModule == kaModule }
|
||||
.mapNotNull { propertySymbol ->
|
||||
propertySymbol.receiverType?.expandedSymbol
|
||||
?.takeIf { receiverClassSymbol -> isEntityInterface(receiverClassSymbol) && !isEntityBuilderInterface(receiverClassSymbol) }
|
||||
?.let { propertySymbol to it }
|
||||
}
|
||||
return objModuleStub.registerContent(this@registerObjModuleContent, extensionProperties.toList())
|
||||
}
|
||||
|
||||
private fun KaSession.createObjModuleStub(
|
||||
packageName: String,
|
||||
packageSymbol: KaPackageSymbol,
|
||||
kaModule: KaModule,
|
||||
): ObjModuleStub {
|
||||
val module = CompiledObjModuleImpl(packageName)
|
||||
|
||||
val types = packageSymbol.packageScope.declarations
|
||||
.filterIsInstance<KaClassSymbol>()
|
||||
.filter(::isEntityInterface)
|
||||
.filter { it.containingModule == kaModule }
|
||||
.sortedBy { it.name }
|
||||
.map { it to createObjTypeStub(it, module) }
|
||||
.toList()
|
||||
|
||||
val moduleAbstractTypes = moduleAbstractTypes()
|
||||
return ObjModuleStub(module, types, moduleAbstractTypes, kaModule)
|
||||
}
|
||||
|
||||
private fun KaSession.getObjClass(entityInterface: KaClassSymbol): ObjClass<*> {
|
||||
val containingPackage = getPackageSymbol(entityInterface) ?: error("Cannot find package for ${entityInterface.name ?: entityInterface}")
|
||||
val objModule = getObjModule(entityInterface.packageName, containingPackage, entityInterface.containingModule)
|
||||
val entityInterfaceName = entityInterface.name?.identifier ?: error("Too many errors")
|
||||
return objModule.types.find { it.name == entityInterfaceName } ?: error("Cannot find $entityInterfaceName in $objModule")
|
||||
}
|
||||
|
||||
private inner class ObjModuleStub(
|
||||
val module: CompiledObjModuleImpl,
|
||||
// TODO: storing KaClassSymbol is unsafe, ObjModuleStub should inherit from KaLifetimeOwner
|
||||
val types: List<Pair<KaClassSymbol, ObjClassImpl<Obj>>>,
|
||||
val moduleAbstractTypes: List<KaClassSymbol>,
|
||||
val kaModule: KaModule,
|
||||
) /* : KaLifetimeOwner */ {
|
||||
@RequiresReadLock
|
||||
fun registerContent(kaSession: KaSession, extProperties: List<Pair<KaPropertySymbol, KaClassSymbol>>): CompiledObjModule =
|
||||
with(kaSession) {
|
||||
var extPropertyId = 0
|
||||
for ((classSymbol, objType) in types) {
|
||||
val properties = classSymbol.declaredMemberScope.callables
|
||||
.filterIsInstance<KaPropertySymbol>().toList()
|
||||
.filter { it.containingModule == kaModule }
|
||||
|
||||
for ((propertyId, propertySymbol) in properties.withIndex()) {
|
||||
val kind = computeKind(propertySymbol)
|
||||
if (kind !is ObjProperty.ValueKind.Computable ||
|
||||
// We can't simply skip all `Computable` because some of them are SymbolicIds
|
||||
// propertySymbol.overriddenDescriptors.isNotEmpty()
|
||||
propertySymbol.allOverriddenSymbols.any()
|
||||
) {
|
||||
objType.addField(createOwnProperty(propertySymbol, propertyId, objType))
|
||||
}
|
||||
}
|
||||
|
||||
classSymbol.superTypes.forEach { superType ->
|
||||
val superSymbol = superType.expandedSymbol
|
||||
if (superSymbol is KaClassSymbol && isEntityInterface(superSymbol)) {
|
||||
val superClass = findObjClass(superSymbol)
|
||||
objType.addSuperType(superClass)
|
||||
}
|
||||
}
|
||||
|
||||
module.addType(objType)
|
||||
}
|
||||
|
||||
registerModuleAbstractTypes()
|
||||
|
||||
for ((extProperty, receiverClass) in extProperties) {
|
||||
module.addExtension(createExtProperty(extProperty, receiverClass, extPropertyId++))
|
||||
}
|
||||
|
||||
module
|
||||
}
|
||||
|
||||
private fun KaSession.registerModuleAbstractTypes() {
|
||||
for (abstractTypeClassSymbol in moduleAbstractTypes) {
|
||||
val javaClassFqn = abstractTypeClassSymbol.javaClassFqn
|
||||
val superTypes = abstractTypeClassSymbol.superTypesJavaFqns
|
||||
val blobType = ValueType.Blob<Any>(javaClassFqn, superTypes)
|
||||
|
||||
val inheritors = mutableListOf<ValueType.JvmClass<*>>()
|
||||
val inheritorsKtClasses = inheritors(abstractTypeClassSymbol, javaPsiFacade, allProjectScope)
|
||||
for (inheritor in inheritorsKtClasses) {
|
||||
analyze(inheritor) {
|
||||
val inheritorSymbol = inheritor.namedClassSymbol
|
||||
if (inheritorSymbol != null && inheritorSymbol.packageName == module.name && inheritorSymbol.containingModule == kaModule) {
|
||||
val inheritorValueType = classSymbolToValueType(inheritorSymbol, hashMapOf(javaClassFqn to blobType), true)
|
||||
inheritors.add(inheritorValueType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inheritors.isNotEmpty()) {
|
||||
module.addAbstractType(ValueType.AbstractClass<Any>(javaClassFqn, superTypes, inheritors))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KaSession.createOwnProperty(
|
||||
property: KaPropertySymbol,
|
||||
propertyId: Int,
|
||||
receiver: ObjClassImpl<Obj>,
|
||||
): OwnProperty<Obj, *> {
|
||||
val valueType = convertType(property.returnType, hashMapOf(), isChild(property))
|
||||
return OwnPropertyImpl(receiver, property.name.identifier, valueType, computeKind(property),
|
||||
property.isAnnotatedBy(WorkspaceModelDefaults.OPEN_ANNOTATION.classId), !property.isVal, false, false,
|
||||
propertyId, property.isAnnotatedBy(WorkspaceModelDefaults.EQUALS_BY_ANNOTATION.classId),
|
||||
property.sourcePsiSafe())
|
||||
}
|
||||
|
||||
private fun KaSession.createExtProperty(
|
||||
extProperty: KaPropertySymbol,
|
||||
receiverClass: KaClassSymbol,
|
||||
extPropertyId: Int,
|
||||
): ExtProperty<*, *> {
|
||||
val valueType = convertType(extProperty.returnType, hashMapOf(), false)
|
||||
val propertyAnnotations = extProperty.getter?.annotations?.mapNotNull { annotation ->
|
||||
annotation.classId?.asSingleFqName()?.let {
|
||||
ObjAnnotationImpl(it.asString(), it.pathSegments().map { segment -> segment.asString() })
|
||||
}
|
||||
} ?: emptyList()
|
||||
|
||||
return ExtPropertyImpl(findObjClass(receiverClass), extProperty.name.identifier, valueType, computeKind(extProperty),
|
||||
extProperty.isAnnotatedBy(WorkspaceModelDefaults.OPEN_ANNOTATION.classId), !extProperty.isVal, false, module,
|
||||
extPropertyId, propertyAnnotations, extProperty.sourcePsiSafe())
|
||||
}
|
||||
|
||||
private fun KaSession.convertType(
|
||||
type: KaType,
|
||||
knownTypes: MutableMap<String, ValueType.Blob<*>>,
|
||||
hasChildAnnotation: Boolean,
|
||||
): ValueType<*> {
|
||||
if (type !is KaClassType) error("$type is not a class")
|
||||
if (type.nullability == KaTypeNullability.NULLABLE) {
|
||||
val nonNullableType = type.withNullability(KaTypeNullability.NON_NULLABLE)
|
||||
return ValueType.Optional(convertType(nonNullableType, knownTypes, hasChildAnnotation))
|
||||
}
|
||||
|
||||
val symbol = type.expandedSymbol
|
||||
if (symbol is KaClassSymbol) {
|
||||
val kotlinDefaultValueType = ObjTypeConverter[type.symbol.classId]
|
||||
if (kotlinDefaultValueType != null) return kotlinDefaultValueType
|
||||
|
||||
if (type.isSubtypeOf(StandardClassIds.Collection)) {
|
||||
val typeArguments = type.typeArguments.mapNotNull { it.type }
|
||||
val genericType = convertType(typeArguments.first(), knownTypes, hasChildAnnotation)
|
||||
when {
|
||||
type.isSubtypeOf(StandardClassIds.List) -> return ValueType.List(genericType)
|
||||
type.isSubtypeOf(StandardClassIds.Set) -> return ValueType.Set(genericType)
|
||||
else -> return unsupportedType(type.toString())
|
||||
}
|
||||
}
|
||||
|
||||
if (type.isSubtypeOf(StandardClassIds.Map)) {
|
||||
val (keyType, valueType) = type.typeArguments.mapNotNull { it.type }
|
||||
val convertedKeyType = convertType(keyType, knownTypes, hasChildAnnotation)
|
||||
val convertedValueType = convertType(valueType, knownTypes, hasChildAnnotation)
|
||||
return ValueType.Map(convertedKeyType, convertedValueType)
|
||||
}
|
||||
|
||||
if (symbol.classKind == KaClassKind.INTERFACE && type.isSubtypeOf(WorkspaceModelDefaults.WORKSPACE_ENTITY.classId)) {
|
||||
// TODO IJPL-600 Replace @Child annotation to @Parent annotation and not for the type, but for the field
|
||||
return ValueType.ObjRef(isChild(type) || hasChildAnnotation, findObjClass(symbol))
|
||||
}
|
||||
|
||||
return classSymbolToValueType(symbol, knownTypes, processAbstractTypes)
|
||||
}
|
||||
|
||||
return unsupportedType(type.toString())
|
||||
}
|
||||
|
||||
private fun KaSession.findObjClass(classSymbol: KaClassSymbol): ObjClass<*> {
|
||||
if (classSymbol.packageOrDie.asString() == module.name) {
|
||||
return types.find { it.first.classId == classSymbol.classId }?.second
|
||||
?: error("Cannot find ${classSymbol.name} in $module")
|
||||
}
|
||||
return getObjClass(classSymbol)
|
||||
}
|
||||
|
||||
private fun KaSession.classSymbolToValueType(
|
||||
classSymbol: KaClassSymbol,
|
||||
knownTypes: MutableMap<String, ValueType.Blob<*>>,
|
||||
processAbstractTypes: Boolean,
|
||||
): ValueType.JvmClass<*> {
|
||||
val javaClassFqn = classSymbol.javaClassFqn
|
||||
val superTypesJavaFqns = superTypesJavaFqns(classSymbol, javaPsiFacade, allProjectScope)
|
||||
|
||||
val blobType = ValueType.Blob<Any>(javaClassFqn, superTypesJavaFqns)
|
||||
if (knownTypes.containsKey(javaClassFqn) || isBlob(classSymbol)) {
|
||||
return blobType
|
||||
}
|
||||
|
||||
knownTypes[javaClassFqn] = blobType
|
||||
|
||||
return when {
|
||||
classSymbol.classKind == KaClassKind.OBJECT -> ValueType.Object<Any>(javaClassFqn, superTypesJavaFqns,
|
||||
createProperties(classSymbol, knownTypes).toList())
|
||||
classSymbol.classKind == KaClassKind.ENUM_CLASS -> {
|
||||
val enumEntries = classSymbol.staticMemberScope.callables.filterIsInstance<KaEnumEntrySymbol>().map { it.name.asString() }
|
||||
ValueType.Enum<Any>(javaClassFqn, superTypesJavaFqns, enumEntries.toList(),
|
||||
createProperties(classSymbol, knownTypes).asSequence().withoutEnumFields().toList())
|
||||
}
|
||||
classSymbol.modality == KaSymbolModality.SEALED && classSymbol is KaNamedClassSymbol -> {
|
||||
val subclasses = classSymbol.sealedClassInheritors
|
||||
.map { convertType(it.defaultType, knownTypes, false) as ValueType.JvmClass<*> }
|
||||
ValueType.AbstractClass<Any>(javaClassFqn, superTypesJavaFqns, subclasses)
|
||||
}
|
||||
classSymbol.classKind == KaClassKind.INTERFACE || classSymbol.modality == KaSymbolModality.ABSTRACT -> {
|
||||
if (!processAbstractTypes) {
|
||||
throw IncorrectObjInterfaceException("$javaClassFqn is abstract type. Abstract types are not supported in generator")
|
||||
}
|
||||
val inheritors = inheritors(classSymbol, javaPsiFacade, allProjectScope)
|
||||
.mapNotNull { ktClassOrObject ->
|
||||
analyze(ktClassOrObject) {
|
||||
val inheritorSymbol = ktClassOrObject.namedClassSymbol
|
||||
if (inheritorSymbol != null) {
|
||||
classSymbolToValueType(inheritorSymbol, knownTypes, processAbstractTypes)
|
||||
}
|
||||
else null
|
||||
}
|
||||
}
|
||||
ValueType.AbstractClass<Any>(javaClassFqn, superTypesJavaFqns, inheritors)
|
||||
}
|
||||
else -> ValueType.FinalClass<Any>(javaClassFqn, superTypesJavaFqns, createProperties(classSymbol, knownTypes).toList())
|
||||
}
|
||||
}
|
||||
|
||||
private fun KaSession.createProperties(classSymbol: KaClassSymbol, knownTypes: MutableMap<String, ValueType.Blob<*>>) =
|
||||
classSymbol.memberScope.callables
|
||||
.filterIsInstance<KaPropertySymbol>()
|
||||
.sortedBy { symbol -> symbol.name }
|
||||
.map { propertySymbol ->
|
||||
propertySymbol.location
|
||||
ValueType.ClassProperty(propertySymbol.name.identifier, convertType(propertySymbol.returnType, knownTypes, false))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Kirill does not understand why it exists
|
||||
private fun Sequence<ValueType.ClassProperty<*>>.withoutEnumFields() = filterNot { it.name == "name" || it.name == "ordinal" }
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k2.metaModel
|
||||
|
||||
import com.intellij.devkit.workspaceModel.metaModel.WorkspaceMetaModelProvider
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.CompiledObjModule
|
||||
import org.jetbrains.kotlin.analysis.api.permissions.KaAllowAnalysisFromWriteAction
|
||||
import org.jetbrains.kotlin.analysis.api.permissions.KaAllowAnalysisOnEdt
|
||||
import org.jetbrains.kotlin.analysis.api.permissions.allowAnalysisFromWriteAction
|
||||
import org.jetbrains.kotlin.analysis.api.permissions.allowAnalysisOnEdt
|
||||
import org.jetbrains.kotlin.idea.base.projectStructure.toKaSourceModuleForProduction
|
||||
import org.jetbrains.kotlin.idea.base.projectStructure.toKaSourceModuleForTest
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
|
||||
internal class WorkspaceMetaModelProviderImpl : WorkspaceMetaModelProvider {
|
||||
|
||||
@OptIn(KaAllowAnalysisFromWriteAction::class, KaAllowAnalysisOnEdt::class)
|
||||
override fun loadObjModules(
|
||||
ktClasses: HashMap<String, KtClass>,
|
||||
module: Module,
|
||||
processAbstractTypes: Boolean,
|
||||
isTestSourceFolder: Boolean,
|
||||
): List<CompiledObjModule> {
|
||||
val packages = ktClasses.values.mapTo(LinkedHashSet()) { it.containingKtFile.packageFqName.asString() }
|
||||
|
||||
val metaModelProvider = WorkspaceMetaModelBuilder(
|
||||
processAbstractTypes,
|
||||
module.project
|
||||
)
|
||||
val compiledObjModule = allowAnalysisOnEdt {
|
||||
allowAnalysisFromWriteAction {
|
||||
packages
|
||||
.filter { it != "" }
|
||||
.mapNotNull { packageName ->
|
||||
if (!isTestSourceFolder) {
|
||||
module.toKaSourceModuleForProduction()
|
||||
}
|
||||
else {
|
||||
module.toKaSourceModuleForTest()
|
||||
}
|
||||
?.let { kaModule ->
|
||||
metaModelProvider.getObjModule(packageName, kaModule)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return compiledObjModule
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k2
|
||||
|
||||
import com.intellij.devkit.workspaceModel.AbstractAllIntellijEntitiesGenerationTest
|
||||
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode
|
||||
|
||||
class AllIntellijEntitiesGenerationTest : AbstractAllIntellijEntitiesGenerationTest() {
|
||||
override val pluginMode: KotlinPluginMode
|
||||
get() = KotlinPluginMode.K2
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.k2
|
||||
|
||||
import com.intellij.devkit.workspaceModel.AbstractEntityCodeGenTest
|
||||
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode
|
||||
|
||||
class EntityCodeGenTest : AbstractEntityCodeGenTest() {
|
||||
override val pluginMode: KotlinPluginMode
|
||||
get() = KotlinPluginMode.K2
|
||||
}
|
||||
+3
@@ -1,10 +1,13 @@
|
||||
<idea-plugin package="com.intellij.devkit.workspaceModel">
|
||||
|
||||
<dependencies>
|
||||
<plugin id="com.intellij.java"/>
|
||||
<plugin id="org.jetbrains.kotlin"/>
|
||||
<module name="intellij.devkit.core"/>
|
||||
</dependencies>
|
||||
|
||||
<resource-bundle>messages.DevKitWorkspaceModelBundle</resource-bundle>
|
||||
|
||||
<actions>
|
||||
<group id="WorkspaceModel" popup="true">
|
||||
<action id="WorkspaceEntitiesJsonClipboard" internal="true"
|
||||
|
||||
@@ -11,9 +11,9 @@ private const val BUNDLE_FQN = "messages.DevKitWorkspaceModelBundle"
|
||||
|
||||
object DevKitWorkspaceModelBundle {
|
||||
private val BUNDLE = DynamicBundle(DevKitWorkspaceModelBundle::class.java, BUNDLE_FQN)
|
||||
|
||||
|
||||
fun message(@NonNls @PropertyKey(resourceBundle = BUNDLE_FQN) key: String, vararg params: Any): @Nls String {
|
||||
|
||||
@Nls
|
||||
fun message(@NonNls @PropertyKey(resourceBundle = BUNDLE_FQN) key: String, vararg params: Any): String {
|
||||
return BUNDLE.getMessage(key, *params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,14 @@ package com.intellij.devkit.workspaceModel.codegen.writer
|
||||
import com.intellij.application.options.CodeStyle
|
||||
import com.intellij.devkit.workspaceModel.CodegenJarLoader
|
||||
import com.intellij.devkit.workspaceModel.DevKitWorkspaceModelBundle
|
||||
import com.intellij.devkit.workspaceModel.codegen.writer.CodeWriter.addGeneratedObjModuleFile
|
||||
import com.intellij.devkit.workspaceModel.metaModel.WorkspaceMetaModelProvider
|
||||
import com.intellij.devkit.workspaceModel.metaModel.impl.WorkspaceMetaModelProviderImpl
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.notification.NotificationGroupManager
|
||||
import com.intellij.notification.NotificationType
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.command.executeCommand
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.DumbService
|
||||
@@ -21,7 +22,7 @@ import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings
|
||||
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil
|
||||
import com.intellij.util.concurrency.annotations.RequiresEdt
|
||||
import com.intellij.util.containers.FactoryMap
|
||||
@@ -31,7 +32,7 @@ import com.intellij.workspaceModel.codegen.engine.*
|
||||
import kotlinx.coroutines.delay
|
||||
import org.jetbrains.io.JsonReaderEx
|
||||
import org.jetbrains.io.JsonUtil
|
||||
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
|
||||
import org.jetbrains.kotlin.idea.formatter.kotlinCustomSettings
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.children
|
||||
@@ -42,6 +43,7 @@ import java.util.*
|
||||
import java.util.jar.Manifest
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
|
||||
private val LOG = logger<CodeWriter>()
|
||||
|
||||
object CodeWriter {
|
||||
@@ -51,7 +53,7 @@ object CodeWriter {
|
||||
processAbstractTypes: Boolean, explicitApiEnabled: Boolean,
|
||||
isTestSourceFolder: Boolean, isTestModule: Boolean,
|
||||
targetFolderGenerator: () -> VirtualFile?,
|
||||
existingTargetFolder: () -> VirtualFile?
|
||||
existingTargetFolder: () -> VirtualFile?,
|
||||
) {
|
||||
val sourceFilePerObjModule = HashMap<String, VirtualFile>()
|
||||
val ktClasses = HashMap<String, KtClass>()
|
||||
@@ -59,15 +61,23 @@ object CodeWriter {
|
||||
if (it.extension == "kt") {
|
||||
val ktFile = PsiManager.getInstance(project).findFile(it) as? KtFile?
|
||||
|
||||
ktFile?.declarations?.filterIsInstance<KtClass>()?.filter { clazz -> clazz.name != null }?.forEach { clazz ->
|
||||
val fqName = clazz.fqName!!.asString()
|
||||
val objModuleName = fqName.replace(clazz.name!!, "").substringBeforeLast(".")
|
||||
ktFile?.declarations
|
||||
?.filterIsInstance<KtClass>()
|
||||
?.filter { it.name != null }
|
||||
?.forEach { ktClass ->
|
||||
val fqName = ktClass.fqName!!.asString()
|
||||
val objModuleName = fqName
|
||||
.replace(ktClass.name!!, "")
|
||||
.substringBeforeLast(".")
|
||||
|
||||
/* We find one virtual file for each module. This is necessary to find the relative path for the generated GeneratedObjModuleFile.
|
||||
See [addGeneratedObjModuleFile] method */
|
||||
sourceFilePerObjModule[objModuleName] = it
|
||||
ktClasses[fqName] = clazz
|
||||
}
|
||||
/**
|
||||
* We find one virtual file for each module.
|
||||
* This is necessary to find the relative path for the generated GeneratedObjModuleFile.
|
||||
* See [addGeneratedObjModuleFile] method.
|
||||
*/
|
||||
sourceFilePerObjModule[objModuleName] = it
|
||||
ktClasses[fqName] = ktClass
|
||||
}
|
||||
}
|
||||
return@processFilesRecursively true
|
||||
}
|
||||
@@ -83,11 +93,12 @@ object CodeWriter {
|
||||
return
|
||||
}
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(project, Runnable {
|
||||
executeCommand(project, DevKitWorkspaceModelBundle.message("command.name.generate.code.for.workspace.entities.in", sourceFolder.name)) {
|
||||
val title = DevKitWorkspaceModelBundle.message("progress.title.generating.code")
|
||||
ApplicationManagerEx.getApplicationEx().runWriteActionWithCancellableProgressInDispatchThread(title, project, null) { indicator ->
|
||||
indicator.text = DevKitWorkspaceModelBundle.message("progress.text.collecting.classes.metadata")
|
||||
val objModules = loadObjModules(ktClasses, module, processAbstractTypes, isTestSourceFolder)
|
||||
val metaLoader: WorkspaceMetaModelProvider = service<WorkspaceMetaModelProvider>()
|
||||
val objModules = metaLoader.loadObjModules(ktClasses, module, processAbstractTypes, isTestSourceFolder)
|
||||
|
||||
val results = generate(codeGenerator, objModules, explicitApiEnabled, isTestModule)
|
||||
val generatedCode = results.flatMap { it.generatedCode }
|
||||
@@ -120,12 +131,6 @@ object CodeWriter {
|
||||
indicator.text = DevKitWorkspaceModelBundle.message("progress.text.writing.code")
|
||||
indicator.isIndeterminate = false
|
||||
|
||||
val settings = CodeStyle.getSettings(project)
|
||||
val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java)
|
||||
val oldValue = kotlinSettings.NAME_COUNT_TO_USE_STAR_IMPORT
|
||||
kotlinSettings.NAME_COUNT_TO_USE_STAR_IMPORT = Int.MAX_VALUE
|
||||
CodeStyleSettingsManager.getInstance(project).notifyCodeStyleSettingsChanged()
|
||||
|
||||
generatedCode.forEachIndexed { i, code ->
|
||||
val psiFactory = KtPsiFactory(project)
|
||||
indicator.fraction = 0.15 + 0.1 * i / generatedCode.size
|
||||
@@ -146,40 +151,47 @@ object CodeWriter {
|
||||
}
|
||||
}
|
||||
|
||||
indicator.text = DevKitWorkspaceModelBundle.message("progress.text.formatting.generated.code")
|
||||
importsByFile.forEach { (file, imports) ->
|
||||
addImports(file, imports.set)
|
||||
addImports(file, imports)
|
||||
}
|
||||
generatedFiles.withoutBigFiles().forEachIndexed { i, file ->
|
||||
indicator.fraction = 0.25 + 0.7 * i / generatedFiles.size
|
||||
CodeStyleManager.getInstance(project).reformat(file)
|
||||
}
|
||||
topLevelDeclarations.entrySet().forEach { (file, placeAndDeclarations) ->
|
||||
val addedElements = ArrayList<KtDeclaration>()
|
||||
for ((place, declarations) in placeAndDeclarations) {
|
||||
var nextPlace: PsiElement = place
|
||||
val newElements = ArrayList<KtDeclaration>()
|
||||
for (declaration in declarations) {
|
||||
val added = file.addAfter(declaration, nextPlace) as KtDeclaration
|
||||
newElements.add(added)
|
||||
nextPlace = added
|
||||
|
||||
CodeStyle.runWithLocalSettings(project, CodeStyle.getSettings(project)) { localSettings ->
|
||||
localSettings.setUpCodeStyle()
|
||||
generatedFiles.withoutBigFiles().forEachIndexed { i, file ->
|
||||
indicator.fraction = 0.25 + 0.7 * i / generatedFiles.size
|
||||
CodeStyleManager.getInstance(project).reformat(file)
|
||||
file.apiFileNameForImplFile?.let { ktClasses[it] }?.containingKtFile?.let { apiFile -> copyHeaderComment(apiFile, file) }
|
||||
}
|
||||
topLevelDeclarations.entrySet().forEach { (file, placeAndDeclarations) ->
|
||||
val addedElements = ArrayList<KtDeclaration>()
|
||||
for ((place, declarations) in placeAndDeclarations) {
|
||||
var nextPlace: PsiElement = place
|
||||
val newElements = ArrayList<KtDeclaration>()
|
||||
for (declaration in declarations) {
|
||||
val added = file.addAfter(declaration, nextPlace) as KtDeclaration
|
||||
newElements.add(added)
|
||||
nextPlace = added
|
||||
}
|
||||
addGeneratedRegionStartComment(file, newElements.first())
|
||||
addGeneratedRegionEndComment(file, newElements.last())
|
||||
addedElements.addAll(newElements)
|
||||
}
|
||||
addGeneratedRegionStartComment(file, newElements.first())
|
||||
addGeneratedRegionEndComment(file, newElements.last())
|
||||
addedElements.addAll(newElements)
|
||||
}
|
||||
}
|
||||
|
||||
val filesWithGeneratedRegions = ktClasses.values.groupBy { it.containingFile }.toList()
|
||||
filesWithGeneratedRegions.forEachIndexed { i, (file, classes) ->
|
||||
indicator.fraction = 0.95 + 0.05 * i / filesWithGeneratedRegions.size
|
||||
reformatCodeInGeneratedRegions(file, classes.mapNotNull { it.body?.node } + listOf(file.node))
|
||||
}
|
||||
val filesWithGeneratedRegions = ktClasses.values.groupBy { it.containingFile }.toList()
|
||||
filesWithGeneratedRegions.forEachIndexed { i, (file, classes) ->
|
||||
indicator.fraction = 0.95 + 0.05 * i / filesWithGeneratedRegions.size
|
||||
reformatCodeInGeneratedRegions(file, classes.mapNotNull { it.body?.node } + listOf(file.node))
|
||||
}
|
||||
|
||||
kotlinSettings.NAME_COUNT_TO_USE_STAR_IMPORT = oldValue
|
||||
CodeStyleSettingsManager.getInstance(project).notifyCodeStyleSettingsChanged()
|
||||
}
|
||||
}
|
||||
}, DevKitWorkspaceModelBundle.message("command.name.generate.code.for.workspace.entities.in", sourceFolder.name), null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CodeStyleSettings.setUpCodeStyle() {
|
||||
val kotlinCustomSettings = this.kotlinCustomSettings
|
||||
kotlinCustomSettings.NAME_COUNT_TO_USE_STAR_IMPORT = Int.MAX_VALUE
|
||||
}
|
||||
|
||||
// Documentation for IndexNotReadyException says that it's enough to run completeJustSubmittedTasks only once
|
||||
@@ -205,7 +217,8 @@ object CodeWriter {
|
||||
|
||||
val message = if (apiVersionFromDownloadedJar == CodegenApiVersion.UNKNOWN_VERSION || apiVersionInDevkit > apiVersionFromDownloadedJar) {
|
||||
DevKitWorkspaceModelBundle.message("notification.workspace.incompatible.codegen.api.versions.content.newer", apiVersionInDevkit, apiVersionFromDownloadedJar)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
DevKitWorkspaceModelBundle.message("notification.workspace.incompatible.codegen.api.versions.content.older", apiVersionInDevkit, apiVersionFromDownloadedJar)
|
||||
}
|
||||
|
||||
@@ -248,7 +261,8 @@ object CodeWriter {
|
||||
val apiVersion: String?
|
||||
try {
|
||||
apiVersion = readApiVersionFromFile(fileAbsolutePath)
|
||||
} catch (e: IOException) {
|
||||
}
|
||||
catch (e: IOException) {
|
||||
LOG.info("Failed to read codegen-api version from file \"$fileAbsolutePath\": " + e.message)
|
||||
return CodegenApiVersion.UNKNOWN_VERSION
|
||||
}
|
||||
@@ -256,18 +270,10 @@ object CodeWriter {
|
||||
return apiVersion ?: CodegenApiVersion.UNKNOWN_VERSION
|
||||
}
|
||||
|
||||
private fun loadObjModules(ktClasses: HashMap<String, KtClass>, module: Module, processAbstractTypes: Boolean, isTestSourceFolder: Boolean): List<CompiledObjModule> {
|
||||
val packages = ktClasses.values.mapTo(LinkedHashSet()) { it.containingKtFile.packageFqName.asString() }
|
||||
|
||||
val metaModelProvider: WorkspaceMetaModelProvider = WorkspaceMetaModelProviderImpl(
|
||||
processAbstractTypes = processAbstractTypes,
|
||||
module.project
|
||||
)
|
||||
return packages.filter { it != "" }.map { metaModelProvider.getObjModule(it, module, isTestSourceFolder) }
|
||||
}
|
||||
|
||||
private fun generate(codeGenerator: CodeGenerator, objModules: List<CompiledObjModule>,
|
||||
explicitApiEnabled: Boolean, isTestModule: Boolean): List<GenerationResult> {
|
||||
private fun generate(
|
||||
codeGenerator: CodeGenerator, objModules: List<CompiledObjModule>,
|
||||
explicitApiEnabled: Boolean, isTestModule: Boolean,
|
||||
): List<GenerationResult> {
|
||||
val generatorSettings = GeneratorSettings(explicitApiEnabled = explicitApiEnabled, testModeEnabled = isTestModule)
|
||||
val entitiesImplementations = objModules.map { codeGenerator.generateEntitiesImplementation(it, generatorSettings) }
|
||||
val metadataStorageImplementation = codeGenerator.generateMetadataStoragesImplementation(objModules, generatorSettings)
|
||||
@@ -303,10 +309,12 @@ object CodeWriter {
|
||||
filesToRemove.forEach { it.delete(CodeWriter) }
|
||||
}
|
||||
|
||||
private fun addGeneratedObjModuleFile(code: ObjModuleFileGeneratedCode, generatedFiles: MutableList<KtFile>,
|
||||
project: Project, sourceFolder: VirtualFile, genFolder: VirtualFile,
|
||||
sourceFilePerObjModule: Map<String, VirtualFile>,
|
||||
importsByFile: MutableMap<KtFile, Imports>, psiFactory: KtPsiFactory) {
|
||||
private fun addGeneratedObjModuleFile(
|
||||
code: ObjModuleFileGeneratedCode, generatedFiles: MutableList<KtFile>,
|
||||
project: Project, sourceFolder: VirtualFile, genFolder: VirtualFile,
|
||||
sourceFilePerObjModule: Map<String, VirtualFile>,
|
||||
importsByFile: MutableMap<KtFile, Imports>, psiFactory: KtPsiFactory,
|
||||
) {
|
||||
val packageFqnName = code.objModuleName
|
||||
|
||||
val sourceFile = sourceFilePerObjModule[packageFqnName]!!
|
||||
@@ -323,10 +331,12 @@ object CodeWriter {
|
||||
importsByFile[addedFile] = implImports
|
||||
}
|
||||
|
||||
private fun addGeneratedObjClassFile(code: ObjClassGeneratedCode, generatedFiles: MutableList<KtFile>,
|
||||
project: Project, sourceFolder: VirtualFile, genFolder: VirtualFile,
|
||||
ktClasses: Map<String, KtClass>, importsByFile: MutableMap<KtFile, Imports>,
|
||||
topLevelDeclarations: MultiMap<KtFile, Pair<KtClass, List<KtDeclaration>>>, psiFactory: KtPsiFactory) {
|
||||
private fun addGeneratedObjClassFile(
|
||||
code: ObjClassGeneratedCode, generatedFiles: MutableList<KtFile>,
|
||||
project: Project, sourceFolder: VirtualFile, genFolder: VirtualFile,
|
||||
ktClasses: Map<String, KtClass>, importsByFile: MutableMap<KtFile, Imports>,
|
||||
topLevelDeclarations: MultiMap<KtFile, Pair<KtClass, List<KtDeclaration>>>, psiFactory: KtPsiFactory,
|
||||
) {
|
||||
|
||||
if (code.target.name in SKIPPED_TYPES) return
|
||||
|
||||
@@ -349,7 +359,6 @@ object CodeWriter {
|
||||
val implPackageFqnName = "${apiFile.packageFqName.asString()}.impl"
|
||||
val implImports = Imports(implPackageFqnName)
|
||||
val implFile = psiFactory.createFile("${code.target.name}Impl.kt", implImports.findAndRemoveFqns(implementationClassText))
|
||||
copyHeaderComment(apiFile, implFile)
|
||||
apiClass.containingKtFile.importDirectives.mapNotNull { it.importPath }.forEach { import ->
|
||||
implImports.add(import.pathStr)
|
||||
}
|
||||
@@ -381,21 +390,20 @@ object CodeWriter {
|
||||
}
|
||||
}
|
||||
|
||||
private fun addImports(file: KtFile, imports: Collection<String>) {
|
||||
private fun addImports(file: KtFile, imports: Imports) {
|
||||
val psiFactory = KtPsiFactory(file.project)
|
||||
val importList = file.importList ?: error("no imports in ${file.name}")
|
||||
val existingImports = importList.imports.mapNotNullTo(HashSet()) { it.importedFqName?.asString() }
|
||||
imports.sorted().filterNot { it in existingImports }.forEach { imported ->
|
||||
val place = importList.imports.find { imported < (it.importedFqName?.asString() ?: "") }
|
||||
val importDirective = psiFactory.createImportDirective(ImportPath.fromString(imported))
|
||||
if (place != null) {
|
||||
val added = importList.addBefore(importDirective, place)
|
||||
importList.addAfter(psiFactory.createNewLine(), added)
|
||||
}
|
||||
else {
|
||||
val added = importList.add(importDirective)
|
||||
importList.addBefore(psiFactory.createNewLine(), added)
|
||||
}
|
||||
importList.imports.asSequence().mapNotNull { it.importPath?.pathStr }.forEach { imports.add(it) }
|
||||
if (importList.children.isNotEmpty()) {
|
||||
importList.deleteChildRange(importList.firstChild, importList.lastChild)
|
||||
}
|
||||
imports.imports.sorted().forEach {
|
||||
val importDirective = psiFactory.createImportDirective(ImportPath.fromString(it))
|
||||
importList.add(importDirective)
|
||||
importList.add(psiFactory.createNewLine())
|
||||
}
|
||||
if (imports.isNotEmpty()) {
|
||||
importList.lastChild.delete()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,13 +462,19 @@ object CodeWriter {
|
||||
if (child.isGeneratedRegionStart) {
|
||||
regionStart = if (child.treePrev?.elementType == KtTokens.WHITE_SPACE) child.treePrev else child
|
||||
}
|
||||
else if (regionStart != null && child.isGeneratedRegionEnd) {
|
||||
generatedRegions.add(regionStart!! to child)
|
||||
else if (child.isGeneratedRegionEnd) {
|
||||
regionStart?.let { generatedRegions.add(it to child) }
|
||||
}
|
||||
}
|
||||
return generatedRegions
|
||||
}
|
||||
|
||||
private val KtFile.apiFileNameForImplFile: String?
|
||||
get() {
|
||||
val packageName = packageFqName.asString()
|
||||
if (!packageName.endsWith(".impl") || !name.endsWith("Impl.kt")) return null
|
||||
return "${packageFqName.asString().dropLast(4)}${name.dropLast(7)}"
|
||||
}
|
||||
|
||||
private const val GENERATED_REGION_START = "//region generated code"
|
||||
|
||||
@@ -492,9 +506,8 @@ object CodeWriter {
|
||||
const val UNKNOWN_VERSION = "unknown version"
|
||||
}
|
||||
|
||||
//Function was added because CodeStyleManager throws an exception for big MetadataStorageImpl files
|
||||
// This function was added because CodeStyleManager throws an exception for big MetadataStorageImpl files
|
||||
private fun Iterable<KtFile>.withoutBigFiles(): Iterable<KtFile> {
|
||||
return filterNot { it.name == GENERATED_METADATA_STORAGE_FILE }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,13 @@ private val packagesImportedByDefault = setOf(
|
||||
)
|
||||
|
||||
class Imports(private val scopeFqn: String?) {
|
||||
val set = mutableSetOf<String>()
|
||||
fun isNotEmpty(): Boolean = set.isNotEmpty() || wildcardImports.isNotEmpty()
|
||||
|
||||
val imports: Set<String>
|
||||
get() = set + wildcardImports.map { "$it.*" }
|
||||
|
||||
private val set = mutableSetOf<String>()
|
||||
private val wildcardImports = mutableSetOf<String>()
|
||||
|
||||
fun findAndRemoveFqns(str: String): String {
|
||||
val res = StringBuilder()
|
||||
@@ -43,11 +49,28 @@ class Imports(private val scopeFqn: String?) {
|
||||
}
|
||||
|
||||
fun add(import: String) {
|
||||
set.add(import)
|
||||
val importSegments = import.split('.')
|
||||
if (importSegments.size < 2) set.add(import)
|
||||
else {
|
||||
val (packageName, name) = import
|
||||
.split('.')
|
||||
.let {
|
||||
it.dropLast(1).joinToString(".") to it.last()
|
||||
}
|
||||
add(packageName, name)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.packageRegex() = Regex("^${replace(".", "\\.")}\\.[^.]*$")
|
||||
|
||||
private fun add(packageName: String, name: String) {
|
||||
if (packageName != scopeFqn && packageName !in packagesImportedByDefault) {
|
||||
if (packageName == scopeFqn || packageName in packagesImportedByDefault || packageName in wildcardImports) {
|
||||
return
|
||||
} else if (name == "*") {
|
||||
val packageRegex = packageName.packageRegex()
|
||||
set.removeIf { it.matches(packageRegex) }
|
||||
wildcardImports.add(packageName)
|
||||
} else {
|
||||
set.add("$packageName.$name")
|
||||
}
|
||||
}
|
||||
|
||||
+5
-8
@@ -7,7 +7,7 @@ import com.intellij.analysis.problemsView.ProblemsCollector
|
||||
import com.intellij.analysis.problemsView.ProblemsProvider
|
||||
import com.intellij.analysis.problemsView.toolWindow.ProblemsViewToolWindowUtils.selectProjectErrorsTab
|
||||
import com.intellij.codeHighlighting.HighlightDisplayLevel
|
||||
import com.intellij.devkit.workspaceModel.metaModel.ObjMetaElementWithSource
|
||||
import com.intellij.devkit.workspaceModel.metaModel.ObjMetaElementWithPsi
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
@@ -18,7 +18,6 @@ import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.util.startOffset
|
||||
import com.intellij.workspaceModel.codegen.engine.GenerationProblem
|
||||
import com.intellij.workspaceModel.codegen.engine.ProblemLocation
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import javax.swing.Icon
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
@@ -49,11 +48,10 @@ class WorkspaceCodegenProblemsProvider(override val project: Project): ProblemsP
|
||||
}
|
||||
|
||||
private fun GenerationProblem.toProblem(): WorkspaceModelCodeGenerationProblem {
|
||||
val sourceElement = when (val problemLocation = location) {
|
||||
is ProblemLocation.Class -> (problemLocation.objClass as ObjMetaElementWithSource).sourceElement
|
||||
is ProblemLocation.Property -> (problemLocation.property as ObjMetaElementWithSource).sourceElement
|
||||
}
|
||||
val psiElement = sourceElement.getPsi() ?: return WorkspaceModelCodeGenerationProblem(this)
|
||||
val psiElement = when (val problemLocation = location) {
|
||||
is ProblemLocation.Class -> (problemLocation.objClass as ObjMetaElementWithPsi).sourcePsi
|
||||
is ProblemLocation.Property -> (problemLocation.property as ObjMetaElementWithPsi).sourcePsi
|
||||
} ?: return WorkspaceModelCodeGenerationProblem(this)
|
||||
val psiToHighlight = (psiElement as? PsiNameIdentifierOwner)?.nameIdentifier ?: psiElement
|
||||
val file = psiToHighlight.containingFile.virtualFile
|
||||
val document = FileDocumentManager.getInstance().getDocument(file) ?: return WorkspaceModelCodeGenerationProblem(this)
|
||||
@@ -84,4 +82,3 @@ class WorkspaceCodegenProblemsProvider(override val project: Project): ProblemsP
|
||||
override val column: Int
|
||||
) : WorkspaceModelCodeGenerationProblem(originalProblem), FileProblem
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// 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.devkit.workspaceModel.metaModel
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.ValueType
|
||||
|
||||
class IncorrectObjInterfaceException(errorMessage: String) : RuntimeException(errorMessage)
|
||||
|
||||
interface ObjMetaElementWithPsi {
|
||||
val sourcePsi: PsiElement?
|
||||
}
|
||||
|
||||
fun unsupportedType(type: String?): ValueType<*> {
|
||||
throw IncorrectObjInterfaceException("Unsupported type '$type'")
|
||||
}
|
||||
+8
-9
@@ -1,16 +1,15 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.metaModel
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.CompiledObjModule
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
|
||||
interface WorkspaceMetaModelProvider {
|
||||
fun getObjModule(packageName: String, module: Module, isTestSourceFolder: Boolean): CompiledObjModule
|
||||
fun loadObjModules(
|
||||
ktClasses: HashMap<String, KtClass>,
|
||||
module: Module,
|
||||
processAbstractTypes: Boolean,
|
||||
isTestSourceFolder: Boolean,
|
||||
): List<CompiledObjModule>
|
||||
}
|
||||
|
||||
class IncorrectObjInterfaceException(errorMessage: String): RuntimeException(errorMessage)
|
||||
|
||||
interface ObjMetaElementWithSource {
|
||||
val sourceElement: SourceElement
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.metaModel
|
||||
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
import com.intellij.platform.workspace.storage.annotations.Abstract
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.annotations.Default
|
||||
import com.intellij.platform.workspace.storage.annotations.Open
|
||||
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
enum class WorkspaceModelDefaults(val fqName: FqName, val classId: ClassId) {
|
||||
DEFAULT_ANNOTATION(FqName(Default::class.qualifiedName!!), ClassId.topLevel(FqName(Default::class.qualifiedName!!))),
|
||||
OPEN_ANNOTATION(FqName(Open::class.qualifiedName!!), ClassId.topLevel(FqName(Open::class.qualifiedName!!))),
|
||||
ABSTRACT_ANNOTATION(FqName(Abstract::class.qualifiedName!!), ClassId.topLevel(FqName(Abstract::class.qualifiedName!!))),
|
||||
CHILD_ANNOTATION(FqName(Child::class.qualifiedName!!), ClassId.topLevel(FqName(Child::class.qualifiedName!!))),
|
||||
EQUALS_BY_ANNOTATION(FqName(EqualsBy::class.qualifiedName!!), ClassId.topLevel(FqName(EqualsBy::class.qualifiedName!!))),
|
||||
|
||||
LIST_INTERFACE(StandardNames.FqNames.list, StandardClassIds.List),
|
||||
SET_INTERFACE(StandardNames.FqNames.set, StandardClassIds.Set),
|
||||
MAP_INTERFACE(StandardNames.FqNames.map, StandardClassIds.Map),
|
||||
|
||||
WORKSPACE_ENTITY(FqName(WorkspaceEntity::class.qualifiedName!!), ClassId.topLevel(FqName(WorkspaceEntity::class.qualifiedName!!))),
|
||||
ENTITY_SOURCE(FqName(EntitySource::class.qualifiedName!!), ClassId.topLevel(FqName(EntitySource::class.qualifiedName!!))),
|
||||
VIRTUAL_FILE_URL(FqName(VirtualFileUrl::class.qualifiedName!!), ClassId.topLevel(FqName(VirtualFileUrl::class.qualifiedName!!))),
|
||||
SYMBOLIC_ENTITY_ID(FqName(SymbolicEntityId::class.qualifiedName!!), ClassId.topLevel(FqName(SymbolicEntityId::class.qualifiedName!!))),
|
||||
ENTITY_POINTER(FqName(EntityPointer::class.qualifiedName!!), ClassId.topLevel(FqName(EntityPointer::class.qualifiedName!!)))
|
||||
;
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.metaModel.impl
|
||||
|
||||
import com.intellij.devkit.workspaceModel.metaModel.ObjMetaElementWithSource
|
||||
import com.intellij.devkit.workspaceModel.metaModel.ObjMetaElementWithPsi
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.*
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
|
||||
private val fieldObjType = ObjTypeImpl<ObjProperty<*, *>>()
|
||||
|
||||
@@ -15,8 +15,8 @@ sealed class ObjPropertyBase<T : Obj, V>(
|
||||
override val open: Boolean,
|
||||
override val mutable: Boolean,
|
||||
override val content: Boolean,
|
||||
override val sourceElement: SourceElement
|
||||
) : ObjProperty<T, V>, ObjMetaElementWithSource {
|
||||
override val sourcePsi: PsiElement?
|
||||
) : ObjProperty<T, V>, ObjMetaElementWithPsi {
|
||||
private val mutableOverrides: MutableList<ObjProperty<T, V>> = ArrayList()
|
||||
private val mutableOverriddenBy: MutableList<ObjProperty<T, V>> = ArrayList()
|
||||
|
||||
@@ -39,8 +39,8 @@ class OwnPropertyImpl<T : Obj, V>(
|
||||
override val constructorParameter: Boolean,
|
||||
override val classLocalId: Int,
|
||||
override val isKey: Boolean,
|
||||
sourceElement: SourceElement
|
||||
) : ObjPropertyBase<T, V>(receiver, name, valueType, valueKind, open, mutable, content, sourceElement), OwnProperty<T, V> {
|
||||
sourcePsi: PsiElement?
|
||||
) : ObjPropertyBase<T, V>(receiver, name, valueType, valueKind, open, mutable, content, sourcePsi), OwnProperty<T, V> {
|
||||
|
||||
override fun toString(): String = "$name (${receiver.name})"
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class ExtPropertyImpl<T : Obj, V>(
|
||||
override val module: ObjModule,
|
||||
override val moduleLocalId: Int,
|
||||
override val annotations: List<ObjAnnotation>,
|
||||
sourceElement: SourceElement,
|
||||
) : ObjPropertyBase<T, V>(receiver, name, valueType, valueKind, open, mutable, content, sourceElement), ExtProperty<T, V> {
|
||||
sourcePsi: PsiElement?
|
||||
) : ObjPropertyBase<T, V>(receiver, name, valueType, valueKind, open, mutable, content, sourcePsi), ExtProperty<T, V> {
|
||||
override fun toString(): String = "$name (${receiver.name})"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.devkit.workspaceModel.metaModel.impl
|
||||
|
||||
import com.intellij.devkit.workspaceModel.metaModel.ObjMetaElementWithSource
|
||||
import com.intellij.devkit.workspaceModel.metaModel.ObjMetaElementWithPsi
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.workspaceModel.codegen.deft.meta.*
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
|
||||
object ObjTypeType : ObjType<ObjType<*>> {
|
||||
override val classifier: ObjType<ObjType<*>>
|
||||
@@ -27,9 +27,9 @@ class ObjClassImpl<T : Obj>(
|
||||
override val module: ObjModule,
|
||||
override val name: String,
|
||||
override val openness: ObjClass.Openness,
|
||||
override val sourceElement: SourceElement,
|
||||
override val sourcePsi: PsiElement?,
|
||||
override val annotations: List<ObjAnnotation>
|
||||
) : ObjClass<T>, ObjTypeImpl<T>(), ObjMetaElementWithSource {
|
||||
) : ObjClass<T>, ObjTypeImpl<T>(), ObjMetaElementWithPsi {
|
||||
override var parentField: OwnProperty<T, *>? = null
|
||||
override var nameField: OwnProperty<T, *>? = null
|
||||
private val mutableFields: MutableList<OwnProperty<T, *>> = ArrayList()
|
||||
@@ -69,4 +69,4 @@ class ObjClassImpl<T : Obj>(
|
||||
|
||||
class ObjAnnotationImpl(override val fqName: String, override val pathSegments: List<String>) : ObjAnnotation {
|
||||
override fun toString(): String = fqName
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" packagePrefix="com.intellij.devkit.workspaceModel" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
@@ -14,8 +14,7 @@
|
||||
<orderEntry type="module" module-name="intellij.devkit.workspaceModel" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.test-framework" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.formatter" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.tests-common" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.plugin.k1" scope="TEST" />
|
||||
<orderEntry type="module" module-name="kotlin.base.plugin" scope="TEST" />
|
||||
<orderEntry type="library" scope="TEST" name="kotlinc.kotlin-compiler-common" level="project" />
|
||||
<orderEntry type="module" module-name="kotlin.base.test" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.devkit" scope="RUNTIME" />
|
||||
@@ -29,5 +28,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.testFramework.junit5" scope="TEST" />
|
||||
<orderEntry type="library" scope="TEST" name="kotlinx-serialization-core" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="kotlinx-serialization-json" level="project" />
|
||||
<orderEntry type="module" module-name="kotlin.tests-common" />
|
||||
</component>
|
||||
</module>
|
||||
+1
-1
@@ -4,8 +4,8 @@ import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.EntityType
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.annotations.Default
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.annotations.Default
|
||||
|
||||
interface DefaultFieldEntity : WorkspaceEntity {
|
||||
val version: Int
|
||||
|
||||
+4
-4
@@ -18,8 +18,8 @@ internal object MetadataStorageImpl: MetadataStorageBase() {
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.DefaultFieldEntity", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.DefaultFieldEntityData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "version", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "data", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.TestData", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "description", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf())), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "data", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.TestData", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "description", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf())), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "anotherVersion", valueType = primitiveTypeIntNotNullable, withDefault = true),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "description", valueType = primitiveTypeStringNotNullable, withDefault = true)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
@@ -27,8 +27,8 @@ OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name =
|
||||
}
|
||||
|
||||
override fun initializeMetadataHash() {
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.DefaultFieldEntity", metadataHash = 124467804)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.TestData", metadataHash = 589453437)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.DefaultFieldEntity", metadataHash = -1646169674)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.TestData", metadataHash = -898117917)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.EntityType
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
|
||||
interface ChildrenCollectionFieldEntity : WorkspaceEntity {
|
||||
val name: String
|
||||
val childrenEntitiesCollection: List<@Child SimpleEntity>
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
interface Builder : WorkspaceEntity.Builder<ChildrenCollectionFieldEntity> {
|
||||
override var entitySource: EntitySource
|
||||
var name: String
|
||||
var childrenEntitiesCollection: List<SimpleEntity.Builder>
|
||||
}
|
||||
|
||||
companion object : EntityType<ChildrenCollectionFieldEntity, Builder>() {
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
@JvmName("create")
|
||||
operator fun invoke(
|
||||
name: String,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder.() -> Unit)? = null,
|
||||
): Builder {
|
||||
val builder = builder()
|
||||
builder.name = name
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
//region generated code
|
||||
fun MutableEntityStorage.modifyChildrenCollectionFieldEntity(
|
||||
entity: ChildrenCollectionFieldEntity,
|
||||
modification: ChildrenCollectionFieldEntity.Builder.() -> Unit,
|
||||
): ChildrenCollectionFieldEntity {
|
||||
return modifyEntity(ChildrenCollectionFieldEntity.Builder::class.java, entity, modification)
|
||||
}
|
||||
//endregion
|
||||
|
||||
interface SimpleEntity : WorkspaceEntity {
|
||||
val version: Int
|
||||
val name: String
|
||||
val isSimple: Boolean
|
||||
val parent: ChildrenCollectionFieldEntity
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
interface Builder : WorkspaceEntity.Builder<SimpleEntity> {
|
||||
override var entitySource: EntitySource
|
||||
var version: Int
|
||||
var name: String
|
||||
var isSimple: Boolean
|
||||
var parent: ChildrenCollectionFieldEntity.Builder
|
||||
}
|
||||
|
||||
companion object : EntityType<SimpleEntity, Builder>() {
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
@JvmName("create")
|
||||
operator fun invoke(
|
||||
version: Int,
|
||||
name: String,
|
||||
isSimple: Boolean,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder.() -> Unit)? = null,
|
||||
): Builder {
|
||||
val builder = builder()
|
||||
builder.version = version
|
||||
builder.name = name
|
||||
builder.isSimple = isSimple
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
//region generated code
|
||||
fun MutableEntityStorage.modifySimpleEntity(
|
||||
entity: SimpleEntity,
|
||||
modification: SimpleEntity.Builder.() -> Unit,
|
||||
): SimpleEntity {
|
||||
return modifyEntity(SimpleEntity.Builder::class.java, entity, modification)
|
||||
}
|
||||
//endregion
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.ConnectionId
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeImplVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityInternalApi
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.impl.EntityLink
|
||||
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.platform.workspace.storage.impl.extractOneToManyChildren
|
||||
import com.intellij.platform.workspace.storage.impl.updateOneToManyChildrenOfParent
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
|
||||
import com.intellij.platform.workspace.storage.instrumentation.MutableEntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.workspaceModel.test.api.ChildrenCollectionFieldEntity
|
||||
import com.intellij.workspaceModel.test.api.SimpleEntity
|
||||
|
||||
@GeneratedCodeApiVersion(3)
|
||||
@GeneratedCodeImplVersion(6)
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class ChildrenCollectionFieldEntityImpl(private val dataSource: ChildrenCollectionFieldEntityData) : ChildrenCollectionFieldEntity,
|
||||
WorkspaceEntityBase(
|
||||
dataSource
|
||||
) {
|
||||
|
||||
private companion object {
|
||||
internal val CHILDRENENTITIESCOLLECTION_CONNECTION_ID: ConnectionId = ConnectionId.create(
|
||||
ChildrenCollectionFieldEntity::class.java, SimpleEntity::class.java, ConnectionId.ConnectionType.ONE_TO_MANY, false
|
||||
)
|
||||
|
||||
private val connections = listOf<ConnectionId>(
|
||||
CHILDRENENTITIESCOLLECTION_CONNECTION_ID,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override val name: String
|
||||
get() {
|
||||
readField("name")
|
||||
return dataSource.name
|
||||
}
|
||||
|
||||
override val childrenEntitiesCollection: List<SimpleEntity>
|
||||
get() = snapshot.extractOneToManyChildren<SimpleEntity>(CHILDRENENTITIESCOLLECTION_CONNECTION_ID, this)!!.toList()
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() {
|
||||
readField("entitySource")
|
||||
return dataSource.entitySource
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
|
||||
internal class Builder(result: ChildrenCollectionFieldEntityData?) :
|
||||
ModifiableWorkspaceEntityBase<ChildrenCollectionFieldEntity, ChildrenCollectionFieldEntityData>(result),
|
||||
ChildrenCollectionFieldEntity.Builder {
|
||||
internal constructor() : this(ChildrenCollectionFieldEntityData())
|
||||
|
||||
override fun applyToBuilder(builder: MutableEntityStorage) {
|
||||
if (this.diff != null) {
|
||||
if (existsInBuilder(builder)) {
|
||||
this.diff = builder
|
||||
return
|
||||
}
|
||||
else {
|
||||
error("Entity ChildrenCollectionFieldEntity is already created in a different builder")
|
||||
}
|
||||
}
|
||||
|
||||
this.diff = builder
|
||||
addToBuilder()
|
||||
this.id = getEntityData().createEntityId()
|
||||
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
|
||||
// Builder may switch to snapshot at any moment and lock entity data to modification
|
||||
this.currentEntityData = null
|
||||
|
||||
// Process linked entities that are connected without a builder
|
||||
processLinkedEntities(builder)
|
||||
checkInitialization() // TODO uncomment and check failed tests
|
||||
}
|
||||
|
||||
private fun checkInitialization() {
|
||||
val _diff = diff
|
||||
if (!getEntityData().isEntitySourceInitialized()) {
|
||||
error("Field WorkspaceEntity#entitySource should be initialized")
|
||||
}
|
||||
if (!getEntityData().isNameInitialized()) {
|
||||
error("Field ChildrenCollectionFieldEntity#name should be initialized")
|
||||
}
|
||||
// Check initialization for list with ref type
|
||||
if (_diff != null) {
|
||||
if (_diff.extractOneToManyChildren<WorkspaceEntityBase>(CHILDRENENTITIESCOLLECTION_CONNECTION_ID, this) == null) {
|
||||
error("Field ChildrenCollectionFieldEntity#childrenEntitiesCollection should be initialized")
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.entityLinks[EntityLink(true, CHILDRENENTITIESCOLLECTION_CONNECTION_ID)] == null) {
|
||||
error("Field ChildrenCollectionFieldEntity#childrenEntitiesCollection should be initialized")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
// Relabeling code, move information from dataSource to this builder
|
||||
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
|
||||
dataSource as ChildrenCollectionFieldEntity
|
||||
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
|
||||
if (this.name != dataSource.name) this.name = dataSource.name
|
||||
updateChildToParentReferences(parents)
|
||||
}
|
||||
|
||||
|
||||
override var entitySource: EntitySource
|
||||
get() = getEntityData().entitySource
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).entitySource = value
|
||||
changedProperty.add("entitySource")
|
||||
|
||||
}
|
||||
|
||||
override var name: String
|
||||
get() = getEntityData().name
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).name = value
|
||||
changedProperty.add("name")
|
||||
}
|
||||
|
||||
// List of non-abstract referenced types
|
||||
var _childrenEntitiesCollection: List<SimpleEntity>? = emptyList()
|
||||
override var childrenEntitiesCollection: List<SimpleEntity.Builder>
|
||||
get() {
|
||||
// Getter of the list of non-abstract referenced types
|
||||
val _diff = diff
|
||||
return if (_diff != null) {
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
((_diff as MutableEntityStorageInstrumentation).getManyChildrenBuilders(CHILDRENENTITIESCOLLECTION_CONNECTION_ID, this)!!
|
||||
.toList() as List<SimpleEntity.Builder>) +
|
||||
(this.entityLinks[EntityLink(true, CHILDRENENTITIESCOLLECTION_CONNECTION_ID)] as? List<SimpleEntity.Builder> ?: emptyList())
|
||||
}
|
||||
else {
|
||||
this.entityLinks[EntityLink(true, CHILDRENENTITIESCOLLECTION_CONNECTION_ID)] as? List<SimpleEntity.Builder> ?: emptyList()
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
// Setter of the list of non-abstract referenced types
|
||||
checkModificationAllowed()
|
||||
val _diff = diff
|
||||
if (_diff != null) {
|
||||
for (item_value in value) {
|
||||
if (item_value is ModifiableWorkspaceEntityBase<*, *> && (item_value as? ModifiableWorkspaceEntityBase<*, *>)?.diff == null) {
|
||||
// Backref setup before adding to store
|
||||
if (item_value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
item_value.entityLinks[EntityLink(false, CHILDRENENTITIESCOLLECTION_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
|
||||
_diff.addEntity(item_value as ModifiableWorkspaceEntityBase<WorkspaceEntity, *>)
|
||||
}
|
||||
}
|
||||
_diff.updateOneToManyChildrenOfParent(CHILDRENENTITIESCOLLECTION_CONNECTION_ID, this, value)
|
||||
}
|
||||
else {
|
||||
for (item_value in value) {
|
||||
if (item_value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
item_value.entityLinks[EntityLink(false, CHILDRENENTITIESCOLLECTION_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
}
|
||||
|
||||
this.entityLinks[EntityLink(true, CHILDRENENTITIESCOLLECTION_CONNECTION_ID)] = value
|
||||
}
|
||||
changedProperty.add("childrenEntitiesCollection")
|
||||
}
|
||||
|
||||
override fun getEntityClass(): Class<ChildrenCollectionFieldEntity> = ChildrenCollectionFieldEntity::class.java
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class ChildrenCollectionFieldEntityData : WorkspaceEntityData<ChildrenCollectionFieldEntity>() {
|
||||
lateinit var name: String
|
||||
|
||||
internal fun isNameInitialized(): Boolean = ::name.isInitialized
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<ChildrenCollectionFieldEntity> {
|
||||
val modifiable = ChildrenCollectionFieldEntityImpl.Builder(null)
|
||||
modifiable.diff = diff
|
||||
modifiable.id = createEntityId()
|
||||
return modifiable
|
||||
}
|
||||
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
override fun createEntity(snapshot: EntityStorageInstrumentation): ChildrenCollectionFieldEntity {
|
||||
val entityId = createEntityId()
|
||||
return snapshot.initializeEntity(entityId) {
|
||||
val entity = ChildrenCollectionFieldEntityImpl(this)
|
||||
entity.snapshot = snapshot
|
||||
entity.id = entityId
|
||||
entity
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMetadata(): EntityMetadata {
|
||||
return MetadataStorageImpl.getMetadataByTypeFqn("com.intellij.workspaceModel.test.api.ChildrenCollectionFieldEntity") as EntityMetadata
|
||||
}
|
||||
|
||||
override fun getEntityInterface(): Class<out WorkspaceEntity> {
|
||||
return ChildrenCollectionFieldEntity::class.java
|
||||
}
|
||||
|
||||
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
|
||||
return ChildrenCollectionFieldEntity(name, entitySource) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
|
||||
val res = mutableListOf<Class<out WorkspaceEntity>>()
|
||||
return res
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as ChildrenCollectionFieldEntityData
|
||||
|
||||
if (this.entitySource != other.entitySource) return false
|
||||
if (this.name != other.name) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as ChildrenCollectionFieldEntityData
|
||||
|
||||
if (this.name != other.name) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = entitySource.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun hashCodeIgnoringEntitySource(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.ConnectionId
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityInternalApi
|
||||
import com.intellij.platform.workspace.storage.metadata.impl.MetadataStorageBase
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.FinalClassMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.OwnPropertyMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.StorageTypeMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.ValueTypeMetadata
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal object MetadataStorageImpl: MetadataStorageBase() {
|
||||
override fun initializeMetadata() {
|
||||
val primitiveTypeStringNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "String")
|
||||
val primitiveTypeIntNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Int")
|
||||
val primitiveTypeBooleanNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Boolean")
|
||||
|
||||
var typeMetadata: StorageTypeMetadata
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.ChildrenCollectionFieldEntity", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.ChildrenCollectionFieldEntityData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "childrenEntitiesCollection", valueType = ValueTypeMetadata.EntityReference(connectionType = ConnectionId.ConnectionType.ONE_TO_MANY, entityFqName = "com.intellij.workspaceModel.test.api.SimpleEntity", isChild = true, isNullable = false), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleEntity", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.SimpleEntityData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "version", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "isSimple", valueType = primitiveTypeBooleanNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "parent", valueType = ValueTypeMetadata.EntityReference(connectionType = ConnectionId.ConnectionType.ONE_TO_MANY, entityFqName = "com.intellij.workspaceModel.test.api.ChildrenCollectionFieldEntity", isChild = false, isNullable = false), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
}
|
||||
|
||||
override fun initializeMetadataHash() {
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.ChildrenCollectionFieldEntity", metadataHash = -454547805)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SimpleEntity", metadataHash = -41718252)
|
||||
}
|
||||
|
||||
}
|
||||
+299
@@ -0,0 +1,299 @@
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.ConnectionId
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeImplVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityInternalApi
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.impl.EntityLink
|
||||
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.platform.workspace.storage.impl.extractOneToManyParent
|
||||
import com.intellij.platform.workspace.storage.impl.updateOneToManyParentOfChild
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
|
||||
import com.intellij.platform.workspace.storage.instrumentation.MutableEntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.workspaceModel.test.api.ChildrenCollectionFieldEntity
|
||||
import com.intellij.workspaceModel.test.api.SimpleEntity
|
||||
|
||||
@GeneratedCodeApiVersion(3)
|
||||
@GeneratedCodeImplVersion(6)
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class SimpleEntityImpl(private val dataSource: SimpleEntityData) : SimpleEntity, WorkspaceEntityBase(dataSource) {
|
||||
|
||||
private companion object {
|
||||
internal val PARENT_CONNECTION_ID: ConnectionId = ConnectionId.create(
|
||||
ChildrenCollectionFieldEntity::class.java, SimpleEntity::class.java, ConnectionId.ConnectionType.ONE_TO_MANY, false
|
||||
)
|
||||
|
||||
private val connections = listOf<ConnectionId>(
|
||||
PARENT_CONNECTION_ID,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override val version: Int
|
||||
get() {
|
||||
readField("version")
|
||||
return dataSource.version
|
||||
}
|
||||
override val name: String
|
||||
get() {
|
||||
readField("name")
|
||||
return dataSource.name
|
||||
}
|
||||
|
||||
override val isSimple: Boolean
|
||||
get() {
|
||||
readField("isSimple")
|
||||
return dataSource.isSimple
|
||||
}
|
||||
override val parent: ChildrenCollectionFieldEntity
|
||||
get() = snapshot.extractOneToManyParent(PARENT_CONNECTION_ID, this)!!
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() {
|
||||
readField("entitySource")
|
||||
return dataSource.entitySource
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
|
||||
internal class Builder(result: SimpleEntityData?) : ModifiableWorkspaceEntityBase<SimpleEntity, SimpleEntityData>(result),
|
||||
SimpleEntity.Builder {
|
||||
internal constructor() : this(SimpleEntityData())
|
||||
|
||||
override fun applyToBuilder(builder: MutableEntityStorage) {
|
||||
if (this.diff != null) {
|
||||
if (existsInBuilder(builder)) {
|
||||
this.diff = builder
|
||||
return
|
||||
}
|
||||
else {
|
||||
error("Entity SimpleEntity is already created in a different builder")
|
||||
}
|
||||
}
|
||||
|
||||
this.diff = builder
|
||||
addToBuilder()
|
||||
this.id = getEntityData().createEntityId()
|
||||
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
|
||||
// Builder may switch to snapshot at any moment and lock entity data to modification
|
||||
this.currentEntityData = null
|
||||
|
||||
// Process linked entities that are connected without a builder
|
||||
processLinkedEntities(builder)
|
||||
checkInitialization() // TODO uncomment and check failed tests
|
||||
}
|
||||
|
||||
private fun checkInitialization() {
|
||||
val _diff = diff
|
||||
if (!getEntityData().isEntitySourceInitialized()) {
|
||||
error("Field WorkspaceEntity#entitySource should be initialized")
|
||||
}
|
||||
if (!getEntityData().isNameInitialized()) {
|
||||
error("Field SimpleEntity#name should be initialized")
|
||||
}
|
||||
if (_diff != null) {
|
||||
if (_diff.extractOneToManyParent<WorkspaceEntityBase>(PARENT_CONNECTION_ID, this) == null) {
|
||||
error("Field SimpleEntity#parent should be initialized")
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)] == null) {
|
||||
error("Field SimpleEntity#parent should be initialized")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
// Relabeling code, move information from dataSource to this builder
|
||||
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
|
||||
dataSource as SimpleEntity
|
||||
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
|
||||
if (this.version != dataSource.version) this.version = dataSource.version
|
||||
if (this.name != dataSource.name) this.name = dataSource.name
|
||||
if (this.isSimple != dataSource.isSimple) this.isSimple = dataSource.isSimple
|
||||
updateChildToParentReferences(parents)
|
||||
}
|
||||
|
||||
|
||||
override var entitySource: EntitySource
|
||||
get() = getEntityData().entitySource
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).entitySource = value
|
||||
changedProperty.add("entitySource")
|
||||
|
||||
}
|
||||
|
||||
override var version: Int
|
||||
get() = getEntityData().version
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).version = value
|
||||
changedProperty.add("version")
|
||||
}
|
||||
|
||||
override var name: String
|
||||
get() = getEntityData().name
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).name = value
|
||||
changedProperty.add("name")
|
||||
}
|
||||
|
||||
override var isSimple: Boolean
|
||||
get() = getEntityData().isSimple
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).isSimple = value
|
||||
changedProperty.add("isSimple")
|
||||
}
|
||||
|
||||
override var parent: ChildrenCollectionFieldEntity.Builder
|
||||
get() {
|
||||
val _diff = diff
|
||||
return if (_diff != null) {
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
((_diff as MutableEntityStorageInstrumentation).getParentBuilder(
|
||||
PARENT_CONNECTION_ID, this
|
||||
) as? ChildrenCollectionFieldEntity.Builder)
|
||||
?: (this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)]!! as ChildrenCollectionFieldEntity.Builder)
|
||||
}
|
||||
else {
|
||||
this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)]!! as ChildrenCollectionFieldEntity.Builder
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
val _diff = diff
|
||||
if (_diff != null && value is ModifiableWorkspaceEntityBase<*, *> && value.diff == null) {
|
||||
// Setting backref of the list
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
val data = (value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] as? List<Any> ?: emptyList()) + this
|
||||
value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] = data
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
_diff.addEntity(value as ModifiableWorkspaceEntityBase<WorkspaceEntity, *>)
|
||||
}
|
||||
if (_diff != null && (value !is ModifiableWorkspaceEntityBase<*, *> || value.diff != null)) {
|
||||
_diff.updateOneToManyParentOfChild(PARENT_CONNECTION_ID, this, value)
|
||||
}
|
||||
else {
|
||||
// Setting backref of the list
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
val data = (value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] as? List<Any> ?: emptyList()) + this
|
||||
value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] = data
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
|
||||
this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)] = value
|
||||
}
|
||||
changedProperty.add("parent")
|
||||
}
|
||||
|
||||
override fun getEntityClass(): Class<SimpleEntity> = SimpleEntity::class.java
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class SimpleEntityData : WorkspaceEntityData<SimpleEntity>() {
|
||||
var version: Int = 0
|
||||
lateinit var name: String
|
||||
var isSimple: Boolean = false
|
||||
|
||||
|
||||
internal fun isNameInitialized(): Boolean = ::name.isInitialized
|
||||
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<SimpleEntity> {
|
||||
val modifiable = SimpleEntityImpl.Builder(null)
|
||||
modifiable.diff = diff
|
||||
modifiable.id = createEntityId()
|
||||
return modifiable
|
||||
}
|
||||
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
override fun createEntity(snapshot: EntityStorageInstrumentation): SimpleEntity {
|
||||
val entityId = createEntityId()
|
||||
return snapshot.initializeEntity(entityId) {
|
||||
val entity = SimpleEntityImpl(this)
|
||||
entity.snapshot = snapshot
|
||||
entity.id = entityId
|
||||
entity
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMetadata(): EntityMetadata {
|
||||
return MetadataStorageImpl.getMetadataByTypeFqn("com.intellij.workspaceModel.test.api.SimpleEntity") as EntityMetadata
|
||||
}
|
||||
|
||||
override fun getEntityInterface(): Class<out WorkspaceEntity> {
|
||||
return SimpleEntity::class.java
|
||||
}
|
||||
|
||||
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
|
||||
return SimpleEntity(version, name, isSimple, entitySource) {
|
||||
parents.filterIsInstance<ChildrenCollectionFieldEntity.Builder>().singleOrNull()?.let { this.parent = it }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
|
||||
val res = mutableListOf<Class<out WorkspaceEntity>>()
|
||||
res.add(ChildrenCollectionFieldEntity::class.java)
|
||||
return res
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as SimpleEntityData
|
||||
|
||||
if (this.entitySource != other.entitySource) return false
|
||||
if (this.version != other.version) return false
|
||||
if (this.name != other.name) return false
|
||||
if (this.isSimple != other.isSimple) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as SimpleEntityData
|
||||
|
||||
if (this.version != other.version) return false
|
||||
if (this.name != other.name) return false
|
||||
if (this.isSimple != other.isSimple) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = entitySource.hashCode()
|
||||
result = 31 * result + version.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + isSimple.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun hashCodeIgnoringEntitySource(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + version.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + isSimple.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
|
||||
interface ChildrenCollectionFieldEntity : WorkspaceEntity {
|
||||
val name: String
|
||||
val childrenEntitiesCollection: List<@Child SimpleEntity>
|
||||
}
|
||||
|
||||
interface SimpleEntity : WorkspaceEntity {
|
||||
val version: Int
|
||||
val name: String
|
||||
val isSimple: Boolean
|
||||
val parent: ChildrenCollectionFieldEntity
|
||||
}
|
||||
+4
@@ -11,6 +11,7 @@ import com.intellij.platform.workspace.storage.impl.containers.toMutableWorkspac
|
||||
interface CollectionFieldEntity : WorkspaceEntity {
|
||||
val versions: Set<Int>
|
||||
val names: List<String>
|
||||
val manifestAttributes: Map<String, String>
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
@@ -18,6 +19,7 @@ interface CollectionFieldEntity : WorkspaceEntity {
|
||||
override var entitySource: EntitySource
|
||||
var versions: MutableSet<Int>
|
||||
var names: MutableList<String>
|
||||
var manifestAttributes: Map<String, String>
|
||||
}
|
||||
|
||||
companion object : EntityType<CollectionFieldEntity, Builder>() {
|
||||
@@ -27,12 +29,14 @@ interface CollectionFieldEntity : WorkspaceEntity {
|
||||
operator fun invoke(
|
||||
versions: Set<Int>,
|
||||
names: List<String>,
|
||||
manifestAttributes: Map<String, String>,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder.() -> Unit)? = null,
|
||||
): Builder {
|
||||
val builder = builder()
|
||||
builder.versions = versions.toMutableWorkspaceSet()
|
||||
builder.names = names.toMutableWorkspaceList()
|
||||
builder.manifestAttributes = manifestAttributes
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
|
||||
+25
-1
@@ -45,6 +45,12 @@ internal class CollectionFieldEntityImpl(private val dataSource: CollectionField
|
||||
return dataSource.names
|
||||
}
|
||||
|
||||
override val manifestAttributes: Map<String, String>
|
||||
get() {
|
||||
readField("manifestAttributes")
|
||||
return dataSource.manifestAttributes
|
||||
}
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() {
|
||||
readField("entitySource")
|
||||
@@ -94,6 +100,9 @@ internal class CollectionFieldEntityImpl(private val dataSource: CollectionField
|
||||
if (!getEntityData().isNamesInitialized()) {
|
||||
error("Field CollectionFieldEntity#names should be initialized")
|
||||
}
|
||||
if (!getEntityData().isManifestAttributesInitialized()) {
|
||||
error("Field CollectionFieldEntity#manifestAttributes should be initialized")
|
||||
}
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
@@ -117,6 +126,7 @@ internal class CollectionFieldEntityImpl(private val dataSource: CollectionField
|
||||
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
|
||||
if (this.versions != dataSource.versions) this.versions = dataSource.versions.toMutableSet()
|
||||
if (this.names != dataSource.names) this.names = dataSource.names.toMutableList()
|
||||
if (this.manifestAttributes != dataSource.manifestAttributes) this.manifestAttributes = dataSource.manifestAttributes.toMutableMap()
|
||||
updateChildToParentReferences(parents)
|
||||
}
|
||||
|
||||
@@ -174,6 +184,14 @@ internal class CollectionFieldEntityImpl(private val dataSource: CollectionField
|
||||
namesUpdater.invoke(value)
|
||||
}
|
||||
|
||||
override var manifestAttributes: Map<String, String>
|
||||
get() = getEntityData().manifestAttributes
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).manifestAttributes = value
|
||||
changedProperty.add("manifestAttributes")
|
||||
}
|
||||
|
||||
override fun getEntityClass(): Class<CollectionFieldEntity> = CollectionFieldEntity::class.java
|
||||
}
|
||||
}
|
||||
@@ -182,9 +200,11 @@ internal class CollectionFieldEntityImpl(private val dataSource: CollectionField
|
||||
internal class CollectionFieldEntityData : WorkspaceEntityData<CollectionFieldEntity>() {
|
||||
lateinit var versions: MutableSet<Int>
|
||||
lateinit var names: MutableList<String>
|
||||
lateinit var manifestAttributes: Map<String, String>
|
||||
|
||||
internal fun isVersionsInitialized(): Boolean = ::versions.isInitialized
|
||||
internal fun isNamesInitialized(): Boolean = ::names.isInitialized
|
||||
internal fun isManifestAttributesInitialized(): Boolean = ::manifestAttributes.isInitialized
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<CollectionFieldEntity> {
|
||||
val modifiable = CollectionFieldEntityImpl.Builder(null)
|
||||
@@ -221,7 +241,7 @@ internal class CollectionFieldEntityData : WorkspaceEntityData<CollectionFieldEn
|
||||
}
|
||||
|
||||
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
|
||||
return CollectionFieldEntity(versions, names, entitySource) {
|
||||
return CollectionFieldEntity(versions, names, manifestAttributes, entitySource) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,6 +259,7 @@ internal class CollectionFieldEntityData : WorkspaceEntityData<CollectionFieldEn
|
||||
if (this.entitySource != other.entitySource) return false
|
||||
if (this.versions != other.versions) return false
|
||||
if (this.names != other.names) return false
|
||||
if (this.manifestAttributes != other.manifestAttributes) return false
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -250,6 +271,7 @@ internal class CollectionFieldEntityData : WorkspaceEntityData<CollectionFieldEn
|
||||
|
||||
if (this.versions != other.versions) return false
|
||||
if (this.names != other.names) return false
|
||||
if (this.manifestAttributes != other.manifestAttributes) return false
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -257,6 +279,7 @@ internal class CollectionFieldEntityData : WorkspaceEntityData<CollectionFieldEn
|
||||
var result = entitySource.hashCode()
|
||||
result = 31 * result + versions.hashCode()
|
||||
result = 31 * result + names.hashCode()
|
||||
result = 31 * result + manifestAttributes.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -264,6 +287,7 @@ internal class CollectionFieldEntityData : WorkspaceEntityData<CollectionFieldEn
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + versions.hashCode()
|
||||
result = 31 * result + names.hashCode()
|
||||
result = 31 * result + manifestAttributes.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -15,18 +15,21 @@ internal object MetadataStorageImpl: MetadataStorageBase() {
|
||||
val primitiveTypeSetNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Set")
|
||||
val primitiveTypeStringNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "String")
|
||||
val primitiveTypeListNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "List")
|
||||
val primitiveTypeMapNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Map")
|
||||
|
||||
var typeMetadata: StorageTypeMetadata
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.CollectionFieldEntity", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.CollectionFieldEntityData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "versions", valueType = ValueTypeMetadata.ParameterizedType(generics = listOf(primitiveTypeIntNotNullable), primitive = primitiveTypeSetNotNullable), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "names", valueType = ValueTypeMetadata.ParameterizedType(generics = listOf(primitiveTypeStringNotNullable), primitive = primitiveTypeListNotNullable), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "names", valueType = ValueTypeMetadata.ParameterizedType(generics = listOf(primitiveTypeStringNotNullable), primitive = primitiveTypeListNotNullable), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "manifestAttributes", valueType = ValueTypeMetadata.ParameterizedType(generics = listOf(primitiveTypeStringNotNullable,
|
||||
primitiveTypeStringNotNullable), primitive = primitiveTypeMapNotNullable), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
}
|
||||
|
||||
override fun initializeMetadataHash() {
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.CollectionFieldEntity", metadataHash = 1735861848)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.CollectionFieldEntity", metadataHash = 1555273165)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -5,4 +5,5 @@ import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
interface CollectionFieldEntity : WorkspaceEntity {
|
||||
val versions: Set<Int>
|
||||
val names: List<String>
|
||||
}
|
||||
val manifestAttributes: Map<String, String>
|
||||
}
|
||||
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.EntityType
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
|
||||
interface EntityWithChildren : WorkspaceEntity {
|
||||
val name: String
|
||||
val propertyChild: @Child ChildEntityType1?
|
||||
@Child val typeChild: ChildEntityType2?
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
interface Builder : WorkspaceEntity.Builder<EntityWithChildren> {
|
||||
override var entitySource: EntitySource
|
||||
var name: String
|
||||
var propertyChild: ChildEntityType1.Builder?
|
||||
var typeChild: ChildEntityType2.Builder?
|
||||
}
|
||||
|
||||
companion object : EntityType<EntityWithChildren, Builder>() {
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
@JvmName("create")
|
||||
operator fun invoke(
|
||||
name: String,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder.() -> Unit)? = null,
|
||||
): Builder {
|
||||
val builder = builder()
|
||||
builder.name = name
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
//region generated code
|
||||
fun MutableEntityStorage.modifyEntityWithChildren(
|
||||
entity: EntityWithChildren,
|
||||
modification: EntityWithChildren.Builder.() -> Unit,
|
||||
): EntityWithChildren {
|
||||
return modifyEntity(EntityWithChildren.Builder::class.java, entity, modification)
|
||||
}
|
||||
//endregion
|
||||
|
||||
interface ChildEntityType1 : WorkspaceEntity {
|
||||
val version: Int
|
||||
val parent: EntityWithChildren
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
interface Builder : WorkspaceEntity.Builder<ChildEntityType1> {
|
||||
override var entitySource: EntitySource
|
||||
var version: Int
|
||||
var parent: EntityWithChildren.Builder
|
||||
}
|
||||
|
||||
companion object : EntityType<ChildEntityType1, Builder>() {
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
@JvmName("create")
|
||||
operator fun invoke(
|
||||
version: Int,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder.() -> Unit)? = null,
|
||||
): Builder {
|
||||
val builder = builder()
|
||||
builder.version = version
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
//region generated code
|
||||
fun MutableEntityStorage.modifyChildEntityType1(
|
||||
entity: ChildEntityType1,
|
||||
modification: ChildEntityType1.Builder.() -> Unit,
|
||||
): ChildEntityType1 {
|
||||
return modifyEntity(ChildEntityType1.Builder::class.java, entity, modification)
|
||||
}
|
||||
//endregion
|
||||
|
||||
interface ChildEntityType2 : WorkspaceEntity {
|
||||
val version: Int
|
||||
val parent: EntityWithChildren
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
interface Builder : WorkspaceEntity.Builder<ChildEntityType2> {
|
||||
override var entitySource: EntitySource
|
||||
var version: Int
|
||||
var parent: EntityWithChildren.Builder
|
||||
}
|
||||
|
||||
companion object : EntityType<ChildEntityType2, Builder>() {
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
@JvmName("create")
|
||||
operator fun invoke(
|
||||
version: Int,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder.() -> Unit)? = null,
|
||||
): Builder {
|
||||
val builder = builder()
|
||||
builder.version = version
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
//region generated code
|
||||
fun MutableEntityStorage.modifyChildEntityType2(
|
||||
entity: ChildEntityType2,
|
||||
modification: ChildEntityType2.Builder.() -> Unit,
|
||||
): ChildEntityType2 {
|
||||
return modifyEntity(ChildEntityType2.Builder::class.java, entity, modification)
|
||||
}
|
||||
//endregion
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.ConnectionId
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeImplVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityInternalApi
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.impl.EntityLink
|
||||
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.platform.workspace.storage.impl.extractOneToOneParent
|
||||
import com.intellij.platform.workspace.storage.impl.updateOneToOneParentOfChild
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
|
||||
import com.intellij.platform.workspace.storage.instrumentation.MutableEntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.workspaceModel.test.api.ChildEntityType1
|
||||
import com.intellij.workspaceModel.test.api.EntityWithChildren
|
||||
|
||||
@GeneratedCodeApiVersion(3)
|
||||
@GeneratedCodeImplVersion(6)
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class ChildEntityType1Impl(private val dataSource: ChildEntityType1Data) : ChildEntityType1, WorkspaceEntityBase(dataSource) {
|
||||
|
||||
private companion object {
|
||||
internal val PARENT_CONNECTION_ID: ConnectionId =
|
||||
ConnectionId.create(EntityWithChildren::class.java, ChildEntityType1::class.java, ConnectionId.ConnectionType.ONE_TO_ONE, false)
|
||||
|
||||
private val connections = listOf<ConnectionId>(
|
||||
PARENT_CONNECTION_ID,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override val version: Int
|
||||
get() {
|
||||
readField("version")
|
||||
return dataSource.version
|
||||
}
|
||||
override val parent: EntityWithChildren
|
||||
get() = snapshot.extractOneToOneParent(PARENT_CONNECTION_ID, this)!!
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() {
|
||||
readField("entitySource")
|
||||
return dataSource.entitySource
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
|
||||
internal class Builder(result: ChildEntityType1Data?) : ModifiableWorkspaceEntityBase<ChildEntityType1, ChildEntityType1Data>(result),
|
||||
ChildEntityType1.Builder {
|
||||
internal constructor() : this(ChildEntityType1Data())
|
||||
|
||||
override fun applyToBuilder(builder: MutableEntityStorage) {
|
||||
if (this.diff != null) {
|
||||
if (existsInBuilder(builder)) {
|
||||
this.diff = builder
|
||||
return
|
||||
}
|
||||
else {
|
||||
error("Entity ChildEntityType1 is already created in a different builder")
|
||||
}
|
||||
}
|
||||
|
||||
this.diff = builder
|
||||
addToBuilder()
|
||||
this.id = getEntityData().createEntityId()
|
||||
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
|
||||
// Builder may switch to snapshot at any moment and lock entity data to modification
|
||||
this.currentEntityData = null
|
||||
|
||||
// Process linked entities that are connected without a builder
|
||||
processLinkedEntities(builder)
|
||||
checkInitialization() // TODO uncomment and check failed tests
|
||||
}
|
||||
|
||||
private fun checkInitialization() {
|
||||
val _diff = diff
|
||||
if (!getEntityData().isEntitySourceInitialized()) {
|
||||
error("Field WorkspaceEntity#entitySource should be initialized")
|
||||
}
|
||||
if (_diff != null) {
|
||||
if (_diff.extractOneToOneParent<WorkspaceEntityBase>(PARENT_CONNECTION_ID, this) == null) {
|
||||
error("Field ChildEntityType1#parent should be initialized")
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)] == null) {
|
||||
error("Field ChildEntityType1#parent should be initialized")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
// Relabeling code, move information from dataSource to this builder
|
||||
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
|
||||
dataSource as ChildEntityType1
|
||||
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
|
||||
if (this.version != dataSource.version) this.version = dataSource.version
|
||||
updateChildToParentReferences(parents)
|
||||
}
|
||||
|
||||
|
||||
override var entitySource: EntitySource
|
||||
get() = getEntityData().entitySource
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).entitySource = value
|
||||
changedProperty.add("entitySource")
|
||||
|
||||
}
|
||||
|
||||
override var version: Int
|
||||
get() = getEntityData().version
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).version = value
|
||||
changedProperty.add("version")
|
||||
}
|
||||
|
||||
override var parent: EntityWithChildren.Builder
|
||||
get() {
|
||||
val _diff = diff
|
||||
return if (_diff != null) {
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
((_diff as MutableEntityStorageInstrumentation).getParentBuilder(PARENT_CONNECTION_ID, this) as? EntityWithChildren.Builder)
|
||||
?: (this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)]!! as EntityWithChildren.Builder)
|
||||
}
|
||||
else {
|
||||
this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)]!! as EntityWithChildren.Builder
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
val _diff = diff
|
||||
if (_diff != null && value is ModifiableWorkspaceEntityBase<*, *> && value.diff == null) {
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
_diff.addEntity(value as ModifiableWorkspaceEntityBase<WorkspaceEntity, *>)
|
||||
}
|
||||
if (_diff != null && (value !is ModifiableWorkspaceEntityBase<*, *> || value.diff != null)) {
|
||||
_diff.updateOneToOneParentOfChild(PARENT_CONNECTION_ID, this, value)
|
||||
}
|
||||
else {
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
|
||||
this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)] = value
|
||||
}
|
||||
changedProperty.add("parent")
|
||||
}
|
||||
|
||||
override fun getEntityClass(): Class<ChildEntityType1> = ChildEntityType1::class.java
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class ChildEntityType1Data : WorkspaceEntityData<ChildEntityType1>() {
|
||||
var version: Int = 0
|
||||
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<ChildEntityType1> {
|
||||
val modifiable = ChildEntityType1Impl.Builder(null)
|
||||
modifiable.diff = diff
|
||||
modifiable.id = createEntityId()
|
||||
return modifiable
|
||||
}
|
||||
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
override fun createEntity(snapshot: EntityStorageInstrumentation): ChildEntityType1 {
|
||||
val entityId = createEntityId()
|
||||
return snapshot.initializeEntity(entityId) {
|
||||
val entity = ChildEntityType1Impl(this)
|
||||
entity.snapshot = snapshot
|
||||
entity.id = entityId
|
||||
entity
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMetadata(): EntityMetadata {
|
||||
return MetadataStorageImpl.getMetadataByTypeFqn("com.intellij.workspaceModel.test.api.ChildEntityType1") as EntityMetadata
|
||||
}
|
||||
|
||||
override fun getEntityInterface(): Class<out WorkspaceEntity> {
|
||||
return ChildEntityType1::class.java
|
||||
}
|
||||
|
||||
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
|
||||
return ChildEntityType1(version, entitySource) {
|
||||
parents.filterIsInstance<EntityWithChildren.Builder>().singleOrNull()?.let { this.parent = it }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
|
||||
val res = mutableListOf<Class<out WorkspaceEntity>>()
|
||||
res.add(EntityWithChildren::class.java)
|
||||
return res
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as ChildEntityType1Data
|
||||
|
||||
if (this.entitySource != other.entitySource) return false
|
||||
if (this.version != other.version) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as ChildEntityType1Data
|
||||
|
||||
if (this.version != other.version) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = entitySource.hashCode()
|
||||
result = 31 * result + version.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun hashCodeIgnoringEntitySource(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + version.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.ConnectionId
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeImplVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityInternalApi
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.impl.EntityLink
|
||||
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.platform.workspace.storage.impl.extractOneToOneParent
|
||||
import com.intellij.platform.workspace.storage.impl.updateOneToOneParentOfChild
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
|
||||
import com.intellij.platform.workspace.storage.instrumentation.MutableEntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.workspaceModel.test.api.ChildEntityType2
|
||||
import com.intellij.workspaceModel.test.api.EntityWithChildren
|
||||
|
||||
@GeneratedCodeApiVersion(3)
|
||||
@GeneratedCodeImplVersion(6)
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class ChildEntityType2Impl(private val dataSource: ChildEntityType2Data) : ChildEntityType2, WorkspaceEntityBase(dataSource) {
|
||||
|
||||
private companion object {
|
||||
internal val PARENT_CONNECTION_ID: ConnectionId =
|
||||
ConnectionId.create(EntityWithChildren::class.java, ChildEntityType2::class.java, ConnectionId.ConnectionType.ONE_TO_ONE, false)
|
||||
|
||||
private val connections = listOf<ConnectionId>(
|
||||
PARENT_CONNECTION_ID,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override val version: Int
|
||||
get() {
|
||||
readField("version")
|
||||
return dataSource.version
|
||||
}
|
||||
override val parent: EntityWithChildren
|
||||
get() = snapshot.extractOneToOneParent(PARENT_CONNECTION_ID, this)!!
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() {
|
||||
readField("entitySource")
|
||||
return dataSource.entitySource
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
|
||||
internal class Builder(result: ChildEntityType2Data?) : ModifiableWorkspaceEntityBase<ChildEntityType2, ChildEntityType2Data>(result),
|
||||
ChildEntityType2.Builder {
|
||||
internal constructor() : this(ChildEntityType2Data())
|
||||
|
||||
override fun applyToBuilder(builder: MutableEntityStorage) {
|
||||
if (this.diff != null) {
|
||||
if (existsInBuilder(builder)) {
|
||||
this.diff = builder
|
||||
return
|
||||
}
|
||||
else {
|
||||
error("Entity ChildEntityType2 is already created in a different builder")
|
||||
}
|
||||
}
|
||||
|
||||
this.diff = builder
|
||||
addToBuilder()
|
||||
this.id = getEntityData().createEntityId()
|
||||
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
|
||||
// Builder may switch to snapshot at any moment and lock entity data to modification
|
||||
this.currentEntityData = null
|
||||
|
||||
// Process linked entities that are connected without a builder
|
||||
processLinkedEntities(builder)
|
||||
checkInitialization() // TODO uncomment and check failed tests
|
||||
}
|
||||
|
||||
private fun checkInitialization() {
|
||||
val _diff = diff
|
||||
if (!getEntityData().isEntitySourceInitialized()) {
|
||||
error("Field WorkspaceEntity#entitySource should be initialized")
|
||||
}
|
||||
if (_diff != null) {
|
||||
if (_diff.extractOneToOneParent<WorkspaceEntityBase>(PARENT_CONNECTION_ID, this) == null) {
|
||||
error("Field ChildEntityType2#parent should be initialized")
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)] == null) {
|
||||
error("Field ChildEntityType2#parent should be initialized")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
// Relabeling code, move information from dataSource to this builder
|
||||
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
|
||||
dataSource as ChildEntityType2
|
||||
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
|
||||
if (this.version != dataSource.version) this.version = dataSource.version
|
||||
updateChildToParentReferences(parents)
|
||||
}
|
||||
|
||||
|
||||
override var entitySource: EntitySource
|
||||
get() = getEntityData().entitySource
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).entitySource = value
|
||||
changedProperty.add("entitySource")
|
||||
|
||||
}
|
||||
|
||||
override var version: Int
|
||||
get() = getEntityData().version
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).version = value
|
||||
changedProperty.add("version")
|
||||
}
|
||||
|
||||
override var parent: EntityWithChildren.Builder
|
||||
get() {
|
||||
val _diff = diff
|
||||
return if (_diff != null) {
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
((_diff as MutableEntityStorageInstrumentation).getParentBuilder(PARENT_CONNECTION_ID, this) as? EntityWithChildren.Builder)
|
||||
?: (this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)]!! as EntityWithChildren.Builder)
|
||||
}
|
||||
else {
|
||||
this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)]!! as EntityWithChildren.Builder
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
val _diff = diff
|
||||
if (_diff != null && value is ModifiableWorkspaceEntityBase<*, *> && value.diff == null) {
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
_diff.addEntity(value as ModifiableWorkspaceEntityBase<WorkspaceEntity, *>)
|
||||
}
|
||||
if (_diff != null && (value !is ModifiableWorkspaceEntityBase<*, *> || value.diff != null)) {
|
||||
_diff.updateOneToOneParentOfChild(PARENT_CONNECTION_ID, this, value)
|
||||
}
|
||||
else {
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
|
||||
this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)] = value
|
||||
}
|
||||
changedProperty.add("parent")
|
||||
}
|
||||
|
||||
override fun getEntityClass(): Class<ChildEntityType2> = ChildEntityType2::class.java
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class ChildEntityType2Data : WorkspaceEntityData<ChildEntityType2>() {
|
||||
var version: Int = 0
|
||||
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<ChildEntityType2> {
|
||||
val modifiable = ChildEntityType2Impl.Builder(null)
|
||||
modifiable.diff = diff
|
||||
modifiable.id = createEntityId()
|
||||
return modifiable
|
||||
}
|
||||
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
override fun createEntity(snapshot: EntityStorageInstrumentation): ChildEntityType2 {
|
||||
val entityId = createEntityId()
|
||||
return snapshot.initializeEntity(entityId) {
|
||||
val entity = ChildEntityType2Impl(this)
|
||||
entity.snapshot = snapshot
|
||||
entity.id = entityId
|
||||
entity
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMetadata(): EntityMetadata {
|
||||
return MetadataStorageImpl.getMetadataByTypeFqn("com.intellij.workspaceModel.test.api.ChildEntityType2") as EntityMetadata
|
||||
}
|
||||
|
||||
override fun getEntityInterface(): Class<out WorkspaceEntity> {
|
||||
return ChildEntityType2::class.java
|
||||
}
|
||||
|
||||
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
|
||||
return ChildEntityType2(version, entitySource) {
|
||||
parents.filterIsInstance<EntityWithChildren.Builder>().singleOrNull()?.let { this.parent = it }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
|
||||
val res = mutableListOf<Class<out WorkspaceEntity>>()
|
||||
res.add(EntityWithChildren::class.java)
|
||||
return res
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as ChildEntityType2Data
|
||||
|
||||
if (this.entitySource != other.entitySource) return false
|
||||
if (this.version != other.version) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as ChildEntityType2Data
|
||||
|
||||
if (this.version != other.version) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = entitySource.hashCode()
|
||||
result = 31 * result + version.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun hashCodeIgnoringEntitySource(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + version.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
+286
@@ -0,0 +1,286 @@
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.ConnectionId
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeImplVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityInternalApi
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.impl.EntityLink
|
||||
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.platform.workspace.storage.impl.extractOneToOneChild
|
||||
import com.intellij.platform.workspace.storage.impl.updateOneToOneChildOfParent
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
|
||||
import com.intellij.platform.workspace.storage.instrumentation.MutableEntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.workspaceModel.test.api.ChildEntityType1
|
||||
import com.intellij.workspaceModel.test.api.ChildEntityType2
|
||||
import com.intellij.workspaceModel.test.api.EntityWithChildren
|
||||
|
||||
@GeneratedCodeApiVersion(3)
|
||||
@GeneratedCodeImplVersion(6)
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class EntityWithChildrenImpl(private val dataSource: EntityWithChildrenData) : EntityWithChildren,
|
||||
WorkspaceEntityBase(dataSource) {
|
||||
|
||||
private companion object {
|
||||
internal val PROPERTYCHILD_CONNECTION_ID: ConnectionId =
|
||||
ConnectionId.create(EntityWithChildren::class.java, ChildEntityType1::class.java, ConnectionId.ConnectionType.ONE_TO_ONE, false)
|
||||
internal val TYPECHILD_CONNECTION_ID: ConnectionId =
|
||||
ConnectionId.create(EntityWithChildren::class.java, ChildEntityType2::class.java, ConnectionId.ConnectionType.ONE_TO_ONE, false)
|
||||
|
||||
private val connections = listOf<ConnectionId>(
|
||||
PROPERTYCHILD_CONNECTION_ID,
|
||||
TYPECHILD_CONNECTION_ID,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override val name: String
|
||||
get() {
|
||||
readField("name")
|
||||
return dataSource.name
|
||||
}
|
||||
|
||||
override val propertyChild: ChildEntityType1?
|
||||
get() = snapshot.extractOneToOneChild(PROPERTYCHILD_CONNECTION_ID, this)
|
||||
|
||||
override val typeChild: ChildEntityType2?
|
||||
get() = snapshot.extractOneToOneChild(TYPECHILD_CONNECTION_ID, this)
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() {
|
||||
readField("entitySource")
|
||||
return dataSource.entitySource
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
|
||||
internal class Builder(result: EntityWithChildrenData?) :
|
||||
ModifiableWorkspaceEntityBase<EntityWithChildren, EntityWithChildrenData>(result), EntityWithChildren.Builder {
|
||||
internal constructor() : this(EntityWithChildrenData())
|
||||
|
||||
override fun applyToBuilder(builder: MutableEntityStorage) {
|
||||
if (this.diff != null) {
|
||||
if (existsInBuilder(builder)) {
|
||||
this.diff = builder
|
||||
return
|
||||
}
|
||||
else {
|
||||
error("Entity EntityWithChildren is already created in a different builder")
|
||||
}
|
||||
}
|
||||
|
||||
this.diff = builder
|
||||
addToBuilder()
|
||||
this.id = getEntityData().createEntityId()
|
||||
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
|
||||
// Builder may switch to snapshot at any moment and lock entity data to modification
|
||||
this.currentEntityData = null
|
||||
|
||||
// Process linked entities that are connected without a builder
|
||||
processLinkedEntities(builder)
|
||||
checkInitialization() // TODO uncomment and check failed tests
|
||||
}
|
||||
|
||||
private fun checkInitialization() {
|
||||
val _diff = diff
|
||||
if (!getEntityData().isEntitySourceInitialized()) {
|
||||
error("Field WorkspaceEntity#entitySource should be initialized")
|
||||
}
|
||||
if (!getEntityData().isNameInitialized()) {
|
||||
error("Field EntityWithChildren#name should be initialized")
|
||||
}
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
// Relabeling code, move information from dataSource to this builder
|
||||
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
|
||||
dataSource as EntityWithChildren
|
||||
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
|
||||
if (this.name != dataSource.name) this.name = dataSource.name
|
||||
updateChildToParentReferences(parents)
|
||||
}
|
||||
|
||||
|
||||
override var entitySource: EntitySource
|
||||
get() = getEntityData().entitySource
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).entitySource = value
|
||||
changedProperty.add("entitySource")
|
||||
|
||||
}
|
||||
|
||||
override var name: String
|
||||
get() = getEntityData().name
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).name = value
|
||||
changedProperty.add("name")
|
||||
}
|
||||
|
||||
override var propertyChild: ChildEntityType1.Builder?
|
||||
get() {
|
||||
val _diff = diff
|
||||
return if (_diff != null) {
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
((_diff as MutableEntityStorageInstrumentation).getOneChildBuilder(
|
||||
PROPERTYCHILD_CONNECTION_ID, this
|
||||
) as? ChildEntityType1.Builder)
|
||||
?: (this.entityLinks[EntityLink(true, PROPERTYCHILD_CONNECTION_ID)] as? ChildEntityType1.Builder)
|
||||
}
|
||||
else {
|
||||
this.entityLinks[EntityLink(true, PROPERTYCHILD_CONNECTION_ID)] as? ChildEntityType1.Builder
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
val _diff = diff
|
||||
if (_diff != null && value is ModifiableWorkspaceEntityBase<*, *> && value.diff == null) {
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
value.entityLinks[EntityLink(false, PROPERTYCHILD_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
_diff.addEntity(value as ModifiableWorkspaceEntityBase<WorkspaceEntity, *>)
|
||||
}
|
||||
if (_diff != null && (value !is ModifiableWorkspaceEntityBase<*, *> || value.diff != null)) {
|
||||
_diff.updateOneToOneChildOfParent(PROPERTYCHILD_CONNECTION_ID, this, value)
|
||||
}
|
||||
else {
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
value.entityLinks[EntityLink(false, PROPERTYCHILD_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
|
||||
this.entityLinks[EntityLink(true, PROPERTYCHILD_CONNECTION_ID)] = value
|
||||
}
|
||||
changedProperty.add("propertyChild")
|
||||
}
|
||||
|
||||
override var typeChild: ChildEntityType2.Builder?
|
||||
get() {
|
||||
val _diff = diff
|
||||
return if (_diff != null) {
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
((_diff as MutableEntityStorageInstrumentation).getOneChildBuilder(TYPECHILD_CONNECTION_ID, this) as? ChildEntityType2.Builder)
|
||||
?: (this.entityLinks[EntityLink(true, TYPECHILD_CONNECTION_ID)] as? ChildEntityType2.Builder)
|
||||
}
|
||||
else {
|
||||
this.entityLinks[EntityLink(true, TYPECHILD_CONNECTION_ID)] as? ChildEntityType2.Builder
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
val _diff = diff
|
||||
if (_diff != null && value is ModifiableWorkspaceEntityBase<*, *> && value.diff == null) {
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
value.entityLinks[EntityLink(false, TYPECHILD_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
_diff.addEntity(value as ModifiableWorkspaceEntityBase<WorkspaceEntity, *>)
|
||||
}
|
||||
if (_diff != null && (value !is ModifiableWorkspaceEntityBase<*, *> || value.diff != null)) {
|
||||
_diff.updateOneToOneChildOfParent(TYPECHILD_CONNECTION_ID, this, value)
|
||||
}
|
||||
else {
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
value.entityLinks[EntityLink(false, TYPECHILD_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
|
||||
this.entityLinks[EntityLink(true, TYPECHILD_CONNECTION_ID)] = value
|
||||
}
|
||||
changedProperty.add("typeChild")
|
||||
}
|
||||
|
||||
override fun getEntityClass(): Class<EntityWithChildren> = EntityWithChildren::class.java
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class EntityWithChildrenData : WorkspaceEntityData<EntityWithChildren>() {
|
||||
lateinit var name: String
|
||||
|
||||
internal fun isNameInitialized(): Boolean = ::name.isInitialized
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<EntityWithChildren> {
|
||||
val modifiable = EntityWithChildrenImpl.Builder(null)
|
||||
modifiable.diff = diff
|
||||
modifiable.id = createEntityId()
|
||||
return modifiable
|
||||
}
|
||||
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
override fun createEntity(snapshot: EntityStorageInstrumentation): EntityWithChildren {
|
||||
val entityId = createEntityId()
|
||||
return snapshot.initializeEntity(entityId) {
|
||||
val entity = EntityWithChildrenImpl(this)
|
||||
entity.snapshot = snapshot
|
||||
entity.id = entityId
|
||||
entity
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMetadata(): EntityMetadata {
|
||||
return MetadataStorageImpl.getMetadataByTypeFqn("com.intellij.workspaceModel.test.api.EntityWithChildren") as EntityMetadata
|
||||
}
|
||||
|
||||
override fun getEntityInterface(): Class<out WorkspaceEntity> {
|
||||
return EntityWithChildren::class.java
|
||||
}
|
||||
|
||||
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
|
||||
return EntityWithChildren(name, entitySource) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
|
||||
val res = mutableListOf<Class<out WorkspaceEntity>>()
|
||||
return res
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as EntityWithChildrenData
|
||||
|
||||
if (this.entitySource != other.entitySource) return false
|
||||
if (this.name != other.name) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as EntityWithChildrenData
|
||||
|
||||
if (this.name != other.name) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = entitySource.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun hashCodeIgnoringEntitySource(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.ConnectionId
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityInternalApi
|
||||
import com.intellij.platform.workspace.storage.metadata.impl.MetadataStorageBase
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.FinalClassMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.OwnPropertyMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.StorageTypeMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.ValueTypeMetadata
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal object MetadataStorageImpl: MetadataStorageBase() {
|
||||
override fun initializeMetadata() {
|
||||
val primitiveTypeIntNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Int")
|
||||
val primitiveTypeStringNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "String")
|
||||
|
||||
var typeMetadata: StorageTypeMetadata
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.ChildEntityType1", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.ChildEntityType1Data", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "version", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "parent", valueType = ValueTypeMetadata.EntityReference(connectionType = ConnectionId.ConnectionType.ONE_TO_ONE, entityFqName = "com.intellij.workspaceModel.test.api.EntityWithChildren", isChild = false, isNullable = false), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.ChildEntityType2", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.ChildEntityType2Data", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "version", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "parent", valueType = ValueTypeMetadata.EntityReference(connectionType = ConnectionId.ConnectionType.ONE_TO_ONE, entityFqName = "com.intellij.workspaceModel.test.api.EntityWithChildren", isChild = false, isNullable = false), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.EntityWithChildren", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.EntityWithChildrenData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "propertyChild", valueType = ValueTypeMetadata.EntityReference(connectionType = ConnectionId.ConnectionType.ONE_TO_ONE, entityFqName = "com.intellij.workspaceModel.test.api.ChildEntityType1", isChild = true, isNullable = true), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "typeChild", valueType = ValueTypeMetadata.EntityReference(connectionType = ConnectionId.ConnectionType.ONE_TO_ONE, entityFqName = "com.intellij.workspaceModel.test.api.ChildEntityType2", isChild = true, isNullable = true), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
}
|
||||
|
||||
override fun initializeMetadataHash() {
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.ChildEntityType1", metadataHash = 1430777503)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.ChildEntityType2", metadataHash = -1568141121)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.EntityWithChildren", metadataHash = 104242451)
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
|
||||
interface EntityWithChildren : WorkspaceEntity {
|
||||
val name: String
|
||||
val propertyChild: @Child ChildEntityType1?
|
||||
@Child val typeChild: ChildEntityType2?
|
||||
}
|
||||
|
||||
interface ChildEntityType1 : WorkspaceEntity {
|
||||
val version: Int
|
||||
val parent: EntityWithChildren
|
||||
}
|
||||
|
||||
interface ChildEntityType2 : WorkspaceEntity {
|
||||
val version: Int
|
||||
val parent: EntityWithChildren
|
||||
}
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.storage.EntityType
|
||||
import com.intellij.platform.workspace.storage.annotations.Default
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.EntityType
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.ModifiableWorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.annotations.Default
|
||||
|
||||
|
||||
interface FinalFieldsEntity : WorkspaceEntity {
|
||||
|
||||
+9
-9
@@ -11,27 +11,27 @@ import com.intellij.platform.workspace.storage.metadata.model.ValueTypeMetadata
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal object MetadataStorageImpl: MetadataStorageBase() {
|
||||
override fun initializeMetadata() {
|
||||
val primitiveTypeStringNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "String")
|
||||
val primitiveTypeIntNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Int")
|
||||
val primitiveTypeBooleanNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Boolean")
|
||||
val primitiveTypeStringNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = true, type = "String")
|
||||
val primitiveTypeStringNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "String")
|
||||
val primitiveTypeBooleanNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Boolean")
|
||||
val primitiveTypeIntNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Int")
|
||||
|
||||
var typeMetadata: StorageTypeMetadata
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.FinalFieldsEntity", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.FinalFieldsEntityData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "descriptor", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.AnotherDataClass", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "version", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "descriptor", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.AnotherDataClass", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "displayName", valueType = primitiveTypeStringNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "revision", valueType = primitiveTypeStringNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "source", valueType = primitiveTypeBooleanNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "displayName", valueType = primitiveTypeStringNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "url", valueType = primitiveTypeStringNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "revision", valueType = primitiveTypeStringNullable, withDefault = false)), supertypes = listOf())), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "version", valueType = primitiveTypeIntNotNullable, withDefault = false)), supertypes = listOf())), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
}
|
||||
|
||||
override fun initializeMetadataHash() {
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.FinalFieldsEntity", metadataHash = 1499543638)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.AnotherDataClass", metadataHash = -1492715258)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.FinalFieldsEntity", metadataHash = -241552936)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.AnotherDataClass", metadataHash = 1379646916)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
|
||||
import java.net.URL
|
||||
|
||||
interface EntityWithManyImports : WorkspaceEntityWithSymbolicId {
|
||||
val version: Int
|
||||
val name: String
|
||||
val files: List<@Child SimpleEntity>
|
||||
val pointer: EntityPointer<SimpleEntity>
|
||||
|
||||
override val symbolicId: SimpleId
|
||||
get() = SimpleId(name)
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
interface Builder : WorkspaceEntity.Builder<EntityWithManyImports> {
|
||||
override var entitySource: EntitySource
|
||||
var version: Int
|
||||
var name: String
|
||||
var files: List<SimpleEntity.Builder>
|
||||
var pointer: EntityPointer
|
||||
}
|
||||
|
||||
companion object : EntityType<EntityWithManyImports, Builder>() {
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
@JvmName("create")
|
||||
operator fun invoke(
|
||||
version: Int,
|
||||
name: String,
|
||||
pointer: EntityPointer,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder.() -> Unit)? = null,
|
||||
): Builder {
|
||||
val builder = builder()
|
||||
builder.version = version
|
||||
builder.name = name
|
||||
builder.pointer = pointer
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
//region generated code
|
||||
fun MutableEntityStorage.modifyEntityWithManyImports(
|
||||
entity: EntityWithManyImports,
|
||||
modification: EntityWithManyImports.Builder.() -> Unit,
|
||||
): EntityWithManyImports {
|
||||
return modifyEntity(EntityWithManyImports.Builder::class.java, entity, modification)
|
||||
}
|
||||
//endregion
|
||||
|
||||
data class SimpleId(val name: String) : SymbolicEntityId<EntityWithManyImports> {
|
||||
override val presentableName: String
|
||||
get() = name
|
||||
}
|
||||
|
||||
interface SimpleEntity : WorkspaceEntity {
|
||||
val url: VirtualFileUrl
|
||||
val parent: EntityWithManyImports
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
interface Builder : WorkspaceEntity.Builder<SimpleEntity> {
|
||||
override var entitySource: EntitySource
|
||||
var url: VirtualFileUrl
|
||||
var parent: EntityWithManyImports.Builder
|
||||
}
|
||||
|
||||
companion object : EntityType<SimpleEntity, Builder>() {
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
@JvmName("create")
|
||||
operator fun invoke(
|
||||
url: VirtualFileUrl,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder.() -> Unit)? = null,
|
||||
): Builder {
|
||||
val builder = builder()
|
||||
builder.url = url
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
//region generated code
|
||||
fun MutableEntityStorage.modifySimpleEntity(
|
||||
entity: SimpleEntity,
|
||||
modification: SimpleEntity.Builder.() -> Unit,
|
||||
): SimpleEntity {
|
||||
return modifyEntity(SimpleEntity.Builder::class.java, entity, modification)
|
||||
}
|
||||
//endregion
|
||||
|
||||
data class UnrelatedToEntities(val name: String, val data: EntityPointer<SimpleEntity>) {
|
||||
fun doSomething(src: EntitySource) {
|
||||
}
|
||||
}
|
||||
+308
@@ -0,0 +1,308 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.impl.EntityLink
|
||||
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.platform.workspace.storage.impl.extractOneToManyChildren
|
||||
import com.intellij.platform.workspace.storage.impl.updateOneToManyChildrenOfParent
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
|
||||
import com.intellij.platform.workspace.storage.instrumentation.MutableEntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
|
||||
import com.intellij.workspaceModel.test.api.EntityWithManyImports
|
||||
import com.intellij.workspaceModel.test.api.SimpleEntity
|
||||
import com.intellij.workspaceModel.test.api.SimpleId
|
||||
import java.net.URL
|
||||
|
||||
@GeneratedCodeApiVersion(3)
|
||||
@GeneratedCodeImplVersion(6)
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class EntityWithManyImportsImpl(private val dataSource: EntityWithManyImportsData) : EntityWithManyImports,
|
||||
WorkspaceEntityBase(dataSource) {
|
||||
|
||||
private companion object {
|
||||
internal val FILES_CONNECTION_ID: ConnectionId =
|
||||
ConnectionId.create(EntityWithManyImports::class.java, SimpleEntity::class.java, ConnectionId.ConnectionType.ONE_TO_MANY, false)
|
||||
|
||||
private val connections = listOf<ConnectionId>(
|
||||
FILES_CONNECTION_ID,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override val symbolicId: SimpleId = super.symbolicId
|
||||
|
||||
override val version: Int
|
||||
get() {
|
||||
readField("version")
|
||||
return dataSource.version
|
||||
}
|
||||
override val name: String
|
||||
get() {
|
||||
readField("name")
|
||||
return dataSource.name
|
||||
}
|
||||
|
||||
override val files: List<SimpleEntity>
|
||||
get() = snapshot.extractOneToManyChildren<SimpleEntity>(FILES_CONNECTION_ID, this)!!.toList()
|
||||
|
||||
override val pointer: EntityPointer
|
||||
get() {
|
||||
readField("pointer")
|
||||
return dataSource.pointer
|
||||
}
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() {
|
||||
readField("entitySource")
|
||||
return dataSource.entitySource
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
|
||||
internal class Builder(result: EntityWithManyImportsData?) :
|
||||
ModifiableWorkspaceEntityBase<EntityWithManyImports, EntityWithManyImportsData>(result), EntityWithManyImports.Builder {
|
||||
internal constructor() : this(EntityWithManyImportsData())
|
||||
|
||||
override fun applyToBuilder(builder: MutableEntityStorage) {
|
||||
if (this.diff != null) {
|
||||
if (existsInBuilder(builder)) {
|
||||
this.diff = builder
|
||||
return
|
||||
}
|
||||
else {
|
||||
error("Entity EntityWithManyImports is already created in a different builder")
|
||||
}
|
||||
}
|
||||
|
||||
this.diff = builder
|
||||
addToBuilder()
|
||||
this.id = getEntityData().createEntityId()
|
||||
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
|
||||
// Builder may switch to snapshot at any moment and lock entity data to modification
|
||||
this.currentEntityData = null
|
||||
|
||||
// Process linked entities that are connected without a builder
|
||||
processLinkedEntities(builder)
|
||||
checkInitialization() // TODO uncomment and check failed tests
|
||||
}
|
||||
|
||||
private fun checkInitialization() {
|
||||
val _diff = diff
|
||||
if (!getEntityData().isEntitySourceInitialized()) {
|
||||
error("Field WorkspaceEntity#entitySource should be initialized")
|
||||
}
|
||||
if (!getEntityData().isNameInitialized()) {
|
||||
error("Field EntityWithManyImports#name should be initialized")
|
||||
}
|
||||
// Check initialization for list with ref type
|
||||
if (_diff != null) {
|
||||
if (_diff.extractOneToManyChildren<WorkspaceEntityBase>(FILES_CONNECTION_ID, this) == null) {
|
||||
error("Field EntityWithManyImports#files should be initialized")
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.entityLinks[EntityLink(true, FILES_CONNECTION_ID)] == null) {
|
||||
error("Field EntityWithManyImports#files should be initialized")
|
||||
}
|
||||
}
|
||||
if (!getEntityData().isPointerInitialized()) {
|
||||
error("Field EntityWithManyImports#pointer should be initialized")
|
||||
}
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
// Relabeling code, move information from dataSource to this builder
|
||||
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
|
||||
dataSource as EntityWithManyImports
|
||||
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
|
||||
if (this.version != dataSource.version) this.version = dataSource.version
|
||||
if (this.name != dataSource.name) this.name = dataSource.name
|
||||
if (this.pointer != dataSource.pointer) this.pointer = dataSource.pointer
|
||||
updateChildToParentReferences(parents)
|
||||
}
|
||||
|
||||
|
||||
override var entitySource: EntitySource
|
||||
get() = getEntityData().entitySource
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).entitySource = value
|
||||
changedProperty.add("entitySource")
|
||||
|
||||
}
|
||||
|
||||
override var version: Int
|
||||
get() = getEntityData().version
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).version = value
|
||||
changedProperty.add("version")
|
||||
}
|
||||
|
||||
override var name: String
|
||||
get() = getEntityData().name
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).name = value
|
||||
changedProperty.add("name")
|
||||
}
|
||||
|
||||
// List of non-abstract referenced types
|
||||
var _files: List<SimpleEntity>? = emptyList()
|
||||
override var files: List<SimpleEntity.Builder>
|
||||
get() {
|
||||
// Getter of the list of non-abstract referenced types
|
||||
val _diff = diff
|
||||
return if (_diff != null) {
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
((_diff as MutableEntityStorageInstrumentation).getManyChildrenBuilders(FILES_CONNECTION_ID, this)!!
|
||||
.toList() as List<SimpleEntity.Builder>) +
|
||||
(this.entityLinks[EntityLink(true, FILES_CONNECTION_ID)] as? List<SimpleEntity.Builder> ?: emptyList())
|
||||
}
|
||||
else {
|
||||
this.entityLinks[EntityLink(true, FILES_CONNECTION_ID)] as? List<SimpleEntity.Builder> ?: emptyList()
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
// Setter of the list of non-abstract referenced types
|
||||
checkModificationAllowed()
|
||||
val _diff = diff
|
||||
if (_diff != null) {
|
||||
for (item_value in value) {
|
||||
if (item_value is ModifiableWorkspaceEntityBase<*, *> && (item_value as? ModifiableWorkspaceEntityBase<*, *>)?.diff == null) {
|
||||
// Backref setup before adding to store
|
||||
if (item_value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
item_value.entityLinks[EntityLink(false, FILES_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
|
||||
_diff.addEntity(item_value as ModifiableWorkspaceEntityBase<WorkspaceEntity, *>)
|
||||
}
|
||||
}
|
||||
_diff.updateOneToManyChildrenOfParent(FILES_CONNECTION_ID, this, value)
|
||||
}
|
||||
else {
|
||||
for (item_value in value) {
|
||||
if (item_value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
item_value.entityLinks[EntityLink(false, FILES_CONNECTION_ID)] = this
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
}
|
||||
|
||||
this.entityLinks[EntityLink(true, FILES_CONNECTION_ID)] = value
|
||||
}
|
||||
changedProperty.add("files")
|
||||
}
|
||||
|
||||
override var pointer: EntityPointer
|
||||
get() = getEntityData().pointer
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).pointer = value
|
||||
changedProperty.add("pointer")
|
||||
|
||||
}
|
||||
|
||||
override fun getEntityClass(): Class<EntityWithManyImports> = EntityWithManyImports::class.java
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class EntityWithManyImportsData : WorkspaceEntityData<EntityWithManyImports>() {
|
||||
var version: Int = 0
|
||||
lateinit var name: String
|
||||
lateinit var pointer: EntityPointer
|
||||
|
||||
|
||||
internal fun isNameInitialized(): Boolean = ::name.isInitialized
|
||||
internal fun isPointerInitialized(): Boolean = ::pointer.isInitialized
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<EntityWithManyImports> {
|
||||
val modifiable = EntityWithManyImportsImpl.Builder(null)
|
||||
modifiable.diff = diff
|
||||
modifiable.id = createEntityId()
|
||||
return modifiable
|
||||
}
|
||||
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
override fun createEntity(snapshot: EntityStorageInstrumentation): EntityWithManyImports {
|
||||
val entityId = createEntityId()
|
||||
return snapshot.initializeEntity(entityId) {
|
||||
val entity = EntityWithManyImportsImpl(this)
|
||||
entity.snapshot = snapshot
|
||||
entity.id = entityId
|
||||
entity
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMetadata(): EntityMetadata {
|
||||
return MetadataStorageImpl.getMetadataByTypeFqn("com.intellij.workspaceModel.test.api.EntityWithManyImports") as EntityMetadata
|
||||
}
|
||||
|
||||
override fun getEntityInterface(): Class<out WorkspaceEntity> {
|
||||
return EntityWithManyImports::class.java
|
||||
}
|
||||
|
||||
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
|
||||
return EntityWithManyImports(version, name, pointer, entitySource) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
|
||||
val res = mutableListOf<Class<out WorkspaceEntity>>()
|
||||
return res
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as EntityWithManyImportsData
|
||||
|
||||
if (this.entitySource != other.entitySource) return false
|
||||
if (this.version != other.version) return false
|
||||
if (this.name != other.name) return false
|
||||
if (this.pointer != other.pointer) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as EntityWithManyImportsData
|
||||
|
||||
if (this.version != other.version) return false
|
||||
if (this.name != other.name) return false
|
||||
if (this.pointer != other.pointer) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = entitySource.hashCode()
|
||||
result = 31 * result + version.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + pointer.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun hashCodeIgnoringEntitySource(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + version.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + pointer.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.ConnectionId
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityInternalApi
|
||||
import com.intellij.platform.workspace.storage.metadata.impl.MetadataStorageBase
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.FinalClassMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.OwnPropertyMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.StorageTypeMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.ValueTypeMetadata
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal object MetadataStorageImpl: MetadataStorageBase() {
|
||||
override fun initializeMetadata() {
|
||||
val primitiveTypeStringNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "String")
|
||||
val primitiveTypeIntNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Int")
|
||||
|
||||
var typeMetadata: StorageTypeMetadata
|
||||
|
||||
typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.SymbolicEntityId"))
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.EntityWithManyImports", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.EntityWithManyImportsData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity",
|
||||
"com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "version", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "files", valueType = ValueTypeMetadata.EntityReference(connectionType = ConnectionId.ConnectionType.ONE_TO_MANY, entityFqName = "com.intellij.workspaceModel.test.api.SimpleEntity", isChild = true, isNullable = false), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "pointer", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntityPointer")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = true, isKey = false, isOpen = false, name = "symbolicId", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.SymbolicEntityId"))), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleEntity", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.SimpleEntityData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "url", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.url.VirtualFileUrl")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "parent", valueType = ValueTypeMetadata.EntityReference(connectionType = ConnectionId.ConnectionType.ONE_TO_MANY, entityFqName = "com.intellij.workspaceModel.test.api.EntityWithManyImports", isChild = false, isNullable = false), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
}
|
||||
|
||||
override fun initializeMetadataHash() {
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.EntityWithManyImports", metadataHash = 279598191)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SimpleEntity", metadataHash = 8198385)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SimpleId", metadataHash = 1096965603)
|
||||
addMetadataHash(typeFqn = "com.intellij.platform.workspace.storage.SymbolicEntityId", metadataHash = -1044278955)
|
||||
}
|
||||
|
||||
}
|
||||
+256
@@ -0,0 +1,256 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.impl.EntityLink
|
||||
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.platform.workspace.storage.impl.extractOneToManyParent
|
||||
import com.intellij.platform.workspace.storage.impl.updateOneToManyParentOfChild
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
|
||||
import com.intellij.platform.workspace.storage.instrumentation.MutableEntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
|
||||
import com.intellij.workspaceModel.test.api.EntityWithManyImports
|
||||
import com.intellij.workspaceModel.test.api.SimpleEntity
|
||||
import java.net.URL
|
||||
|
||||
@GeneratedCodeApiVersion(3)
|
||||
@GeneratedCodeImplVersion(6)
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class SimpleEntityImpl(private val dataSource: SimpleEntityData) : SimpleEntity, WorkspaceEntityBase(dataSource) {
|
||||
|
||||
private companion object {
|
||||
internal val PARENT_CONNECTION_ID: ConnectionId =
|
||||
ConnectionId.create(EntityWithManyImports::class.java, SimpleEntity::class.java, ConnectionId.ConnectionType.ONE_TO_MANY, false)
|
||||
|
||||
private val connections = listOf<ConnectionId>(
|
||||
PARENT_CONNECTION_ID,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override val url: VirtualFileUrl
|
||||
get() {
|
||||
readField("url")
|
||||
return dataSource.url
|
||||
}
|
||||
|
||||
override val parent: EntityWithManyImports
|
||||
get() = snapshot.extractOneToManyParent(PARENT_CONNECTION_ID, this)!!
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() {
|
||||
readField("entitySource")
|
||||
return dataSource.entitySource
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
|
||||
internal class Builder(result: SimpleEntityData?) : ModifiableWorkspaceEntityBase<SimpleEntity, SimpleEntityData>(result),
|
||||
SimpleEntity.Builder {
|
||||
internal constructor() : this(SimpleEntityData())
|
||||
|
||||
override fun applyToBuilder(builder: MutableEntityStorage) {
|
||||
if (this.diff != null) {
|
||||
if (existsInBuilder(builder)) {
|
||||
this.diff = builder
|
||||
return
|
||||
}
|
||||
else {
|
||||
error("Entity SimpleEntity is already created in a different builder")
|
||||
}
|
||||
}
|
||||
|
||||
this.diff = builder
|
||||
addToBuilder()
|
||||
this.id = getEntityData().createEntityId()
|
||||
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
|
||||
// Builder may switch to snapshot at any moment and lock entity data to modification
|
||||
this.currentEntityData = null
|
||||
|
||||
index(this, "url", this.url)
|
||||
// Process linked entities that are connected without a builder
|
||||
processLinkedEntities(builder)
|
||||
checkInitialization() // TODO uncomment and check failed tests
|
||||
}
|
||||
|
||||
private fun checkInitialization() {
|
||||
val _diff = diff
|
||||
if (!getEntityData().isEntitySourceInitialized()) {
|
||||
error("Field WorkspaceEntity#entitySource should be initialized")
|
||||
}
|
||||
if (!getEntityData().isUrlInitialized()) {
|
||||
error("Field SimpleEntity#url should be initialized")
|
||||
}
|
||||
if (_diff != null) {
|
||||
if (_diff.extractOneToManyParent<WorkspaceEntityBase>(PARENT_CONNECTION_ID, this) == null) {
|
||||
error("Field SimpleEntity#parent should be initialized")
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)] == null) {
|
||||
error("Field SimpleEntity#parent should be initialized")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
// Relabeling code, move information from dataSource to this builder
|
||||
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
|
||||
dataSource as SimpleEntity
|
||||
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
|
||||
if (this.url != dataSource.url) this.url = dataSource.url
|
||||
updateChildToParentReferences(parents)
|
||||
}
|
||||
|
||||
|
||||
override var entitySource: EntitySource
|
||||
get() = getEntityData().entitySource
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).entitySource = value
|
||||
changedProperty.add("entitySource")
|
||||
|
||||
}
|
||||
|
||||
override var url: VirtualFileUrl
|
||||
get() = getEntityData().url
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).url = value
|
||||
changedProperty.add("url")
|
||||
val _diff = diff
|
||||
if (_diff != null) index(this, "url", value)
|
||||
}
|
||||
|
||||
override var parent: EntityWithManyImports.Builder
|
||||
get() {
|
||||
val _diff = diff
|
||||
return if (_diff != null) {
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
((_diff as MutableEntityStorageInstrumentation).getParentBuilder(PARENT_CONNECTION_ID, this) as? EntityWithManyImports.Builder)
|
||||
?: (this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)]!! as EntityWithManyImports.Builder)
|
||||
}
|
||||
else {
|
||||
this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)]!! as EntityWithManyImports.Builder
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
val _diff = diff
|
||||
if (_diff != null && value is ModifiableWorkspaceEntityBase<*, *> && value.diff == null) {
|
||||
// Setting backref of the list
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
val data = (value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] as? List<Any> ?: emptyList()) + this
|
||||
value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] = data
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
_diff.addEntity(value as ModifiableWorkspaceEntityBase<WorkspaceEntity, *>)
|
||||
}
|
||||
if (_diff != null && (value !is ModifiableWorkspaceEntityBase<*, *> || value.diff != null)) {
|
||||
_diff.updateOneToManyParentOfChild(PARENT_CONNECTION_ID, this, value)
|
||||
}
|
||||
else {
|
||||
// Setting backref of the list
|
||||
if (value is ModifiableWorkspaceEntityBase<*, *>) {
|
||||
val data = (value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] as? List<Any> ?: emptyList()) + this
|
||||
value.entityLinks[EntityLink(true, PARENT_CONNECTION_ID)] = data
|
||||
}
|
||||
// else you're attaching a new entity to an existing entity that is not modifiable
|
||||
|
||||
this.entityLinks[EntityLink(false, PARENT_CONNECTION_ID)] = value
|
||||
}
|
||||
changedProperty.add("parent")
|
||||
}
|
||||
|
||||
override fun getEntityClass(): Class<SimpleEntity> = SimpleEntity::class.java
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class SimpleEntityData : WorkspaceEntityData<SimpleEntity>() {
|
||||
lateinit var url: VirtualFileUrl
|
||||
|
||||
internal fun isUrlInitialized(): Boolean = ::url.isInitialized
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<SimpleEntity> {
|
||||
val modifiable = SimpleEntityImpl.Builder(null)
|
||||
modifiable.diff = diff
|
||||
modifiable.id = createEntityId()
|
||||
return modifiable
|
||||
}
|
||||
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
override fun createEntity(snapshot: EntityStorageInstrumentation): SimpleEntity {
|
||||
val entityId = createEntityId()
|
||||
return snapshot.initializeEntity(entityId) {
|
||||
val entity = SimpleEntityImpl(this)
|
||||
entity.snapshot = snapshot
|
||||
entity.id = entityId
|
||||
entity
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMetadata(): EntityMetadata {
|
||||
return MetadataStorageImpl.getMetadataByTypeFqn("com.intellij.workspaceModel.test.api.SimpleEntity") as EntityMetadata
|
||||
}
|
||||
|
||||
override fun getEntityInterface(): Class<out WorkspaceEntity> {
|
||||
return SimpleEntity::class.java
|
||||
}
|
||||
|
||||
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
|
||||
return SimpleEntity(url, entitySource) {
|
||||
parents.filterIsInstance<EntityWithManyImports.Builder>().singleOrNull()?.let { this.parent = it }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
|
||||
val res = mutableListOf<Class<out WorkspaceEntity>>()
|
||||
res.add(EntityWithManyImports::class.java)
|
||||
return res
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as SimpleEntityData
|
||||
|
||||
if (this.entitySource != other.entitySource) return false
|
||||
if (this.url != other.url) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as SimpleEntityData
|
||||
|
||||
if (this.url != other.url) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = entitySource.hashCode()
|
||||
result = 31 * result + url.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun hashCodeIgnoringEntitySource(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + url.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId // stoopid and unnecessary
|
||||
import java.net.URL // stoopid but necessary (user-added)
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
|
||||
|
||||
interface EntityWithManyImports : WorkspaceEntityWithSymbolicId {
|
||||
val version: Int
|
||||
val name: String
|
||||
val files: List<@Child SimpleEntity>
|
||||
val pointer: EntityPointer<SimpleEntity>
|
||||
|
||||
override val symbolicId: SimpleId
|
||||
get() = SimpleId(name)
|
||||
}
|
||||
|
||||
data class SimpleId(val name: String) : SymbolicEntityId<EntityWithManyImports> {
|
||||
override val presentableName: String
|
||||
get() = name
|
||||
}
|
||||
|
||||
interface SimpleEntity : WorkspaceEntity {
|
||||
val url: VirtualFileUrl
|
||||
val parent: EntityWithManyImports
|
||||
}
|
||||
|
||||
data class UnrelatedToEntities(val name: String, val data: EntityPointer<SimpleEntity>) {
|
||||
fun doSomething(src: EntitySource) {
|
||||
}
|
||||
}
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
import com.intellij.platform.workspace.storage.annotations.Abstract
|
||||
|
||||
interface SimpleEntity : WorkspaceEntityWithSymbolicId {
|
||||
override val symbolicId: SimpleId
|
||||
get() = SimpleId(name)
|
||||
|
||||
val name: String
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
interface Builder : WorkspaceEntity.Builder<SimpleEntity> {
|
||||
override var entitySource: EntitySource
|
||||
var name: String
|
||||
}
|
||||
|
||||
companion object : EntityType<SimpleEntity, Builder>() {
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
@JvmName("create")
|
||||
operator fun invoke(
|
||||
name: String,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder.() -> Unit)? = null,
|
||||
): Builder {
|
||||
val builder = builder()
|
||||
builder.name = name
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
//region generated code
|
||||
fun MutableEntityStorage.modifySimpleEntity(
|
||||
entity: SimpleEntity,
|
||||
modification: SimpleEntity.Builder.() -> Unit,
|
||||
): SimpleEntity {
|
||||
return modifyEntity(SimpleEntity.Builder::class.java, entity, modification)
|
||||
}
|
||||
//endregion
|
||||
|
||||
data class SimpleId(val name: String) : SymbolicEntityId<SimpleEntity> {
|
||||
override val presentableName: String
|
||||
get() = name
|
||||
}
|
||||
|
||||
// partial copy of org.jetbrains.kotlin.idea.workspaceModel.KotlinSettingsEntity
|
||||
@Abstract
|
||||
interface BaseEntity : WorkspaceEntity {
|
||||
val name: String
|
||||
val moduleId: SimpleId
|
||||
|
||||
val aBaseEntityProperty: String
|
||||
val dBaseEntityProperty: String
|
||||
val bBaseEntityProperty: String
|
||||
|
||||
val sealedDataClassProperty: BaseDataClass
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
interface Builder<T : BaseEntity> : WorkspaceEntity.Builder<T> {
|
||||
override var entitySource: EntitySource
|
||||
var name: String
|
||||
var moduleId: SimpleId
|
||||
var aBaseEntityProperty: String
|
||||
var dBaseEntityProperty: String
|
||||
var bBaseEntityProperty: String
|
||||
var sealedDataClassProperty: BaseDataClass
|
||||
}
|
||||
|
||||
companion object : EntityType<BaseEntity, Builder<BaseEntity>>() {
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
@JvmName("create")
|
||||
operator fun invoke(
|
||||
name: String,
|
||||
moduleId: SimpleId,
|
||||
aBaseEntityProperty: String,
|
||||
dBaseEntityProperty: String,
|
||||
bBaseEntityProperty: String,
|
||||
sealedDataClassProperty: BaseDataClass,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder<BaseEntity>.() -> Unit)? = null,
|
||||
): Builder<BaseEntity> {
|
||||
val builder = builder()
|
||||
builder.name = name
|
||||
builder.moduleId = moduleId
|
||||
builder.aBaseEntityProperty = aBaseEntityProperty
|
||||
builder.dBaseEntityProperty = dBaseEntityProperty
|
||||
builder.bBaseEntityProperty = bBaseEntityProperty
|
||||
builder.sealedDataClassProperty = sealedDataClassProperty
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
interface ChildEntity : BaseEntity {
|
||||
val cChildEntityProperty: String
|
||||
|
||||
//region generated code
|
||||
@GeneratedCodeApiVersion(3)
|
||||
interface Builder : WorkspaceEntity.Builder<ChildEntity>, BaseEntity.Builder<ChildEntity> {
|
||||
override var entitySource: EntitySource
|
||||
override var name: String
|
||||
override var moduleId: SimpleId
|
||||
override var aBaseEntityProperty: String
|
||||
override var dBaseEntityProperty: String
|
||||
override var bBaseEntityProperty: String
|
||||
override var sealedDataClassProperty: BaseDataClass
|
||||
var cChildEntityProperty: String
|
||||
}
|
||||
|
||||
companion object : EntityType<ChildEntity, Builder>(BaseEntity) {
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
@JvmName("create")
|
||||
operator fun invoke(
|
||||
name: String,
|
||||
moduleId: SimpleId,
|
||||
aBaseEntityProperty: String,
|
||||
dBaseEntityProperty: String,
|
||||
bBaseEntityProperty: String,
|
||||
sealedDataClassProperty: BaseDataClass,
|
||||
cChildEntityProperty: String,
|
||||
entitySource: EntitySource,
|
||||
init: (Builder.() -> Unit)? = null,
|
||||
): Builder {
|
||||
val builder = builder()
|
||||
builder.name = name
|
||||
builder.moduleId = moduleId
|
||||
builder.aBaseEntityProperty = aBaseEntityProperty
|
||||
builder.dBaseEntityProperty = dBaseEntityProperty
|
||||
builder.bBaseEntityProperty = bBaseEntityProperty
|
||||
builder.sealedDataClassProperty = sealedDataClassProperty
|
||||
builder.cChildEntityProperty = cChildEntityProperty
|
||||
builder.entitySource = entitySource
|
||||
init?.invoke(builder)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
//region generated code
|
||||
fun MutableEntityStorage.modifyChildEntity(
|
||||
entity: ChildEntity,
|
||||
modification: ChildEntity.Builder.() -> Unit,
|
||||
): ChildEntity {
|
||||
return modifyEntity(ChildEntity.Builder::class.java, entity, modification)
|
||||
}
|
||||
//endregion
|
||||
|
||||
sealed class BaseDataClass(val baseConstructorProperty: String) {
|
||||
open val baseBodyProperty: Int = 15
|
||||
val anotherBaseBodyProperty: Int = 16
|
||||
}
|
||||
|
||||
sealed class DerivedDataClass(
|
||||
baseConstructorPropertyValue: String,
|
||||
val derivedConstructorProperty: String
|
||||
) : BaseDataClass(baseConstructorPropertyValue) {
|
||||
val derivedBodyProperty: Int = 23
|
||||
}
|
||||
|
||||
class DerivedDerivedDataClass(
|
||||
baseConstructorPropertyValue: String,
|
||||
override val baseBodyProperty: Int,
|
||||
derivedConstructorPropertyValue: String,
|
||||
val derivedDerivedConstructorProperty: String
|
||||
) : DerivedDataClass(baseConstructorPropertyValue, derivedConstructorPropertyValue) {
|
||||
val deriveDerivedBodyProperty: Int = 42
|
||||
}
|
||||
+427
@@ -0,0 +1,427 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
import com.intellij.platform.workspace.storage.annotations.Abstract
|
||||
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.SoftLinkable
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.platform.workspace.storage.impl.indices.WorkspaceMutableIndex
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.workspaceModel.test.api.BaseDataClass
|
||||
import com.intellij.workspaceModel.test.api.ChildEntity
|
||||
import com.intellij.workspaceModel.test.api.DerivedDataClass
|
||||
import com.intellij.workspaceModel.test.api.DerivedDerivedDataClass
|
||||
import com.intellij.workspaceModel.test.api.SimpleId
|
||||
|
||||
@GeneratedCodeApiVersion(3)
|
||||
@GeneratedCodeImplVersion(6)
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class ChildEntityImpl(private val dataSource: ChildEntityData) : ChildEntity, WorkspaceEntityBase(dataSource) {
|
||||
|
||||
private companion object {
|
||||
|
||||
|
||||
private val connections = listOf<ConnectionId>(
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override val name: String
|
||||
get() {
|
||||
readField("name")
|
||||
return dataSource.name
|
||||
}
|
||||
|
||||
override val moduleId: SimpleId
|
||||
get() {
|
||||
readField("moduleId")
|
||||
return dataSource.moduleId
|
||||
}
|
||||
|
||||
override val aBaseEntityProperty: String
|
||||
get() {
|
||||
readField("aBaseEntityProperty")
|
||||
return dataSource.aBaseEntityProperty
|
||||
}
|
||||
|
||||
override val dBaseEntityProperty: String
|
||||
get() {
|
||||
readField("dBaseEntityProperty")
|
||||
return dataSource.dBaseEntityProperty
|
||||
}
|
||||
|
||||
override val bBaseEntityProperty: String
|
||||
get() {
|
||||
readField("bBaseEntityProperty")
|
||||
return dataSource.bBaseEntityProperty
|
||||
}
|
||||
|
||||
override val sealedDataClassProperty: BaseDataClass
|
||||
get() {
|
||||
readField("sealedDataClassProperty")
|
||||
return dataSource.sealedDataClassProperty
|
||||
}
|
||||
|
||||
override val cChildEntityProperty: String
|
||||
get() {
|
||||
readField("cChildEntityProperty")
|
||||
return dataSource.cChildEntityProperty
|
||||
}
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() {
|
||||
readField("entitySource")
|
||||
return dataSource.entitySource
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
|
||||
internal class Builder(result: ChildEntityData?) : ModifiableWorkspaceEntityBase<ChildEntity, ChildEntityData>(result),
|
||||
ChildEntity.Builder {
|
||||
internal constructor() : this(ChildEntityData())
|
||||
|
||||
override fun applyToBuilder(builder: MutableEntityStorage) {
|
||||
if (this.diff != null) {
|
||||
if (existsInBuilder(builder)) {
|
||||
this.diff = builder
|
||||
return
|
||||
}
|
||||
else {
|
||||
error("Entity ChildEntity is already created in a different builder")
|
||||
}
|
||||
}
|
||||
|
||||
this.diff = builder
|
||||
addToBuilder()
|
||||
this.id = getEntityData().createEntityId()
|
||||
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
|
||||
// Builder may switch to snapshot at any moment and lock entity data to modification
|
||||
this.currentEntityData = null
|
||||
|
||||
// Process linked entities that are connected without a builder
|
||||
processLinkedEntities(builder)
|
||||
checkInitialization() // TODO uncomment and check failed tests
|
||||
}
|
||||
|
||||
private fun checkInitialization() {
|
||||
val _diff = diff
|
||||
if (!getEntityData().isEntitySourceInitialized()) {
|
||||
error("Field WorkspaceEntity#entitySource should be initialized")
|
||||
}
|
||||
if (!getEntityData().isNameInitialized()) {
|
||||
error("Field BaseEntity#name should be initialized")
|
||||
}
|
||||
if (!getEntityData().isModuleIdInitialized()) {
|
||||
error("Field BaseEntity#moduleId should be initialized")
|
||||
}
|
||||
if (!getEntityData().isABaseEntityPropertyInitialized()) {
|
||||
error("Field BaseEntity#aBaseEntityProperty should be initialized")
|
||||
}
|
||||
if (!getEntityData().isDBaseEntityPropertyInitialized()) {
|
||||
error("Field BaseEntity#dBaseEntityProperty should be initialized")
|
||||
}
|
||||
if (!getEntityData().isBBaseEntityPropertyInitialized()) {
|
||||
error("Field BaseEntity#bBaseEntityProperty should be initialized")
|
||||
}
|
||||
if (!getEntityData().isSealedDataClassPropertyInitialized()) {
|
||||
error("Field BaseEntity#sealedDataClassProperty should be initialized")
|
||||
}
|
||||
if (!getEntityData().isCChildEntityPropertyInitialized()) {
|
||||
error("Field ChildEntity#cChildEntityProperty should be initialized")
|
||||
}
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
// Relabeling code, move information from dataSource to this builder
|
||||
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
|
||||
dataSource as ChildEntity
|
||||
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
|
||||
if (this.name != dataSource.name) this.name = dataSource.name
|
||||
if (this.moduleId != dataSource.moduleId) this.moduleId = dataSource.moduleId
|
||||
if (this.aBaseEntityProperty != dataSource.aBaseEntityProperty) this.aBaseEntityProperty = dataSource.aBaseEntityProperty
|
||||
if (this.dBaseEntityProperty != dataSource.dBaseEntityProperty) this.dBaseEntityProperty = dataSource.dBaseEntityProperty
|
||||
if (this.bBaseEntityProperty != dataSource.bBaseEntityProperty) this.bBaseEntityProperty = dataSource.bBaseEntityProperty
|
||||
if (this.sealedDataClassProperty != dataSource.sealedDataClassProperty) this.sealedDataClassProperty =
|
||||
dataSource.sealedDataClassProperty
|
||||
if (this.cChildEntityProperty != dataSource.cChildEntityProperty) this.cChildEntityProperty = dataSource.cChildEntityProperty
|
||||
updateChildToParentReferences(parents)
|
||||
}
|
||||
|
||||
|
||||
override var entitySource: EntitySource
|
||||
get() = getEntityData().entitySource
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).entitySource = value
|
||||
changedProperty.add("entitySource")
|
||||
|
||||
}
|
||||
|
||||
override var name: String
|
||||
get() = getEntityData().name
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).name = value
|
||||
changedProperty.add("name")
|
||||
}
|
||||
|
||||
override var moduleId: SimpleId
|
||||
get() = getEntityData().moduleId
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).moduleId = value
|
||||
changedProperty.add("moduleId")
|
||||
|
||||
}
|
||||
|
||||
override var aBaseEntityProperty: String
|
||||
get() = getEntityData().aBaseEntityProperty
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).aBaseEntityProperty = value
|
||||
changedProperty.add("aBaseEntityProperty")
|
||||
}
|
||||
|
||||
override var dBaseEntityProperty: String
|
||||
get() = getEntityData().dBaseEntityProperty
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).dBaseEntityProperty = value
|
||||
changedProperty.add("dBaseEntityProperty")
|
||||
}
|
||||
|
||||
override var bBaseEntityProperty: String
|
||||
get() = getEntityData().bBaseEntityProperty
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).bBaseEntityProperty = value
|
||||
changedProperty.add("bBaseEntityProperty")
|
||||
}
|
||||
|
||||
override var sealedDataClassProperty: BaseDataClass
|
||||
get() = getEntityData().sealedDataClassProperty
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).sealedDataClassProperty = value
|
||||
changedProperty.add("sealedDataClassProperty")
|
||||
|
||||
}
|
||||
|
||||
override var cChildEntityProperty: String
|
||||
get() = getEntityData().cChildEntityProperty
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).cChildEntityProperty = value
|
||||
changedProperty.add("cChildEntityProperty")
|
||||
}
|
||||
|
||||
override fun getEntityClass(): Class<ChildEntity> = ChildEntity::class.java
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class ChildEntityData : WorkspaceEntityData<ChildEntity>(), SoftLinkable {
|
||||
lateinit var name: String
|
||||
lateinit var moduleId: SimpleId
|
||||
lateinit var aBaseEntityProperty: String
|
||||
lateinit var dBaseEntityProperty: String
|
||||
lateinit var bBaseEntityProperty: String
|
||||
lateinit var sealedDataClassProperty: BaseDataClass
|
||||
lateinit var cChildEntityProperty: String
|
||||
|
||||
internal fun isNameInitialized(): Boolean = ::name.isInitialized
|
||||
internal fun isModuleIdInitialized(): Boolean = ::moduleId.isInitialized
|
||||
internal fun isABaseEntityPropertyInitialized(): Boolean = ::aBaseEntityProperty.isInitialized
|
||||
internal fun isDBaseEntityPropertyInitialized(): Boolean = ::dBaseEntityProperty.isInitialized
|
||||
internal fun isBBaseEntityPropertyInitialized(): Boolean = ::bBaseEntityProperty.isInitialized
|
||||
internal fun isSealedDataClassPropertyInitialized(): Boolean = ::sealedDataClassProperty.isInitialized
|
||||
internal fun isCChildEntityPropertyInitialized(): Boolean = ::cChildEntityProperty.isInitialized
|
||||
|
||||
override fun getLinks(): Set<SymbolicEntityId<*>> {
|
||||
val result = HashSet<SymbolicEntityId<*>>()
|
||||
result.add(moduleId)
|
||||
val _sealedDataClassProperty = sealedDataClassProperty
|
||||
when (_sealedDataClassProperty) {
|
||||
is DerivedDataClass -> {
|
||||
val __sealedDataClassProperty = _sealedDataClassProperty
|
||||
when (__sealedDataClassProperty) {
|
||||
is DerivedDerivedDataClass -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun index(index: WorkspaceMutableIndex<SymbolicEntityId<*>>) {
|
||||
index.index(this, moduleId)
|
||||
val _sealedDataClassProperty = sealedDataClassProperty
|
||||
when (_sealedDataClassProperty) {
|
||||
is DerivedDataClass -> {
|
||||
val __sealedDataClassProperty = _sealedDataClassProperty
|
||||
when (__sealedDataClassProperty) {
|
||||
is DerivedDerivedDataClass -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateLinksIndex(prev: Set<SymbolicEntityId<*>>, index: WorkspaceMutableIndex<SymbolicEntityId<*>>) {
|
||||
// TODO verify logic
|
||||
val mutablePreviousSet = HashSet(prev)
|
||||
val removedItem_moduleId = mutablePreviousSet.remove(moduleId)
|
||||
if (!removedItem_moduleId) {
|
||||
index.index(this, moduleId)
|
||||
}
|
||||
val _sealedDataClassProperty = sealedDataClassProperty
|
||||
when (_sealedDataClassProperty) {
|
||||
is DerivedDataClass -> {
|
||||
val __sealedDataClassProperty = _sealedDataClassProperty
|
||||
when (__sealedDataClassProperty) {
|
||||
is DerivedDerivedDataClass -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (removed in mutablePreviousSet) {
|
||||
index.remove(this, removed)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateLink(oldLink: SymbolicEntityId<*>, newLink: SymbolicEntityId<*>): Boolean {
|
||||
var changed = false
|
||||
val moduleId_data = if (moduleId == oldLink) {
|
||||
changed = true
|
||||
newLink as SimpleId
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
if (moduleId_data != null) {
|
||||
moduleId = moduleId_data
|
||||
}
|
||||
val _sealedDataClassProperty = sealedDataClassProperty
|
||||
val res_sealedDataClassProperty = when (_sealedDataClassProperty) {
|
||||
is DerivedDataClass -> {
|
||||
val __sealedDataClassProperty = _sealedDataClassProperty
|
||||
val res__sealedDataClassProperty = when (__sealedDataClassProperty) {
|
||||
is DerivedDerivedDataClass -> {
|
||||
__sealedDataClassProperty
|
||||
}
|
||||
}
|
||||
res__sealedDataClassProperty
|
||||
}
|
||||
}
|
||||
if (res_sealedDataClassProperty != null) {
|
||||
sealedDataClassProperty = res_sealedDataClassProperty
|
||||
}
|
||||
return changed
|
||||
}
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<ChildEntity> {
|
||||
val modifiable = ChildEntityImpl.Builder(null)
|
||||
modifiable.diff = diff
|
||||
modifiable.id = createEntityId()
|
||||
return modifiable
|
||||
}
|
||||
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
override fun createEntity(snapshot: EntityStorageInstrumentation): ChildEntity {
|
||||
val entityId = createEntityId()
|
||||
return snapshot.initializeEntity(entityId) {
|
||||
val entity = ChildEntityImpl(this)
|
||||
entity.snapshot = snapshot
|
||||
entity.id = entityId
|
||||
entity
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMetadata(): EntityMetadata {
|
||||
return MetadataStorageImpl.getMetadataByTypeFqn("com.intellij.workspaceModel.test.api.ChildEntity") as EntityMetadata
|
||||
}
|
||||
|
||||
override fun getEntityInterface(): Class<out WorkspaceEntity> {
|
||||
return ChildEntity::class.java
|
||||
}
|
||||
|
||||
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
|
||||
return ChildEntity(
|
||||
name, moduleId, aBaseEntityProperty, dBaseEntityProperty, bBaseEntityProperty, sealedDataClassProperty, cChildEntityProperty,
|
||||
entitySource
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
|
||||
val res = mutableListOf<Class<out WorkspaceEntity>>()
|
||||
return res
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as ChildEntityData
|
||||
|
||||
if (this.entitySource != other.entitySource) return false
|
||||
if (this.name != other.name) return false
|
||||
if (this.moduleId != other.moduleId) return false
|
||||
if (this.aBaseEntityProperty != other.aBaseEntityProperty) return false
|
||||
if (this.dBaseEntityProperty != other.dBaseEntityProperty) return false
|
||||
if (this.bBaseEntityProperty != other.bBaseEntityProperty) return false
|
||||
if (this.sealedDataClassProperty != other.sealedDataClassProperty) return false
|
||||
if (this.cChildEntityProperty != other.cChildEntityProperty) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as ChildEntityData
|
||||
|
||||
if (this.name != other.name) return false
|
||||
if (this.moduleId != other.moduleId) return false
|
||||
if (this.aBaseEntityProperty != other.aBaseEntityProperty) return false
|
||||
if (this.dBaseEntityProperty != other.dBaseEntityProperty) return false
|
||||
if (this.bBaseEntityProperty != other.bBaseEntityProperty) return false
|
||||
if (this.sealedDataClassProperty != other.sealedDataClassProperty) return false
|
||||
if (this.cChildEntityProperty != other.cChildEntityProperty) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = entitySource.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + moduleId.hashCode()
|
||||
result = 31 * result + aBaseEntityProperty.hashCode()
|
||||
result = 31 * result + dBaseEntityProperty.hashCode()
|
||||
result = 31 * result + bBaseEntityProperty.hashCode()
|
||||
result = 31 * result + sealedDataClassProperty.hashCode()
|
||||
result = 31 * result + cChildEntityProperty.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun hashCodeIgnoringEntitySource(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + moduleId.hashCode()
|
||||
result = 31 * result + aBaseEntityProperty.hashCode()
|
||||
result = 31 * result + dBaseEntityProperty.hashCode()
|
||||
result = 31 * result + bBaseEntityProperty.hashCode()
|
||||
result = 31 * result + sealedDataClassProperty.hashCode()
|
||||
result = 31 * result + cChildEntityProperty.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityInternalApi
|
||||
import com.intellij.platform.workspace.storage.metadata.impl.MetadataStorageBase
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.ExtendableClassMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.FinalClassMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.OwnPropertyMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.StorageTypeMetadata
|
||||
import com.intellij.platform.workspace.storage.metadata.model.ValueTypeMetadata
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal object MetadataStorageImpl: MetadataStorageBase() {
|
||||
override fun initializeMetadata() {
|
||||
val primitiveTypeStringNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "String")
|
||||
val primitiveTypeIntNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Int")
|
||||
|
||||
var typeMetadata: StorageTypeMetadata
|
||||
|
||||
typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.SymbolicEntityId"))
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.BaseEntity", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.BaseEntityData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "moduleId", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.SymbolicEntityId"))), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "aBaseEntityProperty", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "dBaseEntityProperty", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "bBaseEntityProperty", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "sealedDataClassProperty", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = ExtendableClassMetadata.AbstractClassMetadata(fqName = "com.intellij.workspaceModel.test.api.BaseDataClass", subclasses = listOf(FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.DerivedDerivedDataClass", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "anotherBaseBodyProperty", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "baseBodyProperty", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "baseConstructorProperty", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "deriveDerivedBodyProperty", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "derivedBodyProperty", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "derivedConstructorProperty", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "derivedDerivedConstructorProperty", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.workspaceModel.test.api.BaseDataClass",
|
||||
"com.intellij.workspaceModel.test.api.DerivedDataClass"))), supertypes = listOf())), withDefault = false)), extProperties = listOf(), isAbstract = true)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.ChildEntity", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.ChildEntityData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity",
|
||||
"com.intellij.workspaceModel.test.api.BaseEntity"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "moduleId", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.SymbolicEntityId"))), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "aBaseEntityProperty", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "dBaseEntityProperty", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "bBaseEntityProperty", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "sealedDataClassProperty", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = ExtendableClassMetadata.AbstractClassMetadata(fqName = "com.intellij.workspaceModel.test.api.BaseDataClass", subclasses = listOf(FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.DerivedDerivedDataClass", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "anotherBaseBodyProperty", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "baseBodyProperty", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "baseConstructorProperty", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "deriveDerivedBodyProperty", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "derivedBodyProperty", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "derivedConstructorProperty", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "derivedDerivedConstructorProperty", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.workspaceModel.test.api.BaseDataClass",
|
||||
"com.intellij.workspaceModel.test.api.DerivedDataClass"))), supertypes = listOf())), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "cChildEntityProperty", valueType = primitiveTypeStringNotNullable, withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleEntity", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.SimpleEntityData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity",
|
||||
"com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = true, isKey = false, isOpen = false, name = "symbolicId", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.SymbolicEntityId"))), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
}
|
||||
|
||||
override fun initializeMetadataHash() {
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.BaseEntity", metadataHash = -433943746)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.ChildEntity", metadataHash = -296025373)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SimpleEntity", metadataHash = -2018622680)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SimpleId", metadataHash = 1096965603)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.BaseDataClass", metadataHash = 937384310)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.DerivedDataClass", metadataHash = 1525344553)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.DerivedDerivedDataClass", metadataHash = -597612584)
|
||||
addMetadataHash(typeFqn = "com.intellij.platform.workspace.storage.SymbolicEntityId", metadataHash = -1044278955)
|
||||
}
|
||||
|
||||
}
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.test.api.impl
|
||||
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
import com.intellij.platform.workspace.storage.annotations.Abstract
|
||||
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
import com.intellij.workspaceModel.test.api.SimpleEntity
|
||||
import com.intellij.workspaceModel.test.api.SimpleId
|
||||
|
||||
@GeneratedCodeApiVersion(3)
|
||||
@GeneratedCodeImplVersion(6)
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class SimpleEntityImpl(private val dataSource: SimpleEntityData) : SimpleEntity, WorkspaceEntityBase(dataSource) {
|
||||
|
||||
private companion object {
|
||||
|
||||
|
||||
private val connections = listOf<ConnectionId>(
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override val symbolicId: SimpleId = super.symbolicId
|
||||
|
||||
override val name: String
|
||||
get() {
|
||||
readField("name")
|
||||
return dataSource.name
|
||||
}
|
||||
|
||||
override val entitySource: EntitySource
|
||||
get() {
|
||||
readField("entitySource")
|
||||
return dataSource.entitySource
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
|
||||
internal class Builder(result: SimpleEntityData?) : ModifiableWorkspaceEntityBase<SimpleEntity, SimpleEntityData>(result),
|
||||
SimpleEntity.Builder {
|
||||
internal constructor() : this(SimpleEntityData())
|
||||
|
||||
override fun applyToBuilder(builder: MutableEntityStorage) {
|
||||
if (this.diff != null) {
|
||||
if (existsInBuilder(builder)) {
|
||||
this.diff = builder
|
||||
return
|
||||
}
|
||||
else {
|
||||
error("Entity SimpleEntity is already created in a different builder")
|
||||
}
|
||||
}
|
||||
|
||||
this.diff = builder
|
||||
addToBuilder()
|
||||
this.id = getEntityData().createEntityId()
|
||||
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
|
||||
// Builder may switch to snapshot at any moment and lock entity data to modification
|
||||
this.currentEntityData = null
|
||||
|
||||
// Process linked entities that are connected without a builder
|
||||
processLinkedEntities(builder)
|
||||
checkInitialization() // TODO uncomment and check failed tests
|
||||
}
|
||||
|
||||
private fun checkInitialization() {
|
||||
val _diff = diff
|
||||
if (!getEntityData().isEntitySourceInitialized()) {
|
||||
error("Field WorkspaceEntity#entitySource should be initialized")
|
||||
}
|
||||
if (!getEntityData().isNameInitialized()) {
|
||||
error("Field SimpleEntity#name should be initialized")
|
||||
}
|
||||
}
|
||||
|
||||
override fun connectionIdList(): List<ConnectionId> {
|
||||
return connections
|
||||
}
|
||||
|
||||
// Relabeling code, move information from dataSource to this builder
|
||||
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
|
||||
dataSource as SimpleEntity
|
||||
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
|
||||
if (this.name != dataSource.name) this.name = dataSource.name
|
||||
updateChildToParentReferences(parents)
|
||||
}
|
||||
|
||||
|
||||
override var entitySource: EntitySource
|
||||
get() = getEntityData().entitySource
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).entitySource = value
|
||||
changedProperty.add("entitySource")
|
||||
|
||||
}
|
||||
|
||||
override var name: String
|
||||
get() = getEntityData().name
|
||||
set(value) {
|
||||
checkModificationAllowed()
|
||||
getEntityData(true).name = value
|
||||
changedProperty.add("name")
|
||||
}
|
||||
|
||||
override fun getEntityClass(): Class<SimpleEntity> = SimpleEntity::class.java
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class SimpleEntityData : WorkspaceEntityData<SimpleEntity>() {
|
||||
lateinit var name: String
|
||||
|
||||
internal fun isNameInitialized(): Boolean = ::name.isInitialized
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<SimpleEntity> {
|
||||
val modifiable = SimpleEntityImpl.Builder(null)
|
||||
modifiable.diff = diff
|
||||
modifiable.id = createEntityId()
|
||||
return modifiable
|
||||
}
|
||||
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
override fun createEntity(snapshot: EntityStorageInstrumentation): SimpleEntity {
|
||||
val entityId = createEntityId()
|
||||
return snapshot.initializeEntity(entityId) {
|
||||
val entity = SimpleEntityImpl(this)
|
||||
entity.snapshot = snapshot
|
||||
entity.id = entityId
|
||||
entity
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMetadata(): EntityMetadata {
|
||||
return MetadataStorageImpl.getMetadataByTypeFqn("com.intellij.workspaceModel.test.api.SimpleEntity") as EntityMetadata
|
||||
}
|
||||
|
||||
override fun getEntityInterface(): Class<out WorkspaceEntity> {
|
||||
return SimpleEntity::class.java
|
||||
}
|
||||
|
||||
override fun createDetachedEntity(parents: List<WorkspaceEntity.Builder<*>>): WorkspaceEntity.Builder<*> {
|
||||
return SimpleEntity(name, entitySource) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
|
||||
val res = mutableListOf<Class<out WorkspaceEntity>>()
|
||||
return res
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as SimpleEntityData
|
||||
|
||||
if (this.entitySource != other.entitySource) return false
|
||||
if (this.name != other.name) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (this.javaClass != other.javaClass) return false
|
||||
|
||||
other as SimpleEntityData
|
||||
|
||||
if (this.name != other.name) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = entitySource.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun hashCodeIgnoringEntitySource(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
import com.intellij.platform.workspace.storage.annotations.Abstract
|
||||
|
||||
interface SimpleEntity : WorkspaceEntityWithSymbolicId {
|
||||
override val symbolicId: SimpleId
|
||||
get() = SimpleId(name)
|
||||
|
||||
val name: String
|
||||
}
|
||||
|
||||
data class SimpleId(val name: String) : SymbolicEntityId<SimpleEntity> {
|
||||
override val presentableName: String
|
||||
get() = name
|
||||
}
|
||||
|
||||
// partial copy of org.jetbrains.kotlin.idea.workspaceModel.KotlinSettingsEntity
|
||||
@Abstract
|
||||
interface BaseEntity : WorkspaceEntity {
|
||||
val name: String
|
||||
val moduleId: SimpleId
|
||||
|
||||
val aBaseEntityProperty: String
|
||||
val dBaseEntityProperty: String
|
||||
val bBaseEntityProperty: String
|
||||
|
||||
val sealedDataClassProperty: BaseDataClass
|
||||
}
|
||||
|
||||
interface ChildEntity : BaseEntity {
|
||||
val cChildEntityProperty: String
|
||||
}
|
||||
|
||||
sealed class BaseDataClass(val baseConstructorProperty: String) {
|
||||
open val baseBodyProperty: Int = 15
|
||||
val anotherBaseBodyProperty: Int = 16
|
||||
}
|
||||
|
||||
sealed class DerivedDataClass(
|
||||
baseConstructorPropertyValue: String,
|
||||
val derivedConstructorProperty: String
|
||||
) : BaseDataClass(baseConstructorPropertyValue) {
|
||||
val derivedBodyProperty: Int = 23
|
||||
}
|
||||
|
||||
class DerivedDerivedDataClass(
|
||||
baseConstructorPropertyValue: String,
|
||||
override val baseBodyProperty: Int,
|
||||
derivedConstructorPropertyValue: String,
|
||||
val derivedDerivedConstructorProperty: String
|
||||
) : DerivedDataClass(baseConstructorPropertyValue, derivedConstructorPropertyValue) {
|
||||
val deriveDerivedBodyProperty: Int = 42
|
||||
}
|
||||
+1
-1
@@ -1,11 +1,11 @@
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.jps.entities.ContentRootEntity
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.EntityType
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.jps.entities.ContentRootEntity
|
||||
import com.intellij.platform.workspace.storage.annotations.Child
|
||||
|
||||
interface ReferredEntity : WorkspaceEntity {
|
||||
|
||||
+2
-4
@@ -4,8 +4,7 @@ import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.EntityType
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.annotations.Default
|
||||
import com.intellij.platform.workspace.storage.PersistentEntityId
|
||||
import com.intellij.platform.workspace.storage.SymbolicEntityId
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId
|
||||
|
||||
@@ -75,5 +74,4 @@ sealed class SealedClassWithLinks {
|
||||
data class Ordered(val list: List<SimpleId>) : Many()
|
||||
data class Unordered(val set: Set<SimpleId>) : Many()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+22
-16
@@ -12,41 +12,47 @@ import com.intellij.platform.workspace.storage.metadata.model.ValueTypeMetadata
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal object MetadataStorageImpl: MetadataStorageBase() {
|
||||
override fun initializeMetadata() {
|
||||
val primitiveTypeIntNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Int")
|
||||
val primitiveTypeStringNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "String")
|
||||
val primitiveTypeIntNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Int")
|
||||
val primitiveTypeListNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "List")
|
||||
val primitiveTypeSetNotNullable = ValueTypeMetadata.SimpleType.PrimitiveType(isNullable = false, type = "Set")
|
||||
|
||||
var typeMetadata: StorageTypeMetadata
|
||||
|
||||
typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.SymbolicEntityId"))
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
|
||||
typeMetadata = EntityMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleSymbolicIdEntity", entityDataFqName = "com.intellij.workspaceModel.test.api.impl.SimpleSymbolicIdEntityData", supertypes = listOf("com.intellij.platform.workspace.storage.WorkspaceEntity",
|
||||
"com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId"), properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "entitySource", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.platform.workspace.storage.EntitySource")), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "version", valueType = primitiveTypeIntNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "related", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf())), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "sealedClassWithLinks", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = ExtendableClassMetadata.AbstractClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SealedClassWithLinks", subclasses = listOf(FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many\$Ordered", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "list", valueType = ValueTypeMetadata.ParameterizedType(generics = listOf(ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf()))), primitive = primitiveTypeListNotNullable), withDefault = false)), supertypes = listOf("com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many",
|
||||
"com.intellij.workspaceModel.test.api.SealedClassWithLinks")),
|
||||
FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many\$Unordered", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "set", valueType = ValueTypeMetadata.ParameterizedType(generics = listOf(ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.workspaceModel.test.api.SimpleId"))), primitive = primitiveTypeSetNotNullable), withDefault = false)), supertypes = listOf("com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many",
|
||||
"com.intellij.workspaceModel.test.api.SealedClassWithLinks")),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "related", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.SymbolicEntityId"))), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "sealedClassWithLinks", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = ExtendableClassMetadata.AbstractClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SealedClassWithLinks", subclasses = listOf(FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many\$Ordered", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "list", valueType = ValueTypeMetadata.ParameterizedType(generics = listOf(ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.SymbolicEntityId")))), primitive = primitiveTypeListNotNullable), withDefault = false)), supertypes = listOf("com.intellij.workspaceModel.test.api.SealedClassWithLinks",
|
||||
"com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many")),
|
||||
FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many\$Unordered", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "set", valueType = ValueTypeMetadata.ParameterizedType(generics = listOf(ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.workspaceModel.test.api.SimpleId"))), primitive = primitiveTypeSetNotNullable), withDefault = false)), supertypes = listOf("com.intellij.workspaceModel.test.api.SealedClassWithLinks",
|
||||
"com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many")),
|
||||
FinalClassMetadata.ObjectMetadata(fqName = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Nothing", properties = listOf(), supertypes = listOf("com.intellij.workspaceModel.test.api.SealedClassWithLinks")),
|
||||
FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Single", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "id", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.KnownClass(fqName = "com.intellij.workspaceModel.test.api.SimpleId")), withDefault = false)), supertypes = listOf("com.intellij.workspaceModel.test.api.SealedClassWithLinks"))), supertypes = listOf())), withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = true, isKey = false, isOpen = false, name = "symbolicId", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf())), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
OwnPropertyMetadata(isComputable = true, isKey = false, isOpen = false, name = "symbolicId", valueType = ValueTypeMetadata.SimpleType.CustomType(isNullable = false, typeMetadata = FinalClassMetadata.ClassMetadata(fqName = "com.intellij.workspaceModel.test.api.SimpleId", properties = listOf(OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "name", valueType = primitiveTypeStringNotNullable, withDefault = false),
|
||||
OwnPropertyMetadata(isComputable = false, isKey = false, isOpen = false, name = "presentableName", valueType = primitiveTypeStringNotNullable, withDefault = false)), supertypes = listOf("com.intellij.platform.workspace.storage.SymbolicEntityId"))), withDefault = false)), extProperties = listOf(), isAbstract = false)
|
||||
|
||||
addMetadata(typeMetadata)
|
||||
}
|
||||
|
||||
override fun initializeMetadataHash() {
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SimpleSymbolicIdEntity", metadataHash = 920886074)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SimpleId", metadataHash = 503726574)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SealedClassWithLinks", metadataHash = 869203958)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many", metadataHash = 1388134395)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many\$Ordered", metadataHash = -2032838886)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many\$Unordered", metadataHash = -1543556527)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SimpleSymbolicIdEntity", metadataHash = -99546289)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SimpleId", metadataHash = 1096965603)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SealedClassWithLinks", metadataHash = 229222369)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many", metadataHash = 372382182)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many\$Ordered", metadataHash = -1632944095)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Many\$Unordered", metadataHash = -585653981)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Nothing", metadataHash = 1541593304)
|
||||
addMetadataHash(typeFqn = "com.intellij.workspaceModel.test.api.SealedClassWithLinks\$Single", metadataHash = -800484835)
|
||||
addMetadataHash(typeFqn = "com.intellij.platform.workspace.storage.SymbolicEntityId", metadataHash = -1044278955)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+192
-3
@@ -5,14 +5,15 @@ import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeApiVersion
|
||||
import com.intellij.platform.workspace.storage.GeneratedCodeImplVersion
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.PersistentEntityId
|
||||
import com.intellij.platform.workspace.storage.SymbolicEntityId
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityInternalApi
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId
|
||||
import com.intellij.platform.workspace.storage.annotations.Default
|
||||
import com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.SoftLinkable
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityBase
|
||||
import com.intellij.platform.workspace.storage.impl.WorkspaceEntityData
|
||||
import com.intellij.platform.workspace.storage.impl.indices.WorkspaceMutableIndex
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentation
|
||||
import com.intellij.platform.workspace.storage.instrumentation.EntityStorageInstrumentationApi
|
||||
import com.intellij.platform.workspace.storage.metadata.model.EntityMetadata
|
||||
@@ -177,7 +178,7 @@ internal class SimpleSymbolicIdEntityImpl(private val dataSource: SimpleSymbolic
|
||||
}
|
||||
|
||||
@OptIn(WorkspaceEntityInternalApi::class)
|
||||
internal class SimpleSymbolicIdEntityData : WorkspaceEntityData<SimpleSymbolicIdEntity>() {
|
||||
internal class SimpleSymbolicIdEntityData : WorkspaceEntityData<SimpleSymbolicIdEntity>(), SoftLinkable {
|
||||
var version: Int = 0
|
||||
lateinit var name: String
|
||||
lateinit var related: SimpleId
|
||||
@@ -188,6 +189,194 @@ internal class SimpleSymbolicIdEntityData : WorkspaceEntityData<SimpleSymbolicId
|
||||
internal fun isRelatedInitialized(): Boolean = ::related.isInitialized
|
||||
internal fun isSealedClassWithLinksInitialized(): Boolean = ::sealedClassWithLinks.isInitialized
|
||||
|
||||
override fun getLinks(): Set<SymbolicEntityId<*>> {
|
||||
val result = HashSet<SymbolicEntityId<*>>()
|
||||
result.add(related)
|
||||
val _sealedClassWithLinks = sealedClassWithLinks
|
||||
when (_sealedClassWithLinks) {
|
||||
is SealedClassWithLinks.Many -> {
|
||||
val __sealedClassWithLinks = _sealedClassWithLinks
|
||||
when (__sealedClassWithLinks) {
|
||||
is SealedClassWithLinks.Many.Ordered -> {
|
||||
for (item in __sealedClassWithLinks.list) {
|
||||
result.add(item)
|
||||
}
|
||||
}
|
||||
is SealedClassWithLinks.Many.Unordered -> {
|
||||
for (item in __sealedClassWithLinks.set) {
|
||||
result.add(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is SealedClassWithLinks.Nothing -> {
|
||||
}
|
||||
is SealedClassWithLinks.Single -> {
|
||||
result.add(_sealedClassWithLinks.id)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun index(index: WorkspaceMutableIndex<SymbolicEntityId<*>>) {
|
||||
index.index(this, related)
|
||||
val _sealedClassWithLinks = sealedClassWithLinks
|
||||
when (_sealedClassWithLinks) {
|
||||
is SealedClassWithLinks.Many -> {
|
||||
val __sealedClassWithLinks = _sealedClassWithLinks
|
||||
when (__sealedClassWithLinks) {
|
||||
is SealedClassWithLinks.Many.Ordered -> {
|
||||
for (item in __sealedClassWithLinks.list) {
|
||||
index.index(this, item)
|
||||
}
|
||||
}
|
||||
is SealedClassWithLinks.Many.Unordered -> {
|
||||
for (item in __sealedClassWithLinks.set) {
|
||||
index.index(this, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is SealedClassWithLinks.Nothing -> {
|
||||
}
|
||||
is SealedClassWithLinks.Single -> {
|
||||
index.index(this, _sealedClassWithLinks.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateLinksIndex(prev: Set<SymbolicEntityId<*>>, index: WorkspaceMutableIndex<SymbolicEntityId<*>>) {
|
||||
// TODO verify logic
|
||||
val mutablePreviousSet = HashSet(prev)
|
||||
val removedItem_related = mutablePreviousSet.remove(related)
|
||||
if (!removedItem_related) {
|
||||
index.index(this, related)
|
||||
}
|
||||
val _sealedClassWithLinks = sealedClassWithLinks
|
||||
when (_sealedClassWithLinks) {
|
||||
is SealedClassWithLinks.Many -> {
|
||||
val __sealedClassWithLinks = _sealedClassWithLinks
|
||||
when (__sealedClassWithLinks) {
|
||||
is SealedClassWithLinks.Many.Ordered -> {
|
||||
for (item in __sealedClassWithLinks.list) {
|
||||
val removedItem_item = mutablePreviousSet.remove(item)
|
||||
if (!removedItem_item) {
|
||||
index.index(this, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
is SealedClassWithLinks.Many.Unordered -> {
|
||||
for (item in __sealedClassWithLinks.set) {
|
||||
val removedItem_item = mutablePreviousSet.remove(item)
|
||||
if (!removedItem_item) {
|
||||
index.index(this, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is SealedClassWithLinks.Nothing -> {
|
||||
}
|
||||
is SealedClassWithLinks.Single -> {
|
||||
val removedItem__sealedClassWithLinks_id = mutablePreviousSet.remove(_sealedClassWithLinks.id)
|
||||
if (!removedItem__sealedClassWithLinks_id) {
|
||||
index.index(this, _sealedClassWithLinks.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
for (removed in mutablePreviousSet) {
|
||||
index.remove(this, removed)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateLink(oldLink: SymbolicEntityId<*>, newLink: SymbolicEntityId<*>): Boolean {
|
||||
var changed = false
|
||||
val related_data = if (related == oldLink) {
|
||||
changed = true
|
||||
newLink as SimpleId
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
if (related_data != null) {
|
||||
related = related_data
|
||||
}
|
||||
val _sealedClassWithLinks = sealedClassWithLinks
|
||||
val res_sealedClassWithLinks = when (_sealedClassWithLinks) {
|
||||
is SealedClassWithLinks.Many -> {
|
||||
val __sealedClassWithLinks = _sealedClassWithLinks
|
||||
val res__sealedClassWithLinks = when (__sealedClassWithLinks) {
|
||||
is SealedClassWithLinks.Many.Ordered -> {
|
||||
val __sealedClassWithLinks_list_data = __sealedClassWithLinks.list.map {
|
||||
val it_data = if (it == oldLink) {
|
||||
changed = true
|
||||
newLink as SimpleId
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
if (it_data != null) {
|
||||
it_data
|
||||
}
|
||||
else {
|
||||
it
|
||||
}
|
||||
}
|
||||
var __sealedClassWithLinks_data = __sealedClassWithLinks
|
||||
if (__sealedClassWithLinks_list_data != null) {
|
||||
__sealedClassWithLinks_data = __sealedClassWithLinks_data.copy(list = __sealedClassWithLinks_list_data)
|
||||
}
|
||||
__sealedClassWithLinks_data
|
||||
}
|
||||
is SealedClassWithLinks.Many.Unordered -> {
|
||||
val __sealedClassWithLinks_set_data = __sealedClassWithLinks.set.map {
|
||||
val it_data = if (it == oldLink) {
|
||||
changed = true
|
||||
newLink as SimpleId
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
if (it_data != null) {
|
||||
it_data
|
||||
}
|
||||
else {
|
||||
it
|
||||
}
|
||||
}
|
||||
var __sealedClassWithLinks_data = __sealedClassWithLinks
|
||||
if (__sealedClassWithLinks_set_data != null) {
|
||||
__sealedClassWithLinks_data = __sealedClassWithLinks_data.copy(set = __sealedClassWithLinks_set_data)
|
||||
}
|
||||
__sealedClassWithLinks_data
|
||||
}
|
||||
}
|
||||
res__sealedClassWithLinks
|
||||
}
|
||||
is SealedClassWithLinks.Nothing -> {
|
||||
_sealedClassWithLinks
|
||||
}
|
||||
is SealedClassWithLinks.Single -> {
|
||||
val _sealedClassWithLinks_id_data = if (_sealedClassWithLinks.id == oldLink) {
|
||||
changed = true
|
||||
newLink as SimpleId
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
var _sealedClassWithLinks_data = _sealedClassWithLinks
|
||||
if (_sealedClassWithLinks_id_data != null) {
|
||||
_sealedClassWithLinks_data = _sealedClassWithLinks_data.copy(id = _sealedClassWithLinks_id_data)
|
||||
}
|
||||
_sealedClassWithLinks_data
|
||||
}
|
||||
}
|
||||
if (res_sealedClassWithLinks != null) {
|
||||
sealedClassWithLinks = res_sealedClassWithLinks
|
||||
}
|
||||
return changed
|
||||
}
|
||||
|
||||
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<SimpleSymbolicIdEntity> {
|
||||
val modifiable = SimpleSymbolicIdEntityImpl.Builder(null)
|
||||
modifiable.diff = diff
|
||||
|
||||
+2
-5
@@ -1,8 +1,6 @@
|
||||
package com.intellij.workspaceModel.test.api
|
||||
|
||||
import com.intellij.platform.workspace.storage.annotations.Default
|
||||
import com.intellij.platform.workspace.storage.PersistentEntityId
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntity
|
||||
import com.intellij.platform.workspace.storage.SymbolicEntityId
|
||||
import com.intellij.platform.workspace.storage.WorkspaceEntityWithSymbolicId
|
||||
|
||||
interface SimpleSymbolicIdEntity : WorkspaceEntityWithSymbolicId {
|
||||
@@ -28,5 +26,4 @@ sealed class SealedClassWithLinks {
|
||||
data class Ordered(val list: List<SimpleId>) : Many()
|
||||
data class Unordered(val set: Set<SimpleId>) : Many()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+22
-19
@@ -8,6 +8,7 @@ import com.intellij.java.workspace.entities.JavaSourceRootPropertiesEntity
|
||||
import com.intellij.java.workspace.entities.javaSourceRoots
|
||||
import com.intellij.openapi.application.runWriteActionAndWait
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType
|
||||
import com.intellij.openapi.roots.ModifiableRootModel
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
@@ -46,8 +47,8 @@ import java.nio.file.Paths
|
||||
import kotlin.io.path.invariantSeparatorsPathString
|
||||
import kotlin.io.path.pathString
|
||||
|
||||
class AllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
private val LOG = logger<AllIntellijEntitiesGenerationTest>()
|
||||
abstract class AbstractAllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
private val LOG = logger<AbstractAllIntellijEntitiesGenerationTest>()
|
||||
|
||||
private val virtualFileManager = IdeVirtualFileUrlManagerImpl()
|
||||
|
||||
@@ -75,6 +76,7 @@ class AllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
override val testDataDirectory: File
|
||||
get() = File(IdeaTestExecutionPolicy.getHomePathWithPolicy())
|
||||
|
||||
// IJPL-895
|
||||
fun `_test generation of all entities in intellij codebase`() {
|
||||
executeEntitiesGeneration(::generateAndCompare)
|
||||
}
|
||||
@@ -148,8 +150,10 @@ class AllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
modulesToCheck.forEach { (moduleEntity, sourceRoot), pathToPackages ->
|
||||
val isTestModule = sourceRoot.rootTypeId == JAVA_TEST_ROOT_ENTITY_TYPE_ID
|
||||
|
||||
fun generateForSpecificModule(processAbstractTypes: Boolean, beforeGeneration: (ModifiableRootModel) -> Unit,
|
||||
afterGeneration: (ModifiableRootModel) -> Unit) {
|
||||
fun generateForSpecificModule(
|
||||
processAbstractTypes: Boolean, beforeGeneration: (ModifiableRootModel) -> Unit,
|
||||
afterGeneration: (ModifiableRootModel) -> Unit,
|
||||
) {
|
||||
runWriteActionAndWait {
|
||||
val modifiableModel = ModuleRootManager.getInstance(module).modifiableModel
|
||||
beforeGeneration(modifiableModel)
|
||||
@@ -165,11 +169,11 @@ class AllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
}
|
||||
|
||||
when (moduleEntity.name) {
|
||||
"intellij.platform.workspace.storage"-> {
|
||||
"intellij.platform.workspace.storage" -> {
|
||||
generateForSpecificModule(false, { modifiableModel -> removeWorkspaceStorageLibrary(modifiableModel) },
|
||||
{ modifiableModel -> addWorkspaceStorageLibrary(modifiableModel) })
|
||||
}
|
||||
"intellij.platform.workspace.jps"-> {
|
||||
"intellij.platform.workspace.jps" -> {
|
||||
generateForSpecificModule(false, { modifiableModel -> removeWorkspaceJpsEntitiesLibrary(modifiableModel) },
|
||||
{ modifiableModel -> addWorkspaceJpsEntitiesLibrary(modifiableModel) })
|
||||
}
|
||||
@@ -191,9 +195,9 @@ class AllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
addIntellijJavaLibrary(modifiableModel)
|
||||
addKotlinJpsCommonJar(modifiableModel)
|
||||
}, { modifiableModel ->
|
||||
removeIntellijJavaLibrary(modifiableModel)
|
||||
removeKotlinJpsCommonJar(modifiableModel)
|
||||
})
|
||||
removeIntellijJavaLibrary(modifiableModel)
|
||||
removeKotlinJpsCommonJar(modifiableModel)
|
||||
})
|
||||
}
|
||||
in modulesWithAbstractTypes -> {
|
||||
val projectModelUpdateResult = generationFunction(storage, moduleEntity, sourceRoot, pathToPackages, true, false, isTestModule)
|
||||
@@ -216,7 +220,7 @@ class AllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
storage: MutableEntityStorage, moduleEntity: ModuleEntity,
|
||||
sourceRoot: SourceRootEntity, pathToPackages: Set<String>,
|
||||
processAbstractTypes: Boolean, explicitApiEnabled: Boolean,
|
||||
isTestModule: Boolean
|
||||
isTestModule: Boolean,
|
||||
): Boolean {
|
||||
val relativize = Path.of(IdeaTestExecutionPolicy.getHomePathWithPolicy()).relativize(Path.of(sourceRoot.url.presentableUrl))
|
||||
myFixture.copyDirectoryToProject(relativize.invariantSeparatorsPathString, "")
|
||||
@@ -272,7 +276,7 @@ class AllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
storage: MutableEntityStorage, moduleEntity: ModuleEntity,
|
||||
sourceRoot: SourceRootEntity, pathToPackages: Set<String>,
|
||||
processAbstractTypes: Boolean, explicitApiEnabled: Boolean,
|
||||
isTestModule: Boolean
|
||||
isTestModule: Boolean,
|
||||
): Boolean {
|
||||
val genSourceRoots = sourceRoot.contentRoot.sourceRoots.flatMap { it.javaSourceRoots }.filter { it.generated }
|
||||
val relativize = Path.of(IdeaTestExecutionPolicy.getHomePathWithPolicy()).relativize(Path.of(sourceRoot.url.presentableUrl))
|
||||
@@ -314,7 +318,8 @@ class AllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
private fun setupCustomIndent(moduleEntity: ModuleEntity) {
|
||||
val indent = modulesWithCustomIndentSize[moduleEntity.name] ?: return
|
||||
val settings = CodeStyle.getSettings(project)
|
||||
val indentOptions = settings.getIndentOptions(KotlinFileType.INSTANCE)
|
||||
val kotlinFileType: LanguageFileType? = KotlinFileType.INSTANCE
|
||||
val indentOptions = settings.getIndentOptions(kotlinFileType)
|
||||
indentOptions.INDENT_SIZE = indent
|
||||
indentOptions.TAB_SIZE = indent
|
||||
indentOptions.CONTINUATION_INDENT_SIZE = indent
|
||||
@@ -323,7 +328,8 @@ class AllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
private fun resetCustomIndent(moduleEntity: ModuleEntity) {
|
||||
modulesWithCustomIndentSize[moduleEntity.name] ?: return
|
||||
val settings = CodeStyle.getSettings(project)
|
||||
val indentOptions = settings.getIndentOptions(KotlinFileType.INSTANCE)
|
||||
val kotlinFileType: LanguageFileType? = KotlinFileType.INSTANCE
|
||||
val indentOptions = settings.getIndentOptions(kotlinFileType)
|
||||
indentOptions.INDENT_SIZE = INDENT_SIZE
|
||||
indentOptions.TAB_SIZE = TAB_SIZE
|
||||
indentOptions.CONTINUATION_INDENT_SIZE = CONTINUATION_INDENT_SIZE
|
||||
@@ -348,14 +354,11 @@ class AllIntellijEntitiesGenerationTest : CodeGenerationTestBase() {
|
||||
return filter { path -> none { anotherPath -> anotherPath != path && anotherPath.isSubPathOf(path) } }
|
||||
}
|
||||
|
||||
private fun Path.isSubPathOf(anotherPath: Path): Boolean
|
||||
= anotherPath.startsWith(this)
|
||||
|
||||
|
||||
private fun Path.isSubPathOf(anotherPath: Path): Boolean = anotherPath.startsWith(this)
|
||||
|
||||
internal object TestErrorReporter : ErrorReporter {
|
||||
override fun reportError(message: String, file: VirtualFileUrl) {
|
||||
throw AssertionFailedError("Failed to load ${file.url}: $message")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+19
-4
@@ -2,11 +2,11 @@
|
||||
package com.intellij.devkit.workspaceModel
|
||||
|
||||
import com.intellij.openapi.application.ex.PathManagerEx
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import org.junit.jupiter.api.Assertions
|
||||
|
||||
class EntityCodeGenTest : CodeGenerationTestBase() {
|
||||
abstract class AbstractEntityCodeGenTest : CodeGenerationTestBase() {
|
||||
override val testDataDirectory: File
|
||||
get() = File(PathManagerEx.getCommunityHomePath() + "/plugins/devkit/intellij.devkit.workspaceModel/tests/testData/codeGen/$testDirectoryName")
|
||||
|
||||
@@ -39,6 +39,14 @@ class EntityCodeGenTest : CodeGenerationTestBase() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testEntityWithChildrenCollection() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testEntityWithDifferentChildrenTargets() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testRefsFromAnotherModule() {
|
||||
doTest()
|
||||
}
|
||||
@@ -63,6 +71,14 @@ class EntityCodeGenTest : CodeGenerationTestBase() {
|
||||
doTest(processAbstractTypes = true)
|
||||
}
|
||||
|
||||
fun testImports() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testPropertiesOrder() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testBothLinksAreParents() {
|
||||
doTestAndCheckErrorMessage("Both fields MainEntity#secondaryEntities and SecondaryEntity#mainEntity are marked as parent. Did you forget to add @Child annotation?")
|
||||
}
|
||||
@@ -97,8 +113,7 @@ class EntityCodeGenTest : CodeGenerationTestBase() {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private fun getExpectedDir(): Path {
|
||||
return testDataDirectory.toPath().resolve("after")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@
|
||||
- name: intellij.devkit.themes
|
||||
- name: intellij.devkit.uiDesigner
|
||||
- name: intellij.devkit.workspaceModel
|
||||
- name: intellij.devkit.workspaceModel.k1
|
||||
- name: intellij.devkit.workspaceModel.k2
|
||||
- name: intellij.kotlin.devkit
|
||||
- name: intellij.kotlin.devkit.k1
|
||||
- name: intellij.kotlin.devkit.k2
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
<module name="intellij.devkit.themes"/>
|
||||
<module name="intellij.devkit.uiDesigner"/>
|
||||
<module name="intellij.devkit.workspaceModel"/>
|
||||
<module name="intellij.devkit.workspaceModel.k1"/>
|
||||
<module name="intellij.devkit.workspaceModel.k2"/>
|
||||
<module name="intellij.kotlin.devkit"/>
|
||||
<module name="intellij.kotlin.devkit.k1"/>
|
||||
<module name="intellij.kotlin.devkit.k2"/>
|
||||
|
||||
Reference in New Issue
Block a user