tinygql 0.1.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,8 +13,7 @@ module TinyGQL
13
13
 
14
14
  def initialize doc
15
15
  @lexer = Lexer.new doc
16
- @lexer.advance
17
- @token_name = @lexer.token_name
16
+ accept_token
18
17
  end
19
18
 
20
19
  def parse
@@ -25,8 +24,13 @@ module TinyGQL
25
24
 
26
25
  attr_reader :token_name
27
26
 
27
+ def pos
28
+ @lexer.start
29
+ end
30
+
28
31
  def document
29
- Nodes::Document.new definition_list
32
+ loc = pos
33
+ Nodes::Document.new loc, definition_list
30
34
  end
31
35
 
32
36
  def definition_list
@@ -65,52 +69,58 @@ module TinyGQL
65
69
  end
66
70
 
67
71
  def input_object_type_extension
72
+ loc = pos
68
73
  expect_token :INPUT
69
74
  name = self.name
70
75
  directives = if at?(:DIR_SIGN); self.directives; end
71
76
  input_fields_definition = if at?(:LCURLY); self.input_fields_definition; end
72
- Nodes::InputObjectTypeExtension.new(name, directives, input_fields_definition)
77
+ Nodes::InputObjectTypeExtension.new(loc, name, directives, input_fields_definition)
73
78
  end
74
79
 
75
80
  def enum_type_extension
81
+ loc = pos
76
82
  expect_token :ENUM
77
83
  name = self.name
78
84
  directives = if at?(:DIR_SIGN); self.directives; end
79
85
  enum_values_definition = if at?(:LCURLY); self.enum_values_definition; end
80
- Nodes::EnumTypeExtension.new(name, directives, enum_values_definition)
86
+ Nodes::EnumTypeExtension.new(loc, name, directives, enum_values_definition)
81
87
  end
82
88
 
83
89
  def union_type_extension
90
+ loc = pos
84
91
  expect_token :UNION
85
92
  name = self.name
86
93
  directives = if at?(:DIR_SIGN); self.directives; end
87
94
  union_member_types = if at?(:EQUALS); self.union_member_types; end
88
- Nodes::UnionTypeExtension.new(name, directives, union_member_types)
95
+ Nodes::UnionTypeExtension.new(loc, name, directives, union_member_types)
89
96
  end
90
97
 
91
98
  def interface_type_extension
99
+ loc = pos
92
100
  expect_token :INTERFACE
93
101
  name = self.name
94
102
  implements_interfaces = if at?(:IMPLEMENTS); self.implements_interfaces; end
95
103
  directives = if at?(:DIR_SIGN); self.directives; end
96
104
  fields_definition = if at?(:LCURLY); self.fields_definition; end
97
- Nodes::InterfaceTypeExtension.new(name, implements_interfaces, directives, fields_definition)
105
+ Nodes::InterfaceTypeExtension.new(loc, name, implements_interfaces, directives, fields_definition)
98
106
  end
99
107
 
100
108
  def scalar_type_extension
109
+ loc = pos
101
110
  expect_token :SCALAR
102
111
  name = self.name
103
112
  directives = if at?(:DIR_SIGN); self.directives; end
104
- Nodes::ScalarTypeExtension.new(name, directives)
113
+ Nodes::ScalarTypeExtension.new(loc, name, directives)
105
114
  end
106
115
 
107
116
  def object_type_extension
117
+ loc = pos
108
118
  expect_token :TYPE
109
119
  name = self.name
110
120
  implements_interfaces = if at?(:IMPLEMENTS); self.implements_interfaces; end
111
121
  directives = if at?(:DIR_SIGN); self.directives; end
112
122
  fields_definition = if at?(:LCURLY); self.fields_definition; end
113
- Nodes::ObjectTypeExtension.new(name, implements_interfaces, directives, fields_definition)
123
+ Nodes::ObjectTypeExtension.new(loc, name, implements_interfaces, directives, fields_definition)
114
124
  end
115
125
 
116
126
  def type_system_definition desc
@@ -123,13 +133,14 @@ module TinyGQL
123
133
  end
124
134
 
125
135
  def directive_defintion desc
136
+ loc = pos
126
137
  expect_token :DIRECTIVE
127
138
  expect_token :DIR_SIGN
128
139
  name = self.name
129
140
  arguments_definition = if at?(:LPAREN); self.arguments_definition; end
130
141
  expect_token :ON
131
142
  directive_locations = self.directive_locations
132
- Nodes::DirectiveDefinition.new(desc, name, arguments_definition, directive_locations)
143
+ Nodes::DirectiveDefinition.new(loc, desc, name, arguments_definition, directive_locations)
133
144
  end
134
145
 
135
146
  def directive_locations
@@ -142,11 +153,12 @@ module TinyGQL
142
153
  end
143
154
 
144
155
  def directive_location
156
+ loc = pos
145
157
  directive = expect_token_value :IDENTIFIER
146
158
 
147
159
  case directive
148
160
  when "QUERY", "MUTATION", "SUBSCRIPTION", "FIELD", "FRAGMENT_DEFINITION", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"
149
- Nodes::ExecutableDirectiveLocation.new(directive)
161
+ Nodes::ExecutableDirectiveLocation.new(loc, directive)
150
162
  when "SCHEMA",
151
163
  "SCALAR",
152
164
  "OBJECT",
@@ -158,7 +170,7 @@ module TinyGQL
158
170
  "ENUM_VALUE",
159
171
  "INPUT_OBJECT",
160
172
  "INPUT_FIELD_DEFINITION"
161
- Nodes::TypeSystemDirectiveLocation.new(directive)
173
+ Nodes::TypeSystemDirectiveLocation.new(loc, directive)
162
174
  else
163
175
  raise UnexpectedToken, "Expected directive #{directive}"
164
176
  end
@@ -178,11 +190,12 @@ module TinyGQL
178
190
  end
179
191
 
180
192
  def input_object_type_definition desc
193
+ loc = pos
181
194
  expect_token :INPUT
182
195
  name = self.name
183
196
  directives = if at?(:DIR_SIGN); self.directives; end
184
197
  input_fields_definition = if at?(:LCURLY); self.input_fields_definition; end
185
- Nodes::InputObjectTypeDefinition.new(desc, name, directives, input_fields_definition)
198
+ Nodes::InputObjectTypeDefinition.new(loc, desc, name, directives, input_fields_definition)
186
199
  end
187
200
 
188
201
  def input_fields_definition
@@ -196,11 +209,12 @@ module TinyGQL
196
209
  end
197
210
 
198
211
  def enum_type_definition desc
212
+ loc = pos
199
213
  expect_token :ENUM
200
214
  name = self.name
201
215
  directives = if at?(:DIR_SIGN); self.directives; end
202
216
  enum_values_definition = if at?(:LCURLY); self.enum_values_definition; end
203
- Nodes::EnumTypeDefinition.new(desc, name, directives, enum_values_definition)
217
+ Nodes::EnumTypeDefinition.new(loc, desc, name, directives, enum_values_definition)
204
218
  end
205
219
 
206
220
  def enum_values_definition
@@ -214,25 +228,28 @@ module TinyGQL
214
228
  end
215
229
 
216
230
  def enum_value_definition
231
+ loc = pos
217
232
  description = if at?(:STRING); string_value; end
218
233
  enum_value = self.enum_value
219
234
  directives = if at?(:DIR_SIGN); self.directives; end
220
- Nodes::EnumValueDefinition.new(description, enum_value, directives)
235
+ Nodes::EnumValueDefinition.new(loc, description, enum_value, directives)
221
236
  end
222
237
 
223
238
  def scalar_type_definition desc
239
+ loc = pos
224
240
  expect_token :SCALAR
225
241
  name = self.name
226
242
  directives = if at?(:DIR_SIGN); self.directives; end
227
- Nodes::ScalarTypeDefinition.new(desc, name, directives)
243
+ Nodes::ScalarTypeDefinition.new(loc, desc, name, directives)
228
244
  end
229
245
 
230
246
  def union_type_definition desc
247
+ loc = pos
231
248
  expect_token :UNION
232
249
  name = self.name
233
250
  directives = if at?(:DIR_SIGN); self.directives; end
234
251
  union_member_types = if at?(:EQUALS); self.union_member_types; end
235
- Nodes::UnionTypeDefinition.new(desc, name, directives, union_member_types)
252
+ Nodes::UnionTypeDefinition.new(loc, desc, name, directives, union_member_types)
236
253
  end
237
254
 
238
255
  def union_member_types
@@ -246,21 +263,23 @@ module TinyGQL
246
263
  end
247
264
 
248
265
  def interface_type_definition desc
266
+ loc = pos
249
267
  expect_token :INTERFACE
250
268
  name = self.name
251
269
  directives = if at?(:DIR_SIGN); self.directives; end
252
270
  fields_definition = if at?(:LCURLY); self.fields_definition; end
253
- Nodes::InterfaceTypeDefinition.new(desc, name, directives, fields_definition)
271
+ Nodes::InterfaceTypeDefinition.new(loc, desc, name, directives, fields_definition)
254
272
  end
255
273
 
256
274
  def object_type_definition desc
275
+ loc = pos
257
276
  expect_token :TYPE
258
277
  name = self.name
259
278
  implements_interfaces = if at?(:IMPLEMENTS); self.implements_interfaces; end
260
279
  directives = if at?(:DIR_SIGN); self.directives; end
261
280
  fields_definition = if at?(:LCURLY); self.fields_definition; end
262
281
 
263
- Nodes::ObjectTypeDefinition.new(desc, name, implements_interfaces, directives, fields_definition)
282
+ Nodes::ObjectTypeDefinition.new(loc, desc, name, implements_interfaces, directives, fields_definition)
264
283
  end
265
284
 
266
285
  def fields_definition
@@ -274,6 +293,7 @@ module TinyGQL
274
293
  end
275
294
 
276
295
  def field_definition
296
+ loc = pos
277
297
  description = if at?(:STRING); string_value; end
278
298
  name = self.name
279
299
  arguments_definition = if at?(:LPAREN); self.arguments_definition; end
@@ -281,7 +301,7 @@ module TinyGQL
281
301
  type = self.type
282
302
  directives = if at?(:DIR_SIGN); self.directives; end
283
303
 
284
- Nodes::FieldDefinition.new(description, name, arguments_definition, type, directives)
304
+ Nodes::FieldDefinition.new(loc, description, name, arguments_definition, type, directives)
285
305
  end
286
306
 
287
307
  def arguments_definition
@@ -295,13 +315,14 @@ module TinyGQL
295
315
  end
296
316
 
297
317
  def input_value_definition
318
+ loc = pos
298
319
  description = if at?(:STRING); string_value; end
299
320
  name = self.name
300
321
  expect_token :COLON
301
322
  type = self.type
302
323
  default_value = if at?(:EQUALS); self.default_value; end
303
324
  directives = if at?(:DIR_SIGN); self.directives; end
304
- Nodes::InputValueDefinition.new(description, name, type, default_value, directives)
325
+ Nodes::InputValueDefinition.new(loc, description, name, type, default_value, directives)
305
326
  end
306
327
 
307
328
  def implements_interfaces
@@ -316,21 +337,23 @@ module TinyGQL
316
337
  end
317
338
 
318
339
  def schema_definition desc
340
+ loc = pos
319
341
  expect_token :SCHEMA
320
342
 
321
343
  directives = if at?(:DIR_SIGN); self.directives; end
322
344
  expect_token :LCURLY
323
345
  defs = root_operation_type_definition
324
346
  expect_token :RCURLY
325
- Nodes::SchemaDefinition.new(desc, directives, defs)
347
+ Nodes::SchemaDefinition.new(loc, desc, directives, defs)
326
348
  end
327
349
 
328
350
  def root_operation_type_definition
329
351
  list = []
330
352
  while !at?(:RCURLY)
353
+ loc = pos
331
354
  operation_type = self.operation_type
332
355
  expect_token :COLON
333
- list << Nodes::RootOperationTypeDefinition.new(operation_type, named_type)
356
+ list << Nodes::RootOperationTypeDefinition.new(loc, operation_type, named_type)
334
357
  end
335
358
  list
336
359
  end
@@ -344,6 +367,7 @@ module TinyGQL
344
367
  end
345
368
 
346
369
  def fragment_definition
370
+ loc = pos
347
371
  expect_token :FRAGMENT
348
372
  expect_token(:IDENTIFIER) if at?(:ON)
349
373
  name = self.name
@@ -352,10 +376,11 @@ module TinyGQL
352
376
  self.directives
353
377
  end
354
378
 
355
- Nodes::FragmentDefinition.new(name, tc, directives, selection_set)
379
+ Nodes::FragmentDefinition.new(loc, name, tc, directives, selection_set)
356
380
  end
357
381
 
358
382
  def operation_definition
383
+ loc = pos
359
384
  case token_name
360
385
  when :QUERY, :MUTATION, :SUBSCRIPTION
361
386
  type = self.operation_type
@@ -365,6 +390,7 @@ module TinyGQL
365
390
  end
366
391
 
367
392
  Nodes::OperationDefinition.new(
393
+ loc,
368
394
  type,
369
395
  ident,
370
396
  variable_definitions,
@@ -403,15 +429,17 @@ module TinyGQL
403
429
  end
404
430
 
405
431
  def fragment_spread
432
+ loc = pos
406
433
  name = self.name
407
434
  directives = if at?(:DIR_SIGN); self.directives; end
408
435
 
409
436
  expect_token(:IDENTIFIER) if at?(:ON)
410
437
 
411
- Nodes::FragmentSpread.new(name, directives)
438
+ Nodes::FragmentSpread.new(loc, name, directives)
412
439
  end
413
440
 
414
441
  def inline_fragment
442
+ loc = pos
415
443
  type_condition = if at?(:ON)
416
444
  self.type_condition
417
445
  end
@@ -420,15 +448,17 @@ module TinyGQL
420
448
  self.directives
421
449
  end
422
450
 
423
- Nodes::InlineFragment.new(type_condition, directives, selection_set)
451
+ Nodes::InlineFragment.new(loc, type_condition, directives, selection_set)
424
452
  end
425
453
 
426
454
  def type_condition
455
+ loc = pos
427
456
  expect_token :ON
428
- Nodes::TypeCondition.new(named_type)
457
+ Nodes::TypeCondition.new(loc, named_type)
429
458
  end
430
459
 
431
460
  def field
461
+ loc = pos
432
462
  name = self.name
433
463
 
434
464
  aliaz = nil
@@ -443,11 +473,21 @@ module TinyGQL
443
473
  directives = if at?(:DIR_SIGN); self.directives; end
444
474
  selection_set = if at?(:LCURLY); self.selection_set; end
445
475
 
446
- Nodes::Field.new(aliaz, name, arguments, directives, selection_set)
476
+ Nodes::Field.new(loc, aliaz, name, arguments, directives, selection_set)
447
477
  end
448
478
 
449
479
  def operation_type
450
- expect_tokens([:QUERY, :MUTATION, :SUBSCRIPTION])
480
+ val = if at?(:QUERY)
481
+ "query"
482
+ elsif at?(:MUTATION)
483
+ "mutation"
484
+ elsif at?(:SUBSCRIPTION)
485
+ "subscription"
486
+ else
487
+ expect_token(:QUERY)
488
+ end
489
+ accept_token
490
+ val
451
491
  end
452
492
 
453
493
  def directives
@@ -459,13 +499,14 @@ module TinyGQL
459
499
  end
460
500
 
461
501
  def directive
502
+ loc = pos
462
503
  expect_token(:DIR_SIGN)
463
504
  name = self.name
464
505
  arguments = if at?(:LPAREN)
465
506
  self.arguments
466
507
  end
467
508
 
468
- Nodes::Directive.new(name, arguments)
509
+ Nodes::Directive.new(loc, name, arguments)
469
510
  end
470
511
 
471
512
  def arguments
@@ -479,9 +520,10 @@ module TinyGQL
479
520
  end
480
521
 
481
522
  def argument
523
+ loc = pos
482
524
  name = self.name
483
525
  expect_token(:COLON)
484
- Nodes::Argument.new(name, value)
526
+ Nodes::Argument.new(loc, name, value)
485
527
  end
486
528
 
487
529
  def variable_definitions
@@ -495,14 +537,15 @@ module TinyGQL
495
537
  end
496
538
 
497
539
  def variable_definition
498
- var = variable
540
+ loc = pos
541
+ var = variable if at?(:VAR_SIGN)
499
542
  expect_token(:COLON)
500
543
  type = self.type
501
544
  default_value = if at?(:EQUALS)
502
545
  self.default_value
503
546
  end
504
547
 
505
- Nodes::VariableDefinition.new(var, type, default_value)
548
+ Nodes::VariableDefinition.new(loc, var, type, default_value)
506
549
  end
507
550
 
508
551
  def default_value
@@ -527,49 +570,61 @@ module TinyGQL
527
570
  end
528
571
 
529
572
  def object_value
573
+ start = pos
530
574
  expect_token(:LCURLY)
531
575
  list = []
532
576
  while !at?(:RCURLY)
577
+ loc = pos
533
578
  n = name
534
579
  expect_token(:COLON)
535
- list << Nodes::ObjectField.new(n, value)
580
+ list << Nodes::ObjectField.new(loc, n, value)
536
581
  end
537
582
  expect_token(:RCURLY)
538
- Nodes::ObjectValue.new(list)
583
+ Nodes::ObjectValue.new(start, list)
539
584
  end
540
585
 
541
586
  def list_value
587
+ loc = pos
542
588
  expect_token(:LBRACKET)
543
589
  list = []
544
590
  while !at?(:RBRACKET)
545
591
  list << value
546
592
  end
547
593
  expect_token(:RBRACKET)
548
- Nodes::ListValue.new(list)
594
+ Nodes::ListValue.new(loc, list)
549
595
  end
550
596
 
551
597
  def enum_value
552
- Nodes::EnumValue.new(expect_token_value(:IDENTIFIER))
598
+ Nodes::EnumValue.new(pos, expect_token_value(:IDENTIFIER))
553
599
  end
554
600
 
555
601
  def float_value
556
- Nodes::FloatValue.new(expect_token_value(:FLOAT))
602
+ Nodes::FloatValue.new(pos, expect_token_value(:FLOAT))
557
603
  end
558
604
 
559
605
  def int_value
560
- Nodes::IntValue.new(expect_token_value(:INT))
606
+ Nodes::IntValue.new(pos, expect_token_value(:INT))
561
607
  end
562
608
 
563
609
  def string_value
564
- Nodes::StringValue.new(expect_token_value(:STRING))
610
+ Nodes::StringValue.new(pos, expect_string_value)
565
611
  end
566
612
 
567
613
  def boolean_value
568
- Nodes::BooleanValue.new(expect_tokens([:TRUE, :FALSE]))
614
+ if at?(:TRUE)
615
+ accept_token
616
+ Nodes::BooleanValue.new(pos, "true")
617
+ elsif at?(:FALSE)
618
+ accept_token
619
+ Nodes::BooleanValue.new(pos, "false")
620
+ else
621
+ expect_token(:TRUE)
622
+ end
569
623
  end
570
624
 
571
625
  def null_value
572
- Nodes::NullValue.new(expect_token_value(:NULL))
626
+ expect_token :NULL
627
+ Nodes::NullValue.new(pos, "null")
573
628
  end
574
629
 
575
630
  def type
@@ -579,47 +634,49 @@ module TinyGQL
579
634
  end
580
635
 
581
636
  if at?(:BANG)
582
- Nodes::NotNullType.new type
637
+ Nodes::NotNullType.new pos, type
583
638
  expect_token(:BANG)
584
639
  end
585
640
  type
586
641
  end
587
642
 
588
643
  def list_type
644
+ loc = pos
589
645
  expect_token(:LBRACKET)
590
- type = Nodes::ListType.new(self.type)
646
+ type = Nodes::ListType.new(loc, self.type)
591
647
  expect_token(:RBRACKET)
592
648
  type
593
649
  end
594
650
 
595
651
  def named_type
596
- Nodes::NamedType.new(name)
652
+ Nodes::NamedType.new(pos, name)
597
653
  end
598
654
 
599
655
  def variable
600
- return unless at?(:VAR_SIGN)
601
- accept_token
602
- Nodes::Variable.new name
656
+ loc = pos
657
+ expect_token(:VAR_SIGN)
658
+ Nodes::Variable.new loc, name
603
659
  end
604
660
 
605
661
  def name
606
662
  case token_name
607
- when :IDENTIFIER, :INPUT, :QUERY, :TYPE then accept_token_value
663
+ when :IDENTIFIER then expect_token_value(:IDENTIFIER)
664
+ when :TYPE then
665
+ accept_token
666
+ "type"
667
+ when :QUERY then
668
+ accept_token
669
+ "query"
670
+ when :INPUT then
671
+ accept_token
672
+ "input"
608
673
  else
609
- expect_token_value(:IDENTIFIER)
674
+ expect_token(:IDENTIFIER)
610
675
  end
611
676
  end
612
677
 
613
678
  def accept_token
614
- @lexer.advance
615
- @token_name = @lexer.token_name
616
- end
617
-
618
- # Only use when we care about the accepted token's value
619
- def accept_token_value
620
- token_value = @lexer.token_value
621
- accept_token
622
- token_value
679
+ @token_name = @lexer.advance
623
680
  end
624
681
 
625
682
  def expect_token tok
@@ -636,12 +693,9 @@ module TinyGQL
636
693
  token_value
637
694
  end
638
695
 
639
- def expect_tokens toks
640
- token_value = @lexer.token_value
641
- unless toks.any? { |tok| at?(tok) }
642
- raise UnexpectedToken, "Expected token #{tok}, actual: #{token_name}"
643
- end
644
- accept_token
696
+ def expect_string_value
697
+ token_value = @lexer.string_value
698
+ expect_token :STRING
645
699
  token_value
646
700
  end
647
701
 
@@ -1,3 +1,3 @@
1
1
  module TinyGQL
2
- VERSION = '0.1.4'
2
+ VERSION = '0.3.0'
3
3
  end
data/test/lexer_test.rb CHANGED
@@ -101,5 +101,106 @@ eod
101
101
  [:RCURLY, "}"],
102
102
  [:RCURLY, "}"]], toks
103
103
  end
104
+
105
+ def test_lex_4
106
+ words = ["true", "null", "enum", "type"]
107
+ doc = words.join(" ")
108
+
109
+ lexer = Lexer.new doc
110
+ toks = []
111
+ while tok = lexer.next_token
112
+ toks << tok
113
+ end
114
+
115
+ assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
116
+ end
117
+
118
+ def test_lex_5
119
+ words = ["input", "false", "query", "union"]
120
+ doc = words.join(" ")
121
+
122
+ lexer = Lexer.new doc
123
+ toks = []
124
+ while tok = lexer.next_token
125
+ toks << tok
126
+ end
127
+
128
+ assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
129
+ end
130
+
131
+ def test_lex_6
132
+ words = ["extend", "scalar", "schema"]
133
+ doc = words.join(" ")
134
+
135
+ lexer = Lexer.new doc
136
+ toks = []
137
+ while tok = lexer.next_token
138
+ toks << tok
139
+ end
140
+
141
+ assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
142
+ end
143
+
144
+ def test_lex_8
145
+ words = ["mutation", "fragment"]
146
+ doc = words.join(" ")
147
+
148
+ lexer = Lexer.new doc
149
+ toks = []
150
+ while tok = lexer.next_token
151
+ toks << tok
152
+ end
153
+
154
+ assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
155
+ end
156
+
157
+ def test_lex_9
158
+ words = ["interface", "directive"]
159
+ doc = words.join(" ")
160
+
161
+ lexer = Lexer.new doc
162
+ toks = []
163
+ while tok = lexer.next_token
164
+ toks << tok
165
+ end
166
+
167
+ assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
168
+ end
169
+
170
+ def test_kw_lex
171
+ words = ["on", "fragment", "true", "false", "null", "query", "mutation", "subscription", "schema", "scalar", "type", "extend", "implements", "interface", "union", "enum", "input", "directive", "repeatable"]
172
+ doc = words.join(" ")
173
+
174
+ lexer = Lexer.new doc
175
+ toks = []
176
+ while tok = lexer.next_token
177
+ toks << tok
178
+ end
179
+
180
+ assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
181
+ end
182
+
183
+ def test_looks_like_kw
184
+ words = ["fragment", "fragments"]
185
+ doc = words.join(" ")
186
+
187
+ lexer = Lexer.new doc
188
+ toks = []
189
+ while tok = lexer.advance
190
+ toks << tok
191
+ end
192
+
193
+ assert_equal [:FRAGMENT, :IDENTIFIER], toks
194
+ end
195
+
196
+ def test_num_with_dots
197
+ lexer = Lexer.new "1...2"
198
+ toks = []
199
+ while tok = lexer.advance
200
+ toks << tok
201
+ end
202
+
203
+ assert_equal [:INT, :ELLIPSIS, :INT], toks
204
+ end
104
205
  end
105
206
  end
data/test/parser_test.rb CHANGED
@@ -46,6 +46,23 @@ eod
46
46
  assert_equal ["likeStory", "story", "likeCount"], ast.find_all(&:field?).map(&:name)
47
47
  end
48
48
 
49
+ def test_has_position_and_line
50
+ doc = <<-eod
51
+ mutation {
52
+ likeStory(sturyID: 12345) {
53
+ story {
54
+ likeCount
55
+ }
56
+ }
57
+ }
58
+ eod
59
+ parser = Parser.new doc
60
+ ast = parser.parse
61
+ expected = ["likeStory", "story", "likeCount"].map { |str| doc.index(str) }
62
+ assert_equal expected, ast.find_all(&:field?).map(&:start)
63
+ assert_equal [2, 3, 4], ast.find_all(&:field?).map { |n| n.line(doc) }
64
+ end
65
+
49
66
  def test_field_alias
50
67
  doc = <<-eod
51
68
  mutation {