Use pre-stored macro file

This commit is contained in:
Edwin Cheng 2019-12-23 21:47:11 +08:00
parent 16156d766d
commit 12cc2ed557
4 changed files with 51 additions and 33 deletions

View file

@ -17,7 +17,7 @@ use hir_def::{
nameres::ModuleSource,
path::path,
resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
AssocItemId, DefWithBodyId, Expander,
AssocItemId, DefWithBodyId,
};
use hir_expand::{
hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind,
@ -215,10 +215,27 @@ 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(&macro_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 = if let Some(macro_call) = ast::MacroCall::cast(expr.syntax().clone()) {
let mut expander = Expander::new(db, self.file_id, self.body_owner?.module(db).id);
let expr = expand_macro_call_to_expr(db, &mut expander, macro_call)?;
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)?
@ -508,21 +525,6 @@ fn scope_for_offset(
})
}
fn expand_macro_call_to_expr(
db: &impl HirDatabase,
expander: &mut Expander,
macro_call: ast::MacroCall,
) -> Option<InFile<ast::Expr>> {
let (mark, expr): (_, ast::Expr) = expander.enter_expand(db, macro_call)?;
let expr = if let Some(child) = ast::MacroCall::cast(expr.syntax().clone()) {
expand_macro_call_to_expr(db, expander, child)
} else {
Some(expander.to_source(expr))
};
expander.exit(db, mark);
expr
}
// XXX: during completion, cursor might be outside of any particular
// expression. Try to figure out the correct scope...
fn adjust(