diff options
author | Edwin Cheng <[email protected]> | 2020-03-18 09:47:59 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2020-03-25 11:50:12 +0000 |
commit | 34dc8d25c1e461cc311d6d4404f74502513cd3ae (patch) | |
tree | 00aab26b07c1cd42dfa350eeddc6c41e5bea178b | |
parent | e2dd17f75b1bb5e1185acff66211e74430177592 (diff) |
Add basic custom derive lowering
-rw-r--r-- | Cargo.lock | 8 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 60 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/builtin_derive.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/eager.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/hygiene.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/lib.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/proc_macro.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/macros.rs | 23 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 2 |
11 files changed, 152 insertions, 28 deletions
diff --git a/Cargo.lock b/Cargo.lock index 908319f87..d61343657 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -1082,6 +1082,14 @@ dependencies = [ | |||
1082 | ] | 1082 | ] |
1083 | 1083 | ||
1084 | [[package]] | 1084 | [[package]] |
1085 | name = "ra_proc_macro" | ||
1086 | version = "0.1.0" | ||
1087 | dependencies = [ | ||
1088 | "ra_mbe", | ||
1089 | "ra_tt", | ||
1090 | ] | ||
1091 | |||
1092 | [[package]] | ||
1085 | name = "ra_prof" | 1093 | name = "ra_prof" |
1086 | version = "0.1.0" | 1094 | version = "0.1.0" |
1087 | dependencies = [ | 1095 | dependencies = [ |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 516dd773e..b3e811671 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -475,6 +475,9 @@ impl AsMacroCall for AstIdWithPath<ast::ModuleItem> { | |||
475 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 475 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
476 | ) -> Option<MacroCallId> { | 476 | ) -> Option<MacroCallId> { |
477 | let def = resolver(self.path.clone())?; | 477 | let def = resolver(self.path.clone())?; |
478 | Some(def.as_lazy_macro(db.upcast(), MacroCallKind::Attr(self.ast_id)).into()) | 478 | Some( |
479 | def.as_lazy_macro(db.upcast(), MacroCallKind::Attr(self.ast_id, self.path.to_string())) | ||
480 | .into(), | ||
481 | ) | ||
479 | } | 482 | } |
480 | } | 483 | } |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 5b292c250..76be71a30 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -7,6 +7,7 @@ use hir_expand::{ | |||
7 | builtin_derive::find_builtin_derive, | 7 | builtin_derive::find_builtin_derive, |
8 | builtin_macro::find_builtin_macro, | 8 | builtin_macro::find_builtin_macro, |
9 | name::{name, AsName, Name}, | 9 | name::{name, AsName, Name}, |
10 | proc_macro::ProcMacroExpander, | ||
10 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, | 11 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, |
11 | }; | 12 | }; |
12 | use ra_cfg::CfgOptions; | 13 | use ra_cfg::CfgOptions; |
@@ -238,6 +239,18 @@ impl DefCollector<'_> { | |||
238 | self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); | 239 | self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); |
239 | } | 240 | } |
240 | 241 | ||
242 | /// Define a proc macro | ||
243 | /// | ||
244 | /// A proc macro is similar to normal macro scope, but it would not visiable in legacy textual scoped. | ||
245 | /// And unconditionally exported. | ||
246 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { | ||
247 | self.update( | ||
248 | self.def_map.root, | ||
249 | &[(name, PerNs::macros(macro_, Visibility::Public))], | ||
250 | Visibility::Public, | ||
251 | ); | ||
252 | } | ||
253 | |||
241 | /// Import macros from `#[macro_use] extern crate`. | 254 | /// Import macros from `#[macro_use] extern crate`. |
242 | fn import_macros_from_extern_crate( | 255 | fn import_macros_from_extern_crate( |
243 | &mut self, | 256 | &mut self, |
@@ -537,8 +550,9 @@ impl DefCollector<'_> { | |||
537 | true | 550 | true |
538 | }); | 551 | }); |
539 | attribute_macros.retain(|directive| { | 552 | attribute_macros.retain(|directive| { |
540 | if let Some(call_id) = | 553 | if let Some(call_id) = directive |
541 | directive.ast_id.as_call_id(self.db, |path| self.resolve_attribute_macro(&path)) | 554 | .ast_id |
555 | .as_call_id(self.db, |path| self.resolve_attribute_macro(&directive, &path)) | ||
542 | { | 556 | { |
543 | resolved.push((directive.module_id, call_id, 0)); | 557 | resolved.push((directive.module_id, call_id, 0)); |
544 | res = ReachedFixedPoint::No; | 558 | res = ReachedFixedPoint::No; |
@@ -562,9 +576,11 @@ impl DefCollector<'_> { | |||
562 | res | 576 | res |
563 | } | 577 | } |
564 | 578 | ||
565 | fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> { | 579 | fn resolve_attribute_macro( |
566 | // FIXME this is currently super hacky, just enough to support the | 580 | &self, |
567 | // built-in derives | 581 | directive: &DeriveDirective, |
582 | path: &ModPath, | ||
583 | ) -> Option<MacroDefId> { | ||
568 | if let Some(name) = path.as_ident() { | 584 | if let Some(name) = path.as_ident() { |
569 | // FIXME this should actually be handled with the normal name | 585 | // FIXME this should actually be handled with the normal name |
570 | // resolution; the std lib defines built-in stubs for the derives, | 586 | // resolution; the std lib defines built-in stubs for the derives, |
@@ -573,7 +589,15 @@ impl DefCollector<'_> { | |||
573 | return Some(def_id); | 589 | return Some(def_id); |
574 | } | 590 | } |
575 | } | 591 | } |
576 | None | 592 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
593 | self.db, | ||
594 | ResolveMode::Other, | ||
595 | directive.module_id, | ||
596 | &path, | ||
597 | BuiltinShadowMode::Module, | ||
598 | ); | ||
599 | |||
600 | resolved_res.resolved_def.take_macros() | ||
577 | } | 601 | } |
578 | 602 | ||
579 | fn collect_macro_expansion( | 603 | fn collect_macro_expansion( |
@@ -776,8 +800,8 @@ impl ModCollector<'_, '_> { | |||
776 | // FIXME: check attrs to see if this is an attribute macro invocation; | 800 | // FIXME: check attrs to see if this is an attribute macro invocation; |
777 | // in which case we don't add the invocation, just a single attribute | 801 | // in which case we don't add the invocation, just a single attribute |
778 | // macro invocation | 802 | // macro invocation |
779 | |||
780 | self.collect_derives(attrs, def); | 803 | self.collect_derives(attrs, def); |
804 | self.collect_proc_macro(attrs); | ||
781 | 805 | ||
782 | let name = def.name.clone(); | 806 | let name = def.name.clone(); |
783 | let container = ContainerId::ModuleId(module); | 807 | let container = ContainerId::ModuleId(module); |
@@ -854,6 +878,28 @@ impl ModCollector<'_, '_> { | |||
854 | } | 878 | } |
855 | } | 879 | } |
856 | 880 | ||
881 | fn collect_proc_macro(&mut self, attrs: &Attrs) { | ||
882 | if let Some(derive_subtree) = attrs.by_key("proc_macro_derive").tt_values().next() { | ||
883 | if let Some(tt) = derive_subtree.token_trees.get(0) { | ||
884 | let ident = match &tt { | ||
885 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident, | ||
886 | _ => return, // anything else would be an error (which we currently ignore) | ||
887 | }; | ||
888 | let name = ident.as_name(); | ||
889 | let krate = self.def_collector.def_map.krate; | ||
890 | let expander = ProcMacroExpander::new(krate); | ||
891 | |||
892 | let macro_id = MacroDefId { | ||
893 | ast_id: None, | ||
894 | krate: Some(krate), | ||
895 | kind: MacroDefKind::ProcMacro(expander), | ||
896 | }; | ||
897 | |||
898 | self.def_collector.define_proc_macro(name.clone(), macro_id); | ||
899 | } | ||
900 | } | ||
901 | } | ||
902 | |||
857 | fn collect_macro(&mut self, mac: &raw::MacroData) { | 903 | fn collect_macro(&mut self, mac: &raw::MacroData) { |
858 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); | 904 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); |
859 | 905 | ||
diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index a5b50a832..7f753bbca 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( | |||
229 | mod tests { | 229 | mod 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::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 | name::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 | name::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 | name::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 | name::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..c2eb75ee5 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}; | |||
11 | use crate::{ | 11 | use 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 | ||
24 | impl TokenExpander { | 25 | impl 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::ProcMacro(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 687d40294..9ff743b9e 100644 --- a/crates/ra_hir_expand/src/eager.rs +++ b/crates/ra_hir_expand/src/eager.rs | |||
@@ -112,7 +112,8 @@ 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::ProcMacro(_) => { | ||
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)? |
diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs index dfbac494f..182c08eb3 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::ProcMacro(_) => 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..ac1d12252 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -11,6 +11,7 @@ pub mod hygiene; | |||
11 | pub mod diagnostics; | 11 | pub mod diagnostics; |
12 | pub mod builtin_derive; | 12 | pub mod builtin_derive; |
13 | pub mod builtin_macro; | 13 | pub mod builtin_macro; |
14 | pub mod proc_macro; | ||
14 | pub mod quote; | 15 | pub mod quote; |
15 | pub mod eager; | 16 | pub mod eager; |
16 | 17 | ||
@@ -27,6 +28,7 @@ use ra_syntax::{ | |||
27 | use crate::ast_id_map::FileAstId; | 28 | use crate::ast_id_map::FileAstId; |
28 | use crate::builtin_derive::BuiltinDeriveExpander; | 29 | use crate::builtin_derive::BuiltinDeriveExpander; |
29 | use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander}; | 30 | use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander}; |
31 | use crate::proc_macro::ProcMacroExpander; | ||
30 | 32 | ||
31 | #[cfg(test)] | 33 | #[cfg(test)] |
32 | mod test_db; | 34 | mod 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 | ProcMacro(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)] |
229 | pub enum MacroCallKind { | 232 | pub 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 | ||
234 | impl MacroCallKind { | 237 | impl 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..68c828790 --- /dev/null +++ b/crates/ra_hir_expand/src/proc_macro.rs | |||
@@ -0,0 +1,32 @@ | |||
1 | //! Proc Macro Expander stub | ||
2 | |||
3 | use crate::{db::AstDatabase, LazyMacroId, MacroCallKind, MacroCallLoc}; | ||
4 | use ra_db::CrateId; | ||
5 | |||
6 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] | ||
7 | pub struct ProcMacroExpander { | ||
8 | krate: CrateId, | ||
9 | } | ||
10 | |||
11 | impl 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 | dbg!(name); | ||
29 | |||
30 | unimplemented!() | ||
31 | } | ||
32 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 2e309a379..d59e4eea6 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs | |||
@@ -639,3 +639,26 @@ mod clone { | |||
639 | ); | 639 | ); |
640 | assert_eq!("(Wrapper<S>, {unknown})", type_at_pos(&db, pos)); | 640 | assert_eq!("(Wrapper<S>, {unknown})", type_at_pos(&db, pos)); |
641 | } | 641 | } |
642 | |||
643 | #[test] | ||
644 | fn infer_custom_derive_simple() { | ||
645 | let (db, pos) = TestDB::with_position( | ||
646 | r#" | ||
647 | //- /main.rs crate:main deps:foo | ||
648 | use foo::Foo; | ||
649 | |||
650 | #[derive(Foo)] | ||
651 | struct S{} | ||
652 | |||
653 | fn test() { | ||
654 | S{}<|>; | ||
655 | } | ||
656 | |||
657 | //- /lib.rs crate:foo | ||
658 | #[proc_macro_derive(Foo)] | ||
659 | pub fn derive_foo(_item: TokenStream) -> TokenStream { | ||
660 | } | ||
661 | "#, | ||
662 | ); | ||
663 | assert_eq!("S", type_at_pos(&db, pos)); | ||
664 | } | ||
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index e3cde9eed..8e8ae2b29 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -33,7 +33,7 @@ impl TokenTextRange { | |||
33 | } | 33 | } |
34 | 34 | ||
35 | /// Maps `tt::TokenId` to the relative range of the original token. | 35 | /// Maps `tt::TokenId` to the relative range of the original token. |
36 | #[derive(Debug, PartialEq, Eq, Default)] | 36 | #[derive(Debug, PartialEq, Eq, Clone, Default)] |
37 | pub struct TokenMap { | 37 | pub struct TokenMap { |
38 | /// Maps `tt::TokenId` to the *relative* source range. | 38 | /// Maps `tt::TokenId` to the *relative* source range. |
39 | entries: Vec<(tt::TokenId, TokenTextRange)>, | 39 | entries: Vec<(tt::TokenId, TokenTextRange)>, |