Skip to content

Commit

Permalink
Update to Kotlin 1.5 (kordlib#299)
Browse files Browse the repository at this point in the history
* Update to 1.5.0-RC

* trigger on branch pushes

* Port to Kotlin 1.5 (kordlib#268)

* Port dependencies to Kotlin 1.5
- Convert AbstractRateLimiter.AbstractRequestToken to a static rather than an inner class due to a compiler bug
- Downgrade kx.ser-json to 1.0.0 to avoid a compiler bug
- Bump other Kotlin dependencies to latest

fixup! Port dependencies to Kotlin 1.5 - Convert AbstractRateLimiter.AbstractRequestToken to a static rather than an inner class due to a compiler bug - Downgrade kx.ser-json to 1.0.0 to avoid a compiler bug - Bump other Kotlin dependencies to latest

* Replace deprecated kotlin.time APIs

* Replace more deprecated APIs & inline classes

* Replace deprecated usage of time API in tests

* Possibly fix test

Co-authored-by: Hope <[email protected]>

* Port to Kotlin 1.5
- Bump dependencies to 1.5 recommended versions
- Remove inline classes in favor of value classes
- Add required opt-ins
- Migrate some more deprecated apis

* Fix some gradle issues

* Fix Gradle compilation issue

* Remove documentationFileName as the new dokka version doesn't support it anymore and there is no replacement yet

* Port kotlinx.serialization to 1.2.0 (kordlib#279)

* Port kotlinx.serialization to 1.2.0
- Convert local classes to top level classes (See Kotlin/kotlinx.serialization#1472)
- Improve handling of empty JSON bodies (See Kotlin/kotlinx.serialization#678)
- Fix Failing Command test

* Fix failing test

* Properly decode null in gateway events (kordlib#286)

* Properly decode null in gateway events

* Update gateway/src/main/kotlin/Event.kt

Co-authored-by: Bart Arys <[email protected]>

Co-authored-by: Bart Arys <[email protected]>

* Update Kotlinx.serialization (kordlib#290)

* Update Kotlin 1.5 branch to upstream (kordlib#292)

* Implement voice stage channel (kordlib#239)

* compute All

* implement rest endpoints

* JSON representation

* implement core representation

* handle stage channels

* Apply suggestions

Co-authored-by: BartArys <[email protected]>

* Remove duplicated factory function
Co-authored-by: BartArys <[email protected]>

* add documentation

* Document the requestToSpeak variable

Co-authored-by: BartArys <[email protected]>

* Fix CI triggers

* Add "Competing" activity type (Fix kordlib#270) (kordlib#272)

* Make Updatestatus activities not-null (kordlib#274)

As per Discord's documentation: discord/discord-api-docs#2789

* Fix memory issues related to Permission combining (kordlib#277)

* Do not octuple bitset size on copy

the pure plus and minus function create a new array to work with, this incorrectly created an array of a size equal to the amount of bits that were allocated, instead the amount of longs. Thus, octupling the internal size.

* Optimize Permission All

The All Permission folded each DiscordBitSet of each value into eachother, resulting in n + 1 bitsets being created. This commit changes that to use the internal `add` which instead, which only mutates the single bitset created.

* Add Stream permission

It was missing

* Add Permission All regression tests

* Update deprecated message (kordlib#280)

* Expose the creation of application commands behavior (kordlib#281)

* Fix GuildUpdate core handling (kordlib#284)

* Expose the creation of application commands behavior

* Fix type of emitted event

* Sealed message types (kordlib#282)

* Expose the creation of application commands behavior

* Make message types sealed

* make Unknown a class

* Add missing message types

* make MessageTypeSerializer internal

* Add buttons to Activity (kordlib#287)

* Add buttons to Activity

* Also pass buttons in constructor

* Add missing fields to Guild (kordlib#288)

* Add missing fields to Guild
- Add welcome_screen
- Add nsfw

* Fix failing tests

* Fix another failing tests

* Add Message.applicationId (kordlib#289)

Co-authored-by: Hope <[email protected]>
Co-authored-by: BartArys <[email protected]>
Co-authored-by: HopeBaron <[email protected]>
Co-authored-by: Bart Arys <[email protected]>
Co-authored-by: Noah Hendrickson <[email protected]>

* Fix broken CI (kordlib#293)

* Migrate to kotlinx-datetime (kordlib#297)

* Migrate API code to kotlinx-datetime

* Update tests

* Remove dead code

* Replace iso serializing with kx.dt

* Bump dependencies to Kotlin 1.5.10 (kordlib#305)

* Bump dependencies to Kotlin 1.5.10
- Fix sample code

* Update remaining dependencies

* Update ktor to 1.6.0

Co-authored-by: HopeBaron <[email protected]>
Co-authored-by: Michael Rittmeister <[email protected]>
Co-authored-by: Hope <[email protected]>
Co-authored-by: Noah Hendrickson <[email protected]>
  • Loading branch information
5 people committed Jun 7, 2021
1 parent e3a7c57 commit fb82421
Show file tree
Hide file tree
Showing 64 changed files with 392 additions and 376 deletions.
5 changes: 2 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.apache.commons.codec.binary.Base64
buildscript {
repositories {
jcenter()
mavenCentral()
maven(url = "https://plugins.gradle.org/m2/")
}
dependencies {
Expand All @@ -20,7 +21,7 @@ buildscript {

plugins {
id("org.jetbrains.kotlin.jvm") version Versions.kotlin
id("org.jetbrains.dokka") version "1.4.0"
id("org.jetbrains.dokka") version "1.4.30"
id("org.ajoberstar.git-publish") version "2.1.3"

signing
Expand All @@ -32,7 +33,6 @@ apply(plugin = "binary-compatibility-validator")

repositories {
mavenCentral()
jcenter()
mavenLocal()
}

Expand Down Expand Up @@ -218,7 +218,6 @@ tasks {
dokkaHtmlMultiModule.configure {
dependsOn(clean)
outputDirectory.set(file(dokkaOutputDir))
documentationFileName.set("DokkaDescription.md")
}


Expand Down
2 changes: 1 addition & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repositories {
}

dependencies {
implementation(kotlin("gradle-plugin-api", version = "1.4.0"))
implementation(kotlin("gradle-plugin-api", version = "1.5.0"))
implementation(gradleApi())
implementation(localGroovy())
}
1 change: 0 additions & 1 deletion buildSrc/src/main/kotlin/Compiler.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
object CompilerArguments {
const val inlineClasses = "-XXLanguage:+InlineClasses"
const val coroutines = "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
const val time = "-Xopt-in=kotlin.time.ExperimentalTime"
const val stdLib = "-Xopt-in=kotlin.ExperimentalStdlibApi"
Expand Down
16 changes: 9 additions & 7 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
object Versions {
const val kotlin = "1.4.32"
const val kotlinxSerialization = "1.1.0"
const val ktor = "1.5.2"
const val kotlinxCoroutines = "1.4.2"
const val kotlinLogging = "2.0.4"
const val atomicFu = "0.15.1"
const val binaryCompatibilityValidator = "0.4.0"
const val kotlin = "1.5.10"
const val kotlinxSerialization = "1.2.1"
const val ktor = "1.6.0"
const val kotlinxCoroutines = "1.5.0"
const val kotlinLogging = "2.0.6"
const val dateTime = "0.2.1"
const val atomicFu = "0.16.1"
const val binaryCompatibilityValidator = "0.5.0"

//test deps
const val kotlinTest = kotlin
Expand All @@ -28,6 +29,7 @@ object Dependencies {
"org.jetbrains.kotlinx:kotlinx-serialization-json:${Versions.kotlinxSerialization}"
const val `kotlinx-coroutines` = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinxCoroutines}"
const val `kotlinx-atomicfu` = "org.jetbrains.kotlinx:atomicfu-jvm:${Versions.atomicFu}"
const val `kotlinx-datetime` = "org.jetbrains.kotlinx:kotlinx-datetime:${Versions.dateTime}"

const val `kotlin-logging` = "io.github.microutils:kotlin-logging:${Versions.kotlinLogging}"

Expand Down
5 changes: 4 additions & 1 deletion common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ configurations {
}
}

dependencies {
api(Dependencies.`kotlinx-datetime`)
}

tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = Jvm.target
freeCompilerArgs = listOf(
CompilerArguments.inlineClasses,
CompilerArguments.coroutines,
CompilerArguments.time,
CompilerArguments.optIn
Expand Down
14 changes: 6 additions & 8 deletions common/src/main/kotlin/entity/Snowflake.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package dev.kord.common.entity

import kotlinx.datetime.Clock
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import java.time.Instant
import kotlinx.datetime.Instant
import kotlin.time.Duration
import kotlin.time.TimeMark
import kotlin.time.toKotlinDuration

/**
* A unique identifier for entities [used by discord](https://discord.com/developers/docs/reference#snowflakes).
Expand All @@ -28,11 +28,11 @@ class Snowflake(val value: Long) : Comparable<Snowflake> {
/**
* Creates a Snowflake from a given [instant].
*/
constructor(instant: Instant) : this((instant.toEpochMilli() shl 22) - discordEpochLong)
constructor(instant: Instant) : this((instant.toEpochMilliseconds() shl 22) - discordEpochLong)

val asString get() = value.toString()

val timeStamp: Instant get() = Instant.ofEpochMilli(discordEpochLong + (value shr 22))
val timeStamp: Instant get() = Instant.fromEpochMilliseconds(discordEpochLong + (value shr 22))

val timeMark: TimeMark get() = SnowflakeMark(value shr 22)

Expand All @@ -48,7 +48,7 @@ class Snowflake(val value: Long) : Comparable<Snowflake> {

companion object {
private const val discordEpochLong = 1420070400000L
val discordEpochStart: Instant = Instant.ofEpochMilli(discordEpochLong)
val discordEpochStart: Instant = Instant.fromEpochMilliseconds(discordEpochLong)

/**
* The maximum value a Snowflake can hold.
Expand Down Expand Up @@ -78,7 +78,5 @@ class Snowflake(val value: Long) : Comparable<Snowflake> {

private class SnowflakeMark(val epochMilliseconds: Long) : TimeMark() {

override fun elapsedNow(): Duration =
java.time.Duration.between(Instant.ofEpochMilli(epochMilliseconds), Instant.now()).toKotlinDuration()

override fun elapsedNow(): Duration = Instant.fromEpochMilliseconds(epochMilliseconds) - Clock.System.now()
}
16 changes: 7 additions & 9 deletions common/src/main/kotlin/ratelimit/BucketRateLimiter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package dev.kord.common.ratelimit

import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.time.Clock
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlin.time.Duration
import kotlin.time.milliseconds
import kotlin.time.toKotlinDuration
import java.time.Duration as JavaDuration


/**
Expand All @@ -19,30 +17,30 @@ import java.time.Duration as JavaDuration
class BucketRateLimiter(
private val capacity: Int,
private val refillInterval: Duration,
private val clock: Clock = Clock.systemUTC()
private val clock: Clock = Clock.System
) : RateLimiter {

private val mutex = Mutex()

private var count = 0
private var nextInterval = 0L
private var nextInterval = Instant.fromEpochMilliseconds(0)

init {
require(capacity > 0) { "capacity must be a positive number" }
require(refillInterval.isPositive()) { "refill interval must be positive" }
}

private val isNextInterval get() = nextInterval <= clock.millis()
private val isNextInterval get() = nextInterval <= clock.now()

private val isAtCapacity get() = count == capacity

private fun resetState() {
count = 0
nextInterval = clock.millis() + refillInterval.inMilliseconds.toLong()
nextInterval = clock.now() + refillInterval
}

private suspend fun delayUntilNextInterval() {
val delay = nextInterval - clock.millis()
val delay = nextInterval - clock.now()
kotlinx.coroutines.delay(delay)
}

Expand Down
8 changes: 8 additions & 0 deletions common/src/test/kotlin/FixedClock.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant

fun Clock.Companion.fixed(instant: Instant): Clock = FixedClock(instant)

private class FixedClock(private val instant: Instant): Clock {
override fun now(): Instant = instant
}
23 changes: 12 additions & 11 deletions common/src/test/kotlin/entity/optional/OptionalBooleanTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,42 @@ import org.junit.jupiter.api.Test

internal class OptionalBooleanTest {

@Serializable
private class EmptyOptionalEntity(val value: OptionalBoolean = OptionalBoolean.Missing)

@Test
fun `deserializing nothing in optional assigns Missing`(){
@Language("json")
val json = """{}"""

@Serializable
class Entity(val value: OptionalBoolean = OptionalBoolean.Missing)

val entity = Json.decodeFromString<Entity>(json)
val entity = Json.decodeFromString<EmptyOptionalEntity>(json)

assert(entity.value is OptionalBoolean.Missing)
}

@Serializable
private class NullOptionalEntity(@Suppress("unused") val value: OptionalBoolean = OptionalBoolean.Missing)

@Test
fun `deserializing null in optional throws SerializationException`(){
@Language("json")
val json = """{ "value":null }"""

@Serializable
class Entity(@Suppress("unused") val value: OptionalBoolean = OptionalBoolean.Missing)

org.junit.jupiter.api.assertThrows<SerializationException> {
Json.decodeFromString<Entity>(json)
Json.decodeFromString<NullOptionalEntity>(json)
}
}

@Serializable
private class ValueOptionalEntity(@Suppress("unused") val value: OptionalBoolean = OptionalBoolean.Missing)

@Test
fun `deserializing value in optional assigns Value`(){
@Language("json")
val json = """{ "value":true }"""

@Serializable
class Entity(@Suppress("unused") val value: OptionalBoolean = OptionalBoolean.Missing)

val entity = Json.decodeFromString<Entity>(json)
val entity = Json.decodeFromString<ValueOptionalEntity>(json)
require(entity.value is OptionalBoolean.Value)

Assertions.assertEquals(true, entity.value.value)
Expand Down
24 changes: 13 additions & 11 deletions common/src/test/kotlin/entity/optional/OptionalIntTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,43 @@ import org.junit.jupiter.api.Test

internal class OptionalIntTest {

@Serializable
private class EmptyOptionalEntity(val value: OptionalInt = OptionalInt.Missing)

@Test
fun `deserializing nothing in optional assigns Missing`(){
@Language("json")
val json = """{}"""

@Serializable
class Entity(val value: OptionalInt = OptionalInt.Missing)

val entity = Json.decodeFromString<Entity>(json)
val entity = Json.decodeFromString<EmptyOptionalEntity>(json)

assert(entity.value is OptionalInt.Missing)
}


@Serializable
private class NullOptionalEntity(@Suppress("unused") val value: OptionalInt = OptionalInt.Missing)

@Test
fun `deserializing null in optional throws SerializationException`(){
@Language("json")
val json = """{ "value":null }"""

@Serializable
class Entity(@Suppress("unused") val value: OptionalInt = OptionalInt.Missing)

org.junit.jupiter.api.assertThrows<SerializationException> {
Json.decodeFromString<Entity>(json)
Json.decodeFromString<NullOptionalEntity>(json)
}
}

@Serializable
class ValueOptionalEntity(@Suppress("unused") val value: OptionalInt = OptionalInt.Missing)

@Test
fun `deserializing value in optional assigns Value`(){
@Language("json")
val json = """{ "value":5 }"""

@Serializable
class Entity(@Suppress("unused") val value: OptionalInt = OptionalInt.Missing)

val entity = Json.decodeFromString<Entity>(json)
val entity = Json.decodeFromString<ValueOptionalEntity>(json)
require(entity.value is OptionalInt.Value)

assertEquals(5, entity.value.value)
Expand Down
30 changes: 17 additions & 13 deletions common/src/test/kotlin/entity/optional/OptionalLongTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,45 @@ import org.junit.jupiter.api.Test

internal class OptionalLongTest {

@Serializable
class EmptyOptionalEntity(val value: OptionalLong = OptionalLong.Missing)

@Test
fun `deserializing nothing in optional assigns Missing`(){
fun `deserializing nothing in optional assigns Missing`() {
@Language("json")
val json = """{}"""

@Serializable
class Entity(val value: OptionalLong = OptionalLong.Missing)

val entity = Json.decodeFromString<Entity>(json)
val entity = Json.decodeFromString<EmptyOptionalEntity>(json)

assert(entity.value is OptionalLong.Missing)
}


@Serializable
class NullOptionalEntity(@Suppress("unused") val value: OptionalLong = OptionalLong.Missing)

@Test
fun `deserializing null in optional throws SerializationException`(){
fun `deserializing null in optional throws SerializationException`() {
@Language("json")
val json = """{ "value":null }"""

@Serializable
class Entity(@Suppress("unused") val value: OptionalLong = OptionalLong.Missing)

org.junit.jupiter.api.assertThrows<SerializationException> {
Json.decodeFromString<Entity>(json)
Json.decodeFromString<NullOptionalEntity>(json)
}
}


@Serializable
class ValueOptionalEntity(@Suppress("unused") val value: OptionalLong = OptionalLong.Missing)

@Test
fun `deserializing value in optional assigns Value`(){
fun `deserializing value in optional assigns Value`() {
@Language("json")
val json = """{ "value":5 }"""

@Serializable
class Entity(@Suppress("unused") val value: OptionalLong = OptionalLong.Missing)

val entity = Json.decodeFromString<Entity>(json)
val entity = Json.decodeFromString<ValueOptionalEntity>(json)
require(entity.value is OptionalLong.Value)

Assertions.assertEquals(5, entity.value.value)
Expand Down
Loading

0 comments on commit fb82421

Please sign in to comment.