syn_error_experiment/
error.rs1use std;
2use std::fmt::{self, Display};
3use std::iter::FromIterator;
4
5use proc_macro2::{
6 Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
7};
8
9use syn::buffer::Cursor;
10
11pub type Result<T> = std::result::Result<T, Error>;
13
14#[derive(Debug)]
16pub struct Error {
17 span: Span,
18 message: String,
19}
20
21impl Error {
22 pub fn new<T: Display>(span: Span, message: T) -> Self {
23 Error {
24 span: span,
25 message: message.to_string(),
26 }
27 }
28
29 pub fn into_compile_error(self) -> TokenStream {
37 TokenStream::from_iter(vec![
39 TokenTree::Ident(Ident::new("compile_error", self.span)),
40 TokenTree::Punct({
41 let mut punct = Punct::new('!', Spacing::Alone);
42 punct.set_span(self.span);
43 punct
44 }),
45 TokenTree::Group({
46 let mut group = Group::new(Delimiter::Brace, {
47 TokenStream::from_iter(vec![TokenTree::Literal({
48 let mut string = Literal::string(&self.message);
49 string.set_span(self.span);
50 string
51 })])
52 });
53 group.set_span(self.span);
54 group
55 }),
56 ])
57 }
58}
59
60#[doc(hidden)]
62pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
63 if cursor.eof() {
64 Error::new(scope, format!("unexpected end of input, {}", message))
65 } else {
66 Error::new(cursor.span(), message)
67 }
68}
69
70impl Display for Error {
71 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
72 formatter.write_str(&self.message)
73 }
74}
75
76impl std::error::Error for Error {
77 fn description(&self) -> &str {
78 "parse error"
79 }
80}
81
82impl From<LexError> for Error {
83 fn from(err: LexError) -> Self {
84 Error::new(Span::call_site(), format!("{:?}", err))
85 }
86}