mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
pack enum variants into arena
This commit is contained in:
parent
c4a351b736
commit
87288d802c
7 changed files with 54 additions and 73 deletions
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use ra_arena::{RawId, Arena, impl_arena_id};
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
TreeArc,
|
TreeArc,
|
||||||
ast::{self, NameOwner, StructFlavor}
|
ast::{self, NameOwner, StructFlavor}
|
||||||
|
@ -12,7 +13,6 @@ use crate::{
|
||||||
Name, AsName, Struct, Enum, EnumVariant, Crate,
|
Name, AsName, Struct, Enum, EnumVariant, Crate,
|
||||||
HirDatabase, HirFileId,
|
HirDatabase, HirFileId,
|
||||||
type_ref::TypeRef,
|
type_ref::TypeRef,
|
||||||
ids::LocationCtx,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
@ -66,43 +66,47 @@ fn variants(enum_def: &ast::EnumDef) -> impl Iterator<Item = &ast::EnumVariant>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 (file_id, enum_def) = self.parent.source(db);
|
||||||
let var = variants(&*enum_def)
|
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()
|
.unwrap()
|
||||||
|
.0
|
||||||
.to_owned();
|
.to_owned();
|
||||||
(file_id, var)
|
(file_id, var)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub(crate) struct EnumVariantId(RawId);
|
||||||
|
impl_arena_id!(EnumVariantId);
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct EnumData {
|
pub struct EnumData {
|
||||||
pub(crate) name: Option<Name>,
|
pub(crate) name: Option<Name>,
|
||||||
pub(crate) variants: Vec<(Name, EnumVariant)>,
|
pub(crate) variants: Arena<EnumVariantId, EnumVariantData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnumData {
|
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> {
|
pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc<EnumData> {
|
||||||
let (_file_id, enum_def) = e.source(db);
|
let (_file_id, enum_def) = e.source(db);
|
||||||
let variants = variants(&*enum_def)
|
let mut res = EnumData {
|
||||||
.enumerate()
|
name: enum_def.name().map(|n| n.as_name()),
|
||||||
.filter_map(|(idx, variant_def)| {
|
variants: Arena::default(),
|
||||||
let name = variant_def.name()?.as_name();
|
};
|
||||||
let var = EnumVariant {
|
for var in variants(&*enum_def) {
|
||||||
parent: e,
|
let data = EnumVariantData {
|
||||||
idx: idx as u32,
|
name: var.name().map(|it| it.as_name()),
|
||||||
};
|
variant_data: Arc::new(VariantData::new(var.flavor())),
|
||||||
Some((name, var))
|
};
|
||||||
})
|
res.variants.alloc(data);
|
||||||
.collect();
|
}
|
||||||
|
|
||||||
Arc::new(EnumData::new(&*enum_def, variants))
|
Arc::new(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,33 +114,6 @@ impl EnumData {
|
||||||
pub struct EnumVariantData {
|
pub struct EnumVariantData {
|
||||||
pub(crate) name: Option<Name>,
|
pub(crate) name: Option<Name>,
|
||||||
pub(crate) variant_data: Arc<VariantData>,
|
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
|
/// A single field of an enum variant or struct
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
expr::BodySyntaxMapping,
|
expr::BodySyntaxMapping,
|
||||||
ty::{InferenceResult, VariantDef},
|
ty::{InferenceResult, VariantDef},
|
||||||
adt::VariantData,
|
adt::{VariantData, EnumVariantId},
|
||||||
generics::GenericParams,
|
generics::GenericParams,
|
||||||
docs::{Documentation, Docs, docs_from_ast},
|
docs::{Documentation, Docs, docs_from_ast},
|
||||||
module_tree::ModuleId,
|
module_tree::ModuleId,
|
||||||
|
@ -252,8 +252,20 @@ impl Enum {
|
||||||
db.enum_data(*self).name.clone()
|
db.enum_data(*self).name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn variants(&self, db: &impl HirDatabase) -> Vec<(Name, EnumVariant)> {
|
pub fn variants(&self, db: &impl HirDatabase) -> Vec<EnumVariant> {
|
||||||
db.enum_data(*self).variants.clone()
|
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> {
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct EnumVariant {
|
pub struct EnumVariant {
|
||||||
pub(crate) parent: Enum,
|
pub(crate) parent: Enum,
|
||||||
pub(crate) idx: u32,
|
pub(crate) id: EnumVariantId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnumVariant {
|
impl EnumVariant {
|
||||||
|
@ -285,11 +297,13 @@ impl EnumVariant {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
|
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> {
|
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> {
|
pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> {
|
||||||
|
|
|
@ -8,12 +8,12 @@ use crate::{
|
||||||
SourceFileItems, SourceItemId, Crate, Module, HirInterner,
|
SourceFileItems, SourceItemId, Crate, Module, HirInterner,
|
||||||
query_definitions,
|
query_definitions,
|
||||||
Function, FnSignature, FnScopes,
|
Function, FnSignature, FnScopes,
|
||||||
Struct, Enum, EnumVariant,
|
Struct, Enum,
|
||||||
macros::MacroExpansion,
|
macros::MacroExpansion,
|
||||||
module_tree::ModuleTree,
|
module_tree::ModuleTree,
|
||||||
nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
|
nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
|
||||||
ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, VariantDef},
|
ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, VariantDef},
|
||||||
adt::{StructData, EnumData, EnumVariantData},
|
adt::{StructData, EnumData},
|
||||||
impl_block::ModuleImplBlocks,
|
impl_block::ModuleImplBlocks,
|
||||||
generics::{GenericParams, GenericDef},
|
generics::{GenericParams, GenericDef},
|
||||||
};
|
};
|
||||||
|
@ -35,9 +35,6 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
|
||||||
#[salsa::invoke(crate::adt::EnumData::enum_data_query)]
|
#[salsa::invoke(crate::adt::EnumData::enum_data_query)]
|
||||||
fn enum_data(&self, e: Enum) -> Arc<EnumData>;
|
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)]
|
#[salsa::invoke(crate::ty::infer)]
|
||||||
fn infer(&self, func: Function) -> Arc<InferenceResult>;
|
fn infer(&self, func: Function) -> Arc<InferenceResult>;
|
||||||
|
|
||||||
|
|
|
@ -231,7 +231,6 @@ salsa::database_storage! {
|
||||||
fn type_for_field() for db::TypeForFieldQuery;
|
fn type_for_field() for db::TypeForFieldQuery;
|
||||||
fn struct_data() for db::StructDataQuery;
|
fn struct_data() for db::StructDataQuery;
|
||||||
fn enum_data() for db::EnumDataQuery;
|
fn enum_data() for db::EnumDataQuery;
|
||||||
fn enum_variant_data() for db::EnumVariantDataQuery;
|
|
||||||
fn impls_in_module() for db::ImplsInModuleQuery;
|
fn impls_in_module() for db::ImplsInModuleQuery;
|
||||||
fn impls_in_crate() for db::ImplsInCrateQuery;
|
fn impls_in_crate() for db::ImplsInCrateQuery;
|
||||||
fn body_hir() for db::BodyHirQuery;
|
fn body_hir() for db::BodyHirQuery;
|
||||||
|
|
|
@ -397,13 +397,8 @@ impl ItemMap {
|
||||||
ModuleDef::Enum(e) => {
|
ModuleDef::Enum(e) => {
|
||||||
// enum variant
|
// enum variant
|
||||||
tested_by!(item_map_enum_importing);
|
tested_by!(item_map_enum_importing);
|
||||||
let matching_variant = e
|
match e.variant(db, &segment.name) {
|
||||||
.variants(db)
|
Some(variant) => PerNs::both(variant.into(), (*e).into()),
|
||||||
.into_iter()
|
|
||||||
.find(|(n, _variant)| n == &segment.name);
|
|
||||||
|
|
||||||
match matching_variant {
|
|
||||||
Some((_n, variant)) => PerNs::both(variant.into(), (*e).into()),
|
|
||||||
None => PerNs::none(),
|
None => PerNs::none(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,18 +27,18 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ModuleDef::Enum(e) => {
|
hir::ModuleDef::Enum(e) => {
|
||||||
e.variants(ctx.db)
|
e.variants(ctx.db).into_iter().for_each(|variant| {
|
||||||
.into_iter()
|
if let Some(name) = variant.name(ctx.db) {
|
||||||
.for_each(|(variant_name, variant)| {
|
|
||||||
CompletionItem::new(
|
CompletionItem::new(
|
||||||
CompletionKind::Reference,
|
CompletionKind::Reference,
|
||||||
ctx.source_range(),
|
ctx.source_range(),
|
||||||
variant_name.to_string(),
|
name.to_string(),
|
||||||
)
|
)
|
||||||
.kind(CompletionItemKind::EnumVariant)
|
.kind(CompletionItemKind::EnumVariant)
|
||||||
.set_documentation(variant.docs(ctx.db))
|
.set_documentation(variant.docs(ctx.db))
|
||||||
.add_to(acc)
|
.add_to(acc)
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
|
@ -104,7 +104,6 @@ salsa::database_storage! {
|
||||||
fn type_for_field() for hir::db::TypeForFieldQuery;
|
fn type_for_field() for hir::db::TypeForFieldQuery;
|
||||||
fn struct_data() for hir::db::StructDataQuery;
|
fn struct_data() for hir::db::StructDataQuery;
|
||||||
fn enum_data() for hir::db::EnumDataQuery;
|
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_module() for hir::db::ImplsInModuleQuery;
|
||||||
fn impls_in_crate() for hir::db::ImplsInCrateQuery;
|
fn impls_in_crate() for hir::db::ImplsInCrateQuery;
|
||||||
fn body_hir() for hir::db::BodyHirQuery;
|
fn body_hir() for hir::db::BodyHirQuery;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue