Skip to content

[4.x] Add key fields to selections even when they're already selected with an alias (#6503) #6544

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 2 commits into from
May 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.apollographql.apollo.ast.Schema
import com.apollographql.apollo.ast.definitionFromScope
import com.apollographql.apollo.ast.isAbstract
import com.apollographql.apollo.ast.rawType
import com.apollographql.apollo.ast.responseName
import com.apollographql.apollo.ast.rootTypeDefinition
import com.apollographql.apollo.compiler.ADD_TYPENAME_ALWAYS
import com.apollographql.apollo.compiler.ADD_TYPENAME_IF_ABSTRACT
Expand Down Expand Up @@ -94,7 +95,7 @@ private fun List<GQLSelection>.addRequiredFields(
requiredFieldNames.add("__typename")
}

val fieldNames = parentFields + selectionSet.filterIsInstance<GQLField>().map { it.name }.toSet()
val fieldNames = parentFields + selectionSet.filterIsInstance<GQLField>().map { it.responseName() }.toSet()

var newSelections = selectionSet.map {
when (it) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ internal fun checkKeyFields(
schema: Schema,
allFragmentDefinitions: Map<String, GQLFragmentDefinition>,
) {
CheckKeyFieldsScope(schema, allFragmentDefinitions).checkField("Fragment(${fragmentDefinition.name})", fragmentDefinition.selections, fragmentDefinition.typeCondition.name)
CheckKeyFieldsScope(schema, allFragmentDefinitions).checkField(
"Fragment(${fragmentDefinition.name})",
fragmentDefinition.selections,
fragmentDefinition.typeCondition.name
)
}

private fun CheckKeyFieldsScope.checkField(
Expand All @@ -61,9 +65,9 @@ private fun CheckKeyFieldsScope.checkFieldSet(path: String, selections: List<GQL

if (implementedTypes.contains(parentType)) {
// only check types that are actually possible
val fieldNames = mergedFields.map { it.first().field }
.filter { it.alias == null }
.map { it.name }.toSet()
val fieldNames = mergedFields
.flatMap { it.filter { it.field.alias == null }.map { it.field.name } }
.toSet()
val keyFieldNames = keyFields(possibleType)

val missingFieldNames = keyFieldNames.subtract(fieldNames)
Expand Down Expand Up @@ -101,13 +105,15 @@ private fun CheckKeyFieldsScope.collectFields(

listOf(FieldWithParent(it, parentType))
}

is GQLInlineFragment -> {
if (it.directives.hasCondition()) {
return@flatMap emptyList()
}

collectFields(it.selections, it.typeCondition?.name ?: parentType, implementedTypes)
}

is GQLFragmentSpread -> {
if (it.directives.hasCondition()) {
return@flatMap emptyList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// If you updated the codegen and test fixtures, you should commit this file too.

Test: Total LOC:
aggregate-all 204064
aggregate-kotlin-responseBased 65403
aggregate-kotlin-operationBased 41356
aggregate-all 206516
aggregate-kotlin-responseBased 66142
aggregate-kotlin-operationBased 42037
aggregate-kotlin-compat 0
aggregate-java-operationBased 97305
aggregate-java-operationBased 98337

java-operationBased-fragments_with_defer_and_include_directives 5624
kotlin-operationBased-fragments_with_defer_and_include_directives 3369
Expand Down Expand Up @@ -69,6 +69,7 @@ kotlin-responseBased-named_fragment_with_variables
java-operationBased-inline_fragments_with_friends 1048
java-operationBased-operationbased2_ex8 1046
kotlin-responseBased-simple_fragment_with_inline_fragments 1042
java-operationBased-typepolicy 1032
kotlin-operationBased-root_query_fragment_with_nested_fragments 1028
java-operationBased-custom_scalar_type 1022
kotlin-operationBased-simple_fragment 1021
Expand Down Expand Up @@ -119,6 +120,7 @@ kotlin-responseBased-root_query_inline_fragment
kotlin-responseBased-simple_union 762
java-operationBased-typename_always_first 758
java-operationBased-interface_on_interface 740
kotlin-responseBased-typepolicy 739
kotlin-responseBased-fragments_same_type_condition 731
kotlin-operationBased-inline_fragments_with_friends 726
java-operationBased-input_object_variable_and_argument 724
Expand All @@ -129,6 +131,7 @@ kotlin-operationBased-simple_fragment_with_inline_fragments
java-operationBased-interface_always_nested 687
kotlin-operationBased-fragment_spread_with_nested_fields 686
kotlin-responseBased-input_object_variable_and_argument_with_generated_methods 686
kotlin-operationBased-typepolicy 681
kotlin-responseBased-used_arguments 673
kotlin-responseBased-union_fragment 671
java-operationBased-capitalized_fields 670
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
query GetA {
a {
...AFragment1
}
}

fragment AFragment1 on A {
foo
...AFragment2
}

fragment AFragment2 on A {
bar
myId: id
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading