Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/src.rs')
-rw-r--r--crates/hir-def/src/src.rs106
1 files changed, 48 insertions, 58 deletions
diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs
index 3867f39b8b..aa373a27b0 100644
--- a/crates/hir-def/src/src.rs
+++ b/crates/hir-def/src/src.rs
@@ -1,15 +1,13 @@
//! Utilities for mapping between hir IDs and the surface syntax.
use either::Either;
-use hir_expand::InFile;
-use la_arena::ArenaMap;
+use hir_expand::{AstId, InFile};
+use la_arena::{Arena, ArenaMap, Idx};
use syntax::{AstNode, AstPtr, ast};
use crate::{
- GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup,
- UseId, VariantId,
- db::DefDatabase,
- item_tree::{AttrOwner, FieldParent, ItemTreeNode},
+ AstIdLoc, GenericDefId, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup,
+ UseId, VariantId, attr::Attrs, db::DefDatabase,
};
pub trait HasSource {
@@ -23,18 +21,13 @@ pub trait HasSource {
impl<T> HasSource for T
where
- T: ItemTreeLoc,
- T::Id: ItemTreeNode,
+ T: AstIdLoc,
{
- type Value = <T::Id as ItemTreeNode>::Source;
+ type Value = T::Ast;
fn ast_ptr(&self, db: &dyn DefDatabase) -> InFile<AstPtr<Self::Value>> {
- let id = self.item_tree_id();
- let file_id = id.file_id();
- let tree = id.item_tree(db);
- let ast_id_map = db.ast_id_map(file_id);
- let node = &tree[id.value];
-
- InFile::new(file_id, ast_id_map.get(node.ast_id()))
+ let id = self.ast_id();
+ let ast_id_map = db.ast_id_map(id.file_id);
+ InFile::new(id.file_id, ast_id_map.get(id.value))
}
}
@@ -43,18 +36,37 @@ pub trait HasChildSource<ChildId> {
fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<ChildId, Self::Value>>;
}
+/// Maps a `UseTree` contained in this import back to its AST node.
+pub fn use_tree_to_ast(
+ db: &dyn DefDatabase,
+ use_ast_id: AstId<ast::Use>,
+ index: Idx<ast::UseTree>,
+) -> ast::UseTree {
+ use_tree_source_map(db, use_ast_id)[index].clone()
+}
+
+/// Maps a `UseTree` contained in this import back to its AST node.
+fn use_tree_source_map(db: &dyn DefDatabase, use_ast_id: AstId<ast::Use>) -> Arena<ast::UseTree> {
+ // Re-lower the AST item and get the source map.
+ // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
+ let ast = use_ast_id.to_node(db);
+ let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
+ let mut span_map = None;
+ crate::item_tree::lower_use_tree(db, ast_use_tree, &mut |range| {
+ span_map.get_or_insert_with(|| db.span_map(use_ast_id.file_id)).span_for_range(range).ctx
+ })
+ .expect("failed to lower use tree")
+ .1
+}
+
impl HasChildSource<la_arena::Idx<ast::UseTree>> for UseId {
type Value = ast::UseTree;
fn child_source(
&self,
db: &dyn DefDatabase,
) -> InFile<ArenaMap<la_arena::Idx<ast::UseTree>, Self::Value>> {
- let loc = &self.lookup(db);
- let use_ = &loc.id.item_tree(db)[loc.id.value];
- InFile::new(
- loc.id.file_id(),
- use_.use_tree_source_map(db, loc.id.file_id()).into_iter().collect(),
- )
+ let loc = self.lookup(db);
+ InFile::new(loc.id.file_id, use_tree_source_map(db, loc.id).into_iter().collect())
}
}
@@ -124,49 +136,30 @@ impl HasChildSource<LocalFieldId> for VariantId {
type Value = Either<ast::TupleField, ast::RecordField>;
fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> {
- let item_tree;
- let (src, parent, container) = match *self {
+ let (src, container) = match *self {
VariantId::EnumVariantId(it) => {
let lookup = it.lookup(db);
- item_tree = lookup.id.item_tree(db);
- (
- lookup.source(db).map(|it| it.kind()),
- FieldParent::EnumVariant(lookup.id.value),
- lookup.parent.lookup(db).container,
- )
+ (lookup.source(db).map(|it| it.kind()), lookup.parent.lookup(db).container)
}
VariantId::StructId(it) => {
let lookup = it.lookup(db);
- item_tree = lookup.id.item_tree(db);
- (
- lookup.source(db).map(|it| it.kind()),
- FieldParent::Struct(lookup.id.value),
- lookup.container,
- )
+ (lookup.source(db).map(|it| it.kind()), lookup.container)
}
VariantId::UnionId(it) => {
let lookup = it.lookup(db);
- item_tree = lookup.id.item_tree(db);
- (
- lookup.source(db).map(|it| it.kind()),
- FieldParent::Union(lookup.id.value),
- lookup.container,
- )
+ (lookup.source(db).map(|it| it.kind()), lookup.container)
}
};
-
+ let span_map = db.span_map(src.file_id);
let mut map = ArenaMap::new();
match &src.value {
ast::StructKind::Tuple(fl) => {
let cfg_options = container.krate.cfg_options(db);
let mut idx = 0;
- for (i, fd) in fl.fields().enumerate() {
- let attrs = item_tree.attrs(
- db,
- container.krate,
- AttrOwner::make_field_indexed(parent, i),
- );
- if !attrs.is_cfg_enabled(cfg_options) {
+ for fd in fl.fields() {
+ let enabled =
+ Attrs::is_cfg_enabled_for(db, &fd, span_map.as_ref(), cfg_options).is_ok();
+ if !enabled {
continue;
}
map.insert(
@@ -179,13 +172,10 @@ impl HasChildSource<LocalFieldId> for VariantId {
ast::StructKind::Record(fl) => {
let cfg_options = container.krate.cfg_options(db);
let mut idx = 0;
- for (i, fd) in fl.fields().enumerate() {
- let attrs = item_tree.attrs(
- db,
- container.krate,
- AttrOwner::make_field_indexed(parent, i),
- );
- if !attrs.is_cfg_enabled(cfg_options) {
+ for fd in fl.fields() {
+ let enabled =
+ Attrs::is_cfg_enabled_for(db, &fd, span_map.as_ref(), cfg_options).is_ok();
+ if !enabled {
continue;
}
map.insert(
@@ -195,7 +185,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
idx += 1;
}
}
- _ => (),
+ ast::StructKind::Unit => (),
}
InFile::new(src.file_id, map)
}