Skip to content

Commit ceb6b9a

Browse files
smyrickdariuszkuc
authored andcommitted
feat: do not cache list types (#202)
* feat: do not cache list types To simplify logic and make the cache simplier, we will not cache any list type. This means that the TypeCache is truely just caching fully qualified types. Lists will still be generated but they will not hit the cache to get their graphql type until they request a class. This will also help if we want to support adding Sets to the types as it not just becomes one location we have to update for all the valid list types * fix: delete unused extension method
1 parent 0e6bc8a commit ceb6b9a

File tree

5 files changed

+95
-57
lines changed

5 files changed

+95
-57
lines changed

src/main/kotlin/com/expedia/graphql/generator/extensions/kClassExtensions.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,6 @@ internal fun KClass<*>.getSimpleName(isInputClass: Boolean = false): String {
6060
}
6161
}
6262

63-
internal fun KClass<*>.getQualifiedName(): String = this.qualifiedName ?: ""
63+
internal fun KClass<*>.getQualifiedName(): String = this.qualifiedName.orEmpty()
6464

6565
internal fun KClass<*>.isPublic(): Boolean = this.visibility == KVisibility.PUBLIC

src/main/kotlin/com/expedia/graphql/generator/extensions/kTypeExtensions.kt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,6 @@ internal fun KType.getWrappedType(): KType {
2929
}
3030
}
3131

32-
internal fun KType.getWrappedName(isInputType: Boolean = false): String {
33-
val isPrimitiveArray = primitiveArrayTypes.containsKey(this.getKClass())
34-
return when {
35-
isPrimitiveArray -> this.getSimpleName()
36-
this.getKClass().isList() -> "List<${this.getWrappedType().getSimpleName(isInputType)}>"
37-
this.getKClass().isArray() -> "Array<${this.getWrappedType().getSimpleName(isInputType)}>"
38-
else -> this.getSimpleName(isInputType)
39-
}
40-
}
41-
4232
internal fun KType.getSimpleName(isInputType: Boolean = false): String = this.getKClass().getSimpleName(isInputType)
4333

4434
internal val KType.qualifiedName: String

src/main/kotlin/com/expedia/graphql/generator/state/TypesCache.kt

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import com.expedia.graphql.exceptions.ConflictingTypesException
44
import com.expedia.graphql.exceptions.TypeNotSupportedException
55
import com.expedia.graphql.generator.extensions.getKClass
66
import com.expedia.graphql.generator.extensions.getSimpleName
7-
import com.expedia.graphql.generator.extensions.getWrappedName
87
import com.expedia.graphql.generator.extensions.isListType
98
import com.expedia.graphql.generator.extensions.qualifiedName
109
import graphql.schema.GraphQLType
@@ -20,7 +19,7 @@ internal class TypesCache(private val supportedPackages: List<String>) {
2019

2120
@Throws(ConflictingTypesException::class)
2221
fun get(cacheKey: TypesCacheKey): GraphQLType? {
23-
val cacheKeyString = getCacheKeyString(cacheKey)
22+
val cacheKeyString = getCacheKeyString(cacheKey) ?: return null
2423
val cachedType = cache[cacheKeyString]
2524

2625
if (cachedType != null) {
@@ -36,39 +35,38 @@ internal class TypesCache(private val supportedPackages: List<String>) {
3635
}
3736

3837
fun put(key: TypesCacheKey, kGraphQLType: KGraphQLType): KGraphQLType? {
39-
typeUnderConstruction.remove(kGraphQLType.kClass)
40-
return cache.put(getCacheKeyString(key), kGraphQLType)
38+
val cacheKey = getCacheKeyString(key)
39+
40+
if (cacheKey != null) {
41+
typeUnderConstruction.remove(kGraphQLType.kClass)
42+
return cache.put(cacheKey, kGraphQLType)
43+
}
44+
45+
return null
4146
}
4247

4348
fun doesNotContainGraphQLType(graphQLType: GraphQLType) =
4449
cache.none { (_, v) -> v.graphQLType.name == graphQLType.name }
4550

4651
fun doesNotContain(kClass: KClass<*>): Boolean = cache.none { (_, ktype) -> ktype.kClass == kClass }
4752

48-
private fun getCacheKeyString(cacheKey: TypesCacheKey): String {
49-
val kClass = cacheKey.type.getKClass()
50-
51-
if (kClass.isSubclassOf(Enum::class)) {
52-
return kClass.getSimpleName()
53-
}
54-
55-
if (isTypeNotSupported(cacheKey.type)) {
56-
throw TypeNotSupportedException(cacheKey.type, supportedPackages)
53+
/**
54+
* We do not want to cache list types since it is just a simple wrapper.
55+
* Enums do not have a different name for input and output.
56+
*/
57+
private fun getCacheKeyString(cacheKey: TypesCacheKey): String? {
58+
val type = cacheKey.type
59+
val kClass = type.getKClass()
60+
61+
return when {
62+
kClass.isListType() -> null
63+
kClass.isSubclassOf(Enum::class) -> kClass.getSimpleName()
64+
isTypeNotSupported(type) -> throw TypeNotSupportedException(type, supportedPackages)
65+
else -> type.getSimpleName(cacheKey.inputType)
5766
}
58-
59-
return cacheKey.type.getWrappedName(cacheKey.inputType)
6067
}
6168

62-
private fun isTypeNotSupported(type: KType): Boolean {
63-
64-
if (type.getKClass().isListType()) {
65-
return false
66-
}
67-
68-
return supportedPackages.none {
69-
type.qualifiedName.startsWith(it)
70-
}
71-
}
69+
private fun isTypeNotSupported(type: KType): Boolean = supportedPackages.none { type.qualifiedName.startsWith(it) }
7270

7371
private fun putTypeUnderConstruction(kClass: KClass<*>) = typeUnderConstruction.add(kClass)
7472

src/test/kotlin/com/expedia/graphql/generator/extensions/KTypeExtensionsKtTest.kt

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,25 +86,4 @@ internal class KTypeExtensionsKtTest {
8686
assertEquals("com.expedia.graphql.generator.extensions.KTypeExtensionsKtTest.MyClass", MyClass::class.starProjectedType.qualifiedName)
8787
assertEquals("", object { }::class.starProjectedType.qualifiedName)
8888
}
89-
90-
@Test
91-
fun getName() {
92-
assertEquals("MyClass", MyClass::class.starProjectedType.getWrappedName())
93-
94-
assertEquals("MyClassInput", MyClass::class.starProjectedType.getWrappedName(isInputType = true))
95-
96-
assertEquals("List<String>", MyClass::listFun.findParameterByName("list")?.type?.getWrappedName())
97-
98-
assertEquals("List<StringInput>", MyClass::listFun.findParameterByName("list")?.type?.getWrappedName(isInputType = true))
99-
100-
assertEquals("Array<String>", MyClass::arrayFun.findParameterByName("array")?.type?.getWrappedName())
101-
102-
assertEquals("IntArray", MyClass::primitiveArrayFun.findParameterByName("intArray")?.type?.getWrappedName())
103-
104-
assertEquals("IntArray", MyClass::primitiveArrayFun.findParameterByName("intArray")?.type?.getWrappedName(isInputType = true))
105-
106-
assertFailsWith(CouldNotGetNameOfKClassException::class) {
107-
object {}::class.starProjectedType.getWrappedName()
108-
}
109-
}
11089
}

src/test/kotlin/com/expedia/graphql/generator/state/TypesCacheTest.kt

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import graphql.schema.GraphQLTypeVisitor
55
import graphql.util.TraversalControl
66
import graphql.util.TraverserContext
77
import org.junit.jupiter.api.Test
8+
import kotlin.reflect.full.findParameterByName
89
import kotlin.reflect.full.starProjectedType
910
import kotlin.test.assertEquals
1011
import kotlin.test.assertFalse
@@ -28,6 +29,16 @@ class TypesCacheTest {
2829
override fun accept(context: TraverserContext<GraphQLType>, visitor: GraphQLTypeVisitor): TraversalControl = context.thisNode().accept(context, visitor)
2930
}
3031

32+
internal class MyClass {
33+
fun listFun(list: List<String>) = list.joinToString(separator = ",") { it }
34+
35+
fun objectListFun(list: List<MyType>) = list.map { it.id.toString() }.joinToString(separator = ",") { it }
36+
37+
fun arrayFun(array: Array<String>) = array.joinToString(separator = ",") { it }
38+
39+
fun primitiveArrayFun(intArray: IntArray) = intArray.joinToString(separator = ",") { it.toString() }
40+
}
41+
3142
@Test
3243
fun `basic get and put with non input type`() {
3344
val cache = TypesCache(listOf("com.expedia.graphql"))
@@ -56,6 +67,66 @@ class TypesCacheTest {
5667
assertNotNull(cache.get(cacheKey))
5768
}
5869

70+
@Test
71+
fun `list types are not cached`() {
72+
val cache = TypesCache(listOf("com.expedia.graphql"))
73+
74+
val type = MyClass::listFun.findParameterByName("list")?.type
75+
76+
assertNotNull(type)
77+
78+
val cacheKey = TypesCacheKey(type, false)
79+
val cacheValue = KGraphQLType(MyType::class, graphQLType)
80+
81+
assertNull(cache.get(cacheKey))
82+
assertNull(cache.put(cacheKey, cacheValue))
83+
}
84+
85+
@Test
86+
fun `list of objects are not cached`() {
87+
val cache = TypesCache(listOf("com.expedia.graphql"))
88+
89+
val type = MyClass::objectListFun.findParameterByName("list")?.type
90+
91+
assertNotNull(type)
92+
93+
val cacheKey = TypesCacheKey(type, false)
94+
val cacheValue = KGraphQLType(MyType::class, graphQLType)
95+
96+
assertNull(cache.get(cacheKey))
97+
assertNull(cache.put(cacheKey, cacheValue))
98+
}
99+
100+
@Test
101+
fun `primitive array types are not cached`() {
102+
val cache = TypesCache(listOf("com.expedia.graphql"))
103+
104+
val type = MyClass::primitiveArrayFun.findParameterByName("intArray")?.type
105+
106+
assertNotNull(type)
107+
108+
val cacheKey = TypesCacheKey(type, false)
109+
val cacheValue = KGraphQLType(MyType::class, graphQLType)
110+
111+
assertNull(cache.get(cacheKey))
112+
assertNull(cache.put(cacheKey, cacheValue))
113+
}
114+
115+
@Test
116+
fun `array types are not cached`() {
117+
val cache = TypesCache(listOf("com.expedia.graphql"))
118+
119+
val type = MyClass::arrayFun.findParameterByName("array")?.type
120+
121+
assertNotNull(type)
122+
123+
val cacheKey = TypesCacheKey(type, false)
124+
val cacheValue = KGraphQLType(MyType::class, graphQLType)
125+
126+
assertNull(cache.get(cacheKey))
127+
assertNull(cache.put(cacheKey, cacheValue))
128+
}
129+
59130
@Test
60131
fun `verify doesNotContainGraphQLType()`() {
61132
val cache = TypesCache(listOf("com.expedia.graphql"))

0 commit comments

Comments
 (0)