From 0b555e8b56fff6238c8ea4d31d52fdcda8859b86 Mon Sep 17 00:00:00 2001 From: Nikolay Chashnikov Date: Tue, 28 Nov 2023 12:13:48 +0100 Subject: [PATCH] [configuration store] fix updating component state from stream provider if it was removed In the previous version, if 'updatedFromStreamProvider' is firstly called when the element cannot be loaded (e.g., because its file is empty, such a situation reproduced in RemoteDevConfigShareTest, see CWM-8547), it stored 'null' in 'storageDataRef', and then 'updatedFromStreamProvider' is called again and now the element is loaded, it did nothing, so configuration of the component wasn't updated. GitOrigin-RevId: 65636a3e984a9416c1a9e532328aac5f3cc9d0c2 --- .../src/XmlElementStorage.kt | 2 +- .../testSrc/ApplicationStoreTest.kt | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/platform/configuration-store-impl/src/XmlElementStorage.kt b/platform/configuration-store-impl/src/XmlElementStorage.kt index 96527ca7b771..ff0e5c445c4e 100644 --- a/platform/configuration-store-impl/src/XmlElementStorage.kt +++ b/platform/configuration-store-impl/src/XmlElementStorage.kt @@ -208,7 +208,7 @@ abstract class XmlElementStorage protected constructor(val fileSpec: String, // if data was loaded, mark as changed all loaded components if (states != null) { changedComponentNames.addAll(states.keys()) - setStates(oldStorageData = states, newStorageData = null) + setStates(oldStorageData = states, newStorageData = StateMap.EMPTY) } } else if (states != null) { diff --git a/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt b/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt index 37a1d69ed2cd..e4435b1515b9 100644 --- a/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt @@ -12,6 +12,7 @@ import com.intellij.serviceContainer.ComponentManagerImpl import com.intellij.testFramework.* import com.intellij.testFramework.assertions.Assertions.assertThat import com.intellij.testFramework.rules.InMemoryFsRule +import com.intellij.util.io.delete import com.intellij.util.io.write import com.intellij.util.xmlb.XmlSerializerUtil import com.intellij.util.xmlb.annotations.Attribute @@ -512,6 +513,34 @@ internal class ApplicationStoreTest { assertTrue("New old.xml without os prefix not found", testAppConfig.resolve("old.xml").exists()) } + @Test + fun `reload components`() { + @State(name = "A", storages = [Storage(value = "a.xml")]) + class Comp : FooComponent() + + val component = Comp() + componentStore.initComponent(component, null, null) + + writeConfig("a.xml", "") + componentStore.reloadComponents(changedFileSpecs = listOf("a.xml"), deletedFileSpecs = emptyList()) + assertEquals("defaultValue", component.foo) + + writeConfig("a.xml", createComponentFileContent("initial")) + componentStore.reloadComponents(changedFileSpecs = listOf("a.xml"), deletedFileSpecs = emptyList()) + assertEquals("initial", component.foo) + + writeConfig("a.xml", createComponentFileContent("changed")) + componentStore.reloadComponents(changedFileSpecs = listOf("a.xml"), deletedFileSpecs = emptyList()) + assertEquals("changed", component.foo) + + testAppConfig.resolve("a.xml").delete() + componentStore.reloadComponents(changedFileSpecs = emptyList(), deletedFileSpecs = listOf("a.xml")) + assertEquals("defaultValue", component.foo) + } + + private fun createComponentFileContent(fooValue: String, componentName: String = "A") = + """${createComponentData(fooValue, componentName)}""" + @State(name = "A", storages = [Storage(value = "per-os.xml", roamingType = RoamingType.PER_OS)]) private class PerOsComponent : FooComponent()