From 72d134b2d8bbae9e314746ad6e5b71035ef38a2f Mon Sep 17 00:00:00 2001 From: Wesley Ellis Date: Wed, 2 Aug 2017 11:19:21 -0400 Subject: [PATCH 1/7] Allow setting optional fields on input objects to explicit null --- .../templates/APISchema.java.erb | 11 ++++- .../shopify/graphql/support/Generated.java | 48 +++++++++++++++++-- .../graphql/support/GeneratedMinimal.java | 1 + .../graphql/support/IntegrationTest.java | 8 ++++ 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb index 945bfac..8abbca3 100644 --- a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb +++ b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb @@ -18,6 +18,7 @@ import com.shopify.graphql.support.TopLevelResponse; import java.io.Serializable; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; @@ -266,6 +267,7 @@ public class <%= schema_name %> { <% type.optional_input_fields.each do |field| %> private <%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>; <% end %> + private HashSet fieldsSeen = new HashSet<>(); <% unless type.required_input_fields.empty? %> public <%= type.name %>(<%= type.required_input_fields.map{ |field| "#{java_input_type(field.type)} #{escape_reserved_word(field.camelize_name)}" }.join(', ') %>) { @@ -292,6 +294,7 @@ public class <%= schema_name %> { public <%= type.name %> set<%= field.classify_name %>(<%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { this.<%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %>; + fieldsSeen.add("<%= field.name %>"); return this; } <% end %> @@ -306,11 +309,15 @@ public class <%= schema_name %> { <%= generate_build_input_code(escape_reserved_word(field.camelize_name), field.type) %> <% end %> <% type.optional_input_fields.each do |field| %> - if (<%= escape_reserved_word(field.camelize_name) %> != null) { + if (fieldsSeen.contains("<%= field.name %>")) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("<%= field.name %>:"); - <%= generate_build_input_code(escape_reserved_word(field.camelize_name), field.type) %> + if (<%= escape_reserved_word(field.camelize_name) %> != null) { + <%= generate_build_input_code(escape_reserved_word(field.camelize_name), field.type) %> + } else { + _queryBuilder.append("null"); + } } <% end %> _queryBuilder.append('}'); diff --git a/support/src/test/java/com/shopify/graphql/support/Generated.java b/support/src/test/java/com/shopify/graphql/support/Generated.java index 726b41b..135ad3a 100644 --- a/support/src/test/java/com/shopify/graphql/support/Generated.java +++ b/support/src/test/java/com/shopify/graphql/support/Generated.java @@ -19,6 +19,7 @@ import java.io.Serializable; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; @@ -429,6 +430,9 @@ public boolean unwrapsToObject(String key) { } } + /** + * Types of values that can be stored in a key + */ public enum KeyType { INTEGER, @@ -676,6 +680,9 @@ public QueryRootQuery entries(int first, EntriesArgumentsDefinition argsDef, Ent return this; } + /** + * Get an entry of any type with the given key + */ public QueryRootQuery entry(String key, EntryQueryDefinition queryDef) { startField("entry"); @@ -691,6 +698,9 @@ public QueryRootQuery entry(String key, EntryQueryDefinition queryDef) { return this; } + /** + * Get an entry of any type with the given key as a union + */ public QueryRootQuery entryUnion(String key, EntryUnionQueryDefinition queryDef) { startField("entry_union"); @@ -706,6 +716,9 @@ public QueryRootQuery entryUnion(String key, EntryUnionQueryDefinition queryDef) return this; } + /** + * Get a integer value with the given key + */ public QueryRootQuery integer(String key) { startField("integer"); @@ -760,6 +773,9 @@ public QueryRootQuery keys(int first, KeysArgumentsDefinition argsDef) { return this; } + /** + * Get a string value with the given key + */ public QueryRootQuery string(String key) { startField("string"); @@ -936,6 +952,9 @@ public QueryRoot setEntries(List arg) { return this; } + /** + * Get an entry of any type with the given key + */ public Entry getEntry() { return (Entry) get("entry"); } @@ -945,6 +964,9 @@ public QueryRoot setEntry(Entry arg) { return this; } + /** + * Get an entry of any type with the given key as a union + */ public EntryUnion getEntryUnion() { return (EntryUnion) get("entry_union"); } @@ -954,6 +976,9 @@ public QueryRoot setEntryUnion(EntryUnion arg) { return this; } + /** + * Get a integer value with the given key + */ public Integer getInteger() { return (Integer) get("integer"); } @@ -972,6 +997,9 @@ public QueryRoot setKeys(List arg) { return this; } + /** + * Get a string value with the given key + */ public String getString() { return (String) get("string"); } @@ -1042,6 +1070,8 @@ public static class SetIntegerInput implements Serializable { private Boolean negate; + private HashSet fieldsSeen = new HashSet<>(); + public SetIntegerInput(String key, int value) { this.key = key; @@ -1072,6 +1102,7 @@ public LocalDateTime getTtl() { public SetIntegerInput setTtl(LocalDateTime ttl) { this.ttl = ttl; + fieldsSeen.add("ttl"); return this; } @@ -1081,6 +1112,7 @@ public Boolean getNegate() { public SetIntegerInput setNegate(Boolean negate) { this.negate = negate; + fieldsSeen.add("negate"); return this; } @@ -1098,18 +1130,26 @@ public void appendTo(StringBuilder _queryBuilder) { _queryBuilder.append("value:"); _queryBuilder.append(value); - if (ttl != null) { + if (fieldsSeen.contains("ttl")) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("ttl:"); - Query.appendQuotedString(_queryBuilder, ttl.toString()); + if (ttl != null) { + Query.appendQuotedString(_queryBuilder, ttl.toString()); + } else { + _queryBuilder.append("null"); + } } - if (negate != null) { + if (fieldsSeen.contains("negate")) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("negate:"); - _queryBuilder.append(negate); + if (negate != null) { + _queryBuilder.append(negate); + } else { + _queryBuilder.append("null"); + } } _queryBuilder.append('}'); diff --git a/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java b/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java index 808e6a8..084cbc0 100644 --- a/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java +++ b/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java @@ -17,6 +17,7 @@ import java.io.Serializable; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; diff --git a/support/src/test/java/com/shopify/graphql/support/IntegrationTest.java b/support/src/test/java/com/shopify/graphql/support/IntegrationTest.java index 3115cab..0ea10d7 100644 --- a/support/src/test/java/com/shopify/graphql/support/IntegrationTest.java +++ b/support/src/test/java/com/shopify/graphql/support/IntegrationTest.java @@ -156,4 +156,12 @@ public void testMutationResponse() throws Exception { Generated.Mutation data = Generated.MutationResponse.fromJson(json).getData(); assertEquals(true, data.getSetString().booleanValue()); } + + @Test + public void testOptionalFieldOnInput() throws Exception { + String queryString = Generated.mutation(mutation -> mutation + .setInteger(new Generated.SetIntegerInput("answer", 42).setTtl(null)) + ).toString(); + assertEquals("mutation{set_integer(input:{key:\"answer\",value:42,ttl:null})}", queryString); + } } From 209aeae2608682ccdda3e448e493c3a7d12a7dda Mon Sep 17 00:00:00 2001 From: Wesley Ellis Date: Wed, 2 Aug 2017 13:54:52 -0400 Subject: [PATCH 2/7] Use generated boolean fields instead of HashSet to track if an argument was set --- .../graphql_java_gen/templates/APISchema.java.erb | 7 +++---- .../java/com/shopify/graphql/support/Generated.java | 13 ++++++------- .../shopify/graphql/support/GeneratedMinimal.java | 1 - 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb index 8abbca3..aff9d02 100644 --- a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb +++ b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb @@ -18,7 +18,6 @@ import com.shopify.graphql.support.TopLevelResponse; import java.io.Serializable; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Map; @@ -266,8 +265,8 @@ public class <%= schema_name %> { <% end %> <% type.optional_input_fields.each do |field| %> private <%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>; + private boolean <%= escape_reserved_word(field.name) %>Seen = false; <% end %> - private HashSet fieldsSeen = new HashSet<>(); <% unless type.required_input_fields.empty? %> public <%= type.name %>(<%= type.required_input_fields.map{ |field| "#{java_input_type(field.type)} #{escape_reserved_word(field.camelize_name)}" }.join(', ') %>) { @@ -294,7 +293,7 @@ public class <%= schema_name %> { public <%= type.name %> set<%= field.classify_name %>(<%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { this.<%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %>; - fieldsSeen.add("<%= field.name %>"); + this.<%= escape_reserved_word(field.name) %>Seen = true; return this; } <% end %> @@ -309,7 +308,7 @@ public class <%= schema_name %> { <%= generate_build_input_code(escape_reserved_word(field.camelize_name), field.type) %> <% end %> <% type.optional_input_fields.each do |field| %> - if (fieldsSeen.contains("<%= field.name %>")) { + if (this.<%= escape_reserved_word(field.name) %>Seen) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("<%= field.name %>:"); diff --git a/support/src/test/java/com/shopify/graphql/support/Generated.java b/support/src/test/java/com/shopify/graphql/support/Generated.java index 135ad3a..3cce9dd 100644 --- a/support/src/test/java/com/shopify/graphql/support/Generated.java +++ b/support/src/test/java/com/shopify/graphql/support/Generated.java @@ -19,7 +19,6 @@ import java.io.Serializable; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Map; @@ -1067,10 +1066,10 @@ public static class SetIntegerInput implements Serializable { private int value; private LocalDateTime ttl; + private boolean ttlSeen = false; private Boolean negate; - - private HashSet fieldsSeen = new HashSet<>(); + private boolean negateSeen = false; public SetIntegerInput(String key, int value) { this.key = key; @@ -1102,7 +1101,7 @@ public LocalDateTime getTtl() { public SetIntegerInput setTtl(LocalDateTime ttl) { this.ttl = ttl; - fieldsSeen.add("ttl"); + this.ttlSeen = true; return this; } @@ -1112,7 +1111,7 @@ public Boolean getNegate() { public SetIntegerInput setNegate(Boolean negate) { this.negate = negate; - fieldsSeen.add("negate"); + this.negateSeen = true; return this; } @@ -1130,7 +1129,7 @@ public void appendTo(StringBuilder _queryBuilder) { _queryBuilder.append("value:"); _queryBuilder.append(value); - if (fieldsSeen.contains("ttl")) { + if (this.ttlSeen) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("ttl:"); @@ -1141,7 +1140,7 @@ public void appendTo(StringBuilder _queryBuilder) { } } - if (fieldsSeen.contains("negate")) { + if (this.negateSeen) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("negate:"); diff --git a/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java b/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java index 084cbc0..808e6a8 100644 --- a/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java +++ b/support/src/test/java/com/shopify/graphql/support/GeneratedMinimal.java @@ -17,7 +17,6 @@ import java.io.Serializable; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Map; From fb7d84918c3cac155c28928277fb290bd7b06a27 Mon Sep 17 00:00:00 2001 From: Wesley Ellis Date: Wed, 2 Aug 2017 15:35:19 -0400 Subject: [PATCH 3/7] add annotations to input object returns and arguments --- codegen/lib/graphql_java_gen/templates/APISchema.java.erb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb index aff9d02..ba5f611 100644 --- a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb +++ b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb @@ -277,21 +277,23 @@ public class <%= schema_name %> { <% end %> <% type.required_input_fields.each do |field| %> + <%= java_annotations(field) -%> public <%= java_input_type(field.type) %> get<%= field.classify_name %>() { return <%= escape_reserved_word(field.camelize_name) %>; } - public <%= type.name %> set<%= field.classify_name %>(<%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { + public <%= type.name %> set<%= field.classify_name %>(<%= java_annotations(field).gsub(/(.)$/, '\1 ') %><%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { this.<%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %>; return this; } <% end %> <% type.optional_input_fields.each do |field| %> + <%= java_annotations(field) -%> public <%= java_input_type(field.type) %> get<%= field.classify_name %>() { return <%= escape_reserved_word(field.camelize_name) %>; } - public <%= type.name %> set<%= field.classify_name %>(<%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { + public <%= type.name %> set<%= field.classify_name %>(<%= java_annotations(field).gsub(/(.)$/, '\1 ') %><%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { this.<%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %>; this.<%= escape_reserved_word(field.name) %>Seen = true; return this; From 74840a7ea472e21eff34e1f2a730e540f97c55f2 Mon Sep 17 00:00:00 2001 From: Wesley Ellis Date: Thu, 3 Aug 2017 11:58:10 -0400 Subject: [PATCH 4/7] don't escape and do camelize fieldNameSeen fields --- codegen/lib/graphql_java_gen/templates/APISchema.java.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb index ba5f611..10806f0 100644 --- a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb +++ b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb @@ -265,7 +265,7 @@ public class <%= schema_name %> { <% end %> <% type.optional_input_fields.each do |field| %> private <%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>; - private boolean <%= escape_reserved_word(field.name) %>Seen = false; + private boolean <%= field.camelize_name %>Seen = false; <% end %> <% unless type.required_input_fields.empty? %> From b4bff601c3b18fcef5e0996b983d29878e141e20 Mon Sep 17 00:00:00 2001 From: Wesley Ellis Date: Thu, 3 Aug 2017 14:52:01 -0400 Subject: [PATCH 5/7] clean up how annotations are generated, add tests --- Rakefile | 6 +++ codegen/lib/graphql_java_gen.rb | 11 +++-- .../templates/APISchema.java.erb | 10 ++-- .../com/shopify/graphql/support/Nullable.java | 46 +++++++++++++++++++ .../graphql/support/AnnotationTest.java | 28 +++++++++++ .../shopify/graphql/support/Generated.java | 22 +++++++-- 6 files changed, 111 insertions(+), 12 deletions(-) create mode 100644 support/src/main/java/com/shopify/graphql/support/Nullable.java create mode 100644 support/src/test/java/com/shopify/graphql/support/AnnotationTest.java diff --git a/Rakefile b/Rakefile index bdb054b..a9b8b28 100644 --- a/Rakefile +++ b/Rakefile @@ -25,6 +25,12 @@ task :generate do deserialize_expr: ->(expr) { "LocalDateTime.parse(jsonAsString(#{expr}, key))" }, imports: ['java.time.LocalDateTime'], ) + ], + custom_annotations: [ + GraphQLJavaGen::Annotation.new( + 'Nullable', + imports: ['com.shopify.graphql.support.Nullable'] + ) { |field| !field.type.non_null? }, ] ).save('support/src/test/java/com/shopify/graphql/support/Generated.java') diff --git a/codegen/lib/graphql_java_gen.rb b/codegen/lib/graphql_java_gen.rb index 59c9e23..328b855 100644 --- a/codegen/lib/graphql_java_gen.rb +++ b/codegen/lib/graphql_java_gen.rb @@ -253,10 +253,15 @@ def java_implements(type) "implements #{interfaces.to_a.join(', ')} " end - def java_annotations(field) - @annotations.map do |annotation| + def java_annotations(field, in_argument: false) + annotations = @annotations.map do |annotation| "@#{annotation.name}" if annotation.annotate?(field) - end.compact.join("\n") + end.compact + if in_argument + annotations.join(" ") + " " + else + annotations.join("\n") + end end def type_names_set diff --git a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb index 10806f0..01b040a 100644 --- a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb +++ b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb @@ -237,7 +237,7 @@ public class <%= schema_name %> { <% fields.each do |field| %> <%= java_doc(field) %> - <%= java_annotations(field) -%> + <%= java_annotations(field) %> public <%= java_output_type(field.type) %> get<%= field.classify_name %>() { return (<%= java_output_type(field.type) %>) get("<%= field.name %>"); } @@ -277,23 +277,23 @@ public class <%= schema_name %> { <% end %> <% type.required_input_fields.each do |field| %> - <%= java_annotations(field) -%> + <%= java_annotations(field) %> public <%= java_input_type(field.type) %> get<%= field.classify_name %>() { return <%= escape_reserved_word(field.camelize_name) %>; } - public <%= type.name %> set<%= field.classify_name %>(<%= java_annotations(field).gsub(/(.)$/, '\1 ') %><%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { + public <%= type.name %> set<%= field.classify_name %>(<%= java_annotations(field, in_argument: true) %><%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { this.<%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %>; return this; } <% end %> <% type.optional_input_fields.each do |field| %> - <%= java_annotations(field) -%> + <%= java_annotations(field) %> public <%= java_input_type(field.type) %> get<%= field.classify_name %>() { return <%= escape_reserved_word(field.camelize_name) %>; } - public <%= type.name %> set<%= field.classify_name %>(<%= java_annotations(field).gsub(/(.)$/, '\1 ') %><%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { + public <%= type.name %> set<%= field.classify_name %>(<%= java_annotations(field, in_argument: true) %><%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { this.<%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %>; this.<%= escape_reserved_word(field.name) %>Seen = true; return this; diff --git a/support/src/main/java/com/shopify/graphql/support/Nullable.java b/support/src/main/java/com/shopify/graphql/support/Nullable.java new file mode 100644 index 0000000..f1b7b04 --- /dev/null +++ b/support/src/main/java/com/shopify/graphql/support/Nullable.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.shopify.graphql.support; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Denotes that a parameter, field or method return value can be null. + *

+ * When decorating a method call parameter, this denotes that the parameter can + * legitimately be null and the method will gracefully deal with it. Typically + * used on optional parameters. + *

+ * When decorating a method, this denotes the method might legitimately return + * null. + *

+ * This is a marker annotation and it has no specific attributes. + */ +@Documented +@Retention(RUNTIME) +@Target({METHOD, PARAMETER, FIELD, ANNOTATION_TYPE, PACKAGE}) +public @interface Nullable { +} + diff --git a/support/src/test/java/com/shopify/graphql/support/AnnotationTest.java b/support/src/test/java/com/shopify/graphql/support/AnnotationTest.java new file mode 100644 index 0000000..1b77f6f --- /dev/null +++ b/support/src/test/java/com/shopify/graphql/support/AnnotationTest.java @@ -0,0 +1,28 @@ +package com.shopify.graphql.support; + +import org.junit.Test; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.shopify.graphql.support.Generated; + +public class AnnotationTest { + @Test + public void testAppliesAnnotation() throws Exception { + Class obj = Generated.class; + boolean foundNullable = false; + for (Class klass: obj.getDeclaredClasses()) { + for (Method method : klass.getDeclaredMethods()) { + if (method.isAnnotationPresent(Nullable.class)) { + foundNullable = true; + break; + } + } + } + assertTrue("Should have found a class with @Nullable annotation in Generated.java", foundNullable); + } +} diff --git a/support/src/test/java/com/shopify/graphql/support/Generated.java b/support/src/test/java/com/shopify/graphql/support/Generated.java index 3cce9dd..703f4b9 100644 --- a/support/src/test/java/com/shopify/graphql/support/Generated.java +++ b/support/src/test/java/com/shopify/graphql/support/Generated.java @@ -15,6 +15,8 @@ import com.shopify.graphql.support.ID; +import com.shopify.graphql.support.Nullable; + import java.time.LocalDateTime; import java.io.Serializable; @@ -216,6 +218,7 @@ public UnknownEntry setKey(String arg) { return this; } + @Nullable public LocalDateTime getTtl() { return (LocalDateTime) get("ttl"); } @@ -398,6 +401,7 @@ public IntegerEntry setKey(String arg) { return this; } + @Nullable public LocalDateTime getTtl() { return (LocalDateTime) get("ttl"); } @@ -954,6 +958,7 @@ public QueryRoot setEntries(List arg) { /** * Get an entry of any type with the given key */ + @Nullable public Entry getEntry() { return (Entry) get("entry"); } @@ -966,6 +971,7 @@ public QueryRoot setEntry(Entry arg) { /** * Get an entry of any type with the given key as a union */ + @Nullable public EntryUnion getEntryUnion() { return (EntryUnion) get("entry_union"); } @@ -978,6 +984,7 @@ public QueryRoot setEntryUnion(EntryUnion arg) { /** * Get a integer value with the given key */ + @Nullable public Integer getInteger() { return (Integer) get("integer"); } @@ -999,6 +1006,7 @@ public QueryRoot setKeys(List arg) { /** * Get a string value with the given key */ + @Nullable public String getString() { return (String) get("string"); } @@ -1008,6 +1016,7 @@ public QueryRoot setString(String arg) { return this; } + @Nullable public LocalDateTime getTtl() { return (LocalDateTime) get("ttl"); } @@ -1017,6 +1026,7 @@ public QueryRoot setTtl(LocalDateTime arg) { return this; } + @Nullable public KeyType getType() { return (KeyType) get("type"); } @@ -1026,6 +1036,7 @@ public QueryRoot setType(KeyType arg) { return this; } + @Nullable public String getVersion() { return (String) get("version"); } @@ -1081,7 +1092,7 @@ public String getKey() { return key; } - public SetIntegerInput setKey(String key) { + public SetIntegerInput setKey( String key) { this.key = key; return this; } @@ -1090,26 +1101,28 @@ public int getValue() { return value; } - public SetIntegerInput setValue(int value) { + public SetIntegerInput setValue( int value) { this.value = value; return this; } + @Nullable public LocalDateTime getTtl() { return ttl; } - public SetIntegerInput setTtl(LocalDateTime ttl) { + public SetIntegerInput setTtl(@Nullable LocalDateTime ttl) { this.ttl = ttl; this.ttlSeen = true; return this; } + @Nullable public Boolean getNegate() { return negate; } - public SetIntegerInput setNegate(Boolean negate) { + public SetIntegerInput setNegate(@Nullable Boolean negate) { this.negate = negate; this.negateSeen = true; return this; @@ -1239,6 +1252,7 @@ public StringEntry setKey(String arg) { return this; } + @Nullable public LocalDateTime getTtl() { return (LocalDateTime) get("ttl"); } From d0d88959d26f0dfc52dd5331d2f1508fc31ee95a Mon Sep 17 00:00:00 2001 From: Wesley Ellis Date: Tue, 8 Aug 2017 14:07:42 -0400 Subject: [PATCH 6/7] don't add extra space to argument annotations --- codegen/lib/graphql_java_gen.rb | 2 ++ .../src/test/java/com/shopify/graphql/support/Generated.java | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/codegen/lib/graphql_java_gen.rb b/codegen/lib/graphql_java_gen.rb index 328b855..b814aff 100644 --- a/codegen/lib/graphql_java_gen.rb +++ b/codegen/lib/graphql_java_gen.rb @@ -257,6 +257,8 @@ def java_annotations(field, in_argument: false) annotations = @annotations.map do |annotation| "@#{annotation.name}" if annotation.annotate?(field) end.compact + return "" unless annotations.any? + if in_argument annotations.join(" ") + " " else diff --git a/support/src/test/java/com/shopify/graphql/support/Generated.java b/support/src/test/java/com/shopify/graphql/support/Generated.java index 703f4b9..6a58bb3 100644 --- a/support/src/test/java/com/shopify/graphql/support/Generated.java +++ b/support/src/test/java/com/shopify/graphql/support/Generated.java @@ -1092,7 +1092,7 @@ public String getKey() { return key; } - public SetIntegerInput setKey( String key) { + public SetIntegerInput setKey(String key) { this.key = key; return this; } @@ -1101,7 +1101,7 @@ public int getValue() { return value; } - public SetIntegerInput setValue( int value) { + public SetIntegerInput setValue(int value) { this.value = value; return this; } From 3960bdd5e1146c0d522d6231ed0f1b4d7d70d153 Mon Sep 17 00:00:00 2001 From: Wesley Ellis Date: Tue, 8 Aug 2017 14:19:00 -0400 Subject: [PATCH 7/7] fix fieldNameSeen and add test to catch mistakes in future --- .../templates/APISchema.java.erb | 4 +-- codegen/test/support/schema.rb | 1 + .../shopify/graphql/support/Generated.java | 25 +++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb index 01b040a..5357f70 100644 --- a/codegen/lib/graphql_java_gen/templates/APISchema.java.erb +++ b/codegen/lib/graphql_java_gen/templates/APISchema.java.erb @@ -295,7 +295,7 @@ public class <%= schema_name %> { public <%= type.name %> set<%= field.classify_name %>(<%= java_annotations(field, in_argument: true) %><%= java_input_type(field.type) %> <%= escape_reserved_word(field.camelize_name) %>) { this.<%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %>; - this.<%= escape_reserved_word(field.name) %>Seen = true; + this.<%= field.camelize_name %>Seen = true; return this; } <% end %> @@ -310,7 +310,7 @@ public class <%= schema_name %> { <%= generate_build_input_code(escape_reserved_word(field.camelize_name), field.type) %> <% end %> <% type.optional_input_fields.each do |field| %> - if (this.<%= escape_reserved_word(field.name) %>Seen) { + if (this.<%= field.camelize_name %>Seen) { _queryBuilder.append(separator); separator = ","; _queryBuilder.append("<%= field.name %>:"); diff --git a/codegen/test/support/schema.rb b/codegen/test/support/schema.rb index 21d3e2c..2efd2c6 100644 --- a/codegen/test/support/schema.rb +++ b/codegen/test/support/schema.rb @@ -91,6 +91,7 @@ module Schema argument :value, !types.Int argument :ttl, TimeType argument :negate, types.Boolean, default_value: false + argument :api_client, types.String end MutationType = GraphQL::ObjectType.define do diff --git a/support/src/test/java/com/shopify/graphql/support/Generated.java b/support/src/test/java/com/shopify/graphql/support/Generated.java index 6a58bb3..3ae9cf7 100644 --- a/support/src/test/java/com/shopify/graphql/support/Generated.java +++ b/support/src/test/java/com/shopify/graphql/support/Generated.java @@ -1082,6 +1082,9 @@ public static class SetIntegerInput implements Serializable { private Boolean negate; private boolean negateSeen = false; + private String apiClient; + private boolean apiClientSeen = false; + public SetIntegerInput(String key, int value) { this.key = key; @@ -1128,6 +1131,17 @@ public SetIntegerInput setNegate(@Nullable Boolean negate) { return this; } + @Nullable + public String getApiClient() { + return apiClient; + } + + public SetIntegerInput setApiClient(@Nullable String apiClient) { + this.apiClient = apiClient; + this.apiClientSeen = true; + return this; + } + public void appendTo(StringBuilder _queryBuilder) { String separator = ""; _queryBuilder.append('{'); @@ -1164,6 +1178,17 @@ public void appendTo(StringBuilder _queryBuilder) { } } + if (this.apiClientSeen) { + _queryBuilder.append(separator); + separator = ","; + _queryBuilder.append("api_client:"); + if (apiClient != null) { + Query.appendQuotedString(_queryBuilder, apiClient.toString()); + } else { + _queryBuilder.append("null"); + } + } + _queryBuilder.append('}'); } }