graphql-libgraphqlparser 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a36c8dfc90001ecf63d6032683987c72cea30a09
4
+ data.tar.gz: 1dc323ff5bd90ff440849ad4146761818bf32f04
5
+ SHA512:
6
+ metadata.gz: 087f862222ee9b94bc373f47d4333cf6df42ad12205c6a13c7f743fdd21ea86743eb1271e4487dd3b9be72f44627f69d0de36dc5fcb9e74a7cacddb4a6de2204
7
+ data.tar.gz: 4542c42448fb8e552b4a708592d083590120463c9de175b45ab55f8aa41cd28983c4543ceb4833463a7c39292dba11d47b20b077f32f54bb8832fe70454ed0b2
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.bundle
2
+ *.so
3
+ Gemfile.lock
4
+ pkg
5
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,25 @@
1
+ language: ruby
2
+ cache: bundler
3
+ sudo: required
4
+ rvm:
5
+ - 2.1
6
+ - 2.2
7
+ addons:
8
+ apt:
9
+ packages:
10
+ - cmake
11
+ before_install:
12
+ - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
13
+ - sudo apt-get -qq update
14
+ - sudo apt-get install build-essential
15
+ - sudo apt-get -qq install g++-5
16
+ - sudo unlink /usr/bin/g++ && sudo ln -s /usr/bin/g++-5 /usr/bin/g++
17
+ - g++ --version
18
+ - sudo apt-get install bison
19
+ - wget https://github.com/graphql/libgraphqlparser/archive/v0.4.0.tar.gz
20
+ - tar -xzvf v0.4.0.tar.gz
21
+ - cd libgraphqlparser-0.4.0/ && sudo cmake . && sudo make && sudo make install
22
+ - gem update --system
23
+ - gem install bundler
24
+ script:
25
+ - bundle exec rake
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,16 @@
1
+ guard :bundler do
2
+ watch('Gemfile')
3
+ # Uncomment next line if your Gemfile contains the `gemspec' command.
4
+ watch(/^.+\.gemspec/)
5
+ end
6
+
7
+ guard :minitest do
8
+ watch(%r{^test/(.*)_test\.rb})
9
+ watch(%r{^lib/(.+)\.rb}) { |m| "test/#{m[1]}_test.rb" }
10
+ watch(%r{^test/test_helper\.rb}) { 'test' }
11
+ watch(%r{^test/support/.*\.rb}) { 'test' }
12
+ end
13
+
14
+ guard 'rake', task: 'compile' do
15
+ watch(%r{^ext/libgraphqlparser/.+$})
16
+ end
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # graphql-libgraphqlparser [![Build Status](https://travis-ci.org/rmosolgo/graphql-libgraphqlparser-ruby.svg?branch=master)](https://travis-ci.org/rmosolgo/graphql-libgraphqlparser-ruby)
2
+
3
+ Make [`graphql`](https://github.com/rmosolgo/graphql-ruby) faster with [`libgraphqlparser`](https://github.com/graphql/libgraphqlparser). Ruby bindings to a C-level GraphQL parser.
4
+
5
+ It's faster:
6
+
7
+ ```
8
+ ~/projects/graphql-libgraphqlparser $ be ruby benchmark.rb
9
+ user system total real
10
+ Ruby 1.140000 0.010000 1.150000 ( 1.161160)
11
+ C 0.000000 0.000000 0.000000 ( 0.009008)
12
+ ~/projects/graphql-libgraphqlparser $ be ruby benchmark.rb
13
+ user system total real
14
+ Ruby 1.180000 0.000000 1.180000 ( 1.185929)
15
+ C 0.000000 0.000000 0.000000 ( 0.008688)
16
+ ~/projects/graphql-libgraphqlparser $ be ruby benchmark.rb
17
+ user system total real
18
+ Ruby 1.220000 0.010000 1.230000 ( 1.233795)
19
+ C 0.010000 0.000000 0.010000 ( 0.008584)
20
+ ```
21
+
22
+ ## Installation
23
+
24
+ This gem depends on [libgraphqlparser](https://github.com/graphql/libgraphqlparser). You can install it a few ways:
25
+
26
+ - __Homebrew__: `brew install libgraphqlparser`
27
+ - __From Source__:
28
+
29
+ ```
30
+ wget https://github.com/graphql/libgraphqlparser/archive/v0.4.0.tar.gz
31
+ tar -xzvf v0.4.0.tar.gz
32
+ cd libgraphqlparser-0.4.0/ && cmake . && make && make install
33
+ ```
34
+
35
+ Then, install this gem:
36
+
37
+ ```ruby
38
+ gem "graphql-libgraphqlparser"
39
+ ```
40
+
41
+ When you `require` this gem, it overrides `GraphQL.parse`:
42
+
43
+ ```ruby
44
+ require "graphql/libgraphqlparser"
45
+ ```
46
+
47
+ ## Todo
48
+
49
+ - Get directives from OperationDefinitions
50
+ - AbstractNode overrides are full of tension. Resolve that tension with GraphQL main.
51
+ - Node `#type` is sometimes a String, sometimes a Node. That should always be the same.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'bundler/setup'
2
+ require 'rake/extensiontask'
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rake/testtask'
7
+
8
+ Rake::TestTask.new do |t|
9
+ t.libs << "test" << "lib"
10
+ t.pattern = "test/**/*_test.rb"
11
+ end
12
+
13
+ Rake::ExtensionTask.new "libgraphqlparser" do |ext|
14
+ ext.lib_dir = "lib/graphql/libgraphqlparser"
15
+ end
16
+
17
+ task default: [:clobber, :compile, :test]
data/benchmark.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'benchmark'
2
+ require 'graphql'
3
+ require 'graphql/libgraphqlparser'
4
+
5
+ query_string = GraphQL::Introspection::INTROSPECTION_QUERY
6
+
7
+ Benchmark.bm(7) do |x|
8
+ x.report("Ruby") { 20.times { GraphQL.parse_without_libgraphqlparser(query_string) } }
9
+ x.report("C") { 20.times { GraphQL.parse(query_string) } }
10
+ end
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('graphql', '/usr/local/include/graphqlparser', '/usr/local/lib')
4
+ abort 'missing libgraphqlparser' unless have_library 'graphqlparser'
5
+
6
+ create_makefile "libgraphqlparser"
@@ -0,0 +1,67 @@
1
+ #include "libgraphqlparser.h"
2
+ #include "visitor_functions.h"
3
+
4
+ #define ATTACH_CALLBACKS(node_name) \
5
+ Libgraphqlparser_Callbacks.visit_##node_name = node_name##_begin_visit; \
6
+ Libgraphqlparser_Callbacks.end_visit_##node_name = node_name##_end_visit; \
7
+
8
+ VALUE Libgraphqlparser_ParseError;
9
+ VALUE Libgraphqlparser_Builder;
10
+
11
+ static struct GraphQLAstVisitorCallbacks Libgraphqlparser_Callbacks;
12
+
13
+ // Given a Ruby querystring, return a
14
+ // GraphQL::Nodes::Document instance.
15
+ VALUE GraphQL_Libgraphqlparser_parse(VALUE self, VALUE query_string) {
16
+ const char* c_query_string = StringValuePtr(query_string);
17
+ const char* parse_error_message;
18
+ VALUE exception;
19
+ VALUE builder = Qnil;
20
+
21
+ struct GraphQLAstNode *parse_result = graphql_parse_string(c_query_string, &parse_error_message);
22
+
23
+ if (parse_result == NULL) {
24
+ exception = rb_exc_new_cstr(Libgraphqlparser_ParseError, parse_error_message);
25
+ graphql_error_free(parse_error_message);
26
+ rb_exc_raise(exception);
27
+ } else {
28
+ builder = rb_class_new_instance(0, NULL, Libgraphqlparser_Builder);
29
+ graphql_node_visit(parse_result, &Libgraphqlparser_Callbacks, (void*)builder);
30
+ }
31
+
32
+ return builder;
33
+ }
34
+
35
+ // Initialize the extension
36
+ void Init_libgraphqlparser() {
37
+ VALUE GraphQL = rb_define_module("GraphQL");
38
+ VALUE Libgraphqlparser = rb_define_module_under(GraphQL, "Libgraphqlparser");
39
+ rb_define_singleton_method(Libgraphqlparser, "builder_parse", GraphQL_Libgraphqlparser_parse, 1);
40
+
41
+ Libgraphqlparser_ParseError = rb_define_class_under(Libgraphqlparser, "ParseError", rb_eStandardError);
42
+ Libgraphqlparser_Builder = rb_const_get(Libgraphqlparser, rb_intern("Builder"));
43
+
44
+ init_visitor_functions();
45
+ // Attach the functions to the Callbacks struct
46
+ ATTACH_CALLBACKS(document);
47
+ ATTACH_CALLBACKS(operation_definition);
48
+ ATTACH_CALLBACKS(variable_definition);
49
+ ATTACH_CALLBACKS(fragment_definition);
50
+ ATTACH_CALLBACKS(variable);
51
+ ATTACH_CALLBACKS(field);
52
+ ATTACH_CALLBACKS(directive);
53
+ ATTACH_CALLBACKS(argument);
54
+ ATTACH_CALLBACKS(fragment_spread);
55
+ ATTACH_CALLBACKS(inline_fragment);
56
+ ATTACH_CALLBACKS(list_type);
57
+ ATTACH_CALLBACKS(non_null_type);
58
+ ATTACH_CALLBACKS(named_type);
59
+ ATTACH_CALLBACKS(float_value);
60
+ ATTACH_CALLBACKS(int_value);
61
+ ATTACH_CALLBACKS(boolean_value);
62
+ ATTACH_CALLBACKS(string_value);
63
+ ATTACH_CALLBACKS(enum_value);
64
+ ATTACH_CALLBACKS(array_value);
65
+ ATTACH_CALLBACKS(object_value);
66
+ ATTACH_CALLBACKS(object_field);
67
+ }
@@ -0,0 +1,13 @@
1
+ #ifndef Libgraphqlparser_EXT_H
2
+ #define Libgraphqlparser_EXT_H
3
+
4
+ #include <ruby.h>
5
+ #include <ruby/encoding.h>
6
+ #include <c/GraphQLParser.h>
7
+ #include <c/GraphQLAstNode.h>
8
+ #include <c/GraphQLAstVisitor.h>
9
+ #include <c/GraphQLAst.h>
10
+
11
+ void Init_libgraphqlparser();
12
+
13
+ #endif
@@ -0,0 +1,317 @@
1
+ #include "libgraphqlparser.h"
2
+
3
+ // These macros are a bit janky,
4
+ // they depend on the function signature
5
+ // being the same all the time: `(GraphQLAstNode* node, void* builder_ptr)`.
6
+ //
7
+ // Then they provide `rb_node` that you can work on in the function body.
8
+ #define BEGIN(node_name_string) \
9
+ VALUE rb_node = rb_funcall( \
10
+ (VALUE) builder_ptr, \
11
+ begin_visit_intern, \
12
+ 1, \
13
+ rb_str_new2(node_name_string) \
14
+ ); \
15
+ struct GraphQLAstLocation* location = malloc(sizeof(struct GraphQLAstLocation)); \
16
+ graphql_node_get_location((struct GraphQLAstNode *)node, location); \
17
+ rb_funcall(rb_node, line_set_intern, 1, INT2NUM(location->beginLine)); \
18
+ rb_funcall(rb_node, col_set_intern, 1, INT2NUM(location->beginColumn)); \
19
+ free(location); \
20
+
21
+ #define END \
22
+ rb_funcall( \
23
+ (VALUE) builder_ptr, \
24
+ end_visit_intern, \
25
+ 0 \
26
+ ); \
27
+
28
+ #define ADD_LITERAL(rb_value) \
29
+ rb_funcall( \
30
+ (VALUE) builder_ptr, \
31
+ add_value_intern, \
32
+ 1, \
33
+ rb_value \
34
+ ); \
35
+
36
+
37
+ #define ASSIGN_NAME(get_name_fn) \
38
+ rb_funcall(rb_node, name_set_intern, 1, \
39
+ rb_str_new2( \
40
+ GraphQLAstName_get_value( \
41
+ get_name_fn(node) \
42
+ ) \
43
+ ) \
44
+ ); \
45
+
46
+ #define ASSIGN_NAMED_TYPE(get_type_fn) \
47
+ rb_funcall( \
48
+ rb_node, \
49
+ type_set_intern, \
50
+ 1, \
51
+ rb_str_new2( \
52
+ GraphQLAstName_get_value( \
53
+ GraphQLAstNamedType_get_name( \
54
+ get_type_fn(node) \
55
+ ) \
56
+ ) \
57
+ ) \
58
+ ); \
59
+
60
+ VALUE type_set_intern, name_set_intern, add_value_intern, end_visit_intern, begin_visit_intern, line_set_intern, col_set_intern;
61
+ void init_visitor_functions() {
62
+ type_set_intern = rb_intern("type=");
63
+ name_set_intern = rb_intern("name=");
64
+ add_value_intern = rb_intern("add_value");
65
+ end_visit_intern = rb_intern("end_visit");
66
+ begin_visit_intern = rb_intern("begin_visit");
67
+ line_set_intern = rb_intern("line=");
68
+ col_set_intern = rb_intern("col=");
69
+ }
70
+
71
+ // There's a `begin_visit` and `end_visit` for each node.
72
+ // Some of the end_visit callbacks are empty but that's ok,
73
+ // It lets us use macros in the other files.
74
+
75
+ int document_begin_visit(const struct GraphQLAstDocument* node, void* builder_ptr) {
76
+ BEGIN("Document")
77
+ return 1;
78
+ }
79
+
80
+ void document_end_visit(const struct GraphQLAstDocument* node, void* builder_ptr) {
81
+ }
82
+
83
+ int operation_definition_begin_visit(const struct GraphQLAstOperationDefinition* node, void* builder_ptr) {
84
+ const struct GraphQLAstName* ast_operation_name;
85
+ const char* operation_type;
86
+ VALUE operation_type_str;
87
+
88
+ BEGIN("OperationDefinition")
89
+
90
+ ast_operation_name = GraphQLAstOperationDefinition_get_name(node);
91
+ if (ast_operation_name) {
92
+ const char* operation_name = GraphQLAstName_get_value(ast_operation_name);
93
+ rb_funcall(rb_node, name_set_intern, 1, rb_str_new2(operation_name));
94
+ }
95
+
96
+ operation_type = GraphQLAstOperationDefinition_get_operation(node);
97
+
98
+ if (operation_type) {
99
+ operation_type_str = rb_str_new2(operation_type);
100
+ } else {
101
+ operation_type_str = rb_str_new2("query");
102
+ }
103
+
104
+ rb_funcall(rb_node, rb_intern("operation_type="), 1, operation_type_str);
105
+
106
+ return 1;
107
+ }
108
+
109
+ void operation_definition_end_visit(const struct GraphQLAstOperationDefinition* node, void* builder_ptr) {
110
+ END
111
+ }
112
+
113
+ int variable_definition_begin_visit(const struct GraphQLAstVariableDefinition* node, void* builder_ptr) {
114
+ BEGIN("VariableDefinition")
115
+ return 1;
116
+ }
117
+
118
+ void variable_definition_end_visit(const struct GraphQLAstVariableDefinition* node, void* builder_ptr) {
119
+ END
120
+ }
121
+
122
+
123
+ int fragment_definition_begin_visit(const struct GraphQLAstFragmentDefinition* node, void* builder_ptr) {
124
+ BEGIN("FragmentDefinition")
125
+ ASSIGN_NAME(GraphQLAstFragmentDefinition_get_name)
126
+ ASSIGN_NAMED_TYPE(GraphQLAstFragmentDefinition_get_type_condition)
127
+ return 1;
128
+ }
129
+
130
+ void fragment_definition_end_visit(const struct GraphQLAstFragmentDefinition* node, void* builder_ptr) {
131
+ END
132
+ }
133
+
134
+
135
+ int variable_begin_visit(const struct GraphQLAstVariable* node, void* builder_ptr) {
136
+ BEGIN("VariableIdentifier")
137
+ // This might actually assign the name of a VariableDefinition:
138
+ ASSIGN_NAME(GraphQLAstVariable_get_name)
139
+ return 1;
140
+ }
141
+
142
+ void variable_end_visit(const struct GraphQLAstVariable* node, void* builder_ptr) {
143
+ END
144
+ }
145
+
146
+ int field_begin_visit(const struct GraphQLAstField* node, void* builder_ptr) {
147
+ const struct GraphQLAstName* ast_field_alias;
148
+ const char* str_field_alias;
149
+ BEGIN("Field")
150
+ ASSIGN_NAME(GraphQLAstField_get_name)
151
+
152
+ ast_field_alias = GraphQLAstField_get_alias(node);
153
+ if (ast_field_alias) {
154
+ str_field_alias = GraphQLAstName_get_value(ast_field_alias);
155
+ rb_funcall(rb_node, rb_intern("alias="), 1, rb_str_new2(str_field_alias));
156
+ }
157
+ return 1;
158
+ }
159
+
160
+ void field_end_visit(const struct GraphQLAstField* node, void* builder_ptr) {
161
+ END
162
+ }
163
+
164
+ int directive_begin_visit(const struct GraphQLAstDirective* node, void* builder_ptr) {
165
+ BEGIN("Directive")
166
+ ASSIGN_NAME(GraphQLAstDirective_get_name)
167
+ return 1;
168
+ }
169
+
170
+ void directive_end_visit(const struct GraphQLAstDirective* node, void* builder_ptr) {
171
+ END
172
+ }
173
+
174
+ int argument_begin_visit(const struct GraphQLAstArgument* node, void* builder_ptr) {
175
+ BEGIN("Argument")
176
+ ASSIGN_NAME(GraphQLAstArgument_get_name)
177
+ return 1;
178
+ }
179
+
180
+ void argument_end_visit(const struct GraphQLAstArgument* node, void* builder_ptr) {
181
+ END
182
+ }
183
+
184
+ int fragment_spread_begin_visit(const struct GraphQLAstFragmentSpread* node, void* builder_ptr) {
185
+ BEGIN("FragmentSpread")
186
+ ASSIGN_NAME(GraphQLAstFragmentSpread_get_name)
187
+ return 1;
188
+ }
189
+
190
+ void fragment_spread_end_visit(const struct GraphQLAstFragmentSpread* node, void* builder_ptr) {
191
+ END
192
+ }
193
+
194
+ int inline_fragment_begin_visit(const struct GraphQLAstInlineFragment* node, void* builder_ptr) {
195
+ BEGIN("InlineFragment")
196
+ ASSIGN_NAMED_TYPE(GraphQLAstInlineFragment_get_type_condition)
197
+ return 1;
198
+ }
199
+
200
+ void inline_fragment_end_visit(const struct GraphQLAstInlineFragment* node, void* builder_ptr) {
201
+ END
202
+ }
203
+
204
+ int list_type_begin_visit(const struct GraphQLAstListType* node, void* builder_ptr) {
205
+ BEGIN("ListType")
206
+ return 1;
207
+ }
208
+
209
+ void list_type_end_visit(const struct GraphQLAstListType* node, void* builder_ptr) {
210
+ END
211
+ }
212
+
213
+
214
+ int non_null_type_begin_visit(const struct GraphQLAstNonNullType* node, void* builder_ptr) {
215
+ BEGIN("NonNullType")
216
+ return 1;
217
+ }
218
+
219
+ void non_null_type_end_visit(const struct GraphQLAstNonNullType* node, void* builder_ptr) {
220
+ END
221
+ }
222
+
223
+ int named_type_begin_visit(const struct GraphQLAstNamedType* node, void* builder_ptr) {
224
+ BEGIN("TypeName")
225
+ ASSIGN_NAME(GraphQLAstNamedType_get_name)
226
+ return 1;
227
+ }
228
+
229
+ void named_type_end_visit(const struct GraphQLAstNamedType* node, void* builder_ptr) {
230
+ END
231
+ }
232
+
233
+
234
+ int float_value_begin_visit(const struct GraphQLAstFloatValue* node, void* builder_ptr) {
235
+ const char* str_float = GraphQLAstFloatValue_get_value(node);
236
+ VALUE rb_float = rb_funcall(rb_str_new2(str_float), rb_intern("to_f"), 0);
237
+ ADD_LITERAL(rb_float);
238
+ return 1;
239
+ }
240
+
241
+ void float_value_end_visit(const struct GraphQLAstFloatValue* node, void* builder_ptr) {
242
+ }
243
+
244
+ int int_value_begin_visit(const struct GraphQLAstIntValue* node, void* builder_ptr) {
245
+ const char* str_int = GraphQLAstIntValue_get_value(node);
246
+ VALUE rb_int = rb_funcall(rb_str_new2(str_int), rb_intern("to_i"), 0);
247
+ ADD_LITERAL(rb_int);
248
+ return 1;
249
+ }
250
+
251
+ void int_value_end_visit(const struct GraphQLAstIntValue* node, void* builder_ptr) {
252
+ }
253
+
254
+ int boolean_value_begin_visit(const struct GraphQLAstBooleanValue* node, void* builder_ptr) {
255
+ const int bool_value = GraphQLAstBooleanValue_get_value(node);
256
+ if (bool_value) {
257
+ ADD_LITERAL(Qtrue)
258
+ } else {
259
+ ADD_LITERAL(Qfalse)
260
+ }
261
+ return 1;
262
+ }
263
+
264
+ void boolean_value_end_visit(const struct GraphQLAstBooleanValue* node, void* builder_ptr) {
265
+ }
266
+
267
+ int string_value_begin_visit(const struct GraphQLAstStringValue* node, void* builder_ptr) {
268
+ const char* str_value = GraphQLAstStringValue_get_value(node);
269
+ VALUE rb_string = rb_str_new2(str_value);
270
+ int enc = rb_enc_find_index("UTF-8");
271
+ rb_enc_associate_index(rb_string, enc);
272
+ ADD_LITERAL(rb_string);
273
+ return 1;
274
+ }
275
+
276
+ void string_value_end_visit(const struct GraphQLAstStringValue* node, void* builder_ptr) {
277
+ }
278
+
279
+ int enum_value_begin_visit(const struct GraphQLAstEnumValue* node, void* builder_ptr) {
280
+ const char* str_value = GraphQLAstEnumValue_get_value(node);
281
+ VALUE rb_string = rb_str_new2(str_value);
282
+ int enc = rb_enc_find_index("UTF-8");
283
+ rb_enc_associate_index(rb_string, enc);
284
+ ADD_LITERAL(rb_string);
285
+ return 1;
286
+ }
287
+
288
+ void enum_value_end_visit(const struct GraphQLAstEnumValue* node, void* builder_ptr) {
289
+ }
290
+
291
+ int array_value_begin_visit(const struct GraphQLAstArrayValue* node, void* builder_ptr) {
292
+ BEGIN("ArrayLiteral")
293
+ return 1;
294
+ }
295
+
296
+ void array_value_end_visit(const struct GraphQLAstArrayValue* node, void* builder_ptr) {
297
+ END
298
+ }
299
+
300
+ int object_value_begin_visit(const struct GraphQLAstObjectValue* node, void* builder_ptr) {
301
+ BEGIN("InputObject")
302
+ return 1;
303
+ }
304
+
305
+ void object_value_end_visit(const struct GraphQLAstObjectValue* node, void* builder_ptr) {
306
+ END
307
+ }
308
+
309
+ int object_field_begin_visit(const struct GraphQLAstObjectField* node, void* builder_ptr) {
310
+ BEGIN("Argument")
311
+ ASSIGN_NAME(GraphQLAstObjectField_get_name)
312
+ return 1;
313
+ }
314
+
315
+ void object_field_end_visit(const struct GraphQLAstObjectField* node, void* builder_ptr) {
316
+ END
317
+ }
@@ -0,0 +1,31 @@
1
+ #ifndef Libgraphqlparser_visitor_functions_H
2
+ #define Libgraphqlparser_visitor_functions_H
3
+
4
+ #define VISITOR_CALLBACKS(snake_name, camel_name) \
5
+ int snake_name##_begin_visit(const struct GraphQLAst##camel_name* document, void* builder_ptr); \
6
+ void snake_name##_end_visit(const struct GraphQLAst##camel_name* document, void* builder_ptr); \
7
+
8
+ void init_visitor_functions();
9
+ VISITOR_CALLBACKS(document, Document);
10
+ VISITOR_CALLBACKS(operation_definition, OperationDefinition);
11
+ VISITOR_CALLBACKS(variable_definition, VariableDefinition);
12
+ VISITOR_CALLBACKS(fragment_definition, FragmentDefinition);
13
+ VISITOR_CALLBACKS(variable, Variable);
14
+ VISITOR_CALLBACKS(field, Field);
15
+ VISITOR_CALLBACKS(directive, Directive);
16
+ VISITOR_CALLBACKS(argument, Argument);
17
+ VISITOR_CALLBACKS(fragment_spread, FragmentSpread);
18
+ VISITOR_CALLBACKS(inline_fragment, InlineFragment);
19
+ VISITOR_CALLBACKS(list_type, ListType);
20
+ VISITOR_CALLBACKS(non_null_type, NonNullType);
21
+ VISITOR_CALLBACKS(named_type, NamedType);
22
+ VISITOR_CALLBACKS(float_value, FloatValue);
23
+ VISITOR_CALLBACKS(int_value, IntValue);
24
+ VISITOR_CALLBACKS(boolean_value, BooleanValue);
25
+ VISITOR_CALLBACKS(string_value, StringValue);
26
+ VISITOR_CALLBACKS(enum_value, EnumValue);
27
+ VISITOR_CALLBACKS(array_value, ArrayValue);
28
+ VISITOR_CALLBACKS(object_value, ObjectValue);
29
+ VISITOR_CALLBACKS(object_field, ObjectField);
30
+
31
+ #endif
@@ -0,0 +1,30 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'graphql/libgraphqlparser/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'graphql-libgraphqlparser'
7
+ spec.version = GraphQL::Libgraphqlparser::VERSION
8
+ spec.authors = ['Robert Mosolgo']
9
+ spec.homepage = 'https://github.com/rmosolgo/graphql-libgraphqlparser-ruby'
10
+ spec.email = ['rdmosolgo@gmail.com']
11
+ spec.summary = "Use Libgraphqlparser to parse queries for the GraphQL gem"
12
+ spec.license = "minitest"
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ['lib']
18
+
19
+ spec.add_runtime_dependency 'graphql', '~> 0.10.0'
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.0'
22
+ spec.add_development_dependency "guard", "~> 2.12"
23
+ spec.add_development_dependency "guard-bundler", "~> 2.1"
24
+ spec.add_development_dependency "guard-minitest", "~> 2.4"
25
+ spec.add_development_dependency "guard-rake", "~> 1.0"
26
+ spec.add_development_dependency 'minitest', '~> 5.8'
27
+ spec.add_development_dependency "minitest-reporters", "~>1.0"
28
+ spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rake-compiler', '~> 0.9'
30
+ end
@@ -0,0 +1,69 @@
1
+ module GraphQL
2
+ module Libgraphqlparser
3
+ # Keeps a stack of parse results, exposing the latest one.
4
+ # The C parser can call methods on this object, assuming
5
+ # they'll be applied to the right object.
6
+ class Builder
7
+ include GraphQL::Language
8
+
9
+ def initialize
10
+ @ast_stack = []
11
+ end
12
+
13
+ def document
14
+ @ast_stack.first
15
+ end
16
+
17
+ def current
18
+ @ast_stack.last
19
+ end
20
+
21
+ def begin_visit(node_class_name)
22
+ # p "--> BEGIN #{node_class_name}"
23
+ node_class = Nodes.const_get(node_class_name)
24
+ node = node_class.new
25
+ case node
26
+ when Nodes::OperationDefinition, Nodes::FragmentDefinition
27
+ current.definitions << node
28
+ when Nodes::VariableDefinition
29
+ current.variables << node
30
+ when Nodes::VariableIdentifier
31
+ if current.is_a?(Nodes::VariableDefinition)
32
+ node = current
33
+ else
34
+ current.value = node
35
+ end
36
+ when Nodes::Directive
37
+ current.directives << node
38
+ when Nodes::Argument
39
+ current.arguments << node
40
+ when Nodes::InlineFragment, Nodes::FragmentSpread, Nodes::Field
41
+ current.selections << node
42
+ when Nodes::TypeName, Nodes::ListType, Nodes::NonNullType
43
+ # Using ||= because FragmentDefinition has already assigned
44
+ # this as a plain string :(
45
+ current.type ||= node
46
+ when Nodes::ArrayLiteral
47
+ # mutability! 🎉
48
+ current.value = node.values
49
+ when Nodes::InputObject
50
+ current.value = node
51
+ end
52
+
53
+ @ast_stack.push(node)
54
+ node
55
+ end
56
+
57
+ def end_visit
58
+ removed = @ast_stack.pop
59
+ # p "--> END #{removed}"
60
+ removed
61
+ end
62
+
63
+ # This is for convenience from C
64
+ def add_value(string_value)
65
+ current.value = string_value
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,132 @@
1
+ module GraphQL
2
+ module Language
3
+ module Nodes
4
+ class AbstractNode
5
+ alias :old_initialize :initialize
6
+ # Allow initialize with no args
7
+ def initialize(*args)
8
+ if args.any?
9
+ old_initialize(*args)
10
+ end
11
+ end
12
+
13
+ def position
14
+ [line, col]
15
+ end
16
+ end
17
+
18
+ # Document = AbstractNode.create(:parts)
19
+ class Document
20
+ def definitions
21
+ @parts ||= []
22
+ end
23
+ end
24
+
25
+ # OperationDefinition = AbstractNode.create(:operation_type, :name, :variables, :directives, :selections)
26
+ class OperationDefinition
27
+ def variables
28
+ @variables ||= []
29
+ end
30
+
31
+ def selections
32
+ @selections ||= []
33
+ end
34
+ end
35
+
36
+ # Variable = AbstractNode.create(:name, :type, :default_value)
37
+ VariableDefinition = Variable
38
+ class VariableDefinition
39
+ # Make it behave like an Argument
40
+ def value=(new_value)
41
+ @default_value = new_value
42
+ end
43
+ end
44
+
45
+ # VariableIdentifier = AbstractNode.create(:name)
46
+
47
+ # FragmentDefinition = AbstractNode.create(:name, :type, :directives, :selections)
48
+ class FragmentDefinition
49
+ def selections
50
+ @selections ||= []
51
+ end
52
+ end
53
+
54
+ # Field = AbstractNode.create(:name, :alias, :arguments, :directives, :selections)
55
+ class Field
56
+ def selections
57
+ @selections ||= []
58
+ end
59
+
60
+ def directives
61
+ @directives ||= []
62
+ end
63
+
64
+ def arguments
65
+ @arguments ||= []
66
+ end
67
+ end
68
+
69
+ # Directive = AbstractNode.create(:name, :arguments)
70
+ class Directive
71
+ def arguments
72
+ @arguments ||= []
73
+ end
74
+ end
75
+
76
+ # FragmentSpread = AbstractNode.create(:name, :directives)
77
+ class FragmentSpread
78
+ def directives
79
+ @directives ||= []
80
+ end
81
+ end
82
+
83
+ # InlineFragment = AbstractNode.create(:type, :directives, :selections)
84
+ class InlineFragment
85
+ def directives
86
+ @directives ||= []
87
+ end
88
+ def selections
89
+ @selections ||= []
90
+ end
91
+ end
92
+
93
+ # ListType = AbstractNode.create(:of_type)
94
+ # NonNullType = AbstractNode.create(:of_type)
95
+ # TypeName = AbstractNode.create(:name)
96
+ class ListType
97
+ def type=(inner_type)
98
+ self.of_type = inner_type
99
+ end
100
+ def type; self.of_type; end
101
+ end
102
+ class NonNullType
103
+ def type=(inner_type)
104
+ self.of_type = inner_type
105
+ end
106
+ def type; self.of_type; end
107
+ end
108
+
109
+ # Argument = AbstractNode.create(:name, :value)
110
+ # Enum = AbstractNode.create(:name)
111
+ class InputObject
112
+ def arguments
113
+ @pairs ||= []
114
+ end
115
+ end
116
+
117
+ class ArrayLiteral < AbstractNode
118
+ attr_reader :values
119
+
120
+ def initialize
121
+ @values = []
122
+ end
123
+
124
+ # This makes it behave like Argument,
125
+ # while it's on the stack it can gobble up values
126
+ def value=(new_value)
127
+ values << new_value
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,5 @@
1
+ module GraphQL
2
+ module Libgraphqlparser
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,26 @@
1
+ require 'graphql'
2
+ require 'graphql/libgraphqlparser/builder'
3
+ require 'graphql/libgraphqlparser/libgraphqlparser'
4
+ require 'graphql/libgraphqlparser/monkey_patches/abstract_node'
5
+ require 'graphql/libgraphqlparser/version'
6
+
7
+ module GraphQL
8
+ module Libgraphqlparser
9
+ def self.parse(string)
10
+ builder = builder_parse(string)
11
+ builder.document
12
+ end
13
+ end
14
+
15
+ class << self
16
+ def parse_with_libgraphqlparser(string)
17
+ Libgraphqlparser.parse(string)
18
+ end
19
+
20
+ alias :parse_without_libgraphqlparser :parse
21
+
22
+ def parse(string, as: nil)
23
+ parse_with_libgraphqlparser(string)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,231 @@
1
+ require 'test_helper'
2
+
3
+ describe GraphQL::Libgraphqlparser do
4
+ let(:document) { GraphQL::Libgraphqlparser.parse(query_string) }
5
+ let(:query_string) {%|
6
+ query getStuff($someVar: Int = 1, $anotherVar: [String!] ) {
7
+ myField: someField(someArg: $someVar, ok: 1.4) @skip(if: $anotherVar) @thing(or: "Whatever")
8
+
9
+ anotherField(someArg: [1,2,3]) {
10
+ nestedField
11
+ ... moreNestedFields @skip(if: true)
12
+ }
13
+
14
+ ... on OtherType @include(unless: false){
15
+ field
16
+ anotherField
17
+ }
18
+
19
+ }
20
+
21
+ fragment moreNestedFields on NestedType {
22
+ anotherNestedField
23
+ }
24
+ |}
25
+
26
+ describe '.parse' do
27
+ it 'parses queries' do
28
+ assert document
29
+ end
30
+
31
+ describe "visited nodes" do
32
+ let(:query) { document.definitions.first }
33
+ let(:fragment_def) { document.definitions.last }
34
+
35
+ it "creates a valid document" do
36
+ assert document.is_a?(GraphQL::Language::Nodes::Document)
37
+ assert_equal 2, document.definitions.length
38
+ end
39
+
40
+ it "creates a valid operation" do
41
+ assert query.is_a?(GraphQL::Language::Nodes::OperationDefinition)
42
+ assert_equal "getStuff", query.name
43
+ assert_equal "query", query.operation_type
44
+ assert_equal 2, query.variables.length
45
+ assert_equal 3, query.selections.length
46
+ assert_equal [2, 5], [query.line, query.col]
47
+ end
48
+
49
+ it "creates a valid fragment definition" do
50
+ assert fragment_def.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
51
+ assert_equal "moreNestedFields", fragment_def.name
52
+ assert_equal 1, fragment_def.selections.length
53
+ assert_equal "NestedType", fragment_def.type
54
+ assert_equal [17, 5], fragment_def.position
55
+ end
56
+
57
+ describe "variable definitions" do
58
+ let(:optional_var) { query.variables.first }
59
+ it "gets name and type" do
60
+ assert_equal "someVar", optional_var.name
61
+ assert_equal "Int", optional_var.type.name
62
+ end
63
+
64
+ it "gets default value" do
65
+ assert_equal 1, optional_var.default_value
66
+ end
67
+
68
+ it "gets position info" do
69
+ assert_equal [2, 20], optional_var.position
70
+ end
71
+ end
72
+
73
+ describe "fields" do
74
+ let(:leaf_field) { query.selections.first }
75
+ let(:parent_field) { query.selections[1] }
76
+
77
+ it "gets name, alias, arguments and directives" do
78
+ assert_equal "someField", leaf_field.name
79
+ assert_equal "myField", leaf_field.alias
80
+ assert_equal 2, leaf_field.directives.length
81
+ assert_equal 2, leaf_field.arguments.length
82
+ end
83
+
84
+ it "gets nested fields" do
85
+ assert_equal 2, parent_field.selections.length
86
+ end
87
+
88
+ it "gets location info" do
89
+ assert_equal [3 ,7], leaf_field.position
90
+ end
91
+ end
92
+
93
+ describe "arguments" do
94
+ let(:literal_argument) { query.selections.first.arguments.last }
95
+ let(:variable_argument) { query.selections.first.arguments.first }
96
+
97
+ it "gets name and literal value" do
98
+ assert_equal "ok", literal_argument.name
99
+ assert_equal 1.4, literal_argument.value
100
+ end
101
+
102
+ it "gets name and variable value" do
103
+ assert_equal "someArg", variable_argument.name
104
+ assert_equal "someVar", variable_argument.value.name
105
+ end
106
+
107
+ it "gets position info" do
108
+ assert_equal [3, 26], variable_argument.position
109
+ end
110
+ end
111
+
112
+ describe "fragment spreads" do
113
+ let(:fragment_spread) { query.selections[1].selections.last }
114
+ it "gets the name and directives" do
115
+ assert_equal "moreNestedFields", fragment_spread.name
116
+ assert_equal 1, fragment_spread.directives.length
117
+ end
118
+
119
+ it "gets position info" do
120
+ assert_equal [7, 9], fragment_spread.position
121
+ end
122
+ end
123
+
124
+ describe "directives" do
125
+ let(:variable_directive) { query.selections.first.directives.first }
126
+
127
+ it "gets the name and arguments" do
128
+ assert_equal "skip", variable_directive.name
129
+ assert_equal "if", variable_directive.arguments.first.name
130
+ assert_equal 1, variable_directive.arguments.length
131
+ end
132
+
133
+ it "gets position info" do
134
+ assert_equal [3, 54], variable_directive.position
135
+ end
136
+ end
137
+
138
+ describe "inline fragments" do
139
+ let(:inline_fragment) { query.selections[2] }
140
+ it "gets the type and directives" do
141
+ assert_equal "OtherType", inline_fragment.type
142
+ assert_equal 2, inline_fragment.selections.length
143
+ assert_equal 1, inline_fragment.directives.length
144
+ end
145
+
146
+ it "gets position info" do
147
+ assert_equal [10, 7], inline_fragment.position
148
+ end
149
+ end
150
+
151
+ describe "inputs" do
152
+ let(:query_string) {%|
153
+ {
154
+ field(
155
+ int: 3,
156
+ float: 4.7e-24,
157
+ bool: false,
158
+ string: "☀︎🏆",
159
+ enum: ENUM_NAME,
160
+ array: [7, 8, 9]
161
+ object: {a: [1,2,3], b: {c: "4"}}
162
+ )
163
+ }
164
+ |}
165
+
166
+ let(:inputs) { document.definitions.first.selections.first.arguments }
167
+
168
+ it "parses ints" do
169
+ assert_equal 3, inputs[0].value
170
+ end
171
+
172
+ it "parses floats" do
173
+ assert_equal 0.47e-23, inputs[1].value
174
+ end
175
+
176
+ it "parses booleans" do
177
+ assert_equal false, inputs[2].value
178
+ end
179
+
180
+ it "parses UTF-8 strings" do
181
+ assert_equal "☀︎🏆", inputs[3].value
182
+ end
183
+
184
+ it "parses enums" do
185
+ assert_equal "ENUM_NAME", inputs[4].value
186
+ end
187
+
188
+ it "parses arrays" do
189
+ assert_equal [7,8,9], inputs[5].value
190
+ end
191
+
192
+ it "parses objects" do
193
+ obj = inputs[6].value
194
+ assert_equal "a", obj.arguments[0].name
195
+ assert_equal [1,2,3], obj.arguments[0].value
196
+ assert_equal "b", obj.arguments[1].name
197
+ assert_equal "c", obj.arguments[1].value.arguments[0].name
198
+ assert_equal "4", obj.arguments[1].value.arguments[0].value
199
+ end
200
+ end
201
+ end
202
+
203
+ describe "unnamed queries" do
204
+ let(:query_string) {%|
205
+ { name, age, height }
206
+ |}
207
+ let(:operation) { document.definitions.first }
208
+
209
+ it "parses unnamed queries" do
210
+ assert_equal 1, document.definitions.length
211
+ assert_equal "query", operation.operation_type
212
+ assert_equal nil, operation.name
213
+ assert_equal 3, operation.selections.length
214
+ end
215
+ end
216
+
217
+ describe "introspection query" do
218
+ let(:query_string) { GraphQL::Introspection::INTROSPECTION_QUERY }
219
+ it "parses a big ol' query" do
220
+ assert(document)
221
+ end
222
+ end
223
+ end
224
+
225
+ describe "errors" do
226
+ let(:query_string) {%| query doSomething { bogus { } |}
227
+ it "raises a parse error" do
228
+ err = assert_raises(GraphQL::Libgraphqlparser::ParseError) { document }
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,6 @@
1
+ require 'graphql'
2
+ require 'graphql/libgraphqlparser'
3
+ require 'minitest'
4
+ require 'minitest/autorun'
5
+ require "minitest/reporters"
6
+ Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
metadata ADDED
@@ -0,0 +1,205 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: graphql-libgraphqlparser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Robert Mosolgo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: graphql
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.10.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.10.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard-bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.4'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.4'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '5.8'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '5.8'
111
+ - !ruby/object:Gem::Dependency
112
+ name: minitest-reporters
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rake
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '10.0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '10.0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rake-compiler
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.9'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.9'
153
+ description:
154
+ email:
155
+ - rdmosolgo@gmail.com
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - ".gitignore"
161
+ - ".travis.yml"
162
+ - Gemfile
163
+ - Guardfile
164
+ - README.md
165
+ - Rakefile
166
+ - benchmark.rb
167
+ - ext/libgraphqlparser/extconf.rb
168
+ - ext/libgraphqlparser/libgraphqlparser.c
169
+ - ext/libgraphqlparser/libgraphqlparser.h
170
+ - ext/libgraphqlparser/visitor_functions.c
171
+ - ext/libgraphqlparser/visitor_functions.h
172
+ - graphql-libgraphqlparser.gemspec
173
+ - lib/graphql/libgraphqlparser.rb
174
+ - lib/graphql/libgraphqlparser/builder.rb
175
+ - lib/graphql/libgraphqlparser/monkey_patches/abstract_node.rb
176
+ - lib/graphql/libgraphqlparser/version.rb
177
+ - test/graphql/libgraphqlparser_test.rb
178
+ - test/test_helper.rb
179
+ homepage: https://github.com/rmosolgo/graphql-libgraphqlparser-ruby
180
+ licenses:
181
+ - minitest
182
+ metadata: {}
183
+ post_install_message:
184
+ rdoc_options: []
185
+ require_paths:
186
+ - lib
187
+ required_ruby_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ required_rubygems_version: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ requirements: []
198
+ rubyforge_project:
199
+ rubygems_version: 2.2.2
200
+ signing_key:
201
+ specification_version: 4
202
+ summary: Use Libgraphqlparser to parse queries for the GraphQL gem
203
+ test_files:
204
+ - test/graphql/libgraphqlparser_test.rb
205
+ - test/test_helper.rb