mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Merge #1221
1221: Use correct FileId when expanding macros in expressions r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
c368b147e3
2 changed files with 44 additions and 33 deletions
|
@ -10,7 +10,7 @@ use ra_syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Path, Name, HirDatabase, Resolver,DefWithBody, Either,
|
Path, Name, HirDatabase, Resolver,DefWithBody, Either, HirFileId,
|
||||||
name::AsName,
|
name::AsName,
|
||||||
ids::{MacroCallId},
|
ids::{MacroCallId},
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
|
@ -488,15 +488,19 @@ pub(crate) struct ExprCollector<DB> {
|
||||||
params: Vec<PatId>,
|
params: Vec<PatId>,
|
||||||
body_expr: Option<ExprId>,
|
body_expr: Option<ExprId>,
|
||||||
resolver: Resolver,
|
resolver: Resolver,
|
||||||
// FIXEME: Its a quick hack,see issue #1196
|
// Expr collector expands macros along the way. original points to the file
|
||||||
is_in_macro: bool,
|
// we started with, current points to the current macro expansion. source
|
||||||
|
// maps don't support macros yet, so we only record info into source map if
|
||||||
|
// current == original (see #1196)
|
||||||
|
original_file_id: HirFileId,
|
||||||
|
current_file_id: HirFileId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, DB> ExprCollector<&'a DB>
|
impl<'a, DB> ExprCollector<&'a DB>
|
||||||
where
|
where
|
||||||
DB: HirDatabase,
|
DB: HirDatabase,
|
||||||
{
|
{
|
||||||
fn new(owner: DefWithBody, resolver: Resolver, db: &'a DB) -> Self {
|
fn new(owner: DefWithBody, file_id: HirFileId, resolver: Resolver, db: &'a DB) -> Self {
|
||||||
ExprCollector {
|
ExprCollector {
|
||||||
owner,
|
owner,
|
||||||
resolver,
|
resolver,
|
||||||
|
@ -506,23 +510,23 @@ where
|
||||||
source_map: BodySourceMap::default(),
|
source_map: BodySourceMap::default(),
|
||||||
params: Vec::new(),
|
params: Vec::new(),
|
||||||
body_expr: None,
|
body_expr: None,
|
||||||
is_in_macro: false,
|
original_file_id: file_id,
|
||||||
|
current_file_id: file_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId {
|
fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId {
|
||||||
let id = self.exprs.alloc(expr);
|
let id = self.exprs.alloc(expr);
|
||||||
if !self.is_in_macro {
|
if self.current_file_id == self.original_file_id {
|
||||||
self.source_map.expr_map.insert(syntax_ptr, id);
|
self.source_map.expr_map.insert(syntax_ptr, id);
|
||||||
self.source_map.expr_map_back.insert(id, syntax_ptr);
|
self.source_map.expr_map_back.insert(id, syntax_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
|
fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
|
||||||
let id = self.pats.alloc(pat);
|
let id = self.pats.alloc(pat);
|
||||||
|
|
||||||
if !self.is_in_macro {
|
if self.current_file_id == self.original_file_id {
|
||||||
self.source_map.pat_map.insert(ptr, id);
|
self.source_map.pat_map.insert(ptr, id);
|
||||||
self.source_map.pat_map_back.insert(id, ptr);
|
self.source_map.pat_map_back.insert(id, ptr);
|
||||||
}
|
}
|
||||||
|
@ -815,12 +819,19 @@ where
|
||||||
// very hacky.FIXME change to use the macro resolution
|
// very hacky.FIXME change to use the macro resolution
|
||||||
let path = e.path().and_then(Path::from_ast);
|
let path = e.path().and_then(Path::from_ast);
|
||||||
|
|
||||||
if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, e) {
|
let ast_id = self
|
||||||
|
.db
|
||||||
|
.ast_id_map(self.current_file_id)
|
||||||
|
.ast_id(e)
|
||||||
|
.with_file_id(self.current_file_id);
|
||||||
|
|
||||||
|
if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, ast_id) {
|
||||||
if let Some(expr) = expand_macro_to_expr(self.db, call_id, e.token_tree()) {
|
if let Some(expr) = expand_macro_to_expr(self.db, call_id, e.token_tree()) {
|
||||||
log::debug!("macro expansion {}", expr.syntax().debug_dump());
|
log::debug!("macro expansion {}", expr.syntax().debug_dump());
|
||||||
let old = std::mem::replace(&mut self.is_in_macro, true);
|
let old_file_id =
|
||||||
|
std::mem::replace(&mut self.current_file_id, call_id.into());
|
||||||
let id = self.collect_expr(&expr);
|
let id = self.collect_expr(&expr);
|
||||||
self.is_in_macro = old;
|
self.current_file_id = old_file_id;
|
||||||
id
|
id
|
||||||
} else {
|
} else {
|
||||||
// FIXME: Instead of just dropping the error from expansion
|
// FIXME: Instead of just dropping the error from expansion
|
||||||
|
@ -1006,12 +1017,24 @@ pub(crate) fn body_with_source_map_query(
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
def: DefWithBody,
|
def: DefWithBody,
|
||||||
) -> (Arc<Body>, Arc<BodySourceMap>) {
|
) -> (Arc<Body>, Arc<BodySourceMap>) {
|
||||||
let mut collector = ExprCollector::new(def, def.resolver(db), db);
|
let mut collector;
|
||||||
|
|
||||||
match def {
|
match def {
|
||||||
DefWithBody::Const(ref c) => collector.collect_const_body(&c.source(db).1),
|
DefWithBody::Const(ref c) => {
|
||||||
DefWithBody::Function(ref f) => collector.collect_fn_body(&f.source(db).1),
|
let (file_id, src) = c.source(db);
|
||||||
DefWithBody::Static(ref s) => collector.collect_static_body(&s.source(db).1),
|
collector = ExprCollector::new(def, file_id, def.resolver(db), db);
|
||||||
|
collector.collect_const_body(&src)
|
||||||
|
}
|
||||||
|
DefWithBody::Function(ref f) => {
|
||||||
|
let (file_id, src) = f.source(db);
|
||||||
|
collector = ExprCollector::new(def, file_id, def.resolver(db), db);
|
||||||
|
collector.collect_fn_body(&src)
|
||||||
|
}
|
||||||
|
DefWithBody::Static(ref s) => {
|
||||||
|
let (file_id, src) = s.source(db);
|
||||||
|
collector = ExprCollector::new(def, file_id, def.resolver(db), db);
|
||||||
|
collector.collect_static_body(&src)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (body, source_map) = collector.finish();
|
let (body, source_map) = collector.finish();
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::{
|
||||||
code_model_api::Crate,
|
code_model_api::Crate,
|
||||||
MacroCallId,
|
MacroCallId,
|
||||||
MacroCallLoc,
|
MacroCallLoc,
|
||||||
|
AstId,
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
name::{Name, KnownName},
|
name::{Name, KnownName},
|
||||||
nameres::{PerNs, CrateDefMap, CrateModuleId},
|
nameres::{PerNs, CrateDefMap, CrateModuleId},
|
||||||
|
@ -17,7 +18,7 @@ use crate::{
|
||||||
expr::{scope::{ExprScopes, ScopeId}, PatId},
|
expr::{scope::{ExprScopes, ScopeId}, PatId},
|
||||||
impl_block::ImplBlock,
|
impl_block::ImplBlock,
|
||||||
path::Path,
|
path::Path,
|
||||||
Trait
|
Trait,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
|
@ -138,25 +139,12 @@ impl Resolver {
|
||||||
&self,
|
&self,
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
path: Option<Path>,
|
path: Option<Path>,
|
||||||
call: &ast::MacroCall,
|
ast_id: AstId<ast::MacroCall>,
|
||||||
) -> Option<MacroCallId> {
|
) -> Option<MacroCallId> {
|
||||||
let name = path.and_then(|path| path.expand_macro_expr()).unwrap_or_else(Name::missing);
|
let name = path.and_then(|path| path.expand_macro_expr()).unwrap_or_else(Name::missing);
|
||||||
let macro_def_id = self.module().and_then(|(module, _)| module.find_macro(&name));
|
let def_id = self.module().and_then(|(module, _)| module.find_macro(&name))?;
|
||||||
if let Some(def_id) = macro_def_id {
|
|
||||||
self.module().and_then(|(module, _)| {
|
|
||||||
// we do this to get the ast_id for the macro call
|
|
||||||
// if we used the ast_id from the def_id variable
|
|
||||||
// it gives us the ast_id of the defenition site
|
|
||||||
let module = module.mk_module(module.root());
|
|
||||||
let hir_file_id = module.definition_source(db).0;
|
|
||||||
let ast_id = db.ast_id_map(hir_file_id).ast_id(call).with_file_id(hir_file_id);
|
|
||||||
let call_loc = MacroCallLoc { def: *def_id, ast_id }.id(db);
|
let call_loc = MacroCallLoc { def: *def_id, ast_id }.id(db);
|
||||||
|
|
||||||
Some(call_loc)
|
Some(call_loc)
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the resolved path segments
|
/// Returns the resolved path segments
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue