class GraphQL::StaticValidation::FieldsWillMerge

def find_conflicts(field_map, context)

def find_conflicts(field_map, context)
  field_map.each do |name, ast_fields|
    comparison = FieldDefinitionComparison.new(name, ast_fields, context)
    context.errors.push(*comparison.errors)
    subfield_map = {}
    visited_fragments = []
    ast_fields.each do |defn|
      gather_fields_by_name(defn.selections, subfield_map, visited_fragments, context)
    end
    find_conflicts(subfield_map, context)
  end
end

def gather_fields_by_name(fields, field_map, visited_fragments, context)

def gather_fields_by_name(fields, field_map, visited_fragments, context)
  fields.each do |field|
    if field.is_a?(GraphQL::Language::Nodes::InlineFragment)
      next_fields = field.selections
    elsif field.is_a?(GraphQL::Language::Nodes::FragmentSpread)
      if visited_fragments.include?(field.name)
        next
      else
        visited_fragments << field.name
      end
      fragment_defn = context.fragments[field.name]
      next_fields = fragment_defn ? fragment_defn.selections : []
    else
      name_in_selection = field.alias || field.name
      field_map[name_in_selection] ||= []
      field_map[name_in_selection].push(field)
      next_fields = []
    end
    gather_fields_by_name(next_fields, field_map, visited_fragments, context)
  end
  field_map
end

def validate(context)

def validate(context)
  fragments = {}
  has_selections = []
  visitor = context.visitor
  visitor[GraphQL::Language::Nodes::OperationDefinition] << -> (node, parent) {
    if node.selections.any?
      has_selections << node
    end
  }
  visitor[GraphQL::Language::Nodes::Document].leave << -> (node, parent) {
    has_selections.each { |node|
      field_map = gather_fields_by_name(node.selections, {}, [], context)
      find_conflicts(field_map, context)
    }
  }
end