Skip to content

Commit a25f455

Browse files
authored
Move coordinate factory (#715)
* Move coordinate factory to Nadel * Refactor input * Fix applied directive support * Add tests * Add tests * Move filterNot up
1 parent 17d31be commit a25f455

9 files changed

Lines changed: 1513 additions & 35 deletions

File tree

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package graphql.nadel.definition.coordinates
2+
3+
import graphql.nadel.engine.blueprint.NadelSchemaTraverser
4+
import graphql.nadel.engine.blueprint.NadelSchemaTraverserElement
5+
import graphql.nadel.engine.blueprint.NadelSchemaTraverserVisitor
6+
import graphql.schema.GraphQLDirective
7+
import graphql.schema.GraphQLNamedType
8+
import graphql.schema.GraphQLSchema
9+
import graphql.schema.idl.DirectiveInfo
10+
import graphql.schema.idl.ScalarInfo
11+
12+
class NadelSchemaMemberCoordinatesFactory {
13+
fun create(
14+
schema: GraphQLSchema,
15+
): Set<NadelSchemaMemberCoordinates> {
16+
val roots = buildList {
17+
fun addGraphQLType(type: GraphQLNamedType?) {
18+
if (type != null) {
19+
add(NadelSchemaTraverserElement.from(type))
20+
}
21+
}
22+
23+
fun addGraphQLDirective(directive: GraphQLDirective?) {
24+
if (directive != null) {
25+
add(NadelSchemaTraverserElement.from(directive))
26+
}
27+
}
28+
29+
addGraphQLType(schema.queryType)
30+
addGraphQLType(schema.mutationType)
31+
addGraphQLType(schema.subscriptionType)
32+
33+
schema.additionalTypes.forEach { type ->
34+
if (type is GraphQLNamedType) {
35+
addGraphQLType(type)
36+
}
37+
}
38+
schema.directives.forEach { directive ->
39+
addGraphQLDirective(directive)
40+
}
41+
}
42+
43+
return createImpl(roots)
44+
}
45+
46+
fun create(
47+
roots: List<GraphQLNamedType>,
48+
): Set<NadelSchemaMemberCoordinates> {
49+
return createImpl(
50+
roots = roots.map {
51+
NadelSchemaTraverserElement.from(it)
52+
},
53+
)
54+
}
55+
56+
private fun createImpl(
57+
roots: List<NadelSchemaTraverserElement>,
58+
): Set<NadelSchemaMemberCoordinates> {
59+
val coordinates = mutableSetOf<NadelSchemaMemberCoordinates>()
60+
61+
NadelSchemaTraverser()
62+
.traverse(
63+
roots,
64+
object : NadelSchemaTraverserVisitor {
65+
override fun visitGraphQLArgument(
66+
element: NadelSchemaTraverserElement.Argument,
67+
): Boolean {
68+
coordinates.add(element.coordinates())
69+
return true
70+
}
71+
72+
override fun visitGraphQLUnionType(
73+
element: NadelSchemaTraverserElement.UnionType,
74+
): Boolean {
75+
coordinates.add(element.coordinates())
76+
return true
77+
}
78+
79+
override fun visitGraphQLUnionMemberType(
80+
element: NadelSchemaTraverserElement.UnionMemberType,
81+
): Boolean {
82+
coordinates.add(element.coordinates())
83+
return true
84+
}
85+
86+
override fun visitGraphQLInterfaceType(
87+
element: NadelSchemaTraverserElement.InterfaceType,
88+
): Boolean {
89+
coordinates.add(element.coordinates())
90+
return true
91+
}
92+
93+
override fun visitGraphQLEnumType(
94+
element: NadelSchemaTraverserElement.EnumType,
95+
): Boolean {
96+
coordinates.add(element.coordinates())
97+
return true
98+
}
99+
100+
override fun visitGraphQLEnumValueDefinition(
101+
element: NadelSchemaTraverserElement.EnumValueDefinition,
102+
): Boolean {
103+
coordinates.add(element.coordinates())
104+
return true
105+
}
106+
107+
override fun visitGraphQLFieldDefinition(
108+
element: NadelSchemaTraverserElement.FieldDefinition,
109+
): Boolean {
110+
coordinates.add(element.coordinates())
111+
return true
112+
}
113+
114+
override fun visitGraphQLInputObjectField(
115+
element: NadelSchemaTraverserElement.InputObjectField,
116+
): Boolean {
117+
coordinates.add(element.coordinates())
118+
return true
119+
}
120+
121+
override fun visitGraphQLInputObjectType(
122+
element: NadelSchemaTraverserElement.InputObjectType,
123+
): Boolean {
124+
coordinates.add(element.coordinates())
125+
return true
126+
}
127+
128+
override fun visitGraphQLObjectType(
129+
element: NadelSchemaTraverserElement.ObjectType,
130+
): Boolean {
131+
coordinates.add(element.coordinates())
132+
return true
133+
}
134+
135+
override fun visitGraphQLScalarType(
136+
element: NadelSchemaTraverserElement.ScalarType,
137+
): Boolean {
138+
// Ignore built in scalars
139+
if (ScalarInfo.isGraphqlSpecifiedScalar(element.node.name)) {
140+
return false
141+
}
142+
143+
coordinates.add(element.coordinates())
144+
return true
145+
}
146+
147+
override fun visitGraphQLDirective(
148+
element: NadelSchemaTraverserElement.Directive,
149+
): Boolean {
150+
// Ignore built in directives
151+
if (DirectiveInfo.isGraphqlSpecifiedDirective(element.node.name)) {
152+
return false
153+
}
154+
155+
coordinates.add(element.coordinates())
156+
return true
157+
}
158+
159+
override fun visitGraphQLAppliedDirective(
160+
element: NadelSchemaTraverserElement.AppliedDirective,
161+
): Boolean {
162+
coordinates.add(element.coordinates())
163+
return false // Don't traverse argument further
164+
}
165+
166+
override fun visitGraphQLAppliedDirectiveArgument(
167+
element: NadelSchemaTraverserElement.AppliedDirectiveArgument,
168+
): Boolean {
169+
coordinates.add(element.coordinates())
170+
return true
171+
}
172+
}
173+
)
174+
175+
return coordinates
176+
}
177+
}

lib/src/main/java/graphql/nadel/engine/blueprint/NadelFastSchemaTraverser.kt

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package graphql.nadel.engine.blueprint
22

3+
import graphql.introspection.Introspection
34
import graphql.schema.GraphQLSchema
5+
import graphql.schema.idl.DirectiveInfo
6+
import graphql.schema.idl.ScalarInfo
47

58
/**
69
* Significantly faster than normal [graphql.schema.SchemaTraverser] as it's simpler.
@@ -10,12 +13,34 @@ import graphql.schema.GraphQLSchema
1013
* That's 4x faster.
1114
*/
1215
internal class NadelSchemaTraverser {
16+
fun traverse(
17+
schema: GraphQLSchema,
18+
visitor: NadelSchemaTraverserVisitor,
19+
) {
20+
val typeRoots = schema.typeMap.asSequence()
21+
.filterNot { (typeName) ->
22+
Introspection.isIntrospectionTypes(typeName) || ScalarInfo.isGraphqlSpecifiedScalar(typeName)
23+
}
24+
.map { (_, type) ->
25+
NadelSchemaTraverserElement.from(type)
26+
}
27+
val directiveRoots = schema.directives.asSequence()
28+
.filterNot { directive ->
29+
DirectiveInfo.isGraphqlSpecifiedDirective(directive.name)
30+
}
31+
.map { directive ->
32+
NadelSchemaTraverserElement.from(directive)
33+
}
34+
35+
return traverse((typeRoots + directiveRoots).asIterable(), visitor)
36+
}
37+
1338
fun traverse(
1439
schema: GraphQLSchema,
1540
roots: Iterable<String>,
1641
visitor: NadelSchemaTraverserVisitor,
1742
) {
18-
val queue: MutableList<NadelSchemaTraverserElement> = roots
43+
val rootsResolved: MutableList<NadelSchemaTraverserElement> = roots
1944
.mapNotNullTo(mutableListOf()) { typeName ->
2045
val type = schema.typeMap[typeName]
2146
// Types can be deleted by transformer, so they may not exist in end schema
@@ -31,11 +56,27 @@ internal class NadelSchemaTraverser {
3156
}
3257
}
3358

34-
val visitedTypes: MutableSet<String> = roots.toMutableSet()
59+
return traverse(rootsResolved, visitor)
60+
}
61+
62+
fun traverse(
63+
roots: Iterable<NadelSchemaTraverserElement>,
64+
visitor: NadelSchemaTraverserVisitor,
65+
) {
66+
val queue: MutableList<NadelSchemaTraverserElement> = roots.toMutableList()
67+
68+
val visitedRoots: MutableSet<String> = roots
69+
.mapNotNullTo(mutableSetOf()) {
70+
if (it is NadelSchemaTraverserElement.Type) {
71+
it.node.name
72+
} else {
73+
null
74+
}
75+
}
3576

3677
val addToQueue = fun(element: NadelSchemaTraverserElement) {
3778
if (element is NadelSchemaTraverserElement.Type) {
38-
if (visitedTypes.add(element.node.name)) {
79+
if (visitedRoots.add(element.node.name)) {
3980
queue.add(element)
4081
}
4182
} else {

0 commit comments

Comments
 (0)