|
6 | 6 | import graphql.analysis.QueryVisitorInlineFragmentEnvironment;
|
7 | 7 | import graphql.analysis.QueryVisitorStub;
|
8 | 8 | import graphql.language.Argument;
|
| 9 | +import graphql.language.AstTransformer; |
9 | 10 | import graphql.language.Document;
|
10 | 11 | import graphql.language.Field;
|
11 | 12 | import graphql.language.FragmentDefinition;
|
12 | 13 | import graphql.language.FragmentSpread;
|
13 | 14 | import graphql.language.InlineFragment;
|
14 | 15 | import graphql.language.Node;
|
| 16 | +import graphql.language.NodeVisitorStub; |
15 | 17 | import graphql.language.OperationDefinition;
|
16 | 18 | import graphql.language.Value;
|
17 | 19 | import graphql.language.VariableReference;
|
18 | 20 | import graphql.schema.GraphQLObjectType;
|
19 | 21 | import graphql.schema.GraphQLSchema;
|
| 22 | +import graphql.util.TraversalControl; |
| 23 | +import graphql.util.TraverserContext; |
| 24 | +import lombok.Getter; |
| 25 | + |
20 | 26 | import java.util.ArrayList;
|
| 27 | +import java.util.Collection; |
21 | 28 | import java.util.List;
|
22 | 29 | import java.util.Map;
|
23 | 30 | import java.util.Set;
|
24 | 31 | import java.util.stream.Collectors;
|
25 | 32 | import java.util.stream.Stream;
|
26 |
| -import lombok.Getter; |
27 | 33 |
|
28 | 34 | /**
|
29 | 35 | * This class provides assistance in extracting all VariableReference names used in GraphQL nodes.
|
30 | 36 | */
|
31 | 37 | public class VariableDefinitionFilter {
|
32 | 38 |
|
| 39 | + private static AstTransformer astTransformer = new AstTransformer(); |
| 40 | + |
33 | 41 | /**
|
34 | 42 | * Traverses a GraphQL Node and returns all VariableReference names used in all nodes in the graph.
|
35 | 43 | *
|
@@ -67,8 +75,20 @@ public Set<String> getVariableReferencesFromNode(GraphQLSchema graphQLSchema, Gr
|
67 | 75 |
|
68 | 76 | Set<VariableReference> additionalReferences = operationDirectiveVariableReferences(operationDefinitions);
|
69 | 77 |
|
70 |
| - return Stream.concat(variableReferenceVisitor.getVariableReferences().stream(), additionalReferences.stream()) |
71 |
| - .map(VariableReference::getName).collect(Collectors.toSet()); |
| 78 | + Stream<VariableReference> variableReferenceStream; |
| 79 | + if((variableReferenceVisitor.getVariableReferences().size() + additionalReferences.size()) != variables.size()) { |
| 80 | + NodeTraverser nodeTraverser = new NodeTraverser(); |
| 81 | + astTransformer.transform(rootNode, nodeTraverser); |
| 82 | + |
| 83 | + variableReferenceStream = Stream.of(variableReferenceVisitor.getVariableReferences(), |
| 84 | + additionalReferences, |
| 85 | + nodeTraverser.getVariableReferenceExtractor().getVariableReferences()) |
| 86 | + .flatMap(Collection::stream); |
| 87 | + } else { |
| 88 | + variableReferenceStream = Stream.concat(variableReferenceVisitor.getVariableReferences().stream(), additionalReferences.stream()); |
| 89 | + } |
| 90 | + return variableReferenceStream.map(VariableReference::getName).collect(Collectors.toSet()); |
| 91 | + |
72 | 92 | }
|
73 | 93 |
|
74 | 94 | private Set<VariableReference> operationDirectiveVariableReferences(List<OperationDefinition> operationDefinitions) {
|
@@ -163,4 +183,19 @@ private void captureVariableReferences(Stream<Argument> arguments) {
|
163 | 183 | variableReferenceExtractor.captureVariableReferences(values);
|
164 | 184 | }
|
165 | 185 | }
|
| 186 | + |
| 187 | + static class NodeTraverser extends NodeVisitorStub { |
| 188 | + |
| 189 | + @Getter |
| 190 | + private final VariableReferenceExtractor variableReferenceExtractor = new VariableReferenceExtractor(); |
| 191 | + |
| 192 | + public TraversalControl visitArgument(Argument node, TraverserContext<Node> context) { |
| 193 | + return this.visitNode(node, context); |
| 194 | + } |
| 195 | + |
| 196 | + public TraversalControl visitVariableReference(VariableReference node, TraverserContext<Node> context) { |
| 197 | + variableReferenceExtractor.captureVariableReference(node); |
| 198 | + return this.visitValue(node, context); |
| 199 | + } |
| 200 | + } |
166 | 201 | }
|
0 commit comments