1use crate::{ast::AstToken, kinds::SyntaxKind::*};
2use rowan::{ast::AstNode as OtherAstNode, NodeOrToken};
3
4use crate::ast;
5
6use super::{InterpolPart, PathContent};
7
8impl ast::nodes::Path {
9 pub fn parts(&self) -> impl Iterator<Item = InterpolPart<PathContent>> {
10 self.syntax().children_with_tokens().map(|child| match child {
11 NodeOrToken::Token(token) => {
12 assert_eq!(token.kind(), TOKEN_PATH);
13 InterpolPart::Literal(PathContent::cast(token).unwrap())
14 }
15 NodeOrToken::Node(node) => {
16 InterpolPart::Interpolation(ast::Interpol::cast(node.clone()).unwrap())
17 }
18 })
19 }
20}
21
22#[cfg(test)]
23mod tests {
24 use rowan::ast::AstNode;
25
26 use crate::{
27 ast::{self, AstToken, InterpolPart, PathContent},
28 Root,
29 };
30
31 #[test]
32 fn parts() {
33 fn assert_eq_ast_ctn(it: &mut dyn Iterator<Item = InterpolPart<PathContent>>, x: &str) {
34 let tmp = it.next().expect("unexpected EOF");
35 if let InterpolPart::Interpolation(astn) = tmp {
36 assert_eq!(astn.expr().unwrap().syntax().to_string(), x);
37 } else {
38 unreachable!("unexpected literal {:?}", tmp);
39 }
40 }
41
42 fn assert_eq_lit(it: &mut dyn Iterator<Item = InterpolPart<PathContent>>, x: &str) {
43 let tmp = it.next().expect("unexpected EOF");
44 if let InterpolPart::Literal(astn) = tmp {
45 assert_eq!(astn.syntax().text(), x);
46 } else {
47 unreachable!("unexpected interpol {:?}", tmp);
48 }
49 }
50
51 let inp = r#"./a/b/${"c"}/${d}/e/f"#;
52 let expr = Root::parse(inp).ok().unwrap().expr().unwrap();
53 match expr {
54 ast::Expr::Path(p) => {
55 let mut it = p.parts();
56 assert_eq_lit(&mut it, "./a/b/");
57 assert_eq_ast_ctn(&mut it, "\"c\"");
58 assert_eq_lit(&mut it, "/");
59 assert_eq_ast_ctn(&mut it, "d");
60 assert_eq_lit(&mut it, "/e/f");
61 }
62 _ => unreachable!(),
63 }
64 }
65}