mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
fix copyFrom and add test, use kotlin-friendly xml serializer to serialize component states
This commit is contained in:
@@ -20,9 +20,6 @@ import com.intellij.openapi.util.JDOMExternalizable
|
||||
import com.intellij.openapi.util.WriteExternalException
|
||||
import com.intellij.openapi.vfs.LargeFileWriteRequestor
|
||||
import com.intellij.openapi.vfs.SafeWriteRequestor
|
||||
import com.intellij.reference.SoftReference
|
||||
import com.intellij.util.xmlb.SkipDefaultsSerializationFilter
|
||||
import com.intellij.util.xmlb.XmlSerializer
|
||||
import org.jdom.Element
|
||||
|
||||
abstract class SaveSessionBase : StateStorage.SaveSession, StateStorage.ExternalizationSession, SafeWriteRequestor, LargeFileWriteRequestor {
|
||||
@@ -46,9 +43,8 @@ abstract class SaveSessionBase : StateStorage.SaveSession, StateStorage.External
|
||||
protected abstract fun setSerializedState(componentName: String, element: Element?)
|
||||
}
|
||||
|
||||
private val skipDefaultsSerializationFilter = ThreadLocal<SoftReference<SkipDefaultsSerializationFilter>>()
|
||||
|
||||
fun serializeState(state: Any): Element? {
|
||||
internal fun serializeState(state: Any): Element? {
|
||||
@Suppress("DEPRECATION")
|
||||
if (state is Element) {
|
||||
return state
|
||||
}
|
||||
@@ -58,11 +54,6 @@ fun serializeState(state: Any): Element? {
|
||||
return element
|
||||
}
|
||||
else {
|
||||
var serializationFilter = SoftReference.dereference(skipDefaultsSerializationFilter.get())
|
||||
if (serializationFilter == null) {
|
||||
serializationFilter = SkipDefaultsSerializationFilter()
|
||||
skipDefaultsSerializationFilter.set(SoftReference(serializationFilter))
|
||||
}
|
||||
return XmlSerializer.serializeIfNotDefault(state, serializationFilter)
|
||||
return state.serialize()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.configurationStore
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.PersistentStateComponent
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
import com.intellij.util.isEmpty
|
||||
import org.jdom.Element
|
||||
|
||||
abstract class StorageBaseEx<T : Any> : StateStorageBase<T>() {
|
||||
@@ -61,7 +62,7 @@ class StateGetter<S : Any, T : Any>(private val component: PersistentStateCompon
|
||||
}
|
||||
else {
|
||||
serializeState(stateAfterLoad)?.normalizeRootName().let {
|
||||
if (JDOMUtil.isEmpty(it)) null else it
|
||||
if (it.isEmpty()) null else it
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ internal class SchemeManagerTest {
|
||||
}
|
||||
|
||||
fun TestScheme.save(file: Path) {
|
||||
file.write(serialize().toByteArray())
|
||||
file.write(serialize()!!.toByteArray())
|
||||
}
|
||||
|
||||
@Test fun `different extensions`() {
|
||||
@@ -429,7 +429,7 @@ data class TestScheme(@field:com.intellij.util.xmlb.annotations.Attribute @field
|
||||
name = value
|
||||
}
|
||||
|
||||
override fun writeScheme() = serialize()
|
||||
override fun writeScheme() = serialize()!!
|
||||
}
|
||||
|
||||
open class TestSchemesProcessor : LazySchemeProcessor<TestScheme, TestScheme>() {
|
||||
|
||||
@@ -6,15 +6,17 @@ import com.intellij.util.loadElement
|
||||
import com.intellij.util.xmlb.annotations.Attribute
|
||||
import org.junit.Test
|
||||
|
||||
internal class AState : BaseState() {
|
||||
internal class AState(languageLevel: String? = null, nestedComplex: NestedState? = null) : BaseState() {
|
||||
@get:Attribute("customName")
|
||||
var languageLevel by storedProperty<String?>()
|
||||
var languageLevel by storedProperty<String?>(languageLevel)
|
||||
|
||||
var bar by string()
|
||||
|
||||
var property2 by storedProperty(0)
|
||||
|
||||
var floatProperty by storedProperty(0.3)
|
||||
|
||||
var nestedComplex by storedProperty<NestedState?>()
|
||||
var nestedComplex by storedProperty<NestedState?>(nestedComplex)
|
||||
}
|
||||
|
||||
internal class NestedState : BaseState() {
|
||||
@@ -37,6 +39,10 @@ class StoredPropertyStateTest {
|
||||
|
||||
assertThat(state).isNotEqualTo(AState())
|
||||
|
||||
val newEqualState = AState()
|
||||
newEqualState.languageLevel = String("foo".toCharArray())
|
||||
assertThat(state).isEqualTo(newEqualState)
|
||||
|
||||
assertThat(state.serialize()).isEqualTo("""<AState customName="foo" />""")
|
||||
assertThat(loadElement("""<AState customName="foo" />""").deserialize(AState::class.java).languageLevel).isEqualTo("foo")
|
||||
}
|
||||
@@ -57,5 +63,10 @@ class StoredPropertyStateTest {
|
||||
|
||||
state.languageLevel = null
|
||||
assertThat(state.modificationCount).isEqualTo(4)
|
||||
|
||||
state.copyFrom(AState("foo", nestedState))
|
||||
@Suppress("USELESS_CAST")
|
||||
assertThat(state.languageLevel as String?).isEqualTo("foo")
|
||||
assertThat(state.modificationCount).isEqualTo(5)
|
||||
}
|
||||
}
|
||||
@@ -242,7 +242,7 @@ internal class XmlSerializerTest {
|
||||
bean.INT_V = 987
|
||||
bean.STRING_V = "1234"
|
||||
|
||||
val element = bean.serialize()
|
||||
val element = bean.serialize()!!
|
||||
|
||||
val node = element.children.get(0)
|
||||
element.removeContent(node)
|
||||
@@ -660,8 +660,8 @@ internal class XmlSerializerTest {
|
||||
private val XML_PREFIX = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
|
||||
internal fun assertSerializer(bean: Any, expected: String, filter: SerializationFilter?, description: String = "Serialization failure"): Element {
|
||||
val element = bean.serialize(filter)
|
||||
var actual = JDOMUtil.writeElement(element, "\n").trim()
|
||||
val element = bean.serialize(filter, createElementIfEmpty = true)!!
|
||||
var actual = JDOMUtil.writeElement(element).trim()
|
||||
if (!expected.startsWith(XML_PREFIX) && actual.startsWith(XML_PREFIX)) {
|
||||
actual = actual.substring(XML_PREFIX.length).trim()
|
||||
}
|
||||
|
||||
+11
-12
@@ -3,32 +3,31 @@ package com.intellij.configurationStore.xml;
|
||||
import com.intellij.configurationStore.XmlSerializer;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.xmlb.SerializationFilter;
|
||||
import com.intellij.util.xmlb.annotations.Transient;
|
||||
import junit.framework.TestCase;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.intellij.testFramework.assertions.Assertions.assertThat;
|
||||
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public class XmlSerializerWithDefaultJDOMExternalizerCompatibilityTest extends TestCase {
|
||||
public void testCompatibility() throws Exception {
|
||||
final MyBean bean = new MyBean();
|
||||
assertCompatibleSerialization(bean, "MyBean");
|
||||
assertCompatibleSerialization(new MyBean());
|
||||
}
|
||||
|
||||
private static void assertCompatibleSerialization(final Object data, final String rootTagName) throws Exception {
|
||||
assertEquals(serializeWithJDom(data, rootTagName), serializeWithXmlSerializer(data));
|
||||
private static void assertCompatibleSerialization(final Object data) throws Exception {
|
||||
assertThat(serializeWithJDom(data)).isEqualTo(serializeWithXmlSerializer(data));
|
||||
}
|
||||
|
||||
private static String serializeWithXmlSerializer(final Object data) throws Exception {
|
||||
Element element = serialize(data, null);
|
||||
Element element = serialize(data);
|
||||
|
||||
String s = JDOMUtil.writeElement(element, "\n");
|
||||
return StringUtil.trimStart(s, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>").trim();
|
||||
}
|
||||
|
||||
private static String serializeWithJDom(final Object data, String rootTagName) throws Exception {
|
||||
final Element jDomRoot = new Element(rootTagName);
|
||||
private static String serializeWithJDom(final Object data) throws Exception {
|
||||
final Element jDomRoot = new Element("MyBean");
|
||||
|
||||
if (data instanceof com.intellij.openapi.util.JDOMExternalizable) {
|
||||
((com.intellij.openapi.util.JDOMExternalizable)data).writeExternal(jDomRoot);
|
||||
@@ -37,11 +36,11 @@ public class XmlSerializerWithDefaultJDOMExternalizerCompatibilityTest extends T
|
||||
com.intellij.openapi.util.DefaultJDOMExternalizer.writeExternal(data, jDomRoot);
|
||||
}
|
||||
|
||||
return JDOMUtil.writeElement(jDomRoot, "\n").trim();
|
||||
return JDOMUtil.writeElement(jDomRoot).trim();
|
||||
}
|
||||
|
||||
private static Element serialize(Object bean, @Nullable SerializationFilter filter) {
|
||||
return XmlSerializer.serialize(bean, filter);
|
||||
private static Element serialize(Object bean) {
|
||||
return XmlSerializer.serialize(bean, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@@ -20,23 +20,56 @@ import com.intellij.util.SmartList
|
||||
import com.intellij.util.xmlb.Accessor
|
||||
import com.intellij.util.xmlb.SerializationFilter
|
||||
import com.intellij.util.xmlb.annotations.Transient
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
abstract class BaseState : SerializationFilter, ModificationTracker {
|
||||
// if property value differs from default
|
||||
private val properties: MutableList<StoredProperty> = SmartList()
|
||||
|
||||
@Volatile
|
||||
internal var modificationCount: Long = 0
|
||||
@Transient
|
||||
@JvmField
|
||||
internal var ownModificationCount: Long = 0
|
||||
|
||||
// reset on load state
|
||||
fun resetModificationCount() {
|
||||
modificationCount = 0
|
||||
ownModificationCount = 0
|
||||
}
|
||||
|
||||
protected fun incrementModificationCount() {
|
||||
modificationCount++
|
||||
ownModificationCount++
|
||||
}
|
||||
|
||||
fun <T> storedProperty(defaultValue: T? = null): StoredPropertyBase<T?> {
|
||||
val result = ObjectStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty string is always normalized to null.
|
||||
*/
|
||||
fun string(defaultValue: String? = null): StoredPropertyBase<String?> {
|
||||
val result = NormalizedStringStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun storedProperty(defaultValue: Int = 0): StoredPropertyBase<Int> {
|
||||
val result = IntStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun storedProperty(defaultValue: Float = 0f): StoredPropertyBase<Float> {
|
||||
val result = FloatStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun storedProperty(defaultValue: Boolean = false): StoredPropertyBase<Boolean> {
|
||||
val result = ObjectStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
override fun accepts(accessor: Accessor, bean: Any): Boolean {
|
||||
@@ -48,42 +81,9 @@ abstract class BaseState : SerializationFilter, ModificationTracker {
|
||||
return false
|
||||
}
|
||||
|
||||
fun <T> storedProperty(defaultValue: T? = null): ReadWriteProperty<BaseState, T?> {
|
||||
val result = ObjectStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty string is always normalized to null.
|
||||
*/
|
||||
fun string(defaultValue: String? = null): ReadWriteProperty<BaseState, String?> {
|
||||
val result = StringStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun storedProperty(defaultValue: Int = 0): ReadWriteProperty<BaseState, Int> {
|
||||
val result = IntStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun storedProperty(defaultValue: Float = 0f): ReadWriteProperty<BaseState, Float> {
|
||||
val result = FloatStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun storedProperty(defaultValue: Boolean = false): ReadWriteProperty<BaseState, Boolean> {
|
||||
val result = ObjectStoredProperty(defaultValue)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
@Transient
|
||||
override fun getModificationCount(): Long {
|
||||
var result = modificationCount
|
||||
var result = ownModificationCount
|
||||
for (property in properties) {
|
||||
val value = property.value
|
||||
if (value is ModificationTracker) {
|
||||
@@ -112,8 +112,10 @@ abstract class BaseState : SerializationFilter, ModificationTracker {
|
||||
|
||||
fun copyFrom(state: BaseState) {
|
||||
assert(state.properties.size == properties.size)
|
||||
var changed = false
|
||||
for ((index, property) in properties.withIndex()) {
|
||||
val otherProperty = state.properties.get(index)
|
||||
//assert(otherProperty.name == property.name)
|
||||
if (property.name != null) {
|
||||
if (otherProperty.name == null) {
|
||||
otherProperty.name = property.name
|
||||
@@ -122,37 +124,30 @@ abstract class BaseState : SerializationFilter, ModificationTracker {
|
||||
assert(otherProperty.name == property.name)
|
||||
}
|
||||
}
|
||||
property.setValue(otherProperty)
|
||||
if (property.setValue(otherProperty)) {
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
incrementModificationCount()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal interface StoredProperty {
|
||||
val defaultValue: Any?
|
||||
val value: Any?
|
||||
|
||||
var name: String?
|
||||
|
||||
fun setValue(other: StoredProperty)
|
||||
}
|
||||
|
||||
private class ObjectStoredProperty<T>(override val defaultValue: T) : ReadWriteProperty<BaseState, T>, StoredProperty {
|
||||
private class ObjectStoredProperty<T>(override val defaultValue: T) : StoredPropertyBase<T>() {
|
||||
override var value = defaultValue
|
||||
override var name: String? = null
|
||||
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>): T {
|
||||
name = property.name
|
||||
return value
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: T) {
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, value: T) {
|
||||
name = property.name
|
||||
|
||||
if (value != newValue) {
|
||||
thisRef.modificationCount++
|
||||
|
||||
value = newValue
|
||||
if (this.value != value) {
|
||||
thisRef.ownModificationCount++
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,66 +155,71 @@ private class ObjectStoredProperty<T>(override val defaultValue: T) : ReadWriteP
|
||||
|
||||
override fun hashCode() = value?.hashCode() ?: 0
|
||||
|
||||
override fun toString() = if (value === defaultValue) "" else value?.toString() ?: super.toString()
|
||||
override fun toString() = if (value == defaultValue) "" else value?.toString() ?: super.toString()
|
||||
|
||||
override fun setValue(other: StoredProperty) {
|
||||
override fun setValue(other: StoredProperty): Boolean {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
value = (other as ObjectStoredProperty<T>).value
|
||||
val newValue = (other as ObjectStoredProperty<T>).value
|
||||
if (newValue == value) {
|
||||
return false
|
||||
}
|
||||
|
||||
value = newValue
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private class StringStoredProperty(override val defaultValue: String?) : ReadWriteProperty<BaseState, String?>, StoredProperty {
|
||||
private class NormalizedStringStoredProperty(override val defaultValue: String?) : StoredPropertyBase<String?>() {
|
||||
override var value = defaultValue
|
||||
override var name: String? = null
|
||||
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>): String? {
|
||||
name = property.name
|
||||
return value
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") _newValue: String?) {
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, value: String?) {
|
||||
name = property.name
|
||||
|
||||
var newValue = _newValue
|
||||
var newValue = value
|
||||
if (newValue != null && newValue.isEmpty()) {
|
||||
newValue = null
|
||||
}
|
||||
|
||||
if (value != newValue) {
|
||||
thisRef.modificationCount++
|
||||
value = newValue
|
||||
if (this.value != newValue) {
|
||||
thisRef.ownModificationCount++
|
||||
this.value = newValue
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?) = this === other || (other is StringStoredProperty && value == other.value)
|
||||
override fun equals(other: Any?) = this === other || (other is NormalizedStringStoredProperty && value == other.value)
|
||||
|
||||
override fun hashCode() = value?.hashCode() ?: 0
|
||||
|
||||
override fun toString() = if (value == defaultValue) "" else value ?: super.toString()
|
||||
|
||||
override fun setValue(other: StoredProperty) {
|
||||
value = (other as StringStoredProperty).value
|
||||
override fun setValue(other: StoredProperty): Boolean {
|
||||
val newValue = (other as NormalizedStringStoredProperty).value
|
||||
if (newValue == value) {
|
||||
return false
|
||||
}
|
||||
|
||||
value = newValue
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private class IntStoredProperty(override val defaultValue: Int) : ReadWriteProperty<BaseState, Int>, StoredProperty {
|
||||
private class IntStoredProperty(override val defaultValue: Int) : StoredPropertyBase<Int>() {
|
||||
override var value = defaultValue
|
||||
override var name: String? = null
|
||||
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>): Int {
|
||||
name = property.name
|
||||
return value
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: Int) {
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, value: Int) {
|
||||
name = property.name
|
||||
|
||||
if (value != newValue) {
|
||||
thisRef.modificationCount++
|
||||
|
||||
value = newValue
|
||||
if (this.value != value) {
|
||||
thisRef.ownModificationCount++
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,28 +229,30 @@ private class IntStoredProperty(override val defaultValue: Int) : ReadWritePrope
|
||||
|
||||
override fun toString() = if (value == defaultValue) "" else value.toString()
|
||||
|
||||
override fun setValue(other: StoredProperty) {
|
||||
value = (other as IntStoredProperty).value
|
||||
override fun setValue(other: StoredProperty): Boolean {
|
||||
val newValue = (other as IntStoredProperty).value
|
||||
if (newValue == value) {
|
||||
return false
|
||||
}
|
||||
|
||||
value = newValue
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private class FloatStoredProperty(override val defaultValue: Float) : ReadWriteProperty<BaseState, Float>, StoredProperty {
|
||||
private class FloatStoredProperty(override val defaultValue: Float) : StoredPropertyBase<Float>() {
|
||||
override var value = defaultValue
|
||||
override var name: String? = null
|
||||
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>): Float {
|
||||
name = property.name
|
||||
return value
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") newValue: Float) {
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, value: Float) {
|
||||
name = property.name
|
||||
|
||||
if (value != newValue) {
|
||||
thisRef.modificationCount++
|
||||
|
||||
value = newValue
|
||||
if (this.value != value) {
|
||||
thisRef.ownModificationCount++
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +262,13 @@ private class FloatStoredProperty(override val defaultValue: Float) : ReadWriteP
|
||||
|
||||
override fun toString() = if (value == defaultValue) "" else value.toString()
|
||||
|
||||
override fun setValue(other: StoredProperty) {
|
||||
value = (other as FloatStoredProperty).value
|
||||
override fun setValue(other: StoredProperty): Boolean {
|
||||
val newValue = (other as FloatStoredProperty).value
|
||||
if (newValue == value) {
|
||||
return false
|
||||
}
|
||||
|
||||
value = newValue
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.components
|
||||
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
|
||||
internal interface StoredProperty {
|
||||
val defaultValue: Any?
|
||||
val value: Any?
|
||||
|
||||
var name: String?
|
||||
|
||||
// true if changed
|
||||
fun setValue(other: StoredProperty): Boolean
|
||||
}
|
||||
|
||||
// type must be exposed otherwise `provideDelegate` doesn't work
|
||||
abstract class StoredPropertyBase<T> : ReadWriteProperty<BaseState, T>, StoredProperty {
|
||||
override final var name: String? = null
|
||||
|
||||
// operator fun provideDelegate(thisRef: Any, property: KProperty<*>): ReadWriteProperty<BaseState, T> {
|
||||
// name = property.name
|
||||
// return this
|
||||
// }
|
||||
}
|
||||
@@ -34,14 +34,25 @@ import kotlin.concurrent.write
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.primaryConstructor
|
||||
|
||||
private val skipDefaultsSerializationFilter = ThreadLocal<SoftReference<SkipDefaultsSerializationFilter>>()
|
||||
|
||||
private fun getDefaultSerializationFilter(): SkipDefaultsSerializationFilter {
|
||||
var result = SoftReference.dereference(skipDefaultsSerializationFilter.get())
|
||||
if (result == null) {
|
||||
result = SkipDefaultsSerializationFilter()
|
||||
skipDefaultsSerializationFilter.set(SoftReference(result))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun <T : Any> T.serialize(filter: SerializationFilter? = SkipDefaultsSerializationFilter()): Element {
|
||||
fun <T : Any> T.serialize(filter: SerializationFilter? = getDefaultSerializationFilter(), createElementIfEmpty: Boolean = false): Element? {
|
||||
try {
|
||||
val clazz = javaClass
|
||||
val binding = serializer.getClassBinding(clazz)
|
||||
return if (binding is BeanBinding) {
|
||||
// top level expects not null (null indicates error, empty element will be omitted)
|
||||
binding.serialize(this, true, filter)
|
||||
binding.serialize(this, createElementIfEmpty, filter)
|
||||
}
|
||||
else {
|
||||
binding.serialize(this, null, filter) as Element
|
||||
|
||||
@@ -42,7 +42,7 @@ class LoadTest : IcsTestCase() {
|
||||
|
||||
@Test fun `load scheme`() {
|
||||
val localScheme = TestScheme("local")
|
||||
provider.write("$dirName/local.xml", localScheme.serialize().toByteArray())
|
||||
provider.write("$dirName/local.xml", localScheme.serialize()!!.toByteArray())
|
||||
|
||||
val schemeManager = createSchemeManager(dirName)
|
||||
schemeManager.loadSchemes()
|
||||
@@ -58,8 +58,8 @@ class LoadTest : IcsTestCase() {
|
||||
|
||||
assertThat(dirPath).doesNotExist()
|
||||
|
||||
provider.write("$dirName/local1.xml", TestScheme("local1").serialize().toByteArray())
|
||||
provider.write("$dirName/local2.xml", TestScheme("local2").serialize().toByteArray())
|
||||
provider.write("$dirName/local1.xml", TestScheme("local1").serialize()!!.toByteArray())
|
||||
provider.write("$dirName/local2.xml", TestScheme("local2").serialize()!!.toByteArray())
|
||||
|
||||
assertThat(dirPath.resolve("local1.xml")).isRegularFile()
|
||||
assertThat(dirPath.resolve("local2.xml")).isRegularFile()
|
||||
@@ -74,7 +74,7 @@ class LoadTest : IcsTestCase() {
|
||||
|
||||
@Test fun `load scheme with the same names`() {
|
||||
val localScheme = TestScheme("local")
|
||||
val data = localScheme.serialize().toByteArray()
|
||||
val data = localScheme.serialize()!!.toByteArray()
|
||||
provider.write("$dirName/local.xml", data)
|
||||
provider.write("$dirName/local2.xml", data)
|
||||
|
||||
@@ -86,12 +86,12 @@ class LoadTest : IcsTestCase() {
|
||||
@Test fun `load scheme from repo and read-only repo`() {
|
||||
val localScheme = TestScheme("local")
|
||||
|
||||
provider.write("$dirName/local.xml", localScheme.serialize().toByteArray())
|
||||
provider.write("$dirName/local.xml", localScheme.serialize()!!.toByteArray())
|
||||
|
||||
val remoteScheme = TestScheme("remote")
|
||||
val remoteRepository = tempDirManager.createRepository()
|
||||
remoteRepository
|
||||
.add("$dirName/Mac OS X from RubyMine.xml", remoteScheme.serialize().toByteArray())
|
||||
.add("$dirName/Mac OS X from RubyMine.xml", remoteScheme.serialize()!!.toByteArray())
|
||||
.commit("")
|
||||
|
||||
remoteRepository.useAsReadOnlySource {
|
||||
@@ -114,12 +114,12 @@ class LoadTest : IcsTestCase() {
|
||||
val schemeName = "Emacs"
|
||||
val localScheme = TestScheme(schemeName, "local")
|
||||
|
||||
provider.write("$dirName/$schemeName.xml", localScheme.serialize().toByteArray())
|
||||
provider.write("$dirName/$schemeName.xml", localScheme.serialize()!!.toByteArray())
|
||||
|
||||
val remoteScheme = TestScheme(schemeName, "remote")
|
||||
val remoteRepository = tempDirManager.createRepository("remote")
|
||||
remoteRepository
|
||||
.add("$dirName/$schemeName.xml", remoteScheme.serialize().toByteArray())
|
||||
.add("$dirName/$schemeName.xml", remoteScheme.serialize()!!.toByteArray())
|
||||
.commit("")
|
||||
|
||||
remoteRepository.useAsReadOnlySource {
|
||||
|
||||
Reference in New Issue
Block a user