graphql 2.0.26 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/relay.rb +18 -1
  3. data/lib/graphql/execution/interpreter/runtime.rb +23 -21
  4. data/lib/graphql/language/document_from_schema_definition.rb +6 -16
  5. data/lib/graphql/language/lexer.rb +86 -56
  6. data/lib/graphql/language/nodes.rb +1 -1
  7. data/lib/graphql/language/parser.rb +706 -691
  8. data/lib/graphql/language/parser.y +1 -0
  9. data/lib/graphql/language/printer.rb +233 -145
  10. data/lib/graphql/language/sanitized_printer.rb +14 -21
  11. data/lib/graphql/language/visitor.rb +18 -81
  12. data/lib/graphql/pagination/connection.rb +23 -1
  13. data/lib/graphql/query.rb +2 -19
  14. data/lib/graphql/rake_task.rb +3 -12
  15. data/lib/graphql/schema/addition.rb +6 -0
  16. data/lib/graphql/schema/field/scope_extension.rb +7 -1
  17. data/lib/graphql/schema/field.rb +1 -1
  18. data/lib/graphql/schema/member/scoped.rb +19 -0
  19. data/lib/graphql/schema/object.rb +8 -0
  20. data/lib/graphql/schema/printer.rb +8 -7
  21. data/lib/graphql/schema/resolver.rb +10 -8
  22. data/lib/graphql/schema/subscription.rb +11 -4
  23. data/lib/graphql/schema/validator.rb +1 -1
  24. data/lib/graphql/schema/warden.rb +3 -34
  25. data/lib/graphql/schema.rb +4 -20
  26. data/lib/graphql/static_validation/validation_context.rb +0 -3
  27. data/lib/graphql/static_validation.rb +0 -1
  28. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -1
  29. data/lib/graphql/subscriptions.rb +11 -6
  30. data/lib/graphql/types/relay/connection_behaviors.rb +19 -2
  31. data/lib/graphql/types/relay/edge_behaviors.rb +7 -0
  32. data/lib/graphql/version.rb +1 -1
  33. data/lib/graphql.rb +0 -1
  34. metadata +2 -4
  35. data/lib/graphql/filter.rb +0 -59
  36. data/lib/graphql/static_validation/type_stack.rb +0 -216
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b25908e65f82d9c17e76e1f38b874e882c124b7102dc7ae2cb3caf4e819aa370
4
- data.tar.gz: d3933abea4a559db3767c6a1ea3f37401432a7fd67842df6c9bd3e28e4034a8d
3
+ metadata.gz: 785d064bf9279c1c66291e629607bbfe14f33ea0a8ad3e22549d253116159f81
4
+ data.tar.gz: a66884908e066f99293c3171aa1856977ba01fde58dca3a65a978ef025de8f32
5
5
  SHA512:
6
- metadata.gz: a8a85cb8ee54143b1ed00b6aa030479a1b48e164142e93e6b1e95f0f8cb44da36fcd1f3b53470f8edb783f43d469fd4e2dafa505217440832eb0d92165107239
7
- data.tar.gz: dc61c951d84cc9199910145230cf55691d4fdb3a8f243b0e9f5dd9ee78c498a739de3d0bb72a65ade0cab07a9310a072dc7855ad5943425e778bd9b79f182e67
6
+ metadata.gz: f27e18f66f871cde5a6aedfea89621e57014c02062736b55aa86ebc4f64bdec83de93dca83c4aaede60c321113f4099efeab362cc3d4a2047d725e5ec2e7d73b
7
+ data.tar.gz: 4071a8921d60279b5ffc3ba11bb653e07596a9a97c0bab783c6a183558ff632996431d365052c27ea571b0b0c3a6a267f3cc10d1d4eff202eec513fc469f094e
@@ -6,7 +6,24 @@ module Graphql
6
6
  # Add Node, `node(id:)`, and `nodes(ids:)`
7
7
  template("node_type.erb", "#{options[:directory]}/types/node_type.rb")
8
8
  in_root do
9
- fields = " # Add `node(id: ID!) and `nodes(ids: [ID!]!)`\n include GraphQL::Types::Relay::HasNodeField\n include GraphQL::Types::Relay::HasNodesField\n\n"
9
+ fields = <<-RUBY
10
+ field :node, Types::NodeType, null: true, description: "Fetches an object given its ID." do
11
+ argument :id, ID, required: true, description: "ID of the object."
12
+ end
13
+
14
+ def node(id:)
15
+ context.schema.object_from_id(id, context)
16
+ end
17
+
18
+ field :nodes, [Types::NodeType, null: true], null: true, description: "Fetches a list of objects given a list of IDs." do
19
+ argument :ids, [ID], required: true, description: "IDs of the objects."
20
+ end
21
+
22
+ def nodes(ids:)
23
+ ids.map { |id| context.schema.object_from_id(id, context) }
24
+ end
25
+
26
+ RUBY
10
27
  inject_into_file "#{options[:directory]}/types/query_type.rb", fields, after: /class .*QueryType\s*<\s*[^\s]+?\n/m, force: false
11
28
  end
12
29
 
@@ -15,10 +15,11 @@ module GraphQL
15
15
  @current_arguments = nil
16
16
  @current_result_name = nil
17
17
  @current_result = nil
18
+ @was_authorized_by_scope_items = nil
18
19
  end
19
20
 
20
21
  attr_accessor :current_result, :current_result_name,
21
- :current_arguments, :current_field, :current_object
22
+ :current_arguments, :current_field, :current_object, :was_authorized_by_scope_items
22
23
  end
23
24
 
24
25
  module GraphQLResult
@@ -244,6 +245,7 @@ module GraphQL
244
245
  root_operation = query.selected_operation
245
246
  root_op_type = root_operation.operation_type || "query"
246
247
  root_type = schema.root_type_for_operation(root_op_type)
248
+
247
249
  st = get_current_runtime_state
248
250
  st.current_object = query.root_value
249
251
  st.current_result = @response
@@ -426,12 +428,6 @@ module GraphQL
426
428
  end
427
429
  end
428
430
 
429
- return_type = field_defn.type
430
-
431
- # This seems janky, but we need to know
432
- # the field's return type at this path in order
433
- # to propagate `null`
434
- return_type_non_null = return_type.non_null?
435
431
  # Set this before calling `run_with_directives`, so that the directive can have the latest path
436
432
  st = get_current_runtime_state
437
433
  st.current_field = field_defn
@@ -441,26 +437,27 @@ module GraphQL
441
437
  if is_introspection
442
438
  owner_object = field_defn.owner.wrap(owner_object, context)
443
439
  end
444
-
440
+ return_type = field_defn.type
445
441
  total_args_count = field_defn.arguments(context).size
446
442
  if total_args_count == 0
447
443
  resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
448
444
  if field_defn.extras.size == 0
449
445
  evaluate_selection_with_resolved_keyword_args(
450
- NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null
446
+ NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type.non_null?
451
447
  )
452
448
  else
453
- evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null)
449
+ evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type)
454
450
  end
455
451
  else
456
452
  @query.arguments_cache.dataload_for(ast_node, field_defn, owner_object) do |resolved_arguments|
457
- evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null)
453
+ evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type)
458
454
  end
459
455
  end
460
456
  end
461
457
 
462
- def evaluate_selection_with_args(arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type, return_type_non_null) # rubocop:disable Metrics/ParameterLists
458
+ def evaluate_selection_with_args(arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type) # rubocop:disable Metrics/ParameterLists
463
459
  after_lazy(arguments, field: field_defn, ast_node: ast_node, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result) do |resolved_arguments|
460
+ return_type_non_null = return_type.non_null?
464
461
  if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
465
462
  continue_value(resolved_arguments, owner_type, field_defn, return_type_non_null, ast_node, result_name, selection_result)
466
463
  next
@@ -553,7 +550,10 @@ module GraphQL
553
550
  after_lazy(app_result, field: field_defn, ast_node: ast_node, owner_object: object, arguments: resolved_arguments, result_name: result_name, result: selection_result) do |inner_result|
554
551
  continue_value = continue_value(inner_result, owner_type, field_defn, return_type_non_null, ast_node, result_name, selection_result)
555
552
  if HALT != continue_value
556
- continue_field(continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, resolved_arguments, result_name, selection_result)
553
+ st = get_current_runtime_state
554
+ was_scoped = st.was_authorized_by_scope_items
555
+ st.was_authorized_by_scope_items = nil
556
+ continue_field(continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, resolved_arguments, result_name, selection_result, was_scoped)
557
557
  end
558
558
  end
559
559
  end
@@ -733,7 +733,7 @@ module GraphQL
733
733
  # Location information from `path` and `ast_node`.
734
734
  #
735
735
  # @return [Lazy, Array, Hash, Object] Lazy, Array, and Hash are all traversed to resolve lazy values later
736
- def continue_field(value, owner_type, field, current_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
736
+ def continue_field(value, owner_type, field, current_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result, was_scoped) # rubocop:disable Metrics/ParameterLists
737
737
  if current_type.non_null?
738
738
  current_type = current_type.of_type
739
739
  is_non_null = true
@@ -767,12 +767,12 @@ module GraphQL
767
767
  set_result(selection_result, result_name, nil, false, is_non_null)
768
768
  nil
769
769
  else
770
- continue_field(resolved_value, owner_type, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result)
770
+ continue_field(resolved_value, owner_type, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result, was_scoped)
771
771
  end
772
772
  end
773
773
  when "OBJECT"
774
774
  object_proxy = begin
775
- current_type.wrap(value, context)
775
+ was_scoped ? current_type.wrap_scoped(value, context) : current_type.wrap(value, context)
776
776
  rescue GraphQL::ExecutionError => err
777
777
  err
778
778
  end
@@ -804,7 +804,6 @@ module GraphQL
804
804
  st.current_object = continue_value
805
805
  st.current_result_name = nil
806
806
  st.current_result = this_result
807
-
808
807
  # This is a less-frequent case; use a fast check since it's often not there.
809
808
  if (directives = selections[:graphql_directives])
810
809
  selections.delete(:graphql_directives)
@@ -839,10 +838,10 @@ module GraphQL
839
838
  idx += 1
840
839
  if use_dataloader_job
841
840
  @dataloader.append_job do
842
- resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
841
+ resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type, was_scoped)
843
842
  end
844
843
  else
845
- resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
844
+ resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type, was_scoped)
846
845
  end
847
846
  end
848
847
 
@@ -873,7 +872,7 @@ module GraphQL
873
872
  end
874
873
  end
875
874
 
876
- def resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type) # rubocop:disable Metrics/ParameterLists
875
+ def resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type, was_scoped) # rubocop:disable Metrics/ParameterLists
877
876
  st = get_current_runtime_state
878
877
  st.current_result_name = this_idx
879
878
  st.current_result = response_list
@@ -882,7 +881,7 @@ module GraphQL
882
881
  after_lazy(inner_value, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, result_name: this_idx, result: response_list) do |inner_inner_value|
883
882
  continue_value = continue_value(inner_inner_value, owner_type, field, inner_type_non_null, ast_node, this_idx, response_list)
884
883
  if HALT != continue_value
885
- continue_field(continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments, this_idx, response_list)
884
+ continue_field(continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments, this_idx, response_list, was_scoped)
886
885
  end
887
886
  end
888
887
  end
@@ -962,6 +961,8 @@ module GraphQL
962
961
  def after_lazy(lazy_obj, field:, owner_object:, arguments:, ast_node:, result:, result_name:, eager: false, trace: true, &block)
963
962
  if lazy?(lazy_obj)
964
963
  orig_result = result
964
+ st = get_current_runtime_state
965
+ was_authorized_by_scope_items = st.was_authorized_by_scope_items
965
966
  lazy = GraphQL::Execution::Lazy.new(field: field) do
966
967
  st = get_current_runtime_state
967
968
  st.current_object = owner_object
@@ -969,6 +970,7 @@ module GraphQL
969
970
  st.current_arguments = arguments
970
971
  st.current_result_name = result_name
971
972
  st.current_result = orig_result
973
+ st.was_authorized_by_scope_items = was_authorized_by_scope_items
972
974
  # Wrap the execution of _this_ method with tracing,
973
975
  # but don't wrap the continuation below
974
976
  inner_obj = begin
@@ -14,7 +14,7 @@ module GraphQL
14
14
  # @param include_built_in_directives [Boolean] Whether or not to include built in directives in the AST
15
15
  class DocumentFromSchemaDefinition
16
16
  def initialize(
17
- schema, context: nil, only: nil, except: nil, include_introspection_types: false,
17
+ schema, context: nil, include_introspection_types: false,
18
18
  include_built_in_directives: false, include_built_in_scalars: false, always_include_schema: false
19
19
  )
20
20
  @schema = schema
@@ -26,21 +26,11 @@ module GraphQL
26
26
 
27
27
  schema_context = schema.context_class.new(query: nil, object: nil, schema: schema, values: context)
28
28
 
29
- @warden = if only || except
30
- filter = GraphQL::Filter
31
- .new(only: only, except: except)
32
- .merge(only: @schema.method(:visible?))
33
- GraphQL::Schema::Warden.new(
34
- filter,
35
- schema: @schema,
36
- context: schema_context,
37
- )
38
- else
39
- @schema.warden_class.new(
40
- schema: @schema,
41
- context: schema_context,
42
- )
43
- end
29
+
30
+ @warden = @schema.warden_class.new(
31
+ schema: @schema,
32
+ context: schema_context,
33
+ )
44
34
 
45
35
  schema_context.warden = @warden
46
36
  end
@@ -4,7 +4,7 @@ require "strscan"
4
4
 
5
5
  module GraphQL
6
6
  module Language
7
- module Lexer
7
+ class Lexer
8
8
  IDENTIFIER = /[_A-Za-z][_0-9A-Za-z]*/
9
9
  NEWLINE = /[\c\r\n]/
10
10
  BLANK = /[, \t]+/
@@ -87,60 +87,81 @@ module GraphQL
87
87
  # # catch-all for anything else. must be at the bottom for precedence.
88
88
  UNKNOWN_CHAR = /./
89
89
 
90
- def self.tokenize string
91
- meta = {
92
- line: 1,
93
- col: 1,
94
- tokens: [],
95
- previous_token: nil,
96
- }
90
+ def initialize(value)
91
+ @line = 1
92
+ @col = 1
93
+ @previous_token = nil
97
94
 
95
+ @scan = scanner value
96
+ end
97
+
98
+ class BadEncoding < Lexer # :nodoc:
99
+ def scanner(value)
100
+ [emit(:BAD_UNICODE_ESCAPE, 0, 0, value)]
101
+ end
102
+
103
+ def next_token
104
+ @scan.pop
105
+ end
106
+ end
107
+
108
+ def self.tokenize(string)
98
109
  value = string.dup.force_encoding(Encoding::UTF_8)
99
110
 
100
- unless value.valid_encoding?
101
- emit(:BAD_UNICODE_ESCAPE, 0, 0, meta, value)
102
- return meta[:tokens]
111
+ scanner = if value.valid_encoding?
112
+ new value
113
+ else
114
+ BadEncoding.new value
103
115
  end
104
116
 
105
- scan = StringScanner.new value
106
-
107
- while !scan.eos?
108
- pos = scan.pos
109
-
110
- case
111
- when str = scan.scan(FLOAT) then emit(:FLOAT, pos, scan.pos, meta, str)
112
- when str = scan.scan(INT) then emit(:INT, pos, scan.pos, meta, str)
113
- when str = scan.scan(LIT) then emit(LIT_NAME_LUT[str], pos, scan.pos, meta, -str)
114
- when str = scan.scan(IDENTIFIER) then emit(:IDENTIFIER, pos, scan.pos, meta, str)
115
- when str = scan.scan(BLOCK_STRING) then emit_block(pos, scan.pos, meta, str.gsub(/^#{BLOCK_QUOTE}|#{BLOCK_QUOTE}$/, ''))
116
- when str = scan.scan(QUOTED_STRING) then emit_string(pos, scan.pos, meta, str.gsub(/^"|"$/, ''))
117
- when str = scan.scan(COMMENT) then record_comment(pos, scan.pos, meta, str)
118
- when str = scan.scan(NEWLINE)
119
- meta[:line] += 1
120
- meta[:col] = 1
121
- when scan.scan(BLANK)
122
- meta[:col] += scan.pos - pos
123
- when str = scan.scan(UNKNOWN_CHAR) then emit(:UNKNOWN_CHAR, pos, scan.pos, meta, str)
124
- else
125
- # This should never happen since `UNKNOWN_CHAR` ensures we make progress
126
- raise "Unknown string?"
127
- end
117
+ toks = []
118
+
119
+ while tok = scanner.next_token
120
+ toks << tok
128
121
  end
129
122
 
130
- meta[:tokens]
123
+ toks
124
+ end
125
+
126
+ def next_token
127
+ return if @scan.eos?
128
+
129
+ pos = @scan.pos
130
+
131
+ case
132
+ when str = @scan.scan(FLOAT) then emit(:FLOAT, pos, @scan.pos, str)
133
+ when str = @scan.scan(INT) then emit(:INT, pos, @scan.pos, str)
134
+ when str = @scan.scan(LIT) then emit(LIT_NAME_LUT[str], pos, @scan.pos, -str)
135
+ when str = @scan.scan(IDENTIFIER) then emit(:IDENTIFIER, pos, @scan.pos, str)
136
+ when str = @scan.scan(BLOCK_STRING) then emit_block(pos, @scan.pos, str.gsub(/\A#{BLOCK_QUOTE}|#{BLOCK_QUOTE}\z/, ''))
137
+ when str = @scan.scan(QUOTED_STRING) then emit_string(pos, @scan.pos, str.gsub(/^"|"$/, ''))
138
+ when str = @scan.scan(COMMENT) then record_comment(pos, @scan.pos, str)
139
+ when str = @scan.scan(NEWLINE)
140
+ @line += 1
141
+ @col = 1
142
+ next_token
143
+ when @scan.scan(BLANK)
144
+ @col += @scan.pos - pos
145
+ next_token
146
+ when str = @scan.scan(UNKNOWN_CHAR) then emit(:UNKNOWN_CHAR, pos, @scan.pos, str)
147
+ else
148
+ # This should never happen since `UNKNOWN_CHAR` ensures we make progress
149
+ raise "Unknown string?"
150
+ end
131
151
  end
132
152
 
133
- def self.emit(token_name, ts, te, meta, token_value)
134
- meta[:tokens] << token = [
153
+ def emit(token_name, ts, te, token_value)
154
+ token = [
135
155
  token_name,
136
- meta[:line],
137
- meta[:col],
156
+ @line,
157
+ @col,
138
158
  token_value,
139
- meta[:previous_token],
159
+ @previous_token,
140
160
  ]
141
- meta[:previous_token] = token
161
+ @previous_token = token
142
162
  # Bump the column counter for the next token
143
- meta[:col] += te - ts
163
+ @col += te - ts
164
+ token
144
165
  end
145
166
 
146
167
  # Replace any escaped unicode or whitespace with the _actual_ characters
@@ -169,18 +190,19 @@ module GraphQL
169
190
  nil
170
191
  end
171
192
 
172
- def self.record_comment(ts, te, meta, str)
193
+ def record_comment(ts, te, str)
173
194
  token = [
174
195
  :COMMENT,
175
- meta[:line],
176
- meta[:col],
196
+ @line,
197
+ @col,
177
198
  str,
178
- meta[:previous_token],
199
+ @previous_token,
179
200
  ]
180
201
 
181
- meta[:previous_token] = token
202
+ @previous_token = token
182
203
 
183
- meta[:col] += te - ts
204
+ @col += te - ts
205
+ next_token
184
206
  end
185
207
 
186
208
  ESCAPES = /\\["\\\/bfnrt]/
@@ -197,26 +219,34 @@ module GraphQL
197
219
  UTF_8 = /\\u(?:([\dAa-f]{4})|\{([\da-f]{4,})\})(?:\\u([\dAa-f]{4}))?/i
198
220
  VALID_STRING = /\A(?:[^\\]|#{ESCAPES}|#{UTF_8})*\z/o
199
221
 
200
- def self.emit_block(ts, te, meta, value)
222
+ def emit_block(ts, te, value)
201
223
  line_incr = value.count("\n")
202
224
  value = GraphQL::Language::BlockString.trim_whitespace(value)
203
- emit_string(ts, te, meta, value)
204
- meta[:line] += line_incr
225
+ tok = emit_string(ts, te, value)
226
+ @line += line_incr
227
+ tok
205
228
  end
206
229
 
207
- def self.emit_string(ts, te, meta, value)
230
+ def emit_string(ts, te, value)
208
231
  if !value.valid_encoding? || !value.match?(VALID_STRING)
209
- emit(:BAD_UNICODE_ESCAPE, ts, te, meta, value)
232
+ emit(:BAD_UNICODE_ESCAPE, ts, te, value)
210
233
  else
211
- replace_escaped_characters_in_place(value)
234
+ self.class.replace_escaped_characters_in_place(value)
212
235
 
213
236
  if !value.valid_encoding?
214
- emit(:BAD_UNICODE_ESCAPE, ts, te, meta, value)
237
+ emit(:BAD_UNICODE_ESCAPE, ts, te, value)
215
238
  else
216
- emit(:STRING, ts, te, meta, value)
239
+ emit(:STRING, ts, te, value)
217
240
  end
218
241
  end
219
242
  end
243
+
244
+ private
245
+
246
+ def scanner(value)
247
+ StringScanner.new value
248
+ end
249
+
220
250
  end
221
251
  end
222
252
  end
@@ -535,7 +535,7 @@ module GraphQL
535
535
  # @example Creating a custom string from a document
536
536
  # class VariableScrubber < GraphQL::Language::Printer
537
537
  # def print_argument(arg)
538
- # "#{arg.name}: <HIDDEN>"
538
+ # print_string("#{arg.name}: <HIDDEN>")
539
539
  # end
540
540
  # end
541
541
  #