Kotlin 1.3.70 and some dependency upgrades

parent bfd19009
Pipeline #15442 passed with stages
in 5 minutes and 53 seconds
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.gradle.DokkaTask
import org.jetbrains.dokka.gradle.LinkMapping
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
if (!JavaVersion.current().isJava8Compatible)
error("Only JDK 8 or newer is supported!")
plugins {
kotlin("jvm") version "1.3.61"
kotlin("plugin.serialization") version "1.3.61"
id("org.jetbrains.dokka") version "0.9.18"
kotlin("jvm") version "1.3.70"
kotlin("plugin.serialization") version "1.3.70"
id("org.jetbrains.dokka") version "0.10.1"
}
repositories {
jcenter()
}
val ktorVersion = "1.2.6"
val junitVersion = "5.5.2"
val ktorVersion = "1.3.1"
val junitVersion = "5.6.0"
val aspectjVersion = "1.9.5"
dependencies {
......@@ -28,20 +26,20 @@ dependencies {
implementation(kotlin("stdlib-jdk8"))
// Coroutines
implementation("org.jetbrains.kotlinx", "kotlinx-coroutines-core", "1.3.2")
implementation("org.jetbrains.kotlinx", "kotlinx-coroutines-core", "1.3.3")
// Kotlin serialization
implementation("org.jetbrains.kotlinx", "kotlinx-serialization-runtime", "0.14.0")
implementation("org.jetbrains.kotlinx", "kotlinx-serialization-runtime", "0.20.0")
// OpenJFX
if (JavaVersion.current().isJava11Compatible) {
for (pkg in listOf("base", "controls", "fxml", "graphics"))
for (os in listOf("linux", "mac", "win"))
implementation("org.openjfx", "javafx-$pkg", "13.0.1", classifier = os)
implementation("org.openjfx", "javafx-$pkg", "13.0.2", classifier = os)
}
// Provides RichText TextAreas. Used for code input area.
implementation("org.fxmisc.richtext", "richtextfx", "0.10.3")
implementation("org.fxmisc.richtext", "richtextfx", "0.10.4")
// Google GSON library for JSON
implementation("com.google.code.gson", "gson", "2.8.6")
......@@ -58,19 +56,19 @@ dependencies {
implementation("io.ktor", "ktor-freemarker", ktorVersion)
// http4k WebSocket client library
implementation("org.http4k", "http4k-client-websocket", "3.200.0")
implementation("org.http4k", "http4k-client-websocket", "3.239.0")
// AspectJ runtime
runtimeOnly("org.aspectj", "aspectjrt", aspectjVersion)
// NOP (no-operation) logger implementation
runtimeOnly("org.slf4j", "slf4j-nop", "1.7.29")
runtimeOnly("org.slf4j", "slf4j-nop", "1.7.30")
testImplementation("org.junit.jupiter", "junit-jupiter-api", junitVersion)
testImplementation("org.junit.jupiter", "junit-jupiter-params", junitVersion)
testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine", junitVersion)
testImplementation("org.mockito", "mockito-junit-jupiter", "3.2.0")
testImplementation("org.mockito", "mockito-junit-jupiter", "3.3.0")
}
version = "2.0.3"
......@@ -261,48 +259,47 @@ pseucoJavaCompilerProject.tasks {
/* --- Dokka --- */
val dokka by tasks.getting(DokkaTask::class) {
jdkVersion = 8
impliedPlatforms = mutableListOf("JVM")
includeNonPublic = true
externalDocumentationLink {
if (JavaVersion.current().isJava11Compatible) {
val path = "https://openjfx.io/javadoc/${dependencyVersion("javafx").substringBefore(".")}/"
url = url(path)
packageListUrl = url(path + "element-list")
} else
url = url("https://docs.oracle.com/javase/8/javafx/api/")
}
externalDocumentationLink {
url = url("https://fxmisc.github.io/richtext/javadoc/${dependencyVersion("richtextfx")}/")
}
configuration {
jdkVersion = 8
includeNonPublic = true
externalDocumentationLink {
if (JavaVersion.current().isJava11Compatible) {
val path = "https://openjfx.io/javadoc/${dependencyVersion("javafx").substringBefore(".")}/"
url = url(path)
packageListUrl = url(path + "element-list")
} else
url = url("https://docs.oracle.com/javase/8/javafx/api/")
}
externalDocumentationLink {
url = url("https://www.javadoc.io/com.google.code.gson/gson/${dependencyVersion("gson")}/")
packageListUrl = url("$url/element-list")
}
externalDocumentationLink {
url = url("https://fxmisc.github.io/richtext/javadoc/${dependencyVersion("richtextfx")}/")
}
externalDocumentationLink {
url = url("https://commons.apache.org/proper/commons-lang/javadocs/api-${dependencyVersion("commons-lang3")}/")
}
externalDocumentationLink {
url = url("https://www.javadoc.io/com.google.code.gson/gson/${dependencyVersion("gson")}/")
packageListUrl = url("$url/element-list")
}
externalDocumentationLink {
url = url("https://commons.apache.org/proper/commons-io/javadocs/api-${dependencyVersion("commons-io")}/")
}
externalDocumentationLink {
url = url("https://commons.apache.org/proper/commons-lang/javadocs/api-${dependencyVersion("commons-lang3")}/")
}
externalDocumentationLink {
url = url("https://http4k.org/api/")
}
externalDocumentationLink {
url = url("https://commons.apache.org/proper/commons-io/javadocs/api-${dependencyVersion("commons-io")}/")
}
externalDocumentationLink {
url = url("https://api.ktor.io/$ktorVersion/")
}
externalDocumentationLink {
url = url("https://http4k.org/api/")
}
linkMapping {
dir = "src/main/kotlin"
url = "https://dgit.cs.uni-saarland.de/pseuco/pseuco-ide/blob/master/src/main/kotlin"
suffix = "#L"
sourceLink {
path = "src/main/kotlin"
url = "https://dgit.cs.uni-saarland.de/pseuco/pseuco-ide/blob/master/src/main/kotlin"
lineSuffix = "#L"
}
}
}
......@@ -312,11 +309,6 @@ fun String.exec(): Process = Runtime.getRuntime().exec(this)
val Process.text
get() = inputStream.bufferedReader().use { it.readLine() }.trim()
fun DokkaTask.externalDocumentationLink(closure: DokkaConfiguration.ExternalDocumentationLink.Builder.() -> Unit) =
externalDocumentationLink(delegateClosureOf(closure))
fun DokkaTask.linkMapping(closure: LinkMapping.() -> Unit) = linkMapping(delegateClosureOf(closure))
fun url(path: String) = uri(path).toURL()
fun dependencyVersion(dependencyName: String, configuration: String = "implementation") =
......
......@@ -7,6 +7,7 @@ import kotlinx.serialization.Required
import kotlinx.serialization.SerialDescriptor
import kotlinx.serialization.Serializable
import kotlinx.serialization.UnionKind
import kotlinx.serialization.builtins.serializer
/**
* Class representing sharable pseuCo.com files.
......@@ -48,18 +49,13 @@ data class PseuCoComFile(val name: String, val content: String, @Required val ty
* @since 2.0.4
*/
companion object : KSerializer<Type> {
override val descriptor = object : SerialDescriptor {
override val name = "PseuCoComFile.Type"
override val kind = UnionKind.ENUM_KIND
override val elementsCount = values().size
override fun getElementDescriptor(index: Int): SerialDescriptor = this
override fun getElementIndex(name: String): Int = valueOf(name.toUpperCase()).ordinal
override fun getElementName(index: Int): String = values()[index].name.toLowerCase()
override val descriptor = SerialDescriptor("PseuCoComFile.Type", UnionKind.ENUM_KIND) {
values().forEach { element(it.name.toLowerCase(), String.serializer().descriptor) }
}
override fun deserialize(decoder: Decoder): Type = values()[descriptor.getElementIndex(decoder.decodeString())]
override fun serialize(encoder: Encoder, obj: Type) = encoder.encodeString(descriptor.getElementName(obj.ordinal))
override fun serialize(encoder: Encoder, value: Type) = encoder.encodeString(descriptor.getElementName(value.ordinal))
}
}
}
......@@ -7,7 +7,7 @@ import kotlinx.serialization.Encoder
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialDescriptor
import kotlinx.serialization.Serializable
import kotlinx.serialization.internal.SerialClassDescImpl
import kotlinx.serialization.builtins.serializer
/**
* Class mimicking the JSON object format used by the [pseuCo.com](https://pseuco.com) sharing API.
......@@ -42,12 +42,10 @@ data class PseuCoComExchange(val file: PseuCoComFile, val temporary: Boolean, va
* @since 2.0.4
*/
companion object : KSerializer<PseuCoComExchange> {
override val descriptor: SerialDescriptor = object : SerialClassDescImpl("PseuCoComExchange") {
init {
addElement("file")
addElement("temporary")
addElement("sharingAgreementVersion")
}
override val descriptor = SerialDescriptor("PseuCoComExchange") {
element("file", PseuCoComFile.serializer().descriptor)
element("temporary", Boolean.serializer().descriptor)
element("sharingAgreementVersion", Int.serializer().descriptor, isOptional = true)
}
override fun deserialize(decoder: Decoder): PseuCoComExchange {
......@@ -73,12 +71,12 @@ data class PseuCoComExchange(val file: PseuCoComFile, val temporary: Boolean, va
return decodeAttributes()
}
override fun serialize(encoder: Encoder, obj: PseuCoComExchange) {
override fun serialize(encoder: Encoder, value: PseuCoComExchange) {
val structure = encoder.beginStructure(descriptor)
structure.encodeSerializableElement(descriptor, 0, PseuCoComFile.serializer(), obj.file)
structure.encodeBooleanElement(descriptor, 1, obj.temporary)
if (!obj.temporary)
structure.encodeIntElement(descriptor, 2, obj.sharingAgreementVersion!!)
structure.encodeSerializableElement(descriptor, 0, PseuCoComFile.serializer(), value.file)
structure.encodeBooleanElement(descriptor, 1, value.temporary)
if (!value.temporary)
structure.encodeIntElement(descriptor, 2, value.sharingAgreementVersion!!)
structure.endStructure(descriptor)
}
}
......
......@@ -7,14 +7,15 @@ import io.ktor.client.engine.apache.Apache
import io.ktor.client.request.accept
import io.ktor.client.request.get
import io.ktor.client.request.post
import io.ktor.client.response.HttpResponse
import io.ktor.client.statement.HttpStatement
import io.ktor.content.TextContent
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.http.URLProtocol
import io.ktor.http.withCharset
import kotlinx.coroutines.io.jvm.javaio.toInputStream
import io.ktor.utils.io.jvm.javaio.toInputStream
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.json.JsonException
import java.awt.Desktop
import java.net.URI
......@@ -26,6 +27,7 @@ import java.net.URISyntaxException
* @author Konstantin Kopper
* @since 2.0.0
*/
@Suppress("EXPERIMENTAL_API_USAGE")
object PseuCoShare : FileSharer {
/**
......@@ -63,7 +65,7 @@ object PseuCoShare : FileSharer {
*/
@Throws(PseuCoShareException::class)
suspend fun shareFile(file: PseuCoComFile, temporary: Boolean = false): URI {
val c = client.post<HttpResponse> {
val c = client.post<HttpStatement> {
url {
protocol = URLProtocol.HTTPS
host = "pseuco.com"
......@@ -74,7 +76,7 @@ object PseuCoShare : FileSharer {
body = TextContent(Json.stringify(PseuCoComExchange.serializer(),
if (temporary) PseuCoComExchange(file) else PseuCoComExchange(file, 1)),
contentType = ContentType.Application.Json)
}
}.execute()
if (c.status != HttpStatusCode.OK)
throw PseuCoShareException("Unexpected status code, expected ${HttpStatusCode.OK.value}, got ${c.status}",
......@@ -82,7 +84,7 @@ object PseuCoShare : FileSharer {
?.let { IllegalStateException("Response body: $it") })
return try {
URI(Json.plain.parseJson(c.content.toInputStream().reader().use { it.readText() }).jsonObject["url"]!!.primitive.content)
URI(Json(JsonConfiguration.Stable).parseJson(c.content.toInputStream().reader().use { it.readText() }).jsonObject["url"]!!.primitive.content)
} catch (e: JsonException) {
throw PseuCoShareException("Parsing the API response failed.", e)
} catch (e: URISyntaxException) {
......@@ -101,7 +103,7 @@ object PseuCoShare : FileSharer {
*/
@Throws(PseuCoShareException::class)
suspend fun downloadFile(id: String): PseuCoComFile {
val c = client.get<HttpResponse> {
val c = client.get<HttpStatement> {
url {
protocol = URLProtocol.HTTPS
host = "pseuco.com"
......@@ -110,7 +112,7 @@ object PseuCoShare : FileSharer {
parameters["id"] = id
}
accept(ContentType.Application.Json.withCharset(Charsets.UTF_8))
}
}.execute()
if (c.status != HttpStatusCode.OK)
throw PseuCoShareException("Unexpected status code, expected ${HttpStatusCode.OK.value}, got ${c.status}.",
......
......@@ -15,7 +15,6 @@ import io.ktor.server.engine.ApplicationEngine
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import java.util.Random
import java.util.concurrent.TimeUnit
/**
* Web server used for communicating with [pseuCo.com](https://pseuco.com).
......@@ -82,7 +81,7 @@ class PseuCoHttpServer(private val port: Int = 28373) : PseuCoServer {
server.start(wait = wait)
}
override fun stop() = this.server.stop(0, 0, TimeUnit.SECONDS)
override fun stop() = this.server.stop(0, 0)
override fun storeFile(file: PseuCoComFile): Int = generateId().also { this.files[it] = file }
......
......@@ -26,11 +26,11 @@ import io.ktor.websocket.WebSockets
import io.ktor.websocket.webSocket
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.json.JsonException
import util.Workspace
import java.io.File
import java.util.Random
import java.util.concurrent.TimeUnit
import kotlin.collections.set
import kotlin.reflect.KProperty
......@@ -78,6 +78,23 @@ object PseuCoWebSocket : PseuCoServer {
*/
private val connections = mutableListOf<WebSocketServerSession>()
/**
* [Json] instance used to parse and serialize [SocketMessage]s.
*
* @author Konstantin Kopper
* @since 2.0.4
*/
private val json = Json(JsonConfiguration.Stable)
/**
* [Json] instance used to parse and serialize [SocketMessage]s.
* Ignores unknown keys during parsing.
*
* @author Konstantin Kopper
* @since 2.0.4
*/
private val jsonNonStrict = Json(JsonConfiguration.Stable.copy(ignoreUnknownKeys = true))
/**
* The actual server.
* Listens on [port] for new WebSocket connections.
......@@ -100,7 +117,7 @@ object PseuCoWebSocket : PseuCoServer {
}
@Suppress("MoveVariableDeclarationIntoWhen")
val request = Json.plain.parseJson(frame.readText()).let {
val request = json.parseJson(frame.readText()).let {
val o = try {
it.jsonObject
} catch (e: JsonException) {
......@@ -114,7 +131,7 @@ object PseuCoWebSocket : PseuCoServer {
}
try {
Json.nonstrict.fromJson(SocketMessage.serializer(), it)
jsonNonStrict.fromJson(SocketMessage.serializer(), it)
} catch (e: JsonException) {
sendError("Parsing the request failed.")
null
......@@ -156,7 +173,7 @@ object PseuCoWebSocket : PseuCoServer {
override fun stop() {
// Close remaining connections and stop server.
connections.forEach { it.launch { it.close(CloseReason(CloseReason.Codes.NORMAL, "Shutting down.")) } }
server.stop(10, 10, TimeUnit.MILLISECONDS)
server.stop(10, 10)
}
override fun storeFile(file: PseuCoComFile): Int = generateID().also { files[it] = file }
......
......@@ -6,11 +6,10 @@ import kotlinx.serialization.Decoder
import kotlinx.serialization.Encoder
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialDescriptor
import kotlinx.serialization.SerialKind
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.UnionKind
import kotlinx.serialization.internal.SerialClassDescImpl
import kotlinx.serialization.builtins.serializer
/**
* All valid messages used in the pseuCo WebSockets file sharing protocol.
......@@ -132,17 +131,13 @@ sealed class SocketMessage(val type: String) {
it.name.toLowerCase().replace(Regex("_(\\w)")) { match -> match.groupValues[1].toUpperCase() }
}
override val descriptor = object : SerialDescriptor {
override val name: String = "SocketMessage.Response.Error.Code"
override val kind: SerialKind = UnionKind.ENUM_KIND
override val elementsCount: Int = values().size
override fun getElementIndex(name: String): Int = valueOf(name).ordinal
override fun getElementName(index: Int): String = values()[index].name
override val descriptor = SerialDescriptor("SocketMessage.Response.Error.Code", UnionKind.ENUM_KIND) {
values().forEach { element(it.name, String.serializer().descriptor) }
}
override fun deserialize(decoder: Decoder): Code = values()[stringValues.indexOf(decoder.decodeString())]
override fun serialize(encoder: Encoder, obj: Code) = encoder.encodeString(stringValues[obj.ordinal])
override fun serialize(encoder: Encoder, value: Code) = encoder.encodeString(stringValues[value.ordinal])
}
}
}
......@@ -155,14 +150,12 @@ sealed class SocketMessage(val type: String) {
* @since 2.0.4
*/
companion object : KSerializer<SocketMessage> {
override val descriptor: SerialDescriptor = object : SerialClassDescImpl("SocketMessage") {
init {
addElement("type")
addElement("id", isOptional = true)
addElement("file", isOptional = true)
addElement("message", isOptional = true)
addElement("code", isOptional = true)
}
override val descriptor = SerialDescriptor("SocketMessage") {
element("type", String.serializer().descriptor)
element("id", Int.serializer().descriptor, isOptional = true)
element("file", PseuCoComFile.serializer().descriptor, isOptional = true)
element("message", String.serializer().descriptor, isOptional = true)
element("code", Response.Error.Code.descriptor, isOptional = true)
}
override fun deserialize(decoder: Decoder): SocketMessage {
......@@ -200,18 +193,18 @@ sealed class SocketMessage(val type: String) {
return decodeAttributes()
}
override fun serialize(encoder: Encoder, obj: SocketMessage) {
override fun serialize(encoder: Encoder, value: SocketMessage) {
val structure = encoder.beginStructure(descriptor)
structure.encodeStringElement(descriptor, 0, obj.type)
when (obj) {
is Request.Get -> structure.encodeIntElement(descriptor, 1, obj.id)
is Request.Open -> structure.encodeSerializableElement(descriptor, 2, PseuCoComFile.serializer(), obj.file)
is Response.File -> structure.encodeSerializableElement(descriptor, 2, PseuCoComFile.serializer(), obj.file)
structure.encodeStringElement(descriptor, 0, value.type)
when (value) {
is Request.Get -> structure.encodeIntElement(descriptor, 1, value.id)
is Request.Open -> structure.encodeSerializableElement(descriptor, 2, PseuCoComFile.serializer(), value.file)
is Response.File -> structure.encodeSerializableElement(descriptor, 2, PseuCoComFile.serializer(), value.file)
is Response.Success -> {
}
is Response.Error -> {
structure.encodeStringElement(descriptor, 3, obj.message)
structure.encodeSerializableElement(descriptor, 4, Response.Error.Code.Companion, obj.code)
structure.encodeStringElement(descriptor, 3, value.message)
structure.encodeSerializableElement(descriptor, 4, Response.Error.Code.Companion, value.code)
}
}
structure.endStructure(descriptor)
......
......@@ -25,7 +25,6 @@ import io.ktor.server.netty.Netty
import kotlinx.coroutines.launch
import java.awt.Desktop
import java.net.URI
import java.util.concurrent.TimeUnit
import kotlin.system.exitProcess
/**
......@@ -158,7 +157,7 @@ object CompanionWebApp {
* @author Konstantin Kopper
* @since 2.0.0
*/
fun stop() = server.stop(0, 0, TimeUnit.SECONDS)
fun stop() = server.stop(0, 0)
/**
* The [URI] this server is reachable at.
......
......@@ -8,11 +8,10 @@ import kotlinx.serialization.SerialDescriptor
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.Serializer
import kotlinx.serialization.UnstableDefault
import kotlinx.serialization.internal.SerialClassDescImpl
import kotlinx.serialization.builtins.list
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.list
import kotlinx.serialization.serializer
import kotlinx.serialization.json.JsonConfiguration
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertIterableEquals
import org.junit.jupiter.api.Assertions.assertTimeoutPreemptively
......@@ -27,14 +26,14 @@ import java.time.Duration
import kotlin.reflect.full.functions
import kotlin.reflect.jvm.isAccessible
@UnstableDefault
@DisabledIfEnvironmentVariable(named = "CI", matches = "true")
class CompilerTests {
@Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
private val tests = File(this::class.java.getResource("/pseuco-tests/tests").toURI())
.listFiles { f -> f.extension == "json" }
.map { f ->
Json.parse(CompilerTestConfig.serializer(), f.readText()).let {
Json(JsonConfiguration.Stable.copy(isLenient = true)).parse(CompilerTestConfig.serializer(), f.readText()).let {
CompilerTest(File(f.absolutePath.replace(Regex("json$"), "pseuco")),
"${it.description} (${f.nameWithoutExtension})", it.correctnessProperties)
}
......@@ -81,12 +80,10 @@ class CompilerTests {
@Serializer(forClass = CorrectnessProperty::class)
companion object : KSerializer<CorrectnessProperty> {
override val descriptor: SerialDescriptor = object : SerialClassDescImpl("CorrectnessProperty") {
init {
addElement("type")
addElement("output", isOptional = true)
addElement("possibilities", isOptional = true)
}
override val descriptor = SerialDescriptor("CorrectnessProperty") {
element("type", String.serializer().descriptor)
element("output", String.serializer().list.descriptor, isOptional = true)
element("possibilities", String.serializer().list.descriptor, isOptional = true)
}
override fun deserialize(decoder: Decoder): CorrectnessProperty {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment