diff options
Diffstat (limited to 'crates/hir_def/src/item_tree.rs')
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 68 |
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 | ||
78 | impl ItemTree { | 78 | impl 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 | ||
339 | macro_rules! from_attrs { | 343 | macro_rules! from_attrs { |
@@ -348,7 +352,7 @@ macro_rules! from_attrs { | |||
348 | }; | 352 | }; |
349 | } | 353 | } |
350 | 354 | ||
351 | from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>)); | 355 | from_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. |
354 | pub trait ItemTreeNode: Clone { | 358 | pub trait ItemTreeNode: Clone { |
@@ -397,7 +401,47 @@ impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> { | |||
397 | } | 401 | } |
398 | } | 402 | } |
399 | 403 | ||
400 | pub type ItemTreeId<N> = InFile<FileItemTreeId<N>>; | 404 | #[derive(Debug)] |
405 | pub struct ItemTreeId<N: ItemTreeNode> { | ||
406 | file: HirFileId, | ||
407 | pub value: FileItemTreeId<N>, | ||
408 | } | ||
409 | |||
410 | impl<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 | |||
424 | impl<N: ItemTreeNode> Copy for ItemTreeId<N> {} | ||
425 | impl<N: ItemTreeNode> Clone for ItemTreeId<N> { | ||
426 | fn clone(&self) -> Self { | ||
427 | *self | ||
428 | } | ||
429 | } | ||
430 | |||
431 | impl<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 | |||
437 | impl<N: ItemTreeNode> Eq for ItemTreeId<N> {} | ||
438 | |||
439 | impl<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 | ||
402 | macro_rules! mod_items { | 446 | macro_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 | ||
487 | impl_index!(fields: Field, variants: Variant); | 531 | impl_index!(fields: Field, variants: Variant, params: Param); |
488 | 532 | ||
489 | impl Index<RawVisibilityId> for ItemTree { | 533 | impl 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)] | ||
613 | pub enum Param { | ||
614 | Normal(Idx<TypeRef>), | ||
615 | Varargs, | ||
616 | } | ||
617 | |||
569 | #[derive(Debug, Clone, PartialEq, Eq)] | 618 | #[derive(Debug, Clone, PartialEq, Eq)] |
570 | pub struct FunctionQualifier { | 619 | pub 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. | ||
799 | pub struct IdRange<T> { | 849 | pub 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 | ||
867 | impl<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 | |||
817 | impl<T> fmt::Debug for IdRange<T> { | 873 | impl<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() |