State

abstract class State(source)

A state holds variables that can be configured, validated, copied, and loaded.

In a State, fields are typically mutable, because the user can change the field. However, fields that themselves also contain data (e.g. a Collection or a DecoratorScheme) should be stored as immutable references (but may themselves be mutable). For example, instead of having the field var list: List<String>, a State should have the field val list: MutableList<String>. This reflects the typical case in which the user does not change the reference to the object, but changes the properties inside the object. And, more importantly, means that nested a SchemeEditor can share a single unchanging reference to a State with its nested SchemeEditors.

Properties should be annotated with Transient (not kotlin.jvm.Transient) to ensure they are not stored. The specifics of how the annotation is applied and inherited are complicated. The following rules apply:

  • Immutable non-Collections (e.g. val foo: Int or val bar: State) are not serialized. These properties should not be annotated, not even "just in case" nor "for clarity".

  • Immutable Collections (e.g. val foo: List<Int> or val bar: List<State>) are not serialized, unless annotated with a serialization annotation such as com.intellij.util.xmlb.annotations.XCollection or com.intellij.util.xmlb.annotations.OptionTag.

  • Mutable properties (i.e. var) are serialized, unless annotated with Transient.

  • Do not combine Transient with any other serialization annotations.

  • To annotate a mutable property (i.e. var), use @get:Transient.

  • To annotate a lateinit property (i.e. lateinit var), use both @field:Transient and @get:Transient.

  • When a property overrides a property from a superclass, only the annotations in the subclass are relevant.

  • Since abstract properties must always be overridden, they should be annotated only in the subclass. Adding additional annotations "for clarity" in a superclass should be avoided, since it is completely useless and therefore misleading.

  • Since open properties are not always overridden, if they are annotated, they should be annotated in both the superclass and the subclass.

  • See also isSerialized in StateReflection in Randomness' test module.

These observations are based on IntelliJ Community 2024.1. See also the bug report at IJPL-175868.

Inheritors

Constructors

Link copied to clipboard
constructor()

Properties

Link copied to clipboard

The context of this state in the form of a reference to the Settings.

Link copied to clipboard
var uuid: String

A UUID to uniquely track this scheme even when it is copied.

Link copied to clipboard
open val validators: List<Validator<*>>

Lists the Validators relevant to this State.

Functions

Link copied to clipboard
open fun applyContext(context: Box<Settings>)

Sets the State.context of this State to context.

fun applyContext(context: Settings)

Sets the State.context of this State to be a reference to context.

Link copied to clipboard
abstract fun deepCopy(retainUuid: Boolean = false): State

Returns a deep copy, retaining the uuid if and only if retainUuid is true.

Link copied to clipboard
protected fun <SELF : State> SELF.deepCopyTransient(retainUuid: Boolean): SELF

When invoked by the instance this on (another) instance self as self.deepCopyTransient(), this method copies Transient fields from this to self, and returns self.

Link copied to clipboard

Validates the state, and indicates whether and why it is invalid.

Link copied to clipboard
fun State.validators(body: ValidatorDsl.() -> Unit): List<Validator<*>>

Initiates the ValidatorDsl on this State, and returns all Validators that were created inside the DSL using the DSL's own functions.