Skip to content

[generator] avoid duplicate argument deserialization #1379

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Mar 8, 2022
Merged
Prev Previous commit
Next Next commit
Handle enum arguments
  • Loading branch information
rocketraman authored and Dariusz Kuc committed Feb 24, 2022
commit 7a85c2ef2d037e455994ca75f0ae62c5fee34123
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,17 @@ import com.expediagroup.graphql.generator.internal.extensions.getKClass
import com.expediagroup.graphql.generator.internal.extensions.getName
import com.expediagroup.graphql.generator.internal.extensions.getTypeOfFirstArgument
import com.expediagroup.graphql.generator.internal.extensions.isOptionalInputType
import com.expediagroup.graphql.generator.internal.extensions.isSubclassOf
import com.expediagroup.graphql.generator.internal.extensions.qualifiedName
import graphql.schema.DataFetchingEnvironment
import kotlin.reflect.KClass
import kotlin.reflect.KParameter
import kotlin.reflect.KType
import kotlin.reflect.full.primaryConstructor

internal fun getEnumValue(paramType: KType, enumValue: String) =
paramType.getKClass().java.enumConstants.filterIsInstance(Enum::class.java).first { it.name == enumValue }

/**
* Convert the input object [argumentValue] given from graphql-java to a class we can pass to the Kotlin function.
*/
Expand Down Expand Up @@ -79,6 +84,10 @@ private fun convertValue(
return mapToKotlinObject(argumentValue as Map<String, *>, paramType.getKClass())
}

if (paramType.isSubclassOf(Enum::class) && argumentValue is String) {
return getEnumValue(paramType, argumentValue)
}

// Value is already parsed so we can return it as-is
return argumentValue
}
Expand All @@ -95,9 +104,12 @@ private fun <T : Any> mapToKotlinObject(inputMap: Map<String, *>, targetClass: K
val input = inputMap[it.getName()]
if (input is Map<*, *>) {
val nestedTarged = it.type.getKClass()

@Suppress("UNCHECKED_CAST")
val subValue = mapToKotlinObject(input as Map<String, *>, nestedTarged)
constructorValues[it] = subValue
} else if (it.type.isSubclassOf(Enum::class)) {
constructorValues[it] = convertValue(it.type, input)
} else {
constructorValues[it] = input
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ class ConvertArgumentToObjectKtTest {
assertEquals("hello", castResult.foo)
}

@Test
fun `enum object is parsed`() {
val kParam = assertNotNull(TestFunctions::enumInput.findParameterByName("input"))
val mockEnv = mockk<DataFetchingEnvironment>()
val inputValue = "BAR"
val result = convertArgumentToObject(kParam, mockEnv, "input", inputValue)
val castResult = assertIs<Foo>(result)
assertEquals(Foo.BAR, castResult)
}

@Test
fun `generic map object is parsed`() {
val kParam = assertNotNull(TestFunctions::inputObject.findParameterByName("input"))
Expand Down Expand Up @@ -138,6 +148,7 @@ class ConvertArgumentToObjectKtTest {
class TestFunctions {
fun stringInput(input: String): String = TODO()
fun listStringInput(input: List<String>): String = TODO()
fun enumInput(input: Foo): String = TODO()
fun inputObject(input: TestInput): String = TODO()
fun optionalInput(input: OptionalInput<String>): String = TODO()
fun optionalInputObject(input: OptionalInput<TestInput>): String = TODO()
Expand All @@ -149,4 +160,9 @@ class ConvertArgumentToObjectKtTest {
val bar: String? = null,
val baz: List<String>? = null
)

enum class Foo {
BAR,
BAZ
}
}