Make generics and attr queries use ItemTree

Now it's fast
This commit is contained in:
Jonas Schievink 2020-06-22 19:15:54 +02:00
parent 19586bc5c6
commit ffa0435050
5 changed files with 79 additions and 21 deletions

View file

@ -13,7 +13,11 @@ use ra_syntax::{
use tt::Subtree;
use crate::{
db::DefDatabase, nameres::ModuleSource, path::ModPath, src::HasChildSource, src::HasSource,
db::DefDatabase,
item_tree::{ItemTreeId, ItemTreeNode},
nameres::ModuleSource,
path::ModPath,
src::HasChildSource,
AdtId, AttrDefId, Lookup,
};
@ -65,19 +69,19 @@ impl Attrs {
Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
}
AttrDefId::AdtId(it) => match it {
AdtId::StructId(it) => attrs_from_loc(it.lookup(db), db),
AdtId::EnumId(it) => attrs_from_loc(it.lookup(db), db),
AdtId::UnionId(it) => attrs_from_loc(it.lookup(db), db),
AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
},
AttrDefId::TraitId(it) => attrs_from_loc(it.lookup(db), db),
AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::MacroDefId(it) => {
it.ast_id.map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db))
}
AttrDefId::ImplId(it) => attrs_from_loc(it.lookup(db), db),
AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db),
AttrDefId::StaticId(it) => attrs_from_loc(it.lookup(db), db),
AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db),
AttrDefId::TypeAliasId(it) => attrs_from_loc(it.lookup(db), db),
AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
}
}
@ -187,11 +191,8 @@ where
Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
}
fn attrs_from_loc<T>(node: T, db: &dyn DefDatabase) -> Attrs
where
T: HasSource,
T::Value: ast::AttrsOwner,
{
let src = node.source(db);
Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> Attrs {
let tree = db.item_tree(id.file_id);
let mod_item = N::id_to_mod_item(id.value);
tree.attrs(mod_item).clone()
}

View file

@ -74,8 +74,53 @@ impl GenericParams {
def: GenericDefId,
) -> Arc<GenericParams> {
let _p = profile("generic_params_query");
let (params, _source_map) = GenericParams::new(db, def);
Arc::new(params)
let generics = match def {
GenericDefId::FunctionId(id) => {
let id = id.lookup(db).id;
let tree = db.item_tree(id.file_id);
let item = &tree[id.value];
item.generic_params.clone()
}
GenericDefId::AdtId(AdtId::StructId(id)) => {
let id = id.lookup(db).id;
let tree = db.item_tree(id.file_id);
let item = &tree[id.value];
item.generic_params.clone()
}
GenericDefId::AdtId(AdtId::EnumId(id)) => {
let id = id.lookup(db).id;
let tree = db.item_tree(id.file_id);
let item = &tree[id.value];
item.generic_params.clone()
}
GenericDefId::AdtId(AdtId::UnionId(id)) => {
let id = id.lookup(db).id;
let tree = db.item_tree(id.file_id);
let item = &tree[id.value];
item.generic_params.clone()
}
GenericDefId::TraitId(id) => {
let id = id.lookup(db).id;
let tree = db.item_tree(id.file_id);
let item = &tree[id.value];
item.generic_params.clone()
}
GenericDefId::TypeAliasId(id) => {
let id = id.lookup(db).id;
let tree = db.item_tree(id.file_id);
let item = &tree[id.value];
item.generic_params.clone()
}
GenericDefId::ImplId(id) => {
let id = id.lookup(db).id;
let tree = db.item_tree(id.file_id);
let item = &tree[id.value];
item.generic_params.clone()
}
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => GenericParams::default(),
};
Arc::new(generics)
}
fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {

View file

@ -175,6 +175,9 @@ pub trait ItemTreeNode: Clone {
/// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type.
fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>>;
/// Upcasts a `FileItemTreeId` to a generic `ModItem`.
fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
}
/// Trait for item tree nodes that allow accessing the original AST node.
@ -232,6 +235,10 @@ macro_rules! nodes {
None
}
}
fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem {
ModItem::$node(id)
}
}
)+ };
}

View file

@ -553,7 +553,12 @@ impl Ctx {
generics.fill(&self.body_ctx, &mut sm, node);
}
GenericsOwner::Impl => {}
GenericsOwner::Impl => {
// Note that we don't add `Self` here: in `impl`s, `Self` is not a
// type-parameter, but rather is a type-alias for impl's target
// type, so this is handled by the resolver.
generics.fill(&self.body_ctx, &mut sm, node);
}
}
generics
}

View file

@ -200,7 +200,7 @@ fn simple_inner_items() {
inner attrs: Attrs { entries: None }
top-level items:
Impl { generic_params: GenericParams { types: Arena { len: 0, data: [] }, where_predicates: [] }, target_trait: Some(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("D"))] }, generic_args: [None] })), target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Response"))] }, generic_args: [Some(GenericArgs { args: [Type(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("T"))] }, generic_args: [None] }))], has_self_type: false, bindings: [] })] }), is_negative: false, items: [Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) }
Impl { generic_params: GenericParams { types: Arena { len: 1, data: [TypeParamData { name: Some(Name(Text("T"))), default: None, provenance: TypeParamList }] }, where_predicates: [WherePredicate { target: TypeRef(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("T"))] }, generic_args: [None] })), bound: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("A"))] }, generic_args: [None] }) }] }, target_trait: Some(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("D"))] }, generic_args: [None] })), target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Response"))] }, generic_args: [Some(GenericArgs { args: [Type(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("T"))] }, generic_args: [None] }))], has_self_type: false, bindings: [] })] }), is_negative: false, items: [Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) }
inner items:
FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(2):