Skip to content

Commit a3f4dc8

Browse files
d4rkendariuszkuc
authored andcommitted
Add missing description & deprecation annotation processing for enum classes and values. (#77)
Closes #76
1 parent 8614439 commit a3f4dc8

File tree

4 files changed

+89
-18
lines changed

4 files changed

+89
-18
lines changed

detekt_baseline.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
<ID>MethodOverloading:SchemaGeneratorTest.kt$SchemaGeneratorTest</ID>
77
<ID>TooManyFunctions:SchemaGenerator.kt$SchemaGenerator</ID>
88
<ID>ComplexInterface:SchemaGeneratorHooks.kt$SchemaGeneratorHooks</ID>
9+
<ID>TooManyFunctions:annotationExtensions.kt$com.expedia.graphql.schema.extensions.annotationExtensions.kt</ID>
910
</Whitelist>
1011
</SmellBaseline>

src/main/kotlin/com/expedia/graphql/schema/extensions/annotationExtensions.kt

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,33 @@ import com.google.common.base.CaseFormat
1010
import graphql.schema.GraphQLArgument
1111
import graphql.schema.GraphQLDirective
1212
import graphql.schema.GraphQLInputType
13+
import java.lang.reflect.Field
1314
import kotlin.reflect.KAnnotatedElement
1415
import kotlin.reflect.KParameter
1516
import kotlin.reflect.full.findAnnotation
1617
import com.expedia.graphql.annotations.GraphQLDirective as DirectiveAnnotation
1718

1819
internal fun KAnnotatedElement.graphQLDescription(): String? {
1920
val directiveNames = listOfDirectives().map { it.normalizeDirectiveName() }
20-
2121
val description = this.findAnnotation<GraphQLDescription>()?.value
22+
return formatGraphQLDescription(description, directiveNames)
23+
}
24+
25+
internal fun Field.graphQLDescription(): String? {
26+
val directiveNames = listOfDirectives().map { it.normalizeDirectiveName() }
27+
val description = this.getAnnotation(GraphQLDescription::class.java)?.value
28+
return formatGraphQLDescription(description, directiveNames)
29+
}
2230

23-
return when {
24-
description != null && directiveNames.isNotEmpty() ->
25-
"""$description
31+
private fun formatGraphQLDescription(description: String?, directiveNames: List<String>): String? = when {
32+
description != null && directiveNames.isNotEmpty() ->
33+
"""$description
2634
|
2735
|Directives: ${directiveNames.joinToString(", ")}
2836
""".trimMargin()
29-
description == null && directiveNames.isNotEmpty() ->
30-
"Directives: ${directiveNames.joinToString(", ")}"
31-
else -> description
32-
}
37+
description == null && directiveNames.isNotEmpty() ->
38+
"Directives: ${directiveNames.joinToString(", ")}"
39+
else -> description
3340
}
3441

3542
private fun KAnnotatedElement.listOfDirectives(): List<String> {
@@ -48,13 +55,32 @@ private fun KAnnotatedElement.listOfDirectives(): List<String> {
4855
.toList()
4956
}
5057

51-
internal fun KAnnotatedElement.getDeprecationReason(): String? {
52-
val annotation = this.findAnnotation<Deprecated>() ?: return null
58+
private fun Field.listOfDirectives(): List<String> {
59+
val deprecationReason: String? = this.getDeprecationReason()?.let { "deprecated" }
60+
61+
return this.declaredAnnotations.asSequence()
62+
.mapNotNull { it.getDirectiveInfo() }
63+
.map {
64+
when {
65+
it.effectiveName.isNullOrEmpty().not() -> "@${it.effectiveName}"
66+
else -> null
67+
}
68+
}
69+
.plus(deprecationReason)
70+
.filterNotNull()
71+
.toList()
72+
}
73+
74+
internal fun KAnnotatedElement.getDeprecationReason(): String? = this.findAnnotation<Deprecated>()?.getReason()
75+
76+
internal fun Field.getDeprecationReason(): String? = this.getDeclaredAnnotation(Deprecated::class.java)?.getReason()
77+
78+
internal fun Deprecated.getReason(): String? {
5379
val builder = StringBuilder()
54-
builder.append(annotation.message)
55-
if (!annotation.replaceWith.expression.isBlank()) {
80+
builder.append(this.message)
81+
if (!this.replaceWith.expression.isBlank()) {
5682
builder.append(", replace with ")
57-
builder.append(annotation.replaceWith.expression)
83+
builder.append(this.replaceWith.expression)
5884
}
5985
return builder.toString()
6086
}
Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,29 @@
11
package com.expedia.graphql.schema.generator.types
22

3+
import com.expedia.graphql.schema.extensions.getDeprecationReason
4+
import com.expedia.graphql.schema.extensions.graphQLDescription
35
import graphql.schema.GraphQLEnumType
6+
import graphql.schema.GraphQLEnumValueDefinition
47
import kotlin.reflect.KClass
58

69
internal fun enumType(kClass: KClass<out Enum<*>>): GraphQLEnumType {
7-
val builder = GraphQLEnumType.newEnum()
10+
val enumBuilder = GraphQLEnumType.newEnum()
11+
12+
enumBuilder.name(kClass.simpleName)
13+
enumBuilder.description(kClass.graphQLDescription())
814

915
kClass.java.enumConstants.forEach {
10-
builder.value(it.name)
16+
val valueBuilder = GraphQLEnumValueDefinition.newEnumValueDefinition()
17+
18+
valueBuilder.name(it.name)
19+
valueBuilder.value(it.name)
20+
21+
val valueField = kClass.java.getField(it.name)
22+
valueBuilder.description(valueField.graphQLDescription())
23+
valueBuilder.deprecationReason(valueField.getDeprecationReason())
24+
25+
enumBuilder.value(valueBuilder.build())
1126
}
1227

13-
builder.name(kClass.simpleName)
14-
return builder.build()
28+
return enumBuilder.build()
1529
}

src/test/kotlin/com/expedia/graphql/schema/generator/types/EnumTypeTest.kt

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
package com.expedia.graphql.schema.generator.types
22

3+
import com.expedia.graphql.annotations.GraphQLDescription
34
import org.junit.jupiter.api.Test
45
import kotlin.test.assertEquals
6+
import kotlin.test.assertFalse
7+
import kotlin.test.assertNotNull
8+
import kotlin.test.assertNull
9+
import kotlin.test.assertTrue
510

611
internal class EnumTypeTest {
7-
12+
@GraphQLDescription("MyTestEnum description")
813
private enum class MyTestEnum {
14+
@GraphQLDescription("enum 'ONE' description")
915
ONE,
16+
17+
@Deprecated("Deprecated enum value")
1018
TWO
1119
}
1220

@@ -18,4 +26,26 @@ internal class EnumTypeTest {
1826
assertEquals(expected = "ONE", actual = actual.values[0].value)
1927
assertEquals(expected = "TWO", actual = actual.values[1].value)
2028
}
29+
30+
@Test
31+
fun `Description on enum class and values`() {
32+
val gqlEnum = assertNotNull(enumType(MyTestEnum::class))
33+
assertEquals("MyTestEnum description", gqlEnum.description)
34+
35+
val one = assertNotNull(gqlEnum.getValue("ONE"))
36+
assertEquals("enum 'ONE' description", one.description)
37+
}
38+
39+
@Test
40+
fun `Deprecation on enum values`() {
41+
val gqlEnum = assertNotNull(enumType(MyTestEnum::class))
42+
43+
val one = assertNotNull(gqlEnum.getValue("ONE"))
44+
assertFalse(one.isDeprecated)
45+
assertNull(one.deprecationReason)
46+
47+
val two = assertNotNull(gqlEnum.getValue("TWO"))
48+
assertTrue(two.isDeprecated)
49+
assertEquals("Deprecated enum value", two.deprecationReason)
50+
}
2151
}

0 commit comments

Comments
 (0)