1use miette::{Diagnostic, NamedSource, SourceSpan};
2use proc_macro2::LineColumn;
3use thiserror::Error;
4
5pub fn get_span(src: &str, start: &LineColumn, end: &LineColumn) -> SourceSpan {
6 let mut remaining_lines = end.line - 1;
7 let mut bytepos_start: usize = 0;
8 let mut bytepos_end: usize = 0;
9 for (i, c) in src.chars().enumerate() {
10 if c == '\n' {
11 if end.line - remaining_lines == start.line {
12 bytepos_end = i + start.column;
13 break;
14 } else {
15 bytepos_start = i + 1;
16 }
17 remaining_lines -= 1;
18 }
19 }
20
21 return (bytepos_start, bytepos_end - bytepos_start).into();
22}
23
24#[macro_export]
25macro_rules! span {
26 ($item: expr, $source: ident) => {{
27 $crate::error::get_span($source, &$item.span().start(), &$item.span().end())
28 }};
29}
30
31#[derive(Error, Debug, Diagnostic)]
32#[non_exhaustive]
33pub enum ErrorKind {
34 #[error("Couldn't parse this token")]
46 #[diagnostic(code(FILE_PARSE_ERROR), url(docsrs))]
47 FileParseError {
48 #[source_code]
49 src: NamedSource,
50 #[label("this token")]
51 span: SourceSpan,
52 #[help]
53 note: Option<String>,
54 },
55
56 #[error(transparent)]
57 #[diagnostic(code(IO_ERROR))]
58 IoError(#[from] std::io::Error),
59
60 #[error("Unexpected token")]
67 #[diagnostic(
68 code(UNEXPECTED_TOKEN),
69 url(docsrs),
70 help("Try removing the the unexpected token in `{filename:?}`")
71 )]
72 UnexpectedToken {
73 filename: String,
74 },
76
77 #[error("This lint doesn't exist")]
78 #[diagnostic(code(UNEXPECTED_LINT), url(docsrs))]
79 UnknownLint {
80 #[source_code]
81 src: NamedSource,
82 #[label("this lint")]
83 span: SourceSpan,
84 #[help]
85 note: Option<String>,
86 },
87
88 #[error("The {item_kind} `{item_name}` isn't tested")]
90 #[diagnostic(code(ITEM_NOT_TESTED), url(docsrs))]
91 ItemNotTested {
92 #[source_code]
93 src: NamedSource,
94 item_name: String,
95 item_kind: String,
96 #[label("this {item_kind}")]
97 span: SourceSpan,
98 },
99}