spanned.rs 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. use crate::ToTokens;
  3. use proc_macro2::extra::DelimSpan;
  4. use proc_macro2::{Span, TokenStream};
  5. // Not public API other than via the syn crate. Use syn::spanned::Spanned.
  6. pub trait Spanned: private::Sealed {
  7. fn __span(&self) -> Span;
  8. }
  9. impl Spanned for Span {
  10. fn __span(&self) -> Span {
  11. *self
  12. }
  13. }
  14. impl Spanned for DelimSpan {
  15. fn __span(&self) -> Span {
  16. self.join()
  17. }
  18. }
  19. impl<T: ?Sized + ToTokens> Spanned for T {
  20. fn __span(&self) -> Span {
  21. join_spans(self.into_token_stream())
  22. }
  23. }
  24. fn join_spans(tokens: TokenStream) -> Span {
  25. let mut iter = tokens.into_iter().map(|tt| tt.span());
  26. let first = match iter.next() {
  27. Some(span) => span,
  28. None => return Span::call_site(),
  29. };
  30. iter.fold(None, |_prev, next| Some(next))
  31. .and_then(|last| first.join(last))
  32. .unwrap_or(first)
  33. }
  34. mod private {
  35. use crate::ToTokens;
  36. use proc_macro2::extra::DelimSpan;
  37. use proc_macro2::Span;
  38. pub trait Sealed {}
  39. impl Sealed for Span {}
  40. impl Sealed for DelimSpan {}
  41. impl<T: ?Sized + ToTokens> Sealed for T {}
  42. }