blob: 33effd56414fff8d59701c96262632e262e29eca [file] [log] [blame]
David Tolnay453cfd12016-10-23 11:00:14 -07001#![cfg(feature = "expand")]
2
3extern crate syn;
4use syn::*;
5
6#[macro_use]
7extern crate quote;
8use quote::Tokens;
9
10extern crate tempdir;
11use tempdir::TempDir;
12
13use std::fs::File;
14use std::io::{Read, Write};
15
16#[test]
17fn test_cfg() {
18 let original = quote! {
19 use super::*;
20
21 #[derive(A)]
22 struct P;
23
24 #[cfg_attr(feature = "q", derive(A))]
25 struct Q;
26
27 #[derive(A)]
28 #[cfg(feature = "r")]
29 struct R;
30
31 #[cfg(feature = "s1")]
32 #[cfg(all(feature = "s2", feature = "s3"))]
33 #[cfg_attr(feature = "s4", derive(A))]
34 struct S;
35 };
36
37 let expected = quote! {
38 // Unmodified from the input
39 use super::*;
40
41 type P = ();
42
43 #[cfg(feature = "q")]
44 type Q = ();
45
46 #[cfg(feature = "r")]
47 type R = ();
48
49 #[cfg(all(feature = "s1", feature = "s2", feature = "s3", feature = "s4"))]
50 type S = ();
51 };
52
53 test_expand(original, expected);
54}
55
56#[test]
57fn test_recursive() {
58 let original = quote! {
59 #[d]
60 #[cfg_attr(feature = "f", derive(Copy, B, Clone))]
61 #[e]
62 #[cfg(feature = "e")]
63 struct T;
64 };
65
66 let expected = quote! {
67 // From #[derive(A)] on struct S produced by #[derive(B)]
68 #[cfg(all(feature = "e", feature = "f", feature = "g"))]
69 type S = ();
70
71 // From #[derive(B)] on struct T
72 #[cfg(all(feature = "e", feature = "f"))]
73 impl B for T {}
74
75 // From the input
76 #[d]
77 #[cfg_attr(feature = "f", derive(Copy, Clone))]
78 #[e]
79 #[cfg(feature = "e")]
80 struct T;
81 };
82
83 test_expand(original, expected);
84}
85
86fn test_expand(original: Tokens, expected: Tokens) {
87 let dir = TempDir::new("syn").expect("create temp dir");
88 let src_path = dir.path().join("expand.in.rs");
89 let dst_path = dir.path().join("expand.rs");
90
91 // Write the src file
92 let mut src_file = File::create(&src_path).expect("create temp file");
93 src_file.write_all(original.to_string().as_bytes()).expect("write temp file");
94
95 // Run expansion
96 let mut registry = Registry::new();
97 registry.add_derive("A", expand_a);
98 registry.add_derive("B", expand_b);
99 registry.expand_file(&src_path, &dst_path).unwrap();
100
101 // Read the dst file
102 let mut expanded = String::new();
103 let mut dst_file = File::open(&dst_path).expect("open output file");
104 dst_file.read_to_string(&mut expanded).expect("read output file");
105
106 assert_eq!(expanded, expected.to_string());
107}
108
109fn expand_a(input: MacroInput) -> Result<Expanded, String> {
110 let name = &input.ident;
111 let out = quote! {
112 type #name = ();
113 };
114 Ok(Expanded {
115 new_items: parse_items(&out.to_string()).unwrap(),
116 original: None,
117 })
118}
119
120fn expand_b(input: MacroInput) -> Result<Expanded, String> {
121 assert_eq!(quote!(#input), quote! {
122 #[d]
123 #[cfg_attr(feature = "f", derive(Copy, Clone))]
124 #[e]
125 struct T;
126 });
127 let out = quote! {
128 #[cfg_attr(feature = "g", derive(A))]
129 struct S;
130
131 impl B for T {}
132 };
133 Ok(Expanded {
134 new_items: parse_items(&out.to_string()).unwrap(),
135 original: Some(input),
136 })
137}