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

View file

@ -74,8 +74,53 @@ impl GenericParams {
def: GenericDefId, def: GenericDefId,
) -> Arc<GenericParams> { ) -> Arc<GenericParams> {
let _p = profile("generic_params_query"); 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>) { 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. /// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type.
fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>>; 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. /// Trait for item tree nodes that allow accessing the original AST node.
@ -232,6 +235,10 @@ macro_rules! nodes {
None 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); 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 generics
} }

View file

@ -200,7 +200,7 @@ fn simple_inner_items() {
inner attrs: Attrs { entries: None } inner attrs: Attrs { entries: None }
top-level items: 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: inner items:
FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(2): FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(2):