diff options
-rw-r--r-- | crates/ra_assists/src/assists/add_explicit_type.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 26 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 2 |
4 files changed, 49 insertions, 13 deletions
diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs index eeb4ff39f..2c602a79e 100644 --- a/crates/ra_assists/src/assists/add_explicit_type.rs +++ b/crates/ra_assists/src/assists/add_explicit_type.rs | |||
@@ -74,6 +74,24 @@ mod tests { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | #[test] | 76 | #[test] |
77 | fn add_explicit_type_works_for_macro_call() { | ||
78 | check_assist( | ||
79 | add_explicit_type, | ||
80 | "macro_rules! v { () => {0u64} } fn f() { let a<|> = v!(); }", | ||
81 | "macro_rules! v { () => {0u64} } fn f() { let a<|>: u64 = v!(); }", | ||
82 | ); | ||
83 | } | ||
84 | |||
85 | #[test] | ||
86 | fn add_explicit_type_works_for_macro_call_recursive() { | ||
87 | check_assist( | ||
88 | add_explicit_type, | ||
89 | "macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a<|> = v!(); }", | ||
90 | "macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a<|>: u64 = v!(); }", | ||
91 | ); | ||
92 | } | ||
93 | |||
94 | #[test] | ||
77 | fn add_explicit_type_not_applicable_if_ty_not_inferred() { | 95 | fn add_explicit_type_not_applicable_if_ty_not_inferred() { |
78 | check_assist_not_applicable(add_explicit_type, "fn f() { let a<|> = None; }"); | 96 | check_assist_not_applicable(add_explicit_type, "fn f() { let a<|> = None; }"); |
79 | } | 97 | } |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 85b378483..3af477818 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -17,7 +17,7 @@ use hir_def::{ | |||
17 | nameres::ModuleSource, | 17 | nameres::ModuleSource, |
18 | path::path, | 18 | path::path, |
19 | resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, | 19 | resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, |
20 | AssocItemId, DefWithBodyId, | 20 | AssocItemId, DefWithBodyId, Expander, |
21 | }; | 21 | }; |
22 | use hir_expand::{ | 22 | use hir_expand::{ |
23 | hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, | 23 | hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, |
@@ -216,7 +216,14 @@ impl SourceAnalyzer { | |||
216 | } | 216 | } |
217 | 217 | ||
218 | pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> { | 218 | pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> { |
219 | let expr_id = self.expr_id(expr)?; | 219 | let expr_id = if let Some(macro_call) = ast::MacroCall::cast(expr.syntax().clone()) { |
220 | let mut expander = Expander::new(db, self.file_id, self.body_owner?.module(db).id); | ||
221 | let expr = expand_macro_call_to_expr(db, &mut expander, macro_call)?; | ||
222 | self.body_source_map.as_ref()?.node_expr(expr.as_ref())? | ||
223 | } else { | ||
224 | self.expr_id(expr)? | ||
225 | }; | ||
226 | |||
220 | let ty = self.infer.as_ref()?[expr_id].clone(); | 227 | let ty = self.infer.as_ref()?[expr_id].clone(); |
221 | let environment = TraitEnvironment::lower(db, &self.resolver); | 228 | let environment = TraitEnvironment::lower(db, &self.resolver); |
222 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | 229 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) |
@@ -501,6 +508,21 @@ fn scope_for_offset( | |||
501 | }) | 508 | }) |
502 | } | 509 | } |
503 | 510 | ||
511 | fn expand_macro_call_to_expr( | ||
512 | db: &impl HirDatabase, | ||
513 | expander: &mut Expander, | ||
514 | macro_call: ast::MacroCall, | ||
515 | ) -> Option<InFile<ast::Expr>> { | ||
516 | let (mark, expr): (_, ast::Expr) = expander.enter_expand(db, macro_call)?; | ||
517 | let expr = if let Some(child) = ast::MacroCall::cast(expr.syntax().clone()) { | ||
518 | expand_macro_call_to_expr(db, expander, child) | ||
519 | } else { | ||
520 | Some(expander.to_source(expr)) | ||
521 | }; | ||
522 | expander.exit(db, mark); | ||
523 | expr | ||
524 | } | ||
525 | |||
504 | // XXX: during completion, cursor might be outside of any particular | 526 | // XXX: during completion, cursor might be outside of any particular |
505 | // expression. Try to figure out the correct scope... | 527 | // expression. Try to figure out the correct scope... |
506 | fn adjust( | 528 | fn adjust( |
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index d3e4c50ae..8ab92b23a 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -26,7 +26,7 @@ use crate::{ | |||
26 | DefWithBodyId, HasModule, Lookup, ModuleId, | 26 | DefWithBodyId, HasModule, Lookup, ModuleId, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | pub(crate) struct Expander { | 29 | pub struct Expander { |
30 | crate_def_map: Arc<CrateDefMap>, | 30 | crate_def_map: Arc<CrateDefMap>, |
31 | current_file_id: HirFileId, | 31 | current_file_id: HirFileId, |
32 | hygiene: Hygiene, | 32 | hygiene: Hygiene, |
@@ -35,18 +35,14 @@ pub(crate) struct Expander { | |||
35 | } | 35 | } |
36 | 36 | ||
37 | impl Expander { | 37 | impl Expander { |
38 | pub(crate) fn new( | 38 | pub fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { |
39 | db: &impl DefDatabase, | ||
40 | current_file_id: HirFileId, | ||
41 | module: ModuleId, | ||
42 | ) -> Expander { | ||
43 | let crate_def_map = db.crate_def_map(module.krate); | 39 | let crate_def_map = db.crate_def_map(module.krate); |
44 | let hygiene = Hygiene::new(db, current_file_id); | 40 | let hygiene = Hygiene::new(db, current_file_id); |
45 | let ast_id_map = db.ast_id_map(current_file_id); | 41 | let ast_id_map = db.ast_id_map(current_file_id); |
46 | Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module } | 42 | Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module } |
47 | } | 43 | } |
48 | 44 | ||
49 | pub(crate) fn enter_expand<T: ast::AstNode, DB: DefDatabase>( | 45 | pub fn enter_expand<T: ast::AstNode, DB: DefDatabase>( |
50 | &mut self, | 46 | &mut self, |
51 | db: &DB, | 47 | db: &DB, |
52 | macro_call: ast::MacroCall, | 48 | macro_call: ast::MacroCall, |
@@ -84,14 +80,14 @@ impl Expander { | |||
84 | None | 80 | None |
85 | } | 81 | } |
86 | 82 | ||
87 | pub(crate) fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) { | 83 | pub fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) { |
88 | self.hygiene = Hygiene::new(db, mark.file_id); | 84 | self.hygiene = Hygiene::new(db, mark.file_id); |
89 | self.current_file_id = mark.file_id; | 85 | self.current_file_id = mark.file_id; |
90 | self.ast_id_map = mem::take(&mut mark.ast_id_map); | 86 | self.ast_id_map = mem::take(&mut mark.ast_id_map); |
91 | mark.bomb.defuse(); | 87 | mark.bomb.defuse(); |
92 | } | 88 | } |
93 | 89 | ||
94 | pub(crate) fn to_source<T>(&self, value: T) -> InFile<T> { | 90 | pub fn to_source<T>(&self, value: T) -> InFile<T> { |
95 | InFile { file_id: self.current_file_id, value } | 91 | InFile { file_id: self.current_file_id, value } |
96 | } | 92 | } |
97 | 93 | ||
@@ -116,7 +112,7 @@ impl Expander { | |||
116 | } | 112 | } |
117 | } | 113 | } |
118 | 114 | ||
119 | pub(crate) struct Mark { | 115 | pub struct Mark { |
120 | file_id: HirFileId, | 116 | file_id: HirFileId, |
121 | ast_id_map: Arc<AstIdMap>, | 117 | ast_id_map: Arc<AstIdMap>, |
122 | bomb: DropBomb, | 118 | bomb: DropBomb, |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index f6c7f38d1..f58ce9a95 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -48,7 +48,7 @@ use ra_arena::{impl_arena_id, RawId}; | |||
48 | use ra_db::{impl_intern_key, salsa, CrateId}; | 48 | use ra_db::{impl_intern_key, salsa, CrateId}; |
49 | use ra_syntax::{ast, AstNode}; | 49 | use ra_syntax::{ast, AstNode}; |
50 | 50 | ||
51 | use crate::body::Expander; | 51 | pub use crate::body::Expander; |
52 | use crate::builtin_type::BuiltinType; | 52 | use crate::builtin_type::BuiltinType; |
53 | 53 | ||
54 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 54 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |