1use proc_macro2::{Span, TokenStream};
2use quote::TokenStreamExt;
3use std::{
4 borrow::Borrow,
5 cell::RefCell,
6 fmt::Display,
7 hash::Hash,
8 ops::{Deref, DerefMut},
9};
10use syn::parse::{ParseBuffer, ParseStream};
11
12use crate::{parse_helpers::inputs_span, parse_meta::*};
13
14pub type Error = syn::Error;
16pub type Result<T> = syn::Result<T>;
18
19#[derive(Clone, Debug, Default)]
21#[repr(transparent)]
22pub struct Errors {
23 errors: RefCell<Option<Error>>,
25}
26
27impl Errors {
28 #[inline]
29 pub const fn new() -> Self {
31 Self {
32 errors: RefCell::new(None),
33 }
34 }
35 #[inline]
37 pub fn is_empty(&self) -> bool {
38 self.errors.borrow().is_none()
39 }
40 #[inline]
42 pub fn clear(&self) {
43 self.errors.take();
44 }
45 #[inline]
47 pub fn push<T: Display>(&self, span: Span, message: T) {
48 self.push_syn(Error::new(span, message));
49 }
50 #[inline]
53 pub fn push_call_site<T: Display>(&self, message: T) {
54 self.push(Span::call_site(), message);
55 }
56 #[inline]
59 pub fn push_spanned<T, U>(&self, tokens: T, message: U)
60 where
61 T: quote::ToTokens,
62 U: Display,
63 {
64 self.push_syn(Error::new_spanned(tokens, message));
65 }
66 #[inline]
68 pub fn push_syn(&self, error: Error) {
69 let mut storage = self.errors.borrow_mut();
70 if let Some(storage) = storage.as_mut() {
71 storage.combine(error);
72 } else {
73 storage.replace(error);
74 }
75 }
76 #[inline]
81 pub fn push_result<T>(&self, result: Result<T>) -> Option<T> {
82 match result {
83 Ok(t) => Some(t),
84 Err(e) => {
85 self.push_syn(e);
86 None
87 }
88 }
89 }
90 #[inline]
92 pub fn extend<T: IntoIterator<Item = Error>>(&self, iter: T) {
93 let mut errors = self.errors.borrow_mut();
94 if let Some(errors) = errors.as_mut() {
95 errors.extend(iter);
96 } else {
97 let mut iter = iter.into_iter();
98 if let Some(next) = iter.next() {
99 let errors = errors.insert(next);
100 errors.extend(iter);
101 }
102 }
103 }
104 #[inline]
109 pub fn into_result<T>(self, value: T) -> Result<T> {
110 if let Some(err) = self.errors.take() {
111 Err(err)
112 } else {
113 Ok(value)
114 }
115 }
116 #[inline]
121 pub fn check(self) -> Result<()> {
122 self.into_result(())
123 }
124 #[inline]
130 pub fn unwrap_err(self) -> Error {
131 if let Some(err) = self.errors.take() {
132 err
133 } else {
134 panic!("expected Errors to not be empty");
135 }
136 }
137 #[inline]
143 pub fn bail<T>(self) -> Result<T> {
144 Err(self.unwrap_err())
145 }
146 #[inline]
152 pub fn into_compile_error(self) -> Option<TokenStream> {
153 self.errors.take().map(|e| e.into_compile_error())
154 }
155 #[inline]
160 pub fn into_compile_errors(self) -> impl IntoIterator<Item = TokenStream> {
161 self.errors
162 .take()
163 .into_iter()
164 .map(|e| e.into_compile_error())
165 }
166 pub fn output_with<Q: quote::ToTokens>(self, item: Q) -> TokenStream {
168 let mut tokens = item.into_token_stream();
169 quote::ToTokens::to_tokens(&self, &mut tokens);
170 tokens
171 }
172}
173
174impl quote::ToTokens for Errors {
175 #[inline]
176 fn to_tokens(&self, tokens: &mut TokenStream) {
177 tokens.extend(self.to_token_stream());
178 }
179 fn to_token_stream(&self) -> TokenStream {
180 self.errors
181 .borrow()
182 .as_ref()
183 .map(|e| e.to_compile_error())
184 .unwrap_or_default()
185 }
186 #[inline]
187 fn into_token_stream(self) -> TokenStream
188 where
189 Self: Sized,
190 {
191 self.into_compile_error().unwrap_or_default()
192 }
193}
194
195impl From<Error> for Errors {
196 #[inline]
197 fn from(err: Error) -> Self {
198 Self {
199 errors: RefCell::new(Some(err)),
200 }
201 }
202}
203
204impl FromIterator<Error> for Errors {
205 #[inline]
206 fn from_iter<T: IntoIterator<Item = Error>>(iter: T) -> Self {
207 let mut iter = iter.into_iter();
208 let errors = iter.next().map(|mut first| {
209 first.extend(iter);
210 first
211 });
212 Self {
213 errors: RefCell::new(errors),
214 }
215 }
216}
217
218impl IntoIterator for Errors {
219 type Item = Error;
220 type IntoIter = ErrorsIntoIter;
221 #[inline]
222 fn into_iter(self) -> Self::IntoIter {
223 ErrorsIntoIter {
224 errors: self.errors.take().map(|e| e.into_iter()),
225 }
226 }
227}
228
229pub struct ErrorsIntoIter {
231 errors: Option<<Error as IntoIterator>::IntoIter>,
232}
233
234impl Iterator for ErrorsIntoIter {
235 type Item = Error;
236 fn next(&mut self) -> Option<Self::Item> {
237 self.errors.as_mut().and_then(|e| e.next())
238 }
239}
240
241#[derive(Copy, Clone, Debug)]
246pub struct SpannedValue<T> {
247 value: T,
248 span: Span,
249}
250
251impl<T> SpannedValue<T> {
252 #[inline]
255 pub fn new(value: T) -> Self {
256 Self::with_span(value, Span::call_site())
257 }
258 #[inline]
260 pub fn with_span(value: T, span: Span) -> Self {
261 Self { value, span }
262 }
263 #[inline]
265 pub fn into_inner(value: SpannedValue<T>) -> T {
266 value.value
267 }
268}
269
270impl<T: Default> Default for SpannedValue<T> {
271 #[inline]
272 fn default() -> Self {
273 Self::new(T::default())
274 }
275}
276
277impl<T: Display> Display for SpannedValue<T> {
278 #[inline]
279 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
280 self.value.fmt(f)
281 }
282}
283
284impl<T: PartialEq> PartialEq for SpannedValue<T> {
285 #[inline]
286 fn eq(&self, other: &Self) -> bool {
287 self.value == other.value
288 }
289}
290
291impl<T: Eq> Eq for SpannedValue<T> {}
292
293impl<T: PartialOrd> PartialOrd for SpannedValue<T> {
294 #[inline]
295 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
296 self.value.partial_cmp(&other.value)
297 }
298}
299
300impl<T: Ord> Ord for SpannedValue<T> {
301 #[inline]
302 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
303 self.value.cmp(&other.value)
304 }
305}
306
307impl<T: Hash> Hash for SpannedValue<T> {
308 #[inline]
309 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
310 self.value.hash(state);
311 }
312}
313
314impl<T> quote::ToTokens for SpannedValue<T> {
315 #[inline]
316 fn to_tokens(&self, tokens: &mut TokenStream) {
317 let mut group = proc_macro2::Group::new(proc_macro2::Delimiter::None, Default::default());
318 group.set_span(self.span);
319 tokens.append(group);
320 }
321}
322
323impl<T: ParseMetaItem> ParseMetaItem for SpannedValue<T> {
324 #[inline]
325 fn parse_meta_item(input: ParseStream, mode: crate::ParseMode) -> Result<Self> {
326 let span = input.span();
327 let value = T::parse_meta_item(input, mode)?;
328 let span = input.span().join(span).unwrap_or(span);
329 Ok(Self { value, span })
330 }
331 #[inline]
332 fn parse_meta_item_inline<'s, S: Borrow<ParseBuffer<'s>>>(
333 inputs: &[S],
334 mode: ParseMode,
335 ) -> Result<Self> {
336 let span = inputs.first().map(|p| p.borrow().span());
337 let value = T::parse_meta_item_inline(inputs, mode)?;
338 let span = span
339 .and_then(|s| inputs.last().and_then(|p| p.borrow().span().join(s)))
340 .unwrap_or_else(Span::call_site);
341 Ok(Self { value, span })
342 }
343 #[inline]
344 fn parse_meta_item_flag(span: Span) -> Result<Self> {
345 Ok(Self {
346 value: T::parse_meta_item_flag(span)?,
347 span,
348 })
349 }
350 #[inline]
351 fn parse_meta_item_named(input: ParseStream, name: &str, span: Span) -> Result<Self> {
352 let value = T::parse_meta_item_named(input, name, span)?;
353 let span = input.span().join(span).unwrap_or(span);
354 Ok(Self { value, span })
355 }
356}
357
358impl<T: ParseMetaFlatUnnamed> ParseMetaFlatUnnamed for SpannedValue<T> {
359 #[inline]
360 fn field_count() -> Option<usize> {
361 T::field_count()
362 }
363 fn parse_meta_flat_unnamed<'s, S: Borrow<ParseBuffer<'s>>>(
364 inputs: &[S],
365 mode: ParseMode,
366 index: usize,
367 ) -> Result<Self> {
368 let mut span = crate::parse_helpers::inputs_span(inputs);
369 let value = T::parse_meta_flat_unnamed(inputs, mode, index)?;
370 if let Some(closed) = span.join(inputs_span(inputs)) {
371 span = closed;
372 }
373 Ok(Self { value, span })
374 }
375}
376
377impl<T: ParseMetaFlatNamed> ParseMetaFlatNamed for SpannedValue<T> {
378 const ACCEPTS_ALL: bool = T::ACCEPTS_ALL;
379 #[inline]
380 fn field_names() -> &'static [&'static str] {
381 T::field_names()
382 }
383 fn parse_meta_flat_named<'s, S: Borrow<ParseBuffer<'s>>>(
384 inputs: &[S],
385 mode: ParseMode,
386 prefix: &str,
387 validate: bool,
388 ) -> Result<Self> {
389 let mut span = crate::parse_helpers::inputs_span(inputs);
390 let value = T::parse_meta_flat_named(inputs, mode, prefix, validate)?;
391 if let Some(closed) = span.join(inputs_span(inputs)) {
392 span = closed;
393 }
394 Ok(Self { value, span })
395 }
396}
397
398impl<T: ParseMetaAppend> ParseMetaAppend for SpannedValue<T> {
399 fn parse_meta_append<'s, S, I, P>(inputs: &[S], paths: I) -> Result<Self>
400 where
401 S: Borrow<ParseBuffer<'s>>,
402 I: IntoIterator<Item = P>,
403 I::IntoIter: Clone,
404 P: AsRef<str>,
405 {
406 let mut span = inputs_span(inputs);
407 let value = T::parse_meta_append(inputs, paths)?;
408 if let Some(closed) = span.join(inputs_span(inputs)) {
409 span = closed;
410 }
411 Ok(Self { value, span })
412 }
413}
414
415impl<T: ParseMetaRest> ParseMetaRest for SpannedValue<T> {
416 fn parse_meta_rest<'s, S: Borrow<ParseBuffer<'s>>>(
417 inputs: &[S],
418 exclude: &[&str],
419 ) -> Result<Self> {
420 let mut span = inputs_span(inputs);
421 let value = T::parse_meta_rest(inputs, exclude)?;
422 if let Some(closed) = span.join(inputs_span(inputs)) {
423 span = closed;
424 }
425 Ok(Self { value, span })
426 }
427}
428
429impl<T> From<T> for SpannedValue<T> {
430 #[inline]
431 fn from(value: T) -> Self {
432 Self {
433 value,
434 span: Span::call_site(),
435 }
436 }
437}
438
439impl<T> Deref for SpannedValue<T> {
440 type Target = T;
441 #[inline]
442 fn deref(&self) -> &Self::Target {
443 &self.value
444 }
445}
446
447impl<T> DerefMut for SpannedValue<T> {
448 #[inline]
449 fn deref_mut(&mut self) -> &mut Self::Target {
450 &mut self.value
451 }
452}
453
454#[derive(Copy, Clone, Debug, Default)]
464pub struct Flag(Option<Span>);
465
466impl Flag {
467 #[inline]
469 pub fn set(span: Span) -> Self {
470 Self(Some(span))
471 }
472 #[inline]
474 pub fn set_call_site() -> Self {
475 Self(Some(Span::call_site()))
476 }
477 #[inline]
479 pub fn unset() -> Self {
480 Self(None)
481 }
482 #[inline]
484 pub fn is_set(&self) -> bool {
485 self.0.is_some()
486 }
487}
488
489impl From<bool> for Flag {
490 #[inline]
491 fn from(value: bool) -> Self {
492 Self(value.then(Span::call_site))
493 }
494}
495
496impl From<Flag> for bool {
497 #[inline]
498 fn from(value: Flag) -> Self {
499 value.is_set()
500 }
501}
502
503impl Eq for Flag {}
504
505impl PartialEq for Flag {
506 #[inline]
507 fn eq(&self, other: &Self) -> bool {
508 self.is_set() == other.is_set()
509 }
510}
511
512impl PartialEq<bool> for Flag {
513 #[inline]
514 fn eq(&self, other: &bool) -> bool {
515 self.is_set() == *other
516 }
517}
518
519impl PartialEq<Flag> for bool {
520 #[inline]
521 fn eq(&self, other: &Flag) -> bool {
522 *self == other.is_set()
523 }
524}
525
526impl quote::ToTokens for Flag {
527 #[inline]
528 fn to_tokens(&self, tokens: &mut TokenStream) {
529 tokens.append(proc_macro2::Ident::new(
530 self.0.map(|_| "true").unwrap_or("false"),
531 self.0.unwrap_or_else(Span::call_site),
532 ));
533 }
534}
535
536impl ParseMetaItem for Flag {
537 #[inline]
538 fn parse_meta_item(input: ParseStream, mode: ParseMode) -> Result<Self> {
539 Self::parse_meta_item_inline(&[input], mode)
540 }
541 #[inline]
542 fn parse_meta_item_inline<'s, S: Borrow<ParseBuffer<'s>>>(
543 inputs: &[S],
544 _mode: ParseMode,
545 ) -> Result<Self> {
546 Err(Error::new(
547 crate::parse_helpers::inputs_span(inputs),
548 "field with type `Flag` can only be a named field with no value",
549 ))
550 }
551 #[inline]
552 fn parse_meta_item_flag(span: Span) -> Result<Self> {
553 Ok(Self(Some(span)))
554 }
555 #[inline]
556 fn parse_meta_item_named(input: ParseStream, _name: &str, span: Span) -> Result<Self> {
557 if input.is_empty() || input.peek(syn::Token![,]) {
558 Self::parse_meta_item_flag(span)
559 } else {
560 Err(Error::new(input.span(), "unexpected token"))
561 }
562 }
563 #[inline]
564 fn missing_meta_item(_name: &str, _span: Span) -> Result<Self> {
565 Ok(Self::unset())
566 }
567}