graphql-libgraphqlparser 0.0.1

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.
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