2020-03-25 14:33:01 +00:00
|
|
|
//! A simplified AST that only contains items.
|
|
|
|
|
2020-06-16 12:52:43 +00:00
|
|
|
mod lower;
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
ops::{Index, Range},
|
|
|
|
sync::Arc,
|
|
|
|
};
|
|
|
|
|
|
|
|
use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner};
|
|
|
|
use either::Either;
|
2020-03-25 14:33:01 +00:00
|
|
|
use hir_expand::{
|
2020-06-16 12:52:43 +00:00
|
|
|
ast_id_map::FileAstId,
|
2020-03-25 14:33:01 +00:00
|
|
|
hygiene::Hygiene,
|
|
|
|
name::{name, AsName, Name},
|
2020-06-12 11:58:02 +00:00
|
|
|
HirFileId, InFile,
|
2020-03-25 14:33:01 +00:00
|
|
|
};
|
|
|
|
use ra_arena::{Arena, Idx, RawId};
|
2020-06-11 17:46:56 +00:00
|
|
|
use ra_syntax::{ast, match_ast};
|
2020-06-16 12:52:43 +00:00
|
|
|
use rustc_hash::FxHashMap;
|
2020-06-15 17:16:29 +00:00
|
|
|
use test_utils::mark;
|
2020-03-25 14:33:01 +00:00
|
|
|
|
|
|
|
use crate::{
|
|
|
|
attr::Attrs,
|
2020-06-11 17:46:56 +00:00
|
|
|
db::DefDatabase,
|
2020-06-12 11:58:02 +00:00
|
|
|
generics,
|
2020-03-25 14:33:01 +00:00
|
|
|
path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path},
|
|
|
|
type_ref::{Mutability, TypeBound, TypeRef},
|
|
|
|
visibility::RawVisibility,
|
|
|
|
};
|
|
|
|
|
2020-06-12 11:58:02 +00:00
|
|
|
/// The item tree of a source file.
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Default, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct ItemTree {
|
2020-06-11 17:46:56 +00:00
|
|
|
top_level: Vec<ModItem>,
|
2020-06-15 17:16:02 +00:00
|
|
|
top_attrs: Attrs,
|
|
|
|
attrs: FxHashMap<ModItem, Attrs>,
|
|
|
|
empty_attrs: Attrs,
|
|
|
|
|
2020-03-25 14:33:01 +00:00
|
|
|
imports: Arena<Import>,
|
|
|
|
functions: Arena<Function>,
|
|
|
|
structs: Arena<Struct>,
|
|
|
|
fields: Arena<Field>,
|
|
|
|
unions: Arena<Union>,
|
|
|
|
enums: Arena<Enum>,
|
|
|
|
variants: Arena<Variant>,
|
|
|
|
consts: Arena<Const>,
|
|
|
|
statics: Arena<Static>,
|
|
|
|
traits: Arena<Trait>,
|
|
|
|
impls: Arena<Impl>,
|
|
|
|
type_aliases: Arena<TypeAlias>,
|
|
|
|
mods: Arena<Mod>,
|
|
|
|
macro_calls: Arena<MacroCall>,
|
|
|
|
exprs: Arena<Expr>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ItemTree {
|
2020-06-11 17:46:56 +00:00
|
|
|
pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
|
2020-06-15 17:16:02 +00:00
|
|
|
let _p = ra_prof::profile("item_tree_query");
|
2020-06-11 17:46:56 +00:00
|
|
|
let syntax = if let Some(node) = db.parse_or_expand(file_id) {
|
|
|
|
node
|
|
|
|
} else {
|
|
|
|
return Default::default();
|
|
|
|
};
|
|
|
|
|
2020-06-15 17:16:02 +00:00
|
|
|
let hygiene = Hygiene::new(db.upcast(), file_id);
|
|
|
|
let mut top_attrs = None;
|
2020-06-11 17:46:56 +00:00
|
|
|
let (macro_storage, file_storage);
|
|
|
|
let item_owner = match_ast! {
|
|
|
|
match syntax {
|
|
|
|
ast::MacroItems(items) => {
|
|
|
|
macro_storage = items;
|
|
|
|
¯o_storage as &dyn ModuleItemOwner
|
|
|
|
},
|
|
|
|
ast::SourceFile(file) => {
|
2020-06-15 17:16:02 +00:00
|
|
|
top_attrs = Some(Attrs::new(&file, &hygiene));
|
2020-06-11 17:46:56 +00:00
|
|
|
file_storage = file;
|
|
|
|
&file_storage
|
|
|
|
},
|
|
|
|
_ => return Default::default(),
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let map = db.ast_id_map(file_id);
|
2020-06-16 12:52:43 +00:00
|
|
|
let mut ctx = lower::Ctx {
|
2020-06-11 17:46:56 +00:00
|
|
|
tree: ItemTree::default(),
|
2020-06-15 17:16:02 +00:00
|
|
|
hygiene,
|
2020-06-12 11:58:02 +00:00
|
|
|
file: file_id,
|
2020-06-11 17:46:56 +00:00
|
|
|
source_ast_id_map: map,
|
|
|
|
body_ctx: crate::body::LowerCtx::new(db, file_id),
|
|
|
|
};
|
2020-06-15 17:16:02 +00:00
|
|
|
ctx.tree.top_attrs = top_attrs.unwrap_or_default();
|
2020-06-11 17:46:56 +00:00
|
|
|
Arc::new(ctx.lower(item_owner))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns an iterator over all items located at the top level of the `HirFileId` this
|
|
|
|
/// `ItemTree` was created from.
|
2020-06-12 21:24:26 +00:00
|
|
|
pub fn top_level_items(&self) -> &[ModItem] {
|
|
|
|
&self.top_level
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
2020-06-15 17:16:02 +00:00
|
|
|
|
|
|
|
/// Returns the inner attributes of the source file.
|
|
|
|
pub fn top_level_attrs(&self) -> &Attrs {
|
|
|
|
&self.top_attrs
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn attrs(&self, of: ModItem) -> &Attrs {
|
|
|
|
self.attrs.get(&of).unwrap_or(&self.empty_attrs)
|
|
|
|
}
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_index {
|
|
|
|
( $($fld:ident: $t:ty),+ $(,)? ) => {
|
|
|
|
$(
|
|
|
|
impl Index<Idx<$t>> for ItemTree {
|
|
|
|
type Output = $t;
|
|
|
|
|
|
|
|
fn index(&self, index: Idx<$t>) -> &Self::Output {
|
|
|
|
&self.$fld[index]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)+
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
impl_index!(
|
|
|
|
imports: Import,
|
|
|
|
functions: Function,
|
|
|
|
structs: Struct,
|
|
|
|
fields: Field,
|
|
|
|
unions: Union,
|
|
|
|
enums: Enum,
|
|
|
|
variants: Variant,
|
|
|
|
consts: Const,
|
|
|
|
statics: Static,
|
|
|
|
traits: Trait,
|
|
|
|
impls: Impl,
|
|
|
|
type_aliases: TypeAlias,
|
|
|
|
mods: Mod,
|
|
|
|
macro_calls: MacroCall,
|
|
|
|
exprs: Expr,
|
|
|
|
);
|
|
|
|
|
2020-06-12 11:58:02 +00:00
|
|
|
/// A desugared `extern crate` or `use` import.
|
2020-06-12 21:24:26 +00:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Import {
|
|
|
|
pub path: ModPath,
|
|
|
|
pub alias: Option<ImportAlias>,
|
|
|
|
pub visibility: RawVisibility,
|
|
|
|
pub is_glob: bool,
|
|
|
|
pub is_prelude: bool,
|
|
|
|
pub is_extern_crate: bool,
|
|
|
|
pub is_macro_use: bool,
|
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Function {
|
|
|
|
pub name: Name,
|
|
|
|
pub attrs: Attrs,
|
|
|
|
pub visibility: RawVisibility,
|
2020-06-12 11:58:02 +00:00
|
|
|
pub generic_params: generics::GenericParams,
|
2020-03-25 14:33:01 +00:00
|
|
|
pub has_self_param: bool,
|
|
|
|
pub params: Vec<TypeRef>,
|
|
|
|
pub ret_type: TypeRef,
|
2020-06-15 17:16:02 +00:00
|
|
|
pub ast_id: FileAstId<ast::FnDef>,
|
2020-06-12 11:58:02 +00:00
|
|
|
// FIXME inner items
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Struct {
|
|
|
|
pub name: Name,
|
|
|
|
pub attrs: Attrs,
|
|
|
|
pub visibility: RawVisibility,
|
2020-06-12 11:58:02 +00:00
|
|
|
pub generic_params: generics::GenericParams,
|
2020-03-25 14:33:01 +00:00
|
|
|
pub fields: Fields,
|
2020-06-15 17:16:02 +00:00
|
|
|
pub ast_id: FileAstId<ast::StructDef>,
|
|
|
|
pub kind: StructDefKind,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
|
|
pub enum StructDefKind {
|
|
|
|
/// `struct S { ... }` - type namespace only.
|
|
|
|
Record,
|
|
|
|
/// `struct S(...);`
|
|
|
|
Tuple,
|
|
|
|
/// `struct S;`
|
|
|
|
Unit,
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Union {
|
|
|
|
pub name: Name,
|
|
|
|
pub attrs: Attrs,
|
|
|
|
pub visibility: RawVisibility,
|
2020-06-12 11:58:02 +00:00
|
|
|
pub generic_params: generics::GenericParams,
|
2020-03-25 14:33:01 +00:00
|
|
|
pub fields: Fields,
|
2020-06-15 17:16:02 +00:00
|
|
|
pub ast_id: FileAstId<ast::UnionDef>,
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Enum {
|
|
|
|
pub name: Name,
|
|
|
|
pub attrs: Attrs,
|
|
|
|
pub visibility: RawVisibility,
|
2020-06-12 11:58:02 +00:00
|
|
|
pub generic_params: generics::GenericParams,
|
2020-03-25 14:33:01 +00:00
|
|
|
pub variants: Range<Idx<Variant>>,
|
2020-06-15 17:16:02 +00:00
|
|
|
pub ast_id: FileAstId<ast::EnumDef>,
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Const {
|
|
|
|
/// const _: () = ();
|
|
|
|
pub name: Option<Name>,
|
|
|
|
pub visibility: RawVisibility,
|
|
|
|
pub type_ref: TypeRef,
|
2020-06-15 17:16:02 +00:00
|
|
|
pub ast_id: FileAstId<ast::ConstDef>,
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Static {
|
|
|
|
pub name: Name,
|
|
|
|
pub visibility: RawVisibility,
|
|
|
|
pub type_ref: TypeRef,
|
2020-06-15 17:16:02 +00:00
|
|
|
pub ast_id: FileAstId<ast::StaticDef>,
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Trait {
|
|
|
|
pub name: Name,
|
|
|
|
pub visibility: RawVisibility,
|
2020-06-12 11:58:02 +00:00
|
|
|
pub generic_params: generics::GenericParams,
|
2020-03-25 14:33:01 +00:00
|
|
|
pub auto: bool,
|
|
|
|
pub items: Vec<AssocItem>,
|
2020-06-15 17:16:02 +00:00
|
|
|
pub ast_id: FileAstId<ast::TraitDef>,
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Impl {
|
2020-06-12 11:58:02 +00:00
|
|
|
pub generic_params: generics::GenericParams,
|
2020-03-25 14:33:01 +00:00
|
|
|
pub target_trait: Option<TypeRef>,
|
|
|
|
pub target_type: TypeRef,
|
|
|
|
pub is_negative: bool,
|
|
|
|
pub items: Vec<AssocItem>,
|
2020-06-15 17:16:02 +00:00
|
|
|
pub ast_id: FileAstId<ast::ImplDef>,
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub struct TypeAlias {
|
|
|
|
pub name: Name,
|
|
|
|
pub visibility: RawVisibility,
|
2020-06-12 11:58:02 +00:00
|
|
|
pub generic_params: generics::GenericParams,
|
2020-03-25 14:33:01 +00:00
|
|
|
pub type_ref: Option<TypeRef>,
|
2020-06-15 17:16:02 +00:00
|
|
|
pub ast_id: FileAstId<ast::TypeAliasDef>,
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Mod {
|
|
|
|
pub name: Name,
|
|
|
|
pub visibility: RawVisibility,
|
2020-06-15 17:16:02 +00:00
|
|
|
pub kind: ModKind,
|
|
|
|
pub ast_id: FileAstId<ast::Module>,
|
2020-03-25 14:33:01 +00:00
|
|
|
}
|
|
|
|
|
2020-06-15 17:16:02 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-06-12 21:24:26 +00:00
|
|
|
pub enum ModKind {
|
2020-06-15 17:16:02 +00:00
|
|
|
/// `mod m { ... }`
|
2020-06-12 21:24:26 +00:00
|
|
|
Inline { items: Vec<ModItem> },
|
|
|
|
|
2020-06-15 17:16:02 +00:00
|
|
|
/// `mod m;`
|
2020-06-12 21:24:26 +00:00
|
|
|
Outline {},
|
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct MacroCall {
|
2020-06-15 17:16:02 +00:00
|
|
|
/// For `macro_rules!` declarations, this is the name of the declared macro.
|
2020-03-25 14:33:01 +00:00
|
|
|
pub name: Option<Name>,
|
2020-06-15 17:16:02 +00:00
|
|
|
/// Path to the called macro.
|
2020-03-25 14:33:01 +00:00
|
|
|
pub path: ModPath,
|
2020-06-12 11:58:02 +00:00
|
|
|
/// Has `#[macro_export]`.
|
|
|
|
pub is_export: bool,
|
|
|
|
/// Has `#[macro_export(local_inner_macros)]`.
|
|
|
|
pub is_local_inner: bool,
|
|
|
|
/// Has `#[rustc_builtin_macro]`.
|
|
|
|
pub is_builtin: bool,
|
2020-03-25 14:33:01 +00:00
|
|
|
pub ast_id: FileAstId<ast::MacroCall>,
|
|
|
|
}
|
|
|
|
|
|
|
|
// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
|
|
|
|
// lengths, but we don't do much with them yet.
|
2020-06-11 17:46:56 +00:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Expr;
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
macro_rules! impl_froms {
|
|
|
|
($e:ident { $($v:ident ($t:ty)),* $(,)? }) => {
|
|
|
|
$(
|
|
|
|
impl From<$t> for $e {
|
|
|
|
fn from(it: $t) -> $e {
|
|
|
|
$e::$v(it)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-15 17:16:02 +00:00
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub enum ModItem {
|
|
|
|
Import(Idx<Import>),
|
|
|
|
Function(Idx<Function>),
|
|
|
|
Struct(Idx<Struct>),
|
|
|
|
Union(Idx<Union>),
|
|
|
|
Enum(Idx<Enum>),
|
|
|
|
Const(Idx<Const>),
|
|
|
|
Static(Idx<Static>),
|
|
|
|
Trait(Idx<Trait>),
|
|
|
|
Impl(Idx<Impl>),
|
|
|
|
TypeAlias(Idx<TypeAlias>),
|
|
|
|
Mod(Idx<Mod>),
|
|
|
|
MacroCall(Idx<MacroCall>),
|
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
impl_froms!(ModItem {
|
|
|
|
Import(Idx<Import>),
|
|
|
|
Function(Idx<Function>),
|
|
|
|
Struct(Idx<Struct>),
|
|
|
|
Union(Idx<Union>),
|
|
|
|
Enum(Idx<Enum>),
|
|
|
|
Const(Idx<Const>),
|
|
|
|
Static(Idx<Static>),
|
|
|
|
Trait(Idx<Trait>),
|
|
|
|
Impl(Idx<Impl>),
|
|
|
|
TypeAlias(Idx<TypeAlias>),
|
|
|
|
Mod(Idx<Mod>),
|
|
|
|
MacroCall(Idx<MacroCall>),
|
|
|
|
});
|
|
|
|
|
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub enum AssocItem {
|
|
|
|
Function(Idx<Function>),
|
|
|
|
TypeAlias(Idx<TypeAlias>),
|
|
|
|
Const(Idx<Const>),
|
|
|
|
MacroCall(Idx<MacroCall>),
|
|
|
|
}
|
|
|
|
|
2020-06-11 17:46:56 +00:00
|
|
|
impl_froms!(AssocItem {
|
|
|
|
Function(Idx<Function>),
|
|
|
|
TypeAlias(Idx<TypeAlias>),
|
|
|
|
Const(Idx<Const>),
|
|
|
|
MacroCall(Idx<MacroCall>),
|
|
|
|
});
|
|
|
|
|
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-03-25 14:33:01 +00:00
|
|
|
pub struct Variant {
|
|
|
|
pub name: Name,
|
|
|
|
pub fields: Fields,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub enum Fields {
|
|
|
|
Record(Range<Idx<Field>>),
|
|
|
|
Tuple(Range<Idx<Field>>),
|
|
|
|
Unit,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A single field of an enum variant or struct
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub struct Field {
|
|
|
|
pub name: Name,
|
|
|
|
pub type_ref: TypeRef,
|
|
|
|
pub visibility: RawVisibility,
|
|
|
|
}
|