mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
fix: Don't force draw a dependency edge to the real_span_map query
This commit is contained in:
parent
bd0ffb0248
commit
c04c0dd5ba
16 changed files with 125 additions and 114 deletions
|
@ -400,7 +400,7 @@ pub(crate) fn lower_struct(
|
|||
item_tree: &ItemTree,
|
||||
fields: &Fields,
|
||||
) -> StructKind {
|
||||
let ctx = LowerCtx::with_file_id(db, ast.file_id);
|
||||
let ctx = LowerCtx::new(db, ast.file_id);
|
||||
|
||||
match (&ast.value, fields) {
|
||||
(ast::StructKind::Tuple(fl), Fields::Tuple(fields)) => {
|
||||
|
@ -415,7 +415,9 @@ pub(crate) fn lower_struct(
|
|||
|| FieldData {
|
||||
name: Name::new_tuple_field(i),
|
||||
type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
|
||||
visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
|
||||
visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
|
||||
ctx.span_map().span_for_range(range).ctx
|
||||
}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -433,7 +435,9 @@ pub(crate) fn lower_struct(
|
|||
|| FieldData {
|
||||
name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
|
||||
type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
|
||||
visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
|
||||
visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
|
||||
ctx.span_map().span_for_range(range).ctx
|
||||
}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//! Macro expansion utilities.
|
||||
|
||||
use std::cell::OnceCell;
|
||||
|
||||
use base_db::CrateId;
|
||||
use cfg::CfgOptions;
|
||||
use drop_bomb::DropBomb;
|
||||
|
@ -18,7 +20,7 @@ use crate::{
|
|||
#[derive(Debug)]
|
||||
pub struct Expander {
|
||||
cfg_options: CfgOptions,
|
||||
span_map: SpanMap,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
krate: CrateId,
|
||||
current_file_id: HirFileId,
|
||||
pub(crate) module: ModuleId,
|
||||
|
@ -42,7 +44,7 @@ impl Expander {
|
|||
recursion_depth: 0,
|
||||
recursion_limit,
|
||||
cfg_options: db.crate_graph()[module.krate].cfg_options.clone(),
|
||||
span_map: db.span_map(current_file_id),
|
||||
span_map: OnceCell::new(),
|
||||
krate: module.krate,
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +102,7 @@ impl Expander {
|
|||
}
|
||||
|
||||
pub fn ctx<'a>(&self, db: &'a dyn DefDatabase) -> LowerCtx<'a> {
|
||||
LowerCtx::new(db, self.span_map.clone(), self.current_file_id)
|
||||
LowerCtx::with_span_map_cell(db, self.current_file_id, self.span_map.clone())
|
||||
}
|
||||
|
||||
pub(crate) fn in_file<T>(&self, value: T) -> InFile<T> {
|
||||
|
@ -108,7 +110,15 @@ impl Expander {
|
|||
}
|
||||
|
||||
pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> Attrs {
|
||||
Attrs::filter(db, self.krate, RawAttrs::new(db.upcast(), owner, self.span_map.as_ref()))
|
||||
Attrs::filter(
|
||||
db,
|
||||
self.krate,
|
||||
RawAttrs::new(
|
||||
db.upcast(),
|
||||
owner,
|
||||
self.span_map.get_or_init(|| db.span_map(self.current_file_id)).as_ref(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn cfg_options(&self) -> &CfgOptions {
|
||||
|
@ -120,7 +130,7 @@ impl Expander {
|
|||
}
|
||||
|
||||
pub(crate) fn parse_path(&mut self, db: &dyn DefDatabase, path: ast::Path) -> Option<Path> {
|
||||
let ctx = LowerCtx::new(db, self.span_map.clone(), self.current_file_id);
|
||||
let ctx = LowerCtx::with_span_map_cell(db, self.current_file_id, self.span_map.clone());
|
||||
Path::from_src(&ctx, path)
|
||||
}
|
||||
|
||||
|
@ -165,10 +175,11 @@ impl Expander {
|
|||
let parse = res.value.0.cast::<T>()?;
|
||||
|
||||
self.recursion_depth += 1;
|
||||
let old_span_map = std::mem::replace(
|
||||
&mut self.span_map,
|
||||
SpanMap::ExpansionSpanMap(res.value.1),
|
||||
);
|
||||
let old_span_map = OnceCell::new();
|
||||
if let Some(prev) = self.span_map.take() {
|
||||
_ = old_span_map.set(prev);
|
||||
};
|
||||
_ = self.span_map.set(SpanMap::ExpansionSpanMap(res.value.1));
|
||||
let old_file_id =
|
||||
std::mem::replace(&mut self.current_file_id, macro_file.into());
|
||||
let mark = Mark {
|
||||
|
@ -187,6 +198,6 @@ impl Expander {
|
|||
#[derive(Debug)]
|
||||
pub struct Mark {
|
||||
file_id: HirFileId,
|
||||
span_map: SpanMap,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
bomb: DropBomb,
|
||||
}
|
||||
|
|
|
@ -611,8 +611,10 @@ mod tests {
|
|||
let parsed_path_file = syntax::SourceFile::parse(&format!("use {path};"));
|
||||
let ast_path =
|
||||
parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
|
||||
let mod_path =
|
||||
ModPath::from_src(&db, ast_path, db.span_map(pos.file_id.into()).as_ref()).unwrap();
|
||||
let mod_path = ModPath::from_src(&db, ast_path, &mut |range| {
|
||||
db.span_map(pos.file_id.into()).as_ref().span_for_range(range).ctx
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let def_map = module.def_map(&db);
|
||||
let resolved = def_map
|
||||
|
|
|
@ -251,7 +251,7 @@ impl TypeRef {
|
|||
TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
|
||||
}
|
||||
ast::Type::MacroType(mt) => match mt.macro_call() {
|
||||
Some(mc) => ctx.ast_id(&mc).map(TypeRef::Macro).unwrap_or(TypeRef::Error),
|
||||
Some(mc) => TypeRef::Macro(ctx.ast_id(&mc)),
|
||||
None => TypeRef::Error,
|
||||
},
|
||||
}
|
||||
|
@ -398,9 +398,8 @@ pub enum ConstRef {
|
|||
impl ConstRef {
|
||||
pub(crate) fn from_const_arg(lower_ctx: &LowerCtx<'_>, arg: Option<ast::ConstArg>) -> Self {
|
||||
if let Some(arg) = arg {
|
||||
let ast_id = lower_ctx.ast_id(&arg);
|
||||
if let Some(expr) = arg.expr() {
|
||||
return Self::from_expr(expr, ast_id);
|
||||
return Self::from_expr(expr, Some(lower_ctx.ast_id(&arg)));
|
||||
}
|
||||
}
|
||||
Self::Scalar(LiteralConstRef::Unknown)
|
||||
|
|
|
@ -29,9 +29,6 @@
|
|||
//!
|
||||
//! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
|
||||
//! surface syntax.
|
||||
//!
|
||||
//! Note that we cannot store [`span::Span`]s inside of this, as typing in an item invalidates its
|
||||
//! encompassing span!
|
||||
|
||||
mod lower;
|
||||
mod pretty;
|
||||
|
@ -824,11 +821,13 @@ impl Use {
|
|||
// Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
|
||||
let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
|
||||
let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
|
||||
let span_map = db.span_map(file_id);
|
||||
let (_, source_map) = lower::lower_use_tree(db, span_map.as_ref(), ast_use_tree)
|
||||
.expect("failed to lower use tree");
|
||||
let (_, source_map) = lower::lower_use_tree(db, ast_use_tree, &mut |range| {
|
||||
db.span_map(file_id).span_for_range(range).ctx
|
||||
})
|
||||
.expect("failed to lower use tree");
|
||||
source_map[index].clone()
|
||||
}
|
||||
|
||||
/// Maps a `UseTree` contained in this import back to its AST node.
|
||||
pub fn use_tree_source_map(
|
||||
&self,
|
||||
|
@ -839,10 +838,11 @@ impl Use {
|
|||
// Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
|
||||
let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
|
||||
let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
|
||||
let span_map = db.span_map(file_id);
|
||||
lower::lower_use_tree(db, span_map.as_ref(), ast_use_tree)
|
||||
.expect("failed to lower use tree")
|
||||
.1
|
||||
lower::lower_use_tree(db, ast_use_tree, &mut |range| {
|
||||
db.span_map(file_id).span_for_range(range).ctx
|
||||
})
|
||||
.expect("failed to lower use tree")
|
||||
.1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::collections::hash_map::Entry;
|
|||
|
||||
use hir_expand::{mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId};
|
||||
use la_arena::Arena;
|
||||
use span::AstIdMap;
|
||||
use span::{AstIdMap, SyntaxContextId};
|
||||
use syntax::{
|
||||
ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString},
|
||||
AstNode,
|
||||
|
@ -45,7 +45,7 @@ impl<'a> Ctx<'a> {
|
|||
db,
|
||||
tree: ItemTree::default(),
|
||||
source_ast_id_map: db.ast_id_map(file),
|
||||
body_ctx: crate::lower::LowerCtx::with_file_id(db, file),
|
||||
body_ctx: crate::lower::LowerCtx::new(db, file),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,7 +535,9 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_use(&mut self, use_item: &ast::Use) -> Option<FileItemTreeId<Use>> {
|
||||
let visibility = self.lower_visibility(use_item);
|
||||
let ast_id = self.source_ast_id_map.ast_id(use_item);
|
||||
let (use_tree, _) = lower_use_tree(self.db, self.span_map(), use_item.use_tree()?)?;
|
||||
let (use_tree, _) = lower_use_tree(self.db, use_item.use_tree()?, &mut |range| {
|
||||
self.span_map().span_for_range(range).ctx
|
||||
})?;
|
||||
|
||||
let res = Use { visibility, ast_id, use_tree };
|
||||
Some(id(self.data().uses.alloc(res)))
|
||||
|
@ -558,7 +560,9 @@ impl<'a> Ctx<'a> {
|
|||
|
||||
fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
|
||||
let span_map = self.span_map();
|
||||
let path = Interned::new(ModPath::from_src(self.db.upcast(), m.path()?, span_map)?);
|
||||
let path = Interned::new(ModPath::from_src(self.db.upcast(), m.path()?, &mut |range| {
|
||||
span_map.span_for_range(range).ctx
|
||||
})?);
|
||||
let ast_id = self.source_ast_id_map.ast_id(m);
|
||||
let expand_to = hir_expand::ExpandTo::from_call_site(m);
|
||||
let res = MacroCall {
|
||||
|
@ -672,8 +676,9 @@ impl<'a> Ctx<'a> {
|
|||
}
|
||||
|
||||
fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
|
||||
let vis =
|
||||
RawVisibility::from_opt_ast_with_span_map(self.db, item.visibility(), self.span_map());
|
||||
let vis = RawVisibility::from_ast(self.db, item.visibility(), &mut |range| {
|
||||
self.span_map().span_for_range(range).ctx
|
||||
});
|
||||
self.data().vis.alloc(vis)
|
||||
}
|
||||
|
||||
|
@ -745,12 +750,15 @@ fn lower_abi(abi: ast::Abi) -> Interned<str> {
|
|||
|
||||
struct UseTreeLowering<'a> {
|
||||
db: &'a dyn DefDatabase,
|
||||
span_map: SpanMapRef<'a>,
|
||||
mapping: Arena<ast::UseTree>,
|
||||
}
|
||||
|
||||
impl UseTreeLowering<'_> {
|
||||
fn lower_use_tree(&mut self, tree: ast::UseTree) -> Option<UseTree> {
|
||||
fn lower_use_tree(
|
||||
&mut self,
|
||||
tree: ast::UseTree,
|
||||
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
|
||||
) -> Option<UseTree> {
|
||||
if let Some(use_tree_list) = tree.use_tree_list() {
|
||||
let prefix = match tree.path() {
|
||||
// E.g. use something::{{{inner}}};
|
||||
|
@ -758,15 +766,17 @@ impl UseTreeLowering<'_> {
|
|||
// E.g. `use something::{inner}` (prefix is `None`, path is `something`)
|
||||
// or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
|
||||
Some(path) => {
|
||||
match ModPath::from_src(self.db.upcast(), path, self.span_map) {
|
||||
match ModPath::from_src(self.db.upcast(), path, span_for_range) {
|
||||
Some(it) => Some(it),
|
||||
None => return None, // FIXME: report errors somewhere
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let list =
|
||||
use_tree_list.use_trees().filter_map(|tree| self.lower_use_tree(tree)).collect();
|
||||
let list = use_tree_list
|
||||
.use_trees()
|
||||
.filter_map(|tree| self.lower_use_tree(tree, span_for_range))
|
||||
.collect();
|
||||
|
||||
Some(
|
||||
self.use_tree(
|
||||
|
@ -777,7 +787,7 @@ impl UseTreeLowering<'_> {
|
|||
} else {
|
||||
let is_glob = tree.star_token().is_some();
|
||||
let path = match tree.path() {
|
||||
Some(path) => Some(ModPath::from_src(self.db.upcast(), path, self.span_map)?),
|
||||
Some(path) => Some(ModPath::from_src(self.db.upcast(), path, span_for_range)?),
|
||||
None => None,
|
||||
};
|
||||
let alias = tree.rename().map(|a| {
|
||||
|
@ -813,10 +823,10 @@ impl UseTreeLowering<'_> {
|
|||
|
||||
pub(crate) fn lower_use_tree(
|
||||
db: &dyn DefDatabase,
|
||||
span_map: SpanMapRef<'_>,
|
||||
tree: ast::UseTree,
|
||||
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
|
||||
) -> Option<(UseTree, Arena<ast::UseTree>)> {
|
||||
let mut lowering = UseTreeLowering { db, span_map, mapping: Arena::new() };
|
||||
let tree = lowering.lower_use_tree(tree)?;
|
||||
let mut lowering = UseTreeLowering { db, mapping: Arena::new() };
|
||||
let tree = lowering.lower_use_tree(tree, span_for_range)?;
|
||||
Some((tree, lowering.mapping))
|
||||
}
|
||||
|
|
|
@ -1341,8 +1341,11 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
|
|||
let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
|
||||
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
|
||||
let span_map = db.span_map(self.file_id);
|
||||
let path =
|
||||
self.value.path().and_then(|path| path::ModPath::from_src(db, path, span_map.as_ref()));
|
||||
let path = self.value.path().and_then(|path| {
|
||||
path::ModPath::from_src(db, path, &mut |range| {
|
||||
span_map.as_ref().span_for_range(range).ctx
|
||||
})
|
||||
});
|
||||
|
||||
let Some(path) = path else {
|
||||
return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation")));
|
||||
|
|
|
@ -13,39 +13,36 @@ use crate::{db::DefDatabase, path::Path};
|
|||
|
||||
pub struct LowerCtx<'a> {
|
||||
pub db: &'a dyn DefDatabase,
|
||||
span_map: SpanMap,
|
||||
// FIXME: This optimization is probably pointless, ast id map should pretty much always exist anyways.
|
||||
ast_id_map: Option<(HirFileId, OnceCell<Arc<AstIdMap>>)>,
|
||||
file_id: HirFileId,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
ast_id_map: OnceCell<Arc<AstIdMap>>,
|
||||
}
|
||||
|
||||
impl<'a> LowerCtx<'a> {
|
||||
pub fn new(db: &'a dyn DefDatabase, span_map: SpanMap, file_id: HirFileId) -> Self {
|
||||
LowerCtx { db, span_map, ast_id_map: Some((file_id, OnceCell::new())) }
|
||||
pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
|
||||
LowerCtx { db, file_id, span_map: OnceCell::new(), ast_id_map: OnceCell::new() }
|
||||
}
|
||||
|
||||
pub fn with_file_id(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
|
||||
LowerCtx {
|
||||
db,
|
||||
span_map: db.span_map(file_id),
|
||||
ast_id_map: Some((file_id, OnceCell::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_span_map(db: &'a dyn DefDatabase, span_map: SpanMap) -> Self {
|
||||
LowerCtx { db, span_map, ast_id_map: None }
|
||||
pub fn with_span_map_cell(
|
||||
db: &'a dyn DefDatabase,
|
||||
file_id: HirFileId,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
) -> Self {
|
||||
LowerCtx { db, file_id, span_map, ast_id_map: OnceCell::new() }
|
||||
}
|
||||
|
||||
pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
|
||||
self.span_map.as_ref()
|
||||
self.span_map.get_or_init(|| self.db.span_map(self.file_id)).as_ref()
|
||||
}
|
||||
|
||||
pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
|
||||
Path::from_src(self, ast)
|
||||
}
|
||||
|
||||
pub(crate) fn ast_id<N: AstIdNode>(&self, item: &N) -> Option<AstId<N>> {
|
||||
let &(file_id, ref ast_id_map) = self.ast_id_map.as_ref()?;
|
||||
let ast_id_map = ast_id_map.get_or_init(|| self.db.ast_id_map(file_id));
|
||||
Some(InFile::new(file_id, ast_id_map.ast_id(item)))
|
||||
pub(crate) fn ast_id<N: AstIdNode>(&self, item: &N) -> AstId<N> {
|
||||
InFile::new(
|
||||
self.file_id,
|
||||
self.ast_id_map.get_or_init(|| self.db.ast_id_map(self.file_id)).ast_id(item),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
use std::iter;
|
||||
|
||||
use hir_expand::{span_map::SpanMapRef, InFile};
|
||||
use la_arena::ArenaMap;
|
||||
use span::SyntaxContextId;
|
||||
use syntax::ast;
|
||||
use triomphe::Arc;
|
||||
|
||||
|
@ -34,36 +34,25 @@ impl RawVisibility {
|
|||
}
|
||||
|
||||
pub(crate) fn from_ast(
|
||||
db: &dyn DefDatabase,
|
||||
node: InFile<Option<ast::Visibility>>,
|
||||
) -> RawVisibility {
|
||||
let node = match node.transpose() {
|
||||
None => return RawVisibility::private(),
|
||||
Some(node) => node,
|
||||
};
|
||||
Self::from_ast_with_span_map(db, node.value, db.span_map(node.file_id).as_ref())
|
||||
}
|
||||
|
||||
pub(crate) fn from_opt_ast_with_span_map(
|
||||
db: &dyn DefDatabase,
|
||||
node: Option<ast::Visibility>,
|
||||
span_map: SpanMapRef<'_>,
|
||||
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
|
||||
) -> RawVisibility {
|
||||
let node = match node {
|
||||
None => return RawVisibility::private(),
|
||||
Some(node) => node,
|
||||
};
|
||||
Self::from_ast_with_span_map(db, node, span_map)
|
||||
Self::from_ast_with_span_map(db, node, span_for_range)
|
||||
}
|
||||
|
||||
fn from_ast_with_span_map(
|
||||
db: &dyn DefDatabase,
|
||||
node: ast::Visibility,
|
||||
span_map: SpanMapRef<'_>,
|
||||
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
|
||||
) -> RawVisibility {
|
||||
let path = match node.kind() {
|
||||
ast::VisibilityKind::In(path) => {
|
||||
let path = ModPath::from_src(db.upcast(), path, span_map);
|
||||
let path = ModPath::from_src(db.upcast(), path, span_for_range);
|
||||
match path {
|
||||
None => return RawVisibility::private(),
|
||||
Some(path) => path,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue