From 035d84558cb777806d8c02234051843194459aee Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 6 Apr 2021 22:25:44 +0200 Subject: =?UTF-8?q?Avoid=20O(n=C2=B2)=20when=20constructing=20AttrSourceMa?= =?UTF-8?q?p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/hir_def/src/attr.rs | 57 ++++++++++++++++++++++++++++++++------- crates/hir_def/src/db.rs | 15 ++++++++++- crates/hir_def/src/lib.rs | 8 ++++++ crates/ide_db/src/apply_change.rs | 4 +++ 4 files changed, 74 insertions(+), 10 deletions(-) diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 8a25b8731..d9df7564d 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs @@ -16,7 +16,7 @@ use mbe::ast_to_token_tree; use smallvec::{smallvec, SmallVec}; use syntax::{ ast::{self, AstNode, AttrsOwner}, - match_ast, AstToken, SmolStr, SyntaxNode, TextRange, TextSize, + match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize, }; use tt::Subtree; @@ -403,10 +403,14 @@ impl AttrsWithOwner { return AttrSourceMap { attrs }; } AttrDefId::FieldId(id) => { - id.parent.child_source(db).map(|source| match &source[id.local_id] { - Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()), - Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()), - }) + let map = db.fields_attrs_source_map(id.parent); + let file_id = id.parent.file_id(db); + let root = db.parse_or_expand(file_id).unwrap(); + let owner = match &map[id.local_id] { + Either::Left(it) => ast::AttrsOwnerNode::new(it.to_node(&root)), + Either::Right(it) => ast::AttrsOwnerNode::new(it.to_node(&root)), + }; + InFile::new(file_id, owner) } AttrDefId::AdtId(adt) => match adt { AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), @@ -414,10 +418,12 @@ impl AttrsWithOwner { AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), }, AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), - AttrDefId::EnumVariantId(id) => id - .parent - .child_source(db) - .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), + AttrDefId::EnumVariantId(id) => { + let map = db.variants_attrs_source_map(id.parent); + let file_id = id.parent.lookup(db).id.file_id(); + let root = db.parse_or_expand(file_id).unwrap(); + InFile::new(file_id, ast::AttrsOwnerNode::new(map[id.local_id].to_node(&root))) + } AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), @@ -746,3 +752,36 @@ fn collect_attrs( attrs.into_iter().map(|(_, attr)| attr) } + +pub(crate) fn variants_attrs_source_map( + db: &dyn DefDatabase, + def: EnumId, +) -> Arc>> { + let mut res = ArenaMap::default(); + let child_source = def.child_source(db); + + for (idx, variant) in child_source.value.iter() { + res.insert(idx, AstPtr::new(variant)); + } + + Arc::new(res) +} + +pub(crate) fn fields_attrs_source_map( + db: &dyn DefDatabase, + def: VariantId, +) -> Arc, AstPtr>>> { + let mut res = ArenaMap::default(); + let child_source = def.child_source(db); + + for (idx, variant) in child_source.value.iter() { + res.insert( + idx, + variant + .as_ref() + .either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))), + ); + } + + Arc::new(res) +} diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 9b7a213a1..7eadc8e0d 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs @@ -2,9 +2,10 @@ use std::sync::Arc; use base_db::{salsa, CrateId, SourceDatabase, Upcast}; +use either::Either; use hir_expand::{db::AstDatabase, HirFileId}; use la_arena::ArenaMap; -use syntax::SmolStr; +use syntax::{ast, AstPtr, SmolStr}; use crate::{ adt::{EnumData, StructData}, @@ -122,6 +123,18 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast { #[salsa::invoke(Attrs::fields_attrs_query)] fn fields_attrs(&self, def: VariantId) -> Arc>; + #[salsa::invoke(crate::attr::variants_attrs_source_map)] + fn variants_attrs_source_map( + &self, + def: EnumId, + ) -> Arc>>; + + #[salsa::invoke(crate::attr::fields_attrs_source_map)] + fn fields_attrs_source_map( + &self, + def: VariantId, + ) -> Arc, AstPtr>>>; + #[salsa::invoke(AttrsWithOwner::attrs_query)] fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index abd6c553f..e2af0e514 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs @@ -453,6 +453,14 @@ impl VariantId { } } } + + pub fn file_id(self, db: &dyn db::DefDatabase) -> HirFileId { + match self { + VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(), + VariantId::StructId(it) => it.lookup(db).id.file_id(), + VariantId::UnionId(it) => it.lookup(db).id.file_id(), + } + } } trait Intern { diff --git a/crates/ide_db/src/apply_change.rs b/crates/ide_db/src/apply_change.rs index 111e9325a..6c67425d7 100644 --- a/crates/ide_db/src/apply_change.rs +++ b/crates/ide_db/src/apply_change.rs @@ -152,6 +152,10 @@ impl RootDatabase { hir::db::FileItemTreeQuery hir::db::BlockDefMapQuery hir::db::CrateDefMapQueryQuery + hir::db::FieldsAttrsQuery + hir::db::VariantsAttrsQuery + hir::db::FieldsAttrsSourceMapQuery + hir::db::VariantsAttrsSourceMapQuery hir::db::StructDataQuery hir::db::UnionDataQuery hir::db::EnumDataQuery -- cgit v1.2.3