Skip to content

Commit

Permalink
chore: Update idofront, kotlin 2.0.0, other deps
Browse files Browse the repository at this point in the history
chore: Add shorthand queries up to size 5
chore: Add family filter to any size query
feat: Nullable types in shorthand queries
0ffz committed May 31, 2024
1 parent b53177e commit 5c6c79d
Showing 15 changed files with 177 additions and 35 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ build
target
out
*/out/production/
.kotlin

.classpath
.project
4 changes: 2 additions & 2 deletions addons/geary-autoscan/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -5,8 +5,8 @@ plugins {
}

dependencies {
compileOnly(project(":geary-core"))
compileOnly(project(":geary-serialization"))
implementation(project(":geary-core"))
implementation(project(":geary-serialization"))

implementation(idofrontLibs.reflections)
implementation(idofrontLibs.kotlin.reflect)
4 changes: 2 additions & 2 deletions addons/geary-prefabs/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -8,8 +8,8 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
compileOnly(project(":geary-core"))
compileOnly(project(":geary-serialization"))
implementation(project(":geary-core"))
implementation(project(":geary-serialization"))

implementation(libs.uuid)
implementation(idofrontLibs.idofront.di)
4 changes: 2 additions & 2 deletions addons/geary-serialization/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ kotlin {
sourceSets {
commonMain {
dependencies {
compileOnly(project(":geary-core"))
implementation(project(":geary-core"))

implementation(libs.uuid)
implementation(idofrontLibs.idofront.di)
@@ -20,7 +20,7 @@ kotlin {
}
jvmMain {
dependencies {
compileOnly(idofrontLibs.kotlinx.serialization.kaml)
implementation(idofrontLibs.kotlinx.serialization.kaml)
}
}
}
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@ plugins {
alias(idofrontLibs.plugins.kotlin.multiplatform)
alias(idofrontLibs.plugins.dokka)
alias(idofrontLibs.plugins.mia.autoversion)
alias(idofrontLibs.plugins.dependencyversions)
alias(idofrontLibs.plugins.version.catalog.update)
}

allprojects {
2 changes: 1 addition & 1 deletion geary-benchmarks/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ configure<AllOpenExtension> {

dependencies {
implementation(project(":geary-core"))
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.9")
implementation(libs.kotlinx.benchmark.runtime)
}

benchmark {
2 changes: 1 addition & 1 deletion geary-core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ kotlin {
implementation(idofrontLibs.kotlin.reflect)

api(idofrontLibs.idofront.di)
api(libs.kermit)
api(idofrontLibs.kermit)
api(idofrontLibs.kotlinx.coroutines)
}

Original file line number Diff line number Diff line change
@@ -18,6 +18,12 @@ interface ExecutableObserver<Context> {
handle(query)
}
}

fun <Q1 : Query, Q2: Query> exec(query1: Q1, query2: Q2,handle: Context.(Q1, Q2) -> Unit): Observer {
return filter(query1).filter(query2).exec {
handle(query1, query2)
}
}
}

data class QueryInvolvingObserverBuilder<Context, Q : ShorthandQuery>(
Original file line number Diff line number Diff line change
@@ -72,6 +72,14 @@ abstract class ObserverEventsBuilder<Context> : ExecutableObserver<Context> {
return ObserverBuilder(this, entityTypeOf(cId<A>(), cId<B>(), cId<C>()))
}

inline fun <reified A : Any, reified B : Any, reified C : Any, reified D : Any> involving(size4: QueryShorthands.Size4? = null): ObserverBuilder<Context> {
return ObserverBuilder(this, entityTypeOf(cId<A>(), cId<B>(), cId<C>(), cId<D>()))
}

inline fun <reified A : Any, reified B : Any, reified C : Any, reified D : Any, reified E : Any> involving(size5: QueryShorthands.Size5? = null): ObserverBuilder<Context> {
return ObserverBuilder(this, entityTypeOf(cId<A>(), cId<B>(), cId<C>(), cId<D>(), cId<E>()))
}

fun involvingAny(): ObserverBuilder<Context> {
return ObserverBuilder(this, entityTypeOf())
}
Original file line number Diff line number Diff line change
@@ -8,6 +8,6 @@ interface Accessor {
val originalAccessor: Accessor?
}

interface ReadOnlyAccessor<T> : Accessor, ReadOnlyProperty<Query, T>
interface ReadOnlyAccessor<out T> : Accessor, ReadOnlyProperty<Query, T>

interface ReadWriteAccessor<T> : ReadOnlyAccessor<T>, ReadWriteProperty<Query, T>
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ import com.mineinabyss.geary.helpers.componentId
import com.mineinabyss.geary.helpers.componentIdWithNullable
import com.mineinabyss.geary.systems.accessors.type.*
import com.mineinabyss.geary.systems.query.QueriedEntity
import kotlin.reflect.typeOf

abstract class AccessorOperations {
abstract val cacheAccessors: Boolean
@@ -26,6 +27,17 @@ abstract class AccessorOperations {
}
}

protected inline fun <reified T> QueriedEntity.getPotentiallyNullable(): ReadOnlyAccessor<T> {
val t = typeOf<T>()
return addAccessor {
val id = componentId(t).withRole(HOLDS_DATA)
val compAccessor = ComponentAccessor<T & Any>(null, id)
if(t.isMarkedNullable)
ComponentOrDefaultAccessor<T?>(compAccessor, id) { null }
else compAccessor
} as ReadOnlyAccessor<T>
}

/** Accesses a data stored in a relation with kind [K] and target type [T], ensuring it is on the entity. */
protected inline fun <reified K : Any, reified T : Any> QueriedEntity.getRelation(): ComponentAccessor<T> {
return addAccessor { ComponentAccessor(null, Relation.of<K, T>().id) }
Original file line number Diff line number Diff line change
@@ -36,13 +36,40 @@ abstract class ShorthandQuery3<A, B, C> : ShorthandQuery() {
abstract operator fun component3(): C
}

abstract class ShorthandQuery4<A, B, C, D> : ShorthandQuery() {
abstract val comp1: A
abstract val comp2: B
abstract val comp3: C
abstract val comp4: D

abstract operator fun component1(): A
abstract operator fun component2(): B
abstract operator fun component3(): C
abstract operator fun component4(): D
}

abstract class ShorthandQuery5<A, B, C, D, E> : ShorthandQuery() {
abstract val comp1: A
abstract val comp2: B
abstract val comp3: C
abstract val comp4: D
abstract val comp5: E

abstract operator fun component1(): A
abstract operator fun component2(): B
abstract operator fun component3(): C
abstract operator fun component4(): D
abstract operator fun component5(): E
}


fun query() = object : Query() {}

fun query(match: MutableFamily.Selector.And.() -> Unit) = object : Query() {
override fun ensure() = this { add(family(match)) }
}

inline fun <reified A : Any> query(
inline fun <reified A> query(
size1: QueryShorthands.Size1? = null,
noinline filterFamily: (MutableFamily.Selector.And.() -> Unit)? = null
) = object : ShorthandQuery1<A>() {
@@ -51,36 +78,88 @@ inline fun <reified A : Any> query(
filterFamily?.let { this { it() } }
}

override val comp1 by get<A>()
override val comp1 by getPotentiallyNullable<A>()

override fun component1() = comp1
}

inline fun <reified A : Any, reified B : Any> query(size2: QueryShorthands.Size2? = null) =
object : ShorthandQuery2<A, B>() {
override val involves = entityTypeOf(cId<A>(), cId<B>())
inline fun <reified A, reified B> query(
size2: QueryShorthands.Size2? = null,
noinline filterFamily: (MutableFamily.Selector.And.() -> Unit)? = null,
) = object : ShorthandQuery2<A, B>() {
override val involves = entityTypeOf(cId<A>(), cId<B>())
override fun ensure() {
filterFamily?.let { this { it() } }
}

override val comp1 by getPotentiallyNullable<A>()
override val comp2 by getPotentiallyNullable<B>()

override fun component1(): A = comp1
override fun component2(): B = comp2
}

override val comp1 by get<A>()
override val comp2 by get<B>()

override fun component1(): A = comp1
override fun component2(): B = comp2
inline fun <reified A, reified B, reified C> query(
size3: QueryShorthands.Size3? = null,
noinline filterFamily: (MutableFamily.Selector.And.() -> Unit)? = null,
) = object : ShorthandQuery3<A, B, C>() {
override val involves = entityTypeOf(cId<A>(), cId<B>(), cId<C>())
override fun ensure() {
filterFamily?.let { this { it() } }
}

override val comp1 by getPotentiallyNullable<A>()
override val comp2 by getPotentiallyNullable<B>()
override val comp3 by getPotentiallyNullable<C>()

inline fun <reified A : Any, reified B : Any, reified C : Any> query(size3: QueryShorthands.Size3? = null) =
object : ShorthandQuery3<A, B, C>() {
override val involves = entityTypeOf(cId<A>(), cId<B>(), cId<C>())
override fun component1(): A = comp1
override fun component2(): B = comp2
override fun component3(): C = comp3
}

override val comp1 by get<A>()
override val comp2 by get<B>()
override val comp3 by get<C>()
inline fun <reified A, reified B, reified C, reified D> query(
size4: QueryShorthands.Size4? = null,
noinline filterFamily: (MutableFamily.Selector.And.() -> Unit)? = null,
) = object : ShorthandQuery4<A, B, C, D>() {
override val involves = entityTypeOf(cId<A>(), cId<B>(), cId<C>(), cId<D>())
override fun ensure() {
filterFamily?.let { this { it() } }
}

override val comp1 by getPotentiallyNullable<A>()
override val comp2 by getPotentiallyNullable<B>()
override val comp3 by getPotentiallyNullable<C>()
override val comp4 by getPotentiallyNullable<D>()

override fun component1(): A = comp1
override fun component2(): B = comp2
override fun component3(): C = comp3
override fun component4(): D = comp4
}

override fun component1(): A = comp1
override fun component2(): B = comp2
override fun component3(): C = comp3
inline fun <reified A, reified B, reified C, reified D, reified E> query(
size5: QueryShorthands.Size5? = null,
noinline filterFamily: (MutableFamily.Selector.And.() -> Unit)? = null,
) = object : ShorthandQuery5<A, B, C, D, E>() {
override val involves = entityTypeOf(cId<A>(), cId<B>(), cId<C>(), cId<D>())
override fun ensure() {
filterFamily?.let { this { it() } }
}

override val comp1 by getPotentiallyNullable<A>()
override val comp2 by getPotentiallyNullable<B>()
override val comp3 by getPotentiallyNullable<C>()
override val comp4 by getPotentiallyNullable<D>()
override val comp5 by getPotentiallyNullable<E>()

override fun component1(): A = comp1
override fun component2(): B = comp2
override fun component3(): C = comp3
override fun component4(): D = comp4
override fun component5(): E = comp5
}

@JvmName("toList1")
inline fun <T> CachedQuery<ShorthandQuery1<T>>.toList(): List<T> = map { it.component1() }

@@ -95,4 +174,6 @@ object QueryShorthands {
sealed class Size1
sealed class Size2
sealed class Size3
sealed class Size4
sealed class Size5
}
Original file line number Diff line number Diff line change
@@ -5,7 +5,14 @@ import com.mineinabyss.geary.helpers.entity
import com.mineinabyss.geary.helpers.tests.GearyTest
import com.mineinabyss.geary.modules.geary
import com.mineinabyss.geary.systems.query.Query
import com.mineinabyss.geary.systems.query.query
import com.mineinabyss.geary.systems.query.toList
import io.kotest.assertions.assertSoftly
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.assertions.withClue
import io.kotest.matchers.collections.shouldContain
import io.kotest.matchers.collections.shouldContainAll
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.shouldBe
import org.junit.jupiter.api.BeforeAll
import kotlin.test.Test
@@ -94,4 +101,24 @@ class SimpleQueryTest : GearyTest() {
}.map { it.int.toString() }.toList()
}
}

@Test
fun `should allow querying nullable types as optional in shorthand queries`() {
entity {
set<Int>(1)
set("Both")
}
entity {
set("Only string")
}
val query = geary.queryManager.trackQuery(query<Int, String?>())
val matched = query.toList()
assertSoftly(matched) {
shouldContainAll((0..9 step 2).map { it to null })
shouldContain(1 to "Both")
withClue("Should not include anything else") {
shouldHaveSize(11)
}
}
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -2,5 +2,5 @@ group=com.mineinabyss
version=0.26
# Workaround for dokka builds failing on CI, see https://github.com/Kotlin/dokka/issues/1405
#org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m
idofrontVersion=0.24.0-dev.2
idofrontVersion=0.24.0
kotlin.native.ignoreDisabledTargets=true
19 changes: 12 additions & 7 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
[versions]
androidxCollection = "1.4.0"
atomicfu = "0.24.0"
kotlinxBenchmarkRuntime = "0.4.10"
okio = "3.9.0"
roaringbitmap = "1.0.6"
statelyConcurrency = "2.0.7"
uuid = "0.8.4"

[libraries]
androidx-collection = { module = "androidx.collection:collection", version.ref = "androidxCollection" }
atomicfu = { module = "org.jetbrains.kotlinx:atomicfu", version.ref = "atomicfu" }
uuid = "com.benasher44:uuid:0.8.1"
okio = "com.squareup.okio:okio:3.5.0"
roaringbitmap = "org.roaringbitmap:RoaringBitmap:0.9.32"
bitvector = "net.onedaybeard.bitvector:bitvector-js:0.1.4"
kermit = "co.touchlab:kermit:1.2.2"
androidx-collection = "androidx.collection:collection:1.4.0"
stately-concurrency = "co.touchlab:stately-concurrency:2.0.7"
kotlinx-benchmark-runtime = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime", version.ref = "kotlinxBenchmarkRuntime" }
okio = { module = "com.squareup.okio:okio", version.ref = "okio" }
roaringbitmap = { module = "org.roaringbitmap:RoaringBitmap", version.ref = "roaringbitmap" }
stately-concurrency = { module = "co.touchlab:stately-concurrency", version.ref = "statelyConcurrency" }
uuid = { module = "com.benasher44:uuid", version.ref = "uuid" }

0 comments on commit 5c6c79d

Please sign in to comment.