Skip to content

Commit 3dc3af0

Browse files
committed
Fix method generation
1 parent 4deb98d commit 3dc3af0

File tree

3 files changed

+169
-168
lines changed

3 files changed

+169
-168
lines changed

lib/graphql/language/nodes.rb

+1-2
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,9 @@ def self.from_a(filename, line, col, #{(scalar_method_names + @children_methods.
296296
self.new(filename: filename, line: line, col: col, #{keywords.join(", ")})
297297
end
298298
RUBY
299-
300-
# rubocop:enable Development/NoEvalCop
301299
end
302300
end
301+
# rubocop:enable Development/NoEvalCop
303302
end
304303
end
305304

lib/graphql/language/static_visitor.rb

+69-68
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,75 @@ def visit
2121
@document
2222
end
2323
end
24+
25+
def on_document_children(document_node)
26+
document_node.children.each do |child_node|
27+
visit_method = child_node.visit_method
28+
public_send(visit_method, child_node, document_node)
29+
end
30+
end
31+
32+
def on_field_children(new_node)
33+
new_node.arguments.each do |arg_node| # rubocop:disable Development/ContextIsPassedCop
34+
on_argument(arg_node, new_node)
35+
end
36+
visit_directives(new_node)
37+
visit_selections(new_node)
38+
end
39+
40+
def visit_directives(new_node)
41+
new_node.directives.each do |dir_node|
42+
on_directive(dir_node, new_node)
43+
end
44+
end
45+
46+
def visit_selections(new_node)
47+
new_node.selections.each do |selection|
48+
case selection
49+
when GraphQL::Language::Nodes::Field
50+
on_field(selection, new_node)
51+
when GraphQL::Language::Nodes::InlineFragment
52+
on_inline_fragment(selection, new_node)
53+
when GraphQL::Language::Nodes::FragmentSpread
54+
on_fragment_spread(selection, new_node)
55+
else
56+
raise ArgumentError, "Invariant: unexpected field selection #{selection.class} (#{selection.inspect})"
57+
end
58+
end
59+
end
60+
61+
def on_fragment_definition_children(new_node)
62+
visit_directives(new_node)
63+
visit_selections(new_node)
64+
end
65+
66+
alias :on_inline_fragment_children :on_fragment_definition_children
67+
68+
def on_operation_definition_children(new_node)
69+
new_node.variables.each do |arg_node|
70+
on_variable_definition(arg_node, new_node)
71+
end
72+
visit_directives(new_node)
73+
visit_selections(new_node)
74+
end
75+
76+
def on_argument_children(new_node)
77+
new_node.children.each do |value_node|
78+
case value_node
79+
when Language::Nodes::VariableIdentifier
80+
on_variable_identifier(value_node, new_node)
81+
when Language::Nodes::InputObject
82+
on_input_object(value_node, new_node)
83+
when Language::Nodes::Enum
84+
on_enum(value_node, new_node)
85+
when Language::Nodes::NullValue
86+
on_null_value(value_node, new_node)
87+
else
88+
raise ArgumentError, "Invariant: unexpected argument value node #{value_node.class} (#{value_node.inspect})"
89+
end
90+
end
91+
end
92+
2493
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
2594

2695
# We don't use `alias` here because it breaks `super`
@@ -97,74 +166,6 @@ def #{node_method}(node, parent)
97166
end
98167

99168
# rubocop:disable Development/NoEvalCop
100-
101-
def on_document_children(document_node)
102-
document_node.children.each do |child_node|
103-
visit_method = child_node.visit_method
104-
public_send(visit_method, child_node, document_node)
105-
end
106-
end
107-
108-
def on_field_children(new_node)
109-
new_node.arguments.each do |arg_node| # rubocop:disable Development/ContextIsPassedCop
110-
on_argument(arg_node, new_node)
111-
end
112-
visit_directives(new_node)
113-
visit_selections(new_node)
114-
end
115-
116-
def visit_directives(new_node)
117-
new_node.directives.each do |dir_node|
118-
on_directive(dir_node, new_node)
119-
end
120-
end
121-
122-
def visit_selections(new_node)
123-
new_node.selections.each do |selection|
124-
case selection
125-
when GraphQL::Language::Nodes::Field
126-
on_field(selection, new_node)
127-
when GraphQL::Language::Nodes::InlineFragment
128-
on_inline_fragment(selection, new_node)
129-
when GraphQL::Language::Nodes::FragmentSpread
130-
on_fragment_spread(selection, new_node)
131-
else
132-
raise ArgumentError, "Invariant: unexpected field selection #{selection.class} (#{selection.inspect})"
133-
end
134-
end
135-
end
136-
137-
def on_fragment_definition_children(new_node)
138-
visit_directives(new_node)
139-
visit_selections(new_node)
140-
end
141-
142-
alias :on_inline_fragment_children :on_fragment_definition_children
143-
144-
def on_operation_definition_children(new_node)
145-
new_node.variables.each do |arg_node|
146-
on_variable_definition(arg_node, new_node)
147-
end
148-
visit_directives(new_node)
149-
visit_selections(new_node)
150-
end
151-
152-
def on_argument_children(new_node)
153-
new_node.children.each do |value_node|
154-
case value_node
155-
when Language::Nodes::VariableIdentifier
156-
on_variable_identifier(value_node, new_node)
157-
when Language::Nodes::InputObject
158-
on_input_object(value_node, new_node)
159-
when Language::Nodes::Enum
160-
on_enum(value_node, new_node)
161-
when Language::Nodes::NullValue
162-
on_null_value(value_node, new_node)
163-
else
164-
raise ArgumentError, "Invariant: unexpected argument value node #{value_node.class} (#{value_node.inspect})"
165-
end
166-
end
167-
end
168169
end
169170
end
170171
end

lib/graphql/language/visitor.rb

+99-98
Original file line numberDiff line numberDiff line change
@@ -60,104 +60,6 @@ def visit
6060
@document
6161
end
6262
end
63-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
64-
65-
# We don't use `alias` here because it breaks `super`
66-
def self.make_visit_methods(ast_node_class)
67-
node_method = ast_node_class.visit_method
68-
children_of_type = ast_node_class.children_of_type
69-
child_visit_method = :"#{node_method}_children"
70-
71-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
72-
# The default implementation for visiting an AST node.
73-
# It doesn't _do_ anything, but it continues to visiting the node's children.
74-
# To customize this hook, override one of its make_visit_methods (or the base method?)
75-
# in your subclasses.
76-
#
77-
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
78-
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
79-
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
80-
def #{node_method}(node, parent)
81-
if node.equal?(DELETE_NODE)
82-
# This might be passed to `super(DELETE_NODE, ...)`
83-
# by a user hook, don't want to keep visiting in that case.
84-
[node, parent]
85-
else
86-
new_node = node
87-
#{
88-
if method_defined?(child_visit_method)
89-
"new_node = #{child_visit_method}(new_node)"
90-
elsif children_of_type
91-
children_of_type.map do |child_accessor, child_class|
92-
"node.#{child_accessor}.each do |child_node|
93-
new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
94-
# Reassign `node` in case the child hook makes a modification
95-
if new_child_and_node.is_a?(Array)
96-
new_node = new_child_and_node[1]
97-
end
98-
end"
99-
end.join("\n")
100-
else
101-
""
102-
end
103-
}
104-
105-
if new_node.equal?(node)
106-
[node, parent]
107-
else
108-
[new_node, parent]
109-
end
110-
end
111-
end
112-
113-
def #{node_method}_with_modifications(node, parent)
114-
new_node_and_new_parent = #{node_method}(node, parent)
115-
apply_modifications(node, parent, new_node_and_new_parent)
116-
end
117-
RUBY
118-
end
119-
120-
[
121-
Language::Nodes::Argument,
122-
Language::Nodes::Directive,
123-
Language::Nodes::DirectiveDefinition,
124-
Language::Nodes::DirectiveLocation,
125-
Language::Nodes::Document,
126-
Language::Nodes::Enum,
127-
Language::Nodes::EnumTypeDefinition,
128-
Language::Nodes::EnumTypeExtension,
129-
Language::Nodes::EnumValueDefinition,
130-
Language::Nodes::Field,
131-
Language::Nodes::FieldDefinition,
132-
Language::Nodes::FragmentDefinition,
133-
Language::Nodes::FragmentSpread,
134-
Language::Nodes::InlineFragment,
135-
Language::Nodes::InputObject,
136-
Language::Nodes::InputObjectTypeDefinition,
137-
Language::Nodes::InputObjectTypeExtension,
138-
Language::Nodes::InputValueDefinition,
139-
Language::Nodes::InterfaceTypeDefinition,
140-
Language::Nodes::InterfaceTypeExtension,
141-
Language::Nodes::ListType,
142-
Language::Nodes::NonNullType,
143-
Language::Nodes::NullValue,
144-
Language::Nodes::ObjectTypeDefinition,
145-
Language::Nodes::ObjectTypeExtension,
146-
Language::Nodes::OperationDefinition,
147-
Language::Nodes::ScalarTypeDefinition,
148-
Language::Nodes::ScalarTypeExtension,
149-
Language::Nodes::SchemaDefinition,
150-
Language::Nodes::SchemaExtension,
151-
Language::Nodes::TypeName,
152-
Language::Nodes::UnionTypeDefinition,
153-
Language::Nodes::UnionTypeExtension,
154-
Language::Nodes::VariableDefinition,
155-
Language::Nodes::VariableIdentifier,
156-
].each do |ast_node_class|
157-
make_visit_methods(ast_node_class)
158-
end
159-
160-
# rubocop:enable Development/NoEvalCop
16163

16264
def on_document_children(document_node)
16365
new_node = document_node
@@ -259,6 +161,105 @@ def on_argument_children(new_node)
259161
new_node
260162
end
261163

164+
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
165+
166+
# We don't use `alias` here because it breaks `super`
167+
def self.make_visit_methods(ast_node_class)
168+
node_method = ast_node_class.visit_method
169+
children_of_type = ast_node_class.children_of_type
170+
child_visit_method = :"#{node_method}_children"
171+
172+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
173+
# The default implementation for visiting an AST node.
174+
# It doesn't _do_ anything, but it continues to visiting the node's children.
175+
# To customize this hook, override one of its make_visit_methods (or the base method?)
176+
# in your subclasses.
177+
#
178+
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
179+
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
180+
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
181+
def #{node_method}(node, parent)
182+
if node.equal?(DELETE_NODE)
183+
# This might be passed to `super(DELETE_NODE, ...)`
184+
# by a user hook, don't want to keep visiting in that case.
185+
[node, parent]
186+
else
187+
new_node = node
188+
#{
189+
if method_defined?(child_visit_method)
190+
"new_node = #{child_visit_method}(new_node)"
191+
elsif children_of_type
192+
children_of_type.map do |child_accessor, child_class|
193+
"node.#{child_accessor}.each do |child_node|
194+
new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
195+
# Reassign `node` in case the child hook makes a modification
196+
if new_child_and_node.is_a?(Array)
197+
new_node = new_child_and_node[1]
198+
end
199+
end"
200+
end.join("\n")
201+
else
202+
""
203+
end
204+
}
205+
206+
if new_node.equal?(node)
207+
[node, parent]
208+
else
209+
[new_node, parent]
210+
end
211+
end
212+
end
213+
214+
def #{node_method}_with_modifications(node, parent)
215+
new_node_and_new_parent = #{node_method}(node, parent)
216+
apply_modifications(node, parent, new_node_and_new_parent)
217+
end
218+
RUBY
219+
end
220+
221+
[
222+
Language::Nodes::Argument,
223+
Language::Nodes::Directive,
224+
Language::Nodes::DirectiveDefinition,
225+
Language::Nodes::DirectiveLocation,
226+
Language::Nodes::Document,
227+
Language::Nodes::Enum,
228+
Language::Nodes::EnumTypeDefinition,
229+
Language::Nodes::EnumTypeExtension,
230+
Language::Nodes::EnumValueDefinition,
231+
Language::Nodes::Field,
232+
Language::Nodes::FieldDefinition,
233+
Language::Nodes::FragmentDefinition,
234+
Language::Nodes::FragmentSpread,
235+
Language::Nodes::InlineFragment,
236+
Language::Nodes::InputObject,
237+
Language::Nodes::InputObjectTypeDefinition,
238+
Language::Nodes::InputObjectTypeExtension,
239+
Language::Nodes::InputValueDefinition,
240+
Language::Nodes::InterfaceTypeDefinition,
241+
Language::Nodes::InterfaceTypeExtension,
242+
Language::Nodes::ListType,
243+
Language::Nodes::NonNullType,
244+
Language::Nodes::NullValue,
245+
Language::Nodes::ObjectTypeDefinition,
246+
Language::Nodes::ObjectTypeExtension,
247+
Language::Nodes::OperationDefinition,
248+
Language::Nodes::ScalarTypeDefinition,
249+
Language::Nodes::ScalarTypeExtension,
250+
Language::Nodes::SchemaDefinition,
251+
Language::Nodes::SchemaExtension,
252+
Language::Nodes::TypeName,
253+
Language::Nodes::UnionTypeDefinition,
254+
Language::Nodes::UnionTypeExtension,
255+
Language::Nodes::VariableDefinition,
256+
Language::Nodes::VariableIdentifier,
257+
].each do |ast_node_class|
258+
make_visit_methods(ast_node_class)
259+
end
260+
261+
# rubocop:enable Development/NoEvalCop
262+
262263
private
263264

264265
def apply_modifications(node, parent, new_node_and_new_parent)

0 commit comments

Comments
 (0)