compose_syntax/ast/
module.rs

1use crate::ast::macros::node;
2use crate::ast::{AstNode, Expr, Ident, Str};
3use crate::{SyntaxKind, SyntaxNode, ast, Span};
4use ecow::EcoString;
5
6node! {
7    struct ModuleImport
8}
9
10impl<'a> ModuleImport<'a> {
11    pub fn source(self) -> EcoString {
12        self.0.cast_first::<Str>().get()
13    }
14
15    pub fn source_span(self) -> Span {
16        self.0.cast_first::<Str>().span()
17    }
18
19    pub fn alias(self) -> Option<ast::Ident<'a>> {
20        let mut children = self
21            .0
22            .children()
23            .take_while(|n| n.kind() != SyntaxKind::Colon);
24        while let Some(child) = children.next() {
25            if child.kind() == SyntaxKind::As {
26                return children.next().and_then(SyntaxNode::cast);
27            }
28        }
29
30        None
31    }
32
33    pub fn items(self) -> impl DoubleEndedIterator<Item = ImportItem<'a>> {
34        self.0.children().filter_map(SyntaxNode::cast)
35    }
36}
37
38node! {
39    struct ImportItem
40}
41
42impl<'a> ImportItem<'a> {
43    pub fn path(self) -> Expr<'a> {
44        self.0.cast_first()
45    }
46
47    pub fn alias(self) -> Option<Ident<'a>> {
48        self.0
49            .children()
50            .skip_while(|n| n.kind() != SyntaxKind::As)
51            .find_map(SyntaxNode::cast)
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use crate::assert_ast;
58    use super::*;
59
60    #[test]
61    fn simple_module_import() {
62        assert_ast! {
63            "import \"foo\";",
64            module as ModuleImport {
65                assert_eq!(module.source(), "foo");
66                assert_eq!(module.alias(), None);
67                assert_eq!(module.items().count(), 0);
68            }
69        }
70    }
71
72    #[test]
73    fn module_with_alias() {
74        assert_ast! {
75            "import \"foo\" as bar;",
76            module as ModuleImport {
77                assert_eq!(module.source(), "foo");
78                assert_eq!(module.items().count(), 0);
79                with alias: Ident = module.alias().unwrap() => {
80                    assert_eq!(alias.get(), "bar");
81                }
82            }
83        }
84    }
85
86    #[test]
87    fn module_with_items() {
88        assert_ast! {
89            "import \"foo\" as bar { baz, quz as quux };",
90            module as ModuleImport {
91                assert_eq!(module.source(), "foo");
92                module.items() => [
93                    item as ImportItem {
94                        with path: Ident = item.path() => {
95                            assert_eq!(path.get(), "baz");
96                        }
97                        assert_eq!(item.alias(), None);
98                    }
99                    item as ImportItem {
100                        with path: Ident = item.path() => {
101                            assert_eq!(path.get(), "quz");
102                        }
103                        assert_eq!(item.alias().unwrap().get(), "quux");
104                    }
105                ]
106            }
107        }
108    }
109}