Skip to content

Commit 46a0f02

Browse files
author
Guillaume Scheibel
authored
Polymorphic ignore (#633)
* Fix typo in the function name * Fix transitive property of `@GraphQLIgnore` for polymorphic types
1 parent bd530a8 commit 46a0f02

File tree

6 files changed

+73
-7
lines changed

6 files changed

+73
-7
lines changed

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/extensions/kClassExtensions.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ internal fun KClass<*>.getValidSuperclasses(hooks: SchemaGeneratorHooks): List<K
5555
this.superclasses.flatMap { it.getValidSuperclasses(hooks) }
5656
}
5757

58-
internal fun KClass<*>.findConstructorParamter(name: String): KParameter? =
58+
internal fun KClass<*>.findConstructorParameter(name: String): KParameter? =
5959
this.primaryConstructor?.findParameterByName(name)
6060

6161
internal fun KClass<*>.isInterface(): Boolean = this.java.isInterface || this.isAbstract

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/extensions/kPropertyExtensions.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,4 @@ internal fun KProperty<*>.getPropertyName(parentClass: KClass<*>): String? =
4848
internal fun KProperty<*>.getPropertyAnnotations(parentClass: KClass<*>): List<Annotation> =
4949
this.annotations.union(getConstructorParameter(parentClass)?.annotations.orEmpty()).toList()
5050

51-
private fun KProperty<*>.getConstructorParameter(parentClass: KClass<*>) = parentClass.findConstructorParamter(this.name)
51+
private fun KProperty<*>.getConstructorParameter(parentClass: KClass<*>) = parentClass.findConstructorParameter(this.name)

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/filters/propertyFilters.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@
1616

1717
package com.expediagroup.graphql.generator.filters
1818

19+
import com.expediagroup.graphql.generator.extensions.isGraphQLIgnored
1920
import com.expediagroup.graphql.generator.extensions.isPropertyGraphQLIgnored
2021
import com.expediagroup.graphql.generator.extensions.isPublic
2122
import com.expediagroup.graphql.generator.extensions.qualifiedName
2223
import kotlin.reflect.KClass
2324
import kotlin.reflect.KProperty
25+
import kotlin.reflect.full.memberProperties
26+
import kotlin.reflect.jvm.jvmErasure
2427

2528
private typealias PropertyFilter = (KProperty<*>, KClass<*>) -> Boolean
2629

@@ -29,5 +32,20 @@ private val blacklistTypes: List<String> = listOf("kotlin.reflect.KClass")
2932
private val isPropertyPublic: PropertyFilter = { prop, _ -> prop.isPublic() }
3033
private val isPropertyNotGraphQLIgnored: PropertyFilter = { prop, parentClass -> prop.isPropertyGraphQLIgnored(parentClass).not() }
3134
private val isNotBlacklistedType: PropertyFilter = { prop, _ -> blacklistTypes.contains(prop.returnType.qualifiedName).not() }
35+
private val isNotIgnoredFromSuperClass: PropertyFilter = { prop, parentClass ->
36+
val superPropsIgnored = parentClass.supertypes
37+
.flatMap { superType ->
38+
superType.jvmErasure.memberProperties
39+
.filter { superProp -> basicPropertyFilters.all { it.invoke(superProp, superType::class) } }
40+
.filter { it.isGraphQLIgnored() }
41+
}
3242

33-
internal val propertyFilters: List<PropertyFilter> = listOf(isPropertyPublic, isNotBlacklistedType, isPropertyNotGraphQLIgnored)
43+
superPropsIgnored.none { superProp ->
44+
superProp.name == prop.name &&
45+
superProp.returnType == prop.returnType &&
46+
superProp.visibility == prop.visibility
47+
}
48+
}
49+
50+
private val basicPropertyFilters = listOf(isPropertyPublic, isNotBlacklistedType)
51+
internal val propertyFilters: List<PropertyFilter> = basicPropertyFilters + isPropertyNotGraphQLIgnored + isNotIgnoredFromSuperClass

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/types/InterfaceBuilder.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.expediagroup.graphql.generator.extensions.getSimpleName
2424
import com.expediagroup.graphql.generator.extensions.getValidFunctions
2525
import com.expediagroup.graphql.generator.extensions.getValidProperties
2626
import com.expediagroup.graphql.generator.extensions.getValidSuperclasses
27+
import com.expediagroup.graphql.generator.extensions.isGraphQLIgnored
2728
import com.expediagroup.graphql.generator.extensions.safeCast
2829
import graphql.TypeResolutionEnvironment
2930
import graphql.schema.GraphQLInterfaceType
@@ -58,6 +59,7 @@ internal class InterfaceBuilder(generator: SchemaGenerator) : TypeBuilder(genera
5859
.forEach { builder.field(generator.function(it, kClass.getSimpleName(), abstract = true)) }
5960

6061
subTypeMapper.getSubTypesOf(kClass)
62+
.filter { it.isGraphQLIgnored().not() }
6163
.map { graphQLTypeOf(it.createType()) }
6264
.forEach {
6365
// Do not add objects currently under construction to the additional types

graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/PolymorphicTests.kt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.expediagroup.graphql.generator
1818

1919
import com.expediagroup.graphql.TopLevelObject
20+
import com.expediagroup.graphql.annotations.GraphQLIgnore
2021
import com.expediagroup.graphql.annotations.GraphQLName
2122
import com.expediagroup.graphql.exceptions.InvalidInputFieldTypeException
2223
import com.expediagroup.graphql.testSchemaConfig
@@ -31,6 +32,7 @@ import org.junit.jupiter.api.Test
3132
import kotlin.random.Random
3233
import kotlin.test.assertEquals
3334
import kotlin.test.assertNotNull
35+
import kotlin.test.assertNull
3436
import kotlin.test.assertTrue
3537

3638
internal class PolymorphicTests {
@@ -146,6 +148,33 @@ internal class PolymorphicTests {
146148
assertEquals("StrawberryCake", strawberryCakeResolver.name)
147149
}
148150

151+
@Test
152+
fun `Interface implementations are not computed when marked with GraphQLIgnore annotation`() {
153+
val schema = toSchema(queries = listOf(TopLevelObject(QueryWithIgnoredInfo())), config = testSchemaConfig)
154+
val service = schema.getType("Service") as? GraphQLInterfaceType
155+
assertNotNull(service)
156+
157+
val webService = schema.getType("WebService") as? GraphQLObjectType
158+
assertNotNull(webService)
159+
160+
val microService = schema.getType("MicroService") as? GraphQLObjectType
161+
assertNull(microService)
162+
}
163+
164+
@Test
165+
fun `Ignored interface properties should not appear in the subtype`() {
166+
val schema = toSchema(queries = listOf(TopLevelObject(QueryWithIgnoredInfo())), config = testSchemaConfig)
167+
val service = schema.getType("Service") as? GraphQLInterfaceType
168+
assertNotNull(service)
169+
val interfaceIgnoredField = service.getFieldDefinition("shouldNotBeInTheSchema")
170+
assertNull(interfaceIgnoredField)
171+
172+
val webService = schema.getType("WebService") as? GraphQLObjectType
173+
assertNotNull(webService)
174+
val subtypeIgnoredField = webService.getFieldDefinition("shouldNotBeInTheSchema")
175+
assertNull(subtypeIgnoredField)
176+
}
177+
149178
private fun mockTypeResolutionEnvironment(target: Any, schema: GraphQLSchema): TypeResolutionEnvironment =
150179
TypeResolutionEnvironment(target, emptyMap(), null, null, schema, null)
151180
}
@@ -270,3 +299,20 @@ class Cheesecake : Cake {
270299
interface Dessert
271300

272301
class IceCream : Dessert
302+
303+
class QueryWithIgnoredInfo {
304+
fun webservice(): Service = WebService("gql-kotlin-service")
305+
fun microservice(): Service = MicroService("micro-gql-kotlin-service")
306+
}
307+
308+
interface Service {
309+
val name: String
310+
311+
@GraphQLIgnore
312+
val shouldNotBeInTheSchema: Boolean
313+
}
314+
315+
data class WebService(override val name: String, override val shouldNotBeInTheSchema: Boolean = false) : Service
316+
317+
@GraphQLIgnore
318+
data class MicroService(override val name: String, override val shouldNotBeInTheSchema: Boolean = true) : Service

graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/extensions/KClassExtensionsTest.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,10 @@ open class KClassExtensionsTest {
234234

235235
@Test
236236
fun `test findConstructorParamter`() {
237-
assertNotNull(MyTestClass::class.findConstructorParamter("publicProperty"))
238-
assertNull(MyTestClass::class.findConstructorParamter("foobar"))
239-
assertNull(EmptyConstructorClass::class.findConstructorParamter("id"))
240-
assertNull(TestInterface::class.findConstructorParamter("foobar"))
237+
assertNotNull(MyTestClass::class.findConstructorParameter("publicProperty"))
238+
assertNull(MyTestClass::class.findConstructorParameter("foobar"))
239+
assertNull(EmptyConstructorClass::class.findConstructorParameter("id"))
240+
assertNull(TestInterface::class.findConstructorParameter("foobar"))
241241
}
242242

243243
@Test

0 commit comments

Comments
 (0)