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
  • Loading branch information
0ffz committed May 31, 2024
1 parent 7c8968b commit 2f77116
Show file tree
Hide file tree
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
Expand Up @@ -4,6 +4,7 @@ build
target
out
*/out/production/
.kotlin

.classpath
.project
Expand Down
4 changes: 2 additions & 2 deletions addons/geary-autoscan/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions addons/geary-prefabs/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions addons/geary-serialization/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ kotlin {
sourceSets {
commonMain {
dependencies {
compileOnly(project(":geary-core"))
implementation(project(":geary-core"))

implementation(libs.uuid)
implementation(idofrontLibs.idofront.di)
Expand All @@ -20,7 +20,7 @@ kotlin {
}
jvmMain {
dependencies {
compileOnly(idofrontLibs.kotlinx.serialization.kaml)
implementation(idofrontLibs.kotlinx.serialization.kaml)
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion geary-benchmarks/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion geary-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ kotlin {
implementation(idofrontLibs.kotlin.reflect)

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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
Expand All @@ -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) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>() {
Expand All @@ -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() }

Expand All @@ -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
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Up @@ -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 2f77116

Please sign in to comment.