Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/item_tree.rs')
| -rw-r--r-- | crates/hir-def/src/item_tree.rs | 168 |
1 files changed, 122 insertions, 46 deletions
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 74500fd76e..b39a3fece6 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -113,7 +113,7 @@ impl ItemTree { let ctx = lower::Ctx::new(db, file_id); let syntax = db.parse_or_expand(file_id); let mut top_attrs = None; - let (mut item_tree, mut source_maps) = match_ast! { + let (mut item_tree, source_maps) = match_ast! { match syntax { ast::SourceFile(file) => { top_attrs = Some(RawAttrs::new(db.upcast(), &file, ctx.span_map())); @@ -155,7 +155,6 @@ impl ItemTree { .clone() } else { item_tree.shrink_to_fit(); - source_maps.shrink_to_fit(); (Arc::new(item_tree), Arc::new(source_maps)) } } @@ -175,7 +174,7 @@ impl ItemTree { let block = loc.ast_id.to_node(db.upcast()); let ctx = lower::Ctx::new(db, loc.ast_id.file_id); - let (mut item_tree, mut source_maps) = ctx.lower_block(&block); + let (mut item_tree, source_maps) = ctx.lower_block(&block); if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() { EMPTY @@ -192,7 +191,6 @@ impl ItemTree { .clone() } else { item_tree.shrink_to_fit(); - source_maps.shrink_to_fit(); (Arc::new(item_tree), Arc::new(source_maps)) } } @@ -331,29 +329,59 @@ struct ItemTreeData { } #[derive(Default, Debug, Eq, PartialEq)] -pub struct GenericItemSourceMap { +pub struct ItemTreeSourceMaps { + all_concatenated: Box<[TypesSourceMap]>, + structs_offset: u32, + unions_offset: u32, + enum_generics_offset: u32, + variants_offset: u32, + consts_offset: u32, + statics_offset: u32, + trait_generics_offset: u32, + trait_alias_generics_offset: u32, + impls_offset: u32, + type_aliases_offset: u32, +} + +#[derive(Clone, Copy)] +pub struct GenericItemSourceMap<'a>(&'a [TypesSourceMap; 2]); + +impl<'a> GenericItemSourceMap<'a> { + #[inline] + pub fn item(self) -> &'a TypesSourceMap { + &self.0[0] + } + + #[inline] + pub fn generics(self) -> &'a TypesSourceMap { + &self.0[1] + } +} + +#[derive(Default, Debug, Eq, PartialEq)] +pub struct GenericItemSourceMapBuilder { pub item: TypesSourceMap, pub generics: TypesSourceMap, } #[derive(Default, Debug, Eq, PartialEq)] -pub struct ItemTreeSourceMaps { - functions: Vec<GenericItemSourceMap>, - structs: Vec<GenericItemSourceMap>, - unions: Vec<GenericItemSourceMap>, +struct ItemTreeSourceMapsBuilder { + functions: Vec<GenericItemSourceMapBuilder>, + structs: Vec<GenericItemSourceMapBuilder>, + unions: Vec<GenericItemSourceMapBuilder>, enum_generics: Vec<TypesSourceMap>, variants: Vec<TypesSourceMap>, consts: Vec<TypesSourceMap>, statics: Vec<TypesSourceMap>, trait_generics: Vec<TypesSourceMap>, trait_alias_generics: Vec<TypesSourceMap>, - impls: Vec<GenericItemSourceMap>, - type_aliases: Vec<GenericItemSourceMap>, + impls: Vec<GenericItemSourceMapBuilder>, + type_aliases: Vec<GenericItemSourceMapBuilder>, } -impl ItemTreeSourceMaps { - fn shrink_to_fit(&mut self) { - let ItemTreeSourceMaps { +impl ItemTreeSourceMapsBuilder { + fn build(self) -> ItemTreeSourceMaps { + let ItemTreeSourceMapsBuilder { functions, structs, unions, @@ -366,44 +394,92 @@ impl ItemTreeSourceMaps { impls, type_aliases, } = self; - functions.shrink_to_fit(); - structs.shrink_to_fit(); - unions.shrink_to_fit(); - enum_generics.shrink_to_fit(); - variants.shrink_to_fit(); - consts.shrink_to_fit(); - statics.shrink_to_fit(); - trait_generics.shrink_to_fit(); - trait_alias_generics.shrink_to_fit(); - impls.shrink_to_fit(); - type_aliases.shrink_to_fit(); + let structs_offset = functions.len() as u32 * 2; + let unions_offset = structs_offset + (structs.len() as u32 * 2); + let enum_generics_offset = unions_offset + (unions.len() as u32 * 2); + let variants_offset = enum_generics_offset + (enum_generics.len() as u32); + let consts_offset = variants_offset + (variants.len() as u32); + let statics_offset = consts_offset + (consts.len() as u32); + let trait_generics_offset = statics_offset + (statics.len() as u32); + let trait_alias_generics_offset = trait_generics_offset + (trait_generics.len() as u32); + let impls_offset = trait_alias_generics_offset + (trait_alias_generics.len() as u32); + let type_aliases_offset = impls_offset + (impls.len() as u32 * 2); + let all_concatenated = generics_concat(functions) + .chain(generics_concat(structs)) + .chain(generics_concat(unions)) + .chain(enum_generics) + .chain(variants) + .chain(consts) + .chain(statics) + .chain(trait_generics) + .chain(trait_alias_generics) + .chain(generics_concat(impls)) + .chain(generics_concat(type_aliases)) + .collect(); + return ItemTreeSourceMaps { + all_concatenated, + structs_offset, + unions_offset, + enum_generics_offset, + variants_offset, + consts_offset, + statics_offset, + trait_generics_offset, + trait_alias_generics_offset, + impls_offset, + type_aliases_offset, + }; + + fn generics_concat( + source_maps: Vec<GenericItemSourceMapBuilder>, + ) -> impl Iterator<Item = TypesSourceMap> { + source_maps.into_iter().flat_map(|it| [it.item, it.generics]) + } } } -macro_rules! index_source_maps { - ( $( $field:ident[$tree_id:ident] = $result:ident, )* ) => { - $( - impl Index<FileItemTreeId<$tree_id>> for ItemTreeSourceMaps { - type Output = $result; - fn index(&self, index: FileItemTreeId<$tree_id>) -> &Self::Output { - &self.$field[index.0.into_raw().into_u32() as usize] +impl ItemTreeSourceMaps { + #[inline] + fn generic_item(&self, offset: u32, index: u32) -> GenericItemSourceMap<'_> { + GenericItemSourceMap( + self.all_concatenated[(offset + (index * 2)) as usize..][..2].try_into().unwrap(), + ) + } + + #[inline] + fn non_generic_item(&self, offset: u32, index: u32) -> &TypesSourceMap { + &self.all_concatenated[(offset + index) as usize] + } + + #[inline] + pub fn function(&self, index: FileItemTreeId<Function>) -> GenericItemSourceMap<'_> { + self.generic_item(0, index.0.into_raw().into_u32()) + } +} + +macro_rules! index_item_source_maps { + ( $( $name:ident; $field:ident[$tree_id:ident]; $fn:ident; $ret:ty, )* ) => { + impl ItemTreeSourceMaps { + $( + #[inline] + pub fn $name(&self, index: FileItemTreeId<$tree_id>) -> $ret { + self.$fn(self.$field, index.0.into_raw().into_u32()) } - } - )* + )* + } }; } -index_source_maps! { - functions[Function] = GenericItemSourceMap, - structs[Struct] = GenericItemSourceMap, - unions[Union] = GenericItemSourceMap, - enum_generics[Enum] = TypesSourceMap, - variants[Variant] = TypesSourceMap, - consts[Const] = TypesSourceMap, - statics[Static] = TypesSourceMap, - trait_generics[Trait] = TypesSourceMap, - trait_alias_generics[TraitAlias] = TypesSourceMap, - impls[Impl] = GenericItemSourceMap, - type_aliases[TypeAlias] = GenericItemSourceMap, +index_item_source_maps! { + strukt; structs_offset[Struct]; generic_item; GenericItemSourceMap<'_>, + union; unions_offset[Union]; generic_item; GenericItemSourceMap<'_>, + enum_generic; enum_generics_offset[Enum]; non_generic_item; &TypesSourceMap, + variant; variants_offset[Variant]; non_generic_item; &TypesSourceMap, + konst; consts_offset[Const]; non_generic_item; &TypesSourceMap, + statik; statics_offset[Static]; non_generic_item; &TypesSourceMap, + trait_generic; trait_generics_offset[Trait]; non_generic_item; &TypesSourceMap, + trait_alias_generic; trait_alias_generics_offset[TraitAlias]; non_generic_item; &TypesSourceMap, + impl_; impls_offset[Impl]; generic_item; GenericItemSourceMap<'_>, + type_alias; type_aliases_offset[TypeAlias]; generic_item; GenericItemSourceMap<'_>, } #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] |