-
Notifications
You must be signed in to change notification settings - Fork 662
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
Improve relocation in gradle plugin #4528
Changes from 2 commits
9137a69
21857e0
9d60402
40b5d08
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -4,7 +4,7 @@ plugins { | |||||
antlr | ||||||
id("org.jetbrains.kotlin.jvm") | ||||||
id("apollo.library") | ||||||
id("com.google.devtools.ksp") | ||||||
kotlin("plugin.serialization") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit. We're using the
Suggested change
|
||||||
} | ||||||
|
||||||
apolloLibrary { | ||||||
|
@@ -17,11 +17,8 @@ dependencies { | |||||
api(okio()) | ||||||
api(project(":libraries:apollo-annotations")) | ||||||
|
||||||
implementation(golatac.lib("moshi")) | ||||||
implementation(golatac.lib("moshix.sealed.runtime")) | ||||||
|
||||||
ksp(golatac.lib("moshix.sealed.codegen")) | ||||||
ksp(golatac.lib("moshix.ksp")) | ||||||
implementation(golatac.lib("kotlinx.serialization.json")) | ||||||
implementation(golatac.lib("kotlinx.serialization.json.okio")) | ||||||
|
||||||
testImplementation(golatac.lib("kotlin.test.junit")) | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,94 @@ | ||
package com.apollographql.apollo3.ast.introspection | ||
|
||
import com.squareup.moshi.JsonClass | ||
import com.squareup.moshi.JsonReader | ||
import com.squareup.moshi.Moshi | ||
import dev.zacsweers.moshix.sealed.annotations.TypeLabel | ||
import kotlinx.serialization.ExperimentalSerializationApi | ||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.encodeToString | ||
import kotlinx.serialization.json.Json | ||
import kotlinx.serialization.json.okio.decodeFromBufferedSource | ||
import kotlinx.serialization.json.okio.encodeToBufferedSink | ||
import okio.Buffer | ||
import okio.BufferedSource | ||
import okio.ByteString.Companion.decodeHex | ||
import okio.buffer | ||
import okio.sink | ||
import okio.source | ||
import java.io.File | ||
|
||
@JsonClass(generateAdapter = true) | ||
@Serializable | ||
private data class IntrospectionSchemaEnvelope( | ||
val data: IntrospectionSchema?, | ||
val __schema: IntrospectionSchema.Schema?, | ||
) | ||
|
||
@Serializable | ||
data class IntrospectionSchema( | ||
val __schema: Schema, | ||
) { | ||
@JsonClass(generateAdapter = true) | ||
@Serializable | ||
data class Schema( | ||
val queryType: QueryType, | ||
val mutationType: MutationType?, | ||
val subscriptionType: SubscriptionType?, | ||
val types: List<Type>, | ||
) { | ||
@JsonClass(generateAdapter = true) | ||
@Serializable | ||
data class QueryType(val name: String) | ||
|
||
@JsonClass(generateAdapter = true) | ||
@Serializable | ||
data class MutationType(val name: String) | ||
|
||
@JsonClass(generateAdapter = true) | ||
@Serializable | ||
data class SubscriptionType(val name: String) | ||
|
||
@JsonClass(generateAdapter = true, generator = "sealed:kind") | ||
@Serializable | ||
sealed class Type { | ||
abstract val name: String | ||
abstract val description: String? | ||
|
||
@TypeLabel("SCALAR") | ||
@JsonClass(generateAdapter = true) | ||
@SerialName("SCALAR") | ||
@Serializable | ||
data class Scalar( | ||
override val name: String, | ||
override val description: String?, | ||
) : Type() | ||
|
||
@TypeLabel("OBJECT") | ||
@JsonClass(generateAdapter = true) | ||
@SerialName("OBJECT") | ||
@Serializable | ||
data class Object( | ||
override val name: String, | ||
override val description: String?, | ||
val fields: List<Field>?, | ||
val interfaces: List<Interface>?, | ||
) : Type() | ||
|
||
@TypeLabel("INTERFACE") | ||
@JsonClass(generateAdapter = true) | ||
@SerialName("INTERFACE") | ||
@Serializable | ||
data class Interface( | ||
override val name: String, | ||
override val description: String?, | ||
val kind: String, | ||
martinbonnin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
val fields: List<Field>?, | ||
val interfaces: List<TypeRef>?, | ||
val possibleTypes: List<TypeRef>?, | ||
) : Type() | ||
|
||
@TypeLabel("UNION") | ||
@JsonClass(generateAdapter = true) | ||
@SerialName("UNION") | ||
@Serializable | ||
data class Union( | ||
override val name: String, | ||
override val description: String?, | ||
val fields: List<Field>?, | ||
val possibleTypes: List<TypeRef>?, | ||
) : Type() | ||
|
||
@TypeLabel("ENUM") | ||
@JsonClass(generateAdapter = true) | ||
@SerialName("ENUM") | ||
@Serializable | ||
data class Enum( | ||
override val name: String, | ||
override val description: String?, | ||
val enumValues: List<Value>, | ||
) : Type() { | ||
|
||
|
||
@JsonClass(generateAdapter = true) | ||
@Serializable | ||
data class Value( | ||
val name: String, | ||
val description: String?, | ||
|
@@ -90,17 +97,16 @@ data class IntrospectionSchema( | |
) | ||
} | ||
|
||
@TypeLabel("INPUT_OBJECT") | ||
@JsonClass(generateAdapter = true) | ||
@SerialName("INPUT_OBJECT") | ||
@Serializable | ||
data class InputObject( | ||
override val name: String, | ||
override val description: String?, | ||
val inputFields: List<InputField>, | ||
) : Type() | ||
} | ||
|
||
|
||
@JsonClass(generateAdapter = true) | ||
@Serializable | ||
data class InputField( | ||
val name: String, | ||
val description: String?, | ||
|
@@ -110,7 +116,7 @@ data class IntrospectionSchema( | |
val defaultValue: String?, | ||
) | ||
|
||
@JsonClass(generateAdapter = true) | ||
@Serializable | ||
data class Field( | ||
val name: String, | ||
val description: String?, | ||
|
@@ -120,7 +126,7 @@ data class IntrospectionSchema( | |
val args: List<Argument> = emptyList(), | ||
) { | ||
|
||
@JsonClass(generateAdapter = true) | ||
@Serializable | ||
data class Argument( | ||
val name: String, | ||
val description: String?, | ||
|
@@ -134,7 +140,7 @@ data class IntrospectionSchema( | |
/** | ||
* An introspection TypeRef | ||
*/ | ||
@JsonClass(generateAdapter = true) | ||
@Serializable | ||
data class TypeRef( | ||
val kind: Kind, | ||
val name: String? = "", | ||
|
@@ -147,51 +153,36 @@ data class IntrospectionSchema( | |
} | ||
} | ||
|
||
/** | ||
* | ||
*/ | ||
@OptIn(ExperimentalSerializationApi::class) | ||
private val json: Json by lazy { | ||
Json { | ||
ignoreUnknownKeys = true | ||
martinbonnin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
classDiscriminator = "kind" | ||
explicitNulls = false | ||
} | ||
} | ||
|
||
@OptIn(ExperimentalSerializationApi::class) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it's ok to use this. If a future version changes the signatures, they will break at runtime. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But we bundle and relocate the code, so we should be immune to changes? (OTOH I'm ok with avoiding using this) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We relocate in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That makes sense 👍 |
||
fun BufferedSource.toIntrospectionSchema(origin: String = ""): IntrospectionSchema { | ||
val bom = "EFBBBF".decodeHex() | ||
|
||
if (rangeEquals(0, bom)) { | ||
skip(bom.size.toLong()) | ||
} | ||
|
||
return JsonReader.of(this).use { | ||
try { | ||
val schema = Moshi.Builder().build() | ||
.adapter(IntrospectionSchema.Schema::class.java) | ||
.fromJson(it.locateSchemaRootNode())!! | ||
IntrospectionSchema(__schema = schema) | ||
} catch (e: Exception) { | ||
throw RuntimeException("Cannot decode introspection $origin", e) | ||
} | ||
return try { | ||
val introspectionSchemaEnvelope = json.decodeFromBufferedSource<IntrospectionSchemaEnvelope>(this) | ||
introspectionSchemaEnvelope.data ?: introspectionSchemaEnvelope.__schema?.let { IntrospectionSchema(it) } | ||
?: throw IllegalArgumentException("Invalid introspection schema: $origin") | ||
} catch (e: Exception) { | ||
throw RuntimeException("Cannot decode introspection $origin", e) | ||
} | ||
} | ||
|
||
fun File.toIntrospectionSchema() = inputStream().source().buffer().toIntrospectionSchema("from `$this`") | ||
|
||
fun String.toIntrospectionSchema() = Buffer().writeUtf8(this).toIntrospectionSchema() | ||
|
||
private fun JsonReader.locateSchemaRootNode(): JsonReader { | ||
beginObject() | ||
|
||
var schemaJsonReader: JsonReader? = null | ||
try { | ||
while (schemaJsonReader == null && hasNext()) { | ||
when (nextName()) { | ||
"data" -> beginObject() | ||
"__schema" -> schemaJsonReader = peekJson() | ||
else -> skipValue() | ||
} | ||
} | ||
} catch (e: Exception) { | ||
throw IllegalArgumentException("Failed to locate schema root node `__schema`", e) | ||
} | ||
|
||
return schemaJsonReader ?: throw IllegalArgumentException("Failed to locate schema root node `__schema`") | ||
} | ||
|
||
fun IntrospectionSchema.normalize(): IntrospectionSchema { | ||
return copy( | ||
__schema = __schema.normalize() | ||
|
@@ -204,3 +195,13 @@ fun IntrospectionSchema.Schema.normalize(): IntrospectionSchema.Schema { | |
) | ||
} | ||
|
||
fun IntrospectionSchema.toJson(): String { | ||
return json.encodeToString(this) | ||
} | ||
|
||
@OptIn(ExperimentalSerializationApi::class) | ||
fun IntrospectionSchema.toJson(file: File) { | ||
file.outputStream().sink().buffer().use { | ||
return json.encodeToBufferedSink(this, it) | ||
} | ||
} |
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.
Sorry I missed that one. Do we need this? The serialization plugin should be on maven central these days: https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/plugin/serialization/org.jetbrains.kotlin.plugin.serialization.gradle.plugin/
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.
I removed it again in https://github.com/apollographql/apollo-kotlin/pull/4531/files, see what breaks 👀
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.
Version 1.6.10 (which we use during idea sync) is not on Maven central, but now I'm no longer sure this is needed because I removed it on my machine and it still works 😅
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.
Maybe you have configuration cache enabled 😅 . Ok I'll add it again in #4531 with a comment to remove it at some point