Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ keywords = ["syn"]
include = ["Cargo.toml", "src/**/*.rs", "tests/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]

[dependencies]
proc-macro2 = "0.2"
proc-macro2 = "0.3"
68 changes: 34 additions & 34 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,10 @@ pub mod __rt {
pub fn parse(tokens: &mut ::Tokens, span: Span, s: &str) {
let s: TokenStream = s.parse().expect("invalid token stream");
tokens.append_all(s.into_iter().map(|mut t| {
t.span = span;
t.set_span(span);
t
}));
}

// Not public API.
pub fn append_kind(tokens: &mut ::Tokens, span: Span, kind: TokenNode) {
tokens.append(TokenTree {
span: span,
kind: kind,
})
}
}

/// The whole point.
Expand Down Expand Up @@ -158,9 +150,9 @@ pub mod __rt {
///
/// Any interpolated tokens preserve the `Span` information provided by their
/// `ToTokens` implementation. Tokens that originate within the `quote!`
/// invocation are spanned with [`Span::def_site()`].
/// invocation are spanned with [`Span::call_site()`].
///
/// [`Span::def_site()`]: https://docs.rs/proc-macro2/0.2/proc_macro2/struct.Span.html#method.def_site
/// [`Span::call_site()`]: https://docs.rs/proc-macro2/0.2/proc_macro2/struct.Span.html#method.call_site
///
/// A different span can be provided through the [`quote_spanned!`] macro.
///
Expand Down Expand Up @@ -206,7 +198,7 @@ pub mod __rt {
/// ```
#[macro_export]
macro_rules! quote {
($($tt:tt)*) => (quote_spanned!($crate::__rt::Span::def_site()=> $($tt)*));
($($tt:tt)*) => (quote_spanned!($crate::__rt::Span::call_site()=> $($tt)*));
}

/// Same as `quote!`, but applies a given span to all tokens originating within
Expand Down Expand Up @@ -286,9 +278,9 @@ macro_rules! quote {
/// #
/// # fn main() {
/// # let ty = Type;
/// # let def_site = Span::def_site();
/// # let call_site = Span::call_site();
/// #
/// let ty_span = ty.span().resolved_at(def_site);
/// let ty_span = ty.span();
/// let assert_sync = quote_spanned! {ty_span=>
/// struct _AssertSync where #ty: Sync;
/// };
Expand Down Expand Up @@ -455,12 +447,14 @@ macro_rules! quote_each_token {

($tokens:ident $span:ident # [ $($inner:tt)* ] $($rest:tt)*) => {
quote_each_token!($tokens $span #);
$crate::__rt::append_kind(&mut $tokens,
$span,
$crate::__rt::TokenNode::Group(
$tokens.append({
let mut g = $crate::__rt::Group::new(
$crate::__rt::Delimiter::Bracket,
quote_spanned!($span=> $($inner)*).into()
));
quote_spanned!($span=> $($inner)*).into(),
);
g.set_span($span);
g
});
quote_each_token!($tokens $span $($rest)*);
};

Expand All @@ -470,32 +464,38 @@ macro_rules! quote_each_token {
};

($tokens:ident $span:ident ( $($first:tt)* ) $($rest:tt)*) => {
$crate::__rt::append_kind(&mut $tokens,
$span,
$crate::__rt::TokenNode::Group(
$tokens.append({
let mut g = $crate::__rt::Group::new(
$crate::__rt::Delimiter::Parenthesis,
quote_spanned!($span=> $($first)*).into()
));
quote_spanned!($span=> $($first)*).into(),
);
g.set_span($span);
g
});
quote_each_token!($tokens $span $($rest)*);
};

($tokens:ident $span:ident [ $($first:tt)* ] $($rest:tt)*) => {
$crate::__rt::append_kind(&mut $tokens,
$span,
$crate::__rt::TokenNode::Group(
$tokens.append({
let mut g = $crate::__rt::Group::new(
$crate::__rt::Delimiter::Bracket,
quote_spanned!($span=> $($first)*).into()
));
quote_spanned!($span=> $($first)*).into(),
);
g.set_span($span);
g
});
quote_each_token!($tokens $span $($rest)*);
};

($tokens:ident $span:ident { $($first:tt)* } $($rest:tt)*) => {
$crate::__rt::append_kind(&mut $tokens,
$span,
$crate::__rt::TokenNode::Group(
$tokens.append({
let mut g = $crate::__rt::Group::new(
$crate::__rt::Delimiter::Brace,
quote_spanned!($span=> $($first)*).into()
));
quote_spanned!($span=> $($first)*).into(),
);
g.set_span($span);
g
});
quote_each_token!($tokens $span $($rest)*);
};

Expand Down
58 changes: 25 additions & 33 deletions src/to_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@ use super::Tokens;

use std::borrow::Cow;

use proc_macro2::{Literal, Span, Term, TokenNode, TokenTree, TokenStream};

fn tt(kind: TokenNode) -> TokenTree {
TokenTree {
span: Span::def_site(),
kind: kind,
}
}
use proc_macro2::{Literal, Span, Term, TokenTree, TokenStream};

/// Types that can be interpolated inside a [`quote!`] invocation.
///
Expand All @@ -25,7 +18,7 @@ pub trait ToTokens {
/// use quote::{Tokens, ToTokens};
///
/// extern crate proc_macro2;
/// use proc_macro2::{TokenTree, TokenNode, Spacing, Span};
/// use proc_macro2::{TokenTree, Spacing, Span, Op};
///
/// pub struct Path {
/// pub global: bool,
Expand All @@ -37,14 +30,8 @@ pub trait ToTokens {
/// for (i, segment) in self.segments.iter().enumerate() {
/// if i > 0 || self.global {
/// // Double colon `::`
/// tokens.append(TokenTree {
/// span: Span::def_site(),
/// kind: TokenNode::Op(':', Spacing::Joint),
/// });
/// tokens.append(TokenTree {
/// span: Span::def_site(),
/// kind: TokenNode::Op(':', Spacing::Alone),
/// });
/// tokens.append(Op::new(':', Spacing::Joint));
/// tokens.append(Op::new(':', Spacing::Alone));
/// }
/// segment.to_tokens(tokens);
/// }
Expand Down Expand Up @@ -105,7 +92,7 @@ impl<T: ToTokens> ToTokens for Option<T> {

impl ToTokens for str {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append(tt(TokenNode::Literal(Literal::string(self))));
tokens.append(Literal::string(self));
}
}

Expand All @@ -116,49 +103,54 @@ impl ToTokens for String {
}

macro_rules! primitive {
($($t:ident)*) => ($(
($($t:ident => $name:ident)*) => ($(
impl ToTokens for $t {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append(tt(TokenNode::Literal(Literal::$t(*self))));
tokens.append(Literal::$name(*self));
}
}
)*)
}

primitive! {
i8 i16 i32 i64 isize
u8 u16 u32 u64 usize
f32 f64
i8 => i8_suffixed
i16 => i16_suffixed
i32 => i32_suffixed
i64 => i64_suffixed
isize => isize_suffixed

u8 => u8_suffixed
u16 => u16_suffixed
u32 => u32_suffixed
u64 => u64_suffixed
usize => usize_suffixed

f32 => f32_suffixed
f64 => f64_suffixed
}

impl ToTokens for char {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append(tt(TokenNode::Literal(Literal::character(*self))));
tokens.append(Literal::character(*self));
}
}

impl ToTokens for bool {
fn to_tokens(&self, tokens: &mut Tokens) {
let word = if *self { "true" } else { "false" };
tokens.append(tt(TokenNode::Term(Term::intern(word))));
tokens.append(Term::new(word, Span::call_site()));
}
}

impl ToTokens for Term {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append(tt(TokenNode::Term(*self)));
tokens.append(self.clone());
}
}

impl ToTokens for Literal {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append(tt(TokenNode::Literal(self.clone())));
}
}

impl ToTokens for TokenNode {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append(tt(self.clone()));
tokens.append(self.clone());
}
}

Expand Down
42 changes: 22 additions & 20 deletions src/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,20 @@ impl Debug for Tokens {
}

fn tt_eq(a: &TokenTree, b: &TokenTree) -> bool {
use proc_macro2::{TokenNode, Delimiter, Spacing};
use proc_macro2::{Delimiter, Spacing};

match (&a.kind, &b.kind) {
(&TokenNode::Group(d1, ref s1), &TokenNode::Group(d2, ref s2)) => {
match (d1, d2) {
match (a, b) {
(&TokenTree::Group(ref s1), &TokenTree::Group(ref s2)) => {
match (s1.delimiter(), s2.delimiter()) {
(Delimiter::Parenthesis, Delimiter::Parenthesis)
| (Delimiter::Brace, Delimiter::Brace)
| (Delimiter::Bracket, Delimiter::Bracket)
| (Delimiter::None, Delimiter::None) => {}
_ => return false,
}

let s1 = s1.clone().into_iter();
let mut s2 = s2.clone().into_iter();
let s1 = s1.stream().clone().into_iter();
let mut s2 = s2.stream().clone().into_iter();

for item1 in s1 {
let item2 = match s2.next() {
Expand All @@ -196,16 +196,18 @@ fn tt_eq(a: &TokenTree, b: &TokenTree) -> bool {
}
s2.next().is_none()
}
(&TokenNode::Op(o1, k1), &TokenNode::Op(o2, k2)) => {
o1 == o2 && match (k1, k2) {
(&TokenTree::Op(ref o1), &TokenTree::Op(ref o2)) => {
o1.op() == o2.op() && match (o1.spacing(), o2.spacing()) {
(Spacing::Alone, Spacing::Alone) | (Spacing::Joint, Spacing::Joint) => true,
_ => false,
}
}
(&TokenNode::Literal(ref l1), &TokenNode::Literal(ref l2)) => {
(&TokenTree::Literal(ref l1), &TokenTree::Literal(ref l2)) => {
l1.to_string() == l2.to_string()
}
(&TokenNode::Term(ref s1), &TokenNode::Term(ref s2)) => s1.as_str() == s2.as_str(),
(&TokenTree::Term(ref s1), &TokenTree::Term(ref s2)) => {
s1.as_str() == s2.as_str()
}
_ => false,
}
}
Expand All @@ -224,33 +226,33 @@ impl PartialEq for Tokens {
}

fn tt_hash<H: Hasher>(tt: &TokenTree, h: &mut H) {
use proc_macro2::{TokenNode, Delimiter, Spacing};
use proc_macro2::{Delimiter, Spacing};

match tt.kind {
TokenNode::Group(delim, ref stream) => {
match *tt {
TokenTree::Group(ref g) => {
0u8.hash(h);
match delim {
match g.delimiter() {
Delimiter::Parenthesis => 0u8.hash(h),
Delimiter::Brace => 1u8.hash(h),
Delimiter::Bracket => 2u8.hash(h),
Delimiter::None => 3u8.hash(h),
}

for item in stream.clone() {
for item in g.stream().clone() {
tt_hash(&item, h);
}
0xffu8.hash(h); // terminator w/ a variant we don't normally hash
}
TokenNode::Op(op, kind) => {
TokenTree::Op(ref t) => {
1u8.hash(h);
op.hash(h);
match kind {
t.op().hash(h);
match t.spacing() {
Spacing::Alone => 0u8.hash(h),
Spacing::Joint => 1u8.hash(h),
}
}
TokenNode::Literal(ref lit) => (2u8, lit.to_string()).hash(h),
TokenNode::Term(ref word) => (3u8, word.as_str()).hash(h),
TokenTree::Literal(ref lit) => (2u8, lit.to_string()).hash(h),
TokenTree::Term(ref word) => (3u8, word.as_str()).hash(h),
}
}

Expand Down
15 changes: 6 additions & 9 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ struct X;

impl quote::ToTokens for X {
fn to_tokens(&self, tokens: &mut quote::Tokens) {
tokens.append(proc_macro2::TokenTree {
kind: proc_macro2::TokenNode::Term(Term::intern("X")),
span: Span::def_site(),
});
tokens.append(Term::new("X", Span::call_site()));
}
}

Expand Down Expand Up @@ -185,8 +182,8 @@ fn test_string() {

#[test]
fn test_ident() {
let foo = Term::intern("Foo");
let bar = Term::intern(&format!("Bar{}", 7));
let foo = Term::new("Foo", Span::call_site());
let bar = Term::new(&format!("Bar{}", 7), Span::call_site());
let tokens = quote!(struct #foo; enum #bar {});
let expected = "struct Foo ; enum Bar7 { }";
assert_eq!(expected, tokens.to_string());
Expand Down Expand Up @@ -260,9 +257,9 @@ fn test_box_str() {

#[test]
fn test_cow() {
let owned: Cow<Term> = Cow::Owned(Term::intern("owned"));
let owned: Cow<Term> = Cow::Owned(Term::new("owned", Span::call_site()));

let ident = Term::intern("borrowed");
let ident = Term::new("borrowed", Span::call_site());
let borrowed = Cow::Borrowed(&ident);

let tokens = quote! { #owned #borrowed };
Expand All @@ -272,7 +269,7 @@ fn test_cow() {
#[test]
fn test_closure() {
fn field_i(i: usize) -> Term {
Term::intern(&format!("__field{}", i))
Term::new(&format!("__field{}", i), Span::call_site())
}

let fields = (0usize..3)
Expand Down