Skip to content

Commit 71e5161

Browse files
authored
Fix issue with stack overflow when parsing circle referenced input types (#1643)
Closes #1639
1 parent 86f05cd commit 71e5161

File tree

15 files changed

+524
-15
lines changed

15 files changed

+524
-15
lines changed

.idea/codeStyles/Project.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/parser/GraphQLDocumentParser.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ class GraphQLDocumentParser(val schema: Schema, private val packageNameProvider:
584584
}
585585
}
586586

587-
private fun Set<String>.usedSchemaTypes(): Set<Schema.Type> {
587+
private fun Set<String>.usedSchemaTypes(exclude: Set<String> = emptySet()): Set<Schema.Type> {
588588
if (isEmpty()) {
589589
return emptySet()
590590
}
@@ -596,9 +596,9 @@ class GraphQLDocumentParser(val schema: Schema, private val packageNameProvider:
596596

597597
val inputObjectUsedTypes = usedSchemaTypes
598598
.mapNotNull { type -> type as? Schema.Type.InputObject }
599-
.flatMap { inputObject -> inputObject.usedTypes(exclude = this) }
599+
.flatMap { inputObject -> inputObject.usedTypes(exclude = this + exclude) }
600600
.toSet()
601-
.usedSchemaTypes()
601+
.usedSchemaTypes(this + exclude)
602602

603603
return usedSchemaTypes + inputObjectUsedTypes
604604
}

apollo-compiler/src/test/graphql/com/example/input_object_type/type/ColorInput.java

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,19 @@ public final class ColorInput implements InputType {
2626

2727
private final Input<Episode> enumWithDefaultValue;
2828

29+
private final Input<ReviewRefInput> reviewRefInput;
30+
2931
private transient volatile int $hashCode;
3032

3133
private transient volatile boolean $hashCodeMemoized;
3234

33-
ColorInput(int red, Input<Double> green, double blue, Input<Episode> enumWithDefaultValue) {
35+
ColorInput(int red, Input<Double> green, double blue, Input<Episode> enumWithDefaultValue,
36+
Input<ReviewRefInput> reviewRefInput) {
3437
this.red = red;
3538
this.green = green;
3639
this.blue = blue;
3740
this.enumWithDefaultValue = enumWithDefaultValue;
41+
this.reviewRefInput = reviewRefInput;
3842
}
3943

4044
/**
@@ -65,6 +69,13 @@ public double blue() {
6569
return this.enumWithDefaultValue.value;
6670
}
6771

72+
/**
73+
* Circle ref to review input
74+
*/
75+
public @Nullable ReviewRefInput reviewRefInput() {
76+
return this.reviewRefInput.value;
77+
}
78+
6879
public static Builder builder() {
6980
return new Builder();
7081
}
@@ -82,6 +93,9 @@ public void marshal(InputFieldWriter writer) throws IOException {
8293
if (enumWithDefaultValue.defined) {
8394
writer.writeString("enumWithDefaultValue", enumWithDefaultValue.value != null ? enumWithDefaultValue.value.rawValue() : null);
8495
}
96+
if (reviewRefInput.defined) {
97+
writer.writeObject("reviewRefInput", reviewRefInput.value != null ? reviewRefInput.value.marshaller() : null);
98+
}
8599
}
86100
};
87101
}
@@ -98,6 +112,8 @@ public int hashCode() {
98112
h ^= Double.valueOf(blue).hashCode();
99113
h *= 1000003;
100114
h ^= enumWithDefaultValue.hashCode();
115+
h *= 1000003;
116+
h ^= reviewRefInput.hashCode();
101117
$hashCode = h;
102118
$hashCodeMemoized = true;
103119
}
@@ -114,7 +130,8 @@ public boolean equals(Object o) {
114130
return this.red == that.red
115131
&& this.green.equals(that.green)
116132
&& Double.doubleToLongBits(this.blue) == Double.doubleToLongBits(that.blue)
117-
&& this.enumWithDefaultValue.equals(that.enumWithDefaultValue);
133+
&& this.enumWithDefaultValue.equals(that.enumWithDefaultValue)
134+
&& this.reviewRefInput.equals(that.reviewRefInput);
118135
}
119136
return false;
120137
}
@@ -128,6 +145,8 @@ public static final class Builder {
128145

129146
private Input<Episode> enumWithDefaultValue = Input.fromNullable(Episode.safeValueOf("new"));
130147

148+
private Input<ReviewRefInput> reviewRefInput = Input.absent();
149+
131150
Builder() {
132151
}
133152

@@ -163,6 +182,14 @@ public Builder enumWithDefaultValue(@Nullable Episode enumWithDefaultValue) {
163182
return this;
164183
}
165184

185+
/**
186+
* Circle ref to review input
187+
*/
188+
public Builder reviewRefInput(@Nullable ReviewRefInput reviewRefInput) {
189+
this.reviewRefInput = Input.fromNullable(reviewRefInput);
190+
return this;
191+
}
192+
166193
/**
167194
* Green color
168195
*/
@@ -179,8 +206,16 @@ public Builder enumWithDefaultValueInput(@NotNull Input<Episode> enumWithDefault
179206
return this;
180207
}
181208

209+
/**
210+
* Circle ref to review input
211+
*/
212+
public Builder reviewRefInputInput(@NotNull Input<ReviewRefInput> reviewRefInput) {
213+
this.reviewRefInput = Utils.checkNotNull(reviewRefInput, "reviewRefInput == null");
214+
return this;
215+
}
216+
182217
public ColorInput build() {
183-
return new ColorInput(red, green, blue, enumWithDefaultValue);
218+
return new ColorInput(red, green, blue, enumWithDefaultValue, reviewRefInput);
184219
}
185220
}
186221
}

apollo-compiler/src/test/graphql/com/example/input_object_type/type/ColorInput.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,19 @@ data class ColorInput(
3333
/**
3434
* for test purpose only
3535
*/
36-
val enumWithDefaultValue: Input<Episode> = Input.optional(Episode.safeValueOf("new"))
36+
val enumWithDefaultValue: Input<Episode> = Input.optional(Episode.safeValueOf("new")),
37+
/**
38+
* Circle ref to review input
39+
*/
40+
val reviewRefInput: Input<ReviewRefInput> = Input.optional(null)
3741
) : InputType {
3842
override fun marshaller(): InputFieldMarshaller = InputFieldMarshaller { writer ->
3943
writer.writeInt("red", red)
4044
if (green.defined) writer.writeDouble("green", green.value)
4145
writer.writeDouble("blue", blue)
4246
if (enumWithDefaultValue.defined) writer.writeString("enumWithDefaultValue",
4347
enumWithDefaultValue.value?.rawValue)
48+
if (reviewRefInput.defined) writer.writeObject("reviewRefInput",
49+
reviewRefInput.value?.marshaller())
4450
}
4551
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// AUTO-GENERATED FILE. DO NOT MODIFY.
2+
//
3+
// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found.
4+
// It should not be modified by hand.
5+
//
6+
package com.example.input_object_type.type;
7+
8+
import com.apollographql.apollo.api.Input;
9+
import com.apollographql.apollo.api.InputFieldMarshaller;
10+
import com.apollographql.apollo.api.InputFieldWriter;
11+
import com.apollographql.apollo.api.InputType;
12+
import com.apollographql.apollo.api.internal.Utils;
13+
import java.io.IOException;
14+
import java.lang.Object;
15+
import java.lang.Override;
16+
import org.jetbrains.annotations.NotNull;
17+
import org.jetbrains.annotations.Nullable;
18+
19+
public final class ReviewRefInput implements InputType {
20+
private final Input<ReviewInput> reviewInput;
21+
22+
private transient volatile int $hashCode;
23+
24+
private transient volatile boolean $hashCodeMemoized;
25+
26+
ReviewRefInput(Input<ReviewInput> reviewInput) {
27+
this.reviewInput = reviewInput;
28+
}
29+
30+
public @Nullable ReviewInput reviewInput() {
31+
return this.reviewInput.value;
32+
}
33+
34+
public static Builder builder() {
35+
return new Builder();
36+
}
37+
38+
@Override
39+
public InputFieldMarshaller marshaller() {
40+
return new InputFieldMarshaller() {
41+
@Override
42+
public void marshal(InputFieldWriter writer) throws IOException {
43+
if (reviewInput.defined) {
44+
writer.writeObject("reviewInput", reviewInput.value != null ? reviewInput.value.marshaller() : null);
45+
}
46+
}
47+
};
48+
}
49+
50+
@Override
51+
public int hashCode() {
52+
if (!$hashCodeMemoized) {
53+
int h = 1;
54+
h *= 1000003;
55+
h ^= reviewInput.hashCode();
56+
$hashCode = h;
57+
$hashCodeMemoized = true;
58+
}
59+
return $hashCode;
60+
}
61+
62+
@Override
63+
public boolean equals(Object o) {
64+
if (o == this) {
65+
return true;
66+
}
67+
if (o instanceof ReviewRefInput) {
68+
ReviewRefInput that = (ReviewRefInput) o;
69+
return this.reviewInput.equals(that.reviewInput);
70+
}
71+
return false;
72+
}
73+
74+
public static final class Builder {
75+
private Input<ReviewInput> reviewInput = Input.absent();
76+
77+
Builder() {
78+
}
79+
80+
public Builder reviewInput(@Nullable ReviewInput reviewInput) {
81+
this.reviewInput = Input.fromNullable(reviewInput);
82+
return this;
83+
}
84+
85+
public Builder reviewInputInput(@NotNull Input<ReviewInput> reviewInput) {
86+
this.reviewInput = Utils.checkNotNull(reviewInput, "reviewInput == null");
87+
return this;
88+
}
89+
90+
public ReviewRefInput build() {
91+
return new ReviewRefInput(reviewInput);
92+
}
93+
}
94+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// AUTO-GENERATED FILE. DO NOT MODIFY.
2+
//
3+
// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found.
4+
// It should not be modified by hand.
5+
//
6+
package com.example.input_object_type.type
7+
8+
import com.apollographql.apollo.api.Input
9+
import com.apollographql.apollo.api.InputFieldMarshaller
10+
import com.apollographql.apollo.api.InputType
11+
import kotlin.Suppress
12+
13+
/**
14+
* Circle ref to review input
15+
*/
16+
@Suppress("NAME_SHADOWING", "UNUSED_ANONYMOUS_PARAMETER", "LocalVariableName",
17+
"RemoveExplicitTypeArguments", "NestedLambdaShadowedImplicitParameter")
18+
data class ReviewRefInput(
19+
val reviewInput: Input<ReviewInput> = Input.optional(null)
20+
) : InputType {
21+
override fun marshaller(): InputFieldMarshaller = InputFieldMarshaller { writer ->
22+
if (reviewInput.defined) writer.writeObject("reviewInput", reviewInput.value?.marshaller())
23+
}
24+
}

apollo-compiler/src/test/graphql/com/example/mutation_create_review/type/ColorInput.java

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,19 @@ public final class ColorInput implements InputType {
2626

2727
private final Input<Episode> enumWithDefaultValue;
2828

29+
private final Input<ReviewRefInput> reviewRefInput;
30+
2931
private transient volatile int $hashCode;
3032

3133
private transient volatile boolean $hashCodeMemoized;
3234

33-
ColorInput(int red, Input<Double> green, double blue, Input<Episode> enumWithDefaultValue) {
35+
ColorInput(int red, Input<Double> green, double blue, Input<Episode> enumWithDefaultValue,
36+
Input<ReviewRefInput> reviewRefInput) {
3437
this.red = red;
3538
this.green = green;
3639
this.blue = blue;
3740
this.enumWithDefaultValue = enumWithDefaultValue;
41+
this.reviewRefInput = reviewRefInput;
3842
}
3943

4044
/**
@@ -65,6 +69,13 @@ public double blue() {
6569
return this.enumWithDefaultValue.value;
6670
}
6771

72+
/**
73+
* Circle ref to review input
74+
*/
75+
public @Nullable ReviewRefInput reviewRefInput() {
76+
return this.reviewRefInput.value;
77+
}
78+
6879
public static Builder builder() {
6980
return new Builder();
7081
}
@@ -82,6 +93,9 @@ public void marshal(InputFieldWriter writer) throws IOException {
8293
if (enumWithDefaultValue.defined) {
8394
writer.writeString("enumWithDefaultValue", enumWithDefaultValue.value != null ? enumWithDefaultValue.value.rawValue() : null);
8495
}
96+
if (reviewRefInput.defined) {
97+
writer.writeObject("reviewRefInput", reviewRefInput.value != null ? reviewRefInput.value.marshaller() : null);
98+
}
8599
}
86100
};
87101
}
@@ -98,6 +112,8 @@ public int hashCode() {
98112
h ^= Double.valueOf(blue).hashCode();
99113
h *= 1000003;
100114
h ^= enumWithDefaultValue.hashCode();
115+
h *= 1000003;
116+
h ^= reviewRefInput.hashCode();
101117
$hashCode = h;
102118
$hashCodeMemoized = true;
103119
}
@@ -114,7 +130,8 @@ public boolean equals(Object o) {
114130
return this.red == that.red
115131
&& this.green.equals(that.green)
116132
&& Double.doubleToLongBits(this.blue) == Double.doubleToLongBits(that.blue)
117-
&& this.enumWithDefaultValue.equals(that.enumWithDefaultValue);
133+
&& this.enumWithDefaultValue.equals(that.enumWithDefaultValue)
134+
&& this.reviewRefInput.equals(that.reviewRefInput);
118135
}
119136
return false;
120137
}
@@ -128,6 +145,8 @@ public static final class Builder {
128145

129146
private Input<Episode> enumWithDefaultValue = Input.fromNullable(Episode.safeValueOf("new"));
130147

148+
private Input<ReviewRefInput> reviewRefInput = Input.absent();
149+
131150
Builder() {
132151
}
133152

@@ -163,6 +182,14 @@ public Builder enumWithDefaultValue(@Nullable Episode enumWithDefaultValue) {
163182
return this;
164183
}
165184

185+
/**
186+
* Circle ref to review input
187+
*/
188+
public Builder reviewRefInput(@Nullable ReviewRefInput reviewRefInput) {
189+
this.reviewRefInput = Input.fromNullable(reviewRefInput);
190+
return this;
191+
}
192+
166193
/**
167194
* Green color
168195
*/
@@ -179,8 +206,16 @@ public Builder enumWithDefaultValueInput(@NotNull Input<Episode> enumWithDefault
179206
return this;
180207
}
181208

209+
/**
210+
* Circle ref to review input
211+
*/
212+
public Builder reviewRefInputInput(@NotNull Input<ReviewRefInput> reviewRefInput) {
213+
this.reviewRefInput = Utils.checkNotNull(reviewRefInput, "reviewRefInput == null");
214+
return this;
215+
}
216+
182217
public ColorInput build() {
183-
return new ColorInput(red, green, blue, enumWithDefaultValue);
218+
return new ColorInput(red, green, blue, enumWithDefaultValue, reviewRefInput);
184219
}
185220
}
186221
}

0 commit comments

Comments
 (0)