rails-graphql 0.2.1 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/console.rb +18 -0
- data/ext/extconf.h +3 -0
- data/ext/extconf.rb +1 -54
- data/ext/gql_parser.c +631 -0
- data/ext/gql_parser.h +21 -0
- data/ext/shared.c +477 -0
- data/ext/shared.h +177 -0
- data/lib/generators/graphql/channel_generator.rb +27 -0
- data/lib/generators/graphql/controller_generator.rb +9 -4
- data/lib/generators/graphql/install_generator.rb +49 -0
- data/lib/generators/graphql/schema_generator.rb +9 -4
- data/lib/generators/graphql/templates/channel.erb +7 -0
- data/lib/generators/graphql/templates/config.rb +97 -0
- data/lib/generators/graphql/templates/controller.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +5 -3
- data/lib/gql_parser.so +0 -0
- data/lib/rails/graphql/adapters/mysql_adapter.rb +59 -0
- data/lib/rails/graphql/adapters/pg_adapter.rb +25 -22
- data/lib/rails/graphql/adapters/sqlite_adapter.rb +17 -14
- data/lib/rails/graphql/alternative/field_set.rb +48 -0
- data/lib/rails/graphql/alternative/mutation.rb +17 -0
- data/lib/rails/graphql/alternative/query.rb +98 -0
- data/lib/rails/graphql/alternative/subscription.rb +18 -0
- data/lib/rails/graphql/alternative.rb +20 -0
- data/lib/rails/graphql/argument.rb +25 -26
- data/lib/rails/graphql/callback.rb +30 -14
- data/lib/rails/graphql/collectors/hash_collector.rb +26 -7
- data/lib/rails/graphql/collectors/idented_collector.rb +10 -7
- data/lib/rails/graphql/collectors/json_collector.rb +43 -17
- data/lib/rails/graphql/collectors.rb +4 -4
- data/lib/rails/graphql/config.rb +154 -23
- data/lib/rails/graphql/directive/cached_directive.rb +33 -0
- data/lib/rails/graphql/directive/deprecated_directive.rb +10 -10
- data/lib/rails/graphql/directive/include_directive.rb +4 -4
- data/lib/rails/graphql/directive/skip_directive.rb +4 -4
- data/lib/rails/graphql/directive/specified_by_directive.rb +24 -0
- data/lib/rails/graphql/directive.rb +134 -73
- data/lib/rails/graphql/errors.rb +33 -4
- data/lib/rails/graphql/event.rb +21 -9
- data/lib/rails/graphql/field/authorized_field.rb +17 -6
- data/lib/rails/graphql/field/input_field.rb +8 -12
- data/lib/rails/graphql/field/mutation_field.rb +43 -9
- data/lib/rails/graphql/field/output_field.rb +112 -12
- data/lib/rails/graphql/field/proxied_field.rb +35 -26
- data/lib/rails/graphql/field/resolved_field.rb +27 -25
- data/lib/rails/graphql/field/scoped_config.rb +10 -4
- data/lib/rails/graphql/field/subscription_field.rb +123 -0
- data/lib/rails/graphql/field/typed_field.rb +69 -24
- data/lib/rails/graphql/field.rb +89 -74
- data/lib/rails/graphql/global_id.rb +89 -0
- data/lib/rails/graphql/helpers/attribute_delegator.rb +5 -5
- data/lib/rails/graphql/helpers/inherited_collection/array.rb +51 -0
- data/lib/rails/graphql/helpers/inherited_collection/base.rb +45 -0
- data/lib/rails/graphql/helpers/inherited_collection/hash.rb +88 -0
- data/lib/rails/graphql/helpers/inherited_collection.rb +25 -76
- data/lib/rails/graphql/helpers/instantiable.rb +15 -0
- data/lib/rails/graphql/helpers/leaf_from_ar.rb +7 -7
- data/lib/rails/graphql/helpers/registerable.rb +44 -62
- data/lib/rails/graphql/helpers/unregisterable.rb +16 -0
- data/lib/rails/graphql/helpers/with_arguments.rb +33 -28
- data/lib/rails/graphql/helpers/with_assignment.rb +6 -6
- data/lib/rails/graphql/helpers/with_callbacks.rb +28 -11
- data/lib/rails/graphql/helpers/with_description.rb +73 -0
- data/lib/rails/graphql/helpers/with_directives.rb +58 -30
- data/lib/rails/graphql/helpers/with_events.rb +22 -23
- data/lib/rails/graphql/helpers/with_fields.rb +86 -26
- data/lib/rails/graphql/helpers/with_global_id.rb +22 -0
- data/lib/rails/graphql/helpers/with_name.rb +44 -0
- data/lib/rails/graphql/helpers/with_namespace.rb +7 -4
- data/lib/rails/graphql/helpers/with_owner.rb +8 -7
- data/lib/rails/graphql/helpers/with_schema_fields.rb +162 -56
- data/lib/rails/graphql/helpers/with_validator.rb +9 -9
- data/lib/rails/graphql/helpers.rb +10 -3
- data/lib/rails/graphql/introspection.rb +43 -36
- data/lib/rails/graphql/railtie.rb +89 -33
- data/lib/rails/graphql/railties/app/base_channel.rb +10 -0
- data/lib/rails/graphql/railties/app/base_controller.rb +12 -0
- data/lib/rails/graphql/railties/app/views/_cable.js.erb +56 -0
- data/lib/rails/graphql/railties/app/views/_fetch.js.erb +20 -0
- data/lib/rails/graphql/railties/app/views/graphiql.html.erb +101 -0
- data/lib/rails/graphql/railties/base_generator.rb +5 -17
- data/lib/rails/graphql/railties/channel.rb +157 -0
- data/lib/rails/graphql/railties/controller.rb +91 -25
- data/lib/rails/graphql/railties/controller_runtime.rb +5 -5
- data/lib/rails/graphql/railties/log_subscriber.rb +81 -14
- data/lib/rails/graphql/request/arguments.rb +26 -50
- data/lib/rails/graphql/request/backtrace.rb +212 -0
- data/lib/rails/graphql/request/component/field.rb +98 -70
- data/lib/rails/graphql/request/component/fragment.rb +80 -26
- data/lib/rails/graphql/request/component/operation/subscription.rb +162 -4
- data/lib/rails/graphql/request/component/operation.rb +73 -34
- data/lib/rails/graphql/request/component/spread.rb +79 -27
- data/lib/rails/graphql/request/component/typename.rb +28 -13
- data/lib/rails/graphql/request/component.rb +77 -36
- data/lib/rails/graphql/request/context.rb +19 -9
- data/lib/rails/graphql/request/errors.rb +16 -6
- data/lib/rails/graphql/request/event.rb +23 -8
- data/lib/rails/graphql/request/helpers/directives.rb +69 -27
- data/lib/rails/graphql/request/helpers/selection_set.rb +57 -25
- data/lib/rails/graphql/request/helpers/value_writers.rb +24 -19
- data/lib/rails/graphql/request/prepared_data.rb +100 -0
- data/lib/rails/graphql/request/steps/authorizable.rb +24 -14
- data/lib/rails/graphql/request/steps/organizable.rb +111 -49
- data/lib/rails/graphql/request/steps/{prepareable.rb → preparable.rb} +21 -8
- data/lib/rails/graphql/request/steps/{resolveable.rb → resolvable.rb} +16 -7
- data/lib/rails/graphql/request/strategy/cached_strategy.rb +64 -0
- data/lib/rails/graphql/request/strategy/dynamic_instance.rb +6 -6
- data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +6 -13
- data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +9 -9
- data/lib/rails/graphql/request/strategy.rb +147 -77
- data/lib/rails/graphql/request/subscription.rb +82 -0
- data/lib/rails/graphql/request.rb +353 -104
- data/lib/rails/graphql/schema.rb +251 -106
- data/lib/rails/graphql/shortcuts.rb +33 -8
- data/lib/rails/graphql/source/active_record/builders.rb +64 -51
- data/lib/rails/graphql/source/active_record_source.rb +158 -82
- data/lib/rails/graphql/source/base.rb +83 -0
- data/lib/rails/graphql/source/builder.rb +115 -0
- data/lib/rails/graphql/source/scoped_arguments.rb +39 -21
- data/lib/rails/graphql/source.rb +90 -228
- data/lib/rails/graphql/subscription/provider/action_cable.rb +113 -0
- data/lib/rails/graphql/subscription/provider/base.rb +192 -0
- data/lib/rails/graphql/subscription/provider.rb +18 -0
- data/lib/rails/graphql/subscription/store/base.rb +141 -0
- data/lib/rails/graphql/subscription/store/memory.rb +136 -0
- data/lib/rails/graphql/subscription/store.rb +19 -0
- data/lib/rails/graphql/subscription.rb +17 -0
- data/lib/rails/graphql/to_gql.rb +29 -32
- data/lib/rails/graphql/type/creator.rb +196 -0
- data/lib/rails/graphql/type/enum/directive_location_enum.rb +11 -11
- data/lib/rails/graphql/type/enum/type_kind_enum.rb +3 -3
- data/lib/rails/graphql/type/enum.rb +44 -50
- data/lib/rails/graphql/type/input.rb +92 -25
- data/lib/rails/graphql/type/interface.rb +29 -28
- data/lib/rails/graphql/type/object/directive_object.rb +10 -9
- data/lib/rails/graphql/type/object/enum_value_object.rb +3 -3
- data/lib/rails/graphql/type/object/field_object.rb +24 -6
- data/lib/rails/graphql/type/object/input_value_object.rb +6 -7
- data/lib/rails/graphql/type/object/schema_object.rb +5 -8
- data/lib/rails/graphql/type/object/type_object.rb +62 -25
- data/lib/rails/graphql/type/object.rb +34 -26
- data/lib/rails/graphql/type/scalar/any_scalar.rb +30 -0
- data/lib/rails/graphql/type/scalar/bigint_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar/binary_scalar.rb +5 -3
- data/lib/rails/graphql/type/scalar/boolean_scalar.rb +8 -8
- data/lib/rails/graphql/type/scalar/date_scalar.rb +5 -3
- data/lib/rails/graphql/type/scalar/date_time_scalar.rb +5 -3
- data/lib/rails/graphql/type/scalar/decimal_scalar.rb +5 -3
- data/lib/rails/graphql/type/scalar/float_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar/id_scalar.rb +6 -5
- data/lib/rails/graphql/type/scalar/int_scalar.rb +6 -5
- data/lib/rails/graphql/type/scalar/json_scalar.rb +41 -0
- data/lib/rails/graphql/type/scalar/string_scalar.rb +18 -4
- data/lib/rails/graphql/type/scalar/time_scalar.rb +8 -6
- data/lib/rails/graphql/type/scalar.rb +26 -23
- data/lib/rails/graphql/type/union.rb +21 -18
- data/lib/rails/graphql/type.rb +43 -26
- data/lib/rails/graphql/type_map.rb +268 -165
- data/lib/rails/graphql/uri.rb +167 -0
- data/lib/rails/graphql/version.rb +19 -3
- data/lib/rails/graphql.rake +3 -0
- data/lib/rails/graphql.rb +91 -56
- data/lib/rails-graphql.rb +1 -1
- data/test/assets/en.yml +29 -0
- data/test/assets/introspection-mem.txt +1 -1
- data/test/assets/introspection.gql +2 -0
- data/test/assets/mem.gql +86 -99
- data/test/assets/mysql.gql +406 -0
- data/test/assets/sqlite.gql +96 -73
- data/test/assets/translate.gql +346 -0
- data/test/config.rb +19 -8
- data/test/graphql/schema_test.rb +14 -50
- data/test/graphql/source_test.rb +8 -85
- data/test/graphql/type/enum_test.rb +207 -203
- data/test/graphql/type/input_test.rb +14 -9
- data/test/graphql/type/interface_test.rb +12 -9
- data/test/graphql/type/object_test.rb +8 -2
- data/test/graphql/type/scalar/any_scalar_test.rb +38 -0
- data/test/graphql/type/scalar/boolean_scalar_test.rb +6 -3
- data/test/graphql/type/scalar/json_scalar_test.rb +23 -0
- data/test/graphql/type_map_test.rb +63 -81
- data/test/graphql/type_test.rb +0 -19
- data/test/graphql_test.rb +1 -1
- data/test/integration/{authorization/authorization_test.rb → authorization_test.rb} +40 -14
- data/test/integration/config.rb +36 -3
- data/test/integration/customization_test.rb +39 -0
- data/test/integration/global_id_test.rb +99 -0
- data/test/integration/memory/star_wars_introspection_test.rb +24 -16
- data/test/integration/memory/star_wars_query_test.rb +54 -3
- data/test/integration/memory/star_wars_validation_test.rb +3 -3
- data/test/integration/mysql/star_wars_introspection_test.rb +25 -0
- data/test/integration/persisted_query_test.rb +87 -0
- data/test/integration/resolver_precedence_test.rb +154 -0
- data/test/integration/schemas/memory.rb +24 -10
- data/test/integration/schemas/mysql.rb +62 -0
- data/test/integration/schemas/sqlite.rb +21 -12
- data/test/integration/sqlite/star_wars_global_id_test.rb +89 -0
- data/test/integration/sqlite/star_wars_introspection_test.rb +10 -0
- data/test/integration/sqlite/star_wars_query_test.rb +14 -1
- data/test/integration/translate_test.rb +73 -0
- data/test/test_ext.rb +16 -13
- metadata +125 -161
- data/ext/depend +0 -3
- data/ext/graphqlparser/Ast.cpp +0 -346
- data/ext/graphqlparser/Ast.h +0 -1214
- data/ext/graphqlparser/AstNode.h +0 -36
- data/ext/graphqlparser/AstVisitor.h +0 -137
- data/ext/graphqlparser/GraphQLParser.cpp +0 -76
- data/ext/graphqlparser/GraphQLParser.h +0 -55
- data/ext/graphqlparser/JsonVisitor.cpp +0 -161
- data/ext/graphqlparser/JsonVisitor.cpp.inc +0 -456
- data/ext/graphqlparser/JsonVisitor.h +0 -121
- data/ext/graphqlparser/JsonVisitor.h.inc +0 -110
- data/ext/graphqlparser/VERSION +0 -1
- data/ext/graphqlparser/c/GraphQLAst.cpp +0 -324
- data/ext/graphqlparser/c/GraphQLAst.h +0 -180
- data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +0 -44
- data/ext/graphqlparser/c/GraphQLAstNode.cpp +0 -25
- data/ext/graphqlparser/c/GraphQLAstNode.h +0 -33
- data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +0 -21
- data/ext/graphqlparser/c/GraphQLAstToJSON.h +0 -24
- data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +0 -55
- data/ext/graphqlparser/c/GraphQLAstVisitor.h +0 -53
- data/ext/graphqlparser/c/GraphQLParser.cpp +0 -35
- data/ext/graphqlparser/c/GraphQLParser.h +0 -54
- data/ext/graphqlparser/dump_json_ast.cpp +0 -48
- data/ext/graphqlparser/lexer.lpp +0 -324
- data/ext/graphqlparser/parser.ypp +0 -693
- data/ext/graphqlparser/parsergen/lexer.cpp +0 -2633
- data/ext/graphqlparser/parsergen/lexer.h +0 -528
- data/ext/graphqlparser/parsergen/location.hh +0 -189
- data/ext/graphqlparser/parsergen/parser.tab.cpp +0 -3300
- data/ext/graphqlparser/parsergen/parser.tab.hpp +0 -646
- data/ext/graphqlparser/parsergen/position.hh +0 -179
- data/ext/graphqlparser/parsergen/stack.hh +0 -156
- data/ext/graphqlparser/syntaxdefs.h +0 -19
- data/ext/libgraphqlparser/AstNode.h +0 -36
- data/ext/libgraphqlparser/CMakeLists.txt +0 -148
- data/ext/libgraphqlparser/CONTRIBUTING.md +0 -23
- data/ext/libgraphqlparser/GraphQLParser.cpp +0 -76
- data/ext/libgraphqlparser/GraphQLParser.h +0 -55
- data/ext/libgraphqlparser/JsonVisitor.cpp +0 -161
- data/ext/libgraphqlparser/JsonVisitor.h +0 -121
- data/ext/libgraphqlparser/LICENSE +0 -22
- data/ext/libgraphqlparser/README.clang-tidy +0 -7
- data/ext/libgraphqlparser/README.md +0 -84
- data/ext/libgraphqlparser/ast/ast.ast +0 -203
- data/ext/libgraphqlparser/ast/ast.py +0 -61
- data/ext/libgraphqlparser/ast/c.py +0 -100
- data/ext/libgraphqlparser/ast/c.pyc +0 -0
- data/ext/libgraphqlparser/ast/c_impl.py +0 -61
- data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/c_visitor_impl.py +0 -39
- data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/casing.py +0 -26
- data/ext/libgraphqlparser/ast/casing.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx.py +0 -197
- data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_impl.py +0 -61
- data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +0 -42
- data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +0 -80
- data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_visitor.py +0 -64
- data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
- data/ext/libgraphqlparser/ast/js.py +0 -65
- data/ext/libgraphqlparser/ast/license.py +0 -10
- data/ext/libgraphqlparser/ast/license.pyc +0 -0
- data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +0 -25
- data/ext/libgraphqlparser/c/GraphQLAstNode.h +0 -33
- data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +0 -21
- data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +0 -24
- data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +0 -55
- data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +0 -53
- data/ext/libgraphqlparser/c/GraphQLParser.cpp +0 -35
- data/ext/libgraphqlparser/c/GraphQLParser.h +0 -54
- data/ext/libgraphqlparser/clang-tidy-all.sh +0 -3
- data/ext/libgraphqlparser/cmake/version.cmake +0 -16
- data/ext/libgraphqlparser/dump_json_ast.cpp +0 -48
- data/ext/libgraphqlparser/go/README.md +0 -20
- data/ext/libgraphqlparser/go/callbacks.go +0 -18
- data/ext/libgraphqlparser/go/gotest.go +0 -64
- data/ext/libgraphqlparser/lexer.lpp +0 -324
- data/ext/libgraphqlparser/libgraphqlparser.pc.in +0 -11
- data/ext/libgraphqlparser/parser.ypp +0 -693
- data/ext/libgraphqlparser/parsergen/lexer.cpp +0 -2633
- data/ext/libgraphqlparser/parsergen/lexer.h +0 -528
- data/ext/libgraphqlparser/parsergen/location.hh +0 -189
- data/ext/libgraphqlparser/parsergen/parser.tab.cpp +0 -3300
- data/ext/libgraphqlparser/parsergen/parser.tab.hpp +0 -646
- data/ext/libgraphqlparser/parsergen/position.hh +0 -179
- data/ext/libgraphqlparser/parsergen/stack.hh +0 -156
- data/ext/libgraphqlparser/python/CMakeLists.txt +0 -14
- data/ext/libgraphqlparser/python/README.md +0 -5
- data/ext/libgraphqlparser/python/example.py +0 -31
- data/ext/libgraphqlparser/syntaxdefs.h +0 -19
- data/ext/libgraphqlparser/test/BuildCAPI.c +0 -5
- data/ext/libgraphqlparser/test/CMakeLists.txt +0 -25
- data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +0 -28
- data/ext/libgraphqlparser/test/ParserTests.cpp +0 -352
- data/ext/libgraphqlparser/test/kitchen-sink.graphql +0 -59
- data/ext/libgraphqlparser/test/kitchen-sink.json +0 -1
- data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +0 -78
- data/ext/libgraphqlparser/test/schema-kitchen-sink.json +0 -1
- data/ext/libgraphqlparser/test/valgrind.supp +0 -33
- data/ext/version.cpp +0 -21
- data/lib/graphqlparser.so +0 -0
- data/lib/rails/graphql/native/functions.rb +0 -38
- data/lib/rails/graphql/native/location.rb +0 -41
- data/lib/rails/graphql/native/pointers.rb +0 -23
- data/lib/rails/graphql/native/visitor.rb +0 -349
- data/lib/rails/graphql/native.rb +0 -56
- data/test/integration/schemas/authorization.rb +0 -12
data/ext/shared.c
ADDED
@@ -0,0 +1,477 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "shared.h"
|
3
|
+
|
4
|
+
const char *GQL_VALUE_KEYWORDS[] = {
|
5
|
+
"true",
|
6
|
+
"false",
|
7
|
+
"null"
|
8
|
+
};
|
9
|
+
|
10
|
+
const char *GQL_EXECUTION_KEYWORDS[] = {
|
11
|
+
"query",
|
12
|
+
"mutation",
|
13
|
+
"subscription",
|
14
|
+
"fragment",
|
15
|
+
"on"
|
16
|
+
};
|
17
|
+
|
18
|
+
const char *GQL_DEFINITION_KEYWORDS[] = {
|
19
|
+
"schema",
|
20
|
+
"directive",
|
21
|
+
"enum",
|
22
|
+
"input",
|
23
|
+
"interface",
|
24
|
+
"scalar",
|
25
|
+
"type",
|
26
|
+
"union",
|
27
|
+
"extend",
|
28
|
+
"implements",
|
29
|
+
"repeatable"
|
30
|
+
};
|
31
|
+
|
32
|
+
/* INTERNAL HELPERS */
|
33
|
+
// Just a helper to print things on the console while testing/debugging
|
34
|
+
void gql_debug_print(const char *message)
|
35
|
+
{
|
36
|
+
rb_funcall(rb_mKernel, rb_intern("puts"), 1, rb_str_new2(message));
|
37
|
+
}
|
38
|
+
|
39
|
+
// Initialize a new scanner
|
40
|
+
struct gql_scanner gql_new_scanner(VALUE source)
|
41
|
+
{
|
42
|
+
char *doc = RSTRING_PTR(source);
|
43
|
+
struct gql_scanner scanner = {
|
44
|
+
.start_pos = 1, // Set to 1 just to begin different from the current position
|
45
|
+
.current_pos = 0,
|
46
|
+
.current_line = 1,
|
47
|
+
.last_ln_at = 0,
|
48
|
+
.current = doc[0],
|
49
|
+
.doc = doc};
|
50
|
+
|
51
|
+
return scanner;
|
52
|
+
}
|
53
|
+
|
54
|
+
// Returns the base index of the lexeme from where the upgrade should move from
|
55
|
+
enum gql_lexeme gql_upgrade_basis(const char *upgrade_from[])
|
56
|
+
{
|
57
|
+
if (*upgrade_from == *GQL_VALUE_KEYWORDS)
|
58
|
+
return gql_iv_true;
|
59
|
+
else if (*upgrade_from == *GQL_EXECUTION_KEYWORDS)
|
60
|
+
return gql_ie_query;
|
61
|
+
else if (*upgrade_from == *GQL_DEFINITION_KEYWORDS)
|
62
|
+
return gql_id_schema;
|
63
|
+
else
|
64
|
+
return gql_i_unknown;
|
65
|
+
}
|
66
|
+
|
67
|
+
// This checks if the identifier in the scanner should be upgraded to a keyword
|
68
|
+
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *upgrade_from[])
|
69
|
+
{
|
70
|
+
unsigned long pos, len = GQL_SCAN_SIZE(scanner);
|
71
|
+
unsigned int valid = 0, i = 0;
|
72
|
+
const char *keyword;
|
73
|
+
|
74
|
+
// Check until it finds the end of the array
|
75
|
+
while ((keyword = upgrade_from[i]) != 0)
|
76
|
+
{
|
77
|
+
// Move ot the next item and check the current for different size
|
78
|
+
if(strlen(keyword) == len)
|
79
|
+
{
|
80
|
+
// We cannot use the normal strcomp because we are comparing a mid part of the string
|
81
|
+
for (pos = 0, valid = 1; valid == 1 && pos < len; pos++)
|
82
|
+
{
|
83
|
+
if (keyword[pos] != scanner->doc[scanner->start_pos + pos])
|
84
|
+
valid = 0;
|
85
|
+
}
|
86
|
+
|
87
|
+
// Only return if valid was kept as true
|
88
|
+
if (valid == 1) return gql_upgrade_basis(upgrade_from) + i;
|
89
|
+
}
|
90
|
+
|
91
|
+
// Move to the next index
|
92
|
+
i++;
|
93
|
+
}
|
94
|
+
|
95
|
+
// Return name if was not able to upgrade to a keyword
|
96
|
+
return gql_i_name;
|
97
|
+
}
|
98
|
+
|
99
|
+
/* SCANNER HELPERS */
|
100
|
+
enum gql_lexeme gql_read_name(struct gql_scanner *scanner)
|
101
|
+
{
|
102
|
+
// Read all the chars and digits
|
103
|
+
GQL_SCAN_WHILE(scanner, GQL_S_CHARACTER(scanner->current) || GQL_S_DIGIT(scanner->current));
|
104
|
+
return gql_i_name;
|
105
|
+
}
|
106
|
+
|
107
|
+
enum gql_lexeme gql_read_comment(struct gql_scanner *scanner)
|
108
|
+
{
|
109
|
+
// Move forward until it finds a new line, change the line indicator and return
|
110
|
+
GQL_SCAN_WHILE(scanner, scanner->current != '\n');
|
111
|
+
GQL_SCAN_NEW_LINE(scanner);
|
112
|
+
return gql_i_comment;
|
113
|
+
}
|
114
|
+
|
115
|
+
enum gql_lexeme gql_read_hash(struct gql_scanner *scanner)
|
116
|
+
{
|
117
|
+
// Start with 1 curly open and get the next
|
118
|
+
int curly_opens = 1;
|
119
|
+
GQL_SCAN_NEXT(scanner);
|
120
|
+
|
121
|
+
while (curly_opens > 0)
|
122
|
+
{
|
123
|
+
// EOF returns unknown, { adds to the open, } removes from the open, " reads as string
|
124
|
+
if (scanner->current == '\0')
|
125
|
+
return gql_i_unknown;
|
126
|
+
else if (scanner->current == '"' && gql_read_string(scanner, 0) != gql_iv_string)
|
127
|
+
return gql_i_unknown;
|
128
|
+
else if (scanner->current == '{')
|
129
|
+
curly_opens++;
|
130
|
+
else if (scanner->current == '}')
|
131
|
+
curly_opens--;
|
132
|
+
else if (scanner->current == '\n')
|
133
|
+
GQL_SCAN_NEW_LINE(scanner);
|
134
|
+
|
135
|
+
// Just move to the next char
|
136
|
+
GQL_SCAN_NEXT(scanner);
|
137
|
+
}
|
138
|
+
|
139
|
+
// Save the last position, move to the next and return as hash
|
140
|
+
return gql_iv_hash;
|
141
|
+
}
|
142
|
+
|
143
|
+
enum gql_lexeme gql_read_float(struct gql_scanner *scanner)
|
144
|
+
{
|
145
|
+
// If what made it get in here was an '.', then it can recurse to the exponent of a fraction
|
146
|
+
int at_fraction = scanner->current == '.';
|
147
|
+
|
148
|
+
// Skip the float mark and maybe
|
149
|
+
GQL_SCAN_NEXT(scanner);
|
150
|
+
|
151
|
+
// Skip the exponent sign if possible
|
152
|
+
if (!at_fraction && (scanner->current == '+' || scanner->current == '-'))
|
153
|
+
GQL_SCAN_NEXT(scanner);
|
154
|
+
|
155
|
+
// If the current char is not a digit, we have an unknown
|
156
|
+
if (!GQL_S_DIGIT(scanner->current)) return gql_i_unknown;
|
157
|
+
GQL_SCAN_NEXT(scanner);
|
158
|
+
|
159
|
+
// Read all the numbers
|
160
|
+
GQL_SCAN_WHILE(scanner, GQL_S_DIGIT(scanner->current));
|
161
|
+
|
162
|
+
// If it is at fraction and the next is an exponent marker, then recurse
|
163
|
+
if (at_fraction && (scanner->current == 'e' || scanner->current == 'E'))
|
164
|
+
return gql_read_float(scanner);
|
165
|
+
|
166
|
+
// Otherwise save the last position and just finish the float
|
167
|
+
return gql_iv_float;
|
168
|
+
}
|
169
|
+
|
170
|
+
enum gql_lexeme gql_read_number(struct gql_scanner *scanner)
|
171
|
+
{
|
172
|
+
// Pass over the negative sign
|
173
|
+
if (scanner->current == '-') GQL_SCAN_NEXT(scanner);
|
174
|
+
|
175
|
+
// If begins with zero, it can only be 0 or error
|
176
|
+
if (scanner->current == '0')
|
177
|
+
return (GQL_S_DIGIT(GQL_SCAN_LOOK(scanner, 1))) ? gql_i_unknown : gql_iv_integer;
|
178
|
+
|
179
|
+
// Read all the numbers
|
180
|
+
GQL_SCAN_WHILE(scanner, GQL_S_DIGIT(scanner->current));
|
181
|
+
|
182
|
+
// Save the last position and halt the process if it's not a float marker
|
183
|
+
return (GQL_S_FLOAT_MARK(scanner->current)) ? gql_read_float(scanner) : gql_iv_integer;
|
184
|
+
}
|
185
|
+
|
186
|
+
enum gql_lexeme gql_read_string(struct gql_scanner *scanner, int allow_heredoc)
|
187
|
+
{
|
188
|
+
int start_size, end_size = 0;
|
189
|
+
unsigned long start = scanner->current_pos;
|
190
|
+
|
191
|
+
// Read all the initial quotes and save the size
|
192
|
+
GQL_SCAN_WHILE(scanner, scanner->current == '"');
|
193
|
+
start_size = (int)(scanner->current_pos - start);
|
194
|
+
|
195
|
+
// 4, 5, or more than 6 means an invalid triple-quotes block
|
196
|
+
if (start_size == 4 || start_size == 5 || start_size > 6)
|
197
|
+
return gql_i_unknown;
|
198
|
+
|
199
|
+
// 3 but not accepting heredoc returns an unknown
|
200
|
+
if (allow_heredoc == 0 && start_size == 3)
|
201
|
+
return gql_i_unknown;
|
202
|
+
|
203
|
+
// 2 or 6 means empty string
|
204
|
+
if (start_size == 2 || start_size == 6)
|
205
|
+
return gql_iv_string;
|
206
|
+
|
207
|
+
// Read until the start and end number of quotes matches
|
208
|
+
while (start_size != end_size)
|
209
|
+
{
|
210
|
+
// If it is a quote, add to end and move ot the next
|
211
|
+
if (scanner->current == '"')
|
212
|
+
{
|
213
|
+
end_size++;
|
214
|
+
}
|
215
|
+
else
|
216
|
+
{
|
217
|
+
// Anything that is not a quote reset the end size
|
218
|
+
end_size = 0;
|
219
|
+
|
220
|
+
// If we get to the end of the file, return an unknown
|
221
|
+
if (scanner->current == '\0')
|
222
|
+
return gql_i_unknown;
|
223
|
+
|
224
|
+
// Make sure to mark any new lines
|
225
|
+
if (scanner->current == '\n')
|
226
|
+
GQL_SCAN_NEW_LINE(scanner);
|
227
|
+
|
228
|
+
// Skip one extra character, which means it is skipping the escaped char
|
229
|
+
if (scanner->current == '\\')
|
230
|
+
GQL_SCAN_NEXT(scanner);
|
231
|
+
}
|
232
|
+
|
233
|
+
// Move the cursor
|
234
|
+
GQL_SCAN_NEXT(scanner);
|
235
|
+
}
|
236
|
+
|
237
|
+
// Regardless if a quote comes next, this is now a valid string
|
238
|
+
return (start_size == 3) ? gql_iv_heredoc : gql_iv_string;
|
239
|
+
}
|
240
|
+
|
241
|
+
/* MOST IMPORTANT TOKEN READ FUNCTION */
|
242
|
+
void gql_next_lexeme(struct gql_scanner *scanner)
|
243
|
+
{
|
244
|
+
// Do not move forward if it is unknown
|
245
|
+
if (scanner->lexeme == gql_i_unknown)
|
246
|
+
return;
|
247
|
+
|
248
|
+
// Temporary save the end line and end column
|
249
|
+
GQL_SCAN_SET_END(scanner, 0);
|
250
|
+
|
251
|
+
// Skip everything that can be ignored
|
252
|
+
GQL_SCAN_WHILE(scanner, GQL_S_IGNORE(scanner->current));
|
253
|
+
|
254
|
+
// Mark where the new interesting thing has started
|
255
|
+
scanner->start_pos = scanner->current_pos;
|
256
|
+
scanner->begin_line = scanner->current_line;
|
257
|
+
scanner->begin_column = scanner->current_pos - scanner->last_ln_at;
|
258
|
+
|
259
|
+
// Find what might be the next interesting thing
|
260
|
+
if (scanner->current == '\0')
|
261
|
+
scanner->lexeme = gql_i_eof;
|
262
|
+
else if (GQL_S_CHARACTER(scanner->current))
|
263
|
+
scanner->lexeme = gql_read_name(scanner);
|
264
|
+
else if (scanner->current == '#')
|
265
|
+
scanner->lexeme = gql_read_comment(scanner);
|
266
|
+
else if (GQL_S_DIGIT(scanner->current) || scanner->current == '-')
|
267
|
+
scanner->lexeme = gql_read_number(scanner);
|
268
|
+
else if (scanner->current == '"')
|
269
|
+
scanner->lexeme = gql_read_string(scanner, 1);
|
270
|
+
else if (scanner->current == '[')
|
271
|
+
scanner->lexeme = gql_is_op_brack;
|
272
|
+
else if (scanner->current == '{')
|
273
|
+
scanner->lexeme = gql_is_op_curly;
|
274
|
+
else if (scanner->current == '}')
|
275
|
+
scanner->lexeme = gql_is_cl_curly;
|
276
|
+
else if (scanner->current == '(')
|
277
|
+
scanner->lexeme = gql_is_op_paren;
|
278
|
+
else if (scanner->current == ')')
|
279
|
+
scanner->lexeme = gql_is_cl_paren;
|
280
|
+
else if (scanner->current == ':')
|
281
|
+
scanner->lexeme = gql_is_colon;
|
282
|
+
else if (scanner->current == '=')
|
283
|
+
scanner->lexeme = gql_is_equal;
|
284
|
+
else if (scanner->current == '.')
|
285
|
+
scanner->lexeme = gql_is_period;
|
286
|
+
else if (scanner->current == '@')
|
287
|
+
scanner->lexeme = gql_i_directive;
|
288
|
+
else if (scanner->current == '$')
|
289
|
+
scanner->lexeme = gql_i_variable;
|
290
|
+
else
|
291
|
+
scanner->lexeme = gql_i_unknown;
|
292
|
+
}
|
293
|
+
|
294
|
+
// Skip all comment lexemes
|
295
|
+
void gql_next_lexeme_no_comments(struct gql_scanner *scanner)
|
296
|
+
{
|
297
|
+
do
|
298
|
+
{
|
299
|
+
gql_next_lexeme(scanner);
|
300
|
+
} while (scanner->lexeme == gql_i_comment);
|
301
|
+
}
|
302
|
+
|
303
|
+
/* TOKEN CLASS HELPERS AND METHODS */
|
304
|
+
// Simply add the type of the token and return self for simplicity
|
305
|
+
VALUE gql_set_token_type(VALUE self, const char *type)
|
306
|
+
{
|
307
|
+
rb_iv_set(self, "@type", ID2SYM(rb_intern(type)));
|
308
|
+
return self;
|
309
|
+
}
|
310
|
+
|
311
|
+
// Just simply format the string with the token prefix
|
312
|
+
VALUE gql_inspect_token(VALUE self)
|
313
|
+
{
|
314
|
+
VALUE text = rb_call_super(0, 0);
|
315
|
+
|
316
|
+
if (rb_ivar_defined(self, rb_intern("@type")) == Qfalse)
|
317
|
+
return rb_sprintf("<GQLParser::Token %" PRIsVALUE ">", text);
|
318
|
+
|
319
|
+
VALUE type = rb_iv_get(self, "@type");
|
320
|
+
return rb_sprintf("<GQLParser::Token [%" PRIsVALUE "] %" PRIsVALUE ">", type, text);
|
321
|
+
}
|
322
|
+
|
323
|
+
// Check if the token is of the given type
|
324
|
+
VALUE gql_token_of_type_check(VALUE self, VALUE other)
|
325
|
+
{
|
326
|
+
VALUE type = rb_iv_get(self, "@type");
|
327
|
+
return rb_equal(type, other);
|
328
|
+
}
|
329
|
+
|
330
|
+
// Add the token module to the object and assign its location information
|
331
|
+
VALUE gql_as_token(VALUE self, struct gql_scanner *scanner, int save_type)
|
332
|
+
{
|
333
|
+
// Initialize the instance
|
334
|
+
VALUE instance = rb_class_new_instance(1, &self, QLGParserToken);
|
335
|
+
|
336
|
+
// Add the location instance variables
|
337
|
+
int offset = scanner->begin_line == 1 ? 1 : 0;
|
338
|
+
rb_iv_set(instance, "@begin_line", ULONG2NUM(scanner->begin_line));
|
339
|
+
rb_iv_set(instance, "@begin_column", ULONG2NUM(scanner->begin_column + offset));
|
340
|
+
|
341
|
+
offset = scanner->end_line == 1 ? 1 : 0;
|
342
|
+
rb_iv_set(instance, "@end_line", ULONG2NUM(scanner->end_line));
|
343
|
+
rb_iv_set(instance, "@end_column", ULONG2NUM(scanner->end_column + offset));
|
344
|
+
|
345
|
+
// Check if it has to save the type
|
346
|
+
if (save_type == 1)
|
347
|
+
{
|
348
|
+
// This only covers value types
|
349
|
+
if (scanner->lexeme == gql_iv_integer)
|
350
|
+
gql_set_token_type(instance, "int");
|
351
|
+
else if (scanner->lexeme == gql_iv_float)
|
352
|
+
gql_set_token_type(instance, "float");
|
353
|
+
else if (scanner->lexeme == gql_iv_string)
|
354
|
+
gql_set_token_type(instance, "string");
|
355
|
+
else if (scanner->lexeme == gql_iv_true)
|
356
|
+
gql_set_token_type(instance, "boolean");
|
357
|
+
else if (scanner->lexeme == gql_iv_false)
|
358
|
+
gql_set_token_type(instance, "boolean");
|
359
|
+
else if (scanner->lexeme == gql_iv_enum)
|
360
|
+
gql_set_token_type(instance, "enum");
|
361
|
+
else if (scanner->lexeme == gql_iv_array)
|
362
|
+
gql_set_token_type(instance, "array");
|
363
|
+
else if (scanner->lexeme == gql_iv_hash)
|
364
|
+
gql_set_token_type(instance, "hash");
|
365
|
+
else if (scanner->lexeme == gql_iv_heredoc)
|
366
|
+
gql_set_token_type(instance, "heredoc");
|
367
|
+
}
|
368
|
+
|
369
|
+
// Return the token instance
|
370
|
+
return instance;
|
371
|
+
}
|
372
|
+
|
373
|
+
/* RUBY-BASED HELPERS */
|
374
|
+
// Creates a Ruby String from the scanner
|
375
|
+
VALUE gql_scanner_to_s(struct gql_scanner *scanner)
|
376
|
+
{
|
377
|
+
return rb_str_new(scanner->doc + scanner->start_pos, GQL_SCAN_SIZE(scanner));
|
378
|
+
}
|
379
|
+
|
380
|
+
// Same as the above, but already extend it to a parser token
|
381
|
+
VALUE gql_scanner_to_token(struct gql_scanner *scanner)
|
382
|
+
{
|
383
|
+
return gql_as_token(gql_scanner_to_s(scanner), scanner, 0);
|
384
|
+
}
|
385
|
+
|
386
|
+
// Goes over an array and grab all the elements
|
387
|
+
VALUE gql_array_to_rb(struct gql_scanner *scanner)
|
388
|
+
{
|
389
|
+
// Start the array and the temporary element
|
390
|
+
VALUE result = rb_ary_new();
|
391
|
+
VALUE element;
|
392
|
+
|
393
|
+
// Save the scan and grab the next char
|
394
|
+
GQL_SCAN_NEXT(scanner);
|
395
|
+
|
396
|
+
// Iterate until it finds the end of the array
|
397
|
+
while (scanner->current != ']')
|
398
|
+
{
|
399
|
+
// If we got to the end of the file and the array was not closed, then we have something wrong
|
400
|
+
if (scanner->current == '\0')
|
401
|
+
{
|
402
|
+
scanner->lexeme = gql_i_unknown;
|
403
|
+
return Qnil;
|
404
|
+
}
|
405
|
+
|
406
|
+
// Save the element as an rb token, because we may need the type of each element afterwards
|
407
|
+
element = gql_value_to_token(scanner, 0);
|
408
|
+
|
409
|
+
// If it found an unknown, then we bubble the problem up
|
410
|
+
if (scanner->lexeme == gql_i_unknown)
|
411
|
+
return Qnil;
|
412
|
+
|
413
|
+
// Add the value to the array and scan through everything ignorable
|
414
|
+
rb_ary_push(result, element);
|
415
|
+
GQL_SCAN_WHILE(scanner, GQL_S_IGNORE(scanner->current));
|
416
|
+
}
|
417
|
+
|
418
|
+
// Save where the array has actually ended, change the lexeme and return
|
419
|
+
GQL_SCAN_SET_END(scanner, 0);
|
420
|
+
scanner->lexeme = gql_iv_array;
|
421
|
+
return result;
|
422
|
+
}
|
423
|
+
|
424
|
+
// Turn the current lexeme into its proper ruby object
|
425
|
+
VALUE gql_value_to_rb(struct gql_scanner *scanner, int accept_var)
|
426
|
+
{
|
427
|
+
// EXPERIMENTAL! Skip all the comments
|
428
|
+
gql_next_lexeme_no_comments(scanner);
|
429
|
+
|
430
|
+
// If got a variable and accepts variables,
|
431
|
+
// then it's fine and it won't be resolved in here
|
432
|
+
if (accept_var == 1 && scanner->lexeme == gql_i_variable)
|
433
|
+
return Qnil;
|
434
|
+
|
435
|
+
// Make sure to save the end position of the value
|
436
|
+
GQL_SCAN_SET_END(scanner, 0);
|
437
|
+
|
438
|
+
// If it's a name, then it can be a keyword or a enum value
|
439
|
+
if (scanner->lexeme == gql_i_name)
|
440
|
+
{
|
441
|
+
scanner->lexeme = gql_name_to_keyword(scanner, GQL_VALUE_KEYWORDS);
|
442
|
+
if (scanner->lexeme == gql_iv_true)
|
443
|
+
return Qtrue;
|
444
|
+
else if (scanner->lexeme == gql_iv_false)
|
445
|
+
return Qfalse;
|
446
|
+
else if (scanner->lexeme == gql_iv_null)
|
447
|
+
return Qnil;
|
448
|
+
else
|
449
|
+
scanner->lexeme = gql_iv_enum;
|
450
|
+
}
|
451
|
+
|
452
|
+
// Dealing with an array is way more complex, because you have to turn each
|
453
|
+
// individual value as an rb value
|
454
|
+
if (scanner->lexeme == gql_is_op_brack)
|
455
|
+
return gql_array_to_rb(scanner);
|
456
|
+
|
457
|
+
// If it is a hash, then we can just read through it and later get as a string
|
458
|
+
if (scanner->lexeme == gql_is_op_curly)
|
459
|
+
scanner->lexeme = gql_read_hash(scanner);
|
460
|
+
|
461
|
+
// By getting here with a proper value, just return the string of it, which
|
462
|
+
// will be dealt in the request
|
463
|
+
if (GQL_I_VALUE(scanner->lexeme))
|
464
|
+
return gql_scanner_to_s(scanner);
|
465
|
+
|
466
|
+
// If it got to this point, then it's an unknown
|
467
|
+
scanner->lexeme = gql_i_unknown;
|
468
|
+
return Qnil;
|
469
|
+
}
|
470
|
+
|
471
|
+
// Same as the above, but already extend it to a parser token
|
472
|
+
// IMPORTANT! This might generate a problem because nil, true, and false won't
|
473
|
+
// become parser tokens
|
474
|
+
VALUE gql_value_to_token(struct gql_scanner *scanner, int accept_var)
|
475
|
+
{
|
476
|
+
return gql_as_token(gql_value_to_rb(scanner, accept_var), scanner, 1);
|
477
|
+
}
|
data/ext/shared.h
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
#if !defined RB_INT_PARSE_DEFAULT
|
4
|
+
#define RB_INT_PARSE_DEFAULT 0x07
|
5
|
+
#endif
|
6
|
+
|
7
|
+
#define GQL_PUTS(...) gql_debug_print(RSTRING_PTR(rb_sprintf(__VA_ARGS__)))
|
8
|
+
|
9
|
+
#define GQL_I_STRUCTURE_FST 0x10
|
10
|
+
#define GQL_I_STRUCTURE_LST 0x1f
|
11
|
+
|
12
|
+
#define GQL_I_VALUE_FST 0x20
|
13
|
+
#define GQL_I_VALUE_LST 0x2f
|
14
|
+
|
15
|
+
#define GQL_I_EXECUTION_FST 0x30
|
16
|
+
#define GQL_I_EXECUTION_LST 0x3f
|
17
|
+
|
18
|
+
#define GQL_I_OPERATIONS_FST 0x30
|
19
|
+
#define GQL_I_OPERATIONS_LST 0x32
|
20
|
+
|
21
|
+
#define GQL_I_DEFINITION_FST 0x40
|
22
|
+
#define GQL_I_DEFINITION_LST 0x4f
|
23
|
+
|
24
|
+
#define GQL_I_STRUCTURE(x) (x >= GQL_I_STRUCTURE_FST && x <= GQL_I_STRUCTURE_LST)
|
25
|
+
#define GQL_I_VALUE(x) (x >= GQL_I_VALUE_FST && x <= GQL_I_VALUE_LST)
|
26
|
+
#define GQL_I_EXECUTION(x) (x >= GQL_I_EXECUTION_FST && x <= GQL_I_EXECUTION_LST)
|
27
|
+
#define QGL_I_OPERATION(x) (x >= GQL_I_OPERATIONS_FST && x <= GQL_I_OPERATIONS_LST)
|
28
|
+
#define GQL_I_DEFINITION(x) (x >= GQL_I_DEFINITION_FST && x <= GQL_I_DEFINITION_LST)
|
29
|
+
|
30
|
+
// https://www.asciitable.com/
|
31
|
+
#define GQL_S_IGNORE(x) (x == ' ' || x == ',' || x == '\n' || x == '\r' || x == '\t' || x == '\f' || x == '\b')
|
32
|
+
#define GQL_S_CHARACTER(x) ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || x == '_')
|
33
|
+
#define GQL_S_DIGIT(x) (x >= '0' && x <= '9')
|
34
|
+
#define GQL_S_FLOAT_MARK(x) (x == '.' || x == 'e' || x == 'E')
|
35
|
+
|
36
|
+
#define GQL_SCAN_ERROR(scanner) (scanner->lexeme == gql_i_eof || scanner->lexeme == gql_i_unknown)
|
37
|
+
#define GQL_SCAN_SIZE(scanner) (scanner->current_pos - scanner->start_pos)
|
38
|
+
#define GQL_SCAN_CHAR(scanner) (scanner->doc[scanner->current_pos])
|
39
|
+
#define GQL_SCAN_LOOK(scanner, bytes) (scanner->doc[scanner->current_pos + bytes])
|
40
|
+
#define GQL_SCAN_NEXT(scanner) ({ \
|
41
|
+
scanner->current_pos++; \
|
42
|
+
scanner->current = GQL_SCAN_CHAR(scanner); \
|
43
|
+
})
|
44
|
+
#define GQL_SCAN_NEW_LINE(scanner) ({ \
|
45
|
+
scanner->last_ln_at = scanner->current_pos; \
|
46
|
+
scanner->current_line++; \
|
47
|
+
})
|
48
|
+
#define GQL_SCAN_WHILE(scanner, check) ({ \
|
49
|
+
while (check) \
|
50
|
+
{ \
|
51
|
+
if (GQL_SCAN_CHAR(scanner) == '\n') \
|
52
|
+
{ \
|
53
|
+
GQL_SCAN_NEW_LINE(scanner); \
|
54
|
+
} \
|
55
|
+
GQL_SCAN_NEXT(scanner); \
|
56
|
+
} \
|
57
|
+
})
|
58
|
+
#define GQL_SCAN_SET_END(scanner, offset) ({ \
|
59
|
+
scanner->end_line = scanner->begin_line; \
|
60
|
+
scanner->end_column = scanner->current_pos - offset - scanner->last_ln_at; \
|
61
|
+
})
|
62
|
+
#define GQL_SCAN_SAVE(scanner, memory) ({ \
|
63
|
+
memory[0] = scanner->begin_line; \
|
64
|
+
memory[1] = scanner->begin_column; \
|
65
|
+
})
|
66
|
+
|
67
|
+
#define GQL_SAFE_PUSH(source, value) ({ \
|
68
|
+
if (NIL_P(source)) \
|
69
|
+
source = rb_ary_new(); \
|
70
|
+
rb_ary_push(source, value); \
|
71
|
+
})
|
72
|
+
|
73
|
+
enum gql_lexeme
|
74
|
+
{
|
75
|
+
// Basic identifiers
|
76
|
+
gql_i_eof = 0x00,
|
77
|
+
gql_i_name = 0x01,
|
78
|
+
gql_i_comment = 0x02,
|
79
|
+
gql_i_variable = 0x03,
|
80
|
+
gql_i_directive = 0x04,
|
81
|
+
|
82
|
+
// Structure identifiers
|
83
|
+
gql_is_op_curly = 0x10,
|
84
|
+
gql_is_cl_curly = 0x11,
|
85
|
+
gql_is_op_paren = 0x12,
|
86
|
+
gql_is_cl_paren = 0x13,
|
87
|
+
gql_is_op_brack = 0x14,
|
88
|
+
gql_is_cl_brack = 0x15,
|
89
|
+
gql_is_colon = 0x16,
|
90
|
+
gql_is_equal = 0x17,
|
91
|
+
gql_is_period = 0x18,
|
92
|
+
|
93
|
+
// Value based types
|
94
|
+
gql_iv_integer = 0x20,
|
95
|
+
gql_iv_float = 0x21,
|
96
|
+
gql_iv_string = 0x22,
|
97
|
+
gql_iv_true = 0x23,
|
98
|
+
gql_iv_false = 0x24,
|
99
|
+
gql_iv_null = 0x25,
|
100
|
+
gql_iv_enum = 0x26,
|
101
|
+
gql_iv_array = 0x27,
|
102
|
+
gql_iv_hash = 0x28,
|
103
|
+
gql_iv_heredoc = 0x2f,
|
104
|
+
|
105
|
+
// Execution keywords
|
106
|
+
gql_ie_query = 0x30,
|
107
|
+
gql_ie_mutation = 0x31,
|
108
|
+
gql_ie_subscription = 0x32,
|
109
|
+
gql_ie_fragment = 0x33,
|
110
|
+
gql_ie_on = 0x34,
|
111
|
+
|
112
|
+
// Definition keywords
|
113
|
+
gql_id_schema = 0x40,
|
114
|
+
gql_id_directive = 0x41,
|
115
|
+
gql_id_enum = 0x42,
|
116
|
+
gql_id_input = 0x43,
|
117
|
+
gql_id_interface = 0x44,
|
118
|
+
gql_id_scalar = 0x45,
|
119
|
+
gql_id_type = 0x46,
|
120
|
+
gql_id_union = 0x47,
|
121
|
+
gql_id_extend = 0x48,
|
122
|
+
gql_id_implements = 0x49,
|
123
|
+
gql_id_repeatable = 0x4a,
|
124
|
+
|
125
|
+
// Something went wrong
|
126
|
+
gql_i_unknown = 0xff
|
127
|
+
};
|
128
|
+
|
129
|
+
struct gql_scanner
|
130
|
+
{
|
131
|
+
unsigned long start_pos;
|
132
|
+
unsigned long current_pos;
|
133
|
+
unsigned long current_line;
|
134
|
+
unsigned long last_ln_at;
|
135
|
+
unsigned long begin_line;
|
136
|
+
unsigned long begin_column;
|
137
|
+
unsigned long end_line;
|
138
|
+
unsigned long end_column;
|
139
|
+
char *doc;
|
140
|
+
char current;
|
141
|
+
enum gql_lexeme lexeme;
|
142
|
+
};
|
143
|
+
|
144
|
+
extern VALUE GQLParser;
|
145
|
+
extern VALUE QLGParserToken;
|
146
|
+
extern VALUE gql_eParserError;
|
147
|
+
|
148
|
+
extern const char *GQL_VALUE_KEYWORDS[3];
|
149
|
+
extern const char *GQL_EXECUTION_KEYWORDS[5];
|
150
|
+
extern const char *GQL_DEFINITION_KEYWORDS[12];
|
151
|
+
|
152
|
+
void gql_debug_print(const char *message);
|
153
|
+
struct gql_scanner gql_new_scanner(VALUE source);
|
154
|
+
|
155
|
+
enum gql_lexeme gql_upgrade_basis(const char *upgrade_from[]);
|
156
|
+
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *upgrade_from[]);
|
157
|
+
|
158
|
+
enum gql_lexeme gql_read_name(struct gql_scanner *scanner);
|
159
|
+
enum gql_lexeme gql_read_comment(struct gql_scanner *scanner);
|
160
|
+
enum gql_lexeme gql_read_hash(struct gql_scanner *scanner);
|
161
|
+
enum gql_lexeme gql_read_float(struct gql_scanner *scanner);
|
162
|
+
enum gql_lexeme gql_read_number(struct gql_scanner *scanner);
|
163
|
+
enum gql_lexeme gql_read_string(struct gql_scanner *scanner, int allow_heredoc);
|
164
|
+
|
165
|
+
void gql_next_lexeme(struct gql_scanner *scanner);
|
166
|
+
void gql_next_lexeme_no_comments(struct gql_scanner *scanner);
|
167
|
+
|
168
|
+
VALUE gql_set_token_type(VALUE self, const char *type);
|
169
|
+
VALUE gql_inspect_token(VALUE self);
|
170
|
+
VALUE gql_token_of_type_check(VALUE self, VALUE other);
|
171
|
+
VALUE gql_as_token(VALUE self, struct gql_scanner *scanner, int save_type);
|
172
|
+
|
173
|
+
VALUE gql_scanner_to_s(struct gql_scanner *scanner);
|
174
|
+
VALUE gql_scanner_to_token(struct gql_scanner *scanner);
|
175
|
+
VALUE gql_array_to_rb(struct gql_scanner *scanner);
|
176
|
+
VALUE gql_value_to_rb(struct gql_scanner *scanner, int accept_var);
|
177
|
+
VALUE gql_value_to_token(struct gql_scanner *scanner, int accept_var);
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/base'
|
4
|
+
|
5
|
+
module GraphQL
|
6
|
+
module Generators
|
7
|
+
class ChannelGenerator < Rails::Generators::Base # :nodoc:
|
8
|
+
include Rails::GraphQL::BaseGenerator
|
9
|
+
|
10
|
+
desc 'Add a new action cable channel that operates with GraphQL'
|
11
|
+
|
12
|
+
argument :name, type: :string, optional: true,
|
13
|
+
default: "GraphQLChannel",
|
14
|
+
desc: 'The name for the channel'
|
15
|
+
|
16
|
+
def create_channel_file
|
17
|
+
template 'channel.erb', "app/channels/#{channel_name.underscore}.rb"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def channel_name
|
23
|
+
@channel_name ||= options.fetch(:name, 'GraphQLChannel').classify
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -8,15 +8,20 @@ module GraphQL
|
|
8
8
|
include Rails::GraphQL::BaseGenerator
|
9
9
|
|
10
10
|
desc 'Add a new controller that operates with GraphQL'
|
11
|
-
|
11
|
+
|
12
|
+
argument :name, type: :string, optional: true,
|
13
|
+
default: "GraphQLController",
|
14
|
+
desc: 'The name for the controller'
|
12
15
|
|
13
16
|
def create_controller_file
|
14
17
|
template 'controller.erb', "app/controllers/#{controller_name.underscore}.rb"
|
15
18
|
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
private
|
21
|
+
|
22
|
+
def controller_name
|
23
|
+
@controller_name ||= options.fetch(:name, 'GraphQLController').classify
|
24
|
+
end
|
20
25
|
end
|
21
26
|
end
|
22
27
|
end
|