Skip to content

Commit

Permalink
Generate bit flags (#766)
Browse files Browse the repository at this point in the history
This PR adds bit flag classes to the code generation in Kord (see #686
for the reasoning of generating boilerplate heavy parts of Kord).

It also tries to unify the API shape of all existing bit flag classes by
deprecating some existing declarations and replacing them with
declarations that all bit flag classes have in common. They now have
this general API shape:

sealed class SomeFlag(val shift: Int) {
    val value: ValueType
    operator fun plus(flag: SomeFlag): SomeFlags
    operator fun plus(flags: SomeFlags): SomeFlags

    class Unknown : SomeFlag
    object Flag1 : SomeFlag
    object Flag2 : SomeFlag
    // ...

    companion object {
        val entries: List<SomeFlag>
        fun fromShift(shift: Int): SomeFlag
    }
}

@serializable
class SomeFlags(val value: ValueType) {
    val values: Set<SomeFlag>
    operator fun contains(flag: SomeFlag): Boolean
    operator fun contains(flags: SomeFlags): Boolean
    operator fun plus(flag: SomeFlag): SomeFlags
    operator fun plus(flags: SomeFlags): SomeFlags
    operator fun minus(flag: SomeFlag): SomeFlags
    operator fun minus(flags: SomeFlags): SomeFlags
    fun copy(builder: Builder.() -> Unit): SomeFlags

    class Builder(value: ValueType = /* ... */) {
        operator fun SomeFlag.unaryPlus()
        operator fun SomeFlags.unaryPlus()
        operator fun SomeFlag.unaryMinus()
        operator fun SomeFlags.unaryMinus()
        fun build(): SomeFlags
    }
}

fun SomeFlags(builder: SomeFlags.Builder.() -> Unit): SomeFlags
fun SomeFlags(vararg flags: SomeFlag): SomeFlags
fun SomeFlags(vararg flags: SomeFlags): SomeFlags
fun SomeFlags(flags: Iterable<SomeFlag>): SomeFlags
fun SomeFlags(flags: Iterable<SomeFlags>): SomeFlags

This means that flag classes are no longer enum classes. Binary
compatibility was preserved as far as possible, but the fact that these
classes now no longer have java.lang.Enum as their supertype is a binary
incompatible change.

This PR also

 * adds ActivityFlag.PartyPrivacyFriends,
   ActivityFlag.PartyPrivacyVoiceChannel and ActivityFlag.Embedded
   (these were missing before)

 * deprecates UserFlag.System (it was undocumented in 2021[1])

 * renames Intent.GuildBans to Intent.GuildModeration (see
   https://github.com/discord/discord-api-docs/pull/5849/files#diff-c24665b017972d8f7c266214d30655ea5e105826ef212048f9460632dd61e3df)

 * fixes a bug where .copy{ /* ... */ } would also modify the original
   instance for bit flags based on DiscordBitSet

 * fixes some minus functions that would toggle instead of remove bits
   (this.value xor other.value -> this.value and other.value.inv())

[1] discord/discord-api-docs@9293f0d490ac6acf9d627e429e5a8131b303b528S

---------

Co-authored-by: lukellmann <[email protected]>
  • Loading branch information
DRSchlaubi and lukellmann authored Aug 26, 2023
1 parent 9eee5e4 commit fc1d70f
Show file tree
Hide file tree
Showing 88 changed files with 8,532 additions and 1,615 deletions.
610 changes: 586 additions & 24 deletions common/api/common.api

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions common/src/commonMain/kotlin/Class.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dev.kord.common

import dev.kord.common.annotation.KordInternal
import kotlin.reflect.KClass

// TODO remove when enum artifacts are removed from generated flags

/** @suppress */
@Suppress("unused")
public expect class Class<T>

/** @suppress */
@KordInternal
public expect val <T : Any> KClass<T>.java: Class<T>
1 change: 1 addition & 0 deletions common/src/commonMain/kotlin/DiscordBitSet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public class DiscordBitSet(internal var data: LongArray) { // data is in little-
return "DiscordBitSet($binary)"
}

public fun copy(): DiscordBitSet = DiscordBitSet(data = data.copyOf())
}

public fun DiscordBitSet(vararg widths: Long): DiscordBitSet {
Expand Down
Loading

0 comments on commit fc1d70f

Please sign in to comment.