From dfa0be8192eea8fa4002fc161b1e9fdd8a265bbc Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Wed, 6 Oct 2021 22:06:57 +0200 Subject: [PATCH 1/3] add a test case for #3394 --- .../TestOperation.graphql | 3 + .../input_field_default_value/TestQuery.java | 272 ++++++++++++++++++ .../input_field_default_value/TestQuery.kt | 148 ++++++++++ .../input_field_default_value/schema.sdl | 11 + .../type/CustomType.java | 24 ++ .../type/CustomType.kt | 17 ++ .../type/Filter.java | 83 ++++++ .../input_field_default_value/type/Filter.kt | 21 ++ .../input_field_default_value/type/Input.java | 86 ++++++ .../input_field_default_value/type/Input.kt | 20 ++ 10 files changed, 685 insertions(+) create mode 100644 apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestOperation.graphql create mode 100644 apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestQuery.java create mode 100644 apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestQuery.kt create mode 100644 apollo-compiler/src/test/graphql/com/example/input_field_default_value/schema.sdl create mode 100644 apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/CustomType.java create mode 100644 apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/CustomType.kt create mode 100644 apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Filter.java create mode 100644 apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Filter.kt create mode 100644 apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.java create mode 100644 apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.kt diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestOperation.graphql b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestOperation.graphql new file mode 100644 index 00000000000..63033eacb22 --- /dev/null +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestOperation.graphql @@ -0,0 +1,3 @@ +query TestQuery($input: Input!) { + field(input: $input) +} \ No newline at end of file diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestQuery.java b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestQuery.java new file mode 100644 index 00000000000..21813dafb0a --- /dev/null +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestQuery.java @@ -0,0 +1,272 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found. +// It should not be modified by hand. +// +package com.example.input_field_default_value; + +import com.apollographql.apollo.api.Operation; +import com.apollographql.apollo.api.OperationName; +import com.apollographql.apollo.api.Query; +import com.apollographql.apollo.api.Response; +import com.apollographql.apollo.api.ResponseField; +import com.apollographql.apollo.api.ScalarTypeAdapters; +import com.apollographql.apollo.api.internal.InputFieldMarshaller; +import com.apollographql.apollo.api.internal.InputFieldWriter; +import com.apollographql.apollo.api.internal.OperationRequestBodyComposer; +import com.apollographql.apollo.api.internal.Optional; +import com.apollographql.apollo.api.internal.QueryDocumentMinifier; +import com.apollographql.apollo.api.internal.ResponseFieldMapper; +import com.apollographql.apollo.api.internal.ResponseFieldMarshaller; +import com.apollographql.apollo.api.internal.ResponseReader; +import com.apollographql.apollo.api.internal.ResponseWriter; +import com.apollographql.apollo.api.internal.SimpleOperationResponseParser; +import com.apollographql.apollo.api.internal.UnmodifiableMapBuilder; +import com.apollographql.apollo.api.internal.Utils; +import com.example.input_field_default_value.type.Input; +import java.io.IOException; +import java.lang.Object; +import java.lang.Override; +import java.lang.String; +import java.lang.SuppressWarnings; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import okio.Buffer; +import okio.BufferedSource; +import okio.ByteString; +import org.jetbrains.annotations.NotNull; + +public final class TestQuery implements Query, TestQuery.Variables> { + public static final String OPERATION_ID = "e932e2ab855254eba685491d4fd87a8a0ddaadc3d02a6d7d0b7f5c341b0cdc43"; + + public static final String QUERY_DOCUMENT = QueryDocumentMinifier.minify( + "query TestQuery($input: Input!) {\n" + + " field(input: $input)\n" + + "}" + ); + + public static final OperationName OPERATION_NAME = new OperationName() { + @Override + public String name() { + return "TestQuery"; + } + }; + + private final TestQuery.Variables variables; + + public TestQuery(@NotNull Input input) { + Utils.checkNotNull(input, "input == null"); + variables = new TestQuery.Variables(input); + } + + @Override + public String operationId() { + return OPERATION_ID; + } + + @Override + public String queryDocument() { + return QUERY_DOCUMENT; + } + + @Override + public Optional wrapData(TestQuery.Data data) { + return Optional.fromNullable(data); + } + + @Override + public TestQuery.Variables variables() { + return variables; + } + + @Override + public ResponseFieldMapper responseFieldMapper() { + return new Data.Mapper(); + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public OperationName name() { + return OPERATION_NAME; + } + + @Override + @NotNull + public Response> parse(@NotNull final BufferedSource source, + @NotNull final ScalarTypeAdapters scalarTypeAdapters) throws IOException { + return SimpleOperationResponseParser.parse(source, this, scalarTypeAdapters); + } + + @Override + @NotNull + public Response> parse(@NotNull final ByteString byteString, + @NotNull final ScalarTypeAdapters scalarTypeAdapters) throws IOException { + return parse(new Buffer().write(byteString), scalarTypeAdapters); + } + + @Override + @NotNull + public Response> parse(@NotNull final BufferedSource source) throws + IOException { + return parse(source, ScalarTypeAdapters.DEFAULT); + } + + @Override + @NotNull + public Response> parse(@NotNull final ByteString byteString) throws + IOException { + return parse(byteString, ScalarTypeAdapters.DEFAULT); + } + + @Override + @NotNull + public ByteString composeRequestBody(@NotNull final ScalarTypeAdapters scalarTypeAdapters) { + return OperationRequestBodyComposer.compose(this, false, true, scalarTypeAdapters); + } + + @NotNull + @Override + public ByteString composeRequestBody() { + return OperationRequestBodyComposer.compose(this, false, true, ScalarTypeAdapters.DEFAULT); + } + + @Override + @NotNull + public ByteString composeRequestBody(final boolean autoPersistQueries, + final boolean withQueryDocument, @NotNull final ScalarTypeAdapters scalarTypeAdapters) { + return OperationRequestBodyComposer.compose(this, autoPersistQueries, withQueryDocument, scalarTypeAdapters); + } + + public static final class Builder { + private @NotNull Input input; + + Builder() { + } + + public Builder input(@NotNull Input input) { + this.input = input; + return this; + } + + public TestQuery build() { + Utils.checkNotNull(input, "input == null"); + return new TestQuery(input); + } + } + + public static final class Variables extends Operation.Variables { + private final @NotNull Input input; + + private final transient Map valueMap = new LinkedHashMap<>(); + + Variables(@NotNull Input input) { + this.input = input; + this.valueMap.put("input", input); + } + + public @NotNull Input input() { + return input; + } + + @Override + public Map valueMap() { + return Collections.unmodifiableMap(valueMap); + } + + @Override + public InputFieldMarshaller marshaller() { + return new InputFieldMarshaller() { + @Override + public void marshal(InputFieldWriter writer) throws IOException { + writer.writeObject("input", input.marshaller()); + } + }; + } + } + + /** + * Data from the response after executing this GraphQL operation + */ + public static class Data implements Operation.Data { + static final ResponseField[] $responseFields = { + ResponseField.forInt("field", "field", new UnmodifiableMapBuilder(1) + .put("input", new UnmodifiableMapBuilder(2) + .put("kind", "Variable") + .put("variableName", "input") + .build()) + .build(), false, Collections.emptyList()) + }; + + final int field; + + private transient volatile String $toString; + + private transient volatile int $hashCode; + + private transient volatile boolean $hashCodeMemoized; + + public Data(int field) { + this.field = field; + } + + public int field() { + return this.field; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public ResponseFieldMarshaller marshaller() { + return new ResponseFieldMarshaller() { + @Override + public void marshal(ResponseWriter writer) { + writer.writeInt($responseFields[0], field); + } + }; + } + + @Override + public String toString() { + if ($toString == null) { + $toString = "Data{" + + "field=" + field + + "}"; + } + return $toString; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Data) { + Data that = (Data) o; + return this.field == that.field; + } + return false; + } + + @Override + public int hashCode() { + if (!$hashCodeMemoized) { + int h = 1; + h *= 1000003; + h ^= field; + $hashCode = h; + $hashCodeMemoized = true; + } + return $hashCode; + } + + public static final class Mapper implements ResponseFieldMapper { + @Override + public Data map(ResponseReader reader) { + final int field = reader.readInt($responseFields[0]); + return new Data(field); + } + } + } +} diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestQuery.kt b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestQuery.kt new file mode 100644 index 00000000000..3e9b69d0669 --- /dev/null +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/TestQuery.kt @@ -0,0 +1,148 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found. +// It should not be modified by hand. +// +package com.example.input_field_default_value + +import com.apollographql.apollo.api.Operation +import com.apollographql.apollo.api.OperationName +import com.apollographql.apollo.api.Query +import com.apollographql.apollo.api.Response +import com.apollographql.apollo.api.ResponseField +import com.apollographql.apollo.api.ScalarTypeAdapters +import com.apollographql.apollo.api.ScalarTypeAdapters.Companion.DEFAULT +import com.apollographql.apollo.api.internal.InputFieldMarshaller +import com.apollographql.apollo.api.internal.OperationRequestBodyComposer +import com.apollographql.apollo.api.internal.QueryDocumentMinifier +import com.apollographql.apollo.api.internal.ResponseFieldMapper +import com.apollographql.apollo.api.internal.ResponseFieldMarshaller +import com.apollographql.apollo.api.internal.ResponseReader +import com.apollographql.apollo.api.internal.SimpleOperationResponseParser +import com.apollographql.apollo.api.internal.Throws +import com.example.input_field_default_value.type.Input +import kotlin.Any +import kotlin.Array +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.collections.Map +import kotlin.jvm.Transient +import okio.Buffer +import okio.BufferedSource +import okio.ByteString +import okio.IOException + +@Suppress("NAME_SHADOWING", "UNUSED_ANONYMOUS_PARAMETER", "LocalVariableName", + "RemoveExplicitTypeArguments", "NestedLambdaShadowedImplicitParameter") +data class TestQuery( + val input: Input +) : Query { + @Transient + private val variables: Operation.Variables = object : Operation.Variables() { + override fun valueMap(): Map = mutableMapOf().apply { + this["input"] = this@TestQuery.input + } + + override fun marshaller(): InputFieldMarshaller = InputFieldMarshaller.invoke { writer -> + writer.writeObject("input", this@TestQuery.input.marshaller()) + } + } + + override fun operationId(): String = OPERATION_ID + override fun queryDocument(): String = QUERY_DOCUMENT + override fun wrapData(data: Data?): Data? = data + override fun variables(): Operation.Variables = variables + override fun name(): OperationName = OPERATION_NAME + override fun responseFieldMapper(): ResponseFieldMapper = ResponseFieldMapper.invoke { + Data(it) + } + + @Throws(IOException::class) + override fun parse(source: BufferedSource, scalarTypeAdapters: ScalarTypeAdapters): Response + = SimpleOperationResponseParser.parse(source, this, scalarTypeAdapters) + + @Throws(IOException::class) + override fun parse(byteString: ByteString, scalarTypeAdapters: ScalarTypeAdapters): Response + = parse(Buffer().write(byteString), scalarTypeAdapters) + + @Throws(IOException::class) + override fun parse(source: BufferedSource): Response = parse(source, DEFAULT) + + @Throws(IOException::class) + override fun parse(byteString: ByteString): Response = parse(byteString, DEFAULT) + + override fun composeRequestBody(scalarTypeAdapters: ScalarTypeAdapters): ByteString = + OperationRequestBodyComposer.compose( + operation = this, + autoPersistQueries = false, + withQueryDocument = true, + scalarTypeAdapters = scalarTypeAdapters + ) + + override fun composeRequestBody(): ByteString = OperationRequestBodyComposer.compose( + operation = this, + autoPersistQueries = false, + withQueryDocument = true, + scalarTypeAdapters = DEFAULT + ) + + override fun composeRequestBody( + autoPersistQueries: Boolean, + withQueryDocument: Boolean, + scalarTypeAdapters: ScalarTypeAdapters + ): ByteString = OperationRequestBodyComposer.compose( + operation = this, + autoPersistQueries = autoPersistQueries, + withQueryDocument = withQueryDocument, + scalarTypeAdapters = scalarTypeAdapters + ) + + /** + * Data from the response after executing this GraphQL operation + */ + data class Data( + val field_: Int + ) : Operation.Data { + override fun marshaller(): ResponseFieldMarshaller = ResponseFieldMarshaller.invoke { writer -> + writer.writeInt(RESPONSE_FIELDS[0], this@Data.field_) + } + + companion object { + private val RESPONSE_FIELDS: Array = arrayOf( + ResponseField.forInt("field", "field", mapOf( + "input" to mapOf( + "kind" to "Variable", + "variableName" to "input")), false, null) + ) + + operator fun invoke(reader: ResponseReader): Data = reader.run { + val field_ = readInt(RESPONSE_FIELDS[0])!! + Data( + field_ = field_ + ) + } + + @Suppress("FunctionName") + fun Mapper(): ResponseFieldMapper = ResponseFieldMapper { invoke(it) } + } + } + + companion object { + const val OPERATION_ID: String = + "e932e2ab855254eba685491d4fd87a8a0ddaadc3d02a6d7d0b7f5c341b0cdc43" + + val QUERY_DOCUMENT: String = QueryDocumentMinifier.minify( + """ + |query TestQuery(${'$'}input: Input!) { + | field(input: ${'$'}input) + |} + """.trimMargin() + ) + + val OPERATION_NAME: OperationName = object : OperationName { + override fun name(): String = "TestQuery" + } + } +} diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/schema.sdl b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/schema.sdl new file mode 100644 index 00000000000..e765f8e0679 --- /dev/null +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/schema.sdl @@ -0,0 +1,11 @@ +type Query { + field(input: Input!): Int! +} + +input Input { + filter: Filter! = { delay: 0 } +} + +input Filter { + delay: Int! +} \ No newline at end of file diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/CustomType.java b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/CustomType.java new file mode 100644 index 00000000000..e6b0131857f --- /dev/null +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/CustomType.java @@ -0,0 +1,24 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found. +// It should not be modified by hand. +// +package com.example.input_field_default_value.type; + +import com.apollographql.apollo.api.ScalarType; +import java.lang.Override; +import java.lang.String; + +public enum CustomType implements ScalarType { + ID { + @Override + public String typeName() { + return "ID"; + } + + @Override + public String className() { + return "java.lang.String"; + } + } +} diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/CustomType.kt b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/CustomType.kt new file mode 100644 index 00000000000..8873558b3c7 --- /dev/null +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/CustomType.kt @@ -0,0 +1,17 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found. +// It should not be modified by hand. +// +package com.example.input_field_default_value.type + +import com.apollographql.apollo.api.ScalarType +import kotlin.String + +enum class CustomType : ScalarType { + ID { + override fun typeName(): String = "ID" + + override fun className(): String = "kotlin.String" + } +} diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Filter.java b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Filter.java new file mode 100644 index 00000000000..239541906d1 --- /dev/null +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Filter.java @@ -0,0 +1,83 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found. +// It should not be modified by hand. +// +package com.example.input_field_default_value.type; + +import com.apollographql.apollo.api.InputType; +import com.apollographql.apollo.api.internal.InputFieldMarshaller; +import com.apollographql.apollo.api.internal.InputFieldWriter; +import java.io.IOException; +import java.lang.Object; +import java.lang.Override; + +public final class Filter implements InputType { + private final int delay; + + private transient volatile int $hashCode; + + private transient volatile boolean $hashCodeMemoized; + + Filter(int delay) { + this.delay = delay; + } + + public int delay() { + return this.delay; + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public InputFieldMarshaller marshaller() { + return new InputFieldMarshaller() { + @Override + public void marshal(InputFieldWriter writer) throws IOException { + writer.writeInt("delay", delay); + } + }; + } + + @Override + public int hashCode() { + if (!$hashCodeMemoized) { + int h = 1; + h *= 1000003; + h ^= delay; + $hashCode = h; + $hashCodeMemoized = true; + } + return $hashCode; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Filter) { + Filter that = (Filter) o; + return this.delay == that.delay; + } + return false; + } + + public static final class Builder { + private int delay; + + Builder() { + } + + public Builder delay(int delay) { + this.delay = delay; + return this; + } + + public Filter build() { + return new Filter(delay); + } + } +} diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Filter.kt b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Filter.kt new file mode 100644 index 00000000000..8bc25cfcb37 --- /dev/null +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Filter.kt @@ -0,0 +1,21 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found. +// It should not be modified by hand. +// +package com.example.input_field_default_value.type + +import com.apollographql.apollo.api.InputType +import com.apollographql.apollo.api.internal.InputFieldMarshaller +import kotlin.Int +import kotlin.Suppress + +@Suppress("NAME_SHADOWING", "UNUSED_ANONYMOUS_PARAMETER", "LocalVariableName", + "RemoveExplicitTypeArguments", "NestedLambdaShadowedImplicitParameter") +data class Filter( + val delay: Int +) : InputType { + override fun marshaller(): InputFieldMarshaller = InputFieldMarshaller.invoke { writer -> + writer.writeInt("delay", this@Filter.delay) + } +} diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.java b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.java new file mode 100644 index 00000000000..3c264138083 --- /dev/null +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.java @@ -0,0 +1,86 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found. +// It should not be modified by hand. +// +package com.example.input_field_default_value.type; + +import com.apollographql.apollo.api.InputType; +import com.apollographql.apollo.api.internal.InputFieldMarshaller; +import com.apollographql.apollo.api.internal.InputFieldWriter; +import com.apollographql.apollo.api.internal.Utils; +import java.io.IOException; +import java.lang.Object; +import java.lang.Override; +import org.jetbrains.annotations.NotNull; + +public final class Input implements InputType { + private final @NotNull Filter filter; + + private transient volatile int $hashCode; + + private transient volatile boolean $hashCodeMemoized; + + Input(@NotNull Filter filter) { + this.filter = filter; + } + + public @NotNull Filter filter() { + return this.filter; + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public InputFieldMarshaller marshaller() { + return new InputFieldMarshaller() { + @Override + public void marshal(InputFieldWriter writer) throws IOException { + writer.writeObject("filter", filter.marshaller()); + } + }; + } + + @Override + public int hashCode() { + if (!$hashCodeMemoized) { + int h = 1; + h *= 1000003; + h ^= filter.hashCode(); + $hashCode = h; + $hashCodeMemoized = true; + } + return $hashCode; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof Input) { + Input that = (Input) o; + return this.filter.equals(that.filter); + } + return false; + } + + public static final class Builder { + private @NotNull Filter filter = "{delay:0}"; + + Builder() { + } + + public Builder filter(@NotNull Filter filter) { + this.filter = filter; + return this; + } + + public Input build() { + Utils.checkNotNull(filter, "filter == null"); + return new Input(filter); + } + } +} diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.kt b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.kt new file mode 100644 index 00000000000..fa0f711e967 --- /dev/null +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.kt @@ -0,0 +1,20 @@ +// AUTO-GENERATED FILE. DO NOT MODIFY. +// +// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found. +// It should not be modified by hand. +// +package com.example.input_field_default_value.type + +import com.apollographql.apollo.api.InputType +import com.apollographql.apollo.api.internal.InputFieldMarshaller +import kotlin.Suppress + +@Suppress("NAME_SHADOWING", "UNUSED_ANONYMOUS_PARAMETER", "LocalVariableName", + "RemoveExplicitTypeArguments", "NestedLambdaShadowedImplicitParameter") +data class Input( + val filter: Filter = "{delay:0}" +) : InputType { + override fun marshaller(): InputFieldMarshaller = InputFieldMarshaller.invoke { writer -> + writer.writeObject("filter", this@Input.filter.marshaller()) + } +} From 331a6439da5784837b77efd5a5b8424735dd94ff Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Wed, 6 Oct 2021 22:26:44 +0200 Subject: [PATCH 2/3] do not generate defaultValues for input fields of input object type --- .../apollographql/apollo/compiler/InputTypeSpecBuilder.kt | 4 ++-- .../apollo/compiler/codegen/kotlin/InputType.kt | 5 +++++ .../kotlin/com/apollographql/apollo/compiler/testUtils.kt | 7 +++++++ .../com/example/input_field_default_value/type/Input.java | 2 +- .../com/example/input_field_default_value/type/Input.kt | 2 +- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/InputTypeSpecBuilder.kt b/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/InputTypeSpecBuilder.kt index 7f5ab40c3b9..7f452fbb5c1 100644 --- a/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/InputTypeSpecBuilder.kt +++ b/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/InputTypeSpecBuilder.kt @@ -49,9 +49,9 @@ class InputTypeSpecBuilder( val builderFields = fields.map { it.name.decapitalize().escapeJavaReservedWord() to it.javaTypeName(context) } val builderFieldDefaultValues = fields .filterNot { - // ignore any custom type default values for now as we don't support them + // ignore any custom type or object default values for now as we don't support them val normalizedType = it.type.removeSuffix("!").removeSurrounding("[", "]").removeSuffix("!") - normalizedType.isCustomScalarType(context) + normalizedType.isCustomScalarType(context) || normalizedType.isInputObject(context) } .associate { it.name.decapitalize().escapeJavaReservedWord() to it.defaultValue } val javaDocs = fields diff --git a/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/InputType.kt b/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/InputType.kt index b2e8ade4b15..37642e8bd4a 100644 --- a/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/InputType.kt +++ b/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/InputType.kt @@ -41,6 +41,11 @@ private fun InputType.Field.parameterSpec(): ParameterSpec { else -> rawTypeName } val defaultValue = defaultValue + /** + * For input objects, do not try to create a defaultValue + * See https://github.com/apollographql/apollo-android/issues/3394 + */ + ?.takeIf { type !is FieldType.Object } ?.toDefaultValueCodeBlock(typeName = rawTypeName, fieldType = type) .let { code -> if (isOptional) { diff --git a/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/testUtils.kt b/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/testUtils.kt index 894fd6b9801..a697073d8b5 100644 --- a/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/testUtils.kt +++ b/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/testUtils.kt @@ -1,6 +1,9 @@ package com.apollographql.apollo.compiler +import com.apollographql.apollo.compiler.ast.ObjectType import com.apollographql.apollo.compiler.ir.CodeGenerationContext +import com.apollographql.apollo.compiler.ir.TypeDeclaration.Companion.KIND_INPUT_OBJECT_TYPE +import com.apollographql.apollo.compiler.parser.introspection.IntrospectionSchema import com.squareup.javapoet.* import javax.lang.model.element.Modifier @@ -415,6 +418,10 @@ fun String.isCustomScalarType(context: CodeGenerationContext): Boolean { } } +fun String.isInputObject(context: CodeGenerationContext): Boolean { + return context.typeDeclarations.firstOrNull { it.name == this }?.kind == KIND_INPUT_OBJECT_TYPE +} + fun TypeName.isScalar(context: CodeGenerationContext) = (Util.SCALAR_TYPES.contains(this) || isEnum(context)) fun normalizeGraphQlType(type: String, recursive: Boolean = false): String { diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.java b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.java index 3c264138083..c85b3387308 100644 --- a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.java +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.java @@ -68,7 +68,7 @@ public boolean equals(Object o) { } public static final class Builder { - private @NotNull Filter filter = "{delay:0}"; + private @NotNull Filter filter; Builder() { } diff --git a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.kt b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.kt index fa0f711e967..b2f4a115f44 100644 --- a/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.kt +++ b/apollo-compiler/src/test/graphql/com/example/input_field_default_value/type/Input.kt @@ -12,7 +12,7 @@ import kotlin.Suppress @Suppress("NAME_SHADOWING", "UNUSED_ANONYMOUS_PARAMETER", "LocalVariableName", "RemoveExplicitTypeArguments", "NestedLambdaShadowedImplicitParameter") data class Input( - val filter: Filter = "{delay:0}" + val filter: Filter ) : InputType { override fun marshaller(): InputFieldMarshaller = InputFieldMarshaller.invoke { writer -> writer.writeObject("filter", this@Input.filter.marshaller()) From 7d7318968d5340a6ab67885807ae691a8928cbb4 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Wed, 6 Oct 2021 22:43:01 +0200 Subject: [PATCH 3/3] make an exception for emptyList for backward compatibility --- .../apollo/compiler/InputTypeSpecBuilder.kt | 16 ++++++++++++-- .../compiler/codegen/kotlin/InputType.kt | 21 ++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/InputTypeSpecBuilder.kt b/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/InputTypeSpecBuilder.kt index 7f452fbb5c1..12282e031f6 100644 --- a/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/InputTypeSpecBuilder.kt +++ b/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/InputTypeSpecBuilder.kt @@ -42,16 +42,28 @@ class InputTypeSpecBuilder( ) } + private fun Any?.isEmptyList(): Boolean { + return if (this is List<*>) { + if (isEmpty()) { + true + } else { + first()?.isEmptyList() == true + } + } else { + false + } + } private fun TypeSpec.Builder.addBuilder(): TypeSpec.Builder { if (fields.isEmpty()) { return this } else { val builderFields = fields.map { it.name.decapitalize().escapeJavaReservedWord() to it.javaTypeName(context) } val builderFieldDefaultValues = fields - .filterNot { + .filter { // ignore any custom type or object default values for now as we don't support them val normalizedType = it.type.removeSuffix("!").removeSurrounding("[", "]").removeSuffix("!") - normalizedType.isCustomScalarType(context) || normalizedType.isInputObject(context) + !normalizedType.isCustomScalarType(context) + && (!normalizedType.isInputObject(context) || it.defaultValue.isEmptyList()) } .associate { it.name.decapitalize().escapeJavaReservedWord() to it.defaultValue } val javaDocs = fields diff --git a/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/InputType.kt b/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/InputType.kt index 37642e8bd4a..448d3a986a7 100644 --- a/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/InputType.kt +++ b/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/InputType.kt @@ -34,6 +34,25 @@ private val InputType.primaryConstructorSpec: FunSpec .build() } +private fun FieldType.leafType(): FieldType { + return when (this) { + is FieldType.Array -> this.rawType + else -> this + } +} + +private fun Any?.isEmptyList(): Boolean { + return if (this is List<*>) { + if (isEmpty()) { + true + } else { + first()?.isEmptyList() == true + } + } else { + false + } +} + private fun InputType.Field.parameterSpec(): ParameterSpec { val rawTypeName = type.asTypeName() val typeName = when { @@ -45,7 +64,7 @@ private fun InputType.Field.parameterSpec(): ParameterSpec { * For input objects, do not try to create a defaultValue * See https://github.com/apollographql/apollo-android/issues/3394 */ - ?.takeIf { type !is FieldType.Object } + ?.takeIf { type.leafType() !is FieldType.Object || it.isEmptyList() } ?.toDefaultValueCodeBlock(typeName = rawTypeName, fieldType = type) .let { code -> if (isOptional) {