aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/attr.rs1
-rw-r--r--crates/ra_hir_def/src/body/lower.rs21
-rw-r--r--crates/ra_hir_def/src/expr.rs4
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs2
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs29
-rw-r--r--crates/ra_hir_def/src/nameres/tests/macros.rs37
-rw-r--r--crates/ra_hir_def/src/path/lower.rs15
7 files changed, 97 insertions, 12 deletions
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 5a86af8ba..576cd0c65 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -140,6 +140,7 @@ impl Attr {
140 } 140 }
141} 141}
142 142
143#[derive(Debug, Clone, Copy)]
143pub struct AttrQuery<'a> { 144pub struct AttrQuery<'a> {
144 attrs: &'a Attrs, 145 attrs: &'a Attrs,
145 key: &'static str, 146 key: &'static str,
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index e9dd65b0a..687216dc3 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -203,6 +203,16 @@ impl ExprCollector<'_> {
203 203
204 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) 204 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
205 } 205 }
206 ast::Expr::EffectExpr(e) => match e.effect() {
207 ast::Effect::Try(_) => {
208 let body = self.collect_block_opt(e.block_expr());
209 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
210 }
211 // FIXME: we need to record these effects somewhere...
212 ast::Effect::Async(_) | ast::Effect::Label(_) | ast::Effect::Unsafe(_) => {
213 self.collect_block_opt(e.block_expr())
214 }
215 },
206 ast::Expr::BlockExpr(e) => self.collect_block(e), 216 ast::Expr::BlockExpr(e) => self.collect_block(e),
207 ast::Expr::LoopExpr(e) => { 217 ast::Expr::LoopExpr(e) => {
208 let body = self.collect_block_opt(e.loop_body()); 218 let body = self.collect_block_opt(e.loop_body());
@@ -456,6 +466,7 @@ impl ExprCollector<'_> {
456 krate: Some(self.expander.module.krate), 466 krate: Some(self.expander.module.krate),
457 ast_id: Some(self.expander.ast_id(&e)), 467 ast_id: Some(self.expander.ast_id(&e)),
458 kind: MacroDefKind::Declarative, 468 kind: MacroDefKind::Declarative,
469 local_inner: false,
459 }; 470 };
460 self.body.item_scope.define_legacy_macro(name, mac); 471 self.body.item_scope.define_legacy_macro(name, mac);
461 472
@@ -490,12 +501,8 @@ impl ExprCollector<'_> {
490 } 501 }
491 } 502 }
492 503
493 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { 504 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
494 let syntax_node_ptr = AstPtr::new(&expr.clone().into()); 505 let syntax_node_ptr = AstPtr::new(&block.clone().into());
495 let block = match expr.block() {
496 Some(block) => block,
497 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
498 };
499 self.collect_block_items(&block); 506 self.collect_block_items(&block);
500 let statements = block 507 let statements = block
501 .statements() 508 .statements()
@@ -513,7 +520,7 @@ impl ExprCollector<'_> {
513 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 520 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
514 } 521 }
515 522
516 fn collect_block_items(&mut self, block: &ast::Block) { 523 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
517 let container = ContainerId::DefWithBodyId(self.def); 524 let container = ContainerId::DefWithBodyId(self.def);
518 for item in block.items() { 525 for item in block.items() {
519 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 526 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index aad12e123..a0cdad529 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -101,6 +101,9 @@ pub enum Expr {
101 Try { 101 Try {
102 expr: ExprId, 102 expr: ExprId,
103 }, 103 },
104 TryBlock {
105 body: ExprId,
106 },
104 Cast { 107 Cast {
105 expr: ExprId, 108 expr: ExprId,
106 type_ref: TypeRef, 109 type_ref: TypeRef,
@@ -236,6 +239,7 @@ impl Expr {
236 f(*expr); 239 f(*expr);
237 } 240 }
238 } 241 }
242 Expr::TryBlock { body } => f(*body),
239 Expr::Loop { body } => f(*body), 243 Expr::Loop { body } => f(*body),
240 Expr::While { condition, body } => { 244 Expr::While { condition, body } => {
241 f(*condition); 245 f(*condition);
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 98c74fe25..bf3968bd6 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -204,6 +204,7 @@ impl DefCollector<'_> {
204 ast_id: None, 204 ast_id: None,
205 krate: Some(krate), 205 krate: Some(krate),
206 kind: MacroDefKind::CustomDerive(expander), 206 kind: MacroDefKind::CustomDerive(expander),
207 local_inner: false,
207 }; 208 };
208 209
209 self.define_proc_macro(name.clone(), macro_id); 210 self.define_proc_macro(name.clone(), macro_id);
@@ -941,6 +942,7 @@ impl ModCollector<'_, '_> {
941 ast_id: Some(ast_id.ast_id), 942 ast_id: Some(ast_id.ast_id),
942 krate: Some(self.def_collector.def_map.krate), 943 krate: Some(self.def_collector.def_map.krate),
943 kind: MacroDefKind::Declarative, 944 kind: MacroDefKind::Declarative,
945 local_inner: mac.local_inner,
944 }; 946 };
945 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); 947 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
946 } 948 }
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 39b011ad7..a71503c76 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -188,6 +188,7 @@ pub(super) struct MacroData {
188 pub(super) path: ModPath, 188 pub(super) path: ModPath,
189 pub(super) name: Option<Name>, 189 pub(super) name: Option<Name>,
190 pub(super) export: bool, 190 pub(super) export: bool,
191 pub(super) local_inner: bool,
191 pub(super) builtin: bool, 192 pub(super) builtin: bool,
192} 193}
193 194
@@ -401,14 +402,32 @@ impl RawItemsCollector {
401 402
402 let name = m.name().map(|it| it.as_name()); 403 let name = m.name().map(|it| it.as_name());
403 let ast_id = self.source_ast_id_map.ast_id(&m); 404 let ast_id = self.source_ast_id_map.ast_id(&m);
404 // FIXME: cfg_attr
405 let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export");
406 405
407 // FIXME: cfg_attr 406 // FIXME: cfg_attr
408 let builtin = 407 let export_attr = attrs.by_key("macro_export");
409 m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "rustc_builtin_macro"); 408
409 let export = export_attr.exists();
410 let local_inner = if export {
411 export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
412 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
413 ident.text.contains("local_inner_macros")
414 }
415 _ => false,
416 })
417 } else {
418 false
419 };
420
421 let builtin = attrs.by_key("rustc_builtin_macro").exists();
410 422
411 let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export, builtin }); 423 let m = self.raw_items.macros.alloc(MacroData {
424 ast_id,
425 path,
426 name,
427 export,
428 local_inner,
429 builtin,
430 });
412 self.push_item(current_module, attrs, RawItemKind::Macro(m)); 431 self.push_item(current_module, attrs, RawItemKind::Macro(m));
413 } 432 }
414 433
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs
index b0befdfbd..9bc0e6287 100644
--- a/crates/ra_hir_def/src/nameres/tests/macros.rs
+++ b/crates/ra_hir_def/src/nameres/tests/macros.rs
@@ -136,6 +136,43 @@ fn macro_rules_export_with_local_inner_macros_are_visible() {
136} 136}
137 137
138#[test] 138#[test]
139fn local_inner_macros_makes_local_macros_usable() {
140 let map = def_map(
141 "
142 //- /main.rs crate:main deps:foo
143 foo::structs!(Foo, Bar);
144 mod bar;
145 //- /bar.rs
146 use crate::*;
147 //- /lib.rs crate:foo
148 #[macro_export(local_inner_macros)]
149 macro_rules! structs {
150 ($($i:ident),*) => {
151 inner!($($i),*);
152 }
153 }
154 #[macro_export]
155 macro_rules! inner {
156 ($($i:ident),*) => {
157 $(struct $i { field: u32 } )*
158 }
159 }
160 ",
161 );
162 assert_snapshot!(map, @r###"
163 ⋮crate
164 ⋮Bar: t v
165 ⋮Foo: t v
166 ⋮bar: t
167
168 ⋮crate::bar
169 ⋮Bar: t v
170 ⋮Foo: t v
171 ⋮bar: t
172 "###);
173}
174
175#[test]
139fn unexpanded_macro_should_expand_by_fixedpoint_loop() { 176fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
140 let map = def_map( 177 let map = def_map(
141 " 178 "
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index e3d237a0a..6a0c019fd 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -116,6 +116,21 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
116 } 116 }
117 segments.reverse(); 117 segments.reverse();
118 generic_args.reverse(); 118 generic_args.reverse();
119
120 // handle local_inner_macros :
121 // Basically, even in rustc it is quite hacky:
122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456
123 // We follow what it did anyway :)
124 if segments.len() == 1 && kind == PathKind::Plain {
125 if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
126 if macro_call.is_bang() {
127 if let Some(crate_id) = hygiene.local_inner_macros() {
128 kind = PathKind::DollarCrate(crate_id);
129 }
130 }
131 }
132 }
133
119 let mod_path = ModPath { kind, segments }; 134 let mod_path = ModPath { kind, segments };
120 return Some(Path { type_anchor, mod_path, generic_args }); 135 return Some(Path { type_anchor, mod_path, generic_args });
121 136