Skip to content

Commit 48a54ba

Browse files
committed
Migrate basic tests for proc_macro::quote! from quote crate
1 parent 0351e73 commit 48a54ba

File tree

4 files changed

+365
-0
lines changed

4 files changed

+365
-0
lines changed
Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
#![feature(proc_macro_quote)]
2+
#![feature(proc_macro_totokens)]
3+
4+
extern crate proc_macro;
5+
6+
use std::borrow::Cow;
7+
use std::ffi::{CStr, CString};
8+
9+
use proc_macro::*;
10+
11+
#[proc_macro]
12+
pub fn run_test(input: TokenStream) -> TokenStream {
13+
test_quote_impl();
14+
test_substitution();
15+
test_advanced();
16+
test_integer();
17+
test_floating();
18+
test_char();
19+
test_str();
20+
test_string();
21+
test_c_str();
22+
test_c_string();
23+
test_interpolated_literal();
24+
test_ident();
25+
test_underscore();
26+
test_duplicate();
27+
test_empty_quote();
28+
test_box_str();
29+
test_cow();
30+
test_append_tokens();
31+
// test_outer_line_comment(); // FIXME: Fix it in a subsequent commit
32+
// test_inner_line_comment(); // FIXME: Fix it in a subsequent commit
33+
// test_outer_block_comment(); // FIXME: Fix it in a subsequent commit
34+
// test_inner_block_comment(); // FIXME: Fix it in a subsequent commit
35+
test_outer_attr();
36+
test_inner_attr();
37+
// test_quote_raw_id(); // FIXME: Fix it in a subsequent commit
38+
39+
TokenStream::new()
40+
}
41+
42+
// Based on https://github.com/dtolnay/quote/blob/0245506323a3616daa2ee41c6ad0b871e4d78ae4/tests/test.rs
43+
//
44+
// FIXME: The following tests are removed because they are not supported yet in `proc_macro::quote!`
45+
// - quote_spanned:
46+
// - fn test_quote_spanned_impl
47+
// - fn test_type_inference_for_span
48+
// - format_ident:
49+
// - fn test_format_ident
50+
// - fn test_format_ident_strip_raw
51+
// - repetition:
52+
// - fn test_iter
53+
// - fn test_array
54+
// - fn test_fancy_repetition
55+
// - fn test_nested_fancy_repetition
56+
// - fn test_duplicate_name_repetition
57+
// - fn test_duplicate_name_repetition_no_copy
58+
// - fn test_btreeset_repetition
59+
// - fn test_variable_name_conflict
60+
// - fn test_nonrep_in_repetition
61+
// - fn test_closure
62+
// - fn test_star_after_repetition
63+
64+
struct X;
65+
66+
impl ToTokens for X {
67+
fn to_tokens(&self, tokens: &mut TokenStream) {
68+
Ident::new("X", Span::call_site()).to_tokens(tokens)
69+
}
70+
}
71+
72+
fn test_quote_impl() {
73+
let tokens = quote! {
74+
impl<'a, T: ToTokens> ToTokens for &'a T {
75+
fn to_tokens(&self, tokens: &mut TokenStream) {
76+
(**self).to_tokens(tokens)
77+
}
78+
}
79+
};
80+
81+
let expected = r#"impl < 'a, T : ToTokens > ToTokens for & 'a T
82+
{
83+
fn to_tokens(& self, tokens : & mut TokenStream)
84+
{ (** self).to_tokens(tokens) }
85+
}"#;
86+
87+
assert_eq!(expected, tokens.to_string());
88+
}
89+
90+
fn test_substitution() {
91+
let x = X;
92+
let tokens = quote!($x <$x> ($x) [$x] {$x});
93+
94+
let expected = "X <X > (X) [X] { X }";
95+
96+
assert_eq!(expected, tokens.to_string());
97+
}
98+
99+
fn test_advanced() {
100+
let generics = quote!( <'a, T> );
101+
102+
let where_clause = quote!( where T: Serialize );
103+
104+
let field_ty = quote!(String);
105+
106+
let item_ty = quote!(Cow<'a, str>);
107+
108+
let path = quote!(SomeTrait::serialize_with);
109+
110+
let value = quote!(self.x);
111+
112+
let tokens = quote! {
113+
struct SerializeWith $generics $where_clause {
114+
value: &'a $field_ty,
115+
phantom: ::std::marker::PhantomData<$item_ty>,
116+
}
117+
118+
impl $generics ::serde::Serialize for SerializeWith $generics $where_clause {
119+
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
120+
where S: ::serde::Serializer
121+
{
122+
$path(self.value, s)
123+
}
124+
}
125+
126+
SerializeWith {
127+
value: $value,
128+
phantom: ::std::marker::PhantomData::<$item_ty>,
129+
}
130+
};
131+
132+
let expected = r#"struct SerializeWith < 'a, T > where T : Serialize
133+
{
134+
value : & 'a String, phantom : :: std :: marker :: PhantomData <Cow < 'a,
135+
str > >,
136+
} impl < 'a, T > :: serde :: Serialize for SerializeWith < 'a, T > where T :
137+
Serialize
138+
{
139+
fn serialize < S > (& self, s : & mut S) -> Result < (), S :: Error >
140+
where S : :: serde :: Serializer
141+
{ SomeTrait :: serialize_with(self.value, s) }
142+
} SerializeWith
143+
{
144+
value : self.x, phantom : :: std :: marker :: PhantomData ::<Cow < 'a, str
145+
> >,
146+
}"#;
147+
148+
assert_eq!(expected, tokens.to_string());
149+
}
150+
151+
fn test_integer() {
152+
let ii8 = -1i8;
153+
let ii16 = -1i16;
154+
let ii32 = -1i32;
155+
let ii64 = -1i64;
156+
let ii128 = -1i128;
157+
let iisize = -1isize;
158+
let uu8 = 1u8;
159+
let uu16 = 1u16;
160+
let uu32 = 1u32;
161+
let uu64 = 1u64;
162+
let uu128 = 1u128;
163+
let uusize = 1usize;
164+
165+
let tokens = quote! {
166+
1 1i32 1u256
167+
$ii8 $ii16 $ii32 $ii64 $ii128 $iisize
168+
$uu8 $uu16 $uu32 $uu64 $uu128 $uusize
169+
};
170+
let expected = r#"1 1i32 1u256 -1i8 -1i16 -1i32 -1i64 -1i128 -1isize 1u8 1u16 1u32 1u64 1u128
171+
1usize"#;
172+
assert_eq!(expected, tokens.to_string());
173+
}
174+
175+
fn test_floating() {
176+
let e32 = 2.345f32;
177+
178+
let e64 = 2.345f64;
179+
180+
let tokens = quote! {
181+
$e32
182+
$e64
183+
};
184+
let expected = concat!("2.345f32 2.345f64");
185+
assert_eq!(expected, tokens.to_string());
186+
}
187+
188+
fn test_char() {
189+
let zero = '\u{1}';
190+
let pound = '#';
191+
let quote = '"';
192+
let apost = '\'';
193+
let newline = '\n';
194+
let heart = '\u{2764}';
195+
196+
let tokens = quote! {
197+
$zero $pound $quote $apost $newline $heart
198+
};
199+
let expected = "'\\u{1}' '#' '\"' '\\'' '\\n' '\u{2764}'";
200+
assert_eq!(expected, tokens.to_string());
201+
}
202+
203+
fn test_str() {
204+
let s = "\u{1} a 'b \" c";
205+
let tokens = quote!($s);
206+
let expected = "\"\\u{1} a 'b \\\" c\"";
207+
assert_eq!(expected, tokens.to_string());
208+
}
209+
210+
fn test_string() {
211+
let s = "\u{1} a 'b \" c".to_string();
212+
let tokens = quote!($s);
213+
let expected = "\"\\u{1} a 'b \\\" c\"";
214+
assert_eq!(expected, tokens.to_string());
215+
}
216+
217+
fn test_c_str() {
218+
let s = CStr::from_bytes_with_nul(b"\x01 a 'b \" c\0").unwrap();
219+
let tokens = quote!($s);
220+
let expected = "c\"\\u{1} a 'b \\\" c\"";
221+
assert_eq!(expected, tokens.to_string());
222+
}
223+
224+
fn test_c_string() {
225+
let s = CString::new(&b"\x01 a 'b \" c"[..]).unwrap();
226+
let tokens = quote!($s);
227+
let expected = "c\"\\u{1} a 'b \\\" c\"";
228+
assert_eq!(expected, tokens.to_string());
229+
}
230+
231+
fn test_interpolated_literal() {
232+
macro_rules! m {
233+
($literal:literal) => {
234+
quote!($literal)
235+
};
236+
}
237+
238+
let tokens = m!(1);
239+
let expected = "1";
240+
assert_eq!(expected, tokens.to_string());
241+
242+
let tokens = m!(-1);
243+
let expected = "- 1";
244+
assert_eq!(expected, tokens.to_string());
245+
246+
let tokens = m!(true);
247+
let expected = "true";
248+
assert_eq!(expected, tokens.to_string());
249+
250+
let tokens = m!(-true);
251+
let expected = "- true";
252+
assert_eq!(expected, tokens.to_string());
253+
}
254+
255+
fn test_ident() {
256+
let foo = Ident::new("Foo", Span::call_site());
257+
let bar = Ident::new(&format!("Bar{}", 7), Span::call_site());
258+
let tokens = quote!(struct $foo; enum $bar {});
259+
let expected = "struct Foo; enum Bar7 {}";
260+
assert_eq!(expected, tokens.to_string());
261+
}
262+
263+
fn test_underscore() {
264+
let tokens = quote!(let _;);
265+
let expected = "let _;";
266+
assert_eq!(expected, tokens.to_string());
267+
}
268+
269+
fn test_duplicate() {
270+
let ch = 'x';
271+
272+
let tokens = quote!($ch $ch);
273+
274+
let expected = "'x' 'x'";
275+
assert_eq!(expected, tokens.to_string());
276+
}
277+
278+
fn test_empty_quote() {
279+
let tokens = quote!();
280+
assert_eq!("", tokens.to_string());
281+
}
282+
283+
fn test_box_str() {
284+
let b = "str".to_owned().into_boxed_str();
285+
let tokens = quote! { $b };
286+
assert_eq!("\"str\"", tokens.to_string());
287+
}
288+
289+
fn test_cow() {
290+
let owned: Cow<Ident> = Cow::Owned(Ident::new("owned", Span::call_site()));
291+
292+
let ident = Ident::new("borrowed", Span::call_site());
293+
let borrowed = Cow::Borrowed(&ident);
294+
295+
let tokens = quote! { $owned $borrowed };
296+
assert_eq!("owned borrowed", tokens.to_string());
297+
}
298+
299+
fn test_append_tokens() {
300+
let mut a = quote!(a);
301+
let b = quote!(b);
302+
a.extend(b);
303+
assert_eq!("a b", a.to_string());
304+
}
305+
306+
fn test_outer_line_comment() {
307+
let tokens = quote! {
308+
/// doc
309+
};
310+
let expected = "# [doc = r\" doc\"]";
311+
assert_eq!(expected, tokens.to_string());
312+
}
313+
314+
fn test_inner_line_comment() {
315+
let tokens = quote! {
316+
//! doc
317+
};
318+
let expected = "# ! [doc = r\" doc\"]";
319+
assert_eq!(expected, tokens.to_string());
320+
}
321+
322+
fn test_outer_block_comment() {
323+
let tokens = quote! {
324+
/** doc */
325+
};
326+
let expected = "# [doc = r\" doc \"]";
327+
assert_eq!(expected, tokens.to_string());
328+
}
329+
330+
fn test_inner_block_comment() {
331+
let tokens = quote! {
332+
/*! doc */
333+
};
334+
let expected = "# ! [doc = r\" doc \"]";
335+
assert_eq!(expected, tokens.to_string());
336+
}
337+
338+
fn test_outer_attr() {
339+
let tokens = quote! {
340+
#[inline]
341+
};
342+
let expected = "#[inline]";
343+
assert_eq!(expected, tokens.to_string());
344+
}
345+
346+
fn test_inner_attr() {
347+
let tokens = quote! {
348+
#![no_std]
349+
};
350+
let expected = "#! [no_std]";
351+
assert_eq!(expected, tokens.to_string());
352+
}
353+
354+
fn test_quote_raw_id() {
355+
let id = quote!(r#raw_id);
356+
assert_eq!(id.to_string(), "r#raw_id");
357+
}

tests/ui/proc-macro/quote/basic.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//@ run-pass
2+
//@ proc-macro: basic.rs
3+
4+
extern crate basic;
5+
6+
fn main() {
7+
basic::run_test!();
8+
}
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)