aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock8
-rw-r--r--crates/ra_hir_def/src/lib.rs5
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs60
-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.rs3
-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.rs32
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs23
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs2
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]]
1085name = "ra_proc_macro"
1086version = "0.1.0"
1087dependencies = [
1088 "ra_mbe",
1089 "ra_tt",
1090]
1091
1092[[package]]
1085name = "ra_prof" 1093name = "ra_prof"
1086version = "0.1.0" 1094version = "0.1.0"
1087dependencies = [ 1095dependencies = [
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};
12use ra_cfg::CfgOptions; 13use 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(
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::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};
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::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;
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 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)]
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..68c828790
--- /dev/null
+++ b/crates/ra_hir_expand/src/proc_macro.rs
@@ -0,0 +1,32 @@
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 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]
644fn infer_custom_derive_simple() {
645 let (db, pos) = TestDB::with_position(
646 r#"
647//- /main.rs crate:main deps:foo
648use foo::Foo;
649
650#[derive(Foo)]
651struct S{}
652
653fn test() {
654 S{}<|>;
655}
656
657//- /lib.rs crate:foo
658#[proc_macro_derive(Foo)]
659pub 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)]
37pub struct TokenMap { 37pub 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)>,