1 //! A simplified AST that only contains items.
15 use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner};
18 ast_id_map::FileAstId,
20 name::{name, AsName, Name},
23 use ra_arena::{Arena, Idx, RawId};
24 use ra_syntax::{ast, match_ast};
25 use rustc_hash::FxHashMap;
31 generics::GenericParams,
32 path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path},
33 type_ref::{Mutability, TypeBound, TypeRef},
34 visibility::RawVisibility,
36 use smallvec::SmallVec;
38 /// The item tree of a source file.
39 #[derive(Debug, Eq, PartialEq)]
42 top_level: Vec<ModItem>,
44 attrs: FxHashMap<ModItem, Attrs>,
46 inner_items: FxHashMap<FileAstId<ast::ModuleItem>, SmallVec<[ModItem; 1]>>,
48 imports: Arena<Import>,
49 extern_crates: Arena<ExternCrate>,
50 functions: Arena<Function>,
51 structs: Arena<Struct>,
55 variants: Arena<Variant>,
57 statics: Arena<Static>,
60 type_aliases: Arena<TypeAlias>,
62 macro_calls: Arena<MacroCall>,
67 pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
68 let _p = ra_prof::profile("item_tree_query");
69 let syntax = if let Some(node) = db.parse_or_expand(file_id) {
72 return Arc::new(Self::empty(file_id));
75 let hygiene = Hygiene::new(db.upcast(), file_id);
76 let mut top_attrs = None;
77 let (macro_storage, file_storage);
78 let item_owner = match_ast! {
80 ast::MacroItems(items) => {
81 macro_storage = items;
82 ¯o_storage as &dyn ModuleItemOwner
84 ast::SourceFile(file) => {
85 top_attrs = Some(Attrs::new(&file, &hygiene));
89 _ => return Arc::new(Self::empty(file_id)),
93 let ctx = lower::Ctx::new(db, hygiene, file_id);
94 let mut item_tree = ctx.lower(item_owner);
95 item_tree.top_attrs = top_attrs.unwrap_or_default();
99 fn empty(file_id: HirFileId) -> Self {
102 top_level: Default::default(),
103 top_attrs: Default::default(),
104 attrs: Default::default(),
105 empty_attrs: Default::default(),
106 inner_items: Default::default(),
107 imports: Default::default(),
108 extern_crates: Default::default(),
109 functions: Default::default(),
110 structs: Default::default(),
111 fields: Default::default(),
112 unions: Default::default(),
113 enums: Default::default(),
114 variants: Default::default(),
115 consts: Default::default(),
116 statics: Default::default(),
117 traits: Default::default(),
118 impls: Default::default(),
119 type_aliases: Default::default(),
120 mods: Default::default(),
121 macro_calls: Default::default(),
122 exprs: Default::default(),
126 /// Returns an iterator over all items located at the top level of the `HirFileId` this
127 /// `ItemTree` was created from.
128 pub fn top_level_items(&self) -> &[ModItem] {
132 /// Returns the inner attributes of the source file.
133 pub fn top_level_attrs(&self) -> &Attrs {
137 pub fn attrs(&self, of: ModItem) -> &Attrs {
138 self.attrs.get(&of).unwrap_or(&self.empty_attrs)
141 /// Returns the lowered inner items that `ast` corresponds to.
143 /// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered
144 /// to multiple items in the `ItemTree`.
145 pub fn inner_items(&self, ast: FileAstId<ast::ModuleItem>) -> &[ModItem] {
146 &self.inner_items[&ast]
149 pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ {
150 self.inner_items.values().flatten().copied()
153 pub fn source<S: ItemTreeSource>(
155 db: &dyn DefDatabase,
156 of: FileItemTreeId<S>,
158 // This unwrap cannot fail, since it has either succeeded above, or resulted in an empty
159 // ItemTree (in which case there is no valid `FileItemTreeId` to call this method with).
161 .parse_or_expand(self.file_id)
162 .expect("parse_or_expand failed on constructed ItemTree");
164 let id = self[of].ast_id();
165 let map = db.ast_id_map(self.file_id);
166 let ptr = map.get(id);
171 /// Trait implemented by all nodes in the item tree.
172 pub trait ItemTreeNode: Clone {
173 /// Looks up an instance of `Self` in an item tree.
174 fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
176 /// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type.
177 fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>>;
180 /// Trait for item tree nodes that allow accessing the original AST node.
181 pub trait ItemTreeSource: ItemTreeNode {
182 type Source: AstNode + Into<ast::ModuleItem>;
184 fn ast_id(&self) -> FileAstId<Self::Source>;
187 pub struct FileItemTreeId<N: ItemTreeNode> {
192 impl<N: ItemTreeNode> Clone for FileItemTreeId<N> {
193 fn clone(&self) -> Self {
194 Self { index: self.index, _p: PhantomData }
197 impl<N: ItemTreeNode> Copy for FileItemTreeId<N> {}
199 impl<N: ItemTreeNode> PartialEq for FileItemTreeId<N> {
200 fn eq(&self, other: &FileItemTreeId<N>) -> bool {
201 self.index == other.index
204 impl<N: ItemTreeNode> Eq for FileItemTreeId<N> {}
206 impl<N: ItemTreeNode> Hash for FileItemTreeId<N> {
207 fn hash<H: Hasher>(&self, state: &mut H) {
208 self.index.hash(state)
212 impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 pub type ItemTreeId<N> = InFile<FileItemTreeId<N>>;
221 ( $($node:ident in $fld:ident),+ $(,)? ) => { $(
222 impl ItemTreeNode for $node {
223 fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self {
228 fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>> {
229 if let ModItem::$node(id) = mod_item {
241 ExternCrate in extern_crates,
242 Function in functions,
250 TypeAlias in type_aliases,
252 MacroCall in macro_calls,
255 macro_rules! source {
256 ( $($node:ident -> $ast:path),+ $(,)? ) => { $(
257 impl ItemTreeSource for $node {
260 fn ast_id(&self) -> FileAstId<Self::Source> {
268 Import -> ast::UseItem,
269 ExternCrate -> ast::ExternCrateItem,
270 Function -> ast::FnDef,
271 Struct -> ast::StructDef,
272 Union -> ast::UnionDef,
273 Enum -> ast::EnumDef,
274 Const -> ast::ConstDef,
275 Static -> ast::StaticDef,
276 Trait -> ast::TraitDef,
277 Impl -> ast::ImplDef,
278 TypeAlias -> ast::TypeAliasDef,
280 MacroCall -> ast::MacroCall,
283 macro_rules! impl_index {
284 ( $($fld:ident: $t:ty),+ $(,)? ) => {
286 impl Index<Idx<$t>> for ItemTree {
289 fn index(&self, index: Idx<$t>) -> &Self::Output {
309 type_aliases: TypeAlias,
311 macro_calls: MacroCall,
315 impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
317 fn index(&self, id: FileItemTreeId<N>) -> &N {
318 N::lookup(self, id.index)
322 /// A desugared `use` import.
323 #[derive(Debug, Clone, Eq, PartialEq)]
326 pub alias: Option<ImportAlias>,
327 pub visibility: RawVisibility,
329 pub is_prelude: bool,
330 /// AST ID of the `use` or `extern crate` item this import was derived from. Note that many
331 /// `Import`s can map to the same `use` item.
332 pub ast_id: FileAstId<ast::UseItem>,
335 #[derive(Debug, Clone, Eq, PartialEq)]
336 pub struct ExternCrate {
338 pub alias: Option<ImportAlias>,
339 pub visibility: RawVisibility,
340 /// Whether this is a `#[macro_use] extern crate ...`.
341 pub is_macro_use: bool,
342 pub ast_id: FileAstId<ast::ExternCrateItem>,
345 #[derive(Debug, Clone, Eq, PartialEq)]
346 pub struct Function {
349 pub visibility: RawVisibility,
350 pub generic_params: GenericParams,
351 pub has_self_param: bool,
353 pub params: Vec<TypeRef>,
354 pub ret_type: TypeRef,
355 pub ast_id: FileAstId<ast::FnDef>,
358 #[derive(Debug, Clone, Eq, PartialEq)]
362 pub visibility: RawVisibility,
363 pub generic_params: GenericParams,
365 pub ast_id: FileAstId<ast::StructDef>,
366 pub kind: StructDefKind,
369 #[derive(Debug, Clone, Eq, PartialEq)]
370 pub enum StructDefKind {
371 /// `struct S { ... }` - type namespace only.
379 #[derive(Debug, Clone, Eq, PartialEq)]
383 pub visibility: RawVisibility,
384 pub generic_params: GenericParams,
386 pub ast_id: FileAstId<ast::UnionDef>,
389 #[derive(Debug, Clone, Eq, PartialEq)]
393 pub visibility: RawVisibility,
394 pub generic_params: GenericParams,
395 pub variants: Range<Idx<Variant>>,
396 pub ast_id: FileAstId<ast::EnumDef>,
399 #[derive(Debug, Clone, Eq, PartialEq)]
401 /// const _: () = ();
402 pub name: Option<Name>,
403 pub visibility: RawVisibility,
404 pub type_ref: TypeRef,
405 pub ast_id: FileAstId<ast::ConstDef>,
408 #[derive(Debug, Clone, Eq, PartialEq)]
411 pub visibility: RawVisibility,
413 pub type_ref: TypeRef,
414 pub ast_id: FileAstId<ast::StaticDef>,
417 #[derive(Debug, Clone, Eq, PartialEq)]
420 pub visibility: RawVisibility,
421 pub generic_params: GenericParams,
423 pub items: Vec<AssocItem>,
424 pub ast_id: FileAstId<ast::TraitDef>,
427 #[derive(Debug, Clone, Eq, PartialEq)]
429 pub generic_params: GenericParams,
430 pub target_trait: Option<TypeRef>,
431 pub target_type: TypeRef,
432 pub is_negative: bool,
433 pub items: Vec<AssocItem>,
434 pub ast_id: FileAstId<ast::ImplDef>,
437 #[derive(Debug, Clone, PartialEq, Eq)]
438 pub struct TypeAlias {
440 pub visibility: RawVisibility,
441 /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
442 pub bounds: Vec<TypeBound>,
443 pub generic_params: GenericParams,
444 pub type_ref: Option<TypeRef>,
445 pub ast_id: FileAstId<ast::TypeAliasDef>,
448 #[derive(Debug, Clone, Eq, PartialEq)]
451 pub visibility: RawVisibility,
453 pub ast_id: FileAstId<ast::Module>,
456 #[derive(Debug, Clone, Eq, PartialEq)]
459 Inline { items: Vec<ModItem> },
465 #[derive(Debug, Clone, Eq, PartialEq)]
466 pub struct MacroCall {
467 /// For `macro_rules!` declarations, this is the name of the declared macro.
468 pub name: Option<Name>,
469 /// Path to the called macro.
471 /// Has `#[macro_export]`.
473 /// Has `#[macro_export(local_inner_macros)]`.
474 pub is_local_inner: bool,
475 /// Has `#[rustc_builtin_macro]`.
476 pub is_builtin: bool,
477 pub ast_id: FileAstId<ast::MacroCall>,
480 // NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
481 // lengths, but we don't do much with them yet.
482 #[derive(Debug, Clone, Eq, PartialEq)]
485 macro_rules! impl_froms {
486 ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => {
488 impl From<$t> for $e {
489 fn from(it: $t) -> $e {
497 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
499 Import(FileItemTreeId<Import>),
500 ExternCrate(FileItemTreeId<ExternCrate>),
501 Function(FileItemTreeId<Function>),
502 Struct(FileItemTreeId<Struct>),
503 Union(FileItemTreeId<Union>),
504 Enum(FileItemTreeId<Enum>),
505 Const(FileItemTreeId<Const>),
506 Static(FileItemTreeId<Static>),
507 Trait(FileItemTreeId<Trait>),
508 Impl(FileItemTreeId<Impl>),
509 TypeAlias(FileItemTreeId<TypeAlias>),
510 Mod(FileItemTreeId<Mod>),
511 MacroCall(FileItemTreeId<MacroCall>),
515 pub fn as_assoc_item(&self) -> Option<AssocItem> {
518 | ModItem::ExternCrate(_)
525 | ModItem::Mod(_) => None,
526 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
527 ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
528 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
529 ModItem::Function(func) => Some(AssocItem::Function(*func)),
533 pub fn downcast<N: ItemTreeNode>(self) -> Option<FileItemTreeId<N>> {
534 N::id_from_mod_item(self)
538 impl_froms!(ModItem {
539 Import(FileItemTreeId<Import>),
540 ExternCrate(FileItemTreeId<ExternCrate>),
541 Function(FileItemTreeId<Function>),
542 Struct(FileItemTreeId<Struct>),
543 Union(FileItemTreeId<Union>),
544 Enum(FileItemTreeId<Enum>),
545 Const(FileItemTreeId<Const>),
546 Static(FileItemTreeId<Static>),
547 Trait(FileItemTreeId<Trait>),
548 Impl(FileItemTreeId<Impl>),
549 TypeAlias(FileItemTreeId<TypeAlias>),
550 Mod(FileItemTreeId<Mod>),
551 MacroCall(FileItemTreeId<MacroCall>),
554 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
556 Function(FileItemTreeId<Function>),
557 TypeAlias(FileItemTreeId<TypeAlias>),
558 Const(FileItemTreeId<Const>),
559 MacroCall(FileItemTreeId<MacroCall>),
562 impl_froms!(AssocItem {
563 Function(FileItemTreeId<Function>),
564 TypeAlias(FileItemTreeId<TypeAlias>),
565 Const(FileItemTreeId<Const>),
566 MacroCall(FileItemTreeId<MacroCall>),
569 impl From<AssocItem> for ModItem {
570 fn from(item: AssocItem) -> Self {
572 AssocItem::Function(it) => it.into(),
573 AssocItem::TypeAlias(it) => it.into(),
574 AssocItem::Const(it) => it.into(),
575 AssocItem::MacroCall(it) => it.into(),
580 #[derive(Debug, Eq, PartialEq)]
586 #[derive(Debug, Clone, PartialEq, Eq)]
588 Record(Range<Idx<Field>>),
589 Tuple(Range<Idx<Field>>),
593 /// A single field of an enum variant or struct
594 #[derive(Debug, Clone, PartialEq, Eq)]
597 pub type_ref: TypeRef,
598 pub visibility: RawVisibility,