diff --git a/platform/configuration-store-impl/testSrc/StoredPropertyStateTest.kt b/platform/configuration-store-impl/testSrc/StoredPropertyStateTest.kt index 138d03868c51..0513b79320de 100644 --- a/platform/configuration-store-impl/testSrc/StoredPropertyStateTest.kt +++ b/platform/configuration-store-impl/testSrc/StoredPropertyStateTest.kt @@ -3,20 +3,21 @@ package com.intellij.configurationStore import com.intellij.openapi.components.BaseState import com.intellij.testFramework.assertions.Assertions.assertThat import com.intellij.util.loadElement -import com.intellij.util.xmlb.XmlSerializer import com.intellij.util.xmlb.annotations.Attribute import org.junit.Test -private class AState : BaseState() { +internal class AState : BaseState() { @get:Attribute("customName") var languageLevel by storedProperty() var property2 by storedProperty(0) + var floatProperty by storedProperty(0.3) + var nestedComplex by storedProperty() } -private class NestedState : BaseState() { +internal class NestedState : BaseState() { var childProperty by storedProperty() } @@ -36,7 +37,7 @@ class StoredPropertyStateTest { assertThat(state).isNotEqualTo(AState()) - assertThat(XmlSerializer.serialize(state)).isEqualTo("""""") + assertThat(state.serialize()).isEqualTo("""""") assertThat(loadElement("""""").deserialize(AState::class.java).languageLevel).isEqualTo("foo") } diff --git a/platform/configuration-store-impl/testSrc/xml/KotlinXmlSerializerTest.kt b/platform/configuration-store-impl/testSrc/xml/KotlinXmlSerializerTest.kt index c3adb349e467..9c808d14a779 100644 --- a/platform/configuration-store-impl/testSrc/xml/KotlinXmlSerializerTest.kt +++ b/platform/configuration-store-impl/testSrc/xml/KotlinXmlSerializerTest.kt @@ -15,6 +15,7 @@ */ package com.intellij.configurationStore.xml +import com.intellij.configurationStore.AState import com.intellij.configurationStore.deserialize import com.intellij.util.loadElement import com.intellij.util.xmlb.annotations.MapAnnotation @@ -38,6 +39,16 @@ class KotlinXmlSerializerTest { """, data) } + @Test fun floatProperty() { + val state = AState() + state.floatProperty = 3.4 + doSerializerTest(""" + + + """, state) + } + @Test fun nullInMap() { @Tag("bean") class Foo { diff --git a/platform/configuration-store-impl/testSrc/xml/XmlSerializerTest.kt b/platform/configuration-store-impl/testSrc/xml/XmlSerializerTest.kt index e4f867286a43..b825be8c8370 100644 --- a/platform/configuration-store-impl/testSrc/xml/XmlSerializerTest.kt +++ b/platform/configuration-store-impl/testSrc/xml/XmlSerializerTest.kt @@ -15,6 +15,7 @@ */ package com.intellij.configurationStore.xml +import com.intellij.configurationStore.StoredPropertyStateTest import com.intellij.configurationStore.deserialize import com.intellij.configurationStore.serialize import com.intellij.openapi.util.JDOMUtil @@ -39,6 +40,7 @@ import java.util.* XmlSerializerTest::class, XmlSerializerMapTest::class, XmlSerializerCollectionTest::class, + StoredPropertyStateTest::class, KotlinXmlSerializerTest::class ) class XmlSerializerTestSuite diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/StoredProperty.kt b/platform/projectModel-api/src/com/intellij/openapi/components/StoredProperty.kt index bf3e6c089242..dbf9f7437faa 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/StoredProperty.kt +++ b/platform/projectModel-api/src/com/intellij/openapi/components/StoredProperty.kt @@ -24,7 +24,7 @@ import kotlin.reflect.KProperty abstract class BaseState : SerializationFilter, ModificationTracker { // if property value differs from default - private val properties: MutableList> = SmartList() + private val properties: MutableList = SmartList() @Volatile internal var modificationCount: Long = 0 @@ -47,25 +47,25 @@ abstract class BaseState : SerializationFilter, ModificationTracker { } fun storedProperty(defaultValue: T? = null): ReadWriteProperty { - val result = StoredProperty(defaultValue) + val result = ObjectStoredProperty(defaultValue) properties.add(result) return result } fun storedProperty(defaultValue: Int = 0): ReadWriteProperty { - val result = StoredProperty(defaultValue) + val result = IntStoredProperty(defaultValue) properties.add(result) return result } fun storedProperty(defaultValue: Float = 0f): ReadWriteProperty { - val result = StoredProperty(defaultValue) + val result = FloatStoredProperty(defaultValue) properties.add(result) return result } fun storedProperty(defaultValue: Boolean = false): ReadWriteProperty { - val result = StoredProperty(defaultValue) + val result = ObjectStoredProperty(defaultValue) properties.add(result) return result } @@ -99,9 +99,16 @@ abstract class BaseState : SerializationFilter, ModificationTracker { } } -internal class StoredProperty(internal val defaultValue: T) : ReadWriteProperty { - internal var value = defaultValue - internal var name: String? = null +internal interface StoredProperty { + val defaultValue: Any? + val value: Any? + + val name: String? +} + +private class ObjectStoredProperty(override val defaultValue: T) : ReadWriteProperty, StoredProperty { + override var value = defaultValue + override var name: String? = null override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value @@ -115,9 +122,55 @@ internal class StoredProperty(internal val defaultValue: T) : ReadWriteProper } } - override fun equals(other: Any?) = this === other || (other is StoredProperty<*> && value == other.value) + override fun equals(other: Any?) = this === other || (other is ObjectStoredProperty<*> && value == other.value) override fun hashCode() = value?.hashCode() ?: 0 override fun toString() = if (value === defaultValue) "" else value?.toString() ?: super.toString() +} + +private class IntStoredProperty(override val defaultValue: Int) : ReadWriteProperty, StoredProperty { + override var value = defaultValue + override var name: String? = null + + override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value + + @Suppress("UNCHECKED_CAST") + override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: Int) { + if (value != newValue) { + thisRef.modificationCount++ + + name = property.name + value = newValue + } + } + + override fun equals(other: Any?) = this === other || (other is IntStoredProperty && value == other.value) + + override fun hashCode() = value.hashCode() + + override fun toString() = if (value == defaultValue) "" else value.toString() +} + +private class FloatStoredProperty(override val defaultValue: Float) : ReadWriteProperty, StoredProperty { + override var value = defaultValue + override var name: String? = null + + override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value + + @Suppress("UNCHECKED_CAST") + override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: Float) { + if (value != newValue) { + thisRef.modificationCount++ + + name = property.name + value = newValue + } + } + + override fun equals(other: Any?) = this === other || (other is FloatStoredProperty && value == other.value) + + override fun hashCode() = value.hashCode() + + override fun toString() = if (value == defaultValue) "" else value.toString() } \ No newline at end of file