mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Merge #2650
2650: Add macro call support for SourceAnalyzer::type_of r=matklad a=edwin0cheng Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
commit
523b4cbc60
4 changed files with 62 additions and 8 deletions
|
@ -73,6 +73,24 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_explicit_type_works_for_macro_call() {
|
||||
check_assist(
|
||||
add_explicit_type,
|
||||
"macro_rules! v { () => {0u64} } fn f() { let a<|> = v!(); }",
|
||||
"macro_rules! v { () => {0u64} } fn f() { let a<|>: u64 = v!(); }",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_explicit_type_works_for_macro_call_recursive() {
|
||||
check_assist(
|
||||
add_explicit_type,
|
||||
"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a<|> = v!(); }",
|
||||
"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a<|>: u64 = v!(); }",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_explicit_type_not_applicable_if_ty_not_inferred() {
|
||||
check_assist_not_applicable(add_explicit_type, "fn f() { let a<|> = None; }");
|
||||
|
|
|
@ -215,8 +215,32 @@ impl SourceAnalyzer {
|
|||
self.body_source_map.as_ref()?.node_pat(src)
|
||||
}
|
||||
|
||||
fn expand_expr(
|
||||
&self,
|
||||
db: &impl HirDatabase,
|
||||
expr: InFile<&ast::Expr>,
|
||||
) -> Option<InFile<ast::Expr>> {
|
||||
let macro_call = ast::MacroCall::cast(expr.value.syntax().clone())?;
|
||||
let macro_file =
|
||||
self.body_source_map.as_ref()?.node_macro_file(expr.with_value(¯o_call))?;
|
||||
let expanded = db.parse_or_expand(macro_file)?;
|
||||
let kind = expanded.kind();
|
||||
let expr = InFile::new(macro_file, ast::Expr::cast(expanded)?);
|
||||
|
||||
if ast::MacroCall::can_cast(kind) {
|
||||
self.expand_expr(db, expr.as_ref())
|
||||
} else {
|
||||
Some(expr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> {
|
||||
let expr_id = self.expr_id(expr)?;
|
||||
let expr_id = if let Some(expr) = self.expand_expr(db, InFile::new(self.file_id, expr)) {
|
||||
self.body_source_map.as_ref()?.node_expr(expr.as_ref())?
|
||||
} else {
|
||||
self.expr_id(expr)?
|
||||
};
|
||||
|
||||
let ty = self.infer.as_ref()?[expr_id].clone();
|
||||
let environment = TraitEnvironment::lower(db, &self.resolver);
|
||||
Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } })
|
||||
|
|
|
@ -163,6 +163,7 @@ pub struct BodySourceMap {
|
|||
pat_map: FxHashMap<PatSource, PatId>,
|
||||
pat_map_back: ArenaMap<PatId, PatSource>,
|
||||
field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>,
|
||||
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
|
||||
}
|
||||
|
||||
impl Body {
|
||||
|
@ -237,6 +238,11 @@ impl BodySourceMap {
|
|||
self.expr_map.get(&src).cloned()
|
||||
}
|
||||
|
||||
pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<HirFileId> {
|
||||
let src = node.map(|it| AstPtr::new(it));
|
||||
self.expansions.get(&src).cloned()
|
||||
}
|
||||
|
||||
pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> {
|
||||
let src = node.map(|it| Either::Right(AstPtr::new(it)));
|
||||
self.expr_map.get(&src).cloned()
|
||||
|
|
|
@ -446,14 +446,20 @@ where
|
|||
}
|
||||
}
|
||||
// FIXME expand to statements in statement position
|
||||
ast::Expr::MacroCall(e) => match self.expander.enter_expand(self.db, e) {
|
||||
Some((mark, expansion)) => {
|
||||
let id = self.collect_expr(expansion);
|
||||
self.expander.exit(self.db, mark);
|
||||
id
|
||||
ast::Expr::MacroCall(e) => {
|
||||
let macro_call = self.expander.to_source(AstPtr::new(&e));
|
||||
match self.expander.enter_expand(self.db, e.clone()) {
|
||||
Some((mark, expansion)) => {
|
||||
self.source_map
|
||||
.expansions
|
||||
.insert(macro_call, self.expander.current_file_id);
|
||||
let id = self.collect_expr(expansion);
|
||||
self.expander.exit(self.db, mark);
|
||||
id
|
||||
}
|
||||
None => self.alloc_expr(Expr::Missing, syntax_ptr),
|
||||
}
|
||||
None => self.alloc_expr(Expr::Missing, syntax_ptr),
|
||||
},
|
||||
}
|
||||
|
||||
// FIXME implement HIR for these:
|
||||
ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
|
||||
|
|
Loading…
Reference in a new issue