aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_expand
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_expand')
-rw-r--r--crates/ra_hir_expand/src/builtin_derive.rs22
-rw-r--r--crates/ra_hir_expand/src/db.rs11
-rw-r--r--crates/ra_hir_expand/src/eager.rs20
-rw-r--r--crates/ra_hir_expand/src/hygiene.rs1
-rw-r--r--crates/ra_hir_expand/src/lib.rs13
-rw-r--r--crates/ra_hir_expand/src/proc_macro.rs33
6 files changed, 71 insertions, 29 deletions
diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs
index a5b50a832..79aea5806 100644
--- a/crates/ra_hir_expand/src/builtin_derive.rs
+++ b/crates/ra_hir_expand/src/builtin_derive.rs
@@ -229,9 +229,12 @@ fn partial_ord_expand(
229mod tests { 229mod tests {
230 use super::*; 230 use super::*;
231 use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; 231 use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc};
232 use name::{known, Name};
232 use ra_db::{fixture::WithFixture, SourceDatabase}; 233 use ra_db::{fixture::WithFixture, SourceDatabase};
233 234
234 fn expand_builtin_derive(s: &str, expander: BuiltinDeriveExpander) -> String { 235 fn expand_builtin_derive(s: &str, name: Name) -> String {
236 let def = find_builtin_derive(&name).unwrap();
237
235 let (db, file_id) = TestDB::with_single_file(&s); 238 let (db, file_id) = TestDB::with_single_file(&s);
236 let parsed = db.parse(file_id); 239 let parsed = db.parse(file_id);
237 let items: Vec<_> = 240 let items: Vec<_> =
@@ -239,14 +242,9 @@ mod tests {
239 242
240 let ast_id_map = db.ast_id_map(file_id.into()); 243 let ast_id_map = db.ast_id_map(file_id.into());
241 244
242 // the first one should be a macro_rules 245 let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0]));
243 let def =
244 MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(expander) };
245 246
246 let loc = MacroCallLoc { 247 let loc = MacroCallLoc { def, kind: MacroCallKind::Attr(attr_id, name.to_string()) };
247 def,
248 kind: MacroCallKind::Attr(AstId::new(file_id.into(), ast_id_map.ast_id(&items[0]))),
249 };
250 248
251 let id: MacroCallId = db.intern_macro(loc).into(); 249 let id: MacroCallId = db.intern_macro(loc).into();
252 let parsed = db.parse_or_expand(id.as_file()).unwrap(); 250 let parsed = db.parse_or_expand(id.as_file()).unwrap();
@@ -263,7 +261,7 @@ mod tests {
263 #[derive(Copy)] 261 #[derive(Copy)]
264 struct Foo; 262 struct Foo;
265"#, 263"#,
266 BuiltinDeriveExpander::Copy, 264 known::Copy,
267 ); 265 );
268 266
269 assert_eq!(expanded, "impl< >std::marker::CopyforFoo< >{}"); 267 assert_eq!(expanded, "impl< >std::marker::CopyforFoo< >{}");
@@ -276,7 +274,7 @@ mod tests {
276 #[derive(Copy)] 274 #[derive(Copy)]
277 struct Foo<A, B>; 275 struct Foo<A, B>;
278"#, 276"#,
279 BuiltinDeriveExpander::Copy, 277 known::Copy,
280 ); 278 );
281 279
282 assert_eq!( 280 assert_eq!(
@@ -292,7 +290,7 @@ mod tests {
292 #[derive(Copy)] 290 #[derive(Copy)]
293 struct Foo<A, B, 'a, 'b>; 291 struct Foo<A, B, 'a, 'b>;
294"#, 292"#,
295 BuiltinDeriveExpander::Copy, 293 known::Copy,
296 ); 294 );
297 295
298 // We currently just ignore lifetimes 296 // We currently just ignore lifetimes
@@ -310,7 +308,7 @@ mod tests {
310 #[derive(Clone)] 308 #[derive(Clone)]
311 struct Foo<A, B>; 309 struct Foo<A, B>;
312"#, 310"#,
313 BuiltinDeriveExpander::Clone, 311 known::Clone,
314 ); 312 );
315 313
316 assert_eq!( 314 assert_eq!(
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs
index 5a696542f..047452306 100644
--- a/crates/ra_hir_expand/src/db.rs
+++ b/crates/ra_hir_expand/src/db.rs
@@ -11,7 +11,7 @@ use ra_syntax::{algo::diff, AstNode, Parse, SyntaxKind::*, SyntaxNode};
11use crate::{ 11use crate::{
12 ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId, 12 ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId,
13 HirFileId, HirFileIdRepr, LazyMacroId, MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, 13 HirFileId, HirFileIdRepr, LazyMacroId, MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind,
14 MacroFile, 14 MacroFile, ProcMacroExpander,
15}; 15};
16 16
17#[derive(Debug, Clone, Eq, PartialEq)] 17#[derive(Debug, Clone, Eq, PartialEq)]
@@ -19,6 +19,7 @@ pub enum TokenExpander {
19 MacroRules(mbe::MacroRules), 19 MacroRules(mbe::MacroRules),
20 Builtin(BuiltinFnLikeExpander), 20 Builtin(BuiltinFnLikeExpander),
21 BuiltinDerive(BuiltinDeriveExpander), 21 BuiltinDerive(BuiltinDeriveExpander),
22 ProcMacro(ProcMacroExpander),
22} 23}
23 24
24impl TokenExpander { 25impl TokenExpander {
@@ -33,6 +34,7 @@ impl TokenExpander {
33 // FIXME switch these to ExpandResult as well 34 // FIXME switch these to ExpandResult as well
34 TokenExpander::Builtin(it) => it.expand(db, id, tt).into(), 35 TokenExpander::Builtin(it) => it.expand(db, id, tt).into(),
35 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), 36 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
37 TokenExpander::ProcMacro(it) => it.expand(db, id, tt).into(),
36 } 38 }
37 } 39 }
38 40
@@ -41,6 +43,7 @@ impl TokenExpander {
41 TokenExpander::MacroRules(it) => it.map_id_down(id), 43 TokenExpander::MacroRules(it) => it.map_id_down(id),
42 TokenExpander::Builtin(..) => id, 44 TokenExpander::Builtin(..) => id,
43 TokenExpander::BuiltinDerive(..) => id, 45 TokenExpander::BuiltinDerive(..) => id,
46 TokenExpander::ProcMacro(..) => id,
44 } 47 }
45 } 48 }
46 49
@@ -49,6 +52,7 @@ impl TokenExpander {
49 TokenExpander::MacroRules(it) => it.map_id_up(id), 52 TokenExpander::MacroRules(it) => it.map_id_up(id),
50 TokenExpander::Builtin(..) => (id, mbe::Origin::Call), 53 TokenExpander::Builtin(..) => (id, mbe::Origin::Call),
51 TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Call), 54 TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Call),
55 TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call),
52 } 56 }
53 } 57 }
54} 58}
@@ -130,7 +134,10 @@ pub(crate) fn macro_def(
130 MacroDefKind::BuiltInDerive(expander) => { 134 MacroDefKind::BuiltInDerive(expander) => {
131 Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default()))) 135 Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default())))
132 } 136 }
133 MacroDefKind::BuiltInEager(_expander) => None, 137 MacroDefKind::BuiltInEager(_) => None,
138 MacroDefKind::CustomDerive(expander) => {
139 Some(Arc::new((TokenExpander::ProcMacro(expander), mbe::TokenMap::default())))
140 }
134 } 141 }
135} 142}
136 143
diff --git a/crates/ra_hir_expand/src/eager.rs b/crates/ra_hir_expand/src/eager.rs
index 4cbce4df5..932f47c30 100644
--- a/crates/ra_hir_expand/src/eager.rs
+++ b/crates/ra_hir_expand/src/eager.rs
@@ -26,8 +26,8 @@ use crate::{
26}; 26};
27 27
28use ra_parser::FragmentKind; 28use ra_parser::FragmentKind;
29use ra_syntax::{algo::replace_descendants, SyntaxElement, SyntaxNode}; 29use ra_syntax::{algo::SyntaxRewriter, SyntaxNode};
30use std::{collections::HashMap, sync::Arc}; 30use std::sync::Arc;
31 31
32pub fn expand_eager_macro( 32pub fn expand_eager_macro(
33 db: &dyn AstDatabase, 33 db: &dyn AstDatabase,
@@ -95,10 +95,10 @@ fn eager_macro_recur(
95 curr: InFile<SyntaxNode>, 95 curr: InFile<SyntaxNode>,
96 macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, 96 macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>,
97) -> Option<SyntaxNode> { 97) -> Option<SyntaxNode> {
98 let mut original = curr.value.clone(); 98 let original = curr.value.clone();
99 99
100 let children = curr.value.descendants().filter_map(ast::MacroCall::cast); 100 let children = curr.value.descendants().filter_map(ast::MacroCall::cast);
101 let mut replaces: HashMap<SyntaxElement, SyntaxElement> = HashMap::default(); 101 let mut rewriter = SyntaxRewriter::default();
102 102
103 // Collect replacement 103 // Collect replacement
104 for child in children { 104 for child in children {
@@ -112,19 +112,17 @@ fn eager_macro_recur(
112 } 112 }
113 MacroDefKind::Declarative 113 MacroDefKind::Declarative
114 | MacroDefKind::BuiltIn(_) 114 | MacroDefKind::BuiltIn(_)
115 | MacroDefKind::BuiltInDerive(_) => { 115 | MacroDefKind::BuiltInDerive(_)
116 | MacroDefKind::CustomDerive(_) => {
116 let expanded = lazy_expand(db, &def, curr.with_value(child.clone()))?; 117 let expanded = lazy_expand(db, &def, curr.with_value(child.clone()))?;
117 // replace macro inside 118 // replace macro inside
118 eager_macro_recur(db, expanded, macro_resolver)? 119 eager_macro_recur(db, expanded, macro_resolver)?
119 } 120 }
120 }; 121 };
121 122
122 replaces.insert(child.syntax().clone().into(), insert.into()); 123 rewriter.replace(child.syntax(), &insert);
123 } 124 }
124 125
125 if !replaces.is_empty() { 126 let res = rewriter.rewrite(&original);
126 original = replace_descendants(&original, |n| replaces.get(n).cloned()); 127 Some(res)
127 }
128
129 Some(original)
130} 128}
diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs
index dfbac494f..0b41d0e95 100644
--- a/crates/ra_hir_expand/src/hygiene.rs
+++ b/crates/ra_hir_expand/src/hygiene.rs
@@ -30,6 +30,7 @@ impl Hygiene {
30 MacroDefKind::BuiltIn(_) => None, 30 MacroDefKind::BuiltIn(_) => None,
31 MacroDefKind::BuiltInDerive(_) => None, 31 MacroDefKind::BuiltInDerive(_) => None,
32 MacroDefKind::BuiltInEager(_) => None, 32 MacroDefKind::BuiltInEager(_) => None,
33 MacroDefKind::CustomDerive(_) => None,
33 } 34 }
34 } 35 }
35 MacroCallId::EagerMacro(_id) => None, 36 MacroCallId::EagerMacro(_id) => None,
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs
index 6b59ea4c9..86299459f 100644
--- a/crates/ra_hir_expand/src/lib.rs
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -11,6 +11,7 @@ pub mod hygiene;
11pub mod diagnostics; 11pub mod diagnostics;
12pub mod builtin_derive; 12pub mod builtin_derive;
13pub mod builtin_macro; 13pub mod builtin_macro;
14pub mod proc_macro;
14pub mod quote; 15pub mod quote;
15pub mod eager; 16pub mod eager;
16 17
@@ -27,6 +28,7 @@ use ra_syntax::{
27use crate::ast_id_map::FileAstId; 28use crate::ast_id_map::FileAstId;
28use crate::builtin_derive::BuiltinDeriveExpander; 29use crate::builtin_derive::BuiltinDeriveExpander;
29use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander}; 30use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander};
31use crate::proc_macro::ProcMacroExpander;
30 32
31#[cfg(test)] 33#[cfg(test)]
32mod test_db; 34mod test_db;
@@ -217,6 +219,7 @@ pub enum MacroDefKind {
217 // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander 219 // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander
218 BuiltInDerive(BuiltinDeriveExpander), 220 BuiltInDerive(BuiltinDeriveExpander),
219 BuiltInEager(EagerExpander), 221 BuiltInEager(EagerExpander),
222 CustomDerive(ProcMacroExpander),
220} 223}
221 224
222#[derive(Debug, Clone, PartialEq, Eq, Hash)] 225#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -228,21 +231,23 @@ pub struct MacroCallLoc {
228#[derive(Debug, Clone, PartialEq, Eq, Hash)] 231#[derive(Debug, Clone, PartialEq, Eq, Hash)]
229pub enum MacroCallKind { 232pub enum MacroCallKind {
230 FnLike(AstId<ast::MacroCall>), 233 FnLike(AstId<ast::MacroCall>),
231 Attr(AstId<ast::ModuleItem>), 234 Attr(AstId<ast::ModuleItem>, String),
232} 235}
233 236
234impl MacroCallKind { 237impl MacroCallKind {
235 pub fn file_id(&self) -> HirFileId { 238 pub fn file_id(&self) -> HirFileId {
236 match self { 239 match self {
237 MacroCallKind::FnLike(ast_id) => ast_id.file_id, 240 MacroCallKind::FnLike(ast_id) => ast_id.file_id,
238 MacroCallKind::Attr(ast_id) => ast_id.file_id, 241 MacroCallKind::Attr(ast_id, _) => ast_id.file_id,
239 } 242 }
240 } 243 }
241 244
242 pub fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> { 245 pub fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> {
243 match self { 246 match self {
244 MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), 247 MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()),
245 MacroCallKind::Attr(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), 248 MacroCallKind::Attr(ast_id, _) => {
249 ast_id.with_value(ast_id.to_node(db).syntax().clone())
250 }
246 } 251 }
247 } 252 }
248 253
@@ -251,7 +256,7 @@ impl MacroCallKind {
251 MacroCallKind::FnLike(ast_id) => { 256 MacroCallKind::FnLike(ast_id) => {
252 Some(ast_id.to_node(db).token_tree()?.syntax().clone()) 257 Some(ast_id.to_node(db).token_tree()?.syntax().clone())
253 } 258 }
254 MacroCallKind::Attr(ast_id) => Some(ast_id.to_node(db).syntax().clone()), 259 MacroCallKind::Attr(ast_id, _) => Some(ast_id.to_node(db).syntax().clone()),
255 } 260 }
256 } 261 }
257} 262}
diff --git a/crates/ra_hir_expand/src/proc_macro.rs b/crates/ra_hir_expand/src/proc_macro.rs
new file mode 100644
index 000000000..a8dee2052
--- /dev/null
+++ b/crates/ra_hir_expand/src/proc_macro.rs
@@ -0,0 +1,33 @@
1//! Proc Macro Expander stub
2
3use crate::{db::AstDatabase, LazyMacroId, MacroCallKind, MacroCallLoc};
4use ra_db::CrateId;
5
6#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
7pub struct ProcMacroExpander {
8 krate: CrateId,
9}
10
11impl ProcMacroExpander {
12 pub fn new(krate: CrateId) -> ProcMacroExpander {
13 ProcMacroExpander { krate }
14 }
15
16 pub fn expand(
17 &self,
18 db: &dyn AstDatabase,
19 id: LazyMacroId,
20 _tt: &tt::Subtree,
21 ) -> Result<tt::Subtree, mbe::ExpandError> {
22 let loc: MacroCallLoc = db.lookup_intern_macro(id);
23 let name = match loc.kind {
24 MacroCallKind::FnLike(_) => return Err(mbe::ExpandError::ConversionError),
25 MacroCallKind::Attr(_, name) => name,
26 };
27
28 log::debug!("Proc-macro-expanding name = {}", name);
29
30 // Return nothing for now
31 return Ok(tt::Subtree::default());
32 }
33}