Skip to content

Commit d2ca93c

Browse files
authored
Fix AstTransformer extension being converted to base type when changing child node (#2056) (#2066)
(cherry picked from commit 3998b0d)
1 parent c27a9cd commit d2ca93c

10 files changed

+160
-2
lines changed

src/main/java/graphql/analysis/QueryTraverser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
* visitField calls.
3636
*/
3737
@PublicApi
38-
public class QueryTraverser {
38+
public class QueryTraverser {
3939

4040
private final Collection<? extends Node> roots;
4141
private final GraphQLSchema schema;

src/main/java/graphql/language/AstPrinter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ private AstPrinter(boolean compactMode) {
6565
printers.put(ScalarTypeDefinition.class, scalarTypeDefinition());
6666
printers.put(ScalarTypeExtensionDefinition.class, scalarTypeExtensionDefinition());
6767
printers.put(SchemaDefinition.class, schemaDefinition());
68+
printers.put(SchemaExtensionDefinition.class, schemaExtensionDefinition());
6869
printers.put(SelectionSet.class, selectionSet());
6970
printers.put(StringValue.class, value());
7071
printers.put(TypeName.class, type());
@@ -384,6 +385,10 @@ private NodePrinter<InputObjectTypeExtensionDefinition> inputObjectTypeExtension
384385
return (out, node) -> out.printf("extend %s", node(node, InputObjectTypeDefinition.class));
385386
}
386387

388+
private NodePrinter<SchemaExtensionDefinition> schemaExtensionDefinition() {
389+
return (out, node) -> out.printf("extend %s", node(node, SchemaDefinition.class));
390+
}
391+
387392
private NodePrinter<UnionTypeDefinition> unionTypeDefinition() {
388393
String barSep = compactMode ? "|" : " | ";
389394
String equals = compactMode ? "=" : "= ";

src/main/java/graphql/language/EnumTypeExtensionDefinition.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ public static Builder newEnumTypeExtensionDefinition() {
5151
return new Builder();
5252
}
5353

54+
@Override
55+
public EnumTypeExtensionDefinition withNewChildren(NodeChildrenContainer newChildren) {
56+
return transformExtension(builder -> builder
57+
.enumValueDefinitions(newChildren.getChildren(CHILD_ENUM_VALUE_DEFINITIONS))
58+
.directives(newChildren.getChildren(CHILD_DIRECTIVES))
59+
);
60+
}
61+
5462
public EnumTypeExtensionDefinition transformExtension(Consumer<Builder> builderConsumer) {
5563
Builder builder = new Builder(this);
5664
builderConsumer.accept(builder);

src/main/java/graphql/language/InputObjectTypeExtensionDefinition.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ public static Builder newInputObjectTypeExtensionDefinition() {
5151
return new Builder();
5252
}
5353

54+
@Override
55+
public InputObjectTypeExtensionDefinition withNewChildren(NodeChildrenContainer newChildren) {
56+
return transformExtension(builder -> builder
57+
.directives(newChildren.getChildren(CHILD_DIRECTIVES))
58+
.inputValueDefinitions(newChildren.getChildren(CHILD_INPUT_VALUES_DEFINITIONS))
59+
);
60+
}
5461

5562
public InputObjectTypeExtensionDefinition transformExtension(Consumer<Builder> builderConsumer) {
5663
Builder builder = new Builder(this);

src/main/java/graphql/language/InterfaceTypeExtensionDefinition.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ public static Builder newInterfaceTypeExtensionDefinition() {
5252
return new Builder();
5353
}
5454

55+
@Override
56+
public InterfaceTypeExtensionDefinition withNewChildren(NodeChildrenContainer newChildren) {
57+
return transformExtension(builder -> builder
58+
.definitions(newChildren.getChildren(CHILD_DEFINITIONS))
59+
.directives(newChildren.getChildren(CHILD_DIRECTIVES))
60+
);
61+
}
62+
5563
public InterfaceTypeExtensionDefinition transformExtension(Consumer<Builder> builderConsumer) {
5664
Builder builder = new Builder(this);
5765
builderConsumer.accept(builder);

src/main/java/graphql/language/ObjectTypeExtensionDefinition.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ public ObjectTypeExtensionDefinition deepCopy() {
5252
getAdditionalData());
5353
}
5454

55+
@Override
56+
public ObjectTypeExtensionDefinition withNewChildren(NodeChildrenContainer newChildren) {
57+
return transformExtension(builder -> builder.implementz(newChildren.getChildren(CHILD_IMPLEMENTZ))
58+
.directives(newChildren.getChildren(CHILD_DIRECTIVES))
59+
.fieldDefinitions(newChildren.getChildren(CHILD_FIELD_DEFINITIONS)));
60+
}
5561

5662
@Override
5763
public String toString() {

src/main/java/graphql/language/ScalarTypeExtensionDefinition.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ public static Builder newScalarTypeExtensionDefinition() {
4242
return new Builder();
4343
}
4444

45+
@Override
46+
public ScalarTypeExtensionDefinition withNewChildren(NodeChildrenContainer newChildren) {
47+
return transformExtension(builder -> builder
48+
.directives(newChildren.getChildren(CHILD_DIRECTIVES))
49+
);
50+
}
51+
4552
public ScalarTypeExtensionDefinition transformExtension(Consumer<Builder> builderConsumer) {
4653
Builder builder = new Builder(this);
4754
builderConsumer.accept(builder);

src/main/java/graphql/language/UnionTypeExtensionDefinition.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ public static Builder newUnionTypeExtensionDefinition() {
5757
return new Builder();
5858
}
5959

60+
@Override
61+
public UnionTypeExtensionDefinition withNewChildren(NodeChildrenContainer newChildren) {
62+
return transformExtension(builder -> builder
63+
.directives(newChildren.getChildren(CHILD_DIRECTIVES))
64+
.memberTypes(newChildren.getChildren(CHILD_MEMBER_TYPES))
65+
);
66+
}
67+
6068
public UnionTypeExtensionDefinition transformExtension(Consumer<Builder> builderConsumer) {
6169
Builder builder = new Builder(this);
6270
builderConsumer.accept(builder);

src/test/groovy/graphql/language/AstPrinterTest.groovy

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,10 @@ type Query {
466466

467467
def "print type extensions"() {
468468
def query = '''
469+
extend schema {
470+
query: Query
471+
}
472+
469473
extend type Object @directive {
470474
objectField : String
471475
}
@@ -491,7 +495,11 @@ type Query {
491495
String output = printAst(document)
492496

493497
expect:
494-
output == '''extend type Object @directive {
498+
output == '''extend schema {
499+
query: Query
500+
}
501+
502+
extend type Object @directive {
495503
objectField: String
496504
}
497505

src/test/groovy/graphql/language/AstTransformerTest.groovy

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import graphql.util.TraversalControl
55
import graphql.util.TraverserContext
66
import spock.lang.Specification
77

8+
import static graphql.language.AstPrinter.printAst
89
import static graphql.language.AstPrinter.printAstCompact
910
import static graphql.util.TreeTransformerUtil.changeNode
1011
import static graphql.util.TreeTransformerUtil.deleteNode
@@ -795,5 +796,105 @@ class AstTransformerTest extends Specification {
795796

796797
}
797798

799+
def "regression: changing a property of an extension should not change the extension to a base definition"() {
800+
def document = TestUtil.toDocument("""
801+
extend schema { query: Query }
802+
extend type MyObjectType { login: String }
803+
extend input MyInputObjectType { login: String }
804+
extend interface MyInterface { login: String }
805+
extend enum MyEnum { MONDAY }
806+
extend scalar MyScalar @myDirective
807+
extend union MyUnion = MyObjectType
808+
""")
798809

810+
AstTransformer astTransformer = new AstTransformer()
811+
812+
def visitor = new NodeVisitorStub() {
813+
814+
@Override
815+
TraversalControl visitFieldDefinition(FieldDefinition fieldDefinition, TraverserContext<Node> context) {
816+
if (fieldDefinition.name == "login") {
817+
// change name
818+
FieldDefinition signin = fieldDefinition.transform({ builder -> builder.name("signin") })
819+
return changeNode(context, signin)
820+
}
821+
return super.visitFieldDefinition(fieldDefinition, context)
822+
}
823+
824+
@Override
825+
TraversalControl visitInputValueDefinition(InputValueDefinition fieldDefinition, TraverserContext<Node> context) {
826+
if (fieldDefinition.name == "login") {
827+
// change name
828+
InputValueDefinition signin = fieldDefinition.transform({ builder -> builder.name("signin") })
829+
return changeNode(context, signin)
830+
}
831+
return super.visitInputValueDefinition(fieldDefinition, context)
832+
}
833+
834+
@Override
835+
TraversalControl visitEnumValueDefinition(EnumValueDefinition node, TraverserContext<Node> context) {
836+
if (node.name == "MONDAY") {
837+
// change name
838+
return changeNode(context, node.transform({ builder -> builder.name("TUESDAY") }))
839+
}
840+
return super.visitEnumValueDefinition(node, context)
841+
}
842+
843+
@Override
844+
TraversalControl visitSchemaDefinition(SchemaDefinition node, TraverserContext<Node> context) {
845+
if (node instanceof SchemaExtensionDefinition) {
846+
return changeNode(context, node.transformExtension({
847+
it.operationTypeDefinitions([OperationTypeDefinition.newOperationTypeDefinition()
848+
.name("myQuery")
849+
.typeName(TypeName.newTypeName("MyQuery").build())
850+
.build()])
851+
}))
852+
}
853+
return super.visitSchemaDefinition(node, context)
854+
}
855+
}
856+
857+
when:
858+
def newDocument = astTransformer.transform(document, visitor)
859+
860+
then:
861+
newDocument instanceof Document
862+
863+
and:
864+
def transformedDoc = newDocument as Document
865+
transformedDoc.definitions.find {it instanceof NamedNode && it.name == "MyObjectType"} instanceof ObjectTypeExtensionDefinition
866+
transformedDoc.definitions.find {it instanceof NamedNode && it.name == "MyInputObjectType"} instanceof InputObjectTypeExtensionDefinition
867+
transformedDoc.definitions.find {it instanceof NamedNode && it.name == "MyInterface"} instanceof InterfaceTypeExtensionDefinition
868+
transformedDoc.definitions.find {it instanceof NamedNode && it.name == "MyEnum"} instanceof EnumTypeExtensionDefinition
869+
transformedDoc.definitions.find {it instanceof NamedNode && it.name == "MyScalar"} instanceof ScalarTypeExtensionDefinition
870+
transformedDoc.definitions.find {it instanceof NamedNode && it.name == "MyUnion"} instanceof UnionTypeExtensionDefinition
871+
transformedDoc.definitions.find {it instanceof SchemaDefinition } instanceof SchemaExtensionDefinition
872+
873+
and:
874+
printAst(newDocument).trim() == """
875+
|extend schema {
876+
| myQuery: MyQuery
877+
|}
878+
|
879+
|extend type MyObjectType {
880+
| signin: String
881+
|}
882+
|
883+
|extend input MyInputObjectType {
884+
| signin: String
885+
|}
886+
|
887+
|extend interface MyInterface {
888+
| signin: String
889+
|}
890+
|
891+
|extend enum MyEnum {
892+
| TUESDAY
893+
|}
894+
|
895+
|extend scalar MyScalar @myDirective
896+
|
897+
|extend union MyUnion = MyObjectType
898+
""".trim().stripMargin()
899+
}
799900
}

0 commit comments

Comments
 (0)