-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Assert matching response shapes in fields_will_merge #4347
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,26 +33,19 @@ def on_field(node, _parent) | |
|
||
private | ||
|
||
def field_conflicts | ||
@field_conflicts ||= Hash.new do |errors, field| | ||
errors[field] = GraphQL::StaticValidation::FieldsWillMergeError.new(kind: :field, field_name: field) | ||
end | ||
end | ||
|
||
def arg_conflicts | ||
@arg_conflicts ||= Hash.new do |errors, field| | ||
errors[field] = GraphQL::StaticValidation::FieldsWillMergeError.new(kind: :argument, field_name: field) | ||
def conflicts | ||
@conflicts ||= Hash.new do |h, error_type| | ||
h[error_type] = Hash.new do |h2, field_name| | ||
h2[field_name] = GraphQL::StaticValidation::FieldsWillMergeError.new(kind: error_type, field_name: field_name) | ||
end | ||
end | ||
end | ||
|
||
def setting_errors | ||
@field_conflicts = nil | ||
@arg_conflicts = nil | ||
|
||
@conflicts = nil | ||
yield | ||
# don't initialize these if they weren't initialized in the block: | ||
@field_conflicts && @field_conflicts.each_value { |error| add_error(error) } | ||
@arg_conflicts && @arg_conflicts.each_value { |error| add_error(error) } | ||
@conflicts && @conflicts.each_value { |error_type| error_type.each_value { |error| add_error(error) } } | ||
end | ||
|
||
def conflicts_within_selection_set(node, parent_type) | ||
|
@@ -221,7 +214,7 @@ def find_conflict(response_key, field1, field2, mutually_exclusive: false) | |
|
||
if !are_mutually_exclusive | ||
if node1.name != node2.name | ||
conflict = field_conflicts[response_key] | ||
conflict = conflicts[:field][response_key] | ||
|
||
conflict.add_conflict(node1, node1.name) | ||
conflict.add_conflict(node2, node2.name) | ||
|
@@ -230,7 +223,7 @@ def find_conflict(response_key, field1, field2, mutually_exclusive: false) | |
end | ||
|
||
if !same_arguments?(node1, node2) | ||
conflict = arg_conflicts[response_key] | ||
conflict = conflicts[:argument][response_key] | ||
|
||
conflict.add_conflict(node1, GraphQL::Language.serialize(serialize_field_args(node1))) | ||
conflict.add_conflict(node2, GraphQL::Language.serialize(serialize_field_args(node2))) | ||
|
@@ -239,13 +232,50 @@ def find_conflict(response_key, field1, field2, mutually_exclusive: false) | |
end | ||
end | ||
|
||
if !conflicts[:field].key?(response_key) && | ||
(t1 = field1.definition&.type) && | ||
(t2 = field2.definition&.type) && | ||
return_types_conflict?(t1, t2) | ||
|
||
conflict = conflicts[:return_type][response_key] | ||
conflict.add_conflict(node1, "`#{t1.to_type_signature}`") | ||
conflict.add_conflict(node2, "`#{t2.to_type_signature}`") | ||
|
||
@conflict_count += 1 | ||
end | ||
|
||
find_conflicts_between_sub_selection_sets( | ||
field1, | ||
field2, | ||
mutually_exclusive: are_mutually_exclusive, | ||
) | ||
end | ||
|
||
def return_types_conflict?(type1, type2) | ||
if type1.list? | ||
if type2.list? | ||
return_types_conflict?(type1.of_type, type2.of_type) | ||
else | ||
true | ||
end | ||
elsif type2.list? | ||
elsif type1.non_null? | ||
if type2.non_null? | ||
return_types_conflict?(type1.of_type, type2.of_type) | ||
else | ||
true | ||
end | ||
elsif type2.non_null? | ||
true | ||
elsif !type1.kind.fields? && !type2.kind.fields? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again comparing this with if (isLeafType(type1) || isLeafType(type2)) {
return type1 !== type2;
} So There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Revisiting this again today, I've noticed another issue with the My suggestion then would be to introduce a proper There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
type1 != type2 | ||
else | ||
# One or more of these are composite types, | ||
# their selections will be validated later on. | ||
false | ||
end | ||
end | ||
|
||
def find_conflicts_between_sub_selection_sets(field1, field2, mutually_exclusive:) | ||
return if field1.definition.nil? || | ||
field2.definition.nil? || | ||
|
@@ -344,7 +374,7 @@ def find_fields_and_fragments(selections, owner_type:, parents:, fields:, fragme | |
fields << Field.new(node, definition, owner_type, parents) | ||
when GraphQL::Language::Nodes::InlineFragment | ||
fragment_type = node.type ? context.warden.get_type(node.type.name) : owner_type | ||
find_fields_and_fragments(node.selections, parents: [*parents, fragment_type], owner_type: owner_type, fields: fields, fragment_spreads: fragment_spreads) if fragment_type | ||
find_fields_and_fragments(node.selections, parents: [*parents, fragment_type], owner_type: fragment_type, fields: fields, fragment_spreads: fragment_spreads) if fragment_type | ||
when GraphQL::Language::Nodes::FragmentSpread | ||
fragment_spreads << FragmentSpread.new(node.name, parents) | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comparing this with the graphql-js implementation... Shouldn't this return
true
?