Skip to content

Commit 6fdbef2

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

File tree

4 files changed

+366
-0
lines changed

4 files changed

+366
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
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_tests(_: 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();
32+
test_inner_line_comment();
33+
test_outer_block_comment();
34+
test_inner_block_comment();
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 dollar = '$';
191+
let pound = '#';
192+
let quote = '"';
193+
let apost = '\'';
194+
let newline = '\n';
195+
let heart = '\u{2764}';
196+
197+
let tokens = quote! {
198+
$zero $dollar $pound $quote $apost $newline $heart
199+
};
200+
let expected = "'\\u{1}' '$' '#' '\"' '\\'' '\\n' '\u{2764}'";
201+
assert_eq!(expected, tokens.to_string());
202+
}
203+
204+
fn test_str() {
205+
let s = "\u{1} a 'b \" c";
206+
let tokens = quote!($s);
207+
let expected = "\"\\u{1} a 'b \\\" c\"";
208+
assert_eq!(expected, tokens.to_string());
209+
}
210+
211+
fn test_string() {
212+
let s = "\u{1} a 'b \" c".to_string();
213+
let tokens = quote!($s);
214+
let expected = "\"\\u{1} a 'b \\\" c\"";
215+
assert_eq!(expected, tokens.to_string());
216+
}
217+
218+
fn test_c_str() {
219+
let s = CStr::from_bytes_with_nul(b"\x01 a 'b \" c\0").unwrap();
220+
let tokens = quote!($s);
221+
let expected = "c\"\\u{1} a 'b \\\" c\"";
222+
assert_eq!(expected, tokens.to_string());
223+
}
224+
225+
fn test_c_string() {
226+
let s = CString::new(&b"\x01 a 'b \" c"[..]).unwrap();
227+
let tokens = quote!($s);
228+
let expected = "c\"\\u{1} a 'b \\\" c\"";
229+
assert_eq!(expected, tokens.to_string());
230+
}
231+
232+
fn test_interpolated_literal() {
233+
macro_rules! m {
234+
($literal:literal) => {
235+
quote!($literal)
236+
};
237+
}
238+
239+
let tokens = m!(1);
240+
let expected = "1";
241+
assert_eq!(expected, tokens.to_string());
242+
243+
let tokens = m!(-1);
244+
let expected = "- 1";
245+
assert_eq!(expected, tokens.to_string());
246+
247+
let tokens = m!(true);
248+
let expected = "true";
249+
assert_eq!(expected, tokens.to_string());
250+
251+
let tokens = m!(-true);
252+
let expected = "- true";
253+
assert_eq!(expected, tokens.to_string());
254+
}
255+
256+
fn test_ident() {
257+
let foo = Ident::new("Foo", Span::call_site());
258+
let bar = Ident::new(&format!("Bar{}", 7), Span::call_site());
259+
let tokens = quote!(struct $foo; enum $bar {});
260+
let expected = "struct Foo; enum Bar7 {}";
261+
assert_eq!(expected, tokens.to_string());
262+
}
263+
264+
fn test_underscore() {
265+
let tokens = quote!(let _;);
266+
let expected = "let _;";
267+
assert_eq!(expected, tokens.to_string());
268+
}
269+
270+
fn test_duplicate() {
271+
let ch = 'x';
272+
273+
let tokens = quote!($ch $ch);
274+
275+
let expected = "'x' 'x'";
276+
assert_eq!(expected, tokens.to_string());
277+
}
278+
279+
fn test_empty_quote() {
280+
let tokens = quote!();
281+
assert_eq!("", tokens.to_string());
282+
}
283+
284+
fn test_box_str() {
285+
let b = "str".to_owned().into_boxed_str();
286+
let tokens = quote! { $b };
287+
assert_eq!("\"str\"", tokens.to_string());
288+
}
289+
290+
fn test_cow() {
291+
let owned: Cow<Ident> = Cow::Owned(Ident::new("owned", Span::call_site()));
292+
293+
let ident = Ident::new("borrowed", Span::call_site());
294+
let borrowed = Cow::Borrowed(&ident);
295+
296+
let tokens = quote! { $owned $borrowed };
297+
assert_eq!("owned borrowed", tokens.to_string());
298+
}
299+
300+
fn test_append_tokens() {
301+
let mut a = quote!(a);
302+
let b = quote!(b);
303+
a.extend(b);
304+
assert_eq!("a b", a.to_string());
305+
}
306+
307+
fn test_outer_line_comment() {
308+
let tokens = quote! {
309+
/// doc
310+
};
311+
let expected = "#[doc = \" doc\"]";
312+
assert_eq!(expected, tokens.to_string());
313+
}
314+
315+
fn test_inner_line_comment() {
316+
let tokens = quote! {
317+
//! doc
318+
};
319+
let expected = "# ! [doc = \" doc\"]";
320+
assert_eq!(expected, tokens.to_string());
321+
}
322+
323+
fn test_outer_block_comment() {
324+
let tokens = quote! {
325+
/** doc */
326+
};
327+
let expected = "#[doc = \" doc \"]";
328+
assert_eq!(expected, tokens.to_string());
329+
}
330+
331+
fn test_inner_block_comment() {
332+
let tokens = quote! {
333+
/*! doc */
334+
};
335+
let expected = "# ! [doc = \" doc \"]";
336+
assert_eq!(expected, tokens.to_string());
337+
}
338+
339+
fn test_outer_attr() {
340+
let tokens = quote! {
341+
#[inline]
342+
};
343+
let expected = "#[inline]";
344+
assert_eq!(expected, tokens.to_string());
345+
}
346+
347+
fn test_inner_attr() {
348+
let tokens = quote! {
349+
#![no_std]
350+
};
351+
let expected = "#! [no_std]";
352+
assert_eq!(expected, tokens.to_string());
353+
}
354+
355+
fn test_quote_raw_id() {
356+
let id = quote!(r#raw_id);
357+
assert_eq!(id.to_string(), "r#raw_id");
358+
}

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

+8
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_tests!();
8+
}

0 commit comments

Comments
 (0)