Skip to content

Instantly share code, notes, and snippets.

@lqd

lqd/test.rs Secret

Created July 19, 2019 18:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lqd/91a22edae631f3e8c7083e4a7614aba9 to your computer and use it in GitHub Desktop.
Save lqd/91a22edae631f3e8c7083e4a7614aba9 to your computer and use it in GitHub Desktop.
#![feature(proc_macro_span)]
extern crate proc_macro;
#[macro_use]
extern crate quote;
use quote::TokenStreamExt;
use proc_macro::TokenTree;
#[proc_macro_derive(DomObject)]
pub fn expand_token_stream(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input: syn::DeriveInput = syn::parse(input).unwrap();
let fields = if let syn::Data::Struct(syn::DataStruct { ref fields, .. }) = input.data {
fields.iter().collect::<Vec<&syn::Field>>()
} else {
panic!("#[derive(DomObject)] should only be applied on proper structs")
};
let mut field_types = vec![];
for field in fields {
field_types.push(&field.ty);
}
let mut items = quote! {};
items.append_all(field_types.iter().map(|ty| {
quote! {
impl Bar for ((), #ty) {}
}
}));
let x = quote! { #items };
let x: proc_macro::TokenStream = x.into();
let y: proc_macro::TokenStream =
"impl Bar for ((), Qux<Qux<Baz> >) {}
impl Bar for ((), Box<Bar>) {}"
.parse().unwrap();
assert_eq!(x.to_string(), y.to_string()); // the text representation is the same
let trees_x: Vec<_> = x.into_iter().collect();
let trees_y: Vec<_> = y.into_iter().collect();
assert_eq!(trees_x.len(), trees_y.len());
// assert_eq!(format!("{:#?}", x), format!("{:#?}", y)); // but not the spans, this would fail
// print the differences
for (idx, (token_x, token_y)) in trees_x.iter().zip(trees_y.iter()).enumerate() {
if let TokenTree::Group(group_x) = token_x {
if let TokenTree::Group(group_y) = token_y {
let stream_x = group_x.stream().into_iter();
let stream_y = group_y.stream().into_iter();
for (group_idx, (token_x, token_y)) in stream_x.zip(stream_y).enumerate() {
if !token_x.span().eq(&token_y.span()) {
println!("spans differing at group {}, element {}\nsyn/quote: `{:?}`\nproc_macro: `{:?}`\n", idx, group_idx, token_x, token_y);
}
}
}
}
}
let mut stream = proc_macro::TokenStream::new();
stream.extend(trees_x);
stream
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment