Skip to content

Commit fd1ce3c

Browse files
authored
Fix IndexOutOfBoundsException in keyFields validation (#6748)
1 parent f56108c commit fd1ce3c

File tree

3 files changed

+33
-7
lines changed

3 files changed

+33
-7
lines changed

libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo/ast/internal/SchemaValidationScope.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -951,20 +951,22 @@ private fun ValidationScope.keyFields(
951951
return cached
952952
}
953953

954-
val (directives, interfaces) = when (typeDefinition) {
954+
val (directives, allInterfaces) = when (typeDefinition) {
955955
is GQLObjectTypeDefinition -> typeDefinition.directives to typeDefinition.implementsInterfaces
956956
is GQLInterfaceTypeDefinition -> typeDefinition.directives to typeDefinition.implementsInterfaces
957957
else -> error("Unexpected type definition $typeDefinition")
958958
}
959959

960-
val interfacesKeyFields = interfaces.map { keyFields(typeDefinitions[it]!!, keyFieldsCache) }
961-
.filter { it.isNotEmpty() }
960+
val interfacesToKeyFields: Map<String, Set<String>> = allInterfaces.associate { it to keyFields(typeDefinitions[it]!!, keyFieldsCache) }
961+
.filter { it.value.isNotEmpty() }
962+
val interfaces = interfacesToKeyFields.keys.toList()
963+
val interfacesKeyFields = interfacesToKeyFields.values.toList()
962964

963965
val distinct = interfacesKeyFields.distinct()
964966
if (distinct.size > 1) {
965-
val extra = interfaces.indices.map {
967+
val extra = interfaces.indices.joinToString("\n") {
966968
"${interfaces[it]}: ${interfacesKeyFields[it]}"
967-
}.joinToString("\n")
969+
}
968970

969971
registerIssue(
970972
message = "Apollo: Type '${typeDefinition.name}' cannot inherit different keys from different interfaces:\n$extra",
@@ -975,9 +977,9 @@ private fun ValidationScope.keyFields(
975977
val keyFields = directives.filter { originalDirectiveName(it.name) == TYPE_POLICY }.toKeyFields()
976978
val ret = if (keyFields.isNotEmpty()) {
977979
if (distinct.isNotEmpty()) {
978-
val extra = interfaces.indices.map {
980+
val extra = interfaces.indices.joinToString("\n") {
979981
"${interfaces[it]}: ${interfacesKeyFields[it]}"
980-
}.joinToString("\n")
982+
}
981983

982984
registerIssue(
983985
message = "Type '${typeDefinition.name}' cannot have key fields since it implements the following interfaces which also have key fields: $extra",

libraries/apollo-compiler/src/test/validation/schema/typepolicy-clash.expected

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
extend schema @link(url: "https://specs.apollo.dev/kotlin_labs/v0.5/", import: ["@typePolicy"])
2+
3+
type Query {
4+
x: Int
5+
}
6+
7+
interface UnifiedEntity {
8+
unifiedEntityId: ID!
9+
}
10+
11+
interface OtherInterface {
12+
otherField: String!
13+
}
14+
15+
interface Video implements UnifiedEntity & OtherInterface {
16+
unifiedEntityId: ID!
17+
otherField: String!
18+
videoId: ID!
19+
}
20+
21+
extend interface UnifiedEntity @typePolicy(keyFields: "unifiedEntityId")
22+
extend interface Video @typePolicy(keyFields: "videoId")

0 commit comments

Comments
 (0)