1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use syn::parse::ParseStream;

use crate::util;
use crate::widgets::{
    parse_util, Attr, Attrs, Properties, Property, PropertyName, PropertyType, TopLevelWidget,
    Widget, WidgetAttr, WidgetFunc, WidgetTemplateAttr,
};

impl TopLevelWidget {
    pub(super) fn parse(input: ParseStream<'_>) -> Self {
        let attributes: Option<Attrs> = input.parse().ok();

        // Look for #[root] attribute and remove it from the list if it exists
        let (attributes, root_attr) = if let Some(prev_attributes) = attributes {
            let mut attributes = Attrs {
                inner: Vec::with_capacity(prev_attributes.inner.len()),
            };
            let mut root_attr = None;
            for attr in prev_attributes.inner {
                match attr {
                    Attr::Root(ident) => {
                        // Save root attribute and don't push it to the new list
                        root_attr = Some(ident);
                    }
                    _ => attributes.inner.push(attr),
                }
            }
            (Some(attributes), root_attr)
        } else {
            (None, None)
        };

        let inner = match Widget::parse(input, attributes, None) {
            Ok(inner) => inner,
            Err(err) => Widget {
                doc_attr: None,
                attr: WidgetAttr::None,
                template_attr: WidgetTemplateAttr::None,
                mutable: None,
                name: parse_util::string_to_snake_case("incorrect_top_level_widget"),
                name_assigned_by_user: false,
                func: WidgetFunc {
                    path: util::strings_to_path(&["gtk", "Box"]),
                    args: None,
                    method_chain: None,
                    ty: None,
                },
                args: None,
                properties: Properties {
                    properties: vec![Property {
                        name: PropertyName::Ident(parse_util::string_to_snake_case(
                            "invalid_property",
                        )),
                        ty: PropertyType::ParseError(err),
                    }],
                },
                assign_wrapper: None,
                ref_token: None,
                deref_token: None,
                returned_widget: None,
            },
        };

        Self { root_attr, inner }
    }
}