Refactor MetaItem delegates.
This commit is contained in:
parent
eeb4643d93
commit
87af89b47d
@ -5,26 +5,47 @@ import hep.dataforge.names.Name
|
|||||||
import hep.dataforge.names.asName
|
import hep.dataforge.names.asName
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
/* Meta delegates */
|
/* Meta delegates */
|
||||||
//TODO to be replaced in 1.4 by interfaces
|
|
||||||
open class ItemDelegate(
|
|
||||||
open val owner: ItemProvider,
|
|
||||||
val key: Name? = null,
|
|
||||||
open val default: MetaItem<*>? = null
|
|
||||||
) : ReadOnlyProperty<Any?, MetaItem<*>?> {
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*>? {
|
|
||||||
return owner.getItem(key ?: property.name.asName()) ?: default
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun ItemProvider.item(key: Name? = null): ItemDelegate = ItemDelegate(this, key)
|
public typealias ItemDelegate = ReadOnlyProperty<Any?, MetaItem<*>?>
|
||||||
|
|
||||||
|
public fun ItemProvider.item(key: Name? = null): ItemDelegate = ReadOnlyProperty { _, property ->
|
||||||
|
getItem(key ?: property.name.asName())
|
||||||
|
}
|
||||||
|
|
||||||
//TODO add caching for sealed nodes
|
//TODO add caching for sealed nodes
|
||||||
|
|
||||||
|
|
||||||
//Read-only delegates for Metas
|
/**
|
||||||
|
* Apply a converter to this delegate creating a delegate with a custom type
|
||||||
|
*/
|
||||||
|
public fun <R : Any> ItemDelegate.convert(
|
||||||
|
converter: MetaConverter<R>,
|
||||||
|
): ReadOnlyProperty<Any?, R?> = ReadOnlyProperty { thisRef, property ->
|
||||||
|
this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public fun <R : Any> ItemDelegate.convert(
|
||||||
|
converter: MetaConverter<R>,
|
||||||
|
default: () -> R,
|
||||||
|
): ReadOnlyProperty<Any?, R> = ReadOnlyProperty<Any?, R> { thisRef, property ->
|
||||||
|
this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A converter with a custom reader transformation
|
||||||
|
*/
|
||||||
|
public fun <R> ItemDelegate.convert(
|
||||||
|
reader: (MetaItem<*>?) -> R,
|
||||||
|
): ReadOnlyProperty<Any?, R> = ReadOnlyProperty<Any?, R> { thisRef, property ->
|
||||||
|
this@convert.getValue(thisRef, property).let(reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read-only delegates for Metas */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A property delegate that uses custom key
|
* A property delegate that uses custom key
|
||||||
|
@ -12,103 +12,148 @@ import kotlin.reflect.KProperty
|
|||||||
|
|
||||||
/* Read-write delegates */
|
/* Read-write delegates */
|
||||||
|
|
||||||
open class MutableItemDelegate(
|
public typealias MutableItemDelegate = ReadWriteProperty<Any?, MetaItem<*>?>
|
||||||
override val owner: MutableItemProvider,
|
|
||||||
key: Name? = null,
|
public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = object :MutableItemDelegate {
|
||||||
default: MetaItem<*>? = null
|
|
||||||
) : ItemDelegate(owner, key, default), ReadWriteProperty<Any?, MetaItem<*>?> {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*>? {
|
||||||
|
return getItem(key ?: property.name.asName())
|
||||||
|
}
|
||||||
|
|
||||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: MetaItem<*>?) {
|
override fun setValue(thisRef: Any?, property: KProperty<*>, value: MetaItem<*>?) {
|
||||||
val name = key ?: property.name.asName()
|
val name = key ?: property.name.asName()
|
||||||
owner.setItem(name, value)
|
setItem(name, value)
|
||||||
|
}
|
||||||
|
//MutableItemDelegate(this, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mutable converters */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A type converter for a mutable [MetaItem] delegate
|
||||||
|
*/
|
||||||
|
public fun <R : Any> MutableItemDelegate.convert(
|
||||||
|
converter: MetaConverter<R>,
|
||||||
|
): ReadWriteProperty<Any?, R?> = object : ReadWriteProperty<Any?, R?> {
|
||||||
|
|
||||||
|
override fun getValue(thisRef: Any?, property: KProperty<*>): R? =
|
||||||
|
this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
|
||||||
|
|
||||||
|
override fun setValue(thisRef: Any?, property: KProperty<*>, value: R?) {
|
||||||
|
val item = value?.let(converter::objectToMetaItem)
|
||||||
|
this@convert.setValue(thisRef, property, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate =
|
public fun <R : Any> MutableItemDelegate.convert(
|
||||||
MutableItemDelegate(this, key)
|
converter: MetaConverter<R>,
|
||||||
|
default: () -> R,
|
||||||
|
): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
|
||||||
|
|
||||||
//Read-write delegates
|
override fun getValue(thisRef: Any?, property: KProperty<*>): R =
|
||||||
|
this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
|
||||||
|
|
||||||
|
override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
|
||||||
|
val item = value.let(converter::objectToMetaItem)
|
||||||
|
this@convert.setValue(thisRef, property, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun <R> MutableItemDelegate.convert(
|
||||||
|
reader: (MetaItem<*>?) -> R,
|
||||||
|
writer: (R) -> MetaItem<*>?,
|
||||||
|
): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
|
||||||
|
|
||||||
|
override fun getValue(thisRef: Any?, property: KProperty<*>): R =
|
||||||
|
this@convert.getValue(thisRef, property).let(reader)
|
||||||
|
|
||||||
|
override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
|
||||||
|
val item = value?.let(writer)
|
||||||
|
this@convert.setValue(thisRef, property, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read-write delegates */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A property delegate that uses custom key
|
* A property delegate that uses custom key
|
||||||
*/
|
*/
|
||||||
fun MutableItemProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
|
public fun MutableItemProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
|
||||||
item(key).convert(MetaConverter.value)
|
item(key).convert(MetaConverter.value)
|
||||||
|
|
||||||
fun MutableItemProvider.string(key: Name? = null): ReadWriteProperty<Any?, String?> =
|
public fun MutableItemProvider.string(key: Name? = null): ReadWriteProperty<Any?, String?> =
|
||||||
item(key).convert(MetaConverter.string)
|
item(key).convert(MetaConverter.string)
|
||||||
|
|
||||||
fun MutableItemProvider.boolean(key: Name? = null): ReadWriteProperty<Any?, Boolean?> =
|
public fun MutableItemProvider.boolean(key: Name? = null): ReadWriteProperty<Any?, Boolean?> =
|
||||||
item(key).convert(MetaConverter.boolean)
|
item(key).convert(MetaConverter.boolean)
|
||||||
|
|
||||||
fun MutableItemProvider.number(key: Name? = null): ReadWriteProperty<Any?, Number?> =
|
public fun MutableItemProvider.number(key: Name? = null): ReadWriteProperty<Any?, Number?> =
|
||||||
item(key).convert(MetaConverter.number)
|
item(key).convert(MetaConverter.number)
|
||||||
|
|
||||||
fun MutableItemProvider.string(default: String, key: Name? = null): ReadWriteProperty<Any?, String> =
|
public fun MutableItemProvider.string(default: String, key: Name? = null): ReadWriteProperty<Any?, String> =
|
||||||
item(key).convert(MetaConverter.string) { default }
|
item(key).convert(MetaConverter.string) { default }
|
||||||
|
|
||||||
fun MutableItemProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty<Any?, Boolean> =
|
public fun MutableItemProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty<Any?, Boolean> =
|
||||||
item(key).convert(MetaConverter.boolean) { default }
|
item(key).convert(MetaConverter.boolean) { default }
|
||||||
|
|
||||||
fun MutableItemProvider.number(default: Number, key: Name? = null): ReadWriteProperty<Any?, Number> =
|
public fun MutableItemProvider.number(default: Number, key: Name? = null): ReadWriteProperty<Any?, Number> =
|
||||||
item(key).convert(MetaConverter.number) { default }
|
item(key).convert(MetaConverter.number) { default }
|
||||||
|
|
||||||
fun MutableItemProvider.value(key: Name? = null, default: () -> Value): ReadWriteProperty<Any?, Value> =
|
public fun MutableItemProvider.value(key: Name? = null, default: () -> Value): ReadWriteProperty<Any?, Value> =
|
||||||
item(key).convert(MetaConverter.value, default)
|
item(key).convert(MetaConverter.value, default)
|
||||||
|
|
||||||
fun MutableItemProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty<Any?, String> =
|
public fun MutableItemProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty<Any?, String> =
|
||||||
item(key).convert(MetaConverter.string, default)
|
item(key).convert(MetaConverter.string, default)
|
||||||
|
|
||||||
fun MutableItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty<Any?, Boolean> =
|
public fun MutableItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty<Any?, Boolean> =
|
||||||
item(key).convert(MetaConverter.boolean, default)
|
item(key).convert(MetaConverter.boolean, default)
|
||||||
|
|
||||||
fun MutableItemProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
|
public fun MutableItemProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
|
||||||
item(key).convert(MetaConverter.number, default)
|
item(key).convert(MetaConverter.number, default)
|
||||||
|
|
||||||
inline fun <reified E : Enum<E>> MutableItemProvider.enum(default: E, key: Name? = null): ReadWriteProperty<Any?, E> =
|
public inline fun <reified E : Enum<E>> MutableItemProvider.enum(default: E, key: Name? = null): ReadWriteProperty<Any?, E> =
|
||||||
item(key).convert(MetaConverter.enum()) { default }
|
item(key).convert(MetaConverter.enum()) { default }
|
||||||
|
|
||||||
inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
|
public inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
|
||||||
item(key).convert(reader = { it?.let { it.node as M } }, writer = { it?.let { MetaItem.NodeItem(it) } })
|
item(key).convert(reader = { it?.let { it.node as M } }, writer = { it?.let { MetaItem.NodeItem(it) } })
|
||||||
|
|
||||||
|
|
||||||
fun Configurable.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
|
public fun Configurable.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
|
||||||
item(key).convert(MetaConverter.value)
|
item(key).convert(MetaConverter.value)
|
||||||
|
|
||||||
/* Number delegates*/
|
/* Number delegates */
|
||||||
|
|
||||||
fun MutableItemProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> =
|
public fun MutableItemProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> =
|
||||||
item(key).convert(MetaConverter.int)
|
item(key).convert(MetaConverter.int)
|
||||||
|
|
||||||
fun MutableItemProvider.double(key: Name? = null): ReadWriteProperty<Any?, Double?> =
|
public fun MutableItemProvider.double(key: Name? = null): ReadWriteProperty<Any?, Double?> =
|
||||||
item(key).convert(MetaConverter.double)
|
item(key).convert(MetaConverter.double)
|
||||||
|
|
||||||
fun MutableItemProvider.long(key: Name? = null): ReadWriteProperty<Any?, Long?> =
|
public fun MutableItemProvider.long(key: Name? = null): ReadWriteProperty<Any?, Long?> =
|
||||||
item(key).convert(MetaConverter.long)
|
item(key).convert(MetaConverter.long)
|
||||||
|
|
||||||
fun MutableItemProvider.float(key: Name? = null): ReadWriteProperty<Any?, Float?> =
|
public fun MutableItemProvider.float(key: Name? = null): ReadWriteProperty<Any?, Float?> =
|
||||||
item(key).convert(MetaConverter.float)
|
item(key).convert(MetaConverter.float)
|
||||||
|
|
||||||
|
|
||||||
/* Safe number delegates*/
|
/* Safe number delegates*/
|
||||||
|
|
||||||
fun MutableItemProvider.int(default: Int, key: Name? = null): ReadWriteProperty<Any?, Int> =
|
public fun MutableItemProvider.int(default: Int, key: Name? = null): ReadWriteProperty<Any?, Int> =
|
||||||
item(key).convert(MetaConverter.int) { default }
|
item(key).convert(MetaConverter.int) { default }
|
||||||
|
|
||||||
fun MutableItemProvider.double(default: Double, key: Name? = null): ReadWriteProperty<Any?, Double> =
|
public fun MutableItemProvider.double(default: Double, key: Name? = null): ReadWriteProperty<Any?, Double> =
|
||||||
item(key).convert(MetaConverter.double) { default }
|
item(key).convert(MetaConverter.double) { default }
|
||||||
|
|
||||||
fun MutableItemProvider.long(default: Long, key: Name? = null): ReadWriteProperty<Any?, Long> =
|
public fun MutableItemProvider.long(default: Long, key: Name? = null): ReadWriteProperty<Any?, Long> =
|
||||||
item(key).convert(MetaConverter.long) { default }
|
item(key).convert(MetaConverter.long) { default }
|
||||||
|
|
||||||
fun MutableItemProvider.float(default: Float, key: Name? = null): ReadWriteProperty<Any?, Float> =
|
public fun MutableItemProvider.float(default: Float, key: Name? = null): ReadWriteProperty<Any?, Float> =
|
||||||
item(key).convert(MetaConverter.float) { default }
|
item(key).convert(MetaConverter.float) { default }
|
||||||
|
|
||||||
|
|
||||||
/*
|
/* Extra delegates for special cases */
|
||||||
* Extra delegates for special cases
|
|
||||||
*/
|
public fun MutableItemProvider.stringList(
|
||||||
fun MutableItemProvider.stringList(
|
|
||||||
vararg default: String,
|
vararg default: String,
|
||||||
key: Name? = null
|
key: Name? = null
|
||||||
): ReadWriteProperty<Any?, List<String>> = item(key).convert(
|
): ReadWriteProperty<Any?, List<String>> = item(key).convert(
|
||||||
@ -116,14 +161,14 @@ fun MutableItemProvider.stringList(
|
|||||||
writer = { it.map { str -> str.asValue() }.asValue().asMetaItem() }
|
writer = { it.map { str -> str.asValue() }.asValue().asMetaItem() }
|
||||||
)
|
)
|
||||||
|
|
||||||
fun MutableItemProvider.stringList(
|
public fun MutableItemProvider.stringList(
|
||||||
key: Name? = null
|
key: Name? = null
|
||||||
): ReadWriteProperty<Any?, List<String>?> = item(key).convert(
|
): ReadWriteProperty<Any?, List<String>?> = item(key).convert(
|
||||||
reader = { it?.stringList },
|
reader = { it?.stringList },
|
||||||
writer = { it?.map { str -> str.asValue() }?.asValue()?.asMetaItem() }
|
writer = { it?.map { str -> str.asValue() }?.asValue()?.asMetaItem() }
|
||||||
)
|
)
|
||||||
|
|
||||||
fun MutableItemProvider.numberList(
|
public fun MutableItemProvider.numberList(
|
||||||
vararg default: Number,
|
vararg default: Number,
|
||||||
key: Name? = null
|
key: Name? = null
|
||||||
): ReadWriteProperty<Any?, List<Number>> = item(key).convert(
|
): ReadWriteProperty<Any?, List<Number>> = item(key).convert(
|
||||||
@ -131,10 +176,10 @@ fun MutableItemProvider.numberList(
|
|||||||
writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() }
|
writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() }
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/* A special delegate for double arrays */
|
||||||
* A special delegate for double arrays
|
|
||||||
*/
|
|
||||||
fun MutableItemProvider.doubleArray(
|
public fun MutableItemProvider.doubleArray(
|
||||||
vararg default: Double,
|
vararg default: Double,
|
||||||
key: Name? = null
|
key: Name? = null
|
||||||
): ReadWriteProperty<Any?, DoubleArray> =item(key).convert(
|
): ReadWriteProperty<Any?, DoubleArray> =item(key).convert(
|
||||||
@ -142,7 +187,7 @@ fun MutableItemProvider.doubleArray(
|
|||||||
writer = { DoubleArrayValue(it).asMetaItem() }
|
writer = { DoubleArrayValue(it).asMetaItem() }
|
||||||
)
|
)
|
||||||
|
|
||||||
fun <T> MutableItemProvider.listValue(
|
public fun <T> MutableItemProvider.listValue(
|
||||||
key: Name? = null,
|
key: Name? = null,
|
||||||
writer: (T) -> Value = { Value.of(it) },
|
writer: (T) -> Value = { Value.of(it) },
|
||||||
reader: (Value) -> T
|
reader: (Value) -> T
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
package hep.dataforge.meta
|
|
||||||
|
|
||||||
import hep.dataforge.meta.transformations.MetaConverter
|
|
||||||
import kotlin.properties.ReadOnlyProperty
|
|
||||||
import kotlin.properties.ReadWriteProperty
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply a converter to this delegate creating a delegate with a custom type
|
|
||||||
*/
|
|
||||||
fun <R : Any> ItemDelegate.convert(
|
|
||||||
converter: MetaConverter<R>
|
|
||||||
): ReadOnlyProperty<Any?, R?> = object : ReadOnlyProperty<Any?, R?> {
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): R? =
|
|
||||||
this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
fun <R : Any> ItemDelegate.convert(
|
|
||||||
converter: MetaConverter<R>,
|
|
||||||
default: () -> R
|
|
||||||
): ReadOnlyProperty<Any?, R> = object : ReadOnlyProperty<Any?, R> {
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): R =
|
|
||||||
this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A converter with a custom reader transformation
|
|
||||||
*/
|
|
||||||
fun <R> ItemDelegate.convert(
|
|
||||||
reader: (MetaItem<*>?) -> R
|
|
||||||
): ReadOnlyProperty<Any?, R> = object : ReadOnlyProperty<Any?, R> {
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): R =
|
|
||||||
this@convert.getValue(thisRef, property).let(reader)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Mutable converters*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A type converter for a mutable [MetaItem] delegate
|
|
||||||
*/
|
|
||||||
fun <R : Any> MutableItemDelegate.convert(
|
|
||||||
converter: MetaConverter<R>
|
|
||||||
): ReadWriteProperty<Any?, R?> = object : ReadWriteProperty<Any?, R?> {
|
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): R? =
|
|
||||||
this@convert.getValue(thisRef, property)?.let(converter::itemToObject)
|
|
||||||
|
|
||||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: R?) {
|
|
||||||
val item = value?.let(converter::objectToMetaItem)
|
|
||||||
this@convert.setValue(thisRef, property, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <R : Any> MutableItemDelegate.convert(
|
|
||||||
converter: MetaConverter<R>,
|
|
||||||
default: () -> R
|
|
||||||
): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
|
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): R =
|
|
||||||
this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default()
|
|
||||||
|
|
||||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
|
|
||||||
val item = value.let(converter::objectToMetaItem)
|
|
||||||
this@convert.setValue(thisRef, property, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <R> MutableItemDelegate.convert(
|
|
||||||
reader: (MetaItem<*>?) -> R,
|
|
||||||
writer: (R) -> MetaItem<*>?
|
|
||||||
): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
|
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): R =
|
|
||||||
this@convert.getValue(thisRef, property).let(reader)
|
|
||||||
|
|
||||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) {
|
|
||||||
val item = value?.let(writer)
|
|
||||||
this@convert.setValue(thisRef, property, item)
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,7 +18,6 @@ pluginManagement {
|
|||||||
id("ru.mipt.npm.publish") version toolsVersion
|
id("ru.mipt.npm.publish") version toolsVersion
|
||||||
kotlin("jvm") version kotlinVersion
|
kotlin("jvm") version kotlinVersion
|
||||||
kotlin("js") version kotlinVersion
|
kotlin("js") version kotlinVersion
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user