Skip to content

Commit 7a81306

Browse files
author
Shane Myrick
authored
fix: abstract classes as input are invalid (#223)
* fix: abstract classes as input are invalid * update unit tests for detekt
1 parent b53195d commit 7a81306

File tree

9 files changed

+41
-17
lines changed

9 files changed

+41
-17
lines changed

src/main/kotlin/com/expedia/graphql/generator/TypeBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ internal open class TypeBuilder constructor(protected val generator: SchemaGener
5151
kClass.isEnum() -> @Suppress("UNCHECKED_CAST") (generator.enumType(kClass as KClass<Enum<*>>))
5252
kClass.isListType() -> generator.listType(type, inputType)
5353
kClass.isUnion() -> generator.unionType(kClass)
54-
kClass.isInterface() || kClass.isAbstract -> generator.interfaceType(kClass)
54+
kClass.isInterface() -> generator.interfaceType(kClass)
5555
inputType -> generator.inputObjectType(kClass)
5656
else -> generator.objectType(kClass)
5757
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ internal fun KClass<*>.getValidSuperclasses(hooks: SchemaGeneratorHooks): List<K
3939
internal fun KClass<*>.findConstructorParamter(name: String): KParameter? =
4040
this.primaryConstructor?.findParameterByName(name)
4141

42-
internal fun KClass<*>.isInterface(): Boolean = this.java.isInterface
42+
internal fun KClass<*>.isInterface(): Boolean = this.java.isInterface || this.isAbstract
4343

4444
internal fun KClass<*>.isUnion(): Boolean =
4545
this.isInterface() && this.declaredMemberProperties.isEmpty() && this.declaredMemberFunctions.isEmpty()
@@ -67,3 +67,5 @@ internal fun KClass<*>.getSimpleName(isInputClass: Boolean = false): String {
6767
internal fun KClass<*>.getQualifiedName(): String = this.qualifiedName.orEmpty()
6868

6969
internal fun KClass<*>.isPublic(): Boolean = this.visibility == KVisibility.PUBLIC
70+
71+
internal fun KClass<*>.isNotPublic(): Boolean = this.isPublic().not()

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,20 @@ import kotlin.reflect.KProperty
55

66
internal fun KProperty<*>.isPropertyGraphQLID(parentClass: KClass<*>): Boolean = when {
77
this.isGraphQLID() -> true
8-
parentClass.findConstructorParamter(this.name)
9-
?.isGraphQLID()
10-
.isTrue() -> true
8+
getConstructorParameter(parentClass)?.isGraphQLID().isTrue() -> true
119
else -> false
1210
}
1311

1412
internal fun KProperty<*>.isPropertyGraphQLIgnored(parentClass: KClass<*>): Boolean = when {
1513
this.isGraphQLIgnored() -> true
16-
parentClass.findConstructorParamter(this.name)
17-
?.isGraphQLIgnored()
18-
.isTrue() -> true
14+
getConstructorParameter(parentClass)?.isGraphQLIgnored().isTrue() -> true
1915
else -> false
2016
}
2117

2218
internal fun KProperty<*>.getPropertyDeprecationReason(parentClass: KClass<*>): String? =
23-
this.getDeprecationReason() ?: parentClass.findConstructorParamter(this.name)?.getDeprecationReason()
19+
this.getDeprecationReason() ?: getConstructorParameter(parentClass)?.getDeprecationReason()
2420

2521
internal fun KProperty<*>.getPropertyDescription(parentClass: KClass<*>): String? =
26-
this.getGraphQLDescription() ?: parentClass.findConstructorParamter(this.name)?.getGraphQLDescription()
22+
this.getGraphQLDescription() ?: getConstructorParameter(parentClass)?.getGraphQLDescription()
23+
24+
private fun KProperty<*>.getConstructorParameter(parentClass: KClass<*>) = parentClass.findConstructorParamter(this.name)

src/main/kotlin/com/expedia/graphql/generator/filters/superclassFilters.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import kotlin.reflect.KClass
88
private typealias SuperclassFilter = (KClass<*>) -> Boolean
99

1010
private val isPublic: SuperclassFilter = { it.isPublic() }
11-
private val isInterface: SuperclassFilter = { it.isInterface() || it.isAbstract }
11+
private val isInterface: SuperclassFilter = { it.isInterface() }
1212
private val isNotUnion: SuperclassFilter = { it.isUnion().not() }
1313

1414
internal val superclassFilters: List<SuperclassFilter> = listOf(isPublic, isInterface, isNotUnion)

src/main/kotlin/com/expedia/graphql/generator/types/MutationBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import com.expedia.graphql.exceptions.InvalidMutationTypeException
55
import com.expedia.graphql.generator.SchemaGenerator
66
import com.expedia.graphql.generator.TypeBuilder
77
import com.expedia.graphql.generator.extensions.getValidFunctions
8-
import com.expedia.graphql.generator.extensions.isPublic
8+
import com.expedia.graphql.generator.extensions.isNotPublic
99
import graphql.schema.GraphQLObjectType
1010

1111
internal class MutationBuilder(generator: SchemaGenerator) : TypeBuilder(generator) {
@@ -20,7 +20,7 @@ internal class MutationBuilder(generator: SchemaGenerator) : TypeBuilder(generat
2020
mutationBuilder.name(config.topLevelNames.mutation)
2121

2222
for (mutation in mutations) {
23-
if (mutation.kClass.isPublic().not()) {
23+
if (mutation.kClass.isNotPublic()) {
2424
throw InvalidMutationTypeException(mutation.kClass)
2525
}
2626

src/main/kotlin/com/expedia/graphql/generator/types/QueryBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import com.expedia.graphql.exceptions.InvalidSchemaException
66
import com.expedia.graphql.generator.SchemaGenerator
77
import com.expedia.graphql.generator.TypeBuilder
88
import com.expedia.graphql.generator.extensions.getValidFunctions
9-
import com.expedia.graphql.generator.extensions.isPublic
9+
import com.expedia.graphql.generator.extensions.isNotPublic
1010
import graphql.schema.GraphQLObjectType
1111

1212
internal class QueryBuilder(generator: SchemaGenerator) : TypeBuilder(generator) {
@@ -22,7 +22,7 @@ internal class QueryBuilder(generator: SchemaGenerator) : TypeBuilder(generator)
2222
queryBuilder.name(config.topLevelNames.query)
2323

2424
for (query in queries) {
25-
if (query.kClass.isPublic().not()) {
25+
if (query.kClass.isNotPublic()) {
2626
throw InvalidQueryTypeException(query.kClass)
2727
}
2828

src/main/kotlin/com/expedia/graphql/generator/types/SubscriptionBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import com.expedia.graphql.exceptions.InvalidSubscriptionTypeException
55
import com.expedia.graphql.generator.SchemaGenerator
66
import com.expedia.graphql.generator.TypeBuilder
77
import com.expedia.graphql.generator.extensions.getValidFunctions
8-
import com.expedia.graphql.generator.extensions.isPublic
8+
import com.expedia.graphql.generator.extensions.isNotPublic
99
import graphql.schema.GraphQLObjectType
1010

1111
internal class SubscriptionBuilder(generator: SchemaGenerator) : TypeBuilder(generator) {
@@ -20,7 +20,7 @@ internal class SubscriptionBuilder(generator: SchemaGenerator) : TypeBuilder(gen
2020
subscriptionBuilder.name(config.topLevelNames.subscription)
2121

2222
for (subscription in subscriptions) {
23-
if (subscription.kClass.isPublic().not()) {
23+
if (subscription.kClass.isNotPublic()) {
2424
throw InvalidSubscriptionTypeException(subscription.kClass)
2525
}
2626

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ open class KClassExtensionsTest {
198198
@Test
199199
fun `test graphql interface extension`() {
200200
assertTrue(TestInterface::class.isInterface())
201+
assertTrue(SomeAbstractClass::class.isInterface())
201202
assertFalse(MyTestClass::class.isInterface())
202203
}
203204

@@ -246,4 +247,12 @@ open class KClassExtensionsTest {
246247
assertFalse(MyProtectedClass::class.isPublic())
247248
assertFalse(MyTestClass::class.isPublic())
248249
}
250+
251+
@Test
252+
fun isNotPublic() {
253+
assertFalse(MyPublicClass::class.isNotPublic())
254+
assertTrue(MyInternalClass::class.isNotPublic())
255+
assertTrue(MyProtectedClass::class.isNotPublic())
256+
assertTrue(MyTestClass::class.isNotPublic())
257+
}
249258
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,19 @@ internal class KParameterExtensionsKtTest {
2323
val value: String
2424
}
2525

26+
internal abstract class MyAbstractClass {
27+
28+
abstract val implementMe: String
29+
30+
val value: String = "test"
31+
}
32+
2633
internal class Container {
2734

2835
internal fun interfaceInput(myInterface: MyInterface) = myInterface
2936

37+
internal fun absctractInput(myAbstractClass: MyAbstractClass) = myAbstractClass
38+
3039
internal fun noDescription(myClass: MyClass) = myClass
3140

3241
internal fun paramDescription(@GraphQLDescription("param description") myClass: MyClass) = myClass
@@ -77,6 +86,12 @@ internal class KParameterExtensionsKtTest {
7786
assertTrue(param?.isInterface().isTrue())
7887
}
7988

89+
@Test
90+
fun `abstract class input is invalid`() {
91+
val param = Container::absctractInput.findParameterByName("myAbstractClass")
92+
assertTrue(param?.isInterface().isTrue())
93+
}
94+
8095
@Test
8196
fun `valid DataFetchingEnvironment passes`() {
8297
val param = Container::dataFetchingEnvironment.findParameterByName("environment")

0 commit comments

Comments
 (0)