tinygql 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/bin/bench.rb CHANGED
@@ -1,11 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- $:.unshift(File.expand_path("../lib", __dir__))
4
3
  require "tinygql"
5
- require "benchmark"
4
+ require "benchmark/ips"
6
5
 
7
6
  source = File.read(File.expand_path("../test/kitchen-sink.graphql", __dir__))
8
7
 
9
- Benchmark.bm do |x|
10
- x.report { 10_000.times { TinyGQL::Parser.new(source).parse } }
8
+ files = Dir[File.join(File.expand_path("../benchmark", __dir__), "**/*")].select { |f| File.file? f }
9
+
10
+ Benchmark.ips do |x|
11
+ x.report "kitchen-sink" do
12
+ TinyGQL.parse source
13
+ end
14
+
15
+ files.each do |file_name|
16
+ data = File.read file_name
17
+ name = File.basename(file_name, File.extname(file_name))
18
+ x.report name do
19
+ TinyGQL.parse data
20
+ end
21
+ end
11
22
  end
data/bin/profile.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "vernier"
2
+
3
+ Vernier.trace(out: "time_profile.json") {
4
+ require_relative "bench"
5
+ }
data/lib/tinygql/nodes.rb CHANGED
@@ -538,9 +538,10 @@ module TinyGQL
538
538
  end
539
539
  end
540
540
  class SchemaDefinition < Node
541
- attr_reader :directives, :root_operation_definitions
541
+ attr_reader :description, :directives, :root_operation_definitions
542
542
 
543
- def initialize directives, root_operation_definitions
543
+ def initialize description, directives, root_operation_definitions
544
+ @description = description
544
545
  @directives = directives
545
546
  @root_operation_definitions = root_operation_definitions
546
547
  end
@@ -115,12 +115,13 @@ nodes:
115
115
 
116
116
  - name: SchemaDefinition
117
117
  fields:
118
+ - description?
118
119
  - directives?: list
119
120
  - root_operation_definitions: list
120
121
 
121
122
  - name: FieldDefinition
122
123
  fields:
123
- - description?: literal
124
+ - description?
124
125
  - name: literal
125
126
  - arguments_definition?: list
126
127
  - type
@@ -128,7 +129,7 @@ nodes:
128
129
 
129
130
  - name: InputValueDefinition
130
131
  fields:
131
- - description?: literal
132
+ - description?
132
133
  - name: literal
133
134
  - type
134
135
  - default_value?
@@ -136,7 +137,7 @@ nodes:
136
137
 
137
138
  - name: ObjectTypeDefinition
138
139
  fields:
139
- - description?: literal
140
+ - description?
140
141
  - name: literal
141
142
  - implements_interfaces?: list
142
143
  - directives?: list
@@ -144,40 +145,40 @@ nodes:
144
145
 
145
146
  - name: InterfaceTypeDefinition
146
147
  fields:
147
- - description?: literal
148
+ - description?
148
149
  - name: literal
149
150
  - directives?: list
150
151
  - fields_definition?: list
151
152
 
152
153
  - name: UnionTypeDefinition
153
154
  fields:
154
- - description?: literal
155
+ - description?
155
156
  - name: literal
156
157
  - directives?: list
157
158
  - union_member_types?: list
158
159
 
159
160
  - name: ScalarTypeDefinition
160
161
  fields:
161
- - description?: literal
162
+ - description?
162
163
  - name: literal
163
164
  - directives?: list
164
165
 
165
166
  - name: EnumValueDefinition
166
167
  fields:
167
- - description?: literal
168
+ - description?
168
169
  - enum_value
169
170
  - directives?: list
170
171
 
171
172
  - name: EnumTypeDefinition
172
173
  fields:
173
- - description?: literal
174
+ - description?
174
175
  - name: literal
175
176
  - directives?: list
176
177
  - enum_value_definition?: list
177
178
 
178
179
  - name: InputObjectTypeDefinition
179
180
  fields:
180
- - description?: literal
181
+ - description?
181
182
  - name: literal
182
183
  - directives?: list
183
184
  - input_fields_definition?: list
@@ -199,7 +200,7 @@ nodes:
199
200
 
200
201
  - name: DirectiveDefinition
201
202
  fields:
202
- - description?: literal
203
+ - description?
203
204
  - name: literal
204
205
  - arguments_definition?: list
205
206
  - directive_locations: list
@@ -7,7 +7,9 @@ module TinyGQL
7
7
  class Parser
8
8
  class UnexpectedToken < StandardError; end
9
9
 
10
- attr_reader :token_name
10
+ def self.parse doc
11
+ new(doc).parse
12
+ end
11
13
 
12
14
  def initialize doc
13
15
  @lexer = Lexer.new doc
@@ -21,6 +23,8 @@ module TinyGQL
21
23
 
22
24
  private
23
25
 
26
+ attr_reader :token_name
27
+
24
28
  def document
25
29
  Nodes::Document.new definition_list
26
30
  end
@@ -40,7 +44,9 @@ module TinyGQL
40
44
  when :EXTEND
41
45
  type_system_extension
42
46
  else
43
- type_system_definition
47
+ desc = if at?(:STRING); string_value; end
48
+
49
+ type_system_definition desc
44
50
  end
45
51
  end
46
52
 
@@ -62,12 +68,12 @@ module TinyGQL
62
68
  Nodes::ObjectTypeExtension.new(name, implements_interfaces, directives, fields_definition)
63
69
  end
64
70
 
65
- def type_system_definition
71
+ def type_system_definition desc
66
72
  case token_name
67
- when :SCHEMA then schema_definition
68
- when :DIRECTIVE then directive_defintion(nil)
73
+ when :SCHEMA then schema_definition(desc)
74
+ when :DIRECTIVE then directive_defintion(desc)
69
75
  else
70
- type_definition(nil)
76
+ type_definition(desc)
71
77
  end
72
78
  end
73
79
 
@@ -91,9 +97,11 @@ module TinyGQL
91
97
  end
92
98
 
93
99
  def directive_location
94
- case token_name
100
+ directive = expect_token_value :IDENTIFIER
101
+
102
+ case directive
95
103
  when "QUERY", "MUTATION", "SUBSCRIPTION", "FIELD", "FRAGMENT_DEFINITION", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"
96
- Nodes::ExecutableDirectiveLocation.new(accept_token_value)
104
+ Nodes::ExecutableDirectiveLocation.new(directive)
97
105
  when "SCHEMA",
98
106
  "SCALAR",
99
107
  "OBJECT",
@@ -105,9 +113,9 @@ module TinyGQL
105
113
  "ENUM_VALUE",
106
114
  "INPUT_OBJECT",
107
115
  "INPUT_FIELD_DEFINITION"
108
- Nodes::TypeSystemDirectiveLocation.new(accept_token_value)
116
+ Nodes::TypeSystemDirectiveLocation.new(directive)
109
117
  else
110
- expect_token(:IDENTIFIER); nil # error
118
+ raise UnexpectedToken, "Expected directive #{directive}"
111
119
  end
112
120
  end
113
121
 
@@ -161,7 +169,7 @@ module TinyGQL
161
169
  end
162
170
 
163
171
  def enum_value_definition
164
- description = if at?(:STRING); accept_token_value; end
172
+ description = if at?(:STRING); string_value; end
165
173
  enum_value = self.enum_value
166
174
  directives = if at?(:DIR_SIGN); self.directives; end
167
175
  Nodes::EnumValueDefinition.new(description, enum_value, directives)
@@ -221,7 +229,7 @@ module TinyGQL
221
229
  end
222
230
 
223
231
  def field_definition
224
- description = if at?(:STRING); accept_token_value; end
232
+ description = if at?(:STRING); string_value; end
225
233
  name = self.name
226
234
  arguments_definition = if at?(:LPAREN); self.arguments_definition; end
227
235
  expect_token :COLON
@@ -242,7 +250,7 @@ module TinyGQL
242
250
  end
243
251
 
244
252
  def input_value_definition
245
- description = if at?(:STRING); accept_token_value; end
253
+ description = if at?(:STRING); string_value; end
246
254
  name = self.name
247
255
  expect_token :COLON
248
256
  type = self.type
@@ -262,14 +270,14 @@ module TinyGQL
262
270
  list
263
271
  end
264
272
 
265
- def schema_definition
273
+ def schema_definition desc
266
274
  expect_token :SCHEMA
267
275
 
268
276
  directives = if at?(:DIR_SIGN); self.directives; end
269
277
  expect_token :LCURLY
270
278
  defs = root_operation_type_definition
271
279
  expect_token :RCURLY
272
- Nodes::SchemaDefinition.new(directives, defs)
280
+ Nodes::SchemaDefinition.new(desc, directives, defs)
273
281
  end
274
282
 
275
283
  def root_operation_type_definition
@@ -1,3 +1,3 @@
1
1
  module TinyGQL
2
- VERSION = '0.1.2'
2
+ VERSION = '0.1.3'
3
3
  end
@@ -100,12 +100,18 @@ module TinyGQL
100
100
  obj.named_type.accept self
101
101
  end
102
102
  def handle_schema_definition obj
103
+ if obj.description
104
+ obj.description.accept self
105
+ end
103
106
  if obj.directives
104
107
  obj.directives.each { |v| v.accept self }
105
108
  end
106
109
  obj.root_operation_definitions.each { |v| v.accept self }
107
110
  end
108
111
  def handle_field_definition obj
112
+ if obj.description
113
+ obj.description.accept self
114
+ end
109
115
  if obj.arguments_definition
110
116
  obj.arguments_definition.each { |v| v.accept self }
111
117
  end
@@ -115,6 +121,9 @@ module TinyGQL
115
121
  end
116
122
  end
117
123
  def handle_input_value_definition obj
124
+ if obj.description
125
+ obj.description.accept self
126
+ end
118
127
  obj.type.accept self
119
128
  if obj.default_value
120
129
  obj.default_value.accept self
@@ -124,6 +133,9 @@ module TinyGQL
124
133
  end
125
134
  end
126
135
  def handle_object_type_definition obj
136
+ if obj.description
137
+ obj.description.accept self
138
+ end
127
139
  if obj.implements_interfaces
128
140
  obj.implements_interfaces.each { |v| v.accept self }
129
141
  end
@@ -135,6 +147,9 @@ module TinyGQL
135
147
  end
136
148
  end
137
149
  def handle_interface_type_definition obj
150
+ if obj.description
151
+ obj.description.accept self
152
+ end
138
153
  if obj.directives
139
154
  obj.directives.each { |v| v.accept self }
140
155
  end
@@ -143,6 +158,9 @@ module TinyGQL
143
158
  end
144
159
  end
145
160
  def handle_union_type_definition obj
161
+ if obj.description
162
+ obj.description.accept self
163
+ end
146
164
  if obj.directives
147
165
  obj.directives.each { |v| v.accept self }
148
166
  end
@@ -151,17 +169,26 @@ module TinyGQL
151
169
  end
152
170
  end
153
171
  def handle_scalar_type_definition obj
172
+ if obj.description
173
+ obj.description.accept self
174
+ end
154
175
  if obj.directives
155
176
  obj.directives.each { |v| v.accept self }
156
177
  end
157
178
  end
158
179
  def handle_enum_value_definition obj
180
+ if obj.description
181
+ obj.description.accept self
182
+ end
159
183
  obj.enum_value.accept self
160
184
  if obj.directives
161
185
  obj.directives.each { |v| v.accept self }
162
186
  end
163
187
  end
164
188
  def handle_enum_type_definition obj
189
+ if obj.description
190
+ obj.description.accept self
191
+ end
165
192
  if obj.directives
166
193
  obj.directives.each { |v| v.accept self }
167
194
  end
@@ -170,6 +197,9 @@ module TinyGQL
170
197
  end
171
198
  end
172
199
  def handle_input_object_type_definition obj
200
+ if obj.description
201
+ obj.description.accept self
202
+ end
173
203
  if obj.directives
174
204
  obj.directives.each { |v| v.accept self }
175
205
  end
@@ -193,6 +223,9 @@ module TinyGQL
193
223
  def handle_type_system_directive_location obj
194
224
  end
195
225
  def handle_directive_definition obj
226
+ if obj.description
227
+ obj.description.accept self
228
+ end
196
229
  if obj.arguments_definition
197
230
  obj.arguments_definition.each { |v| v.accept self }
198
231
  end
@@ -325,6 +358,9 @@ module TinyGQL
325
358
  seed
326
359
  end
327
360
  def handle_schema_definition obj, seed
361
+ if obj.description
362
+ seed = obj.description.fold self, seed
363
+ end
328
364
  if obj.directives
329
365
  obj.directives.each { |v| seed = v.fold(self, seed) }
330
366
  end
@@ -332,6 +368,9 @@ module TinyGQL
332
368
  seed
333
369
  end
334
370
  def handle_field_definition obj, seed
371
+ if obj.description
372
+ seed = obj.description.fold self, seed
373
+ end
335
374
  if obj.arguments_definition
336
375
  obj.arguments_definition.each { |v| seed = v.fold(self, seed) }
337
376
  end
@@ -342,6 +381,9 @@ module TinyGQL
342
381
  seed
343
382
  end
344
383
  def handle_input_value_definition obj, seed
384
+ if obj.description
385
+ seed = obj.description.fold self, seed
386
+ end
345
387
  seed = obj.type.fold self, seed
346
388
  if obj.default_value
347
389
  seed = obj.default_value.fold self, seed
@@ -352,6 +394,9 @@ module TinyGQL
352
394
  seed
353
395
  end
354
396
  def handle_object_type_definition obj, seed
397
+ if obj.description
398
+ seed = obj.description.fold self, seed
399
+ end
355
400
  if obj.implements_interfaces
356
401
  obj.implements_interfaces.each { |v| seed = v.fold(self, seed) }
357
402
  end
@@ -364,6 +409,9 @@ module TinyGQL
364
409
  seed
365
410
  end
366
411
  def handle_interface_type_definition obj, seed
412
+ if obj.description
413
+ seed = obj.description.fold self, seed
414
+ end
367
415
  if obj.directives
368
416
  obj.directives.each { |v| seed = v.fold(self, seed) }
369
417
  end
@@ -373,6 +421,9 @@ module TinyGQL
373
421
  seed
374
422
  end
375
423
  def handle_union_type_definition obj, seed
424
+ if obj.description
425
+ seed = obj.description.fold self, seed
426
+ end
376
427
  if obj.directives
377
428
  obj.directives.each { |v| seed = v.fold(self, seed) }
378
429
  end
@@ -382,12 +433,18 @@ module TinyGQL
382
433
  seed
383
434
  end
384
435
  def handle_scalar_type_definition obj, seed
436
+ if obj.description
437
+ seed = obj.description.fold self, seed
438
+ end
385
439
  if obj.directives
386
440
  obj.directives.each { |v| seed = v.fold(self, seed) }
387
441
  end
388
442
  seed
389
443
  end
390
444
  def handle_enum_value_definition obj, seed
445
+ if obj.description
446
+ seed = obj.description.fold self, seed
447
+ end
391
448
  seed = obj.enum_value.fold self, seed
392
449
  if obj.directives
393
450
  obj.directives.each { |v| seed = v.fold(self, seed) }
@@ -395,6 +452,9 @@ module TinyGQL
395
452
  seed
396
453
  end
397
454
  def handle_enum_type_definition obj, seed
455
+ if obj.description
456
+ seed = obj.description.fold self, seed
457
+ end
398
458
  if obj.directives
399
459
  obj.directives.each { |v| seed = v.fold(self, seed) }
400
460
  end
@@ -404,6 +464,9 @@ module TinyGQL
404
464
  seed
405
465
  end
406
466
  def handle_input_object_type_definition obj, seed
467
+ if obj.description
468
+ seed = obj.description.fold self, seed
469
+ end
407
470
  if obj.directives
408
471
  obj.directives.each { |v| seed = v.fold(self, seed) }
409
472
  end
@@ -431,6 +494,9 @@ module TinyGQL
431
494
  seed
432
495
  end
433
496
  def handle_directive_definition obj, seed
497
+ if obj.description
498
+ seed = obj.description.fold self, seed
499
+ end
434
500
  if obj.arguments_definition
435
501
  obj.arguments_definition.each { |v| seed = v.fold(self, seed) }
436
502
  end
data/test/parser_test.rb CHANGED
@@ -161,5 +161,31 @@ eod
161
161
  node = ast.find(&:object_type_definition?).first
162
162
  assert_equal ["a", "b", "c"], node.implements_interfaces.map(&:name)
163
163
  end
164
+
165
+ def test_schemas_have_descriptions
166
+ doc = <<-eod
167
+ "foo bar"
168
+ schema {
169
+ query: QueryType
170
+ mutation: MutationType
171
+ }
172
+ eod
173
+ ast = TinyGQL::Parser.parse doc
174
+ node = ast.find(&:schema_definition?)
175
+ assert node
176
+ assert_equal "foo bar", node.description.value
177
+ end
178
+
179
+ def test_directives_have_descriptions
180
+ doc = <<-eod
181
+ """neat!"""
182
+ directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
183
+ eod
184
+ ast = TinyGQL::Parser.parse doc
185
+ node = ast.find(&:directive_definition?)
186
+ assert node
187
+ assert_equal "neat!", node.description.value
188
+ assert_equal ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], node.directive_locations.map(&:name)
189
+ end
164
190
  end
165
191
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tinygql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Patterson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-11 00:00:00.000000000 Z
11
+ date: 2023-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -51,7 +51,9 @@ files:
51
51
  - LICENSE
52
52
  - README.md
53
53
  - Rakefile
54
+ - benchmark/fixtures/negotiate.gql
54
55
  - bin/bench.rb
56
+ - bin/profile.rb
55
57
  - lib/tinygql.rb
56
58
  - lib/tinygql/lexer.rb
57
59
  - lib/tinygql/nodes.rb