huff_neo_utils/ast/
span.rs1use crate::prelude::Span;
2use itertools::Itertools;
3use std::collections::BTreeMap;
4use std::ops::Index;
5
6#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
8pub struct AstSpan(pub Vec<Span>);
9
10impl AstSpan {
11 pub fn error(&self, hint: Option<&String>) -> String {
13 let file_to_source_map = self.0.iter().fold(BTreeMap::<String, Vec<&Span>>::new(), |mut m, s| {
14 let file_name = s.file.as_ref().map(|f2| f2.path.clone()).unwrap_or_default();
15 let mut new_vec: Vec<&Span> = m.get(&file_name).cloned().unwrap_or_default();
16 new_vec.push(s);
17 m.insert(file_name, new_vec);
18 m
19 });
20 let source_str = file_to_source_map.iter().filter(|fs| !fs.0.is_empty()).fold("".to_string(), |s, fs| {
21 let start = fs.1.iter().map(|fs2| fs2.start).min().unwrap_or(0);
22 let end = fs.1.iter().map(|fs2| fs2.end).max().unwrap_or(0);
23 let newline_s = if s.is_empty() { "".to_string() } else { format!("{s}\n") };
24 if start.eq(&0) && end.eq(&0) {
25 format!("{newline_s}-> {}\n > 0|", fs.0)
26 } else {
27 format!(
28 "{}-> {}:{}",
29 newline_s,
30 fs.0,
31 fs.1.iter()
32 .map(|sp| sp.source_seg())
33 .filter(|ss| !ss.is_empty())
34 .collect::<Vec<String>>()
35 .into_iter()
36 .unique()
37 .fold("".to_string(), |acc, ss| { format!("{acc}{ss}") })
38 )
39 }
40 });
41
42 format!("{}{source_str}", hint.map(|msg| format!("{msg}\n")).unwrap_or_default())
44 }
45
46 pub fn file(&self) -> String {
48 self.0.iter().fold("".to_string(), |acc, span| match &span.file {
49 Some(fs) => format!("-> {}\n{acc}", fs.path),
50 None => Default::default(),
51 })
52 }
53
54 pub fn inner_ref(&self) -> &Vec<Span> {
56 &self.0
57 }
58
59 pub fn boxed(self) -> Box<Self> {
61 Box::new(self)
62 }
63
64 pub fn clone_box(&self) -> Box<Self> {
66 Box::new(self.clone())
67 }
68}
69
70impl Index<usize> for AstSpan {
72 type Output = Span;
73 fn index(&self, index: usize) -> &Self::Output {
74 &self.0[index]
75 }
76}