1use std::cell::RefCell;
2use crate::ast::model::Model;
3use crate::{parse_append, parse_container_node_variables, parse_container_node_variables_cleanup, parse_insert, parse_insert_keyword, parse_insert_punctuation, parse_set_identifier_and_string_path, parse_set_optional};
4use crate::parser::parse_availability_end::parse_availability_end;
5use crate::parser::parse_availability_flag::parse_availability_flag;
6use crate::parser::parse_code_comment::parse_code_comment;
7use crate::parser::parse_doc_comment::parse_doc_comment;
8use crate::parser::parse_decorator::parse_decorator;
9use crate::parser::parse_field::parse_field;
10use crate::parser::parse_handler_group::parse_handler_declaration;
11use crate::parser::parse_include_handler_from_template::parse_include_handler_from_template;
12use crate::parser::parse_partial_field::parse_partial_field;
13use crate::parser::parse_span::parse_span;
14use crate::parser::parser_context::ParserContext;
15use crate::parser::pest_parser::{Pair, Rule};
16
17pub(super) fn parse_model_declaration(pair: Pair<'_>, context: &ParserContext) -> Model {
18 let (
19 span,
20 path,
21 mut string_path,
22 mut children,
23 define_availability,
24 actual_availability
25 ) = parse_container_node_variables!(pair, context, named, availability);
26 let mut inside_block = false;
27 let mut comment = None;
28 let mut decorators = vec![];
29 let mut empty_decorator_spans = vec![];
30 let mut empty_field_decorator_spans = vec![];
31 let mut unattached_field_decorators = vec![];
32 let mut identifier = 0;
33 let mut fields = vec![];
34 let mut partial_fields = vec![];
35 let mut handlers = vec![];
36 let mut handler_inclusions = vec![];
37 for current in pair.into_inner() {
38 match current.as_rule() {
39 Rule::MODEL_KEYWORD => parse_insert_keyword!(context, current, children, "model"),
40 Rule::BLOCK_CLOSE => parse_insert_punctuation!(context, current, children, "}"),
41 Rule::BLOCK_OPEN => {
42 parse_insert_punctuation!(context, current, children, "{");
43 inside_block = true;
44 },
45 Rule::triple_comment_block => if !inside_block {
46 parse_set_optional!(parse_doc_comment(current, context), children, comment)
47 } else {
48 context.insert_unattached_doc_comment(parse_span(¤t));
49 parse_append!(parse_doc_comment(current, context), children);
50 },
51 Rule::double_comment_block => parse_append!(parse_code_comment(current, context), children),
52 Rule::decorator => if inside_block {
53 unattached_field_decorators.push(parse_decorator(current, context));
54 } else {
55 parse_insert!(parse_decorator(current, context), children, decorators);
56 },
57 Rule::empty_decorator => if inside_block {
58 empty_field_decorator_spans.push(parse_span(¤t));
59 } else {
60 empty_decorator_spans.push(parse_span(¤t));
61 },
62 Rule::identifier => parse_set_identifier_and_string_path!(context, current, children, identifier, string_path),
63 Rule::field_declaration => parse_insert!(parse_field(current, context), children, fields),
64 Rule::partial_field => parse_insert!(parse_partial_field(current, context), children, partial_fields),
65 Rule::handler_declaration => parse_insert!(parse_handler_declaration(current, context, true), children, handlers),
66 Rule::availability_start => parse_append!(parse_availability_flag(current, context), children),
67 Rule::availability_end => parse_append!(parse_availability_end(current, context), children),
68 Rule::include_handler_from_template => parse_insert!(parse_include_handler_from_template(current, context), children, handler_inclusions),
69 _ => context.insert_unparsed(parse_span(¤t)),
70 }
71 }
72 parse_container_node_variables_cleanup!(context, named);
73 Model {
74 span,
75 path,
76 string_path,
77 children,
78 define_availability,
79 actual_availability,
80 comment,
81 identifier,
82 fields,
83 partial_fields,
84 decorators,
85 empty_decorator_spans,
86 empty_field_decorator_spans,
87 unattached_field_decorators,
88 handlers,
89 handler_inclusions,
90 resolved: RefCell::new(None),
91 }
92}