Seamless Support for PersistenceStateComponent
The new Settings Controller API is currently not intended for use by end clients. All existing implementations of PersistenceStateComponent
that don't use the deprecated API JDOMExternalizable
are fully supported, and no changes are required. Support here means that each component property serves as a key, not the whole component.
Each field of a state class is represented by a key. The value is stored in a unified format (see below), rather than in XML as found in regular storage files.
Only top-level fields serve as keys. In this example, TextDiffSettings.SHARED_SETTINGS
is the key. What if you want to control only CONTEXT_RANGE
? To avoid a complicated API, nested beans are not supported. That's why a unified format was introduced. This format allows you to work with values in a uniform way using the convenient kotlinx serialization API.
The XML value above in unified format will be a JSON:
A unified format provides a robust and straightforward method to decompose values and manage sub-values, if necessary. This approach helps avoid dealing with multiple representations of the same data.
Unified Format
The Settings Controller operates with values in a unified format, where each value is a JsonElement. Please note that the corresponding API is advanced and experimental, and the JsonElement
API may be changed in the future.
For primitive values (no binding or binding plus converter, meaning effectively is a string): "a string"
, number
, boolean
. In other words, a string is quoted with double quotes and other primitive values as is (JSON syntax).
For complex values (binding exists), like
map (
MapBinding
),collection (
CollectionBinding
),bean (
BeanBinding
andKotlinAwareBeanBinding
, aboutKotlinxSerializationBinding
see note about custom bindings),
also a JSON syntax is used.
Maps
If a map has a complex key, then it is an array of objects, with each object representing a single key-value pair:
Maps with non-primitive keys are expected to be rare. Currently, SettingDescriptor
lacks tags which could be used to distinguish formats or provide format details. These could be added if necessary.
Collections
For polymorphic collections, a special key _class
is used as a class discriminator.
Custom Binding
A value for a custom binding is a black box, yet it remains a valid JSON.
KotlinxSerializationBinding
is currently serialized as JSON using a kotlinx serialization framework. This binding is experimental and has never been recommended for non-cache data.JDOMElementBinding
is serialized as a JSON. It is deprecated and is expected to be rare.
Under the Hood
How is it possible, and how is it implemented? To understand the explanation, there are several key things you need to know:
Historically, the IntelliJ Platform uses its own serialization framework.
The
PersistenceStateComponent
has always been recommended to be implemented using state classes, rather than directly using XML DOM.
Thus, if you have XML data and a state class, you can employ the XML serialization framework to interact with the object at a property level.
You can find example in StateStorageBackedByController.
In a nutshell:
State class it is a BeanBinding.
Each bean binding consists of a list of NestedBinding. It is a property.
BeanBinding.serializeProperty
to serialize.BeanBinding.deserializeInto
to deserialize.
Please note that this API is internal and low-level. It requires a profound understanding of the IntelliJ Platform. It may not be as straightforward as it sounds. Therefore, its use outside the IJ Platform is strongly discouraged.