diff options
-rw-r--r-- | crates/ra_hir_expand/src/quote.rs | 2 | ||||
-rw-r--r-- | crates/ra_mbe/src/tests.rs | 79 | ||||
-rw-r--r-- | crates/ra_tt/src/lib.rs | 57 |
3 files changed, 136 insertions, 2 deletions
diff --git a/crates/ra_hir_expand/src/quote.rs b/crates/ra_hir_expand/src/quote.rs index 3fd4233da..219bc2097 100644 --- a/crates/ra_hir_expand/src/quote.rs +++ b/crates/ra_hir_expand/src/quote.rs | |||
@@ -232,7 +232,7 @@ mod tests { | |||
232 | let quoted = quote!(#a); | 232 | let quoted = quote!(#a); |
233 | assert_eq!(quoted.to_string(), "hello"); | 233 | assert_eq!(quoted.to_string(), "hello"); |
234 | let t = format!("{:?}", quoted); | 234 | let t = format!("{:?}", quoted); |
235 | assert_eq!(t, "Subtree { delimiter: None, token_trees: [Leaf(Ident(Ident { text: \"hello\", id: TokenId(4294967295) }))] }"); | 235 | assert_eq!(t, "SUBTREE $\n IDENT hello 4294967295"); |
236 | } | 236 | } |
237 | 237 | ||
238 | #[test] | 238 | #[test] |
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 254318e23..1ef6f6eed 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs | |||
@@ -142,6 +142,79 @@ macro_rules! impl_froms { | |||
142 | } | 142 | } |
143 | 143 | ||
144 | #[test] | 144 | #[test] |
145 | fn test_convert_tt2() { | ||
146 | parse_macro( | ||
147 | r#" | ||
148 | macro_rules! impl_froms { | ||
149 | ($e:ident: $($v:ident),*) => { | ||
150 | $( | ||
151 | impl From<$v> for $e { | ||
152 | fn from(it: $v) -> $e { | ||
153 | $e::$v(it) | ||
154 | } | ||
155 | } | ||
156 | )* | ||
157 | } | ||
158 | } | ||
159 | "#, | ||
160 | ) | ||
161 | .assert_expand( | ||
162 | "impl_froms!(TokenTree: Leaf, Subtree);", | ||
163 | r#" | ||
164 | SUBTREE $ | ||
165 | IDENT impl 20 | ||
166 | IDENT From 21 | ||
167 | PUNCH < [joint] 22 | ||
168 | IDENT Leaf 53 | ||
169 | PUNCH > [alone] 25 | ||
170 | IDENT for 26 | ||
171 | IDENT TokenTree 51 | ||
172 | SUBTREE {} 29 | ||
173 | IDENT fn 30 | ||
174 | IDENT from 31 | ||
175 | SUBTREE () 32 | ||
176 | IDENT it 33 | ||
177 | PUNCH : [alone] 34 | ||
178 | IDENT Leaf 53 | ||
179 | PUNCH - [joint] 37 | ||
180 | PUNCH > [alone] 38 | ||
181 | IDENT TokenTree 51 | ||
182 | SUBTREE {} 41 | ||
183 | IDENT TokenTree 51 | ||
184 | PUNCH : [joint] 44 | ||
185 | PUNCH : [joint] 45 | ||
186 | IDENT Leaf 53 | ||
187 | SUBTREE () 48 | ||
188 | IDENT it 49 | ||
189 | IDENT impl 20 | ||
190 | IDENT From 21 | ||
191 | PUNCH < [joint] 22 | ||
192 | IDENT Subtree 55 | ||
193 | PUNCH > [alone] 25 | ||
194 | IDENT for 26 | ||
195 | IDENT TokenTree 51 | ||
196 | SUBTREE {} 29 | ||
197 | IDENT fn 30 | ||
198 | IDENT from 31 | ||
199 | SUBTREE () 32 | ||
200 | IDENT it 33 | ||
201 | PUNCH : [alone] 34 | ||
202 | IDENT Subtree 55 | ||
203 | PUNCH - [joint] 37 | ||
204 | PUNCH > [alone] 38 | ||
205 | IDENT TokenTree 51 | ||
206 | SUBTREE {} 41 | ||
207 | IDENT TokenTree 51 | ||
208 | PUNCH : [joint] 44 | ||
209 | PUNCH : [joint] 45 | ||
210 | IDENT Subtree 55 | ||
211 | SUBTREE () 48 | ||
212 | IDENT it 49 | ||
213 | "#, | ||
214 | ); | ||
215 | } | ||
216 | |||
217 | #[test] | ||
145 | fn test_expr_order() { | 218 | fn test_expr_order() { |
146 | let expanded = parse_macro( | 219 | let expanded = parse_macro( |
147 | r#" | 220 | r#" |
@@ -1479,6 +1552,12 @@ impl MacroFixture { | |||
1479 | assert_eq!(expansion.to_string(), expected); | 1552 | assert_eq!(expansion.to_string(), expected); |
1480 | } | 1553 | } |
1481 | 1554 | ||
1555 | fn assert_expand(&self, invocation: &str, expected: &str) { | ||
1556 | let expansion = self.expand_tt(invocation); | ||
1557 | let actual = format!("{:?}", expansion); | ||
1558 | test_utils::assert_eq_text!(&actual.trim(), &expected.trim()); | ||
1559 | } | ||
1560 | |||
1482 | fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture { | 1561 | fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture { |
1483 | self.assert_expansion(FragmentKind::Items, invocation, expected); | 1562 | self.assert_expansion(FragmentKind::Items, invocation, expected); |
1484 | self | 1563 | self |
diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index bd484aa30..5248e026c 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs | |||
@@ -57,7 +57,7 @@ pub enum Leaf { | |||
57 | } | 57 | } |
58 | impl_froms!(Leaf: Literal, Punct, Ident); | 58 | impl_froms!(Leaf: Literal, Punct, Ident); |
59 | 59 | ||
60 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] | 60 | #[derive(Clone, PartialEq, Eq, Hash, Default)] |
61 | pub struct Subtree { | 61 | pub struct Subtree { |
62 | pub delimiter: Option<Delimiter>, | 62 | pub delimiter: Option<Delimiter>, |
63 | pub token_trees: Vec<TokenTree>, | 63 | pub token_trees: Vec<TokenTree>, |
@@ -101,6 +101,61 @@ pub struct Ident { | |||
101 | pub id: TokenId, | 101 | pub id: TokenId, |
102 | } | 102 | } |
103 | 103 | ||
104 | fn print_debug_subtree(f: &mut fmt::Formatter<'_>, subtree: &Subtree, level: usize) -> fmt::Result { | ||
105 | let align = std::iter::repeat(" ").take(level).collect::<String>(); | ||
106 | |||
107 | let aux = match subtree.delimiter.map(|it| (it.kind, it.id.0)) { | ||
108 | None => "$".to_string(), | ||
109 | Some((DelimiterKind::Parenthesis, id)) => format!("() {}", id), | ||
110 | Some((DelimiterKind::Brace, id)) => format!("{{}} {}", id), | ||
111 | Some((DelimiterKind::Bracket, id)) => format!("[] {}", id), | ||
112 | }; | ||
113 | |||
114 | if subtree.token_trees.is_empty() { | ||
115 | write!(f, "{}SUBTREE {}", align, aux)?; | ||
116 | } else { | ||
117 | writeln!(f, "{}SUBTREE {}", align, aux)?; | ||
118 | for (idx, child) in subtree.token_trees.iter().enumerate() { | ||
119 | print_debug_token(f, child, level + 1)?; | ||
120 | if idx != subtree.token_trees.len() - 1 { | ||
121 | writeln!(f, "")?; | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | |||
126 | Ok(()) | ||
127 | } | ||
128 | |||
129 | fn print_debug_token(f: &mut fmt::Formatter<'_>, tkn: &TokenTree, level: usize) -> fmt::Result { | ||
130 | let align = std::iter::repeat(" ").take(level).collect::<String>(); | ||
131 | |||
132 | match tkn { | ||
133 | TokenTree::Leaf(leaf) => match leaf { | ||
134 | Leaf::Literal(lit) => write!(f, "{}LITERAL {} {}", align, lit.text, lit.id.0)?, | ||
135 | Leaf::Punct(punct) => write!( | ||
136 | f, | ||
137 | "{}PUNCH {} [{}] {}", | ||
138 | align, | ||
139 | punct.char, | ||
140 | if punct.spacing == Spacing::Alone { "alone" } else { "joint" }, | ||
141 | punct.id.0 | ||
142 | )?, | ||
143 | Leaf::Ident(ident) => write!(f, "{}IDENT {} {}", align, ident.text, ident.id.0)?, | ||
144 | }, | ||
145 | TokenTree::Subtree(subtree) => { | ||
146 | print_debug_subtree(f, subtree, level)?; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | Ok(()) | ||
151 | } | ||
152 | |||
153 | impl Debug for Subtree { | ||
154 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
155 | print_debug_subtree(f, self, 0) | ||
156 | } | ||
157 | } | ||
158 | |||
104 | impl fmt::Display for TokenTree { | 159 | impl fmt::Display for TokenTree { |
105 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 160 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
106 | match self { | 161 | match self { |