aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/item_tree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/item_tree.rs')
-rw-r--r--crates/hir_def/src/item_tree.rs68
1 files changed, 62 insertions, 6 deletions
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 7bb22c4c4..5f5b7151a 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -76,7 +76,7 @@ pub struct ItemTree {
76} 76}
77 77
78impl ItemTree { 78impl ItemTree {
79 pub(crate) fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { 79 pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
80 let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); 80 let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id));
81 let syntax = if let Some(node) = db.parse_or_expand(file_id) { 81 let syntax = if let Some(node) = db.parse_or_expand(file_id) {
82 if node.kind() == SyntaxKind::ERROR { 82 if node.kind() == SyntaxKind::ERROR {
@@ -134,6 +134,7 @@ impl ItemTree {
134 imports, 134 imports,
135 extern_crates, 135 extern_crates,
136 functions, 136 functions,
137 params,
137 structs, 138 structs,
138 fields, 139 fields,
139 unions, 140 unions,
@@ -157,6 +158,7 @@ impl ItemTree {
157 imports.shrink_to_fit(); 158 imports.shrink_to_fit();
158 extern_crates.shrink_to_fit(); 159 extern_crates.shrink_to_fit();
159 functions.shrink_to_fit(); 160 functions.shrink_to_fit();
161 params.shrink_to_fit();
160 structs.shrink_to_fit(); 162 structs.shrink_to_fit();
161 fields.shrink_to_fit(); 163 fields.shrink_to_fit();
162 unions.shrink_to_fit(); 164 unions.shrink_to_fit();
@@ -303,6 +305,7 @@ struct ItemTreeData {
303 imports: Arena<Import>, 305 imports: Arena<Import>,
304 extern_crates: Arena<ExternCrate>, 306 extern_crates: Arena<ExternCrate>,
305 functions: Arena<Function>, 307 functions: Arena<Function>,
308 params: Arena<Param>,
306 structs: Arena<Struct>, 309 structs: Arena<Struct>,
307 fields: Arena<Field>, 310 fields: Arena<Field>,
308 unions: Arena<Union>, 311 unions: Arena<Union>,
@@ -334,6 +337,7 @@ pub enum AttrOwner {
334 337
335 Variant(Idx<Variant>), 338 Variant(Idx<Variant>),
336 Field(Idx<Field>), 339 Field(Idx<Field>),
340 Param(Idx<Param>),
337} 341}
338 342
339macro_rules! from_attrs { 343macro_rules! from_attrs {
@@ -348,7 +352,7 @@ macro_rules! from_attrs {
348 }; 352 };
349} 353}
350 354
351from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>)); 355from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>), Param(Idx<Param>));
352 356
353/// Trait implemented by all item nodes in the item tree. 357/// Trait implemented by all item nodes in the item tree.
354pub trait ItemTreeNode: Clone { 358pub trait ItemTreeNode: Clone {
@@ -397,7 +401,47 @@ impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> {
397 } 401 }
398} 402}
399 403
400pub type ItemTreeId<N> = InFile<FileItemTreeId<N>>; 404#[derive(Debug)]
405pub struct ItemTreeId<N: ItemTreeNode> {
406 file: HirFileId,
407 pub value: FileItemTreeId<N>,
408}
409
410impl<N: ItemTreeNode> ItemTreeId<N> {
411 pub fn new(file: HirFileId, idx: FileItemTreeId<N>) -> Self {
412 Self { file, value: idx }
413 }
414
415 pub fn file_id(self) -> HirFileId {
416 self.file
417 }
418
419 pub fn item_tree(self, db: &dyn DefDatabase) -> Arc<ItemTree> {
420 db.file_item_tree(self.file)
421 }
422}
423
424impl<N: ItemTreeNode> Copy for ItemTreeId<N> {}
425impl<N: ItemTreeNode> Clone for ItemTreeId<N> {
426 fn clone(&self) -> Self {
427 *self
428 }
429}
430
431impl<N: ItemTreeNode> PartialEq for ItemTreeId<N> {
432 fn eq(&self, other: &Self) -> bool {
433 self.file == other.file && self.value == other.value
434 }
435}
436
437impl<N: ItemTreeNode> Eq for ItemTreeId<N> {}
438
439impl<N: ItemTreeNode> Hash for ItemTreeId<N> {
440 fn hash<H: Hasher>(&self, state: &mut H) {
441 self.file.hash(state);
442 self.value.hash(state);
443 }
444}
401 445
402macro_rules! mod_items { 446macro_rules! mod_items {
403 ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => { 447 ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => {
@@ -484,7 +528,7 @@ macro_rules! impl_index {
484 }; 528 };
485} 529}
486 530
487impl_index!(fields: Field, variants: Variant); 531impl_index!(fields: Field, variants: Variant, params: Param);
488 532
489impl Index<RawVisibilityId> for ItemTree { 533impl Index<RawVisibilityId> for ItemTree {
490 type Output = RawVisibility; 534 type Output = RawVisibility;
@@ -560,12 +604,17 @@ pub struct Function {
560 /// Whether the function is located in an `extern` block (*not* whether it is an 604 /// Whether the function is located in an `extern` block (*not* whether it is an
561 /// `extern "abi" fn`). 605 /// `extern "abi" fn`).
562 pub is_in_extern_block: bool, 606 pub is_in_extern_block: bool,
563 pub params: Box<[Idx<TypeRef>]>, 607 pub params: IdRange<Param>,
564 pub is_varargs: bool,
565 pub ret_type: Idx<TypeRef>, 608 pub ret_type: Idx<TypeRef>,
566 pub ast_id: FileAstId<ast::Fn>, 609 pub ast_id: FileAstId<ast::Fn>,
567} 610}
568 611
612#[derive(Debug, Clone, Eq, PartialEq)]
613pub enum Param {
614 Normal(Idx<TypeRef>),
615 Varargs,
616}
617
569#[derive(Debug, Clone, PartialEq, Eq)] 618#[derive(Debug, Clone, PartialEq, Eq)]
570pub struct FunctionQualifier { 619pub struct FunctionQualifier {
571 pub is_default: bool, 620 pub is_default: bool,
@@ -796,6 +845,7 @@ pub struct Variant {
796 pub fields: Fields, 845 pub fields: Fields,
797} 846}
798 847
848/// A range of densely allocated ItemTree IDs.
799pub struct IdRange<T> { 849pub struct IdRange<T> {
800 range: Range<u32>, 850 range: Range<u32>,
801 _p: PhantomData<T>, 851 _p: PhantomData<T>,
@@ -814,6 +864,12 @@ impl<T> Iterator for IdRange<T> {
814 } 864 }
815} 865}
816 866
867impl<T> DoubleEndedIterator for IdRange<T> {
868 fn next_back(&mut self) -> Option<Self::Item> {
869 self.range.next_back().map(|raw| Idx::from_raw(raw.into()))
870 }
871}
872
817impl<T> fmt::Debug for IdRange<T> { 873impl<T> fmt::Debug for IdRange<T> {
818 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 874 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
819 f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish() 875 f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish()