IntelliJ does not serialize nested objects' properties of PersistentStateComponent subclass

27 Views Asked by At

This is how my custom PersistentStateComponent subclass looks like:

@State(name = "Configurations", storages = [Storage("conf.xml")])
@Service(Service.Level.PROJECT)
class CustomConfigurationService : PersistentStateComponent<CustomConfigurationService> {

    var configurations = Configurations()

    override fun getState() = this

    override fun loadState(service: CustomConfigurationService) {
        XmlSerializerUtil.copyBean(service, this)
    }

    // ...
}
data class Configurations(
    val aBoolean: Boolean = false,
    val aString: String? = null,
    val anotherString: String? = null
)

This is how the configurations are stored (after being changed via the UI):

<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="Configurations">
    <option name="configurations">
      <Configurations />
    </option>
  </component>
</project>

If I change the super type to PersistentStateComponent<Configurations>, the file is not created at all.

Why doesn't IntelliJ serialize the Configurations object's properties as well? What can I do, other than placing Configurations's properties directly inside CustomConfigurationService?

1

There are 1 best solutions below

0
InSync On BEST ANSWER

It turns out that I was terribly misguided. Here's how the final code looks like:

import com.intellij.openapi.components.BaseState

class Configurations : BaseState() {
    // property() and string() are BaseState methods
    var aBoolean by property(false)
    var aString by string(null)
    var anotherString by string(null)
}
import com.intellij.openapi.components.SimplePersistentStateComponent
import com.intellij.util.xmlb.XmlSerializerUtil

@State(name = "Configurations", storages = [Storage("conf.xml")])
@Service(Service.Level.PROJECT)
class CustomConfigurationService :
    // This takes care of everything else and gives us a .state property
    SimplePersistentStateComponent<Configurations>(Configurations()) {

    // ...which I shadow using this other property.
    override var configurations: Configurations
        get() = state
        set(value) = XmlSerializerUtil.copyBean(value, state)
    
    companion object {
        fun getInstance() = service<ConfigurationService>()
    }

}

conf.xml's contents eventually looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="Configurations">
    <option name="aBoolean" value="true" />
    <option name="aString" value="Foobar">
  </component>
</project>