omena_parser/
layer_path.rs1use omena_syntax::{LayerPathV0, SyntaxKind, SyntaxNode};
4
5pub fn layer_paths_from_cst(source: &str, layer_rule: &SyntaxNode) -> Vec<LayerPathV0> {
6 if layer_rule.kind() != SyntaxKind::LayerRule
7 || layer_rule
8 .children()
9 .any(|node| node.kind() == SyntaxKind::BogusLayerName)
10 {
11 return Vec::new();
12 }
13
14 let mut paths = Vec::new();
15 let mut authored_segments = Vec::<String>::new();
16 let mut saw_layer_keyword = false;
17 let mut path_valid = true;
18 for token in layer_rule
19 .descendants_with_tokens()
20 .filter_map(|element| element.into_token())
21 {
22 let kind = token.kind();
23 if matches!(
24 kind,
25 SyntaxKind::LeftBrace | SyntaxKind::SassIndent | SyntaxKind::Semicolon
26 ) {
27 break;
28 }
29 if !saw_layer_keyword {
30 if kind == SyntaxKind::AtKeyword {
31 saw_layer_keyword = true;
32 }
33 continue;
34 }
35 match kind {
36 SyntaxKind::Ident | SyntaxKind::CustomPropertyName => {
37 if let Some(text) = source_text_for_token(source, token) {
38 authored_segments.push(text.to_string());
39 } else {
40 path_valid = false;
41 }
42 }
43 SyntaxKind::Dot
44 | SyntaxKind::Whitespace
45 | SyntaxKind::LineComment
46 | SyntaxKind::BlockComment => {}
47 SyntaxKind::Comma => {
48 if path_valid
49 && let Some(path) = LayerPathV0::from_authored_segments(
50 authored_segments.iter().map(String::as_str),
51 )
52 {
53 paths.push(path);
54 }
55 authored_segments.clear();
56 path_valid = true;
57 }
58 _ => path_valid = false,
59 }
60 }
61 if path_valid
62 && let Some(path) =
63 LayerPathV0::from_authored_segments(authored_segments.iter().map(String::as_str))
64 {
65 paths.push(path);
66 }
67 paths
68}
69
70fn source_text_for_token<'a>(
71 source: &'a str,
72 token: &omena_syntax::SyntaxToken,
73) -> Option<&'a str> {
74 let range = token.text_range();
75 source.get(u32::from(range.start()) as usize..u32::from(range.end()) as usize)
76}