aboutsummaryrefslogtreecommitdiff
path: root/quote/src/ident_fragment.rs
diff options
context:
space:
mode:
Diffstat (limited to 'quote/src/ident_fragment.rs')
-rw-r--r--quote/src/ident_fragment.rs72
1 files changed, 72 insertions, 0 deletions
diff --git a/quote/src/ident_fragment.rs b/quote/src/ident_fragment.rs
new file mode 100644
index 0000000..09ead65
--- /dev/null
+++ b/quote/src/ident_fragment.rs
@@ -0,0 +1,72 @@
+use proc_macro2::{Ident, Span};
+use std::fmt;
+
+/// Specialized formatting trait used by `format_ident!`.
+///
+/// [`Ident`] arguments formatted using this trait will have their `r#` prefix
+/// stripped, if present.
+///
+/// See [`format_ident!`] for more information.
+pub trait IdentFragment {
+ /// Format this value as an identifier fragment.
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
+
+ /// Span associated with this `IdentFragment`.
+ ///
+ /// If non-`None`, may be inherited by formatted identifiers.
+ fn span(&self) -> Option<Span> {
+ None
+ }
+}
+
+impl<'a, T: IdentFragment + ?Sized> IdentFragment for &'a T {
+ fn span(&self) -> Option<Span> {
+ <T as IdentFragment>::span(*self)
+ }
+
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ IdentFragment::fmt(*self, f)
+ }
+}
+
+impl<'a, T: IdentFragment + ?Sized> IdentFragment for &'a mut T {
+ fn span(&self) -> Option<Span> {
+ <T as IdentFragment>::span(*self)
+ }
+
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ IdentFragment::fmt(*self, f)
+ }
+}
+
+impl IdentFragment for Ident {
+ fn span(&self) -> Option<Span> {
+ Some(self.span())
+ }
+
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let id = self.to_string();
+ if id.starts_with("r#") {
+ fmt::Display::fmt(&id[2..], f)
+ } else {
+ fmt::Display::fmt(&id[..], f)
+ }
+ }
+}
+
+// Limited set of types which this is implemented for, as we want to avoid types
+// which will often include non-identifier characters in their `Display` impl.
+macro_rules! ident_fragment_display {
+ ($($T:ty),*) => {
+ $(
+ impl IdentFragment for $T {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(self, f)
+ }
+ }
+ )*
+ }
+}
+
+ident_fragment_display!(bool, str, String);
+ident_fragment_display!(u8, u16, u32, u64, u128, usize);