pack enum variants into arena

This commit is contained in:
Aleksey Kladov 2019-01-25 12:41:23 +03:00
parent c4a351b736
commit 87288d802c
7 changed files with 54 additions and 73 deletions

View file

@ -3,6 +3,7 @@
use std::sync::Arc;
use ra_arena::{RawId, Arena, impl_arena_id};
use ra_syntax::{
TreeArc,
ast::{self, NameOwner, StructFlavor}
@ -12,7 +13,6 @@ use crate::{
Name, AsName, Struct, Enum, EnumVariant, Crate,
HirDatabase, HirFileId,
type_ref::TypeRef,
ids::LocationCtx,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@ -66,43 +66,47 @@ fn variants(enum_def: &ast::EnumDef) -> impl Iterator<Item = &ast::EnumVariant>
}
impl EnumVariant {
pub fn source_impl(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumVariant>) {
pub(crate) fn source_impl(
&self,
db: &impl HirDatabase,
) -> (HirFileId, TreeArc<ast::EnumVariant>) {
let (file_id, enum_def) = self.parent.source(db);
let var = variants(&*enum_def)
.nth(self.idx as usize)
.zip(db.enum_data(self.parent).variants.iter())
.find(|(_syntax, (id, _))| *id == self.id)
.unwrap()
.0
.to_owned();
(file_id, var)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct EnumVariantId(RawId);
impl_arena_id!(EnumVariantId);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumData {
pub(crate) name: Option<Name>,
pub(crate) variants: Vec<(Name, EnumVariant)>,
pub(crate) variants: Arena<EnumVariantId, EnumVariantData>,
}
impl EnumData {
fn new(enum_def: &ast::EnumDef, variants: Vec<(Name, EnumVariant)>) -> Self {
let name = enum_def.name().map(|n| n.as_name());
EnumData { name, variants }
}
pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc<EnumData> {
let (_file_id, enum_def) = e.source(db);
let variants = variants(&*enum_def)
.enumerate()
.filter_map(|(idx, variant_def)| {
let name = variant_def.name()?.as_name();
let var = EnumVariant {
parent: e,
idx: idx as u32,
};
Some((name, var))
})
.collect();
let mut res = EnumData {
name: enum_def.name().map(|n| n.as_name()),
variants: Arena::default(),
};
for var in variants(&*enum_def) {
let data = EnumVariantData {
name: var.name().map(|it| it.as_name()),
variant_data: Arc::new(VariantData::new(var.flavor())),
};
res.variants.alloc(data);
}
Arc::new(EnumData::new(&*enum_def, variants))
Arc::new(res)
}
}
@ -110,33 +114,6 @@ impl EnumData {
pub struct EnumVariantData {
pub(crate) name: Option<Name>,
pub(crate) variant_data: Arc<VariantData>,
pub(crate) parent_enum: Enum,
}
impl EnumVariantData {
fn new(variant_def: &ast::EnumVariant, parent_enum: Enum) -> EnumVariantData {
let name = variant_def.name().map(|n| n.as_name());
let variant_data = VariantData::new(variant_def.flavor());
let variant_data = Arc::new(variant_data);
EnumVariantData {
name,
variant_data,
parent_enum,
}
}
pub(crate) fn enum_variant_data_query(
db: &impl HirDatabase,
var: EnumVariant,
) -> Arc<EnumVariantData> {
let (file_id, variant_def) = var.source(db);
let enum_def = variant_def.parent_enum();
let ctx = LocationCtx::new(db, var.module(db), file_id);
let e = Enum {
id: ctx.to_def(enum_def),
};
Arc::new(EnumVariantData::new(&*variant_def, e))
}
}
/// A single field of an enum variant or struct

View file

@ -11,7 +11,7 @@ use crate::{
db::HirDatabase,
expr::BodySyntaxMapping,
ty::{InferenceResult, VariantDef},
adt::VariantData,
adt::{VariantData, EnumVariantId},
generics::GenericParams,
docs::{Documentation, Docs, docs_from_ast},
module_tree::ModuleId,
@ -252,8 +252,20 @@ impl Enum {
db.enum_data(*self).name.clone()
}
pub fn variants(&self, db: &impl HirDatabase) -> Vec<(Name, EnumVariant)> {
db.enum_data(*self).variants.clone()
pub fn variants(&self, db: &impl HirDatabase) -> Vec<EnumVariant> {
db.enum_data(*self)
.variants
.iter()
.map(|(id, _)| EnumVariant { parent: *self, id })
.collect()
}
pub fn variant(&self, db: &impl HirDatabase, name: &Name) -> Option<EnumVariant> {
db.enum_data(*self)
.variants
.iter()
.find(|(_id, data)| data.name.as_ref() == Some(name))
.map(|(id, _)| EnumVariant { parent: *self, id })
}
pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
@ -270,7 +282,7 @@ impl Docs for Enum {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EnumVariant {
pub(crate) parent: Enum,
pub(crate) idx: u32,
pub(crate) id: EnumVariantId,
}
impl EnumVariant {
@ -285,11 +297,13 @@ impl EnumVariant {
}
pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
db.enum_variant_data(*self).name.clone()
db.enum_data(self.parent).variants[self.id].name.clone()
}
pub fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> {
db.enum_variant_data(*self).variant_data.clone()
db.enum_data(self.parent).variants[self.id]
.variant_data
.clone()
}
pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> {

View file

@ -8,12 +8,12 @@ use crate::{
SourceFileItems, SourceItemId, Crate, Module, HirInterner,
query_definitions,
Function, FnSignature, FnScopes,
Struct, Enum, EnumVariant,
Struct, Enum,
macros::MacroExpansion,
module_tree::ModuleTree,
nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, VariantDef},
adt::{StructData, EnumData, EnumVariantData},
adt::{StructData, EnumData},
impl_block::ModuleImplBlocks,
generics::{GenericParams, GenericDef},
};
@ -35,9 +35,6 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
#[salsa::invoke(crate::adt::EnumData::enum_data_query)]
fn enum_data(&self, e: Enum) -> Arc<EnumData>;
#[salsa::invoke(crate::adt::EnumVariantData::enum_variant_data_query)]
fn enum_variant_data(&self, var: EnumVariant) -> Arc<EnumVariantData>;
#[salsa::invoke(crate::ty::infer)]
fn infer(&self, func: Function) -> Arc<InferenceResult>;

View file

@ -231,7 +231,6 @@ salsa::database_storage! {
fn type_for_field() for db::TypeForFieldQuery;
fn struct_data() for db::StructDataQuery;
fn enum_data() for db::EnumDataQuery;
fn enum_variant_data() for db::EnumVariantDataQuery;
fn impls_in_module() for db::ImplsInModuleQuery;
fn impls_in_crate() for db::ImplsInCrateQuery;
fn body_hir() for db::BodyHirQuery;

View file

@ -397,13 +397,8 @@ impl ItemMap {
ModuleDef::Enum(e) => {
// enum variant
tested_by!(item_map_enum_importing);
let matching_variant = e
.variants(db)
.into_iter()
.find(|(n, _variant)| n == &segment.name);
match matching_variant {
Some((_n, variant)) => PerNs::both(variant.into(), (*e).into()),
match e.variant(db, &segment.name) {
Some(variant) => PerNs::both(variant.into(), (*e).into()),
None => PerNs::none(),
}
}

View file

@ -27,18 +27,18 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
}
}
hir::ModuleDef::Enum(e) => {
e.variants(ctx.db)
.into_iter()
.for_each(|(variant_name, variant)| {
e.variants(ctx.db).into_iter().for_each(|variant| {
if let Some(name) = variant.name(ctx.db) {
CompletionItem::new(
CompletionKind::Reference,
ctx.source_range(),
variant_name.to_string(),
name.to_string(),
)
.kind(CompletionItemKind::EnumVariant)
.set_documentation(variant.docs(ctx.db))
.add_to(acc)
});
}
});
}
_ => return,
};

View file

@ -104,7 +104,6 @@ salsa::database_storage! {
fn type_for_field() for hir::db::TypeForFieldQuery;
fn struct_data() for hir::db::StructDataQuery;
fn enum_data() for hir::db::EnumDataQuery;
fn enum_variant_data() for hir::db::EnumVariantDataQuery;
fn impls_in_module() for hir::db::ImplsInModuleQuery;
fn impls_in_crate() for hir::db::ImplsInCrateQuery;
fn body_hir() for hir::db::BodyHirQuery;