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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use crate::structure::atoms::KconfigSymbol;
use crate::structure::kconfig_node::KconfigNode;

#[derive(Debug, Clone)]
pub struct KconfigNodeChildren {
    pub children: Vec<KconfigNode>,
}

impl KconfigNodeChildren {
    pub(crate) fn new_empty() -> Self {
        Self {
            children: Vec::new(),
        }
    }

    pub(crate) fn add_children(&mut self, node: KconfigNode) {
        self.children.push(node);
    }

    pub(crate) fn add_all_children(&mut self, children: KconfigNodeChildren) {
        for chd in children.children {
            self.children.push(chd);
        }
    }

    pub fn get_all_symbols(&self) -> Vec<KconfigSymbol> {
        self.children
            .iter()
            .flat_map(|node| match node {
                KconfigNode::Config(config) => {
                    vec![config.symbol.clone()]
                }
                KconfigNode::Menu(menu) => menu.children.get_all_symbols(),
                KconfigNode::MenuConfig(menu_config) => {
                    vec![menu_config.symbol.clone()]
                }
                KconfigNode::If(if_node) => if_node.children.get_all_symbols(),
            })
            .collect::<Vec<KconfigSymbol>>()
    }
}

#[cfg(test)]
mod test {
    use crate::parser::kconfig_parser_impl::parser_traits::{
        ParseableWithUnknownSpan, ParsingContext,
    };
    use crate::parser::utils::parse_span::ParseSpan;
    use crate::structure::atoms::{
        KconfigDependency, KconfigExpression, KconfigReverseDependency, KconfigSymbol,
    };
    use crate::structure::kconfig_config::KconfigConfig;
    use crate::structure::kconfig_node::KconfigNode::{Config, Menu};
    use crate::structure::kconfig_node_children::KconfigNodeChildren;
    use crate::structure::nodes::{KconfigConfigNode, KconfigMenuNode};
    use crate::structure::property::{
        ConfigType, KconfigDependenciesProperty, KconfigHelpProperty,
        KconfigReverseDependenciesProperty, KconfigTypeProperty,
    };

    #[test]
    fn happy_path_get_all_symbols() {
        let children = KconfigNodeChildren {
            children: vec![
                Config(KconfigConfigNode {
                    symbol: KconfigSymbol::new("MKAY_LOL".to_string()),
                    config: KconfigConfig {
                        type_property: Option::from(KconfigTypeProperty {
                            config_type: ConfigType::Bool,
                            if_dep_on_type: None,
                        }),
                        dependencies: KconfigDependenciesProperty {
                            dependencies: vec![KconfigDependency {
                                expression: KconfigExpression {
                                    source: "HOORAH && OH_YEAH".to_string(),
                                },
                            }],
                        },
                        reverse_dependencies: KconfigReverseDependenciesProperty {
                            dependencies: vec![KconfigReverseDependency {
                                on_symbol: KconfigSymbol::new("GOING_BACKWARDS".to_string()),
                                if_constraint: None,
                            }],
                        },
                        help_property: None,
                    },
                }),
                Config(KconfigConfigNode {
                    symbol: KconfigSymbol::new("HOORAH".to_string()),
                    config: KconfigConfig {
                        type_property: Option::from(KconfigTypeProperty {
                            config_type: ConfigType::Tristate,
                            if_dep_on_type: None,
                        }),
                        dependencies: KconfigDependenciesProperty {
                            dependencies: vec![],
                        },
                        reverse_dependencies: KconfigReverseDependenciesProperty {
                            dependencies: vec![],
                        },
                        help_property: None,
                    },
                }),
                Menu(KconfigMenuNode {
                    name: "Some menu".to_string(),
                    dependencies: KconfigDependenciesProperty {
                        dependencies: vec![],
                    },
                    children: KconfigNodeChildren {
                        children: vec![Config(KconfigConfigNode {
                            symbol: KconfigSymbol::new("BAR".to_string()),
                            config: KconfigConfig {
                                type_property: None,
                                dependencies: KconfigDependenciesProperty {
                                    dependencies: vec![],
                                },
                                reverse_dependencies: KconfigReverseDependenciesProperty {
                                    dependencies: vec![],
                                },
                                help_property: None,
                            },
                        })],
                    },
                }),
            ],
        };

        assert_eq!(
            children.get_all_symbols(),
            vec![
                KconfigSymbol::new("MKAY_LOL".to_string()),
                KconfigSymbol::new("HOORAH".to_string()),
                KconfigSymbol::new("BAR".to_string())
            ]
        );
        // assert_eq!(parse_res.0.help_text, "endmenu lol\nkeke sajt")
    }
}