Skip to content

Commit 8ce7fcb

Browse files
smyrickbrennantaylor
authored andcommitted
feat: remove requirement for @Property: prefix (#97)
* feat: remove requirment for @Property: prefix * test: annotations on different types * fix: simplify constructor find logic * test: remove duplicate test * test: linter - use data class * test: increase test coverage
1 parent cff47bd commit 8ce7fcb

26 files changed

+328
-98
lines changed

example/src/main/kotlin/com.expedia.graphql.sample/model/Widget.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ import com.expedia.graphql.annotations.GraphQLIgnore
55

66
@GraphQLDescription("A useful widget")
77
data class Widget(
8-
@property:GraphQLDescription("The widget's value that can be null")
8+
@GraphQLDescription("The widget's value that can be null")
99
var value: Int? = null,
10-
@property:Deprecated(message = "This field is deprecated", replaceWith = ReplaceWith("value"))
11-
@property:GraphQLDescription("The widget's deprecated value that shouldn't be used")
10+
@Deprecated(message = "This field is deprecated", replaceWith = ReplaceWith("value"))
11+
@GraphQLDescription("The widget's deprecated value that shouldn't be used")
1212
val deprecatedValue: Int? = value,
13-
@property:GraphQLIgnore
13+
@GraphQLIgnore
1414
val ignoredField: String? = "ignored",
1515
private val hiddenField: String? = "hidden"
1616
) {
1717

1818
@GraphQLDescription("returns original value multiplied by target OR null if original value was null")
1919
fun multiplyValueBy(multiplier: Int) = value?.times(multiplier)
20-
}
20+
}

example/src/main/kotlin/com.expedia.graphql.sample/query/ScalarQuery.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ class ScalarMutation : Mutation {
2424
}
2525

2626
data class Person(
27-
@property:GraphQLID
27+
@GraphQLID
2828
val id: Int,
2929

3030
val name: String
31-
)
31+
)

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

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@ package com.expedia.graphql.schema.extensions
33
import com.expedia.graphql.annotations.GraphQLDescription
44
import com.expedia.graphql.annotations.GraphQLID
55
import com.expedia.graphql.annotations.GraphQLIgnore
6-
import java.lang.reflect.Field
76
import kotlin.reflect.KAnnotatedElement
87
import kotlin.reflect.full.findAnnotation
98

10-
internal fun KAnnotatedElement.graphQLDescription(): String? = this.findAnnotation<GraphQLDescription>()?.value
11-
12-
internal fun Field.graphQLDescription(): String? = this.getAnnotation(GraphQLDescription::class.java)?.value
9+
internal fun KAnnotatedElement.getGraphQLDescription(): String? = this.findAnnotation<GraphQLDescription>()?.value
1310

1411
internal fun KAnnotatedElement.getDeprecationReason(): String? = this.findAnnotation<Deprecated>()?.getReason()
1512

16-
internal fun Field.getDeprecationReason(): String? = this.getDeclaredAnnotation(Deprecated::class.java)?.getReason()
13+
internal fun KAnnotatedElement.isGraphQLIgnored(): Boolean = this.findAnnotation<GraphQLIgnore>() != null
14+
15+
internal fun KAnnotatedElement.isGraphQLID(): Boolean = this.findAnnotation<GraphQLID>() != null
1716

18-
private fun Deprecated.getReason(): String? {
17+
internal fun Deprecated.getReason(): String? {
1918
val builder = StringBuilder()
2019
builder.append(this.message)
2120

@@ -26,7 +25,3 @@ private fun Deprecated.getReason(): String? {
2625

2726
return builder.toString()
2827
}
29-
30-
internal fun KAnnotatedElement.isGraphQLIgnored() = this.findAnnotation<GraphQLIgnore>() != null
31-
32-
internal fun KAnnotatedElement.isGraphQLID() = this.findAnnotation<GraphQLID>() != null
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package com.expedia.graphql.schema.extensions
2+
3+
internal fun Boolean?.isTrue(): Boolean = this == true
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.expedia.graphql.schema.extensions
2+
3+
import com.expedia.graphql.annotations.GraphQLDescription
4+
import java.lang.reflect.Field
5+
6+
internal fun Field.getGraphQLDescription(): String? = this.getAnnotation(GraphQLDescription::class.java)?.value
7+
8+
internal fun Field.getDeprecationReason(): String? = this.getDeclaredAnnotation(Deprecated::class.java)?.getReason()

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

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,28 @@ import com.expedia.graphql.schema.generator.functionFilters
44
import com.expedia.graphql.schema.generator.propertyFilters
55
import com.expedia.graphql.schema.hooks.SchemaGeneratorHooks
66
import kotlin.reflect.KClass
7+
import kotlin.reflect.KFunction
8+
import kotlin.reflect.KParameter
9+
import kotlin.reflect.KProperty
710
import kotlin.reflect.full.declaredMemberFunctions
811
import kotlin.reflect.full.declaredMemberProperties
912
import kotlin.reflect.full.isSubclassOf
10-
11-
internal fun KClass<*>.getValidProperties(hooks: SchemaGeneratorHooks) = this.declaredMemberProperties
12-
.filter { hooks.isValidProperty(it) }
13-
.filter { prop -> propertyFilters.all { it.invoke(prop) } }
14-
15-
internal fun KClass<*>.getValidFunctions(hooks: SchemaGeneratorHooks) = this.declaredMemberFunctions
16-
.filter { hooks.isValidFunction(it) }
17-
.filter { func -> functionFilters.all { it.invoke(func) } }
13+
import kotlin.reflect.full.primaryConstructor
14+
15+
internal fun KClass<*>.getValidProperties(hooks: SchemaGeneratorHooks): List<KProperty<*>> =
16+
this.declaredMemberProperties
17+
.filter { hooks.isValidProperty(it) }
18+
.filter { prop -> propertyFilters.all { it.invoke(prop, this) } }
19+
20+
internal fun KClass<*>.getValidFunctions(hooks: SchemaGeneratorHooks): List<KFunction<*>> =
21+
this.declaredMemberFunctions
22+
.filter { hooks.isValidFunction(it) }
23+
.filter { func -> functionFilters.all { it.invoke(func) } }
24+
25+
internal fun KClass<*>.findConstructorParamter(name: String): KParameter? =
26+
this.primaryConstructor
27+
?.parameters
28+
?.find { it.name == name }
1829

1930
internal fun KClass<*>.isGraphQLInterface(): Boolean = this.java.isInterface
2031

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.expedia.graphql.schema.extensions
2+
3+
import kotlin.reflect.KClass
4+
import kotlin.reflect.KProperty
5+
6+
internal fun KProperty<*>.isPropertyGraphQLID(parentClass: KClass<*>): Boolean = when {
7+
this.isGraphQLID() -> true
8+
parentClass.findConstructorParamter(this.name)
9+
?.isGraphQLID()
10+
.isTrue() -> true
11+
else -> false
12+
}
13+
14+
internal fun KProperty<*>.isPropertyGraphQLIgnored(parentClass: KClass<*>): Boolean = when {
15+
this.isGraphQLIgnored() -> true
16+
parentClass.findConstructorParamter(this.name)
17+
?.isGraphQLIgnored()
18+
.isTrue() -> true
19+
else -> false
20+
}
21+
22+
internal fun KProperty<*>.getPropertyDeprecationReason(parentClass: KClass<*>): String? =
23+
this.getDeprecationReason() ?: parentClass.findConstructorParamter(this.name)?.getDeprecationReason()
24+
25+
internal fun KProperty<*>.getPropertyDescription(parentClass: KClass<*>): String? =
26+
this.getGraphQLDescription() ?: parentClass.findConstructorParamter(this.name)?.getGraphQLDescription()

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import kotlin.reflect.KType
66
import kotlin.reflect.full.createType
77
import kotlin.reflect.full.isSubclassOf
88

9-
internal fun KType.graphQLDescription(): String? = (classifier as? KClass<*>)?.graphQLDescription()
10-
119
@Throws(InvalidListTypeException::class)
1210
internal fun KType.getTypeOfFirstArgument(): KType =
1311
this.arguments.firstOrNull()?.type ?: throw InvalidListTypeException(this)

src/main/kotlin/com/expedia/graphql/schema/generator/SchemaGenerator.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ internal class SchemaGenerator(
9595
internal fun function(fn: KFunction<*>, target: Any? = null, abstract: Boolean = false) =
9696
functionTypeBuilder.function(fn, target, abstract)
9797

98-
internal fun property(prop: KProperty<*>) =
99-
propertyTypeBuilder.property(prop)
98+
internal fun property(prop: KProperty<*>, parentClass: KClass<*>) =
99+
propertyTypeBuilder.property(prop, parentClass)
100100

101101
internal fun listType(type: KType, inputType: Boolean) =
102102
listTypeBuilder.listType(type, inputType)
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,29 @@
11
package com.expedia.graphql.schema.generator
22

33
import com.expedia.graphql.schema.extensions.isGraphQLIgnored
4+
import com.expedia.graphql.schema.extensions.isPropertyGraphQLIgnored
45
import kotlin.reflect.KAnnotatedElement
56
import kotlin.reflect.KCallable
7+
import kotlin.reflect.KClass
68
import kotlin.reflect.KFunction
79
import kotlin.reflect.KProperty
810
import kotlin.reflect.KVisibility
911

1012
private typealias CallableFilter = (KCallable<*>) -> Boolean
1113
private typealias AnnotatedElementFilter = (KAnnotatedElement) -> Boolean
12-
private typealias PropertyFilter = (KProperty<*>) -> Boolean
14+
private typealias PropertyFilter = (KProperty<*>, KClass<*>) -> Boolean
1315
private typealias FunctionFilter = (KFunction<*>) -> Boolean
1416

1517
private val blackListFunctions: List<String> = listOf("annotationType", "toString", "copy", "equals", "hashCode")
1618
private val componentFunctionRegex = Regex("component([0-9]+)")
1719

1820
private val isPublic: CallableFilter = { it.visibility == KVisibility.PUBLIC }
21+
private val isPropertyPublic: PropertyFilter = { prop, _ -> isPublic(prop) }
1922
private val isNotGraphQLIgnored: AnnotatedElementFilter = { it.isGraphQLIgnored().not() }
23+
private val isPropertyNotGraphQLIgnored: PropertyFilter = { prop, parentClass -> prop.isPropertyGraphQLIgnored(parentClass).not() }
2024
private val isBlacklistedFunction: FunctionFilter = { blackListFunctions.contains(it.name) }
2125
private val isComponentFunction: FunctionFilter = { it.name.matches(componentFunctionRegex) }
2226
private val isNotBlackListed: FunctionFilter = { (isBlacklistedFunction(it) || isComponentFunction(it)).not() }
2327

24-
internal val propertyFilters: List<PropertyFilter> = listOf(isPublic, isNotGraphQLIgnored)
28+
internal val propertyFilters: List<PropertyFilter> = listOf(isPropertyPublic, isPropertyNotGraphQLIgnored)
2529
internal val functionFilters: List<FunctionFilter> = listOf(isPublic, isNotGraphQLIgnored, isNotBlackListed)

0 commit comments

Comments
 (0)