diff options
Diffstat (limited to 'crates/ra_hir_expand/src')
-rw-r--r-- | crates/ra_hir_expand/src/ast_id_map.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/proc_macro.rs | 106 |
3 files changed, 101 insertions, 15 deletions
diff --git a/crates/ra_hir_expand/src/ast_id_map.rs b/crates/ra_hir_expand/src/ast_id_map.rs index a3ca302c2..d19569245 100644 --- a/crates/ra_hir_expand/src/ast_id_map.rs +++ b/crates/ra_hir_expand/src/ast_id_map.rs | |||
@@ -66,7 +66,7 @@ impl AstIdMap { | |||
66 | // change parent's id. This means that, say, adding a new function to a | 66 | // change parent's id. This means that, say, adding a new function to a |
67 | // trait does not change ids of top-level items, which helps caching. | 67 | // trait does not change ids of top-level items, which helps caching. |
68 | bfs(node, |it| { | 68 | bfs(node, |it| { |
69 | if let Some(module_item) = ast::ModuleItem::cast(it.clone()) { | 69 | if let Some(module_item) = ast::ModuleItem::cast(it) { |
70 | res.alloc(module_item.syntax()); | 70 | res.alloc(module_item.syntax()); |
71 | } | 71 | } |
72 | }); | 72 | }); |
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index f9d3787f6..3da137f2e 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -301,7 +301,7 @@ fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Opti | |||
301 | } | 301 | } |
302 | 302 | ||
303 | // Extern paths ? | 303 | // Extern paths ? |
304 | let krate = db.relevant_crates(call_site).get(0)?.clone(); | 304 | let krate = *db.relevant_crates(call_site).get(0)?; |
305 | let (extern_source_id, relative_file) = | 305 | let (extern_source_id, relative_file) = |
306 | db.crate_graph()[krate].extern_source.extern_path(path)?; | 306 | db.crate_graph()[krate].extern_source.extern_path(path)?; |
307 | 307 | ||
@@ -329,7 +329,7 @@ fn include_expand( | |||
329 | 329 | ||
330 | // FIXME: | 330 | // FIXME: |
331 | // Handle include as expression | 331 | // Handle include as expression |
332 | let res = parse_to_token_tree(&db.file_text(file_id.into())) | 332 | let res = parse_to_token_tree(&db.file_text(file_id)) |
333 | .ok_or_else(|| mbe::ExpandError::ConversionError)? | 333 | .ok_or_else(|| mbe::ExpandError::ConversionError)? |
334 | .0; | 334 | .0; |
335 | 335 | ||
@@ -340,7 +340,7 @@ fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Optio | |||
340 | let call_id: MacroCallId = arg_id.into(); | 340 | let call_id: MacroCallId = arg_id.into(); |
341 | let original_file = call_id.as_file().original_file(db); | 341 | let original_file = call_id.as_file().original_file(db); |
342 | 342 | ||
343 | let krate = db.relevant_crates(original_file).get(0)?.clone(); | 343 | let krate = *db.relevant_crates(original_file).get(0)?; |
344 | db.crate_graph()[krate].env.get(key) | 344 | db.crate_graph()[krate].env.get(key) |
345 | } | 345 | } |
346 | 346 | ||
@@ -447,7 +447,7 @@ mod tests { | |||
447 | file_id: file_id.into(), | 447 | file_id: file_id.into(), |
448 | }; | 448 | }; |
449 | 449 | ||
450 | let id: MacroCallId = db.intern_eager_expansion(eager.into()).into(); | 450 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); |
451 | id.as_file() | 451 | id.as_file() |
452 | } | 452 | } |
453 | }; | 453 | }; |
diff --git a/crates/ra_hir_expand/src/proc_macro.rs b/crates/ra_hir_expand/src/proc_macro.rs index 97d1208ec..4e0e069c8 100644 --- a/crates/ra_hir_expand/src/proc_macro.rs +++ b/crates/ra_hir_expand/src/proc_macro.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | use crate::{db::AstDatabase, LazyMacroId}; | 3 | use crate::{db::AstDatabase, LazyMacroId}; |
4 | use ra_db::{CrateId, ProcMacroId}; | 4 | use ra_db::{CrateId, ProcMacroId}; |
5 | use tt::buffer::{Cursor, TokenBuffer}; | ||
5 | 6 | ||
6 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] | 7 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] |
7 | pub struct ProcMacroExpander { | 8 | pub struct ProcMacroExpander { |
@@ -36,22 +37,107 @@ impl ProcMacroExpander { | |||
36 | .clone() | 37 | .clone() |
37 | .ok_or_else(|| err!("No derive macro found."))?; | 38 | .ok_or_else(|| err!("No derive macro found."))?; |
38 | 39 | ||
39 | let tt = remove_derive_atr(tt, &proc_macro.name) | 40 | let tt = remove_derive_attrs(tt) |
40 | .ok_or_else(|| err!("Fail to remove derive for custom derive"))?; | 41 | .ok_or_else(|| err!("Fail to remove derive for custom derive"))?; |
41 | 42 | ||
42 | proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from) | 43 | proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from) |
43 | } | 44 | } |
44 | } | 45 | } |
45 | 46 | ||
46 | fn remove_derive_atr(tt: &tt::Subtree, _name: &str) -> Option<tt::Subtree> { | 47 | fn eat_punct(cursor: &mut Cursor, c: char) -> bool { |
47 | // FIXME: proper handle the remove derive | 48 | if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = cursor.token_tree() { |
48 | // We assume the first 2 tokens are #[derive(name)] | 49 | if punct.char == c { |
49 | if tt.token_trees.len() > 2 { | 50 | *cursor = cursor.bump(); |
50 | let mut tt = tt.clone(); | 51 | return true; |
51 | tt.token_trees.remove(0); | 52 | } |
52 | tt.token_trees.remove(0); | ||
53 | return Some(tt); | ||
54 | } | 53 | } |
54 | false | ||
55 | } | ||
56 | |||
57 | fn eat_subtree(cursor: &mut Cursor, kind: tt::DelimiterKind) -> bool { | ||
58 | if let Some(tt::TokenTree::Subtree(subtree)) = cursor.token_tree() { | ||
59 | if Some(kind) == subtree.delimiter_kind() { | ||
60 | *cursor = cursor.bump_subtree(); | ||
61 | return true; | ||
62 | } | ||
63 | } | ||
64 | false | ||
65 | } | ||
66 | |||
67 | fn eat_ident(cursor: &mut Cursor, t: &str) -> bool { | ||
68 | if let Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) = cursor.token_tree() { | ||
69 | if t == ident.text.as_str() { | ||
70 | *cursor = cursor.bump(); | ||
71 | return true; | ||
72 | } | ||
73 | } | ||
74 | false | ||
75 | } | ||
76 | |||
77 | fn remove_derive_attrs(tt: &tt::Subtree) -> Option<tt::Subtree> { | ||
78 | let buffer = TokenBuffer::new(&tt.token_trees); | ||
79 | let mut p = buffer.begin(); | ||
80 | let mut result = tt::Subtree::default(); | ||
81 | |||
82 | while !p.eof() { | ||
83 | let curr = p; | ||
55 | 84 | ||
56 | None | 85 | if eat_punct(&mut p, '#') { |
86 | eat_punct(&mut p, '!'); | ||
87 | let parent = p; | ||
88 | if eat_subtree(&mut p, tt::DelimiterKind::Bracket) { | ||
89 | if eat_ident(&mut p, "derive") { | ||
90 | p = parent.bump(); | ||
91 | continue; | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | |||
96 | result.token_trees.push(curr.token_tree()?.clone()); | ||
97 | p = curr.bump(); | ||
98 | } | ||
99 | |||
100 | Some(result) | ||
101 | } | ||
102 | |||
103 | #[cfg(test)] | ||
104 | mod test { | ||
105 | use super::*; | ||
106 | use test_utils::assert_eq_text; | ||
107 | |||
108 | #[test] | ||
109 | fn test_remove_derive_attrs() { | ||
110 | let tt = mbe::parse_to_token_tree( | ||
111 | r#" | ||
112 | #[allow(unused)] | ||
113 | #[derive(Copy)] | ||
114 | #[derive(Hello)] | ||
115 | struct A { | ||
116 | bar: u32 | ||
117 | } | ||
118 | "#, | ||
119 | ) | ||
120 | .unwrap() | ||
121 | .0; | ||
122 | let result = format!("{:#?}", remove_derive_attrs(&tt).unwrap()); | ||
123 | |||
124 | assert_eq_text!( | ||
125 | &result, | ||
126 | r#" | ||
127 | SUBTREE $ | ||
128 | PUNCH # [alone] 0 | ||
129 | SUBTREE [] 1 | ||
130 | IDENT allow 2 | ||
131 | SUBTREE () 3 | ||
132 | IDENT unused 4 | ||
133 | IDENT struct 15 | ||
134 | IDENT A 16 | ||
135 | SUBTREE {} 17 | ||
136 | IDENT bar 18 | ||
137 | PUNCH : [alone] 19 | ||
138 | IDENT u32 20 | ||
139 | "# | ||
140 | .trim() | ||
141 | ); | ||
142 | } | ||
57 | } | 143 | } |