mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 20:09:19 +00:00
Fix expression scope calculation when within macro expansions
This commit is contained in:
parent
882ae7105d
commit
bfb187aacd
7 changed files with 99 additions and 33 deletions
|
@ -68,38 +68,44 @@ impl SourceAnalyzer {
|
|||
pub(crate) fn new_for_body(
|
||||
db: &dyn HirDatabase,
|
||||
def: DefWithBodyId,
|
||||
node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
|
||||
node: InFile<&SyntaxNode>,
|
||||
offset: Option<TextSize>,
|
||||
) -> SourceAnalyzer {
|
||||
let (body, source_map) = db.body_with_source_map(def);
|
||||
let scopes = db.expr_scopes(def);
|
||||
let scope = match offset {
|
||||
None => scope_for(&scopes, &source_map, node),
|
||||
Some(offset) => scope_for_offset(db, &scopes, &source_map, node.file_id, offset),
|
||||
};
|
||||
let resolver = resolver_for_scope(db.upcast(), def, scope);
|
||||
SourceAnalyzer {
|
||||
resolver,
|
||||
def: Some((def, body, source_map)),
|
||||
infer: Some(db.infer(def)),
|
||||
file_id,
|
||||
}
|
||||
Self::new_for_body_(db, def, node, offset, Some(db.infer(def)))
|
||||
}
|
||||
|
||||
pub(crate) fn new_for_body_no_infer(
|
||||
db: &dyn HirDatabase,
|
||||
def: DefWithBodyId,
|
||||
node: InFile<&SyntaxNode>,
|
||||
offset: Option<TextSize>,
|
||||
) -> SourceAnalyzer {
|
||||
Self::new_for_body_(db, def, node, offset, None)
|
||||
}
|
||||
|
||||
pub(crate) fn new_for_body_(
|
||||
db: &dyn HirDatabase,
|
||||
def: DefWithBodyId,
|
||||
node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
|
||||
offset: Option<TextSize>,
|
||||
infer: Option<Arc<InferenceResult>>,
|
||||
) -> SourceAnalyzer {
|
||||
let (body, source_map) = db.body_with_source_map(def);
|
||||
let scopes = db.expr_scopes(def);
|
||||
let scope = match offset {
|
||||
None => scope_for(&scopes, &source_map, node),
|
||||
Some(offset) => scope_for_offset(db, &scopes, &source_map, node.file_id, offset),
|
||||
None => scope_for(db, &scopes, &source_map, node),
|
||||
Some(offset) => {
|
||||
debug_assert!(
|
||||
node.value.text_range().contains_inclusive(offset),
|
||||
"{:?} not in {:?}",
|
||||
offset,
|
||||
node.value.text_range()
|
||||
);
|
||||
scope_for_offset(db, &scopes, &source_map, node.file_id, offset)
|
||||
}
|
||||
};
|
||||
let resolver = resolver_for_scope(db.upcast(), def, scope);
|
||||
SourceAnalyzer { resolver, def: Some((def, body, source_map)), infer: None, file_id }
|
||||
SourceAnalyzer { resolver, def: Some((def, body, source_map)), infer, file_id }
|
||||
}
|
||||
|
||||
pub(crate) fn new_for_resolver(
|
||||
|
@ -662,7 +668,6 @@ impl SourceAnalyzer {
|
|||
return resolved;
|
||||
}
|
||||
|
||||
// This must be a normal source file rather than macro file.
|
||||
let ctx = LowerCtx::new(db.upcast(), self.file_id);
|
||||
let hir_path = Path::from_src(&ctx, path.clone())?;
|
||||
|
||||
|
@ -955,14 +960,17 @@ impl SourceAnalyzer {
|
|||
}
|
||||
|
||||
fn scope_for(
|
||||
db: &dyn HirDatabase,
|
||||
scopes: &ExprScopes,
|
||||
source_map: &BodySourceMap,
|
||||
node: InFile<&SyntaxNode>,
|
||||
) -> Option<ScopeId> {
|
||||
node.value
|
||||
.ancestors()
|
||||
.filter_map(ast::Expr::cast)
|
||||
.filter_map(|it| source_map.node_expr(InFile::new(node.file_id, &it)))
|
||||
node.ancestors_with_macros(db.upcast())
|
||||
.take_while(|it| {
|
||||
!ast::Item::can_cast(it.value.kind()) || ast::MacroCall::can_cast(it.value.kind())
|
||||
})
|
||||
.filter_map(|it| it.map(ast::Expr::cast).transpose())
|
||||
.filter_map(|it| source_map.node_expr(it.as_ref()))
|
||||
.find_map(|it| scopes.scope_for(it))
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue