shape_ast/error/parse_error/
source_context.rs1use crate::error::SourceLocation;
4
5#[derive(Debug, Clone, Default)]
7pub struct SourceContext {
8 pub lines: Vec<SourceLine>,
10 pub error_line_index: usize,
12}
13
14impl SourceContext {
15 pub fn new(lines: Vec<SourceLine>, error_line_index: usize) -> Self {
16 Self {
17 lines,
18 error_line_index,
19 }
20 }
21
22 pub fn from_source(
24 source: &str,
25 location: &SourceLocation,
26 span_end: Option<(usize, usize)>,
27 ) -> Self {
28 let lines: Vec<&str> = source.lines().collect();
29 let error_line_idx = location.line.saturating_sub(1);
30
31 let start_idx = error_line_idx.saturating_sub(2);
33 let end_idx = (error_line_idx + 3).min(lines.len());
34
35 let context_lines: Vec<SourceLine> = (start_idx..end_idx)
36 .map(|i| {
37 let content = lines.get(i).unwrap_or(&"").to_string();
38 let highlights = if i == error_line_idx {
39 let end_col = span_end
40 .filter(|(el, _)| *el == location.line)
41 .map(|(_, ec)| ec)
42 .or(location.length.map(|l| location.column + l))
43 .unwrap_or(location.column + 1);
44
45 vec![Highlight {
46 start: location.column,
47 end: end_col,
48 style: HighlightStyle::Primary,
49 label: None,
50 }]
51 } else {
52 vec![]
53 };
54
55 SourceLine {
56 number: i + 1,
57 content,
58 highlights,
59 }
60 })
61 .collect();
62
63 Self {
64 lines: context_lines,
65 error_line_index: error_line_idx.saturating_sub(start_idx),
66 }
67 }
68}
69
70#[derive(Debug, Clone)]
72pub struct SourceLine {
73 pub number: usize,
75 pub content: String,
77 pub highlights: Vec<Highlight>,
79}
80
81#[derive(Debug, Clone)]
83pub struct Highlight {
84 pub start: usize,
86 pub end: usize,
88 pub style: HighlightStyle,
90 pub label: Option<String>,
92}
93
94impl Highlight {
95 pub fn primary(start: usize, end: usize) -> Self {
96 Self {
97 start,
98 end,
99 style: HighlightStyle::Primary,
100 label: None,
101 }
102 }
103
104 pub fn secondary(start: usize, end: usize) -> Self {
105 Self {
106 start,
107 end,
108 style: HighlightStyle::Secondary,
109 label: None,
110 }
111 }
112
113 pub fn with_label(mut self, label: impl Into<String>) -> Self {
114 self.label = Some(label.into());
115 self
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq)]
120pub enum HighlightStyle {
121 Primary, Secondary, Suggestion, }