internal: add cloning macro fixture

Macro that deep clone the tokens but otherwise preserves source
locations and hygiene info is an interesting case for IDE support. Lets
have this, although we don't actively use it at the moment.
This commit is contained in:
Aleksey Kladov 2021-06-25 10:32:13 +03:00
parent 2ac1ffc0f3
commit c27fdc75fa
2 changed files with 41 additions and 1 deletions

View File

@ -42,6 +42,19 @@ fn test_fn_like_macro() {
);
}
#[test]
fn test_fn_like_macro2() {
assert_expand(
"fn_like_clone_tokens",
r#"ident, []"#,
expect![[r#"
SUBTREE $
IDENT ident 4294967295
PUNCH , [alone] 4294967295
SUBTREE [] 4294967295"#]],
);
}
#[test]
fn test_attr_macro() {
// Corresponds to
@ -70,6 +83,7 @@ fn list_test_macros() {
fn_like_noop [FuncLike]
fn_like_panic [FuncLike]
fn_like_error [FuncLike]
fn_like_clone_tokens [FuncLike]
attr_noop [Attr]
attr_panic [Attr]
attr_error [Attr]

View File

@ -1,6 +1,6 @@
//! Exports a few trivial procedural macros for testing.
use proc_macro::TokenStream;
use proc_macro::{Group, Ident, Punct, TokenStream, TokenTree};
#[proc_macro]
pub fn fn_like_noop(args: TokenStream) -> TokenStream {
@ -17,6 +17,11 @@ pub fn fn_like_error(args: TokenStream) -> TokenStream {
format!("compile_error!(\"fn_like_error!({})\");", args).parse().unwrap()
}
#[proc_macro]
pub fn fn_like_clone_tokens(args: TokenStream) -> TokenStream {
clone_stream(args)
}
#[proc_macro_attribute]
pub fn attr_noop(_args: TokenStream, item: TokenStream) -> TokenStream {
item
@ -46,3 +51,24 @@ pub fn derive_panic(item: TokenStream) -> TokenStream {
pub fn derive_error(item: TokenStream) -> TokenStream {
format!("compile_error!(\"#[derive(DeriveError)] {}\");", item).parse().unwrap()
}
fn clone_stream(ts: TokenStream) -> TokenStream {
ts.into_iter().map(clone_tree).collect()
}
fn clone_tree(t: TokenTree) -> TokenTree {
match t {
TokenTree::Group(orig) => {
let mut new = Group::new(orig.delimiter(), clone_stream(orig.stream()));
new.set_span(orig.span());
TokenTree::Group(new)
}
TokenTree::Ident(orig) => TokenTree::Ident(Ident::new(&orig.to_string(), orig.span())),
TokenTree::Punct(orig) => {
let mut new = Punct::new(orig.as_char(), orig.spacing());
new.set_span(orig.span());
TokenTree::Punct(new)
}
TokenTree::Literal(_orig) => unimplemented!(),
}
}