diff options
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r-- | crates/ra_hir_def/src/attr.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir_def/src/expr.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/raw.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests/macros.rs | 37 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path/lower.rs | 15 |
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)] | ||
143 | pub struct AttrQuery<'a> { | 144 | pub 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] |
139 | fn 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] | ||
139 | fn unexpanded_macro_should_expand_by_fixedpoint_loop() { | 176 | fn 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 | ||