32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 
     | 
    
      # File 'lib/graphql/schema/visibility/visit.rb', line 32
def visit_each(types: entry_point_types, directives: entry_point_directives)
  @unvisited_types && raise("Can't re-enter `visit_each` on this Visit (another visit is already in progress)")
  @unvisited_types = types
  @late_bound_types = []
  directives_to_visit = directives
  while !@unvisited_types.empty? || !@late_bound_types.empty?
    while (type = @unvisited_types.pop)
      if @visited_types.add?(type) && @visit_block.call(type)
        directives_to_visit.concat(type.directives)
        case type.kind.name
        when "OBJECT", "INTERFACE"
          type.interface_type_memberships.each do |itm|
            append_unvisited_type(type, itm.abstract_type)
          end
          if type.kind.interface?
            type.orphan_types.each do |orphan_type|
              append_unvisited_type(type, orphan_type)
            end
          end
          type.all_field_definitions.each do |field|
            field.ensure_loaded
            if @visit_block.call(field)
              directives_to_visit.concat(field.directives)
              append_unvisited_type(type, field.type.unwrap)
              field.all_argument_definitions.each do |argument|
                if @visit_block.call(argument)
                  directives_to_visit.concat(argument.directives)
                  append_unvisited_type(field, argument.type.unwrap)
                end
              end
            end
          end
        when "INPUT_OBJECT"
          type.all_argument_definitions.each do |argument|
            if @visit_block.call(argument)
              directives_to_visit.concat(argument.directives)
              append_unvisited_type(type, argument.type.unwrap)
            end
          end
        when "UNION"
          type.type_memberships.each do |tm|
            append_unvisited_type(type, tm.object_type)
          end
        when "ENUM"
          type.all_enum_value_definitions.each do |val|
            if @visit_block.call(val)
              directives_to_visit.concat(val.directives)
            end
          end
        when "SCALAR"
                  else
          raise "Invariant: unhandled type kind: #{type.kind.inspect}"
        end
      end
    end
    directives_to_visit.each do |dir|
      dir_class = dir.is_a?(Class) ? dir : dir.class
      if @visited_directives.add?(dir_class) && @visit_block.call(dir_class)
        dir_class.all_argument_definitions.each do |arg_defn|
          if @visit_block.call(arg_defn)
            directives_to_visit.concat(arg_defn.directives)
            append_unvisited_type(dir_class, arg_defn.type.unwrap)
          end
        end
      end
    end
    missed_late_types_streak = 0
    while (owner, late_type = @late_bound_types.shift)
      if (late_type.is_a?(String) && (type = Member::BuildType.constantize(type))) ||
          (late_type.is_a?(LateBoundType) && (type = @visited_types.find { |t| t.graphql_name == late_type.graphql_name }))
        missed_late_types_streak = 0         update_type_owner(owner, type)
        append_unvisited_type(owner, type)
      else
                missed_late_types_streak += 1
        @late_bound_types << [owner, late_type]
        if missed_late_types_streak == @late_bound_types.size
          raise UnresolvedLateBoundTypeError.new(type: late_type)
        end
      end
    end
  end
  @unvisited_types = nil
  nil
end
     |