@@ -22,6 +22,7 @@ import com.squareup.kotlinpoet.ClassName
2222import com.squareup.kotlinpoet.FLOAT
2323import com.squareup.kotlinpoet.INT
2424import com.squareup.kotlinpoet.LIST
25+ import com.squareup.kotlinpoet.ParameterizedTypeName
2526import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
2627import com.squareup.kotlinpoet.STRING
2728import com.squareup.kotlinpoet.TypeName
@@ -97,7 +98,7 @@ internal fun generateCustomClassName(context: GraphQLClientGeneratorContext, gra
9798 } else {
9899 // verify we got same selection set for interface and/or objects (unions shouldn't have any fields)
99100 for (cachedType in cachedTypeNames) {
100- if (isCachedTypeApplicable(context, cachedType.simpleName , graphQLTypeDefinition, selectionSet)) {
101+ if (isCachedTypeApplicable(context, cachedType.simpleNameWithoutWrapper() , graphQLTypeDefinition, selectionSet)) {
101102 return cachedType
102103 }
103104 }
@@ -111,11 +112,13 @@ internal fun generateCustomClassName(context: GraphQLClientGeneratorContext, gra
111112 else -> throw RuntimeException (" should never happen" )
112113 }
113114 val className = ClassName (context.packageName, " ${context.rootType} .${typeSpec.name} " )
114- context.classNameCache[overriddenName ]?.add(className)
115+ context.classNameCache[graphQLTypeName ]?.add(className)
115116 className
116117 }
117118}
118119
120+ private fun ClassName.simpleNameWithoutWrapper () = this .simpleName.substringAfter(" ." )
121+
119122private fun isCachedTypeApplicable (context : GraphQLClientGeneratorContext , graphQLTypeName : String , graphQLTypeDefinition : TypeDefinition <* >, selectionSet : SelectionSet ): Boolean =
120123 when (graphQLTypeDefinition) {
121124 is UnionTypeDefinition -> {
@@ -148,21 +151,28 @@ private fun isCachedTypeApplicable(context: GraphQLClientGeneratorContext, graph
148151
149152private fun verifySelectionSet (context : GraphQLClientGeneratorContext , graphQLTypeName : String , selectionSet : SelectionSet ): Boolean {
150153 val selectedFields = calculateSelectedFields(context, graphQLTypeName, selectionSet)
151- val typeSpec = context.typeSpecs[graphQLTypeName]
152- val properties = typeSpec?.propertySpecs?.map { it.name }?.toSet() ? : emptySet()
153- return selectedFields == properties ||
154- (selectedFields.minus(properties).size == 1 && selectedFields.contains(" __typename" ) && context.objectsWithTypeNameSelection.contains(graphQLTypeName))
154+ val properties = calculateGeneratedTypeProperties(context, graphQLTypeName)
155+ if (context.objectsWithTypeNameSelection.contains(graphQLTypeName)) {
156+ properties.add(" __typename" )
157+ }
158+ return selectedFields == properties
155159}
156160
157161private fun calculateSelectedFields (
158162 context : GraphQLClientGeneratorContext ,
159163 targetType : String ,
160- selectionSet : SelectionSet
164+ selectionSet : SelectionSet ,
165+ path : String = ""
161166): Set <String > {
162167 val result = mutableSetOf<String >()
163168 selectionSet.selections.forEach { selection ->
164169 when (selection) {
165- is Field -> result.add(selection.name)
170+ is Field -> {
171+ result.add(path + selection.name)
172+ if (selection.selectionSet != null ) {
173+ result.addAll(calculateSelectedFields(context, targetType, selection.selectionSet, " $path${selection.name} ." ))
174+ }
175+ }
166176 is InlineFragment -> if (selection.typeCondition.name == targetType) {
167177 result.addAll(calculateSelectedFields(context, targetType, selection.selectionSet))
168178 }
@@ -178,3 +188,24 @@ private fun calculateSelectedFields(
178188 }
179189 return result
180190}
191+
192+ private fun calculateGeneratedTypeProperties (context : GraphQLClientGeneratorContext , graphQLTypeName : String , path : String = ""): MutableSet <String > {
193+ val props = mutableSetOf<String >()
194+
195+ val typeSpec = context.typeSpecs[graphQLTypeName]
196+ for (property in typeSpec?.propertySpecs ? : emptyList()) {
197+ props.add(path + property.name)
198+ when (val propertyType = property.type) {
199+ is ParameterizedTypeName -> {
200+ val genericType = propertyType.typeArguments.firstOrNull() as ? ClassName
201+ val genericTypeName = genericType?.simpleNameWithoutWrapper() ? : " "
202+ props.addAll(calculateGeneratedTypeProperties(context, genericTypeName, " $path${property.name} ." ))
203+ }
204+ is ClassName -> {
205+ val fieldTypeName = propertyType.simpleNameWithoutWrapper()
206+ props.addAll(calculateGeneratedTypeProperties(context, fieldTypeName, " $path${property.name} ." ))
207+ }
208+ }
209+ }
210+ return props
211+ }
0 commit comments