compose_syntax/ast/
module.rs1use 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}