From f08109bd2d2fdfe52b0443d5db2f33934aeca5c3 Mon Sep 17 00:00:00 2001 From: Daniel Frampton Date: Mon, 4 Jan 2021 12:56:21 -0800 Subject: Introduce new queries to compute 1) the set of attributes for all variants of an enum, and 2) the set of attributes for all fields of a variant. This avoids the current n^2 behavior when rendering completion for variants, which prevents completion for enums with large numbers of variants. --- crates/hir_def/src/attr.rs | 56 +++++++++++++++++++++++++++++++++++++--------- crates/hir_def/src/db.rs | 11 +++++++-- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 6b79e7bad..9e6426b31 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs @@ -2,6 +2,7 @@ use std::{ops, sync::Arc}; +use arena::map::ArenaMap; use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use either::Either; @@ -21,7 +22,8 @@ use crate::{ nameres::ModuleSource, path::{ModPath, PathKind}, src::HasChildSource, - AdtId, AttrDefId, GenericParamId, Lookup, + AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, + VariantId, }; /// Holds documentation @@ -210,16 +212,10 @@ impl Attrs { } } AttrDefId::FieldId(it) => { - let src = it.parent.child_source(db); - match &src.value[it.local_id] { - Either::Left(_tuple) => RawAttrs::default(), - Either::Right(record) => RawAttrs::from_attrs_owner(db, src.with_value(record)), - } + return db.fields_attrs(it.parent)[it.local_id].clone(); } - AttrDefId::EnumVariantId(var_id) => { - let src = var_id.parent.child_source(db); - let src = src.as_ref().map(|it| &it[var_id.local_id]); - RawAttrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) + AttrDefId::EnumVariantId(it) => { + return db.variants_attrs(it.parent)[it.local_id].clone(); } AttrDefId::AdtId(it) => match it { AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), @@ -259,6 +255,46 @@ impl Attrs { raw_attrs.filter(db, def.krate(db)) } + pub(crate) fn variants_attrs_query( + db: &dyn DefDatabase, + e: EnumId, + ) -> Arc> { + let krate = e.lookup(db).container.module(db).krate; + let src = e.child_source(db); + let mut res = ArenaMap::default(); + + for (id, var) in src.value.iter() { + let attrs = RawAttrs::from_attrs_owner(db, src.with_value(var as &dyn AttrsOwner)) + .filter(db, krate); + + res.insert(id, attrs) + } + + Arc::new(res) + } + + pub(crate) fn fields_attrs_query( + db: &dyn DefDatabase, + v: VariantId, + ) -> Arc> { + let krate = v.module(db).krate; + let src = v.child_source(db); + let mut res = ArenaMap::default(); + + for (id, fld) in src.value.iter() { + let attrs = match fld { + Either::Left(_tuple) => Attrs::default(), + Either::Right(record) => { + RawAttrs::from_attrs_owner(db, src.with_value(record)).filter(db, krate) + } + }; + + res.insert(id, attrs); + } + + Arc::new(res) + } + pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { AttrQuery { attrs: self, key } } diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index d1a459066..d3bf5b34c 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs @@ -1,6 +1,7 @@ //! Defines database & queries for name resolution. use std::sync::Arc; +use arena::map::ArenaMap; use base_db::{salsa, CrateId, SourceDatabase, Upcast}; use hir_expand::{db::AstDatabase, HirFileId}; use syntax::SmolStr; @@ -16,8 +17,8 @@ use crate::{ lang_item::{LangItemTarget, LangItems}, nameres::CrateDefMap, AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, - GenericDefId, ImplId, ImplLoc, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, - TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, + GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, StaticLoc, StructId, + StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -92,6 +93,12 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast { #[salsa::invoke(GenericParams::generic_params_query)] fn generic_params(&self, def: GenericDefId) -> Arc; + #[salsa::invoke(Attrs::variants_attrs_query)] + fn variants_attrs(&self, def: EnumId) -> Arc>; + + #[salsa::invoke(Attrs::fields_attrs_query)] + fn fields_attrs(&self, def: VariantId) -> Arc>; + #[salsa::invoke(Attrs::attrs_query)] fn attrs(&self, def: AttrDefId) -> Attrs; -- cgit v1.2.3