blitz_query_cpp
730 строк · 24.1 Кб
1
2#include <type_system/schema_parser.hpp>
3#include <parser/parser.hpp>
4
5using namespace blitz_query_cpp;
6
7bool schema_parser_t::report_type_already_defined(std::string_view type_name)
8{
9return report_error("Type with name '{}' already defined", type_name);
10}
11
12bool schema_parser_t::report_filed_already_defined(std::string_view type_name, std::string_view field_name)
13{
14return report_error("Fileld with name '{}' already defined in type '{}'", field_name, type_name);
15}
16
17bool schema_parser_t::parse(schema_t &schema, std::string_view schema_string)
18{
19document_t doc{std::string(schema_string)};
20parser_t parser{doc};
21if (!parser.parse())
22{
23return report_error("syntax error: {}", parser.get_error_msg());
24}
25if (!process_doc(schema, doc))
26{
27return false;
28}
29if (!compile(schema))
30{
31return false;
32}
33return true;
34}
35
36bool resolve_field(schema_t &schema, object_type &type, field &item);
37bool resolve_input_value(schema_t &schema, object_type &type, input_value &item);
38
39template <class T>
40bool resolve_directives(const schema_t &schema, T &item)
41{
42for (directive &dir : item.directives)
43{
44if (const auto dir_type = schema.find_directive_type(dir.name))
45{
46dir.directive_type = dir_type;
47}
48}
49return true;
50}
51
52template <class T>
53bool resolve_type(const schema_t &schema, T &item)
54{
55if (const auto type = schema.find_type(item.field_type.name))
56{
57item.field_type.type = type;
58}
59else if (item.declaring_type.name == item.field_type.name) // recursive field
60{
61item.field_type.type = item.declaring_type.type;
62}
63return true;
64}
65
66bool resolve_input_value(schema_t &schema, object_type &type, input_value &item)
67{
68item.declaring_type.type = &type;
69
70if (!resolve_directives(schema, item))
71return false;
72
73if (!resolve_type(schema, item))
74return false;
75
76return true;
77}
78
79bool resolve_field(schema_t &schema, object_type &type, field &item)
80{
81if (!resolve_input_value(schema, type, item))
82return false;
83
84for (auto &carg : item.arguments)
85{
86auto& arg = *const_cast<input_value*>(&carg);
87
88if (!resolve_directives(schema, arg))
89return false;
90if (!resolve_input_value(schema, type, arg))
91return false;
92}
93return true;
94}
95
96bool schema_parser_t::compile(schema_t &schema)
97{
98if (!resolve_directives(schema, schema))
99return false;
100
101for (auto &type_const : schema.types)
102{
103// objects are hashed by name, so changing everything but name sould be kind of OK
104auto& type = *const_cast<object_type*>(&type_const);
105
106if (!resolve_directives(schema, type))
107return false;
108
109for (auto &cf : type.fields)
110{
111auto& fld = *const_cast<field*>(&cf);
112resolve_field(schema, type, fld);
113}
114}
115
116schema.update_types();
117
118return true;
119}
120
121bool schema_parser_t::process_doc(schema_t &schema, const document_t &doc)
122{
123for (const syntax_node *definition : doc.children)
124{
125bool result = false;
126switch (definition->type)
127{
128case syntax_node_type::SchemaDefinition:
129result = process_schema_def(schema, *definition);
130break;
131case syntax_node_type::ScalarTypeDefinition:
132result = process_scalar_type_def(schema, *definition);
133break;
134case syntax_node_type::DirectiveDefinition:
135result = process_directive_type_def(schema, *definition);
136break;
137case syntax_node_type::ObjectTypeDefinition:
138result = process_output_type_def(schema, *definition);
139break;
140case syntax_node_type::EnumTypeDefinition:
141result = process_enum_type_def(schema, *definition);
142break;
143case syntax_node_type::InputObjectTypeDefinition:
144result = process_input_type_def(schema, *definition);
145break;
146case syntax_node_type::InterfaceTypeDefinition:
147result = process_interface_type_def(schema, *definition);
148break;
149case syntax_node_type::UnionTypeDefinition:
150result = process_union_type_def(schema, *definition);
151break;
152case syntax_node_type::SchemaExtension:
153result = process_schema_ext(schema, *definition);
154break;
155case syntax_node_type::InputObjectTypeExtension:
156result = process_input_ext(schema, *definition);
157break;
158case syntax_node_type::EnumTypeExtension:
159result = process_enum_ext(schema, *definition);
160break;
161case syntax_node_type::UnionTypeExtension:
162result = process_union_ext(schema, *definition);
163break;
164case syntax_node_type::ObjectTypeExtension:
165result = process_output_ext(schema, *definition, type_kind::Object);
166break;
167case syntax_node_type::ScalarTypeExtension:
168result = process_scalar_ext(schema, *definition);
169break;
170case syntax_node_type::InterfaceTypeExtension:
171result = process_output_ext(schema, *definition, type_kind::Interface);
172break;
173default:
174return report_error("Not a schema definition found: {}", enum_name(definition->type));
175}
176if (!result)
177return false;
178}
179return true;
180}
181
182bool schema_parser_t::process_schema_def(schema_t &schema, const syntax_node &definition)
183{
184for (syntax_node *child : definition.children)
185{
186if (child->type == syntax_node_type::OperationTypeDefinition)
187{
188if (child->children.size() < 1)
189{
190return false;
191}
192if (child->children[0]->type != syntax_node_type::NamedType)
193{
194return false;
195}
196if (child->operation_type == operation_type_t::Query)
197{
198schema.query_type_name = child->children[0]->content;
199}
200if (child->operation_type == operation_type_t::Mutation)
201{
202schema.mutation_type_name = child->children[0]->content;
203}
204continue;
205}
206
207if (child->type == syntax_node_type::Directive)
208{
209continue;
210}
211return report_error("Unexpected schema element of type: {}", enum_name(child->type));
212}
213if (!process_directives(schema.directives, definition))
214return false;
215return true;
216}
217
218bool schema_parser_t::process_schema_ext(schema_t &schema, const syntax_node &definition)
219{
220for (syntax_node *child : definition.children)
221{
222if (child->type == syntax_node_type::OperationTypeDefinition)
223{
224if (child->children.size() < 1)
225{
226return false;
227}
228if (child->children[0]->type != syntax_node_type::NamedType)
229{
230return false;
231}
232if (child->operation_type == operation_type_t::Query)
233{
234if (schema.query_type_name.size() > 0)
235return report_error(*child, "Query type is already defined in schema");
236schema.query_type_name = child->children[0]->content;
237}
238if (child->operation_type == operation_type_t::Mutation)
239{
240if (schema.mutation_type_name.size() > 0)
241return report_error(*child, "Mutation type is already defined in schema");
242schema.mutation_type_name = child->children[0]->content;
243}
244continue;
245}
246
247if (child->type == syntax_node_type::Directive)
248{
249continue;
250}
251return report_error("Unexpected schema element of type: {}", enum_name(child->type));
252}
253if (!process_directives(schema.directives, definition))
254return false;
255return true;
256}
257
258bool schema_parser_t::process_scalar_type_def(schema_t &schema, const syntax_node &definition)
259{
260object_type type{type_kind::Scalar, definition.name, definition.description};
261if (!process_directives(type, definition))
262return false;
263
264if (!schema.types.insert(std::move(type)).second)
265{
266return report_type_already_defined(definition.name);
267}
268
269return true;
270}
271
272bool schema_parser_t::process_enum_value(object_type &enum_type, const syntax_node &enum_field_node)
273{
274if (enum_field_node.type != syntax_node_type::EnumValueDefinition)
275{
276if (enum_field_node.type != syntax_node_type::Directive)
277return report_error("unexpected node type in enum: {} in enum '{}' at {}", enum_name(enum_field_node.type), enum_field_node.name, enum_type.name, enum_field_node.pos);
278return true;
279}
280
281field field{enum_field_node.name, enum_field_node.description};
282
283if (!process_directives(field, enum_field_node))
284return false;
285
286if (!enum_type.fields.insert(std::move(field)).second)
287return report_filed_already_defined(enum_type.name, enum_field_node.name);
288
289return true;
290}
291
292bool schema_parser_t::process_enum_type_def(schema_t &schema, const syntax_node &definition)
293{
294object_type enum_type{type_kind::Enum, definition.name, definition.description};
295
296if (!process_directives(enum_type, definition))
297return false;
298for (const syntax_node *child_node : definition.children)
299{
300if (!process_enum_value(enum_type, *child_node))
301return false;
302}
303
304if (!schema.types.insert(std::move(enum_type)).second)
305return report_type_already_defined(definition.name);
306
307return true;
308}
309
310bool schema_parser_t::process_parameter_value(parameter_value ¶m, const syntax_node &value_node)
311{
312switch (value_node.type)
313{
314case syntax_node_type::BoolValue:
315param.value_type = value_kind::Boolean;
316param.bool_value = value_node.boolValue;
317return true;
318case syntax_node_type::IntValue:
319param.value_type = value_kind::Integer;
320param.int_value = value_node.intValue;
321return true;
322case syntax_node_type::StringValue:
323param.value_type = value_kind::String;
324param.string_value = value_node.content;
325return true;
326case syntax_node_type::EnumValue:
327param.value_type = value_kind::Enum;
328param.string_value = value_node.content;
329return true;
330case syntax_node_type::NullValue:
331param.value_type = value_kind::Null;
332param.string_value = value_node.content;
333return true;
334case syntax_node_type::FloatValue:
335param.value_type = value_kind::Float;
336param.float_value = value_node.floatValue;
337return true;
338case syntax_node_type::ListValue:
339param.value_type = value_kind::List;
340return process_params(param.fields, value_node);
341case syntax_node_type::ObjectValue:
342param.value_type = value_kind::Object;
343return process_params(param.fields, value_node);
344default:
345return report_error("value expected at {}", value_node.pos);
346}
347return false;
348}
349
350bool schema_parser_t::process_params(named_collection<parameter_value> &arguments, const syntax_node &node)
351{
352for (const syntax_node *child_node : node.children)
353{
354parameter_value param{child_node->name, child_node->description};
355
356if (child_node->children.size() < 1)
357return false;
358syntax_node *value_node = child_node->children[0];
359
360if (!process_parameter_value(param, *value_node))
361return false;
362
363if (!arguments.insert(param).second)
364return report_error(*child_node, "parameter with name '{}' already defined", child_node->name);
365}
366return true;
367}
368
369bool schema_parser_t::process_directives(std::vector<directive> &directives, const syntax_node &definition)
370{
371for (const syntax_node *directive_node : definition.directives)
372{
373directive dir{directive_node->name};
374
375if (!process_params(dir.parameters, *directive_node))
376return false;
377
378directives.push_back(std::move(dir));
379}
380return true;
381}
382
383bool schema_parser_t::process_directive_type_def(schema_t &schema, const syntax_node &definition)
384{
385directive_type dir{definition.name, definition.description, definition.directive_target};
386
387if (!process_arguments(dir.arguments, definition))
388return false;
389
390if (!schema.directive_types.insert(dir).second)
391return report_error("directive type with name {} already defined", definition.name);
392
393return true;
394}
395
396bool schema_parser_t::process_arguments(named_collection<input_value> &arguments, const syntax_node &node)
397{
398for (const syntax_node *child_node : node.arguments)
399{
400if (!child_node->definition_type)
401return report_error(*child_node, "argument type is not defined for {} at {}", child_node->name);
402
403input_value value{child_node->name, child_node->description};
404value.index = arguments.size();
405
406if (!process_input_value(value, *child_node))
407return true;
408
409if (!arguments.insert(std::move(value)).second)
410return report_error(*child_node, "argument with name {} already specified", child_node->name);
411}
412return true;
413}
414
415bool schema_parser_t::process_filed_type(input_value &value, const syntax_node &node)
416{
417const syntax_node *type_definition = node.definition_type;
418while (type_definition && type_definition->type == syntax_node_type::ListType)
419{
420if (type_definition->nullability == nullability_t::Required)
421value.field_type.not_nullable |= (1 << value.field_type.list_nesting_depth);
422value.field_type.list_nesting_depth++;
423if (value.field_type.list_nesting_depth > int(sizeof(value.field_type.not_nullable) * CHAR_BIT - 1))
424{
425return report_error("maximum list nesting exceeded at {}", type_definition->pos);
426}
427type_definition = type_definition->definition_type;
428}
429
430if (type_definition->type != syntax_node_type::NamedType)
431return report_error("named type expected at {}", type_definition->pos);
432
433if (type_definition->nullability == nullability_t::Required)
434value.field_type.not_nullable |= (1 << value.field_type.list_nesting_depth);
435
436value.field_type.name = type_definition->name;
437return true;
438}
439
440bool schema_parser_t::process_input_value(input_value &value, const syntax_node &node)
441{
442if (!process_filed_type(value, node))
443return false;
444// handle default value
445if (node.children.size() > 1u)
446{
447const syntax_node *default_value_node = node.children[1];
448if (!process_parameter_value(value.default_value, *default_value_node))
449return false;
450}
451
452if (!process_directives(value, node))
453return false;
454
455return true;
456}
457
458bool schema_parser_t::process_union_type_def(schema_t &schema, const syntax_node &definition)
459{
460object_type union_type{std::string(definition.name), std::string(definition.description)};
461union_type.kind = type_kind::Union;
462
463if (!process_directives(union_type, definition))
464return false;
465
466for (const syntax_node *union_member_def : definition.implements)
467{
468if (!process_implemented_type(union_type, *union_member_def))
469return false;
470}
471
472if (!schema.types.insert(std::move(union_type)).second)
473return report_type_already_defined(definition.name);
474
475return true;
476}
477
478bool schema_parser_t::process_implemented_type(object_type &type, const syntax_node &member_def)
479{
480auto res = type.implements.emplace(member_def.name);
481if (!res.second)
482{
483return report_error(member_def, "type with name {} already implemented by type {} ", member_def.name, type.name);
484}
485
486return true;
487}
488
489bool schema_parser_t::process_input_type_def(schema_t &schema, const syntax_node &definition)
490{
491object_type input_type{type_kind::InputObject, std::string(definition.name), std::string(definition.description)};
492
493if (!process_directives(input_type, definition))
494return false;
495
496for (const syntax_node *child_node : definition.children)
497{
498if (!process_input_field(input_type, *child_node))
499return false;
500}
501
502if (!schema.types.insert(std::move(input_type)).second)
503return report_type_already_defined(definition.name);
504
505return true;
506}
507
508bool schema_parser_t::process_input_ext(schema_t &schema, const syntax_node &definition)
509{
510auto res = schema.types.find(definition.name);
511if (res == schema.types.end())
512return report_error(definition, "Type {} is not defined", definition.name);
513if (res->kind != type_kind::InputObject)
514return report_error(definition, "Type {} is not InputObject", definition.name);
515
516object_type input_type = std::move(schema.types.extract(res).value());
517
518if (!process_directives(input_type, definition))
519return false;
520
521for (const syntax_node *child_node : definition.children)
522{
523if (!process_input_field(input_type, *child_node))
524return false;
525}
526
527if (!schema.types.insert(std::move(input_type)).second)
528return report_error("Unable to extend type: {}", definition.name);
529
530return true;
531}
532
533bool schema_parser_t::process_scalar_ext(schema_t &schema, const syntax_node &definition)
534{
535auto res = schema.types.find(definition.name);
536if (res == schema.types.end())
537return report_error(definition, "Type {} is not defined", definition.name);
538if (res->kind != type_kind::Scalar)
539return report_error(definition, "Type {} is not Scalar", definition.name);
540
541object_type type = std::move(schema.types.extract(res).value());
542
543if (!process_directives(type, definition))
544return false;
545
546if (!schema.types.insert(std::move(type)).second)
547return report_error("Unable to extend type: {}", definition.name);
548
549return true;
550}
551
552bool schema_parser_t::process_enum_ext(schema_t &schema, const syntax_node &definition)
553{
554auto res = schema.types.find(definition.name);
555if (res == schema.types.end())
556return report_error(definition, "Type {} is not defined", definition.name);
557if (res->kind != type_kind::Enum)
558return report_error(definition, "Type {} is not Enum", definition.name);
559
560object_type enum_type = std::move(schema.types.extract(res).value());
561
562if (!process_directives(enum_type, definition))
563return false;
564for (const syntax_node *child_node : definition.children)
565{
566if (!process_enum_value(enum_type, *child_node))
567return false;
568}
569
570if (!schema.types.insert(std::move(enum_type)).second)
571return report_error("Unable to extend type: {}", definition.name);
572
573return true;
574}
575
576bool schema_parser_t::process_union_ext(schema_t &schema, const syntax_node &definition)
577{
578auto res = schema.types.find(definition.name);
579if (res == schema.types.end())
580return report_error(definition, "Type {} is not defined", definition.name);
581if (res->kind != type_kind::Union)
582return report_error(definition, "Type {} is not Union", definition.name);
583
584object_type union_type = std::move(schema.types.extract(res).value());
585
586if (!process_directives(union_type, definition))
587return false;
588
589for (const syntax_node *union_member_def : definition.implements)
590{
591if (!process_implemented_type(union_type, *union_member_def))
592return false;
593}
594
595if (!schema.types.insert(std::move(union_type)).second)
596return report_error("Unable to extend type: {}", definition.name);
597
598return true;
599}
600
601bool schema_parser_t::process_output_ext(schema_t &schema, const syntax_node &definition, type_kind kind)
602{
603auto res = schema.types.find(definition.name);
604if (res == schema.types.end())
605return report_error(definition, "Type {} is not defined", definition.name);
606if (res->kind != kind)
607return report_error(definition, "Type {} is not matched", definition.name);
608
609object_type output_type = std::move(schema.types.extract(res).value());
610
611if (!process_directives(output_type, definition))
612return false;
613
614for (const syntax_node *inter : definition.implements)
615{
616if (!process_implemented_type(output_type, *inter))
617return false;
618}
619
620for (const syntax_node *child_node : definition.children)
621{
622if (!process_output_field(output_type, *child_node))
623return false;
624}
625
626if (!schema.types.insert(std::move(output_type)).second)
627return report_error("Unable to extend type: {}", definition.name);
628
629return true;
630}
631
632bool schema_parser_t::process_input_field(object_type &type, const syntax_node &field_node)
633{
634if (field_node.type != syntax_node_type::InputValueDefinition)
635{
636if (field_node.type != syntax_node_type::Directive)
637return report_error(field_node, "unexpected node type: {} in input type '{}' at {}", enum_name(field_node.type), type.name);
638return true;
639}
640
641field field{field_node.name, field_node.description};
642
643if (!process_input_value(field, field_node))
644return false;
645field.index = type.fields.size();
646field.declaring_type.name = type.name;
647
648if (!type.fields.insert(std::move(field)).second)
649return report_filed_already_defined(type.name, field_node.name);
650
651return true;
652}
653
654bool schema_parser_t::process_output_type_def(schema_t &schema, const syntax_node &definition)
655{
656object_type output_type{type_kind::Object, std::string(definition.name), std::string(definition.description)};
657
658if (!process_directives(output_type, definition))
659return false;
660
661for (const syntax_node *inter : definition.implements)
662{
663if (!process_implemented_type(output_type, *inter))
664return false;
665}
666
667for (const syntax_node *child_node : definition.children)
668{
669if (!process_output_field(output_type, *child_node))
670return false;
671}
672
673if (!schema.types.insert(std::move(output_type)).second)
674return report_type_already_defined(definition.name);
675
676return true;
677}
678
679bool schema_parser_t::process_interface_type_def(schema_t &schema, const syntax_node &definition)
680{
681object_type output_type{type_kind::Interface, std::string(definition.name), std::string(definition.description)};
682
683if (!process_directives(output_type, definition))
684return false;
685
686for (const syntax_node *inter : definition.implements)
687{
688if (!process_implemented_type(output_type, *inter))
689return false;
690}
691
692for (const syntax_node *child_node : definition.children)
693{
694if (!process_output_field(output_type, *child_node))
695return false;
696}
697
698if (!schema.types.insert(std::move(output_type)).second)
699return report_type_already_defined(definition.name);
700
701return true;
702}
703
704bool schema_parser_t::process_output_field(object_type &type, const syntax_node &field_node)
705{
706if (field_node.type != syntax_node_type::FieldDefinition)
707{
708if (!has_any_flag(field_node.type, syntax_node_type::Directive | syntax_node_type::NamedType))
709return report_error(field_node, "unexpected node type: {} in type type '{}'", enum_name(field_node.type), type.name);
710return true;
711}
712
713field field{field_node.name, field_node.description};
714
715if (!process_filed_type(field, field_node))
716return false;
717
718if (!process_directives(field, field_node))
719return false;
720
721if (!process_arguments(field.arguments, field_node))
722return false;
723
724field.index = type.fields.size();
725field.declaring_type.name = type.name;
726
727if (!type.fields.insert(std::move(field)).second)
728return report_filed_already_defined(type.name, field_node.name);
729
730return true;
731}