diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-06-03 17:17:25 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-06-03 17:17:25 +0100 |
commit | 14153671caaca852c94bd1d0d7f279acb8eb1913 (patch) | |
tree | eb377999a5e8677c210791440b18593f909198e6 /crates/hir_def/src/nameres | |
parent | 7f9c4a59d9a84cd8c734286937439b5cd215be27 (diff) | |
parent | 17565f4deafab800d8d87208cff1e27d028e9b0e (diff) |
Merge #9128
9128: feat: expand procedural attribute macros r=jonas-schievink a=jonas-schievink
This adds experimental support for attribute macros. They can be enabled by setting `rust-analyzer.experimental.procAttrMacros` to `true`.
Known issues:
* Tokens aren't remapped, presumably because we edit the input syntax tree (this causes IDE features to not work inside items with attribute macros on them)
* Macro errors aren't reported correctly
Closes https://github.com/rust-analyzer/rust-analyzer/issues/8971
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/8964 / https://github.com/la10736/rstest/issues/120
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/2984
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/5412
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/6029
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/6687
https://github.com/rust-analyzer/rust-analyzer/issues/6740 is still not fixed – we now expand `#[proc_macro_hack]`, but fail to expand the resulting `proc_macro_call!()` macro.
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/hir_def/src/nameres')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 6b41921ae..b2ce739bd 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -23,7 +23,7 @@ use syntax::ast; | |||
23 | 23 | ||
24 | use crate::{ | 24 | use crate::{ |
25 | attr::{Attr, AttrId, AttrInput, Attrs}, | 25 | attr::{Attr, AttrId, AttrInput, Attrs}, |
26 | builtin_attr, | 26 | attr_macro_as_call_id, builtin_attr, |
27 | db::DefDatabase, | 27 | db::DefDatabase, |
28 | derive_macro_as_call_id, | 28 | derive_macro_as_call_id, |
29 | intern::Interned, | 29 | intern::Interned, |
@@ -223,7 +223,7 @@ struct MacroDirective { | |||
223 | enum MacroDirectiveKind { | 223 | enum MacroDirectiveKind { |
224 | FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind }, | 224 | FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind }, |
225 | Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, | 225 | Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, |
226 | Attr { ast_id: AstIdWithPath<ast::Item>, attr: AttrId, mod_item: ModItem }, | 226 | Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem }, |
227 | } | 227 | } |
228 | 228 | ||
229 | struct DefData<'a> { | 229 | struct DefData<'a> { |
@@ -419,7 +419,7 @@ impl DefCollector<'_> { | |||
419 | let mut unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new()); | 419 | let mut unresolved_macros = std::mem::replace(&mut self.unresolved_macros, Vec::new()); |
420 | let pos = unresolved_macros.iter().position(|directive| { | 420 | let pos = unresolved_macros.iter().position(|directive| { |
421 | if let MacroDirectiveKind::Attr { ast_id, mod_item, attr } = &directive.kind { | 421 | if let MacroDirectiveKind::Attr { ast_id, mod_item, attr } = &directive.kind { |
422 | self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), *attr); | 422 | self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id); |
423 | 423 | ||
424 | let file_id = ast_id.ast_id.file_id; | 424 | let file_id = ast_id.ast_id.file_id; |
425 | let item_tree = self.db.file_item_tree(file_id); | 425 | let item_tree = self.db.file_item_tree(file_id); |
@@ -1050,7 +1050,7 @@ impl DefCollector<'_> { | |||
1050 | let file_id = ast_id.ast_id.file_id; | 1050 | let file_id = ast_id.ast_id.file_id; |
1051 | let item_tree = self.db.file_item_tree(file_id); | 1051 | let item_tree = self.db.file_item_tree(file_id); |
1052 | let mod_dir = self.mod_dirs[&directive.module_id].clone(); | 1052 | let mod_dir = self.mod_dirs[&directive.module_id].clone(); |
1053 | self.skip_attrs.insert(InFile::new(file_id, *mod_item), *attr); | 1053 | self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id); |
1054 | ModCollector { | 1054 | ModCollector { |
1055 | def_collector: &mut *self, | 1055 | def_collector: &mut *self, |
1056 | macro_depth: directive.depth, | 1056 | macro_depth: directive.depth, |
@@ -1067,8 +1067,56 @@ impl DefCollector<'_> { | |||
1067 | } | 1067 | } |
1068 | } | 1068 | } |
1069 | 1069 | ||
1070 | if !self.db.enable_proc_attr_macros() { | ||
1071 | return true; | ||
1072 | } | ||
1073 | |||
1070 | // Not resolved to a derive helper, so try to resolve as a macro. | 1074 | // Not resolved to a derive helper, so try to resolve as a macro. |
1071 | // FIXME: not yet :) | 1075 | match attr_macro_as_call_id( |
1076 | ast_id, | ||
1077 | attr, | ||
1078 | self.db, | ||
1079 | self.def_map.krate, | ||
1080 | &resolver, | ||
1081 | ) { | ||
1082 | Ok(call_id) => { | ||
1083 | let loc: MacroCallLoc = self.db.lookup_intern_macro(call_id); | ||
1084 | if let MacroDefKind::ProcMacro(exp, ..) = &loc.def.kind { | ||
1085 | if exp.is_dummy() { | ||
1086 | // Proc macros that cannot be expanded are treated as not | ||
1087 | // resolved, in order to fall back later. | ||
1088 | self.def_map.diagnostics.push( | ||
1089 | DefDiagnostic::unresolved_proc_macro( | ||
1090 | directive.module_id, | ||
1091 | loc.kind, | ||
1092 | ), | ||
1093 | ); | ||
1094 | |||
1095 | let file_id = ast_id.ast_id.file_id; | ||
1096 | let item_tree = self.db.file_item_tree(file_id); | ||
1097 | let mod_dir = self.mod_dirs[&directive.module_id].clone(); | ||
1098 | self.skip_attrs | ||
1099 | .insert(InFile::new(file_id, *mod_item), attr.id); | ||
1100 | ModCollector { | ||
1101 | def_collector: &mut *self, | ||
1102 | macro_depth: directive.depth, | ||
1103 | module_id: directive.module_id, | ||
1104 | file_id, | ||
1105 | item_tree: &item_tree, | ||
1106 | mod_dir, | ||
1107 | } | ||
1108 | .collect(&[*mod_item]); | ||
1109 | |||
1110 | // Remove the macro directive. | ||
1111 | return false; | ||
1112 | } | ||
1113 | } | ||
1114 | resolved.push((directive.module_id, call_id, directive.depth)); | ||
1115 | res = ReachedFixedPoint::No; | ||
1116 | return false; | ||
1117 | } | ||
1118 | Err(UnresolvedMacro { .. }) => (), | ||
1119 | } | ||
1072 | } | 1120 | } |
1073 | } | 1121 | } |
1074 | 1122 | ||
@@ -1628,7 +1676,7 @@ impl ModCollector<'_, '_> { | |||
1628 | self.def_collector.unresolved_macros.push(MacroDirective { | 1676 | self.def_collector.unresolved_macros.push(MacroDirective { |
1629 | module_id: self.module_id, | 1677 | module_id: self.module_id, |
1630 | depth: self.macro_depth + 1, | 1678 | depth: self.macro_depth + 1, |
1631 | kind: MacroDirectiveKind::Attr { ast_id, attr: attr.id, mod_item }, | 1679 | kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item }, |
1632 | }); | 1680 | }); |
1633 | 1681 | ||
1634 | return Err(()); | 1682 | return Err(()); |