cairo_lang_syntax/node/
with_db.rs1use cairo_lang_filesystem::span::TextWidth;
2use cairo_lang_primitive_token::{PrimitiveSpan, PrimitiveToken, ToPrimitiveTokenStream};
3
4use super::SyntaxNode;
5use super::db::SyntaxGroup;
6
7pub struct SyntaxNodeWithDb<'a, Db: SyntaxGroup> {
8 node: &'a SyntaxNode,
9 db: &'a Db,
10}
11
12impl<'a, Db: SyntaxGroup> SyntaxNodeWithDb<'a, Db> {
13 pub fn new(node: &'a SyntaxNode, db: &'a Db) -> Self {
14 Self { node, db }
15 }
16}
17
18impl<'a, Db: SyntaxGroup> ToPrimitiveTokenStream for SyntaxNodeWithDb<'a, Db> {
19 type Iter = SyntaxNodeWithDbIterator<'a, Db>;
20
21 fn to_primitive_token_stream(&self) -> Self::Iter {
22 SyntaxNodeWithDbIterator::new(
24 Box::new(
25 self.node.tokens(self.db).flat_map(|node| token_from_syntax_node(node, self.db)),
26 ),
27 self.db,
28 )
29 }
30}
31
32pub struct SyntaxNodeWithDbIterator<'a, Db: SyntaxGroup> {
33 inner: Box<dyn Iterator<Item = PrimitiveToken> + 'a>,
34 _db: &'a Db,
35}
36
37impl<'a, Db: SyntaxGroup> SyntaxNodeWithDbIterator<'a, Db> {
38 pub fn new(inner: Box<dyn Iterator<Item = PrimitiveToken> + 'a>, db: &'a Db) -> Self {
39 Self { inner, _db: db }
40 }
41}
42
43impl<Db: SyntaxGroup> Iterator for SyntaxNodeWithDbIterator<'_, Db> {
44 type Item = PrimitiveToken;
45
46 fn next(&mut self) -> Option<Self::Item> {
47 self.inner.next()
48 }
49}
50
51fn token_from_syntax_node(node: SyntaxNode, db: &dyn SyntaxGroup) -> Vec<PrimitiveToken> {
60 let span_without_trivia = node.span_without_trivia(db);
61 let span_with_trivia = node.span(db);
62 let text = node.get_text(db);
63 let mut result = Vec::new();
64 let prefix_len = span_without_trivia.start - span_with_trivia.start;
65 let (prefix, rest) = text.split_at(prefix_len.as_u32() as usize);
66 if prefix_len > TextWidth::ZERO {
67 result.push(PrimitiveToken {
68 content: prefix.to_string(),
69 span: Some(PrimitiveSpan {
70 start: span_with_trivia.start.as_u32() as usize,
71 end: span_without_trivia.start.as_u32() as usize,
72 }),
73 });
74 }
75 let suffix_len = span_with_trivia.end - span_without_trivia.end;
76 let (content, suffix) = rest.split_at(rest.len() - suffix_len.as_u32() as usize);
77 if !content.is_empty() {
78 result.push(PrimitiveToken {
79 content: content.to_string(),
80 span: Some(PrimitiveSpan {
81 start: span_without_trivia.start.as_u32() as usize,
82 end: span_without_trivia.end.as_u32() as usize,
83 }),
84 });
85 }
86 if suffix_len > TextWidth::ZERO {
87 result.push(PrimitiveToken {
88 content: suffix.to_string(),
89 span: Some(PrimitiveSpan {
90 start: span_without_trivia.end.as_u32() as usize,
91 end: span_with_trivia.end.as_u32() as usize,
92 }),
93 });
94 }
95 result
96}