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 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 10 deletions(-) (limited to 'crates/hir_def/src/attr.rs') 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 } } -- cgit v1.2.3