syn_prelude/
to_syn_error.rs1use std::fmt::Display;
2
3use proc_macro2::Span;
4use syn::{punctuated::Punctuated, spanned::Spanned, Error, Ident, LitStr};
5
6use crate::ToSpan;
7
8pub trait ToErr {
9 fn to_err<T>(self) -> syn::Result<T>;
10}
11
12impl ToErr for syn::Error {
13 fn to_err<T>(self) -> syn::Result<T> {
14 Err(self)
15 }
16}
17
18pub trait ToSynError {
19 fn to_syn_error<S: Display>(&self, message: S) -> Error;
20}
21
22impl ToSynError for Span {
23 fn to_syn_error<S: Display>(&self, message: S) -> Error {
24 Error::new(self.span(), message)
25 }
26}
27
28impl ToSynError for Ident {
29 fn to_syn_error<S: Display>(&self, message: S) -> Error {
30 Error::new(self.span(), message)
31 }
32}
33
34impl ToSynError for LitStr {
35 fn to_syn_error<S: Display>(&self, message: S) -> Error {
36 Error::new(self.span(), message)
37 }
38}
39
40pub trait ToOptionalSynError {
41 fn to_optional_syn_error<S: Display>(&self, message: S) -> Option<Error>;
42}
43
44impl ToOptionalSynError for Vec<Span> {
45 fn to_optional_syn_error<S: Display>(&self, message: S) -> Option<Error> {
46 let mut span: Option<Span> = None;
47 for s in self {
48 if let Some(x) = &mut span {
49 span = x.join(*s)
50 } else {
51 span = Some(*s)
52 }
53 }
54 span.map(|s| s.to_syn_error(message))
55 }
56}
57
58impl<T: ToSpan + Clone> ToOptionalSynError for Vec<Option<T>> {
59 fn to_optional_syn_error<S: Display>(&self, message: S) -> Option<Error> {
60 self.iter()
61 .map(|s| s.as_ref().map(|s| s.to_span()))
62 .reduce(|a, b| match (a, b) {
63 (None, None) => None,
64 (None, Some(b)) => Some(b.to_span()),
65 (Some(a), None) => Some(a.to_span()),
66 (Some(a), Some(b)) => a.to_span().join(b.to_span()),
67 })
68 .flatten()
69 .map(|span| span.to_syn_error(message))
70 }
71}
72
73impl<T: ToSpan, P> ToOptionalSynError for Punctuated<T, P> {
74 fn to_optional_syn_error<S: Display>(&self, message: S) -> Option<Error> {
75 if let Some(first) = self.first() {
76 let span = first.to_span();
77 Some(if let Some(last) = self.last() {
78 Error::new(span.join(last.to_span()).unwrap_or(span), message)
79 } else {
80 Error::new(span, message)
81 })
82 } else {
83 None
84 }
85 }
86}
87
88pub trait CombineSynErrors {
89 fn combine_errors(self) -> Option<syn::Error>;
90}
91
92impl CombineSynErrors for Vec<syn::Error> {
93 fn combine_errors(self) -> Option<syn::Error> {
94 let mut i = self.into_iter();
95 if let Some(mut err) = i.next() {
96 while let Some(e) = i.next() {
97 err.combine(e);
98 }
99 Some(err)
100 } else {
101 None
102 }
103 }
104}
105
106pub trait JoinSynErrors {
107 fn join_errors(self) -> syn::Result<()>;
108}
109
110impl<T> JoinSynErrors for Vec<syn::Result<T>> {
111 fn join_errors(self) -> syn::Result<()> {
112 let mut final_err: Option<syn::Error> = None;
113 let mut i = self.into_iter();
114 while let Some(res) = i.next() {
115 if let Err(err) = res {
116 if let Some(final_err) = &mut final_err {
117 final_err.combine(err);
118 } else {
119 final_err = Some(err);
120 }
121 }
122 }
123 if let Some(err) = final_err {
124 Err(err)
125 } else {
126 Ok(())
127 }
128 }
129}
130
131impl<T1, T2> JoinSynErrors for (syn::Result<T1>, syn::Result<T2>) {
132 fn join_errors(self) -> syn::Result<()> {
133 match self {
134 (Ok(_), Ok(_)) => Ok(()),
135 (Ok(_), Err(err2)) => Err(err2),
136 (Err(err1), Ok(_)) => Err(err1),
137 (Err(mut err1), Err(err2)) => {
138 err1.combine(err2);
139 Err(err1)
140 }
141 }
142 }
143}
144
145impl<T1, T2, T3> JoinSynErrors for (syn::Result<T1>, syn::Result<T2>, syn::Result<T3>) {
146 fn join_errors(self) -> syn::Result<()> {
147 let mut err = self.0.err();
148 if let Err(err2) = self.1 {
149 if let Some(err) = &mut err {
150 err.combine(err2);
151 } else {
152 err = Some(err2);
153 }
154 }
155 if let Err(err3) = self.2 {
156 if let Some(err) = &mut err {
157 err.combine(err3);
158 } else {
159 err = Some(err3);
160 }
161 }
162 if let Some(err) = err {
163 Err(err)
164 } else {
165 Ok(())
166 }
167 }
168}