blitz_query_cpp

Форк
0
/
schema_parser.cpp 
730 строк · 24.1 Кб
1

2
#include <type_system/schema_parser.hpp>
3
#include <parser/parser.hpp>
4

5
using namespace blitz_query_cpp;
6

7
bool schema_parser_t::report_type_already_defined(std::string_view type_name)
8
{
9
    return report_error("Type with name '{}' already defined", type_name);
10
}
11

12
bool schema_parser_t::report_filed_already_defined(std::string_view type_name, std::string_view field_name)
13
{
14
    return report_error("Fileld with name '{}' already defined in type '{}'", field_name, type_name);
15
}
16

17
bool schema_parser_t::parse(schema_t &schema, std::string_view schema_string)
18
{
19
    document_t doc{std::string(schema_string)};
20
    parser_t parser{doc};
21
    if (!parser.parse())
22
    {
23
        return report_error("syntax error: {}", parser.get_error_msg());
24
    }
25
    if (!process_doc(schema, doc))
26
    {
27
        return false;
28
    }
29
    if (!compile(schema))
30
    {
31
        return false;
32
    }
33
    return true;
34
}
35

36
bool resolve_field(schema_t &schema, object_type &type, field &item);
37
bool resolve_input_value(schema_t &schema, object_type &type, input_value &item);
38

39
template <class T>
40
bool resolve_directives(const schema_t &schema, T &item)
41
{
42
    for (directive &dir : item.directives)
43
    {
44
        if (const auto dir_type = schema.find_directive_type(dir.name))
45
        {
46
            dir.directive_type = dir_type;
47
        }
48
    }
49
    return true;
50
}
51

52
template <class T>
53
bool resolve_type(const schema_t &schema, T &item)
54
{
55
    if (const auto type = schema.find_type(item.field_type.name))
56
    {
57
        item.field_type.type = type;
58
    }
59
    else if (item.declaring_type.name == item.field_type.name) // recursive field
60
    {
61
        item.field_type.type = item.declaring_type.type;
62
    }
63
    return true;
64
}
65

66
bool resolve_input_value(schema_t &schema, object_type &type, input_value &item)
67
{
68
    item.declaring_type.type = &type;
69

70
    if (!resolve_directives(schema, item))
71
        return false;
72

73
    if (!resolve_type(schema, item))
74
        return false;
75

76
    return true;
77
}
78

79
bool resolve_field(schema_t &schema, object_type &type, field &item)
80
{
81
    if (!resolve_input_value(schema, type, item))
82
        return false;
83

84
    for (auto &carg : item.arguments)
85
    {
86
        auto& arg = *const_cast<input_value*>(&carg);
87

88
        if (!resolve_directives(schema, arg))
89
            return false;
90
        if (!resolve_input_value(schema, type, arg))
91
            return false;        
92
    }
93
    return true;
94
}
95

96
bool schema_parser_t::compile(schema_t &schema)
97
{
98
    if (!resolve_directives(schema, schema))
99
        return false;
100

101
    for (auto &type_const : schema.types)
102
    {
103
        // objects are hashed by name, so changing everything but name sould be kind of OK
104
        auto& type = *const_cast<object_type*>(&type_const);
105

106
        if (!resolve_directives(schema, type))
107
            return false;
108

109
        for (auto &cf : type.fields)
110
        {
111
            auto& fld = *const_cast<field*>(&cf);
112
            resolve_field(schema, type, fld);
113
        }
114
    }
115

116
    schema.update_types();
117
       
118
    return true;
119
}
120

121
bool schema_parser_t::process_doc(schema_t &schema, const document_t &doc)
122
{
123
    for (const syntax_node *definition : doc.children)
124
    {
125
        bool result = false;
126
        switch (definition->type)
127
        {
128
        case syntax_node_type::SchemaDefinition:
129
            result = process_schema_def(schema, *definition);
130
            break;
131
        case syntax_node_type::ScalarTypeDefinition:
132
            result = process_scalar_type_def(schema, *definition);
133
            break;
134
        case syntax_node_type::DirectiveDefinition:
135
            result = process_directive_type_def(schema, *definition);
136
            break;
137
        case syntax_node_type::ObjectTypeDefinition:
138
            result = process_output_type_def(schema, *definition);
139
            break;
140
        case syntax_node_type::EnumTypeDefinition:
141
            result = process_enum_type_def(schema, *definition);
142
            break;
143
        case syntax_node_type::InputObjectTypeDefinition:
144
            result = process_input_type_def(schema, *definition);
145
            break;
146
        case syntax_node_type::InterfaceTypeDefinition:
147
            result = process_interface_type_def(schema, *definition);
148
            break;
149
        case syntax_node_type::UnionTypeDefinition:
150
            result = process_union_type_def(schema, *definition);
151
            break;
152
        case syntax_node_type::SchemaExtension:
153
            result = process_schema_ext(schema, *definition);
154
            break;
155
        case syntax_node_type::InputObjectTypeExtension:
156
            result = process_input_ext(schema, *definition);
157
            break;
158
        case syntax_node_type::EnumTypeExtension:
159
            result = process_enum_ext(schema, *definition);
160
            break;
161
        case syntax_node_type::UnionTypeExtension:
162
            result = process_union_ext(schema, *definition);
163
            break;
164
        case syntax_node_type::ObjectTypeExtension:
165
            result = process_output_ext(schema, *definition, type_kind::Object);
166
            break;
167
        case syntax_node_type::ScalarTypeExtension:
168
            result = process_scalar_ext(schema, *definition);
169
            break;
170
        case syntax_node_type::InterfaceTypeExtension:
171
            result = process_output_ext(schema, *definition, type_kind::Interface);
172
            break;
173
        default:
174
            return report_error("Not a schema definition found: {}", enum_name(definition->type));
175
        }
176
        if (!result)
177
            return false;
178
    }
179
    return true;
180
}
181

182
bool schema_parser_t::process_schema_def(schema_t &schema, const syntax_node &definition)
183
{
184
    for (syntax_node *child : definition.children)
185
    {
186
        if (child->type == syntax_node_type::OperationTypeDefinition)
187
        {
188
            if (child->children.size() < 1)
189
            {
190
                return false;
191
            }
192
            if (child->children[0]->type != syntax_node_type::NamedType)
193
            {
194
                return false;
195
            }
196
            if (child->operation_type == operation_type_t::Query)
197
            {
198
                schema.query_type_name = child->children[0]->content;
199
            }
200
            if (child->operation_type == operation_type_t::Mutation)
201
            {
202
                schema.mutation_type_name = child->children[0]->content;
203
            }
204
            continue;
205
        }
206

207
        if (child->type == syntax_node_type::Directive)
208
        {
209
            continue;
210
        }
211
        return report_error("Unexpected schema element of type: {}", enum_name(child->type));
212
    }
213
    if (!process_directives(schema.directives, definition))
214
        return false;
215
    return true;
216
}
217

218
bool schema_parser_t::process_schema_ext(schema_t &schema, const syntax_node &definition)
219
{
220
    for (syntax_node *child : definition.children)
221
    {
222
        if (child->type == syntax_node_type::OperationTypeDefinition)
223
        {
224
            if (child->children.size() < 1)
225
            {
226
                return false;
227
            }
228
            if (child->children[0]->type != syntax_node_type::NamedType)
229
            {
230
                return false;
231
            }
232
            if (child->operation_type == operation_type_t::Query)
233
            {
234
                if (schema.query_type_name.size() > 0)
235
                    return report_error(*child, "Query type is already defined in schema");
236
                schema.query_type_name = child->children[0]->content;
237
            }
238
            if (child->operation_type == operation_type_t::Mutation)
239
            {
240
                if (schema.mutation_type_name.size() > 0)
241
                    return report_error(*child, "Mutation type is already defined in schema");
242
                schema.mutation_type_name = child->children[0]->content;
243
            }
244
            continue;
245
        }
246

247
        if (child->type == syntax_node_type::Directive)
248
        {
249
            continue;
250
        }
251
        return report_error("Unexpected schema element of type: {}", enum_name(child->type));
252
    }
253
    if (!process_directives(schema.directives, definition))
254
        return false;
255
    return true;
256
}
257

258
bool schema_parser_t::process_scalar_type_def(schema_t &schema, const syntax_node &definition)
259
{
260
    object_type type{type_kind::Scalar, definition.name, definition.description};
261
    if (!process_directives(type, definition))
262
        return false;
263

264
    if (!schema.types.insert(std::move(type)).second)
265
    {
266
        return report_type_already_defined(definition.name);
267
    }
268

269
    return true;
270
}
271

272
bool schema_parser_t::process_enum_value(object_type &enum_type, const syntax_node &enum_field_node)
273
{
274
    if (enum_field_node.type != syntax_node_type::EnumValueDefinition)
275
    {
276
        if (enum_field_node.type != syntax_node_type::Directive)
277
            return 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);
278
        return true;
279
    }
280

281
    field field{enum_field_node.name, enum_field_node.description};
282

283
    if (!process_directives(field, enum_field_node))
284
        return false;
285

286
    if (!enum_type.fields.insert(std::move(field)).second)
287
        return report_filed_already_defined(enum_type.name, enum_field_node.name);
288

289
    return true;
290
}
291

292
bool schema_parser_t::process_enum_type_def(schema_t &schema, const syntax_node &definition)
293
{
294
    object_type enum_type{type_kind::Enum, definition.name, definition.description};
295

296
    if (!process_directives(enum_type, definition))
297
        return false;
298
    for (const syntax_node *child_node : definition.children)
299
    {
300
        if (!process_enum_value(enum_type, *child_node))
301
            return false;
302
    }
303

304
    if (!schema.types.insert(std::move(enum_type)).second)
305
        return report_type_already_defined(definition.name);
306

307
    return true;
308
}
309

310
bool schema_parser_t::process_parameter_value(parameter_value &param, const syntax_node &value_node)
311
{
312
    switch (value_node.type)
313
    {
314
    case syntax_node_type::BoolValue:
315
        param.value_type = value_kind::Boolean;
316
        param.bool_value = value_node.boolValue;
317
        return true;
318
    case syntax_node_type::IntValue:
319
        param.value_type = value_kind::Integer;
320
        param.int_value = value_node.intValue;
321
        return true;
322
    case syntax_node_type::StringValue:
323
        param.value_type = value_kind::String;
324
        param.string_value = value_node.content;
325
        return true;
326
    case syntax_node_type::EnumValue:
327
        param.value_type = value_kind::Enum;
328
        param.string_value = value_node.content;
329
        return true;
330
    case syntax_node_type::NullValue:
331
        param.value_type = value_kind::Null;
332
        param.string_value = value_node.content;
333
        return true;
334
    case syntax_node_type::FloatValue:
335
        param.value_type = value_kind::Float;
336
        param.float_value = value_node.floatValue;
337
        return true;
338
    case syntax_node_type::ListValue:
339
        param.value_type = value_kind::List;
340
        return process_params(param.fields, value_node);
341
    case syntax_node_type::ObjectValue:
342
        param.value_type = value_kind::Object;
343
        return process_params(param.fields, value_node);
344
    default:
345
        return report_error("value expected at {}", value_node.pos);
346
    }
347
    return false;
348
}
349

350
bool schema_parser_t::process_params(named_collection<parameter_value> &arguments, const syntax_node &node)
351
{
352
    for (const syntax_node *child_node : node.children)
353
    {
354
        parameter_value param{child_node->name, child_node->description};
355

356
        if (child_node->children.size() < 1)
357
            return false;
358
        syntax_node *value_node = child_node->children[0];
359

360
        if (!process_parameter_value(param, *value_node))
361
            return false;
362

363
        if (!arguments.insert(param).second)
364
            return report_error(*child_node, "parameter with name '{}' already defined", child_node->name);
365
    }
366
    return true;
367
}
368

369
bool schema_parser_t::process_directives(std::vector<directive> &directives, const syntax_node &definition)
370
{
371
    for (const syntax_node *directive_node : definition.directives)
372
    {
373
        directive dir{directive_node->name};
374

375
        if (!process_params(dir.parameters, *directive_node))
376
            return false;
377

378
        directives.push_back(std::move(dir));
379
    }
380
    return true;
381
}
382

383
bool schema_parser_t::process_directive_type_def(schema_t &schema, const syntax_node &definition)
384
{
385
    directive_type dir{definition.name, definition.description, definition.directive_target};
386

387
    if (!process_arguments(dir.arguments, definition))
388
        return false;
389

390
    if (!schema.directive_types.insert(dir).second)
391
        return report_error("directive type with name {} already defined", definition.name);
392

393
    return true;
394
}
395

396
bool schema_parser_t::process_arguments(named_collection<input_value> &arguments, const syntax_node &node)
397
{
398
    for (const syntax_node *child_node : node.arguments)
399
    {
400
        if (!child_node->definition_type)
401
            return report_error(*child_node, "argument type is not defined for {} at {}", child_node->name);
402

403
        input_value value{child_node->name, child_node->description};
404
        value.index = arguments.size();
405

406
        if (!process_input_value(value, *child_node))
407
            return true;
408

409
        if (!arguments.insert(std::move(value)).second)
410
            return report_error(*child_node, "argument with name {} already specified", child_node->name);
411
    }
412
    return true;
413
}
414

415
bool schema_parser_t::process_filed_type(input_value &value, const syntax_node &node)
416
{
417
    const syntax_node *type_definition = node.definition_type;
418
    while (type_definition && type_definition->type == syntax_node_type::ListType)
419
    {
420
        if (type_definition->nullability == nullability_t::Required)
421
            value.field_type.not_nullable |= (1 << value.field_type.list_nesting_depth);
422
        value.field_type.list_nesting_depth++;
423
        if (value.field_type.list_nesting_depth > int(sizeof(value.field_type.not_nullable) * CHAR_BIT - 1))
424
        {
425
            return report_error("maximum list nesting exceeded at {}", type_definition->pos);
426
        }
427
        type_definition = type_definition->definition_type;
428
    }
429

430
    if (type_definition->type != syntax_node_type::NamedType)
431
        return report_error("named type expected at {}", type_definition->pos);
432

433
    if (type_definition->nullability == nullability_t::Required)
434
        value.field_type.not_nullable |= (1 << value.field_type.list_nesting_depth);
435

436
    value.field_type.name = type_definition->name;
437
    return true;
438
}
439

440
bool schema_parser_t::process_input_value(input_value &value, const syntax_node &node)
441
{
442
    if (!process_filed_type(value, node))
443
        return false;
444
    // handle default value
445
    if (node.children.size() > 1u)
446
    {
447
        const syntax_node *default_value_node = node.children[1];
448
        if (!process_parameter_value(value.default_value, *default_value_node))
449
            return false;
450
    }
451

452
    if (!process_directives(value, node))
453
        return false;
454

455
    return true;
456
}
457

458
bool schema_parser_t::process_union_type_def(schema_t &schema, const syntax_node &definition)
459
{
460
    object_type union_type{std::string(definition.name), std::string(definition.description)};
461
    union_type.kind = type_kind::Union;
462

463
    if (!process_directives(union_type, definition))
464
        return false;
465

466
    for (const syntax_node *union_member_def : definition.implements)
467
    {
468
        if (!process_implemented_type(union_type, *union_member_def))
469
            return false;
470
    }
471

472
    if (!schema.types.insert(std::move(union_type)).second)
473
        return report_type_already_defined(definition.name);
474

475
    return true;
476
}
477

478
bool schema_parser_t::process_implemented_type(object_type &type, const syntax_node &member_def)
479
{
480
    auto res = type.implements.emplace(member_def.name);
481
    if (!res.second)
482
    {
483
        return report_error(member_def, "type with name {} already implemented by type {} ", member_def.name, type.name);
484
    }
485

486
    return true;
487
}
488

489
bool schema_parser_t::process_input_type_def(schema_t &schema, const syntax_node &definition)
490
{
491
    object_type input_type{type_kind::InputObject, std::string(definition.name), std::string(definition.description)};
492

493
    if (!process_directives(input_type, definition))
494
        return false;
495

496
    for (const syntax_node *child_node : definition.children)
497
    {
498
        if (!process_input_field(input_type, *child_node))
499
            return false;
500
    }
501

502
    if (!schema.types.insert(std::move(input_type)).second)
503
        return report_type_already_defined(definition.name);
504

505
    return true;
506
}
507

508
bool schema_parser_t::process_input_ext(schema_t &schema, const syntax_node &definition)
509
{
510
    auto res = schema.types.find(definition.name);
511
    if (res == schema.types.end())
512
        return report_error(definition, "Type {} is not defined", definition.name);
513
    if (res->kind != type_kind::InputObject)
514
        return report_error(definition, "Type {} is not InputObject", definition.name);
515

516
    object_type input_type = std::move(schema.types.extract(res).value());
517

518
    if (!process_directives(input_type, definition))
519
        return false;
520

521
    for (const syntax_node *child_node : definition.children)
522
    {
523
        if (!process_input_field(input_type, *child_node))
524
            return false;
525
    }
526

527
    if (!schema.types.insert(std::move(input_type)).second)
528
        return report_error("Unable to extend type: {}", definition.name);
529

530
    return true;
531
}
532

533
bool schema_parser_t::process_scalar_ext(schema_t &schema, const syntax_node &definition)
534
{
535
    auto res = schema.types.find(definition.name);
536
    if (res == schema.types.end())
537
        return report_error(definition, "Type {} is not defined", definition.name);
538
    if (res->kind != type_kind::Scalar)
539
        return report_error(definition, "Type {} is not Scalar", definition.name);
540

541
    object_type type = std::move(schema.types.extract(res).value());
542

543
    if (!process_directives(type, definition))
544
        return false;
545

546
    if (!schema.types.insert(std::move(type)).second)
547
        return report_error("Unable to extend type: {}", definition.name);
548

549
    return true;
550
}
551

552
bool schema_parser_t::process_enum_ext(schema_t &schema, const syntax_node &definition)
553
{
554
    auto res = schema.types.find(definition.name);
555
    if (res == schema.types.end())
556
        return report_error(definition, "Type {} is not defined", definition.name);
557
    if (res->kind != type_kind::Enum)
558
        return report_error(definition, "Type {} is not Enum", definition.name);
559

560
    object_type enum_type = std::move(schema.types.extract(res).value());
561

562
    if (!process_directives(enum_type, definition))
563
        return false;
564
    for (const syntax_node *child_node : definition.children)
565
    {
566
        if (!process_enum_value(enum_type, *child_node))
567
            return false;
568
    }
569

570
    if (!schema.types.insert(std::move(enum_type)).second)
571
        return report_error("Unable to extend type: {}", definition.name);
572

573
    return true;
574
}
575

576
bool schema_parser_t::process_union_ext(schema_t &schema, const syntax_node &definition)
577
{
578
    auto res = schema.types.find(definition.name);
579
    if (res == schema.types.end())
580
        return report_error(definition, "Type {} is not defined", definition.name);
581
    if (res->kind != type_kind::Union)
582
        return report_error(definition, "Type {} is not Union", definition.name);
583

584
    object_type union_type = std::move(schema.types.extract(res).value());
585

586
    if (!process_directives(union_type, definition))
587
        return false;
588

589
    for (const syntax_node *union_member_def : definition.implements)
590
    {
591
        if (!process_implemented_type(union_type, *union_member_def))
592
            return false;
593
    }
594

595
    if (!schema.types.insert(std::move(union_type)).second)
596
        return report_error("Unable to extend type: {}", definition.name);
597

598
    return true;
599
}
600

601
bool schema_parser_t::process_output_ext(schema_t &schema, const syntax_node &definition, type_kind kind)
602
{
603
    auto res = schema.types.find(definition.name);
604
    if (res == schema.types.end())
605
        return report_error(definition, "Type {} is not defined", definition.name);
606
    if (res->kind != kind)
607
        return report_error(definition, "Type {} is not matched", definition.name);
608

609
    object_type output_type = std::move(schema.types.extract(res).value());
610

611
    if (!process_directives(output_type, definition))
612
        return false;
613

614
    for (const syntax_node *inter : definition.implements)
615
    {
616
        if (!process_implemented_type(output_type, *inter))
617
            return false;
618
    }
619

620
    for (const syntax_node *child_node : definition.children)
621
    {
622
        if (!process_output_field(output_type, *child_node))
623
            return false;
624
    }
625

626
    if (!schema.types.insert(std::move(output_type)).second)
627
        return report_error("Unable to extend type: {}", definition.name);
628

629
    return true;
630
}
631

632
bool schema_parser_t::process_input_field(object_type &type, const syntax_node &field_node)
633
{
634
    if (field_node.type != syntax_node_type::InputValueDefinition)
635
    {
636
        if (field_node.type != syntax_node_type::Directive)
637
            return report_error(field_node, "unexpected node type: {} in input type '{}' at {}", enum_name(field_node.type), type.name);
638
        return true;
639
    }
640

641
    field field{field_node.name, field_node.description};
642

643
    if (!process_input_value(field, field_node))
644
        return false;
645
    field.index = type.fields.size();
646
    field.declaring_type.name = type.name;
647

648
    if (!type.fields.insert(std::move(field)).second)
649
        return report_filed_already_defined(type.name, field_node.name);
650

651
    return true;
652
}
653

654
bool schema_parser_t::process_output_type_def(schema_t &schema, const syntax_node &definition)
655
{
656
    object_type output_type{type_kind::Object, std::string(definition.name), std::string(definition.description)};
657

658
    if (!process_directives(output_type, definition))
659
        return false;
660

661
    for (const syntax_node *inter : definition.implements)
662
    {
663
        if (!process_implemented_type(output_type, *inter))
664
            return false;
665
    }
666

667
    for (const syntax_node *child_node : definition.children)
668
    {
669
        if (!process_output_field(output_type, *child_node))
670
            return false;
671
    }
672

673
    if (!schema.types.insert(std::move(output_type)).second)
674
        return report_type_already_defined(definition.name);
675

676
    return true;
677
}
678

679
bool schema_parser_t::process_interface_type_def(schema_t &schema, const syntax_node &definition)
680
{
681
    object_type output_type{type_kind::Interface, std::string(definition.name), std::string(definition.description)};
682

683
    if (!process_directives(output_type, definition))
684
        return false;
685

686
    for (const syntax_node *inter : definition.implements)
687
    {
688
        if (!process_implemented_type(output_type, *inter))
689
            return false;
690
    }
691

692
    for (const syntax_node *child_node : definition.children)
693
    {
694
        if (!process_output_field(output_type, *child_node))
695
            return false;
696
    }
697

698
    if (!schema.types.insert(std::move(output_type)).second)
699
        return report_type_already_defined(definition.name);
700

701
    return true;
702
}
703

704
bool schema_parser_t::process_output_field(object_type &type, const syntax_node &field_node)
705
{
706
    if (field_node.type != syntax_node_type::FieldDefinition)
707
    {
708
        if (!has_any_flag(field_node.type, syntax_node_type::Directive | syntax_node_type::NamedType))
709
            return report_error(field_node, "unexpected node type: {} in type type '{}'", enum_name(field_node.type), type.name);
710
        return true;
711
    }
712

713
    field field{field_node.name, field_node.description};
714

715
    if (!process_filed_type(field, field_node))
716
        return false;
717

718
    if (!process_directives(field, field_node))
719
        return false;
720

721
    if (!process_arguments(field.arguments, field_node))
722
        return false;
723

724
    field.index = type.fields.size();
725
    field.declaring_type.name = type.name;
726

727
    if (!type.fields.insert(std::move(field)).second)
728
        return report_filed_already_defined(type.name, field_node.name);
729

730
    return true;
731
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.