aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/macros.rs114
1 files changed, 0 insertions, 114 deletions
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs
index ffcf1c3f9..7ca34d434 100644
--- a/crates/ra_hir/src/macros.rs
+++ b/crates/ra_hir/src/macros.rs
@@ -11,7 +11,6 @@ use std::sync::Arc;
11 11
12use ra_syntax::{ 12use ra_syntax::{
13 TextRange, TextUnit, SourceFile, AstNode, SyntaxNode, TreeArc, SyntaxNodePtr, 13 TextRange, TextUnit, SourceFile, AstNode, SyntaxNode, TreeArc, SyntaxNodePtr,
14 SyntaxKind::*,
15 ast::{self, NameOwner}, 14 ast::{self, NameOwner},
16}; 15};
17 16
@@ -196,116 +195,3 @@ pub(crate) fn expand_macro_invocation(
196 let (def, input) = MacroDef::from_call(macro_call)?; 195 let (def, input) = MacroDef::from_call(macro_call)?;
197 def.expand(input).map(Arc::new) 196 def.expand(input).map(Arc::new)
198} 197}
199
200fn macro_call_to_tt(call: &ast::MacroCall) -> Option<tt::Subtree> {
201 let tt = call.token_tree()?;
202 convert_tt(tt.syntax())
203}
204
205fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> {
206 let first_child = tt.first_child()?;
207 let last_child = tt.last_child()?;
208 let delimiter = match (first_child.kind(), last_child.kind()) {
209 (L_PAREN, R_PAREN) => tt::Delimiter::Parenthesis,
210 (L_CURLY, R_CURLY) => tt::Delimiter::Brace,
211 (L_BRACK, R_BRACK) => tt::Delimiter::Bracket,
212 _ => return None,
213 };
214 let mut token_trees = Vec::new();
215 for child in tt.children().skip(1) {
216 if child == first_child || child == last_child || child.kind().is_trivia() {
217 continue;
218 }
219 if child.kind().is_punct() {
220 let mut prev = None;
221 for char in child.leaf_text().unwrap().chars() {
222 if let Some(char) = prev {
223 token_trees.push(
224 tt::Leaf::from(tt::Punct {
225 char,
226 spacing: tt::Spacing::Joint,
227 })
228 .into(),
229 );
230 }
231 prev = Some(char)
232 }
233 if let Some(char) = prev {
234 token_trees.push(
235 tt::Leaf::from(tt::Punct {
236 char,
237 spacing: tt::Spacing::Alone,
238 })
239 .into(),
240 );
241 }
242 } else {
243 let child: tt::TokenTree = if child.kind() == TOKEN_TREE {
244 convert_tt(child)?.into()
245 } else if child.kind().is_keyword() || child.kind() == IDENT {
246 let text = child.leaf_text().unwrap().clone();
247 tt::Leaf::from(tt::Ident { text }).into()
248 } else if child.kind().is_literal() {
249 tt::Leaf::from(tt::Literal {
250 text: child.leaf_text().unwrap().clone(),
251 })
252 .into()
253 } else {
254 log::error!("unknown kind: {:?}", child);
255 return None;
256 };
257 token_trees.push(child)
258 }
259 }
260
261 let res = tt::Subtree {
262 delimiter,
263 token_trees,
264 };
265 Some(res)
266}
267
268#[test]
269fn test_convert_tt() {
270 let macro_definition = r#"
271macro_rules! impl_froms {
272 ($e:ident: $($v:ident),*) => {
273 $(
274 impl From<$v> for $e {
275 fn from(it: $v) -> $e {
276 $e::$v(it)
277 }
278 }
279 )*
280 }
281}
282"#;
283
284 let macro_invocation = r#"
285impl_froms!(TokenTree: Leaf, Subtree);
286"#;
287
288 let source_file = ast::SourceFile::parse(macro_definition);
289 let macro_definition = source_file
290 .syntax()
291 .descendants()
292 .find_map(ast::MacroCall::cast)
293 .unwrap();
294
295 let source_file = ast::SourceFile::parse(macro_invocation);
296 let macro_invocation = source_file
297 .syntax()
298 .descendants()
299 .find_map(ast::MacroCall::cast)
300 .unwrap();
301
302 let definition_tt = macro_call_to_tt(macro_definition).unwrap();
303 let invocation_tt = macro_call_to_tt(macro_invocation).unwrap();
304 let mbe = mbe::parse(&definition_tt).unwrap();
305 let expansion = mbe::exapnd(&mbe, &invocation_tt).unwrap();
306 assert_eq!(
307 expansion.to_string(),
308 "{(impl From < Leaf > for TokenTree {fn from (it : Leaf) -> TokenTree {TokenTree :: Leaf (it)}}) \
309 (impl From < Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree :: Subtree (it)}})}"
310 )
311}