databend_common_ast/
span.rs1use std::fmt::Debug;
16use std::fmt::Display;
17use std::fmt::Formatter;
18
19use derive_visitor::Drive;
20use derive_visitor::DriveMut;
21use serde::Deserialize;
22use serde::Serialize;
23
24pub type Span = Option<Range>;
25
26#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Drive, DriveMut)]
27pub struct Range {
28 pub start: u32,
29 pub end: u32,
30}
31
32impl Range {
33 pub fn start(&self) -> usize {
34 self.start as usize
35 }
36
37 pub fn end(&self) -> usize {
38 self.end as usize
39 }
40}
41
42impl Debug for Range {
43 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
44 write!(f, "{}..{}", self.start, self.end)
45 }
46}
47
48impl Display for Range {
49 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
50 write!(f, "{}..{}", self.start, self.end)
51 }
52}
53
54impl From<Range> for std::ops::Range<usize> {
55 fn from(range: Range) -> std::ops::Range<usize> {
56 (range.start as usize)..(range.end as usize)
57 }
58}
59
60impl From<std::ops::Range<usize>> for Range {
61 fn from(range: std::ops::Range<usize>) -> Range {
62 Range {
63 start: range.start as u32,
64 end: range.end as u32,
65 }
66 }
67}
68
69pub fn offset_span(span: Span, offset: usize) -> Span {
70 span.map(|range| Range {
71 start: range.start + offset as u32,
72 end: range.end + offset as u32,
73 })
74}
75
76pub fn merge_span(lhs: Span, rhs: Span) -> Span {
77 match (lhs, rhs) {
78 (Some(lhs), Some(rhs)) => Some(Range {
79 start: lhs.start.min(rhs.start),
80 end: lhs.end.max(rhs.end),
81 }),
82 (Some(lhs), None) => Some(lhs),
83 (None, Some(rhs)) => Some(rhs),
84 (None, None) => None,
85 }
86}
87
88pub fn pretty_print_error(source: &str, labels: Vec<(Range, String)>) -> String {
89 use rspack_codespan_reporting::diagnostic::Diagnostic;
90 use rspack_codespan_reporting::diagnostic::Label;
91 use rspack_codespan_reporting::files::SimpleFile;
92 use rspack_codespan_reporting::term;
93 use rspack_codespan_reporting::term::termcolor::Buffer;
94 use rspack_codespan_reporting::term::Chars;
95 use rspack_codespan_reporting::term::Config;
96
97 let mut writer = Buffer::no_color();
98 let file = SimpleFile::new("SQL", source);
99 let config = Config {
100 chars: Chars::ascii(),
101 before_label_lines: 3,
102 ..Default::default()
103 };
104
105 let labels = labels
106 .into_iter()
107 .enumerate()
108 .map(|(i, (span, msg))| {
109 if i == 0 {
110 Label::primary((), span).with_message(msg)
111 } else {
112 Label::secondary((), span).with_message(msg)
113 }
114 })
115 .collect();
116
117 let diagnostic = Diagnostic::error().with_labels(labels);
118
119 term::emit(&mut writer, &config, &file, &diagnostic).unwrap();
120
121 std::str::from_utf8(&writer.into_inner())
122 .unwrap()
123 .to_string()
124}