Refactoring properties collection after review

This commit is contained in:
Ilya Chernikov
2018-08-16 18:55:31 +02:00
parent 74f8a541c0
commit 04ffe7754e
22 changed files with 225 additions and 198 deletions
@@ -9,45 +9,52 @@ package kotlin.script.experimental.api
import kotlin.script.experimental.util.PropertiesCollection
interface ScriptCompileConfiguration : PropertiesCollection {
interface ScriptCompileConfigurationKeys
class ScriptCompileConfiguration(baseConfigurations: Iterable<ScriptCompileConfiguration>, body: Builder.() -> Unit) :
PropertiesCollection(Builder(baseConfigurations).apply(body).data) {
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
constructor(
vararg baseConfigurations: ScriptCompileConfiguration, body: Builder.() -> Unit = {}
) : this(baseConfigurations.asIterable(), body)
class Builder internal constructor(baseConfigurations: Iterable<ScriptCompileConfiguration>) :
ScriptCompileConfigurationKeys,
PropertiesCollection.Builder(baseConfigurations)
companion object : ScriptCompileConfiguration {
class Builder internal constructor() : PropertiesCollection.Builder(), ScriptCompileConfiguration {
override val properties = data
}
fun create(body: Builder.() -> Unit): ScriptCompileConfiguration = Builder().apply(body)
}
companion object : ScriptCompileConfigurationKeys
}
val ScriptCompileConfiguration.sourceFragments by PropertiesCollection.key<List<ScriptSourceNamedFragment>>()
val ScriptCompileConfigurationKeys.sourceFragments by PropertiesCollection.key<List<ScriptSourceNamedFragment>>()
val ScriptCompileConfiguration.scriptBodyTarget by PropertiesCollection.keyCopy(ScriptDefinition.scriptBodyTarget)
val ScriptCompileConfigurationKeys.scriptBodyTarget by PropertiesCollection.keyCopy(ScriptDefinition.scriptBodyTarget)
val ScriptCompileConfiguration.scriptImplicitReceivers by PropertiesCollection.keyCopy(ScriptDefinition.scriptImplicitReceivers)
val ScriptCompileConfigurationKeys.scriptImplicitReceivers by PropertiesCollection.keyCopy(ScriptDefinition.scriptImplicitReceivers)
val ScriptCompileConfiguration.contextVariables by PropertiesCollection.keyCopy(ScriptDefinition.contextVariables)
val ScriptCompileConfigurationKeys.contextVariables by PropertiesCollection.keyCopy(ScriptDefinition.contextVariables)
val ScriptCompileConfiguration.defaultImports by PropertiesCollection.keyCopy(ScriptDefinition.defaultImports)
val ScriptCompileConfigurationKeys.defaultImports by PropertiesCollection.keyCopy(ScriptDefinition.defaultImports)
val ScriptCompileConfiguration.restrictions by PropertiesCollection.keyCopy(ScriptDefinition.restrictions)
val ScriptCompileConfigurationKeys.restrictions by PropertiesCollection.keyCopy(ScriptDefinition.restrictions)
val ScriptCompileConfiguration.importedScripts by PropertiesCollection.keyCopy(ScriptDefinition.importedScripts)
val ScriptCompileConfigurationKeys.importedScripts by PropertiesCollection.keyCopy(ScriptDefinition.importedScripts)
val ScriptCompileConfiguration.dependencies by PropertiesCollection.keyCopy(ScriptDefinition.dependencies)
val ScriptCompileConfigurationKeys.dependencies by PropertiesCollection.keyCopy(ScriptDefinition.dependencies)
val ScriptCompileConfiguration.compilerOptions by PropertiesCollection.keyCopy(ScriptDefinition.compilerOptions)
val ScriptCompileConfigurationKeys.compilerOptions by PropertiesCollection.keyCopy(ScriptDefinition.compilerOptions)
interface ProcessedScriptData : PropertiesCollection {
interface ProcessedScriptDataKeys
companion object : ProcessedScriptData
class ProcessedScriptData(properties: Map<PropertiesCollection.Key<*>, Any>) : PropertiesCollection(properties) {
companion object : ProcessedScriptDataKeys
}
val ProcessedScriptData.foundAnnotations by PropertiesCollection.key<List<Annotation>>()
val ProcessedScriptDataKeys.foundAnnotations by PropertiesCollection.key<List<Annotation>>()
val ProcessedScriptData.foundFragments by PropertiesCollection.key<List<ScriptSourceNamedFragment>>()
val ProcessedScriptDataKeys.foundFragments by PropertiesCollection.key<List<ScriptSourceNamedFragment>>()
interface RefineScriptCompilationConfigurationHandler {
@@ -10,57 +10,62 @@ package kotlin.script.experimental.api
import kotlin.reflect.KClass
import kotlin.script.experimental.util.PropertiesCollection
interface ScriptDefinition : PropertiesCollection {
interface ScriptDefinitionKeys
companion object : ScriptDefinition {
open class ScriptDefinition(baseDefinitions: Iterable<ScriptDefinition>, body: Builder.() -> Unit) :
PropertiesCollection(Builder(baseDefinitions).apply(body).data) {
class Builder internal constructor() : PropertiesCollection.Builder(), ScriptDefinition {
override val properties = data
}
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
constructor(vararg baseDefinitions: ScriptDefinition, body: Builder.() -> Unit = {}) : this(baseDefinitions.asIterable(), body)
fun create(body: Builder.() -> Unit): ScriptDefinition = Builder().apply(body)
class Builder internal constructor(baseDefinitions: Iterable<ScriptDefinition>) :
ScriptDefinitionKeys,
PropertiesCollection.Builder(baseDefinitions)
// inherited from script definition for using as a keys anchor
companion object : ScriptDefinitionKeys {
val Default = ScriptDefinition()
}
object Default : ScriptDefinition
}
val ScriptDefinition.name by PropertiesCollection.key<String>("Kotlin script") // Name of the script type
val ScriptDefinitionKeys.name by PropertiesCollection.key<String>("Kotlin script") // Name of the script type
val ScriptDefinition.fileExtension by PropertiesCollection.key<String>("kts") // file extension
val ScriptDefinitionKeys.fileExtension by PropertiesCollection.key<String>("kts") // file extension
val ScriptDefinition.baseClass by PropertiesCollection.key<KotlinType>() // script base class
val ScriptDefinitionKeys.baseClass by PropertiesCollection.key<KotlinType>() // script base class
val ScriptDefinition.scriptBodyTarget by PropertiesCollection.key<ScriptBodyTarget>(ScriptBodyTarget.Constructor)
val ScriptDefinitionKeys.scriptBodyTarget by PropertiesCollection.key<ScriptBodyTarget>(ScriptBodyTarget.Constructor)
val ScriptDefinition.scriptImplicitReceivers by PropertiesCollection.key<List<KotlinType>>() // in the order from outer to inner scope
val ScriptDefinitionKeys.scriptImplicitReceivers by PropertiesCollection.key<List<KotlinType>>() // in the order from outer to inner scope
val ScriptDefinition.contextVariables by PropertiesCollection.key<Map<String, KotlinType>>() // external variables
val ScriptDefinitionKeys.contextVariables by PropertiesCollection.key<Map<String, KotlinType>>() // external variables
val ScriptDefinition.defaultImports by PropertiesCollection.key<List<String>>()
val ScriptDefinitionKeys.defaultImports by PropertiesCollection.key<List<String>>()
val ScriptDefinition.restrictions by PropertiesCollection.key<List<ResolvingRestrictionRule>>()
val ScriptDefinitionKeys.restrictions by PropertiesCollection.key<List<ResolvingRestrictionRule>>()
val ScriptDefinition.importedScripts by PropertiesCollection.key<List<ScriptSource>>()
val ScriptDefinitionKeys.importedScripts by PropertiesCollection.key<List<ScriptSource>>()
val ScriptDefinition.dependencies by PropertiesCollection.key<List<ScriptDependency>>()
val ScriptDefinitionKeys.dependencies by PropertiesCollection.key<List<ScriptDependency>>()
val ScriptDefinition.generatedClassAnnotations by PropertiesCollection.key<List<Annotation>>()
val ScriptDefinitionKeys.generatedClassAnnotations by PropertiesCollection.key<List<Annotation>>()
val ScriptDefinition.generatedMethodAnnotations by PropertiesCollection.key<List<Annotation>>()
val ScriptDefinitionKeys.generatedMethodAnnotations by PropertiesCollection.key<List<Annotation>>()
val ScriptDefinition.compilerOptions by PropertiesCollection.key<List<String>>() // Q: CommonCompilerOptions instead?
val ScriptDefinitionKeys.compilerOptions by PropertiesCollection.key<List<String>>() // Q: CommonCompilerOptions instead?
val ScriptDefinition.refineConfigurationHandler by PropertiesCollection.key<RefineScriptCompilationConfigurationHandler>() // dynamic configurator
val ScriptDefinitionKeys.refineConfigurationHandler by PropertiesCollection.key<RefineScriptCompilationConfigurationHandler>() // dynamic configurator
val ScriptDefinition.refineConfigurationBeforeParsing by PropertiesCollection.key<Boolean>() // default: false
val ScriptDefinitionKeys.refineConfigurationBeforeParsing by PropertiesCollection.key<Boolean>() // default: false
val ScriptDefinition.refineConfigurationOnAnnotations by PropertiesCollection.key<List<KotlinType>>()
val ScriptDefinitionKeys.refineConfigurationOnAnnotations by PropertiesCollection.key<List<KotlinType>>()
val ScriptDefinition.refineConfigurationOnSections by PropertiesCollection.key<List<String>>()
val ScriptDefinitionKeys.refineConfigurationOnSections by PropertiesCollection.key<List<String>>()
// DSL:
val ScriptDefinition.refineConfiguration get() = RefineConfigurationBuilder()
val ScriptDefinition.Builder.refineConfiguration get() = RefineConfigurationBuilder()
class RefineConfigurationBuilder : PropertiesCollection.Builder() {
@@ -9,25 +9,30 @@ package kotlin.script.experimental.api
import kotlin.script.experimental.util.PropertiesCollection
interface ScriptEvaluationEnvironment : PropertiesCollection {
interface ScriptEvaluationEnvironmentKeys
companion object : ScriptEvaluationEnvironment {
class ScriptEvaluationEnvironment(baseEvaluationEnvironments: Iterable<ScriptEvaluationEnvironment>, body: Builder.() -> Unit) :
PropertiesCollection(Builder(baseEvaluationEnvironments).apply(body).data) {
class Builder internal constructor() : PropertiesCollection.Builder(), ScriptEvaluationEnvironment {
override val properties = data
}
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
constructor(
vararg baseEvaluationEnvironments: ScriptEvaluationEnvironment, body: Builder.() -> Unit = {}
) : this(baseEvaluationEnvironments.asIterable(), body)
fun create(body: Builder.() -> Unit): ScriptEvaluationEnvironment = Builder().apply(body)
}
class Builder internal constructor(baseEvaluationEnvironments: Iterable<ScriptEvaluationEnvironment>) :
ScriptDefinitionKeys,
PropertiesCollection.Builder(baseEvaluationEnvironments)
companion object : ScriptEvaluationEnvironmentKeys
}
val ScriptEvaluationEnvironment.implicitReceivers by PropertiesCollection.key<List<Any>>()
val ScriptEvaluationEnvironmentKeys.implicitReceivers by PropertiesCollection.key<List<Any>>()
val ScriptEvaluationEnvironment.contextVariables by PropertiesCollection.key<Map<String, Any?>>() // external variables
val ScriptEvaluationEnvironmentKeys.contextVariables by PropertiesCollection.key<Map<String, Any?>>() // external variables
val ScriptEvaluationEnvironment.constructorArgs by PropertiesCollection.key<List<Any?>>()
val ScriptEvaluationEnvironmentKeys.constructorArgs by PropertiesCollection.key<List<Any?>>()
val ScriptEvaluationEnvironment.runArgs by PropertiesCollection.key<List<Any?>>()
val ScriptEvaluationEnvironmentKeys.runArgs by PropertiesCollection.key<List<Any?>>()
sealed class ResultValue {
class Value(val name: String, val value: Any?, val type: String) : ResultValue() {
@@ -7,37 +7,42 @@ package kotlin.script.experimental.api
import kotlin.reflect.KClass
import kotlin.script.experimental.util.PropertiesCollection
import kotlin.script.experimental.util.getOrNull
interface ScriptingEnvironment : PropertiesCollection {
interface ScriptingEnvironmentKeys
companion object : ScriptingEnvironment {
class ScriptingEnvironment(baseScriptingEnvironments: Iterable<ScriptingEnvironment>, body: Builder.() -> Unit) :
PropertiesCollection(Builder(baseScriptingEnvironments).apply(body).data) {
class Builder internal constructor() : PropertiesCollection.Builder(), ScriptingEnvironment {
override val properties = data
}
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
constructor(
vararg baseScriptingEnvironments: ScriptingEnvironment, body: Builder.() -> Unit = {}
) : this(baseScriptingEnvironments.asIterable(), body)
fun create(body: Builder.() -> Unit): ScriptingEnvironment = Builder().apply(body)
}
class Builder internal constructor(baseScriptingEnvironments: Iterable<ScriptingEnvironment>) :
ScriptingEnvironmentKeys,
PropertiesCollection.Builder(baseScriptingEnvironments)
companion object : ScriptingEnvironmentKeys
}
// should contain all dependencies needed for baseClass and compilationConfigurator
val ScriptingEnvironment.configurationDependencies by PropertiesCollection.key<List<ScriptDependency>>()
val ScriptingEnvironmentKeys.configurationDependencies by PropertiesCollection.key<List<ScriptDependency>>()
// do not use configurationDependencies as script dependencies, so only the dependencies defined by compilationConfigurator will be used
// (NOTE: in this case they should include the dependencies for the base class anyway, since this class is needed for script
// compilation and instantiation, but compilationConfigurator could be excluded)
val ScriptingEnvironment.isolatedDependencies by PropertiesCollection.key<Boolean>(false)
val ScriptingEnvironmentKeys.isolatedDependencies by PropertiesCollection.key<Boolean>(false)
// a "class loader" for KotlinTypes
val ScriptingEnvironment.getScriptingClass by PropertiesCollection.key<GetScriptingClass>()
val ScriptingEnvironmentKeys.getScriptingClass by PropertiesCollection.key<GetScriptingClass>()
interface GetScriptingClass {
operator fun invoke(classType: KotlinType, contextClass: KClass<*>, environment: ScriptingEnvironment): KClass<*>
}
fun ScriptingEnvironment.getScriptingClass(type: KotlinType, contextClass: KClass<*>): KClass<*> {
val getClass = getOrNull(ScriptingEnvironment.getScriptingClass)
val getClass = get(ScriptingEnvironment.getScriptingClass)
?: throw IllegalArgumentException("Expecting 'getScriptingClass' property in the scripting environment: unable to load scripting class $type")
return getClass(type, contextClass, this)
}
@@ -12,7 +12,6 @@ import kotlin.script.experimental.annotations.KotlinScript
import kotlin.script.experimental.annotations.KotlinScriptFileExtension
import kotlin.script.experimental.annotations.KotlinScriptProperties
import kotlin.script.experimental.api.*
import kotlin.script.experimental.util.getOrNull
private const val ERROR_MSG_PREFIX = "Unable to construct script definition: "
@@ -25,7 +24,7 @@ fun createScriptDefinitionFromAnnotatedBaseClass(
contextClass: KClass<*> = ScriptDefinition::class
): ScriptDefinition {
val getScriptingClass = environment.getOrNull(ScriptingEnvironment.getScriptingClass)
val getScriptingClass = environment[ScriptingEnvironment.getScriptingClass]
?: throw IllegalArgumentException("${ERROR_MSG_PREFIX}Expecting 'getScriptingClass' parameter in the scripting environment")
val baseClass: KClass<*> =
@@ -44,17 +43,15 @@ fun createScriptDefinitionFromAnnotatedBaseClass(
throw IllegalArgumentException(ILLEGAL_CONFIG_ANN_ARG, e)
}
return object : ScriptDefinition {
override val properties = properties {
baseClass(baseClassType)
fileExtension(baseClass.findAnnotation<KotlinScriptFileExtension>()?.extension ?: mainAnnotation.extension)
name(mainAnnotation.name)
return ScriptDefinition {
baseClass(baseClassType)
fileExtension(baseClass.findAnnotation<KotlinScriptFileExtension>()?.extension ?: mainAnnotation.extension)
name(mainAnnotation.name)
include(scriptingPropsInstance(mainAnnotation.definition))
include(scriptingPropsInstance(mainAnnotation.definition))
baseClass.annotations.filterIsInstance(KotlinScriptProperties::class.java).forEach { ann ->
include(scriptingPropsInstance(ann.definition))
}
baseClass.annotations.filterIsInstance(KotlinScriptProperties::class.java).forEach { ann ->
include(scriptingPropsInstance(ann.definition))
}
}
}
@@ -11,7 +11,6 @@ import kotlin.script.experimental.api.ScriptCompileConfiguration
import kotlin.script.experimental.api.ScriptSource
import kotlin.script.experimental.api.ScriptSourceNamedFragment
import kotlin.script.experimental.api.sourceFragments
import kotlin.script.experimental.util.getOrNull
fun ScriptSource.getScriptText(): String = when {
text != null -> text!!
@@ -22,7 +21,7 @@ fun ScriptSource.getScriptText(): String = when {
fun getMergedScriptText(script: ScriptSource, configuration: ScriptCompileConfiguration?): String {
val originalScriptText = script.getScriptText()
val sourceFragments = configuration?.getOrNull(ScriptCompileConfiguration.sourceFragments)
val sourceFragments = configuration?.get(ScriptCompileConfiguration.sourceFragments)
return if (sourceFragments == null || sourceFragments.isEmpty()) {
originalScriptText
} else {
@@ -9,16 +9,21 @@ import kotlin.script.experimental.api.EvaluationResult
import kotlin.script.experimental.api.ResultWithDiagnostics
import kotlin.script.experimental.util.PropertiesCollection
interface ReplEvaluationEnvironment : PropertiesCollection {
interface ReplEvaluationEnvironmentKeys
companion object : ReplEvaluationEnvironment {
class ReplEvaluationEnvironment(baseEvaluationEnvironments: Iterable<ReplEvaluationEnvironment>, body: Builder.() -> Unit) :
PropertiesCollection(Builder(baseEvaluationEnvironments).apply(body).data) {
class Builder internal constructor() : PropertiesCollection.Builder(), ReplEvaluationEnvironment {
override val properties = data
}
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
constructor(
vararg baseEvaluationEnvironments: ReplEvaluationEnvironment, body: Builder.() -> Unit = {}
) : this(baseEvaluationEnvironments.asIterable(), body)
fun create(body: Builder.() -> Unit): ReplEvaluationEnvironment = Builder().apply(body)
}
class Builder internal constructor(baseEvaluationEnvironments: Iterable<ReplEvaluationEnvironment>) :
ReplEvaluationEnvironmentKeys,
PropertiesCollection.Builder(baseEvaluationEnvironments)
companion object : ReplEvaluationEnvironmentKeys
}
interface ReplSnippetEvaluator {
@@ -22,19 +22,24 @@ interface ReplCommandProcessor {
data class ReplCommand(val commandName: String, val processor: ReplCommandProcessor)
interface ReplHostEnvironment : PropertiesCollection {
interface ReplHostEnvironmentKeys
companion object : ReplHostEnvironment {
class ReplHostEnvironment(baseReplHostEnvironments: Iterable<ReplHostEnvironment>, body: Builder.() -> Unit) :
PropertiesCollection(Builder(baseReplHostEnvironments).apply(body).data) {
class Builder internal constructor() : PropertiesCollection.Builder(), ReplHostEnvironment {
override val properties = data
}
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
constructor(
vararg baseReplHostEnvironments: ReplHostEnvironment, body: Builder.() -> Unit = {}
) : this(baseReplHostEnvironments.asIterable(), body)
fun create(body: Builder.() -> Unit): ReplHostEnvironment = Builder().apply(body)
}
class Builder internal constructor(baseReplHostEnvironments: Iterable<ReplHostEnvironment>) :
ReplHostEnvironmentKeys,
PropertiesCollection.Builder(baseReplHostEnvironments)
companion object : ReplHostEnvironmentKeys
}
val ReplHostEnvironment.replCommands by PropertiesCollection.key<List<ReplCommand>>()
val ReplHostEnvironmentKeys.replCommands by PropertiesCollection.key<List<ReplCommand>>()
abstract class ReplHost(
val environment: ReplHostEnvironment,
@@ -10,9 +10,7 @@ import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.script.experimental.api.KotlinType
interface PropertiesCollection {
val properties: Map<Key<*>, Any> get() = emptyMap()
open class PropertiesCollection(val properties: Map<Key<*>, Any> = emptyMap()) {
data class Key<T>(val name: String, val defaultValue: T? = null)
@@ -25,22 +23,27 @@ interface PropertiesCollection {
operator fun getValue(thisRef: Any?, property: KProperty<*>): Key<T> = source
}
@Suppress("UNCHECKED_CAST")
operator fun <T> get(key: PropertiesCollection.Key<T>): T? =
properties[key]?.let { it as T } ?: key.defaultValue
companion object {
fun <T> key(defaultValue: T? = null) = PropertyKeyDelegate(defaultValue)
fun <T> keyCopy(source: Key<T>) = PropertyKeyCopyDelegate(source)
}
fun properties(body: Builder.() -> Unit): Map<Key<*>, Any> = Builder().apply(body).data
// properties builder base class (DSL for building properties collection)
open class Builder {
open class Builder(baseProperties: Iterable<PropertiesCollection> = emptyList()) {
val data: MutableMap<PropertiesCollection.Key<*>, Any> = LinkedHashMap()
val data: MutableMap<PropertiesCollection.Key<*>, Any> = LinkedHashMap<PropertiesCollection.Key<*>, Any>().apply {
baseProperties.forEach { putAll(it.properties) }
}
// generic builder for all properties
operator fun <T : Any> PropertiesCollection.Key<T>.invoke(v: T) {
set(this, v)
data[this] = v
}
// generic for lists
@@ -59,28 +62,28 @@ interface PropertiesCollection {
@JvmName("invoke_string_fqn_from_generic")
inline operator fun <reified K> PropertiesCollection.Key<String>.invoke() {
set(this, K::class.qualifiedName!!)
data[this] = K::class.java.name
}
@JvmName("invoke_string_fqn_from_reflected_class")
operator fun PropertiesCollection.Key<String>.invoke(kclass: KClass<*>) {
set(this, kclass.qualifiedName!!)
data[this] = kclass.java.name
}
@JvmName("invoke_string_list_fqn_from_generic")
inline operator fun <reified K> PropertiesCollection.Key<in List<String>>.invoke() {
append(K::class.qualifiedName!!)
append(K::class.java.name)
}
@JvmName("invoke_string_list_fqn_from_reflected_class")
operator fun PropertiesCollection.Key<in List<String>>.invoke(vararg kclasses: KClass<*>) {
append(kclasses.map { it.qualifiedName!! })
append(kclasses.map { it.java.name })
}
// for KotlinType:
inline operator fun <reified K> PropertiesCollection.Key<KotlinType>.invoke() {
set(this, KotlinType(K::class))
data[this] = KotlinType(K::class)
}
operator fun PropertiesCollection.Key<KotlinType>.invoke(kclass: KClass<*>) {
@@ -138,7 +141,7 @@ interface PropertiesCollection {
}
@Suppress("UNCHECKED_CAST")
operator fun <T : Any> get(key: PropertiesCollection.Key<in T>): T? = data[key]?.let { it as T }
private operator fun <T : Any> get(key: PropertiesCollection.Key<in T>): T? = data[key]?.let { it as T }
// appenders to list and map properties
@@ -174,15 +177,22 @@ interface PropertiesCollection {
this.body()
this@Builder.data.putAll(this.data)
}
// a class for extending properties
interface BuilderExtension<T : Builder> {
fun get(): T
}
// include another builder extension
operator fun <T : Builder> BuilderExtension<T>.invoke(body: T.() -> Unit) {
val builder = this.get().apply(body)
this@Builder.data.putAll(builder.data)
}
}
}
@Suppress("UNCHECKED_CAST")
fun <T> PropertiesCollection.getOrNull(key: PropertiesCollection.Key<T>): T? =
properties[key]?.let { it as T } ?: key.defaultValue
fun <T> PropertiesCollection.getOrError(key: PropertiesCollection.Key<T>): T =
getOrNull(key) ?: throw IllegalArgumentException("Unknown key $key")
fun <T> PropertiesCollection.getOrError(key: PropertiesCollection.Key<T>): T =
get(key) ?: throw IllegalArgumentException("Unknown key $key")
@Suppress("UNCHECKED_CAST")
fun <T> getFirstFromChainOrNull(key: PropertiesCollection.Key<T>, vararg propertyCollections: PropertiesCollection?): T? {
@@ -193,16 +203,3 @@ fun <T> getFirstFromChainOrNull(key: PropertiesCollection.Key<T>, vararg propert
return key.defaultValue
}
@Suppress("UNCHECKED_CAST")
fun <T> getMergedFromChainOrNull(key: PropertiesCollection.Key<List<T>>, vararg propertyCollections: PropertiesCollection?): List<T>? {
var found = false
val res = ArrayList<T>()
for (collection in propertyCollections) {
val value = collection?.properties?.get(key)
if (value != null) {
found = true
res.addAll(value as List<T>)
}
}
return if (found) res else key.defaultValue
}