-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generate kord enums with KSP #686
Conversation
# Conflicts: # common/src/main/kotlin/entity/DiscordChannel.kt # core/src/main/kotlin/entity/channel/Channel.kt
# Conflicts: # build.gradle.kts # buildSrc/build.gradle.kts # buildSrc/src/main/kotlin/kord-module.gradle.kts # common/src/main/kotlin/entity/DiscordChannel.kt # common/src/main/kotlin/entity/DiscordMessage.kt # core/src/main/kotlin/gateway/handler/ThreadEventHandler.kt
# Conflicts: # common/src/main/kotlin/entity/DiscordChannel.kt
…resetType`, `AutoModerationRuleEventType` and `AutoModerationActionType`
…`ExplicitContentFilter`, `VerificationLevel`, `NsfwLevel` and `PremiumTier`
… `GuildScheduledEventStatus`
out/ | ||
dokka/ | ||
|
||
**/build/* | ||
!**/build/generated/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now I included the generated files by removing them from the .gitignore
. I'm not sure if this is the way we should do it, @DRSchlaubi had some other ideas before, what do you say?
public final class dev/kord/common/entity/WebhookType$Application : dev/kord/common/entity/WebhookType { | ||
public static final field INSTANCE Ldev/kord/common/entity/WebhookType$Application; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WebhookType.Application
is the only truly new API added in this PR (other API dump changes are only additions of equals()
, hashCode()
, toString()
, entries
, companion objects and deprecation artifacts)
PrivateThread -> TextChannelThread(data, kord) | ||
PublicGuildThread -> TextChannelThread(data, kord) | ||
PrivateThread, PublicGuildThread -> TextChannelThread(data, kord) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is just code deduplication
is ChannelType.PrivateThread, | ||
is ChannelType.GuildText -> TextChannelThreadDeleteEvent(channel, old as? TextChannelThread, shard, context?.get()) | ||
ChannelType.PrivateThread, | ||
ChannelType.PublicGuildThread -> TextChannelThreadDeleteEvent(channel, old as? TextChannelThread, shard, context?.get()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a bug: PublicGuildThread
s would result in an UnknownChannelThreadDeleteEvent
instead of a TextChannelThreadDeleteEvent
// TODO remove eventually | ||
/** For migration purposes. */ | ||
val valuesPropertyName: String = "", | ||
/** For migration purposes. */ | ||
val valuesPropertyType: ValuesPropertyType = NONE, | ||
/** For migration purposes. */ | ||
val deprecatedSerializerName: String = "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these are only added to preserve binary compatibility and will be removed eventually after the corresponding deprecation cycle
# Conflicts: # common/src/main/kotlin/entity/DiscordGuild.kt
48a3e0c
to
e418baf
Compare
This is ready |
does this mean that all Add x code are now redundant? |
Add x code? What do you mean? |
Error codes from other PRs |
Nope, I haven't touched |
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]>
This PR adds KSP and KotlinPoet to the project and introduces an annotation to generate "kord enums" (classes like
ChannelType
). All these classes are now generated with this annotation.We have a lot of sealed classes like
ChannelType
(representing this) that are very similar. They all have:I gave them the name "kord enums" because they are essentially enums with the ability to represent unknown cases.
Every time we add a new one of these classes (e.g. when discord adds a new feature), we have to write a lot of boilerplate to make the class similar to the existing ones. But it's easy to bring in slight variations which leads to inconsistent code over time.
Adding new subtypes to these classes can also be error-prone, since it requires adding the new type and also adding it in the serializer which can be easy to forget (see b75e33f).
This PR introduces a KSP processor to solve these problems. It allows us to define these classes via annotations which reduces boilerplate, keeps consistency across these classes and ensures a single point of truth for the value (we had the value in the subtype declaration and serializer before).
Another benefit is that when we want to change something about all these classes, we just have to adjust the processor.
In the future we might use KSP to also generate other boilerplate heavy parts of kord (flags, builders etc.).
This PR also
equals
,hashCode
andtoString
for every kord enum.WebhookType.Application
(was missing before).DiscordGuildApplicationCommandPermission.Type
withApplicationCommandPermissionType
because of technical reasons (can't generate nested classes).EmbedType
.entries
property in the companion object of every generated kord enum with typeList<KordEnumType>
that is a list of all known entries. The name is taken from Kotlin's upcomingEnum.entries
.UnknownChannelThreadDeleteEvent
instead ofTextChannelThreadDeleteEvent
.