From c7f608d56b7583e6e33431cd91fd3f5d11c18eaa Mon Sep 17 00:00:00 2001 From: Benoit 'BoD' Lubek Date: Tue, 24 Sep 2024 18:29:01 +0200 Subject: [PATCH] Allow mapping scalars to simple generic types (#6158) * Allow mapping scalars to simple generic types * Automatically prefix a few common Kotlin and Java types with their package names --- .../compiler/codegen/java/JavaResolver.kt | 10 +- .../codegen/java/helpers/bestGuess.kt | 51 ++++++ .../compiler/codegen/kotlin/KotlinResolver.kt | 16 +- .../codegen/kotlin/helpers/bestGuess.kt | 63 +++++++ .../custom_scalar_type/TestOperation.graphql | 4 + .../ScalarWithGenericType.java.expected | 173 ++++++++++++++++++ ...hGenericType_ResponseAdapter.java.expected | 52 ++++++ ...larWithGenericTypeSelections.java.expected | 18 ++ .../type/ListOfString.java.expected | 12 ++ .../used-coordinates.json.expected | 2 + .../ScalarWithGenericType.kt.expected | 78 ++++++++ ...ithGenericType_ResponseAdapter.kt.expected | 48 +++++ ...calarWithGenericTypeSelections.kt.expected | 20 ++ .../type/ListOfString.kt.expected | 14 ++ .../used-coordinates.json.expected | 2 + .../type/ListOfString.java.expected | 12 ++ .../type/ListOfString.kt.expected | 14 ++ .../type/ListOfString.java.expected | 12 ++ .../type/ListOfString.kt.expected | 14 ++ .../src/test/graphql/schema.sdl | 3 + .../apollo/compiler/CodegenTest.kt | 7 +- 21 files changed, 615 insertions(+), 10 deletions(-) create mode 100644 libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/java/helpers/bestGuess.kt create mode 100644 libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/helpers/bestGuess.kt create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/ScalarWithGenericType.java.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/adapter/ScalarWithGenericType_ResponseAdapter.java.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/selections/ScalarWithGenericTypeSelections.java.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/type/ListOfString.java.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/ScalarWithGenericType.kt.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/adapter/ScalarWithGenericType_ResponseAdapter.kt.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/selections/ScalarWithGenericTypeSelections.kt.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/type/ListOfString.kt.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/input_object_type/java/operationBased/input_object_type/type/ListOfString.java.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/input_object_type/kotlin/responseBased/input_object_type/type/ListOfString.kt.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/mutation_create_review/java/operationBased/mutation_create_review/type/ListOfString.java.expected create mode 100644 libraries/apollo-compiler/src/test/graphql/com/example/mutation_create_review/kotlin/responseBased/mutation_create_review/type/ListOfString.kt.expected diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/java/JavaResolver.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/java/JavaResolver.kt index 4a1982ee213..f1ca74aa9ef 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/java/JavaResolver.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/java/JavaResolver.kt @@ -10,6 +10,7 @@ import com.apollographql.apollo.compiler.codegen.ResolverClassName import com.apollographql.apollo.compiler.codegen.ResolverEntry import com.apollographql.apollo.compiler.codegen.ResolverKey import com.apollographql.apollo.compiler.codegen.ResolverKeyKind +import com.apollographql.apollo.compiler.codegen.java.helpers.bestGuess import com.apollographql.apollo.compiler.codegen.java.helpers.singletonAdapterInitializer import com.apollographql.apollo.compiler.ir.IrCatchTo import com.apollographql.apollo.compiler.ir.IrCompositeType2 @@ -96,7 +97,7 @@ internal class JavaResolver( val result = resolve(ResolverKey(kind, id)) check(result != null) { - "Cannot resolve $kind($id). " + + "Cannot resolve $kind($id). " + "Have you set up an 'opposite link' on the downstream project to the schema module as a isADependencyOf(..)?" } return result @@ -239,9 +240,9 @@ internal class JavaResolver( } } - private fun resolveScalarTarget(name: String): ClassName? { + private fun resolveScalarTarget(name: String): TypeName? { return scalarMapping[name]?.targetName?.let { - ClassName.bestGuess(it) + bestGuess(it) } } @@ -427,7 +428,8 @@ internal class JavaResolver( } -internal fun ResolverClassName.toJavaPoetClassName(): ClassName = ClassName.get(packageName, simpleNames[0], *simpleNames.drop(1).toTypedArray()) +internal fun ResolverClassName.toJavaPoetClassName(): ClassName = + ClassName.get(packageName, simpleNames[0], *simpleNames.drop(1).toTypedArray()) private val primitiveTypeNames = setOf(TypeName.DOUBLE, TypeName.INT, TypeName.BOOLEAN) diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/java/helpers/bestGuess.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/java/helpers/bestGuess.kt new file mode 100644 index 00000000000..ae40c02cea7 --- /dev/null +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/java/helpers/bestGuess.kt @@ -0,0 +1,51 @@ +package com.apollographql.apollo.compiler.codegen.java.helpers + +import com.squareup.javapoet.ClassName +import com.squareup.javapoet.ParameterizedTypeName +import com.squareup.javapoet.TypeName + +/** + * Best guess a type name. Handles simple generics like `Map`, but no variance or wildcards. + */ +internal fun bestGuess(name: String): TypeName? { + val className = ClassName.bestGuess(name.substringBefore('<').withPackage()) + val typeArgs = name.substringAfter('<', "").substringBefore('>', "") + .split(',') + .filterNot { it.isEmpty() } + .map { it.trim() } + return if (typeArgs.isEmpty()) { + className + } else { + ParameterizedTypeName.get(className, *typeArgs.map { bestGuess(it) }.toTypedArray()) + } +} + +private fun String.withPackage(): String { + return if (this in commonJavaTypes) { + "java.lang.${this}" + } else if (this in commonJavaCollectionsTypes) { + "java.util.${this}" + } else { + this + } +} + +private val commonJavaTypes = setOf( + "Boolean", + "Byte", + "Character", + "Double", + "Float", + "Integer", + "Iterable", + "Long", + "Short", + "String", +) + +private val commonJavaCollectionsTypes = setOf( + "Collection", + "List", + "Map", + "Set", +) diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/KotlinResolver.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/KotlinResolver.kt index 7b7c7de869c..4c96886624f 100644 --- a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/KotlinResolver.kt +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/KotlinResolver.kt @@ -9,6 +9,7 @@ import com.apollographql.apollo.compiler.codegen.ResolverClassName import com.apollographql.apollo.compiler.codegen.ResolverEntry import com.apollographql.apollo.compiler.codegen.ResolverKey import com.apollographql.apollo.compiler.codegen.ResolverKeyKind +import com.apollographql.apollo.compiler.codegen.kotlin.helpers.bestGuess import com.apollographql.apollo.compiler.codegen.kotlin.helpers.obj import com.apollographql.apollo.compiler.ir.IrCatchTo import com.apollographql.apollo.compiler.ir.IrCompositeType2 @@ -43,7 +44,7 @@ internal class KotlinResolver( private val scalarMapping: Map, private val requiresOptInAnnotation: String?, ) { - fun resolve(key: ResolverKey): ClassName? { + fun resolve(key: ResolverKey): ClassName? { return classNames[key] ?: next?.resolve(key) } @@ -60,7 +61,7 @@ internal class KotlinResolver( check(result != null) { "Cannot resolve $kind($id). " + - "Have you set up an 'opposite link' on the downstream project to the schema module as a isADependencyOf(..)?" + "Have you set up an 'opposite link' on the downstream project to the schema module as a isADependencyOf(..)?" } return result } @@ -85,6 +86,7 @@ internal class KotlinResolver( type.optional -> { KotlinSymbols.Optional.parameterizedBy(resolveIrType(type.optional(false), jsExport, isInterface)) } + type.catchTo != IrCatchTo.NoCatch -> { resolveIrType(type.catchTo(IrCatchTo.NoCatch), jsExport, isInterface).let { when (type.catchTo) { @@ -94,9 +96,11 @@ internal class KotlinResolver( } } } + type.nullable -> { resolveIrType(type.nullable(false), jsExport, isInterface).copy(nullable = true) } + else -> { when (type) { is IrListType -> resolveIrType(type.ofType, jsExport, isInterface).wrapInList(jsExport, isInterface) @@ -139,9 +143,9 @@ internal class KotlinResolver( return listType.parameterizedBy(param) } - private fun resolveScalarTarget(name: String): ClassName? { + private fun resolveScalarTarget(name: String): TypeName? { return scalarMapping[name]?.targetName?.let { - ClassName.bestGuess(it) + bestGuess(it) } } @@ -203,6 +207,7 @@ internal class KotlinResolver( val presentFun = MemberName("com.apollographql.apollo.api", "present") CodeBlock.of("%L.%M()", adapterInitializer(type.optional(false), requiresBuffering, jsExport), presentFun) } + type.catchTo != IrCatchTo.NoCatch -> { adapterInitializer(type.catchTo(IrCatchTo.NoCatch), requiresBuffering, jsExport).let { val member = when (type.catchTo) { @@ -213,11 +218,13 @@ internal class KotlinResolver( CodeBlock.of("%L.%M()", it, member) } } + type.maybeError -> { adapterInitializer(type.maybeError(false), requiresBuffering, jsExport).let { CodeBlock.of("%L.%M()", it, KotlinSymbols.errorAware) } } + type.nullable -> { // Don't hardcode the adapter when the scalar is mapped to a user-defined type val scalarWithoutCustomMapping = type is IrScalarType && !scalarMapping.containsKey(type.name) @@ -237,6 +244,7 @@ internal class KotlinResolver( } } } + else -> { when (type) { is IrListType -> { diff --git a/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/helpers/bestGuess.kt b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/helpers/bestGuess.kt new file mode 100644 index 00000000000..34076219fe9 --- /dev/null +++ b/libraries/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/helpers/bestGuess.kt @@ -0,0 +1,63 @@ +package com.apollographql.apollo.compiler.codegen.kotlin.helpers + +import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import com.squareup.kotlinpoet.TypeName + +/** + * Best guess a type name. Handles simple generics like `Map`, but no variance or wildcards. + * Common types such as `String`, `List`, `Map` are automatically prefixed with `kotlin.` or `kotlin.collections.`. + */ +internal fun bestGuess(name: String): TypeName { + val isNullable = name.endsWith('?') + val className = ClassName.bestGuess(name.substringBeforeLast('?').substringBefore('<').withPackage()) + val typeArgs = name.substringAfter('<', "").substringBefore('>', "") + .split(',') + .filterNot { it.isEmpty() } + .map { it.trim() } + return if (typeArgs.isEmpty()) { + className + } else { + className.parameterizedBy(typeArgs.map { bestGuess(it) }) + } + .copy(nullable = isNullable) +} + +private fun String.withPackage(): String { + return if (this in commonKotlinTypes) { + "kotlin.${this}" + } else if (this in commonKotlinCollectionsTypes) { + "kotlin.collections.${this}" + } else { + this + } +} + +private val commonKotlinTypes = setOf( + "Any", + "Boolean", + "Byte", + "Char", + "CharSequence", + "Double", + "Float", + "Int", + "Long", + "Number", + "Short", + "String", + "UByte", + "UInt", + "ULong", + "Unit", + "UShort", +) + +private val commonKotlinCollectionsTypes = setOf( + "Array", + "Collection", + "Iterable", + "List", + "Map", + "Set", +) diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/TestOperation.graphql b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/TestOperation.graphql index 8d1cdb11ce9..2064602818a 100644 --- a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/TestOperation.graphql +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/TestOperation.graphql @@ -10,3 +10,7 @@ query TestQuery { links } } + +query ScalarWithGenericType { + listOfString +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/ScalarWithGenericType.java.expected b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/ScalarWithGenericType.java.expected new file mode 100644 index 00000000000..80c0d1f34af --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/ScalarWithGenericType.java.expected @@ -0,0 +1,173 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.custom_scalar_type; + +import com.apollographql.apollo.api.Adapter; +import com.apollographql.apollo.api.CompiledField; +import com.apollographql.apollo.api.CustomScalarAdapters; +import com.apollographql.apollo.api.ObjectAdapter; +import com.apollographql.apollo.api.Query; +import com.apollographql.apollo.api.json.JsonWriter; +import com.example.custom_scalar_type.adapter.ScalarWithGenericType_ResponseAdapter; +import com.example.custom_scalar_type.selections.ScalarWithGenericTypeSelections; +import java.io.IOException; +import java.lang.Object; +import java.lang.Override; +import java.lang.String; +import java.util.List; + +public class ScalarWithGenericType implements Query { + public static final String OPERATION_ID = "a4310c5c764fd8691ab97d3c217eae966f34ceaf5184630463fcfe5756fc9c6c"; + + /** + * The minimized GraphQL document being sent to the server to save a few bytes. + * The un-minimized version is: + * + * query ScalarWithGenericType { + * listOfString + * } + */ + public static final String OPERATION_DOCUMENT = "query ScalarWithGenericType { listOfString }"; + + public static final String OPERATION_NAME = "ScalarWithGenericType"; + + private transient volatile int $hashCode; + + private transient volatile boolean $hashCodeMemoized; + + private transient volatile String $toString; + + public ScalarWithGenericType() { + + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof ScalarWithGenericType) { + return true; + } + return false; + } + + @Override + public int hashCode() { + if (!$hashCodeMemoized) { + int __h = 1; + $hashCode = __h; + $hashCodeMemoized = true; + } + return $hashCode; + } + + @Override + public String toString() { + if ($toString == null) { + $toString = "ScalarWithGenericType{" + + "}"; + } + return $toString; + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public String id() { + return OPERATION_ID; + } + + @Override + public String document() { + return OPERATION_DOCUMENT; + } + + @Override + public String name() { + return OPERATION_NAME; + } + + @Override + public void serializeVariables(JsonWriter writer, CustomScalarAdapters customScalarAdapters, + boolean withDefaultValues) throws IOException { + // This operation doesn't have any variable + } + + @Override + public Adapter adapter() { + return new ObjectAdapter(ScalarWithGenericType_ResponseAdapter.Data.INSTANCE, false); + } + + @Override + public CompiledField rootField() { + return new CompiledField.Builder( + "data", + com.example.custom_scalar_type.type.Query.type + ) + .selections(ScalarWithGenericTypeSelections.__root) + .build(); + } + + public static final class Builder { + Builder() { + } + + public ScalarWithGenericType build() { + return new ScalarWithGenericType(); + } + } + + public static class Data implements Query.Data { + public List listOfString; + + private transient volatile int $hashCode; + + private transient volatile boolean $hashCodeMemoized; + + private transient volatile String $toString; + + public Data(List listOfString) { + this.listOfString = listOfString; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Data) { + Data that = (Data) o; + return ((this.listOfString == null) ? (that.listOfString == null) : this.listOfString.equals(that.listOfString)); + } + return false; + } + + @Override + public int hashCode() { + if (!$hashCodeMemoized) { + int __h = 1; + __h *= 1000003; + __h ^= (listOfString == null) ? 0 : listOfString.hashCode(); + $hashCode = __h; + $hashCodeMemoized = true; + } + return $hashCode; + } + + @Override + public String toString() { + if ($toString == null) { + $toString = "Data{" + + "listOfString=" + listOfString + + "}"; + } + return $toString; + } + } +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/adapter/ScalarWithGenericType_ResponseAdapter.java.expected b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/adapter/ScalarWithGenericType_ResponseAdapter.java.expected new file mode 100644 index 00000000000..a2dbb5f57ae --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/adapter/ScalarWithGenericType_ResponseAdapter.java.expected @@ -0,0 +1,52 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.custom_scalar_type.adapter; + +import com.apollographql.apollo.api.Adapter; +import com.apollographql.apollo.api.CustomScalarAdapters; +import com.apollographql.apollo.api.NullableAdapter; +import com.apollographql.apollo.api.json.JsonReader; +import com.apollographql.apollo.api.json.JsonWriter; +import com.example.custom_scalar_type.ScalarWithGenericType; +import com.example.custom_scalar_type.type.ListOfString; +import java.io.IOException; +import java.lang.Override; +import java.lang.String; +import java.util.Arrays; +import java.util.List; + +public class ScalarWithGenericType_ResponseAdapter { + public enum Data implements Adapter { + INSTANCE; + + private static final List RESPONSE_NAMES = Arrays.asList("listOfString"); + + @Override + public ScalarWithGenericType.Data fromJson(JsonReader reader, + CustomScalarAdapters customScalarAdapters) throws IOException { + List _listOfString = null; + + loop: + while(true) { + switch (reader.selectName(RESPONSE_NAMES)) { + case 0: _listOfString = new NullableAdapter<>((customScalarAdapters.>responseAdapterFor(ListOfString.type))).fromJson(reader, customScalarAdapters); break; + default: break loop; + } + } + + return new ScalarWithGenericType.Data( + _listOfString + ); + } + + @Override + public void toJson(JsonWriter writer, CustomScalarAdapters customScalarAdapters, + ScalarWithGenericType.Data value) throws IOException { + writer.name("listOfString"); + new NullableAdapter<>((customScalarAdapters.>responseAdapterFor(ListOfString.type))).toJson(writer, customScalarAdapters, value.listOfString); + } + } +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/selections/ScalarWithGenericTypeSelections.java.expected b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/selections/ScalarWithGenericTypeSelections.java.expected new file mode 100644 index 00000000000..be2ec87702e --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/selections/ScalarWithGenericTypeSelections.java.expected @@ -0,0 +1,18 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.custom_scalar_type.selections; + +import com.apollographql.apollo.api.CompiledField; +import com.apollographql.apollo.api.CompiledSelection; +import com.example.custom_scalar_type.type.ListOfString; +import java.util.Arrays; +import java.util.List; + +public class ScalarWithGenericTypeSelections { + public static List __root = Arrays.asList( + new CompiledField.Builder("listOfString", ListOfString.type).build() + ); +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/type/ListOfString.java.expected b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/type/ListOfString.java.expected new file mode 100644 index 00000000000..104af8673eb --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/custom_scalar_type/type/ListOfString.java.expected @@ -0,0 +1,12 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.custom_scalar_type.type; + +import com.apollographql.apollo.api.CustomScalarType; + +public class ListOfString { + public static CustomScalarType type = new CustomScalarType("ListOfString", "List"); +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/used-coordinates.json.expected b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/used-coordinates.json.expected index d74db316ab6..9c1e2cf475c 100644 --- a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/used-coordinates.json.expected +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/java/operationBased/used-coordinates.json.expected @@ -13,6 +13,8 @@ "URL": { }, "Query": { + }, + "ListOfString": { } } } \ No newline at end of file diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/ScalarWithGenericType.kt.expected b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/ScalarWithGenericType.kt.expected new file mode 100644 index 00000000000..e0336060813 --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/ScalarWithGenericType.kt.expected @@ -0,0 +1,78 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.custom_scalar_type + +import com.apollographql.apollo.annotations.ApolloAdaptableWith +import com.apollographql.apollo.api.Adapter +import com.apollographql.apollo.api.CompiledField +import com.apollographql.apollo.api.CustomScalarAdapters +import com.apollographql.apollo.api.Query +import com.apollographql.apollo.api.json.JsonWriter +import com.apollographql.apollo.api.obj +import com.example.custom_scalar_type.adapter.ScalarWithGenericType_ResponseAdapter +import com.example.custom_scalar_type.selections.ScalarWithGenericTypeSelections +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.collections.List +import com.example.custom_scalar_type.type.Query as CompiledQuery + +public class ScalarWithGenericType() : Query { + override fun equals(other: Any?): Boolean = other != null && other::class == this::class + + override fun hashCode(): Int = this::class.hashCode() + + override fun id(): String = OPERATION_ID + + override fun document(): String = OPERATION_DOCUMENT + + override fun name(): String = OPERATION_NAME + + override fun serializeVariables( + writer: JsonWriter, + customScalarAdapters: CustomScalarAdapters, + withDefaultValues: Boolean, + ) { + // This operation doesn't have any variable + } + + override fun adapter(): Adapter = ScalarWithGenericType_ResponseAdapter.Data.obj() + + override fun rootField(): CompiledField = CompiledField.Builder( + name = "data", + type = CompiledQuery.type + ) + .selections(selections = ScalarWithGenericTypeSelections.__root) + .build() + + @ApolloAdaptableWith(ScalarWithGenericType_ResponseAdapter.Data::class) + public data class Data( + public val listOfString: List?, + ) : Query.Data { + public fun listOfStringFilterNotNull(): List? = listOfString?.filterNotNull() + } + + public companion object { + public const val OPERATION_ID: String = + "a4310c5c764fd8691ab97d3c217eae966f34ceaf5184630463fcfe5756fc9c6c" + + /** + * The minimized GraphQL document being sent to the server to save a few bytes. + * The un-minimized version is: + * + * ``` + * query ScalarWithGenericType { + * listOfString + * } + * ``` + */ + public val OPERATION_DOCUMENT: String + get() = "query ScalarWithGenericType { listOfString }" + + public const val OPERATION_NAME: String = "ScalarWithGenericType" + } +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/adapter/ScalarWithGenericType_ResponseAdapter.kt.expected b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/adapter/ScalarWithGenericType_ResponseAdapter.kt.expected new file mode 100644 index 00000000000..60836288371 --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/adapter/ScalarWithGenericType_ResponseAdapter.kt.expected @@ -0,0 +1,48 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.custom_scalar_type.adapter + +import com.apollographql.apollo.api.Adapter +import com.apollographql.apollo.api.CustomScalarAdapters +import com.apollographql.apollo.api.json.JsonReader +import com.apollographql.apollo.api.json.JsonWriter +import com.apollographql.apollo.api.nullable +import com.example.custom_scalar_type.ScalarWithGenericType +import com.example.custom_scalar_type.type.ListOfString +import kotlin.String +import kotlin.collections.List + +public object ScalarWithGenericType_ResponseAdapter { + public object Data : Adapter { + public val RESPONSE_NAMES: List = listOf("listOfString") + + override fun fromJson(reader: JsonReader, customScalarAdapters: CustomScalarAdapters): + ScalarWithGenericType.Data { + var _listOfString: List? = null + + while (true) { + when (reader.selectName(RESPONSE_NAMES)) { + 0 -> _listOfString = customScalarAdapters.responseAdapterFor>(ListOfString.type).nullable().fromJson(reader, customScalarAdapters) + else -> break + } + } + + return ScalarWithGenericType.Data( + listOfString = _listOfString + ) + } + + override fun toJson( + writer: JsonWriter, + customScalarAdapters: CustomScalarAdapters, + `value`: ScalarWithGenericType.Data, + ) { + writer.name("listOfString") + customScalarAdapters.responseAdapterFor>(ListOfString.type).nullable().toJson(writer, + customScalarAdapters, value.listOfString) + } + } +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/selections/ScalarWithGenericTypeSelections.kt.expected b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/selections/ScalarWithGenericTypeSelections.kt.expected new file mode 100644 index 00000000000..10a294f1e48 --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/selections/ScalarWithGenericTypeSelections.kt.expected @@ -0,0 +1,20 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.custom_scalar_type.selections + +import com.apollographql.apollo.api.CompiledField +import com.apollographql.apollo.api.CompiledSelection +import com.example.custom_scalar_type.type.ListOfString +import kotlin.collections.List + +public object ScalarWithGenericTypeSelections { + public val __root: List = listOf( + CompiledField.Builder( + name = "listOfString", + type = ListOfString.type + ).build() + ) +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/type/ListOfString.kt.expected b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/type/ListOfString.kt.expected new file mode 100644 index 00000000000..af7b51be562 --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/custom_scalar_type/type/ListOfString.kt.expected @@ -0,0 +1,14 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.custom_scalar_type.type + +import com.apollographql.apollo.api.CustomScalarType + +public class ListOfString { + public companion object { + public val type: CustomScalarType = CustomScalarType("ListOfString", "List") + } +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/used-coordinates.json.expected b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/used-coordinates.json.expected index d74db316ab6..9c1e2cf475c 100644 --- a/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/used-coordinates.json.expected +++ b/libraries/apollo-compiler/src/test/graphql/com/example/custom_scalar_type/kotlin/responseBased/used-coordinates.json.expected @@ -13,6 +13,8 @@ "URL": { }, "Query": { + }, + "ListOfString": { } } } \ No newline at end of file diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/input_object_type/java/operationBased/input_object_type/type/ListOfString.java.expected b/libraries/apollo-compiler/src/test/graphql/com/example/input_object_type/java/operationBased/input_object_type/type/ListOfString.java.expected new file mode 100644 index 00000000000..9825c8e223c --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/input_object_type/java/operationBased/input_object_type/type/ListOfString.java.expected @@ -0,0 +1,12 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.input_object_type.type; + +import com.apollographql.apollo.api.CustomScalarType; + +public class ListOfString { + public static CustomScalarType type = new CustomScalarType("ListOfString", "List"); +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/input_object_type/kotlin/responseBased/input_object_type/type/ListOfString.kt.expected b/libraries/apollo-compiler/src/test/graphql/com/example/input_object_type/kotlin/responseBased/input_object_type/type/ListOfString.kt.expected new file mode 100644 index 00000000000..a9c251e5a54 --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/input_object_type/kotlin/responseBased/input_object_type/type/ListOfString.kt.expected @@ -0,0 +1,14 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.input_object_type.type + +import com.apollographql.apollo.api.CustomScalarType + +public class ListOfString { + public companion object { + public val type: CustomScalarType = CustomScalarType("ListOfString", "List") + } +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/mutation_create_review/java/operationBased/mutation_create_review/type/ListOfString.java.expected b/libraries/apollo-compiler/src/test/graphql/com/example/mutation_create_review/java/operationBased/mutation_create_review/type/ListOfString.java.expected new file mode 100644 index 00000000000..ee6aa487696 --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/mutation_create_review/java/operationBased/mutation_create_review/type/ListOfString.java.expected @@ -0,0 +1,12 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.mutation_create_review.type; + +import com.apollographql.apollo.api.CustomScalarType; + +public class ListOfString { + public static CustomScalarType type = new CustomScalarType("ListOfString", "List"); +} diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/mutation_create_review/kotlin/responseBased/mutation_create_review/type/ListOfString.kt.expected b/libraries/apollo-compiler/src/test/graphql/com/example/mutation_create_review/kotlin/responseBased/mutation_create_review/type/ListOfString.kt.expected new file mode 100644 index 00000000000..92cd3b55c77 --- /dev/null +++ b/libraries/apollo-compiler/src/test/graphql/com/example/mutation_create_review/kotlin/responseBased/mutation_create_review/type/ListOfString.kt.expected @@ -0,0 +1,14 @@ +// +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL version '$VERSION'. +// +package com.example.mutation_create_review.type + +import com.apollographql.apollo.api.CustomScalarType + +internal class ListOfString { + public companion object { + public val type: CustomScalarType = CustomScalarType("ListOfString", "List") + } +} diff --git a/libraries/apollo-compiler/src/test/graphql/schema.sdl b/libraries/apollo-compiler/src/test/graphql/schema.sdl index 4b6e09d6637..f651fb23589 100644 --- a/libraries/apollo-compiler/src/test/graphql/schema.sdl +++ b/libraries/apollo-compiler/src/test/graphql/schema.sdl @@ -314,6 +314,7 @@ type Query { tree: Tree typeWithGraphQLKeywords: TypeWithGraphQLKeywords getBoolean(booleanArg: Boolean): Boolean + listOfString: ListOfString } """Represents a review for a movie""" @@ -446,3 +447,5 @@ type TypeWithGraphQLKeywords { on: String null(fragment: String): String } + +scalar ListOfString diff --git a/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/CodegenTest.kt b/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/CodegenTest.kt index 6dda2d8e671..242b089d788 100644 --- a/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/CodegenTest.kt +++ b/libraries/apollo-compiler/src/test/kotlin/com/apollographql/apollo/compiler/CodegenTest.kt @@ -278,6 +278,7 @@ class CodegenTest { ?: File("src/test/graphql/schema.sdl") val graphqlFiles = setOf(File(folder, "TestOperation.graphql")) + @Suppress("DEPRECATION") val operationOutputGenerator = OperationOutputGenerator.Default(operationIdGenerator) @@ -304,6 +305,7 @@ class CodegenTest { "URL" to ScalarInfo("java.lang.String", ExpressionAdapterInitializer("com.example.UrlAdapter.INSTANCE")), "ID" to ScalarInfo("java.lang.Long"), "String" to ScalarInfo("java.lang.String", ExpressionAdapterInitializer("new com.example.MyStringAdapter()")), + "ListOfString" to ScalarInfo("List"), ) } else { mapOf( @@ -311,6 +313,7 @@ class CodegenTest { "URL" to ScalarInfo("kotlin.String", ExpressionAdapterInitializer("com.example.UrlAdapter")), "ID" to ScalarInfo("kotlin.Long"), "String" to ScalarInfo("kotlin.String", ExpressionAdapterInitializer("com.example.MyStringAdapter()")), + "ListOfString" to ScalarInfo("List"), ) } } else { @@ -354,7 +357,7 @@ class CodegenTest { val generateModelBuilders = when (folder.name) { "fragment_with_inline_fragment", "java_primitive_types", "java_apollo_optionals", "java_guava_optionals", "java_java_optionals", "simple_target_name", "java_jetbrains_annotations", "java_android_annotations", "java_jsr305_annotations", - -> true + -> true else -> false } @@ -362,7 +365,7 @@ class CodegenTest { val generatePrimitiveTypes = when (folder.name) { "java_primitive_types", "java_apollo_optionals", "java_guava_optionals", "java_java_optionals", "java_jetbrains_annotations", "java_android_annotations", "java_jsr305_annotations", - -> true + -> true else -> false }