From 460dc77d51313a4e6ce3d731af540da3c97e9f98 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 25 Dec 2020 16:19:19 +0300 Subject: [PATCH] Fix MetaItem inference from Any --- build.gradle.kts | 2 +- dataforge-meta/api/dataforge-meta.api | 38 +++++++------- .../kotlin/hep/dataforge/meta/ItemProvider.kt | 7 ++- .../kotlin/hep/dataforge/meta/Meta.kt | 45 ---------------- .../meta/{TypedMetaItem.kt => MetaItem.kt} | 7 +-- .../hep/dataforge/meta/MutableItemProvider.kt | 11 +--- .../kotlin/hep/dataforge/meta/TypedMeta.kt | 51 +++++++++++++++++++ 7 files changed, 84 insertions(+), 77 deletions(-) rename dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/{TypedMetaItem.kt => MetaItem.kt} (92%) create mode 100644 dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/TypedMeta.kt diff --git a/build.gradle.kts b/build.gradle.kts index aa39db90..65e56e40 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("ru.mipt.npm.project") } -val dataforgeVersion by extra("0.3.0-dev-SNAPSHOT") +val dataforgeVersion by extra("0.3.0-dev") val bintrayRepo by extra("dataforge") val githubProject by extra("dataforge-core") diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api index c130e09e..a3c45b6a 100644 --- a/dataforge-meta/api/dataforge-meta.api +++ b/dataforge-meta/api/dataforge-meta.api @@ -131,6 +131,7 @@ public final class hep/dataforge/meta/ItemProviderKt { public static final fun getChild (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;)Lhep/dataforge/meta/ItemProvider; public static final fun getIndexed (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Ljava/util/Map; public static final fun getIndexed (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;)Ljava/util/Map; + public static final fun getRootItem (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/TypedMetaItem; public static final fun getRootNode (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Meta; public static final fun withDefault (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/ItemProvider; } @@ -252,6 +253,22 @@ public final class hep/dataforge/meta/MetaBuilderKt { public static final fun builder (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaBuilder; } +public final class hep/dataforge/meta/MetaItemKt { + public static final fun asMetaItem (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/NodeItem; + public static final fun asMetaItem (Lhep/dataforge/values/Value;)Lhep/dataforge/meta/ValueItem; + public static final fun getBoolean (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Boolean; + public static final fun getDouble (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Double; + public static final fun getFloat (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Float; + public static final fun getInt (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Integer; + public static final fun getLong (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Long; + public static final fun getNode (Lhep/dataforge/meta/TypedMetaItem;)Lhep/dataforge/meta/Meta; + public static final fun getNumber (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Number; + public static final fun getShort (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Short; + public static final fun getString (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/String; + public static final fun getStringList (Lhep/dataforge/meta/TypedMetaItem;)Ljava/util/List; + public static final fun getValue (Lhep/dataforge/meta/TypedMetaItem;)Lhep/dataforge/values/Value; +} + public final class hep/dataforge/meta/MetaItemSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lhep/dataforge/meta/MetaItemSerializer; public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/TypedMetaItem; @@ -263,9 +280,6 @@ public final class hep/dataforge/meta/MetaItemSerializer : kotlinx/serialization public final class hep/dataforge/meta/MetaKt { public static final fun get (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/TypedMetaItem; - public static final fun get (Lhep/dataforge/meta/TypedMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem; - public static final fun get (Lhep/dataforge/meta/TypedMeta;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/TypedMetaItem; - public static final fun get (Lhep/dataforge/meta/TypedMeta;Ljava/lang/String;)Lhep/dataforge/meta/TypedMetaItem; public static final fun isEmpty (Lhep/dataforge/meta/Meta;)Z public static final fun itemSequence (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence; public static final fun iterator (Lhep/dataforge/meta/Meta;)Ljava/util/Iterator; @@ -508,20 +522,10 @@ public final class hep/dataforge/meta/TypedMetaItem$Companion { public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer; } -public final class hep/dataforge/meta/TypedMetaItemKt { - public static final fun asMetaItem (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/NodeItem; - public static final fun asMetaItem (Lhep/dataforge/values/Value;)Lhep/dataforge/meta/ValueItem; - public static final fun getBoolean (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Boolean; - public static final fun getDouble (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Double; - public static final fun getFloat (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Float; - public static final fun getInt (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Integer; - public static final fun getLong (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Long; - public static final fun getNode (Lhep/dataforge/meta/TypedMetaItem;)Lhep/dataforge/meta/Meta; - public static final fun getNumber (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Number; - public static final fun getShort (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Short; - public static final fun getString (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/String; - public static final fun getStringList (Lhep/dataforge/meta/TypedMetaItem;)Ljava/util/List; - public static final fun getValue (Lhep/dataforge/meta/TypedMetaItem;)Lhep/dataforge/values/Value; +public final class hep/dataforge/meta/TypedMetaKt { + public static final fun get (Lhep/dataforge/meta/TypedMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem; + public static final fun get (Lhep/dataforge/meta/TypedMeta;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/TypedMetaItem; + public static final fun get (Lhep/dataforge/meta/TypedMeta;Ljava/lang/String;)Lhep/dataforge/meta/TypedMetaItem; } public final class hep/dataforge/meta/ValueItem : hep/dataforge/meta/TypedMetaItem { diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemProvider.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemProvider.kt index f3d3884f..194a3398 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemProvider.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/ItemProvider.kt @@ -21,10 +21,15 @@ public fun interface ItemProvider { */ public operator fun ItemProvider?.get(name: Name): MetaItem? = this?.getItem(name) +/** + * Root item of this provider + */ +public val ItemProvider.rootItem: MetaItem? get() = get(Name.EMPTY) + /** * The root node of this item provider if it is present */ -public val ItemProvider.rootNode: Meta? get() = get(Name.EMPTY).node +public val ItemProvider.rootNode: Meta? get() = rootItem.node /** * Parse [Name] from [key] using full name notation and pass it to [Meta.get] diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt index f672279e..95d144b0 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt @@ -3,7 +3,6 @@ package hep.dataforge.meta import hep.dataforge.names.* import hep.dataforge.values.Value import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json /** @@ -91,48 +90,4 @@ public fun Meta.itemSequence(): Sequence> = sequence { public operator fun Meta.iterator(): Iterator> = itemSequence().iterator() -/** - * A meta node that ensures that all of its descendants has at least the same type - */ -public interface TypedMeta> : Meta { - override val items: Map> - - @Suppress("UNCHECKED_CAST") - override fun getItem(name: Name): TypedMetaItem? = super.getItem(name)?.let { it as TypedMetaItem } - //Typed meta guarantees that all children have M type -} - -/** - * The same as [Meta.get], but with specific node type - */ -public operator fun > M?.get(name: Name): TypedMetaItem? = this?.getItem(name) - - -public operator fun > M?.get(key: String): TypedMetaItem? = this[key.toName()] -public operator fun > M?.get(key: NameToken): TypedMetaItem? = this[key.asName()] - -/** - * Equals, hashcode and to string for any meta - */ -public abstract class MetaBase : Meta { - - override fun equals(other: Any?): Boolean = if (other is Meta) { - this.items == other.items - } else { - false - } - - override fun hashCode(): Int = items.hashCode() - - override fun toString(): String = Json { - prettyPrint = true - useArrayPolymorphism = true - }.encodeToString(MetaSerializer, this) -} - -/** - * Equals and hash code implementation for meta node - */ -public abstract class AbstractTypedMeta> : TypedMeta, MetaBase() - public fun Meta.isEmpty(): Boolean = this === Meta.EMPTY || this.items.isEmpty() \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/TypedMetaItem.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaItem.kt similarity index 92% rename from dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/TypedMetaItem.kt rename to dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaItem.kt index 94e4ff6a..bfc3a83c 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/TypedMetaItem.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaItem.kt @@ -18,10 +18,11 @@ public sealed class TypedMetaItem() { public companion object { public fun of(arg: Any?): MetaItem { return when (arg) { - null -> ValueItem(Null) + null -> Null.asMetaItem() is MetaItem -> arg - is Meta -> NodeItem(arg) - else -> ValueItem(Value.of(arg)) + is Meta -> arg.asMetaItem() + is ItemProvider -> arg.rootItem ?: Null.asMetaItem() + else -> Value.of(arg).asMetaItem() } } } diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt index 5ca6334a..3625162a 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MutableItemProvider.kt @@ -2,7 +2,6 @@ package hep.dataforge.meta import hep.dataforge.names.* import hep.dataforge.values.Value -import hep.dataforge.values.asValue public interface MutableItemProvider : ItemProvider { public fun setItem(name: Name, item: MetaItem?) @@ -30,15 +29,7 @@ public inline fun MutableItemProvider.remove(name: String): Unit = remove(name.t public operator fun MutableItemProvider.set(name: Name, value: Any?) { when (value) { null -> remove(name) - is Value -> set(name, value) - is Number -> set(name, value.asValue()) - is String -> set(name, value.asValue()) - is Boolean -> set(name, value.asValue()) - is MetaItem -> set(name, value) - is Meta -> set(name, value) - is MetaRepr -> set(name, value.toMeta()) - is Configurable -> set(name, value.config) - else -> set(name, Value.of(value)) + else -> set(name, MetaItem.of(value)) } } diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/TypedMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/TypedMeta.kt new file mode 100644 index 00000000..786054c1 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/TypedMeta.kt @@ -0,0 +1,51 @@ +package hep.dataforge.meta + +import hep.dataforge.names.Name +import hep.dataforge.names.NameToken +import hep.dataforge.names.toName +import kotlinx.serialization.json.Json + +/** + * A meta node that ensures that all of its descendants has at least the same type + */ +public interface TypedMeta> : Meta { + override val items: Map> + + @Suppress("UNCHECKED_CAST") + override fun getItem(name: Name): TypedMetaItem? = super.getItem(name)?.let { it as TypedMetaItem } + //Typed meta guarantees that all children have M type +} + + +/** + * The same as [Meta.get], but with specific node type + */ +public operator fun > M.get(name: Name): TypedMetaItem? = getItem(name) + + +public operator fun > M.get(key: String): TypedMetaItem? = this[key.toName()] +public operator fun > M.get(key: NameToken): TypedMetaItem? = items[key] + +/** + * Equals, hashcode and to string for any meta + */ +public abstract class MetaBase : Meta { + + override fun equals(other: Any?): Boolean = if (other is Meta) { + this.items == other.items + } else { + false + } + + override fun hashCode(): Int = items.hashCode() + + override fun toString(): String = Json { + prettyPrint = true + useArrayPolymorphism = true + }.encodeToString(MetaSerializer, this) +} + +/** + * Equals and hash code implementation for meta node + */ +public abstract class AbstractTypedMeta> : TypedMeta, MetaBase()