mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-01 12:24:29 +00:00
Merge pull request #19982 from Veykril/push-uptnmqtlylsx
Simplify and optimize `ItemTree`
This commit is contained in:
commit
bd002fe65c
9 changed files with 561 additions and 758 deletions
|
|
@ -26,7 +26,7 @@ use crate::{
|
|||
AdtId, AstIdLoc, AttrDefId, GenericParamId, HasModule, LocalFieldId, Lookup, MacroId,
|
||||
VariantId,
|
||||
db::DefDatabase,
|
||||
item_tree::AttrOwner,
|
||||
item_tree::block_item_tree_query,
|
||||
lang_item::LangItem,
|
||||
nameres::{ModuleOrigin, ModuleSource},
|
||||
src::{HasChildSource, HasSource},
|
||||
|
|
@ -523,26 +523,25 @@ impl AttrsWithOwner {
|
|||
let mod_data = &def_map[module.local_id];
|
||||
|
||||
let raw_attrs = match mod_data.origin {
|
||||
ModuleOrigin::File { definition, declaration_tree_id, .. } => {
|
||||
ModuleOrigin::File { definition, declaration_tree_id, declaration, .. } => {
|
||||
let decl_attrs = declaration_tree_id
|
||||
.item_tree(db)
|
||||
.raw_attrs(AttrOwner::ModItem(declaration_tree_id.value.into()))
|
||||
.raw_attrs(declaration.upcast())
|
||||
.clone();
|
||||
let tree = db.file_item_tree(definition.into());
|
||||
let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone();
|
||||
let def_attrs = tree.top_level_raw_attrs().clone();
|
||||
decl_attrs.merge(def_attrs)
|
||||
}
|
||||
ModuleOrigin::CrateRoot { definition } => {
|
||||
let tree = db.file_item_tree(definition.into());
|
||||
tree.raw_attrs(AttrOwner::TopLevel).clone()
|
||||
tree.top_level_raw_attrs().clone()
|
||||
}
|
||||
ModuleOrigin::Inline { definition_tree_id, definition } => {
|
||||
definition_tree_id.item_tree(db).raw_attrs(definition.upcast()).clone()
|
||||
}
|
||||
ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id
|
||||
.item_tree(db)
|
||||
.raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
|
||||
.clone(),
|
||||
ModuleOrigin::BlockExpr { id, .. } => {
|
||||
let tree = db.block_item_tree(id);
|
||||
tree.raw_attrs(AttrOwner::TopLevel).clone()
|
||||
let tree = block_item_tree_query(db, id);
|
||||
tree.top_level_raw_attrs().clone()
|
||||
}
|
||||
};
|
||||
Attrs::expand_cfg_attr(db, module.krate, raw_attrs)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use crate::{
|
|||
},
|
||||
hir::generics::GenericParams,
|
||||
import_map::ImportMap,
|
||||
item_tree::{AttrOwner, ItemTree},
|
||||
item_tree::{ItemTree, file_item_tree_query},
|
||||
lang_item::{self, LangItem},
|
||||
nameres::{
|
||||
assoc::{ImplItems, TraitItems},
|
||||
|
|
@ -108,11 +108,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
|
|||
fn expand_proc_attr_macros(&self) -> bool;
|
||||
|
||||
/// Computes an [`ItemTree`] for the given file or macro expansion.
|
||||
#[salsa::invoke(ItemTree::file_item_tree_query)]
|
||||
fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
|
||||
|
||||
#[salsa::invoke(ItemTree::block_item_tree_query)]
|
||||
fn block_item_tree(&self, block_id: BlockId) -> Arc<ItemTree>;
|
||||
#[salsa::invoke(file_item_tree_query)]
|
||||
#[salsa::transparent]
|
||||
fn file_item_tree(&self, file_id: HirFileId) -> &ItemTree;
|
||||
|
||||
/// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution.
|
||||
#[salsa::invoke(macro_def)]
|
||||
|
|
@ -376,7 +374,7 @@ fn include_macro_invoc(
|
|||
fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool {
|
||||
let file = crate_id.data(db).root_file_id(db);
|
||||
let item_tree = db.file_item_tree(file.into());
|
||||
let attrs = item_tree.raw_attrs(AttrOwner::TopLevel);
|
||||
let attrs = item_tree.top_level_raw_attrs();
|
||||
for attr in &**attrs {
|
||||
match attr.path().as_ident() {
|
||||
Some(ident) if *ident == sym::no_std => return true,
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ mod tests;
|
|||
|
||||
use std::{
|
||||
fmt::{self, Debug},
|
||||
hash::{Hash, Hasher},
|
||||
ops::{Index, Range},
|
||||
hash::Hash,
|
||||
ops::Index,
|
||||
sync::OnceLock,
|
||||
};
|
||||
|
||||
|
|
@ -51,12 +51,12 @@ use hir_expand::{
|
|||
name::Name,
|
||||
};
|
||||
use intern::Interned;
|
||||
use la_arena::{Arena, Idx, RawIdx};
|
||||
use la_arena::{Idx, RawIdx};
|
||||
use rustc_hash::FxHashMap;
|
||||
use smallvec::SmallVec;
|
||||
use span::{AstIdNode, Edition, FileAstId, SyntaxContext};
|
||||
use stdx::never;
|
||||
use syntax::{SyntaxKind, ast, match_ast};
|
||||
use thin_vec::ThinVec;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{BlockId, Lookup, attr::Attrs, db::DefDatabase};
|
||||
|
|
@ -64,13 +64,13 @@ use crate::{BlockId, Lookup, attr::Attrs, db::DefDatabase};
|
|||
pub(crate) use crate::item_tree::lower::{lower_use_tree, visibility_from_ast};
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub struct RawVisibilityId(u32);
|
||||
pub(crate) struct RawVisibilityId(u32);
|
||||
|
||||
impl RawVisibilityId {
|
||||
pub const PUB: Self = RawVisibilityId(u32::MAX);
|
||||
pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::MAX - 1);
|
||||
pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::MAX - 2);
|
||||
pub const PUB_CRATE: Self = RawVisibilityId(u32::MAX - 3);
|
||||
const PUB: Self = RawVisibilityId(u32::MAX);
|
||||
const PRIV_IMPLICIT: Self = RawVisibilityId(u32::MAX - 1);
|
||||
const PRIV_EXPLICIT: Self = RawVisibilityId(u32::MAX - 2);
|
||||
const PUB_CRATE: Self = RawVisibilityId(u32::MAX - 3);
|
||||
}
|
||||
|
||||
impl fmt::Debug for RawVisibilityId {
|
||||
|
|
@ -86,112 +86,115 @@ impl fmt::Debug for RawVisibilityId {
|
|||
}
|
||||
}
|
||||
|
||||
#[salsa_macros::tracked(returns(ref))]
|
||||
pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> ItemTree {
|
||||
let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered();
|
||||
|
||||
let ctx = lower::Ctx::new(db, file_id);
|
||||
let syntax = db.parse_or_expand(file_id);
|
||||
let mut item_tree = match_ast! {
|
||||
match syntax {
|
||||
ast::SourceFile(file) => {
|
||||
let top_attrs = RawAttrs::new(db, &file, ctx.span_map());
|
||||
let mut item_tree = ctx.lower_module_items(&file);
|
||||
item_tree.top_attrs = top_attrs;
|
||||
item_tree
|
||||
},
|
||||
ast::MacroItems(items) => {
|
||||
ctx.lower_module_items(&items)
|
||||
},
|
||||
ast::MacroStmts(stmts) => {
|
||||
// The produced statements can include items, which should be added as top-level
|
||||
// items.
|
||||
ctx.lower_macro_stmts(stmts)
|
||||
},
|
||||
_ => {
|
||||
if never!(syntax.kind() == SyntaxKind::ERROR, "{:?} from {:?} {}", file_id, syntax, syntax) {
|
||||
return Default::default();
|
||||
}
|
||||
panic!("cannot create item tree for file {file_id:?} from {syntax:?} {syntax}");
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
item_tree.shrink_to_fit();
|
||||
item_tree
|
||||
}
|
||||
|
||||
#[salsa_macros::tracked(returns(ref))]
|
||||
pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
|
||||
let _p = tracing::info_span!("block_item_tree_query", ?block).entered();
|
||||
// Blocks have a tendency to be empty due to macro calls that do not expand to items,
|
||||
// so deduplicate this case via `Arc` to reduce the size of the query storage here.
|
||||
static EMPTY: OnceLock<Arc<ItemTree>> = OnceLock::new();
|
||||
|
||||
let loc = block.lookup(db);
|
||||
let block = loc.ast_id.to_node(db);
|
||||
|
||||
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
|
||||
let mut item_tree = ctx.lower_block(&block);
|
||||
if item_tree.small_data.is_empty()
|
||||
&& item_tree.big_data.is_empty()
|
||||
&& item_tree.top_level.is_empty()
|
||||
&& item_tree.attrs.is_empty()
|
||||
&& item_tree.top_attrs.is_empty()
|
||||
{
|
||||
EMPTY
|
||||
.get_or_init(|| {
|
||||
Arc::new(ItemTree {
|
||||
top_level: Box::new([]),
|
||||
attrs: FxHashMap::default(),
|
||||
small_data: FxHashMap::default(),
|
||||
big_data: FxHashMap::default(),
|
||||
top_attrs: RawAttrs::EMPTY,
|
||||
vis: ItemVisibilities { arena: ThinVec::new() },
|
||||
})
|
||||
})
|
||||
.clone()
|
||||
} else {
|
||||
item_tree.shrink_to_fit();
|
||||
Arc::new(item_tree)
|
||||
}
|
||||
}
|
||||
/// The item tree of a source file.
|
||||
#[derive(Debug, Default, Eq, PartialEq)]
|
||||
pub struct ItemTree {
|
||||
top_level: SmallVec<[ModItem; 1]>,
|
||||
attrs: FxHashMap<AttrOwner, RawAttrs>,
|
||||
|
||||
data: Option<Box<ItemTreeData>>,
|
||||
top_level: Box<[ModItemId]>,
|
||||
top_attrs: RawAttrs,
|
||||
attrs: FxHashMap<FileAstId<ast::Item>, RawAttrs>,
|
||||
vis: ItemVisibilities,
|
||||
// FIXME: They values store the key, turn this into a FxHashSet<ModItem> instead?
|
||||
big_data: FxHashMap<FileAstId<ast::Item>, BigModItem>,
|
||||
small_data: FxHashMap<FileAstId<ast::Item>, SmallModItem>,
|
||||
}
|
||||
|
||||
impl ItemTree {
|
||||
pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
|
||||
let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered();
|
||||
static EMPTY: OnceLock<Arc<ItemTree>> = OnceLock::new();
|
||||
|
||||
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 = match_ast! {
|
||||
match syntax {
|
||||
ast::SourceFile(file) => {
|
||||
top_attrs = Some(RawAttrs::new(db, &file, ctx.span_map()));
|
||||
ctx.lower_module_items(&file)
|
||||
},
|
||||
ast::MacroItems(items) => {
|
||||
ctx.lower_module_items(&items)
|
||||
},
|
||||
ast::MacroStmts(stmts) => {
|
||||
// The produced statements can include items, which should be added as top-level
|
||||
// items.
|
||||
ctx.lower_macro_stmts(stmts)
|
||||
},
|
||||
_ => {
|
||||
if never!(syntax.kind() == SyntaxKind::ERROR, "{:?} from {:?} {}", file_id, syntax, syntax) {
|
||||
return Default::default();
|
||||
}
|
||||
panic!("cannot create item tree for file {file_id:?} from {syntax:?} {syntax}");
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(attrs) = top_attrs {
|
||||
item_tree.attrs.insert(AttrOwner::TopLevel, attrs);
|
||||
}
|
||||
if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
|
||||
{
|
||||
EMPTY
|
||||
.get_or_init(|| {
|
||||
Arc::new(ItemTree {
|
||||
top_level: SmallVec::new_const(),
|
||||
attrs: FxHashMap::default(),
|
||||
data: None,
|
||||
})
|
||||
})
|
||||
.clone()
|
||||
} else {
|
||||
item_tree.shrink_to_fit();
|
||||
Arc::new(item_tree)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
|
||||
let _p = tracing::info_span!("block_item_tree_query", ?block).entered();
|
||||
static EMPTY: OnceLock<Arc<ItemTree>> = OnceLock::new();
|
||||
|
||||
let loc = block.lookup(db);
|
||||
let block = loc.ast_id.to_node(db);
|
||||
|
||||
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
|
||||
let mut item_tree = ctx.lower_block(&block);
|
||||
if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
|
||||
{
|
||||
EMPTY
|
||||
.get_or_init(|| {
|
||||
Arc::new(ItemTree {
|
||||
top_level: SmallVec::new_const(),
|
||||
attrs: FxHashMap::default(),
|
||||
data: None,
|
||||
})
|
||||
})
|
||||
.clone()
|
||||
} else {
|
||||
item_tree.shrink_to_fit();
|
||||
Arc::new(item_tree)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over all items located at the top level of the `HirFileId` this
|
||||
/// `ItemTree` was created from.
|
||||
pub fn top_level_items(&self) -> &[ModItem] {
|
||||
pub(crate) fn top_level_items(&self) -> &[ModItemId] {
|
||||
&self.top_level
|
||||
}
|
||||
|
||||
/// Returns the inner attributes of the source file.
|
||||
pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs {
|
||||
Attrs::expand_cfg_attr(
|
||||
db,
|
||||
krate,
|
||||
self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone(),
|
||||
)
|
||||
pub(crate) fn top_level_raw_attrs(&self) -> &RawAttrs {
|
||||
&self.top_attrs
|
||||
}
|
||||
|
||||
pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs {
|
||||
/// Returns the inner attributes of the source file.
|
||||
pub(crate) fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs {
|
||||
Attrs::expand_cfg_attr(db, krate, self.top_attrs.clone())
|
||||
}
|
||||
|
||||
pub(crate) fn raw_attrs(&self, of: FileAstId<ast::Item>) -> &RawAttrs {
|
||||
self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY)
|
||||
}
|
||||
|
||||
pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: Crate, of: AttrOwner) -> Attrs {
|
||||
pub(crate) fn attrs(
|
||||
&self,
|
||||
db: &dyn DefDatabase,
|
||||
krate: Crate,
|
||||
of: FileAstId<ast::Item>,
|
||||
) -> Attrs {
|
||||
Attrs::expand_cfg_attr(db, krate, self.raw_attrs(of).clone())
|
||||
}
|
||||
|
||||
|
|
@ -199,105 +202,79 @@ impl ItemTree {
|
|||
///
|
||||
/// For more detail, see [`ItemTreeDataStats`].
|
||||
pub fn item_tree_stats(&self) -> ItemTreeDataStats {
|
||||
match self.data {
|
||||
Some(ref data) => ItemTreeDataStats {
|
||||
traits: data.traits.len(),
|
||||
impls: data.impls.len(),
|
||||
mods: data.mods.len(),
|
||||
macro_calls: data.macro_calls.len(),
|
||||
macro_rules: data.macro_rules.len(),
|
||||
},
|
||||
None => ItemTreeDataStats::default(),
|
||||
let mut traits = 0;
|
||||
let mut impls = 0;
|
||||
let mut mods = 0;
|
||||
let mut macro_calls = 0;
|
||||
let mut macro_rules = 0;
|
||||
for item in self.small_data.values() {
|
||||
match item {
|
||||
SmallModItem::Trait(_) => traits += 1,
|
||||
SmallModItem::Impl(_) => impls += 1,
|
||||
SmallModItem::MacroRules(_) => macro_rules += 1,
|
||||
SmallModItem::MacroCall(_) => macro_calls += 1,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
for item in self.big_data.values() {
|
||||
match item {
|
||||
BigModItem::Mod(_) => mods += 1,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ItemTreeDataStats { traits, impls, mods, macro_calls, macro_rules }
|
||||
}
|
||||
|
||||
pub fn pretty_print(&self, db: &dyn DefDatabase, edition: Edition) -> String {
|
||||
pretty::print_item_tree(db, self, edition)
|
||||
}
|
||||
|
||||
fn data(&self) -> &ItemTreeData {
|
||||
self.data.as_ref().expect("attempted to access data of empty ItemTree")
|
||||
}
|
||||
|
||||
fn data_mut(&mut self) -> &mut ItemTreeData {
|
||||
self.data.get_or_insert_with(Box::default)
|
||||
}
|
||||
|
||||
fn shrink_to_fit(&mut self) {
|
||||
let ItemTree { top_level, attrs, data } = self;
|
||||
top_level.shrink_to_fit();
|
||||
let ItemTree { top_level: _, attrs, big_data, small_data, vis: _, top_attrs: _ } = self;
|
||||
attrs.shrink_to_fit();
|
||||
if let Some(data) = data {
|
||||
let ItemTreeData {
|
||||
uses,
|
||||
extern_crates,
|
||||
extern_blocks,
|
||||
functions,
|
||||
structs,
|
||||
unions,
|
||||
enums,
|
||||
consts,
|
||||
statics,
|
||||
traits,
|
||||
trait_aliases,
|
||||
impls,
|
||||
type_aliases,
|
||||
mods,
|
||||
macro_calls,
|
||||
macro_rules,
|
||||
macro_defs,
|
||||
vis: _,
|
||||
} = &mut **data;
|
||||
|
||||
uses.shrink_to_fit();
|
||||
extern_crates.shrink_to_fit();
|
||||
extern_blocks.shrink_to_fit();
|
||||
functions.shrink_to_fit();
|
||||
structs.shrink_to_fit();
|
||||
unions.shrink_to_fit();
|
||||
enums.shrink_to_fit();
|
||||
consts.shrink_to_fit();
|
||||
statics.shrink_to_fit();
|
||||
traits.shrink_to_fit();
|
||||
trait_aliases.shrink_to_fit();
|
||||
impls.shrink_to_fit();
|
||||
type_aliases.shrink_to_fit();
|
||||
mods.shrink_to_fit();
|
||||
macro_calls.shrink_to_fit();
|
||||
macro_rules.shrink_to_fit();
|
||||
macro_defs.shrink_to_fit();
|
||||
}
|
||||
big_data.shrink_to_fit();
|
||||
small_data.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
struct ItemVisibilities {
|
||||
arena: Box<[RawVisibility]>,
|
||||
arena: ThinVec<RawVisibility>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
struct ItemTreeData {
|
||||
uses: Arena<Use>,
|
||||
extern_crates: Arena<ExternCrate>,
|
||||
extern_blocks: Arena<ExternBlock>,
|
||||
functions: Arena<Function>,
|
||||
structs: Arena<Struct>,
|
||||
unions: Arena<Union>,
|
||||
enums: Arena<Enum>,
|
||||
consts: Arena<Const>,
|
||||
statics: Arena<Static>,
|
||||
traits: Arena<Trait>,
|
||||
trait_aliases: Arena<TraitAlias>,
|
||||
impls: Arena<Impl>,
|
||||
type_aliases: Arena<TypeAlias>,
|
||||
mods: Arena<Mod>,
|
||||
macro_calls: Arena<MacroCall>,
|
||||
macro_rules: Arena<MacroRules>,
|
||||
macro_defs: Arena<Macro2>,
|
||||
|
||||
vis: ItemVisibilities,
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
enum SmallModItem {
|
||||
Const(Const),
|
||||
Enum(Enum),
|
||||
ExternBlock(ExternBlock),
|
||||
Function(Function),
|
||||
Impl(Impl),
|
||||
Macro2(Macro2),
|
||||
MacroCall(MacroCall),
|
||||
MacroRules(MacroRules),
|
||||
Static(Static),
|
||||
Struct(Struct),
|
||||
Trait(Trait),
|
||||
TraitAlias(TraitAlias),
|
||||
TypeAlias(TypeAlias),
|
||||
Union(Union),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
enum BigModItem {
|
||||
ExternCrate(ExternCrate),
|
||||
Mod(Mod),
|
||||
Use(Use),
|
||||
}
|
||||
|
||||
// `ModItem` is stored a bunch in `ItemTree`'s so we pay the max for each item. It should stay as
|
||||
// small as possible which is why we split them in two, most common ones are 3 usize but some rarer
|
||||
// ones are 5.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const _: [(); std::mem::size_of::<BigModItem>()] = [(); std::mem::size_of::<[usize; 5]>()];
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const _: [(); std::mem::size_of::<SmallModItem>()] = [(); std::mem::size_of::<[usize; 3]>()];
|
||||
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
pub struct ItemTreeDataStats {
|
||||
pub traits: usize,
|
||||
|
|
@ -307,73 +284,13 @@ pub struct ItemTreeDataStats {
|
|||
pub macro_rules: usize,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum AttrOwner {
|
||||
/// Attributes on an item.
|
||||
ModItem(ModItem),
|
||||
/// Inner attributes of the source file.
|
||||
TopLevel,
|
||||
}
|
||||
|
||||
impl From<ModItem> for AttrOwner {
|
||||
#[inline]
|
||||
fn from(value: ModItem) -> Self {
|
||||
AttrOwner::ModItem(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait implemented by all nodes in the item tree.
|
||||
pub trait ItemTreeNode: Clone {
|
||||
pub(crate) trait ItemTreeNode: Clone {
|
||||
type Source: AstIdNode;
|
||||
|
||||
fn ast_id(&self) -> FileAstId<Self::Source>;
|
||||
|
||||
/// Looks up an instance of `Self` in an item tree.
|
||||
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
|
||||
}
|
||||
|
||||
pub struct FileItemTreeId<N>(Idx<N>);
|
||||
|
||||
impl<N> FileItemTreeId<N> {
|
||||
pub fn range_iter(range: Range<Self>) -> impl Iterator<Item = Self> + Clone {
|
||||
(range.start.index().into_raw().into_u32()..range.end.index().into_raw().into_u32())
|
||||
.map(RawIdx::from_u32)
|
||||
.map(Idx::from_raw)
|
||||
.map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> FileItemTreeId<N> {
|
||||
pub fn index(&self) -> Idx<N> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Clone for FileItemTreeId<N> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
impl<N> Copy for FileItemTreeId<N> {}
|
||||
|
||||
impl<N> PartialEq for FileItemTreeId<N> {
|
||||
fn eq(&self, other: &FileItemTreeId<N>) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
impl<N> Eq for FileItemTreeId<N> {}
|
||||
|
||||
impl<N> Hash for FileItemTreeId<N> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> fmt::Debug for FileItemTreeId<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
#[allow(type_alias_bounds)]
|
||||
pub(crate) type ItemTreeAstId<T: ItemTreeNode> = FileAstId<T::Source>;
|
||||
|
||||
/// Identifies a particular [`ItemTree`].
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
|
|
@ -383,14 +300,14 @@ pub struct TreeId {
|
|||
}
|
||||
|
||||
impl TreeId {
|
||||
pub fn new(file: HirFileId, block: Option<BlockId>) -> Self {
|
||||
pub(crate) fn new(file: HirFileId, block: Option<BlockId>) -> Self {
|
||||
Self { file, block }
|
||||
}
|
||||
|
||||
pub fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
|
||||
pub(crate) fn item_tree<'db>(&self, db: &'db dyn DefDatabase) -> &'db ItemTree {
|
||||
match self.block {
|
||||
Some(block) => db.block_item_tree(block),
|
||||
None => db.file_item_tree(self.file),
|
||||
Some(block) => block_item_tree_query(db, block),
|
||||
None => file_item_tree_query(db, self.file),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -399,85 +316,32 @@ impl TreeId {
|
|||
self.file
|
||||
}
|
||||
|
||||
pub fn is_block(self) -> bool {
|
||||
pub(crate) fn is_block(self) -> bool {
|
||||
self.block.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ItemTreeId<N> {
|
||||
tree: TreeId,
|
||||
pub value: FileItemTreeId<N>,
|
||||
}
|
||||
|
||||
impl<N> ItemTreeId<N> {
|
||||
pub fn new(tree: TreeId, idx: FileItemTreeId<N>) -> Self {
|
||||
Self { tree, value: idx }
|
||||
}
|
||||
|
||||
pub fn file_id(self) -> HirFileId {
|
||||
self.tree.file
|
||||
}
|
||||
|
||||
pub fn tree_id(self) -> TreeId {
|
||||
self.tree
|
||||
}
|
||||
|
||||
pub fn item_tree(self, db: &dyn DefDatabase) -> Arc<ItemTree> {
|
||||
self.tree.item_tree(db)
|
||||
}
|
||||
|
||||
pub fn resolved<R>(self, db: &dyn DefDatabase, cb: impl FnOnce(&N) -> R) -> R
|
||||
where
|
||||
ItemTree: Index<FileItemTreeId<N>, Output = N>,
|
||||
{
|
||||
cb(&self.tree.item_tree(db)[self.value])
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Copy for ItemTreeId<N> {}
|
||||
impl<N> Clone for ItemTreeId<N> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> PartialEq for ItemTreeId<N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.tree == other.tree && self.value == other.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Eq for ItemTreeId<N> {}
|
||||
|
||||
impl<N> Hash for ItemTreeId<N> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.tree.hash(state);
|
||||
self.value.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! mod_items {
|
||||
( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => {
|
||||
($mod_item:ident -> $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => {
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum ModItem {
|
||||
pub(crate) enum $mod_item {
|
||||
$(
|
||||
$typ(FileItemTreeId<$typ>),
|
||||
$typ(FileAstId<$ast>),
|
||||
)+
|
||||
}
|
||||
|
||||
impl ModItem {
|
||||
pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> {
|
||||
impl $mod_item {
|
||||
pub(crate) fn ast_id(self) -> FileAstId<ast::Item> {
|
||||
match self {
|
||||
$(ModItem::$typ(it) => tree[it.index()].ast_id().upcast()),+
|
||||
$($mod_item::$typ(it) => it.upcast()),+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
impl From<FileItemTreeId<$typ>> for ModItem {
|
||||
fn from(id: FileItemTreeId<$typ>) -> ModItem {
|
||||
ModItem::$typ(id)
|
||||
impl From<FileAstId<$ast>> for $mod_item {
|
||||
fn from(id: FileAstId<$ast>) -> $mod_item {
|
||||
ModItemId::$typ(id)
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
|
@ -485,21 +349,19 @@ macro_rules! mod_items {
|
|||
$(
|
||||
impl ItemTreeNode for $typ {
|
||||
type Source = $ast;
|
||||
|
||||
fn ast_id(&self) -> FileAstId<Self::Source> {
|
||||
self.ast_id
|
||||
}
|
||||
|
||||
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self {
|
||||
&tree.data().$fld[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<Idx<$typ>> for ItemTree {
|
||||
impl Index<FileAstId<$ast>> for ItemTree {
|
||||
type Output = $typ;
|
||||
|
||||
fn index(&self, index: Idx<$typ>) -> &Self::Output {
|
||||
&self.data().$fld[index]
|
||||
#[allow(unused_imports)]
|
||||
fn index(&self, index: FileAstId<$ast>) -> &Self::Output {
|
||||
use BigModItem::*;
|
||||
use SmallModItem::*;
|
||||
match &self.$fld[&index.upcast()] {
|
||||
$typ(item) => item,
|
||||
_ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index),
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
|
@ -507,23 +369,24 @@ macro_rules! mod_items {
|
|||
}
|
||||
|
||||
mod_items! {
|
||||
Use in uses -> ast::Use,
|
||||
ExternCrate in extern_crates -> ast::ExternCrate,
|
||||
ExternBlock in extern_blocks -> ast::ExternBlock,
|
||||
Function in functions -> ast::Fn,
|
||||
Struct in structs -> ast::Struct,
|
||||
Union in unions -> ast::Union,
|
||||
Enum in enums -> ast::Enum,
|
||||
Const in consts -> ast::Const,
|
||||
Static in statics -> ast::Static,
|
||||
Trait in traits -> ast::Trait,
|
||||
TraitAlias in trait_aliases -> ast::TraitAlias,
|
||||
Impl in impls -> ast::Impl,
|
||||
TypeAlias in type_aliases -> ast::TypeAlias,
|
||||
Mod in mods -> ast::Module,
|
||||
MacroCall in macro_calls -> ast::MacroCall,
|
||||
MacroRules in macro_rules -> ast::MacroRules,
|
||||
Macro2 in macro_defs -> ast::MacroDef,
|
||||
ModItemId ->
|
||||
Const in small_data -> ast::Const,
|
||||
Enum in small_data -> ast::Enum,
|
||||
ExternBlock in small_data -> ast::ExternBlock,
|
||||
ExternCrate in big_data -> ast::ExternCrate,
|
||||
Function in small_data -> ast::Fn,
|
||||
Impl in small_data -> ast::Impl,
|
||||
Macro2 in small_data -> ast::MacroDef,
|
||||
MacroCall in small_data -> ast::MacroCall,
|
||||
MacroRules in small_data -> ast::MacroRules,
|
||||
Mod in big_data -> ast::Module,
|
||||
Static in small_data -> ast::Static,
|
||||
Struct in small_data -> ast::Struct,
|
||||
Trait in small_data -> ast::Trait,
|
||||
TraitAlias in small_data -> ast::TraitAlias,
|
||||
TypeAlias in small_data -> ast::TypeAlias,
|
||||
Union in small_data -> ast::Union,
|
||||
Use in big_data -> ast::Use,
|
||||
}
|
||||
|
||||
impl Index<RawVisibilityId> for ItemTree {
|
||||
|
|
@ -554,31 +417,24 @@ impl Index<RawVisibilityId> for ItemTree {
|
|||
VisibilityExplicitness::Explicit,
|
||||
)
|
||||
}),
|
||||
_ => &self.data().vis.arena[index.0 as usize],
|
||||
_ => &self.vis.arena[index.0 as usize],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
|
||||
type Output = N;
|
||||
fn index(&self, id: FileItemTreeId<N>) -> &N {
|
||||
N::lookup(self, id.index())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Use {
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::Use>,
|
||||
pub use_tree: UseTree,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
pub(crate) use_tree: UseTree,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct UseTree {
|
||||
pub index: Idx<ast::UseTree>,
|
||||
kind: UseTreeKind,
|
||||
}
|
||||
|
||||
// FIXME: Would be nice to encode `None` into this
|
||||
// We could just use a `Name` where `_` well means `_` ..
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ImportAlias {
|
||||
/// Unnamed alias, as in `use Foo as _;`
|
||||
|
|
@ -632,43 +488,37 @@ pub enum UseTreeKind {
|
|||
pub struct ExternCrate {
|
||||
pub name: Name,
|
||||
pub alias: Option<ImportAlias>,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::ExternCrate>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ExternBlock {
|
||||
pub ast_id: FileAstId<ast::ExternBlock>,
|
||||
pub children: Box<[ModItem]>,
|
||||
pub(crate) children: Box<[ModItemId]>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Function {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::Fn>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Struct {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
pub shape: FieldsShape,
|
||||
pub ast_id: FileAstId<ast::Struct>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Union {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::Union>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Enum {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::Enum>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
|
|
@ -706,55 +556,47 @@ impl VisibilityExplicitness {
|
|||
pub struct Const {
|
||||
/// `None` for `const _: () = ();`
|
||||
pub name: Option<Name>,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::Const>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Static {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::Static>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Trait {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::Trait>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct TraitAlias {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::TraitAlias>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Impl {
|
||||
pub ast_id: FileAstId<ast::Impl>,
|
||||
}
|
||||
pub struct Impl {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TypeAlias {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::TypeAlias>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Mod {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub kind: ModKind,
|
||||
pub ast_id: FileAstId<ast::Module>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
pub(crate) kind: ModKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum ModKind {
|
||||
pub(crate) enum ModKind {
|
||||
/// `mod m { ... }`
|
||||
Inline { items: Box<[ModItem]> },
|
||||
Inline { items: Box<[ModItemId]> },
|
||||
/// `mod m;`
|
||||
Outline,
|
||||
}
|
||||
|
|
@ -763,7 +605,6 @@ pub enum ModKind {
|
|||
pub struct MacroCall {
|
||||
/// Path to the called macro.
|
||||
pub path: Interned<ModPath>,
|
||||
pub ast_id: FileAstId<ast::MacroCall>,
|
||||
pub expand_to: ExpandTo,
|
||||
pub ctxt: SyntaxContext,
|
||||
}
|
||||
|
|
@ -772,15 +613,13 @@ pub struct MacroCall {
|
|||
pub struct MacroRules {
|
||||
/// The name of the declared macro.
|
||||
pub name: Name,
|
||||
pub ast_id: FileAstId<ast::MacroRules>,
|
||||
}
|
||||
|
||||
/// "Macros 2.0" macro definition.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Macro2 {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::MacroDef>,
|
||||
pub(crate) visibility: RawVisibilityId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
|
|
@ -793,15 +632,17 @@ pub enum ImportKind {
|
|||
TypeOnly,
|
||||
}
|
||||
|
||||
impl UseTree {
|
||||
impl Use {
|
||||
/// Expands the `UseTree` into individually imported `ModPath`s.
|
||||
pub fn expand(
|
||||
&self,
|
||||
mut cb: impl FnMut(Idx<ast::UseTree>, ModPath, ImportKind, Option<ImportAlias>),
|
||||
) {
|
||||
self.expand_impl(None, &mut cb)
|
||||
self.use_tree.expand_impl(None, &mut 0, &mut cb)
|
||||
}
|
||||
}
|
||||
|
||||
impl UseTree {
|
||||
/// The [`UseTreeKind`] of this `UseTree`.
|
||||
pub fn kind(&self) -> &UseTreeKind {
|
||||
&self.kind
|
||||
|
|
@ -810,6 +651,7 @@ impl UseTree {
|
|||
fn expand_impl(
|
||||
&self,
|
||||
prefix: Option<ModPath>,
|
||||
counting_index: &mut u32,
|
||||
cb: &mut impl FnMut(Idx<ast::UseTree>, ModPath, ImportKind, Option<ImportAlias>),
|
||||
) {
|
||||
fn concat_mod_paths(
|
||||
|
|
@ -845,17 +687,27 @@ impl UseTree {
|
|||
match &self.kind {
|
||||
UseTreeKind::Single { path, alias } => {
|
||||
if let Some((path, kind)) = concat_mod_paths(prefix, path) {
|
||||
cb(self.index, path, kind, alias.clone());
|
||||
cb(Idx::from_raw(RawIdx::from_u32(*counting_index)), path, kind, alias.clone());
|
||||
}
|
||||
}
|
||||
UseTreeKind::Glob { path: Some(path) } => {
|
||||
if let Some((path, _)) = concat_mod_paths(prefix, path) {
|
||||
cb(self.index, path, ImportKind::Glob, None);
|
||||
cb(
|
||||
Idx::from_raw(RawIdx::from_u32(*counting_index)),
|
||||
path,
|
||||
ImportKind::Glob,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
UseTreeKind::Glob { path: None } => {
|
||||
if let Some(prefix) = prefix {
|
||||
cb(self.index, prefix, ImportKind::Glob, None);
|
||||
cb(
|
||||
Idx::from_raw(RawIdx::from_u32(*counting_index)),
|
||||
prefix,
|
||||
ImportKind::Glob,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
UseTreeKind::Prefixed { prefix: additional_prefix, list } => {
|
||||
|
|
@ -867,7 +719,8 @@ impl UseTree {
|
|||
None => prefix,
|
||||
};
|
||||
for tree in &**list {
|
||||
tree.expand_impl(prefix.clone(), cb);
|
||||
*counting_index += 1;
|
||||
tree.expand_impl(prefix.clone(), counting_index, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use hir_expand::{
|
|||
span_map::{SpanMap, SpanMapRef},
|
||||
};
|
||||
use la_arena::Arena;
|
||||
use span::{AstIdMap, SyntaxContext};
|
||||
use span::{AstIdMap, FileAstId, SyntaxContext};
|
||||
use syntax::{
|
||||
AstNode,
|
||||
ast::{self, HasModuleItem, HasName},
|
||||
|
|
@ -20,24 +20,21 @@ use triomphe::Arc;
|
|||
use crate::{
|
||||
db::DefDatabase,
|
||||
item_tree::{
|
||||
AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, FileItemTreeId, Function,
|
||||
Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData, Macro2, MacroCall, MacroRules,
|
||||
Mod, ModItem, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct,
|
||||
StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
|
||||
BigModItem, Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl,
|
||||
ImportAlias, Interned, ItemTree, ItemTreeAstId, Macro2, MacroCall, MacroRules, Mod,
|
||||
ModItemId, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, SmallModItem,
|
||||
Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
|
||||
VisibilityExplicitness,
|
||||
},
|
||||
};
|
||||
|
||||
fn id<N>(index: Idx<N>) -> FileItemTreeId<N> {
|
||||
FileItemTreeId(index)
|
||||
}
|
||||
|
||||
pub(super) struct Ctx<'a> {
|
||||
db: &'a dyn DefDatabase,
|
||||
tree: ItemTree,
|
||||
source_ast_id_map: Arc<AstIdMap>,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
file: HirFileId,
|
||||
top_level: Vec<ModItemId>,
|
||||
visibilities: FxIndexSet<RawVisibility>,
|
||||
}
|
||||
|
||||
|
|
@ -50,6 +47,7 @@ impl<'a> Ctx<'a> {
|
|||
file,
|
||||
span_map: OnceCell::new(),
|
||||
visibilities: FxIndexSet::default(),
|
||||
top_level: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -58,16 +56,14 @@ impl<'a> Ctx<'a> {
|
|||
}
|
||||
|
||||
pub(super) fn lower_module_items(mut self, item_owner: &dyn HasModuleItem) -> ItemTree {
|
||||
self.tree.top_level =
|
||||
item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect();
|
||||
if let Some(data) = &mut self.tree.data {
|
||||
data.vis.arena = self.visibilities.into_iter().collect();
|
||||
}
|
||||
self.top_level = item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect();
|
||||
self.tree.vis.arena = self.visibilities.into_iter().collect();
|
||||
self.tree.top_level = self.top_level.into_boxed_slice();
|
||||
self.tree
|
||||
}
|
||||
|
||||
pub(super) fn lower_macro_stmts(mut self, stmts: ast::MacroStmts) -> ItemTree {
|
||||
self.tree.top_level = stmts
|
||||
self.top_level = stmts
|
||||
.statements()
|
||||
.filter_map(|stmt| {
|
||||
match stmt {
|
||||
|
|
@ -91,20 +87,19 @@ impl<'a> Ctx<'a> {
|
|||
if let Some(call) = tail_macro.macro_call() {
|
||||
cov_mark::hit!(macro_stmt_with_trailing_macro_expr);
|
||||
if let Some(mod_item) = self.lower_mod_item(&call.into()) {
|
||||
self.tree.top_level.push(mod_item);
|
||||
self.top_level.push(mod_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(data) = &mut self.tree.data {
|
||||
data.vis.arena = self.visibilities.into_iter().collect();
|
||||
}
|
||||
self.tree.vis.arena = self.visibilities.into_iter().collect();
|
||||
self.tree.top_level = self.top_level.into_boxed_slice();
|
||||
self.tree
|
||||
}
|
||||
|
||||
pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> ItemTree {
|
||||
self.tree.attrs.insert(AttrOwner::TopLevel, RawAttrs::new(self.db, block, self.span_map()));
|
||||
self.tree.top_level = block
|
||||
self.tree.top_attrs = RawAttrs::new(self.db, block, self.span_map());
|
||||
self.top_level = block
|
||||
.statements()
|
||||
.filter_map(|stmt| match stmt {
|
||||
ast::Stmt::Item(item) => self.lower_mod_item(&item),
|
||||
|
|
@ -120,22 +115,17 @@ impl<'a> Ctx<'a> {
|
|||
if let Some(ast::Expr::MacroExpr(expr)) = block.tail_expr() {
|
||||
if let Some(call) = expr.macro_call() {
|
||||
if let Some(mod_item) = self.lower_mod_item(&call.into()) {
|
||||
self.tree.top_level.push(mod_item);
|
||||
self.top_level.push(mod_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(data) = &mut self.tree.data {
|
||||
data.vis.arena = self.visibilities.into_iter().collect();
|
||||
}
|
||||
self.tree.vis.arena = self.visibilities.into_iter().collect();
|
||||
self.tree.top_level = self.top_level.into_boxed_slice();
|
||||
self.tree
|
||||
}
|
||||
|
||||
fn data(&mut self) -> &mut ItemTreeData {
|
||||
self.tree.data_mut()
|
||||
}
|
||||
|
||||
fn lower_mod_item(&mut self, item: &ast::Item) -> Option<ModItem> {
|
||||
let mod_item: ModItem = match item {
|
||||
fn lower_mod_item(&mut self, item: &ast::Item) -> Option<ModItemId> {
|
||||
let mod_item: ModItemId = match item {
|
||||
ast::Item::Struct(ast) => self.lower_struct(ast)?.into(),
|
||||
ast::Item::Union(ast) => self.lower_union(ast)?.into(),
|
||||
ast::Item::Enum(ast) => self.lower_enum(ast)?.into(),
|
||||
|
|
@ -155,12 +145,12 @@ impl<'a> Ctx<'a> {
|
|||
ast::Item::ExternBlock(ast) => self.lower_extern_block(ast).into(),
|
||||
};
|
||||
let attrs = RawAttrs::new(self.db, item, self.span_map());
|
||||
self.add_attrs(mod_item.into(), attrs);
|
||||
self.add_attrs(mod_item.ast_id(), attrs);
|
||||
|
||||
Some(mod_item)
|
||||
}
|
||||
|
||||
fn add_attrs(&mut self, item: AttrOwner, attrs: RawAttrs) {
|
||||
fn add_attrs(&mut self, item: FileAstId<ast::Item>, attrs: RawAttrs) {
|
||||
if !attrs.is_empty() {
|
||||
match self.tree.attrs.entry(item) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
|
|
@ -173,76 +163,78 @@ impl<'a> Ctx<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> {
|
||||
fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<ItemTreeAstId<Struct>> {
|
||||
let visibility = self.lower_visibility(strukt);
|
||||
let name = strukt.name()?.as_name();
|
||||
let ast_id = self.source_ast_id_map.ast_id(strukt);
|
||||
let shape = adt_shape(strukt.kind());
|
||||
let res = Struct { name, visibility, shape, ast_id };
|
||||
let id = id(self.data().structs.alloc(res));
|
||||
let res = Struct { name, visibility, shape };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Struct(res));
|
||||
|
||||
Some(id)
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
|
||||
fn lower_union(&mut self, union: &ast::Union) -> Option<ItemTreeAstId<Union>> {
|
||||
let visibility = self.lower_visibility(union);
|
||||
let name = union.name()?.as_name();
|
||||
let ast_id = self.source_ast_id_map.ast_id(union);
|
||||
let res = Union { name, visibility, ast_id };
|
||||
let id = id(self.data().unions.alloc(res));
|
||||
Some(id)
|
||||
let res = Union { name, visibility };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Union(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_enum(&mut self, enum_: &ast::Enum) -> Option<FileItemTreeId<Enum>> {
|
||||
fn lower_enum(&mut self, enum_: &ast::Enum) -> Option<ItemTreeAstId<Enum>> {
|
||||
let visibility = self.lower_visibility(enum_);
|
||||
let name = enum_.name()?.as_name();
|
||||
let ast_id = self.source_ast_id_map.ast_id(enum_);
|
||||
let res = Enum { name, visibility, ast_id };
|
||||
let id = id(self.data().enums.alloc(res));
|
||||
Some(id)
|
||||
let res = Enum { name, visibility };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Enum(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> {
|
||||
fn lower_function(&mut self, func: &ast::Fn) -> Option<ItemTreeAstId<Function>> {
|
||||
let visibility = self.lower_visibility(func);
|
||||
let name = func.name()?.as_name();
|
||||
|
||||
let ast_id = self.source_ast_id_map.ast_id(func);
|
||||
|
||||
let res = Function { name, visibility, ast_id };
|
||||
let res = Function { name, visibility };
|
||||
|
||||
let id = id(self.data().functions.alloc(res));
|
||||
Some(id)
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Function(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_type_alias(
|
||||
&mut self,
|
||||
type_alias: &ast::TypeAlias,
|
||||
) -> Option<FileItemTreeId<TypeAlias>> {
|
||||
) -> Option<ItemTreeAstId<TypeAlias>> {
|
||||
let name = type_alias.name()?.as_name();
|
||||
let visibility = self.lower_visibility(type_alias);
|
||||
let ast_id = self.source_ast_id_map.ast_id(type_alias);
|
||||
let res = TypeAlias { name, visibility, ast_id };
|
||||
let id = id(self.data().type_aliases.alloc(res));
|
||||
Some(id)
|
||||
let res = TypeAlias { name, visibility };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TypeAlias(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_static(&mut self, static_: &ast::Static) -> Option<FileItemTreeId<Static>> {
|
||||
fn lower_static(&mut self, static_: &ast::Static) -> Option<ItemTreeAstId<Static>> {
|
||||
let name = static_.name()?.as_name();
|
||||
let visibility = self.lower_visibility(static_);
|
||||
let ast_id = self.source_ast_id_map.ast_id(static_);
|
||||
let res = Static { name, visibility, ast_id };
|
||||
Some(id(self.data().statics.alloc(res)))
|
||||
let res = Static { name, visibility };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Static(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId<Const> {
|
||||
fn lower_const(&mut self, konst: &ast::Const) -> ItemTreeAstId<Const> {
|
||||
let name = konst.name().map(|it| it.as_name());
|
||||
let visibility = self.lower_visibility(konst);
|
||||
let ast_id = self.source_ast_id_map.ast_id(konst);
|
||||
let res = Const { name, visibility, ast_id };
|
||||
id(self.data().consts.alloc(res))
|
||||
let res = Const { name, visibility };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Const(res));
|
||||
ast_id
|
||||
}
|
||||
|
||||
fn lower_module(&mut self, module: &ast::Module) -> Option<FileItemTreeId<Mod>> {
|
||||
fn lower_module(&mut self, module: &ast::Module) -> Option<ItemTreeAstId<Mod>> {
|
||||
let name = module.name()?.as_name();
|
||||
let visibility = self.lower_visibility(module);
|
||||
let kind = if module.semicolon_token().is_some() {
|
||||
|
|
@ -259,56 +251,59 @@ impl<'a> Ctx<'a> {
|
|||
}
|
||||
};
|
||||
let ast_id = self.source_ast_id_map.ast_id(module);
|
||||
let res = Mod { name, visibility, kind, ast_id };
|
||||
Some(id(self.data().mods.alloc(res)))
|
||||
let res = Mod { name, visibility, kind };
|
||||
self.tree.big_data.insert(ast_id.upcast(), BigModItem::Mod(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option<FileItemTreeId<Trait>> {
|
||||
fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option<ItemTreeAstId<Trait>> {
|
||||
let name = trait_def.name()?.as_name();
|
||||
let visibility = self.lower_visibility(trait_def);
|
||||
let ast_id = self.source_ast_id_map.ast_id(trait_def);
|
||||
|
||||
let def = Trait { name, visibility, ast_id };
|
||||
let id = id(self.data().traits.alloc(def));
|
||||
Some(id)
|
||||
let def = Trait { name, visibility };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Trait(def));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_trait_alias(
|
||||
&mut self,
|
||||
trait_alias_def: &ast::TraitAlias,
|
||||
) -> Option<FileItemTreeId<TraitAlias>> {
|
||||
) -> Option<ItemTreeAstId<TraitAlias>> {
|
||||
let name = trait_alias_def.name()?.as_name();
|
||||
let visibility = self.lower_visibility(trait_alias_def);
|
||||
let ast_id = self.source_ast_id_map.ast_id(trait_alias_def);
|
||||
|
||||
let alias = TraitAlias { name, visibility, ast_id };
|
||||
let id = id(self.data().trait_aliases.alloc(alias));
|
||||
Some(id)
|
||||
let alias = TraitAlias { name, visibility };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TraitAlias(alias));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId<Impl> {
|
||||
fn lower_impl(&mut self, impl_def: &ast::Impl) -> ItemTreeAstId<Impl> {
|
||||
let ast_id = self.source_ast_id_map.ast_id(impl_def);
|
||||
// Note that trait impls don't get implicit `Self` unlike traits, because here they are a
|
||||
// type alias rather than a type parameter, so this is handled by the resolver.
|
||||
let res = Impl { ast_id };
|
||||
id(self.data().impls.alloc(res))
|
||||
let res = Impl {};
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Impl(res));
|
||||
ast_id
|
||||
}
|
||||
|
||||
fn lower_use(&mut self, use_item: &ast::Use) -> Option<FileItemTreeId<Use>> {
|
||||
fn lower_use(&mut self, use_item: &ast::Use) -> Option<ItemTreeAstId<Use>> {
|
||||
let visibility = self.lower_visibility(use_item);
|
||||
let ast_id = self.source_ast_id_map.ast_id(use_item);
|
||||
let (use_tree, _) = lower_use_tree(self.db, use_item.use_tree()?, &mut |range| {
|
||||
self.span_map().span_for_range(range).ctx
|
||||
})?;
|
||||
|
||||
let res = Use { visibility, ast_id, use_tree };
|
||||
Some(id(self.data().uses.alloc(res)))
|
||||
let res = Use { visibility, use_tree };
|
||||
self.tree.big_data.insert(ast_id.upcast(), BigModItem::Use(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_extern_crate(
|
||||
&mut self,
|
||||
extern_crate: &ast::ExternCrate,
|
||||
) -> Option<FileItemTreeId<ExternCrate>> {
|
||||
) -> Option<ItemTreeAstId<ExternCrate>> {
|
||||
let name = extern_crate.name_ref()?.as_name();
|
||||
let alias = extern_crate.rename().map(|a| {
|
||||
a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
|
||||
|
|
@ -316,11 +311,12 @@ impl<'a> Ctx<'a> {
|
|||
let visibility = self.lower_visibility(extern_crate);
|
||||
let ast_id = self.source_ast_id_map.ast_id(extern_crate);
|
||||
|
||||
let res = ExternCrate { name, alias, visibility, ast_id };
|
||||
Some(id(self.data().extern_crates.alloc(res)))
|
||||
let res = ExternCrate { name, alias, visibility };
|
||||
self.tree.big_data.insert(ast_id.upcast(), BigModItem::ExternCrate(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
|
||||
fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<ItemTreeAstId<MacroCall>> {
|
||||
let span_map = self.span_map();
|
||||
let path = m.path()?;
|
||||
let range = path.syntax().text_range();
|
||||
|
|
@ -329,29 +325,32 @@ impl<'a> Ctx<'a> {
|
|||
})?);
|
||||
let ast_id = self.source_ast_id_map.ast_id(m);
|
||||
let expand_to = hir_expand::ExpandTo::from_call_site(m);
|
||||
let res = MacroCall { path, ast_id, expand_to, ctxt: span_map.span_for_range(range).ctx };
|
||||
Some(id(self.data().macro_calls.alloc(res)))
|
||||
let res = MacroCall { path, expand_to, ctxt: span_map.span_for_range(range).ctx };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::MacroCall(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> {
|
||||
fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<ItemTreeAstId<MacroRules>> {
|
||||
let name = m.name()?;
|
||||
let ast_id = self.source_ast_id_map.ast_id(m);
|
||||
|
||||
let res = MacroRules { name: name.as_name(), ast_id };
|
||||
Some(id(self.data().macro_rules.alloc(res)))
|
||||
let res = MacroRules { name: name.as_name() };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::MacroRules(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<Macro2>> {
|
||||
fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<ItemTreeAstId<Macro2>> {
|
||||
let name = m.name()?;
|
||||
|
||||
let ast_id = self.source_ast_id_map.ast_id(m);
|
||||
let visibility = self.lower_visibility(m);
|
||||
|
||||
let res = Macro2 { name: name.as_name(), ast_id, visibility };
|
||||
Some(id(self.data().macro_defs.alloc(res)))
|
||||
let res = Macro2 { name: name.as_name(), visibility };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Macro2(res));
|
||||
Some(ast_id)
|
||||
}
|
||||
|
||||
fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId<ExternBlock> {
|
||||
fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> ItemTreeAstId<ExternBlock> {
|
||||
let ast_id = self.source_ast_id_map.ast_id(block);
|
||||
let children: Box<[_]> = block.extern_item_list().map_or(Box::new([]), |list| {
|
||||
list.extern_items()
|
||||
|
|
@ -360,21 +359,22 @@ impl<'a> Ctx<'a> {
|
|||
// (in other words, the knowledge that they're in an extern block must not be used).
|
||||
// This is because an extern block can contain macros whose ItemTree's top-level items
|
||||
// should be considered to be in an extern block too.
|
||||
let mod_item: ModItem = match &item {
|
||||
let mod_item: ModItemId = match &item {
|
||||
ast::ExternItem::Fn(ast) => self.lower_function(ast)?.into(),
|
||||
ast::ExternItem::Static(ast) => self.lower_static(ast)?.into(),
|
||||
ast::ExternItem::TypeAlias(ty) => self.lower_type_alias(ty)?.into(),
|
||||
ast::ExternItem::MacroCall(call) => self.lower_macro_call(call)?.into(),
|
||||
};
|
||||
let attrs = RawAttrs::new(self.db, &item, self.span_map());
|
||||
self.add_attrs(mod_item.into(), attrs);
|
||||
self.add_attrs(mod_item.ast_id(), attrs);
|
||||
Some(mod_item)
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
|
||||
let res = ExternBlock { ast_id, children };
|
||||
id(self.data().extern_blocks.alloc(res))
|
||||
let res = ExternBlock { children };
|
||||
self.tree.small_data.insert(ast_id.upcast(), SmallModItem::ExternBlock(res));
|
||||
ast_id
|
||||
}
|
||||
|
||||
fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
|
||||
|
|
@ -425,17 +425,15 @@ impl UseTreeLowering<'_> {
|
|||
}
|
||||
};
|
||||
|
||||
self.mapping.alloc(tree.clone());
|
||||
let list = use_tree_list
|
||||
.use_trees()
|
||||
.filter_map(|tree| self.lower_use_tree(tree, span_for_range))
|
||||
.collect();
|
||||
|
||||
Some(
|
||||
self.use_tree(
|
||||
UseTreeKind::Prefixed { prefix: prefix.map(Interned::new), list },
|
||||
tree,
|
||||
),
|
||||
)
|
||||
Some(UseTree {
|
||||
kind: UseTreeKind::Prefixed { prefix: prefix.map(Interned::new), list },
|
||||
})
|
||||
} else {
|
||||
let is_glob = tree.star_token().is_some();
|
||||
let path = match tree.path() {
|
||||
|
|
@ -454,23 +452,20 @@ impl UseTreeLowering<'_> {
|
|||
if path.is_none() {
|
||||
cov_mark::hit!(glob_enum_group);
|
||||
}
|
||||
Some(self.use_tree(UseTreeKind::Glob { path: path.map(Interned::new) }, tree))
|
||||
self.mapping.alloc(tree.clone());
|
||||
Some(UseTree { kind: UseTreeKind::Glob { path: path.map(Interned::new) } })
|
||||
}
|
||||
// Globs can't be renamed
|
||||
(_, Some(_), true) | (None, None, false) => None,
|
||||
// `bla::{ as Name}` is invalid
|
||||
(None, Some(_), false) => None,
|
||||
(Some(path), alias, false) => Some(
|
||||
self.use_tree(UseTreeKind::Single { path: Interned::new(path), alias }, tree),
|
||||
),
|
||||
(Some(path), alias, false) => {
|
||||
self.mapping.alloc(tree.clone());
|
||||
Some(UseTree { kind: UseTreeKind::Single { path: Interned::new(path), alias } })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn use_tree(&mut self, kind: UseTreeKind, ast: ast::UseTree) -> UseTree {
|
||||
let index = self.mapping.alloc(ast);
|
||||
UseTree { index, kind }
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn lower_use_tree(
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ use span::{Edition, ErasedFileAstId};
|
|||
|
||||
use crate::{
|
||||
item_tree::{
|
||||
AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl,
|
||||
ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, RawAttrs, RawVisibilityId,
|
||||
Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
|
||||
Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ItemTree,
|
||||
Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, RawAttrs, RawVisibilityId, Static,
|
||||
Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
|
||||
},
|
||||
visibility::RawVisibility,
|
||||
};
|
||||
|
|
@ -17,9 +17,7 @@ pub(super) fn print_item_tree(db: &dyn DefDatabase, tree: &ItemTree, edition: Ed
|
|||
let mut p =
|
||||
Printer { db, tree, buf: String::new(), indent_level: 0, needs_indent: true, edition };
|
||||
|
||||
if let Some(attrs) = tree.attrs.get(&AttrOwner::TopLevel) {
|
||||
p.print_attrs(attrs, true, "\n");
|
||||
}
|
||||
p.print_attrs(&tree.top_attrs, true, "\n");
|
||||
p.blank();
|
||||
|
||||
for item in tree.top_level_items() {
|
||||
|
|
@ -101,8 +99,8 @@ impl Printer<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn print_attrs_of(&mut self, of: impl Into<AttrOwner>, separated_by: &str) {
|
||||
if let Some(attrs) = self.tree.attrs.get(&of.into()) {
|
||||
fn print_attrs_of(&mut self, of: ModItemId, separated_by: &str) {
|
||||
if let Some(attrs) = self.tree.attrs.get(&of.ast_id()) {
|
||||
self.print_attrs(attrs, false, separated_by);
|
||||
}
|
||||
}
|
||||
|
|
@ -159,20 +157,20 @@ impl Printer<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn print_mod_item(&mut self, item: ModItem) {
|
||||
fn print_mod_item(&mut self, item: ModItemId) {
|
||||
self.print_attrs_of(item, "\n");
|
||||
|
||||
match item {
|
||||
ModItem::Use(it) => {
|
||||
let Use { visibility, use_tree, ast_id } = &self.tree[it];
|
||||
ModItemId::Use(ast_id) => {
|
||||
let Use { visibility, use_tree } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "use ");
|
||||
self.print_use_tree(use_tree);
|
||||
wln!(self, ";");
|
||||
}
|
||||
ModItem::ExternCrate(it) => {
|
||||
let ExternCrate { name, alias, visibility, ast_id } = &self.tree[it];
|
||||
ModItemId::ExternCrate(ast_id) => {
|
||||
let ExternCrate { name, alias, visibility } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "extern crate {}", name.display(self.db, self.edition));
|
||||
|
|
@ -181,8 +179,8 @@ impl Printer<'_> {
|
|||
}
|
||||
wln!(self, ";");
|
||||
}
|
||||
ModItem::ExternBlock(it) => {
|
||||
let ExternBlock { ast_id, children } = &self.tree[it];
|
||||
ModItemId::ExternBlock(ast_id) => {
|
||||
let ExternBlock { children } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
w!(self, "extern {{");
|
||||
self.indented(|this| {
|
||||
|
|
@ -192,14 +190,14 @@ impl Printer<'_> {
|
|||
});
|
||||
wln!(self, "}}");
|
||||
}
|
||||
ModItem::Function(it) => {
|
||||
let Function { name, visibility, ast_id } = &self.tree[it];
|
||||
ModItemId::Function(ast_id) => {
|
||||
let Function { name, visibility } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
wln!(self, "fn {};", name.display(self.db, self.edition));
|
||||
}
|
||||
ModItem::Struct(it) => {
|
||||
let Struct { visibility, name, shape: kind, ast_id } = &self.tree[it];
|
||||
ModItemId::Struct(ast_id) => {
|
||||
let Struct { visibility, name, shape: kind } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "struct {}", name.display(self.db, self.edition));
|
||||
|
|
@ -210,22 +208,22 @@ impl Printer<'_> {
|
|||
wln!(self, ";");
|
||||
}
|
||||
}
|
||||
ModItem::Union(it) => {
|
||||
let Union { name, visibility, ast_id } = &self.tree[it];
|
||||
ModItemId::Union(ast_id) => {
|
||||
let Union { name, visibility } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "union {}", name.display(self.db, self.edition));
|
||||
self.print_fields(FieldsShape::Record);
|
||||
wln!(self);
|
||||
}
|
||||
ModItem::Enum(it) => {
|
||||
let Enum { name, visibility, ast_id } = &self.tree[it];
|
||||
ModItemId::Enum(ast_id) => {
|
||||
let Enum { name, visibility } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "enum {} {{ ... }}", name.display(self.db, self.edition));
|
||||
}
|
||||
ModItem::Const(it) => {
|
||||
let Const { name, visibility, ast_id } = &self.tree[it];
|
||||
ModItemId::Const(ast_id) => {
|
||||
let Const { name, visibility } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "const ");
|
||||
|
|
@ -235,8 +233,8 @@ impl Printer<'_> {
|
|||
}
|
||||
wln!(self, " = _;");
|
||||
}
|
||||
ModItem::Static(it) => {
|
||||
let Static { name, visibility, ast_id } = &self.tree[it];
|
||||
ModItemId::Static(ast_id) => {
|
||||
let Static { name, visibility } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "static ");
|
||||
|
|
@ -244,33 +242,33 @@ impl Printer<'_> {
|
|||
w!(self, " = _;");
|
||||
wln!(self);
|
||||
}
|
||||
ModItem::Trait(it) => {
|
||||
let Trait { name, visibility, ast_id } = &self.tree[it];
|
||||
ModItemId::Trait(ast_id) => {
|
||||
let Trait { name, visibility } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "trait {} {{ ... }}", name.display(self.db, self.edition));
|
||||
}
|
||||
ModItem::TraitAlias(it) => {
|
||||
let TraitAlias { name, visibility, ast_id } = &self.tree[it];
|
||||
ModItemId::TraitAlias(ast_id) => {
|
||||
let TraitAlias { name, visibility } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
wln!(self, "trait {} = ..;", name.display(self.db, self.edition));
|
||||
}
|
||||
ModItem::Impl(it) => {
|
||||
let Impl { ast_id } = &self.tree[it];
|
||||
ModItemId::Impl(ast_id) => {
|
||||
let Impl {} = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
w!(self, "impl {{ ... }}");
|
||||
}
|
||||
ModItem::TypeAlias(it) => {
|
||||
let TypeAlias { name, visibility, ast_id } = &self.tree[it];
|
||||
ModItemId::TypeAlias(ast_id) => {
|
||||
let TypeAlias { name, visibility } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "type {}", name.display(self.db, self.edition));
|
||||
w!(self, ";");
|
||||
wln!(self);
|
||||
}
|
||||
ModItem::Mod(it) => {
|
||||
let Mod { name, visibility, kind, ast_id } = &self.tree[it];
|
||||
ModItemId::Mod(ast_id) => {
|
||||
let Mod { name, visibility, kind } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "mod {}", name.display(self.db, self.edition));
|
||||
|
|
@ -289,8 +287,8 @@ impl Printer<'_> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ModItem::MacroCall(it) => {
|
||||
let MacroCall { path, ast_id, expand_to, ctxt } = &self.tree[it];
|
||||
ModItemId::MacroCall(ast_id) => {
|
||||
let MacroCall { path, expand_to, ctxt } = &self.tree[ast_id];
|
||||
let _ = writeln!(
|
||||
self,
|
||||
"// AstId: {:#?}, SyntaxContextId: {}, ExpandTo: {:?}",
|
||||
|
|
@ -300,13 +298,13 @@ impl Printer<'_> {
|
|||
);
|
||||
wln!(self, "{}!(...);", path.display(self.db, self.edition));
|
||||
}
|
||||
ModItem::MacroRules(it) => {
|
||||
let MacroRules { name, ast_id } = &self.tree[it];
|
||||
ModItemId::MacroRules(ast_id) => {
|
||||
let MacroRules { name } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
wln!(self, "macro_rules! {} {{ ... }}", name.display(self.db, self.edition));
|
||||
}
|
||||
ModItem::Macro2(it) => {
|
||||
let Macro2 { name, visibility, ast_id } = &self.tree[it];
|
||||
ModItemId::Macro2(ast_id) => {
|
||||
let Macro2 { name, visibility } = &self.tree[ast_id];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
wln!(self, "macro {} {{ ... }}", name.display(self.db, self.edition));
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ use crate::{
|
|||
LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
|
||||
db::DefDatabase,
|
||||
item_scope::{BuiltinShadowMode, ItemScope},
|
||||
item_tree::{ItemTreeId, Mod, TreeId},
|
||||
item_tree::TreeId,
|
||||
nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
|
||||
per_ns::PerNs,
|
||||
visibility::{Visibility, VisibilityExplicitness},
|
||||
|
|
@ -289,11 +289,11 @@ pub enum ModuleOrigin {
|
|||
File {
|
||||
is_mod_rs: bool,
|
||||
declaration: FileAstId<ast::Module>,
|
||||
declaration_tree_id: ItemTreeId<Mod>,
|
||||
declaration_tree_id: TreeId,
|
||||
definition: EditionedFileId,
|
||||
},
|
||||
Inline {
|
||||
definition_tree_id: ItemTreeId<Mod>,
|
||||
definition_tree_id: TreeId,
|
||||
definition: FileAstId<ast::Module>,
|
||||
},
|
||||
/// Pseudo-module introduced by a block scope (contains only inner items).
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ use crate::{
|
|||
db::DefDatabase,
|
||||
item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports},
|
||||
item_tree::{
|
||||
self, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, ItemTreeId,
|
||||
ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind,
|
||||
self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, Macro2, MacroCall,
|
||||
MacroRules, Mod, ModItemId, ModKind, TreeId,
|
||||
},
|
||||
macro_call_as_call_id,
|
||||
nameres::{
|
||||
|
|
@ -140,7 +140,6 @@ struct ImportSource {
|
|||
id: UseId,
|
||||
is_prelude: bool,
|
||||
kind: ImportKind,
|
||||
item_tree_id: ItemTreeId<item_tree::Use>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
|
|
@ -154,19 +153,19 @@ struct Import {
|
|||
impl Import {
|
||||
fn from_use(
|
||||
tree: &ItemTree,
|
||||
item_tree_id: ItemTreeId<item_tree::Use>,
|
||||
item: FileAstId<ast::Use>,
|
||||
id: UseId,
|
||||
is_prelude: bool,
|
||||
mut cb: impl FnMut(Self),
|
||||
) {
|
||||
let it = &tree[item_tree_id.value];
|
||||
let it = &tree[item];
|
||||
let visibility = &tree[it.visibility];
|
||||
it.use_tree.expand(|idx, path, kind, alias| {
|
||||
it.expand(|idx, path, kind, alias| {
|
||||
cb(Self {
|
||||
path,
|
||||
alias,
|
||||
visibility: visibility.clone(),
|
||||
source: ImportSource { use_tree: idx, id, is_prelude, kind, item_tree_id },
|
||||
source: ImportSource { use_tree: idx, id, is_prelude, kind },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -181,15 +180,15 @@ struct ImportDirective {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
struct MacroDirective {
|
||||
struct MacroDirective<'db> {
|
||||
module_id: LocalModuleId,
|
||||
depth: usize,
|
||||
kind: MacroDirectiveKind,
|
||||
kind: MacroDirectiveKind<'db>,
|
||||
container: ItemContainerId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
enum MacroDirectiveKind {
|
||||
enum MacroDirectiveKind<'db> {
|
||||
FnLike {
|
||||
ast_id: AstIdWithPath<ast::MacroCall>,
|
||||
expand_to: ExpandTo,
|
||||
|
|
@ -206,30 +205,31 @@ enum MacroDirectiveKind {
|
|||
Attr {
|
||||
ast_id: AstIdWithPath<ast::Item>,
|
||||
attr: Attr,
|
||||
mod_item: ModItem,
|
||||
mod_item: ModItemId,
|
||||
/* is this needed? */ tree: TreeId,
|
||||
item_tree: &'db ItemTree,
|
||||
},
|
||||
}
|
||||
|
||||
/// Walks the tree of module recursively
|
||||
struct DefCollector<'a> {
|
||||
db: &'a dyn DefDatabase,
|
||||
struct DefCollector<'db> {
|
||||
db: &'db dyn DefDatabase,
|
||||
def_map: DefMap,
|
||||
local_def_map: LocalDefMap,
|
||||
/// Set only in case of blocks.
|
||||
crate_local_def_map: Option<&'a LocalDefMap>,
|
||||
crate_local_def_map: Option<&'db LocalDefMap>,
|
||||
// The dependencies of the current crate, including optional deps like `test`.
|
||||
deps: FxHashMap<Name, BuiltDependency>,
|
||||
glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, GlobId)>>,
|
||||
unresolved_imports: Vec<ImportDirective>,
|
||||
indeterminate_imports: Vec<(ImportDirective, PerNs)>,
|
||||
unresolved_macros: Vec<MacroDirective>,
|
||||
unresolved_macros: Vec<MacroDirective<'db>>,
|
||||
// We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
|
||||
// resolve. When we emit diagnostics for unresolved imports, we only do so if the import
|
||||
// doesn't start with an unresolved crate's name.
|
||||
unresolved_extern_crates: FxHashSet<Name>,
|
||||
mod_dirs: FxHashMap<LocalModuleId, ModDir>,
|
||||
cfg_options: &'a CfgOptions,
|
||||
cfg_options: &'db CfgOptions,
|
||||
/// List of procedural macros defined by this crate. This is read from the dynamic library
|
||||
/// built by the build system, and is the list of proc-macros we can actually expand. It is
|
||||
/// empty when proc-macro support is disabled (in which case we still do name resolution for
|
||||
|
|
@ -244,10 +244,10 @@ struct DefCollector<'a> {
|
|||
/// This also stores the attributes to skip when we resolve derive helpers and non-macro
|
||||
/// non-builtin attributes in general.
|
||||
// FIXME: There has to be a better way to do this
|
||||
skip_attrs: FxHashMap<InFile<ModItem>, AttrId>,
|
||||
skip_attrs: FxHashMap<InFile<FileAstId<ast::Item>>, AttrId>,
|
||||
}
|
||||
|
||||
impl DefCollector<'_> {
|
||||
impl<'db> DefCollector<'db> {
|
||||
fn seed_with_top_level(&mut self) {
|
||||
let _p = tracing::info_span!("seed_with_top_level").entered();
|
||||
|
||||
|
|
@ -355,7 +355,7 @@ impl DefCollector<'_> {
|
|||
macro_depth: 0,
|
||||
module_id: DefMap::ROOT,
|
||||
tree_id: TreeId::new(file_id.into(), None),
|
||||
item_tree: &item_tree,
|
||||
item_tree,
|
||||
mod_dir: ModDir::root(),
|
||||
}
|
||||
.collect_in_top_module(item_tree.top_level_items());
|
||||
|
|
@ -376,7 +376,7 @@ impl DefCollector<'_> {
|
|||
macro_depth: 0,
|
||||
module_id: DefMap::ROOT,
|
||||
tree_id,
|
||||
item_tree: &item_tree,
|
||||
item_tree,
|
||||
mod_dir: ModDir::root(),
|
||||
}
|
||||
.collect_in_top_module(item_tree.top_level_items());
|
||||
|
|
@ -459,7 +459,7 @@ impl DefCollector<'_> {
|
|||
self.unresolved_macros.iter().enumerate().find_map(|(idx, directive)| match &directive
|
||||
.kind
|
||||
{
|
||||
MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } => {
|
||||
MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree, item_tree } => {
|
||||
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
|
||||
directive.module_id,
|
||||
MacroCallKind::Attr {
|
||||
|
|
@ -470,16 +470,22 @@ impl DefCollector<'_> {
|
|||
attr.path().clone(),
|
||||
));
|
||||
|
||||
self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
|
||||
self.skip_attrs.insert(ast_id.ast_id.with_value(mod_item.ast_id()), attr.id);
|
||||
|
||||
Some((idx, directive, *mod_item, *tree))
|
||||
Some((idx, directive, *mod_item, *tree, *item_tree))
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
match unresolved_attr {
|
||||
Some((pos, &MacroDirective { module_id, depth, container, .. }, mod_item, tree_id)) => {
|
||||
let item_tree = &tree_id.item_tree(self.db);
|
||||
Some((
|
||||
pos,
|
||||
&MacroDirective { module_id, depth, container, .. },
|
||||
mod_item,
|
||||
tree_id,
|
||||
item_tree,
|
||||
)) => {
|
||||
// FIXME: Remove this clone
|
||||
let mod_dir = self.mod_dirs[&module_id].clone();
|
||||
ModCollector {
|
||||
def_collector: self,
|
||||
|
|
@ -860,7 +866,6 @@ impl DefCollector<'_> {
|
|||
kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly),
|
||||
id,
|
||||
use_tree,
|
||||
item_tree_id,
|
||||
..
|
||||
} => {
|
||||
let name = match &import.alias {
|
||||
|
|
@ -893,13 +898,11 @@ impl DefCollector<'_> {
|
|||
let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else {
|
||||
return false;
|
||||
};
|
||||
let item_tree = item_tree_id.item_tree(self.db);
|
||||
let use_kind = item_tree[item_tree_id.value].use_tree.kind();
|
||||
let UseTreeKind::Single { path, .. } = use_kind else {
|
||||
if kind == ImportKind::Glob {
|
||||
return false;
|
||||
};
|
||||
matches!(path.kind, PathKind::Plain | PathKind::SELF)
|
||||
&& path.segments().len() < 2
|
||||
}
|
||||
matches!(import.path.kind, PathKind::Plain | PathKind::SELF)
|
||||
&& import.path.segments().len() < 2
|
||||
};
|
||||
if is_extern_crate_reimport_without_prefix() {
|
||||
def.vis = vis;
|
||||
|
|
@ -1253,7 +1256,7 @@ impl DefCollector<'_> {
|
|||
fn resolve_macros(&mut self) -> ReachedFixedPoint {
|
||||
let mut macros = mem::take(&mut self.unresolved_macros);
|
||||
let mut resolved = Vec::new();
|
||||
let mut push_resolved = |directive: &MacroDirective, call_id| {
|
||||
let mut push_resolved = |directive: &MacroDirective<'_>, call_id| {
|
||||
resolved.push((directive.module_id, directive.depth, directive.container, call_id));
|
||||
};
|
||||
|
||||
|
|
@ -1266,7 +1269,7 @@ impl DefCollector<'_> {
|
|||
let mut eager_callback_buffer = vec![];
|
||||
let mut res = ReachedFixedPoint::Yes;
|
||||
// Retain unresolved macros after this round of resolution.
|
||||
let mut retain = |directive: &MacroDirective| {
|
||||
let mut retain = |directive: &MacroDirective<'db>| {
|
||||
let subns = match &directive.kind {
|
||||
MacroDirectiveKind::FnLike { .. } => MacroSubNs::Bang,
|
||||
MacroDirectiveKind::Attr { .. } | MacroDirectiveKind::Derive { .. } => {
|
||||
|
|
@ -1361,22 +1364,29 @@ impl DefCollector<'_> {
|
|||
return Resolved::Yes;
|
||||
}
|
||||
}
|
||||
MacroDirectiveKind::Attr { ast_id: file_ast_id, mod_item, attr, tree } => {
|
||||
MacroDirectiveKind::Attr {
|
||||
ast_id: file_ast_id,
|
||||
mod_item,
|
||||
attr,
|
||||
tree,
|
||||
item_tree,
|
||||
} => {
|
||||
let &AstIdWithPath { ast_id, ref path } = file_ast_id;
|
||||
let file_id = ast_id.file_id;
|
||||
|
||||
let mut recollect_without = |collector: &mut Self| {
|
||||
// Remove the original directive since we resolved it.
|
||||
let mod_dir = collector.mod_dirs[&directive.module_id].clone();
|
||||
collector.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
|
||||
collector
|
||||
.skip_attrs
|
||||
.insert(InFile::new(file_id, mod_item.ast_id()), attr.id);
|
||||
|
||||
let item_tree = tree.item_tree(self.db);
|
||||
ModCollector {
|
||||
def_collector: collector,
|
||||
macro_depth: directive.depth,
|
||||
module_id: directive.module_id,
|
||||
tree_id: *tree,
|
||||
item_tree: &item_tree,
|
||||
item_tree,
|
||||
mod_dir,
|
||||
}
|
||||
.collect(&[*mod_item], directive.container);
|
||||
|
|
@ -1429,11 +1439,10 @@ impl DefCollector<'_> {
|
|||
// normal (as that would just be an identity expansion with extra output)
|
||||
// Instead we treat derive attributes special and apply them separately.
|
||||
|
||||
let item_tree = tree.item_tree(self.db);
|
||||
let ast_adt_id: FileAstId<ast::Adt> = match *mod_item {
|
||||
ModItem::Struct(strukt) => item_tree[strukt].ast_id().upcast(),
|
||||
ModItem::Union(union) => item_tree[union].ast_id().upcast(),
|
||||
ModItem::Enum(enum_) => item_tree[enum_].ast_id().upcast(),
|
||||
ModItemId::Struct(ast_id) => ast_id.upcast(),
|
||||
ModItemId::Union(ast_id) => ast_id.upcast(),
|
||||
ModItemId::Enum(ast_id) => ast_id.upcast(),
|
||||
_ => {
|
||||
let diag = DefDiagnostic::invalid_derive_target(
|
||||
directive.module_id,
|
||||
|
|
@ -1565,7 +1574,7 @@ impl DefCollector<'_> {
|
|||
macro_depth: depth,
|
||||
tree_id: TreeId::new(file_id, None),
|
||||
module_id,
|
||||
item_tree: &item_tree,
|
||||
item_tree,
|
||||
mod_dir,
|
||||
}
|
||||
.collect(item_tree.top_level_items(), container);
|
||||
|
|
@ -1642,8 +1651,7 @@ impl DefCollector<'_> {
|
|||
import:
|
||||
Import {
|
||||
ref path,
|
||||
source:
|
||||
ImportSource { use_tree, id, is_prelude: _, kind: _, item_tree_id: _ },
|
||||
source: ImportSource { use_tree, id, is_prelude: _, kind: _ },
|
||||
..
|
||||
},
|
||||
..
|
||||
|
|
@ -1667,22 +1675,22 @@ impl DefCollector<'_> {
|
|||
}
|
||||
|
||||
/// Walks a single module, populating defs, imports and macros
|
||||
struct ModCollector<'a, 'b> {
|
||||
def_collector: &'a mut DefCollector<'b>,
|
||||
struct ModCollector<'a, 'db> {
|
||||
def_collector: &'a mut DefCollector<'db>,
|
||||
macro_depth: usize,
|
||||
module_id: LocalModuleId,
|
||||
tree_id: TreeId,
|
||||
item_tree: &'a ItemTree,
|
||||
item_tree: &'db ItemTree,
|
||||
mod_dir: ModDir,
|
||||
}
|
||||
|
||||
impl ModCollector<'_, '_> {
|
||||
fn collect_in_top_module(&mut self, items: &[ModItem]) {
|
||||
fn collect_in_top_module(&mut self, items: &[ModItemId]) {
|
||||
let module = self.def_collector.def_map.module_id(self.module_id);
|
||||
self.collect(items, module.into())
|
||||
}
|
||||
|
||||
fn collect(&mut self, items: &[ModItem], container: ItemContainerId) {
|
||||
fn collect(&mut self, items: &[ModItemId], container: ItemContainerId) {
|
||||
let krate = self.def_collector.def_map.krate;
|
||||
let is_crate_root =
|
||||
self.module_id == DefMap::ROOT && self.def_collector.def_map.block.is_none();
|
||||
|
|
@ -1721,29 +1729,11 @@ impl ModCollector<'_, '_> {
|
|||
.unwrap_or(Visibility::Public)
|
||||
};
|
||||
|
||||
let mut process_mod_item = |item: ModItem| {
|
||||
let attrs = self.item_tree.attrs(db, krate, item.into());
|
||||
let mut process_mod_item = |item: ModItemId| {
|
||||
let attrs = self.item_tree.attrs(db, krate, item.ast_id());
|
||||
if let Some(cfg) = attrs.cfg() {
|
||||
if !self.is_cfg_enabled(&cfg) {
|
||||
let ast_id = match item {
|
||||
ModItem::Use(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::ExternCrate(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::ExternBlock(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::Function(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::Struct(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::Union(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::Enum(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::Const(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::Static(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::Trait(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::TraitAlias(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::Impl(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::TypeAlias(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::Mod(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::MacroCall(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::MacroRules(it) => self.item_tree[it].ast_id.erase(),
|
||||
ModItem::Macro2(it) => self.item_tree[it].ast_id.erase(),
|
||||
};
|
||||
let ast_id = item.ast_id().erase();
|
||||
self.emit_unconfigured_diagnostic(InFile::new(self.file_id(), ast_id), &cfg);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1761,35 +1751,27 @@ impl ModCollector<'_, '_> {
|
|||
self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map);
|
||||
|
||||
match item {
|
||||
ModItem::Mod(m) => self.collect_module(m, &attrs),
|
||||
ModItem::Use(item_tree_id) => {
|
||||
let id = UseLoc {
|
||||
container: module,
|
||||
id: InFile::new(self.file_id(), self.item_tree[item_tree_id].ast_id),
|
||||
}
|
||||
.intern(db);
|
||||
ModItemId::Mod(m) => self.collect_module(m, &attrs),
|
||||
ModItemId::Use(item_tree_id) => {
|
||||
let id =
|
||||
UseLoc { container: module, id: InFile::new(self.file_id(), item_tree_id) }
|
||||
.intern(db);
|
||||
let is_prelude = attrs.by_key(sym::prelude_import).exists();
|
||||
Import::from_use(
|
||||
self.item_tree,
|
||||
ItemTreeId::new(self.tree_id, item_tree_id),
|
||||
id,
|
||||
is_prelude,
|
||||
|import| {
|
||||
self.def_collector.unresolved_imports.push(ImportDirective {
|
||||
module_id: self.module_id,
|
||||
import,
|
||||
status: PartialResolvedImport::Unresolved,
|
||||
});
|
||||
},
|
||||
)
|
||||
Import::from_use(self.item_tree, item_tree_id, id, is_prelude, |import| {
|
||||
self.def_collector.unresolved_imports.push(ImportDirective {
|
||||
module_id: self.module_id,
|
||||
import,
|
||||
status: PartialResolvedImport::Unresolved,
|
||||
});
|
||||
})
|
||||
}
|
||||
ModItem::ExternCrate(item_tree_id) => {
|
||||
let item_tree::ExternCrate { name, visibility, alias, ast_id } =
|
||||
ModItemId::ExternCrate(item_tree_id) => {
|
||||
let item_tree::ExternCrate { name, visibility, alias } =
|
||||
&self.item_tree[item_tree_id];
|
||||
|
||||
let id = ExternCrateLoc {
|
||||
container: module,
|
||||
id: InFile::new(self.tree_id.file_id(), *ast_id),
|
||||
id: InFile::new(self.tree_id.file_id(), item_tree_id),
|
||||
}
|
||||
.intern(db);
|
||||
def_map.modules[self.module_id].scope.define_extern_crate_decl(id);
|
||||
|
|
@ -1852,15 +1834,15 @@ impl ModCollector<'_, '_> {
|
|||
self.def_collector.def_map.diagnostics.push(
|
||||
DefDiagnostic::unresolved_extern_crate(
|
||||
module_id,
|
||||
InFile::new(self.file_id(), *ast_id),
|
||||
InFile::new(self.file_id(), item_tree_id),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
ModItem::ExternBlock(block) => {
|
||||
ModItemId::ExternBlock(block) => {
|
||||
let extern_block_id = ExternBlockLoc {
|
||||
container: module,
|
||||
id: InFile::new(self.file_id(), self.item_tree[block].ast_id),
|
||||
id: InFile::new(self.file_id(), block),
|
||||
}
|
||||
.intern(db);
|
||||
self.def_collector.def_map.modules[self.module_id]
|
||||
|
|
@ -1871,24 +1853,20 @@ impl ModCollector<'_, '_> {
|
|||
ItemContainerId::ExternBlockId(extern_block_id),
|
||||
)
|
||||
}
|
||||
ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container),
|
||||
ModItem::MacroRules(id) => self.collect_macro_rules(id, module),
|
||||
ModItem::Macro2(id) => self.collect_macro_def(id, module),
|
||||
ModItem::Impl(imp) => {
|
||||
let impl_id = ImplLoc {
|
||||
container: module,
|
||||
id: InFile::new(self.file_id(), self.item_tree[imp].ast_id),
|
||||
}
|
||||
.intern(db);
|
||||
ModItemId::MacroCall(mac) => self.collect_macro_call(mac, container),
|
||||
ModItemId::MacroRules(id) => self.collect_macro_rules(id, module),
|
||||
ModItemId::Macro2(id) => self.collect_macro_def(id, module),
|
||||
ModItemId::Impl(imp) => {
|
||||
let impl_id =
|
||||
ImplLoc { container: module, id: InFile::new(self.file_id(), imp) }
|
||||
.intern(db);
|
||||
self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id)
|
||||
}
|
||||
ModItem::Function(id) => {
|
||||
ModItemId::Function(id) => {
|
||||
let it = &self.item_tree[id];
|
||||
let fn_id = FunctionLoc {
|
||||
container,
|
||||
id: InFile::new(self.tree_id.file_id(), it.ast_id),
|
||||
}
|
||||
.intern(db);
|
||||
let fn_id =
|
||||
FunctionLoc { container, id: InFile::new(self.tree_id.file_id(), id) }
|
||||
.intern(db);
|
||||
|
||||
let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
|
||||
|
||||
|
|
@ -1899,7 +1877,7 @@ impl ModCollector<'_, '_> {
|
|||
if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) {
|
||||
self.def_collector.export_proc_macro(
|
||||
proc_macro,
|
||||
InFile::new(self.file_id(), self.item_tree[id].ast_id()),
|
||||
InFile::new(self.file_id(), id),
|
||||
fn_id,
|
||||
);
|
||||
}
|
||||
|
|
@ -1907,13 +1885,13 @@ impl ModCollector<'_, '_> {
|
|||
|
||||
update_def(self.def_collector, fn_id.into(), &it.name, vis, false);
|
||||
}
|
||||
ModItem::Struct(id) => {
|
||||
ModItemId::Struct(id) => {
|
||||
let it = &self.item_tree[id];
|
||||
|
||||
let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
|
||||
update_def(
|
||||
self.def_collector,
|
||||
StructLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) }
|
||||
StructLoc { container: module, id: InFile::new(self.file_id(), id) }
|
||||
.intern(db)
|
||||
.into(),
|
||||
&it.name,
|
||||
|
|
@ -1921,13 +1899,13 @@ impl ModCollector<'_, '_> {
|
|||
!matches!(it.shape, FieldsShape::Record),
|
||||
);
|
||||
}
|
||||
ModItem::Union(id) => {
|
||||
ModItemId::Union(id) => {
|
||||
let it = &self.item_tree[id];
|
||||
|
||||
let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
|
||||
update_def(
|
||||
self.def_collector,
|
||||
UnionLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) }
|
||||
UnionLoc { container: module, id: InFile::new(self.file_id(), id) }
|
||||
.intern(db)
|
||||
.into(),
|
||||
&it.name,
|
||||
|
|
@ -1935,21 +1913,19 @@ impl ModCollector<'_, '_> {
|
|||
false,
|
||||
);
|
||||
}
|
||||
ModItem::Enum(id) => {
|
||||
ModItemId::Enum(id) => {
|
||||
let it = &self.item_tree[id];
|
||||
let enum_ = EnumLoc {
|
||||
container: module,
|
||||
id: InFile::new(self.tree_id.file_id(), it.ast_id),
|
||||
}
|
||||
.intern(db);
|
||||
let enum_ =
|
||||
EnumLoc { container: module, id: InFile::new(self.tree_id.file_id(), id) }
|
||||
.intern(db);
|
||||
|
||||
let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
|
||||
update_def(self.def_collector, enum_.into(), &it.name, vis, false);
|
||||
}
|
||||
ModItem::Const(id) => {
|
||||
ModItemId::Const(id) => {
|
||||
let it = &self.item_tree[id];
|
||||
let const_id =
|
||||
ConstLoc { container, id: InFile::new(self.tree_id.file_id(), it.ast_id) }
|
||||
ConstLoc { container, id: InFile::new(self.tree_id.file_id(), id) }
|
||||
.intern(db);
|
||||
|
||||
match &it.name {
|
||||
|
|
@ -1966,13 +1942,13 @@ impl ModCollector<'_, '_> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ModItem::Static(id) => {
|
||||
ModItemId::Static(id) => {
|
||||
let it = &self.item_tree[id];
|
||||
|
||||
let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
|
||||
update_def(
|
||||
self.def_collector,
|
||||
StaticLoc { container, id: InFile::new(self.file_id(), it.ast_id) }
|
||||
StaticLoc { container, id: InFile::new(self.file_id(), id) }
|
||||
.intern(db)
|
||||
.into(),
|
||||
&it.name,
|
||||
|
|
@ -1980,13 +1956,13 @@ impl ModCollector<'_, '_> {
|
|||
false,
|
||||
);
|
||||
}
|
||||
ModItem::Trait(id) => {
|
||||
ModItemId::Trait(id) => {
|
||||
let it = &self.item_tree[id];
|
||||
|
||||
let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
|
||||
update_def(
|
||||
self.def_collector,
|
||||
TraitLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) }
|
||||
TraitLoc { container: module, id: InFile::new(self.file_id(), id) }
|
||||
.intern(db)
|
||||
.into(),
|
||||
&it.name,
|
||||
|
|
@ -1994,30 +1970,27 @@ impl ModCollector<'_, '_> {
|
|||
false,
|
||||
);
|
||||
}
|
||||
ModItem::TraitAlias(id) => {
|
||||
ModItemId::TraitAlias(id) => {
|
||||
let it = &self.item_tree[id];
|
||||
|
||||
let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
|
||||
update_def(
|
||||
self.def_collector,
|
||||
TraitAliasLoc {
|
||||
container: module,
|
||||
id: InFile::new(self.file_id(), it.ast_id),
|
||||
}
|
||||
.intern(db)
|
||||
.into(),
|
||||
TraitAliasLoc { container: module, id: InFile::new(self.file_id(), id) }
|
||||
.intern(db)
|
||||
.into(),
|
||||
&it.name,
|
||||
vis,
|
||||
false,
|
||||
);
|
||||
}
|
||||
ModItem::TypeAlias(id) => {
|
||||
ModItemId::TypeAlias(id) => {
|
||||
let it = &self.item_tree[id];
|
||||
|
||||
let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
|
||||
update_def(
|
||||
self.def_collector,
|
||||
TypeAliasLoc { container, id: InFile::new(self.file_id(), it.ast_id) }
|
||||
TypeAliasLoc { container, id: InFile::new(self.file_id(), id) }
|
||||
.intern(db)
|
||||
.into(),
|
||||
&it.name,
|
||||
|
|
@ -2034,12 +2007,12 @@ impl ModCollector<'_, '_> {
|
|||
if is_crate_root {
|
||||
items
|
||||
.iter()
|
||||
.filter(|it| matches!(it, ModItem::ExternCrate(..)))
|
||||
.filter(|it| matches!(it, ModItemId::ExternCrate(..)))
|
||||
.copied()
|
||||
.for_each(&mut process_mod_item);
|
||||
items
|
||||
.iter()
|
||||
.filter(|it| !matches!(it, ModItem::ExternCrate(..)))
|
||||
.filter(|it| !matches!(it, ModItemId::ExternCrate(..)))
|
||||
.copied()
|
||||
.for_each(process_mod_item);
|
||||
} else {
|
||||
|
|
@ -2080,19 +2053,18 @@ impl ModCollector<'_, '_> {
|
|||
);
|
||||
}
|
||||
|
||||
fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
|
||||
fn collect_module(&mut self, module_ast_id: ItemTreeAstId<Mod>, attrs: &Attrs) {
|
||||
let path_attr = attrs.by_key(sym::path).string_value_unescape();
|
||||
let is_macro_use = attrs.by_key(sym::macro_use).exists();
|
||||
let module = &self.item_tree[module_id];
|
||||
let module = &self.item_tree[module_ast_id];
|
||||
match &module.kind {
|
||||
// inline module, just recurse
|
||||
ModKind::Inline { items } => {
|
||||
let module_id = self.push_child_module(
|
||||
module.name.clone(),
|
||||
module.ast_id,
|
||||
module_ast_id,
|
||||
None,
|
||||
&self.item_tree[module.visibility],
|
||||
module_id,
|
||||
);
|
||||
|
||||
let Some(mod_dir) =
|
||||
|
|
@ -2115,7 +2087,7 @@ impl ModCollector<'_, '_> {
|
|||
}
|
||||
// out of line module, resolve, parse and recurse
|
||||
ModKind::Outline => {
|
||||
let ast_id = AstId::new(self.file_id(), module.ast_id);
|
||||
let ast_id = AstId::new(self.file_id(), module_ast_id);
|
||||
let db = self.def_collector.db;
|
||||
match self.mod_dir.resolve_declaration(
|
||||
db,
|
||||
|
|
@ -2134,10 +2106,7 @@ impl ModCollector<'_, '_> {
|
|||
match is_enabled {
|
||||
Err(cfg) => {
|
||||
self.emit_unconfigured_diagnostic(
|
||||
InFile::new(
|
||||
self.file_id(),
|
||||
self.item_tree[module_id].ast_id.erase(),
|
||||
),
|
||||
InFile::new(self.file_id(), module_ast_id.erase()),
|
||||
&cfg,
|
||||
);
|
||||
}
|
||||
|
|
@ -2147,14 +2116,13 @@ impl ModCollector<'_, '_> {
|
|||
ast_id.value,
|
||||
Some((file_id, is_mod_rs)),
|
||||
&self.item_tree[module.visibility],
|
||||
module_id,
|
||||
);
|
||||
ModCollector {
|
||||
def_collector: self.def_collector,
|
||||
macro_depth: self.macro_depth,
|
||||
module_id,
|
||||
tree_id: TreeId::new(file_id.into(), None),
|
||||
item_tree: &item_tree,
|
||||
item_tree,
|
||||
mod_dir,
|
||||
}
|
||||
.collect_in_top_module(item_tree.top_level_items());
|
||||
|
|
@ -2175,7 +2143,6 @@ impl ModCollector<'_, '_> {
|
|||
ast_id.value,
|
||||
None,
|
||||
&self.item_tree[module.visibility],
|
||||
module_id,
|
||||
);
|
||||
self.def_collector.def_map.diagnostics.push(
|
||||
DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates),
|
||||
|
|
@ -2192,7 +2159,6 @@ impl ModCollector<'_, '_> {
|
|||
declaration: FileAstId<ast::Module>,
|
||||
definition: Option<(EditionedFileId, bool)>,
|
||||
visibility: &crate::visibility::RawVisibility,
|
||||
mod_tree_id: FileItemTreeId<Mod>,
|
||||
) -> LocalModuleId {
|
||||
let def_map = &mut self.def_collector.def_map;
|
||||
let vis = def_map
|
||||
|
|
@ -2205,15 +2171,14 @@ impl ModCollector<'_, '_> {
|
|||
)
|
||||
.unwrap_or(Visibility::Public);
|
||||
let origin = match definition {
|
||||
None => ModuleOrigin::Inline {
|
||||
definition: declaration,
|
||||
definition_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id),
|
||||
},
|
||||
None => {
|
||||
ModuleOrigin::Inline { definition: declaration, definition_tree_id: self.tree_id }
|
||||
}
|
||||
Some((definition, is_mod_rs)) => ModuleOrigin::File {
|
||||
declaration,
|
||||
definition,
|
||||
is_mod_rs,
|
||||
declaration_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id),
|
||||
declaration_tree_id: self.tree_id,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -2254,11 +2219,14 @@ impl ModCollector<'_, '_> {
|
|||
fn resolve_attributes(
|
||||
&mut self,
|
||||
attrs: &Attrs,
|
||||
mod_item: ModItem,
|
||||
mod_item: ModItemId,
|
||||
container: ItemContainerId,
|
||||
) -> Result<(), ()> {
|
||||
let mut ignore_up_to =
|
||||
self.def_collector.skip_attrs.get(&InFile::new(self.file_id(), mod_item)).copied();
|
||||
let mut ignore_up_to = self
|
||||
.def_collector
|
||||
.skip_attrs
|
||||
.get(&InFile::new(self.file_id(), mod_item.ast_id()))
|
||||
.copied();
|
||||
let iter = attrs
|
||||
.iter()
|
||||
.dedup_by(|a, b| {
|
||||
|
|
@ -2288,11 +2256,7 @@ impl ModCollector<'_, '_> {
|
|||
attr.path.display(self.def_collector.db, Edition::LATEST)
|
||||
);
|
||||
|
||||
let ast_id = AstIdWithPath::new(
|
||||
self.file_id(),
|
||||
mod_item.ast_id(self.item_tree),
|
||||
attr.path.clone(),
|
||||
);
|
||||
let ast_id = AstIdWithPath::new(self.file_id(), mod_item.ast_id(), attr.path.clone());
|
||||
self.def_collector.unresolved_macros.push(MacroDirective {
|
||||
module_id: self.module_id,
|
||||
depth: self.macro_depth + 1,
|
||||
|
|
@ -2301,6 +2265,7 @@ impl ModCollector<'_, '_> {
|
|||
attr: attr.clone(),
|
||||
mod_item,
|
||||
tree: self.tree_id,
|
||||
item_tree: self.item_tree,
|
||||
},
|
||||
container,
|
||||
});
|
||||
|
|
@ -2311,11 +2276,11 @@ impl ModCollector<'_, '_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>, module: ModuleId) {
|
||||
fn collect_macro_rules(&mut self, ast_id: ItemTreeAstId<MacroRules>, module: ModuleId) {
|
||||
let krate = self.def_collector.def_map.krate;
|
||||
let mac = &self.item_tree[id];
|
||||
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
|
||||
let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
|
||||
let mac = &self.item_tree[ast_id];
|
||||
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ast_id.upcast());
|
||||
let f_ast_id = InFile::new(self.file_id(), ast_id.upcast());
|
||||
|
||||
let export_attr = || attrs.by_key(sym::macro_export);
|
||||
|
||||
|
|
@ -2362,7 +2327,7 @@ impl ModCollector<'_, '_> {
|
|||
self.def_collector
|
||||
.def_map
|
||||
.diagnostics
|
||||
.push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
|
||||
.push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -2378,16 +2343,13 @@ impl ModCollector<'_, '_> {
|
|||
|
||||
let macro_id = MacroRulesLoc {
|
||||
container: module,
|
||||
id: InFile::new(self.file_id(), mac.ast_id),
|
||||
id: InFile::new(self.file_id(), ast_id),
|
||||
flags,
|
||||
expander,
|
||||
edition: self.def_collector.def_map.data.edition,
|
||||
}
|
||||
.intern(self.def_collector.db);
|
||||
self.def_collector.def_map.macro_def_to_macro_id.insert(
|
||||
InFile::new(self.file_id(), self.item_tree[id].ast_id()).erase(),
|
||||
macro_id.into(),
|
||||
);
|
||||
self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into());
|
||||
self.def_collector.define_macro_rules(
|
||||
self.module_id,
|
||||
mac.name.clone(),
|
||||
|
|
@ -2396,14 +2358,14 @@ impl ModCollector<'_, '_> {
|
|||
);
|
||||
}
|
||||
|
||||
fn collect_macro_def(&mut self, id: FileItemTreeId<Macro2>, module: ModuleId) {
|
||||
fn collect_macro_def(&mut self, ast_id: ItemTreeAstId<Macro2>, module: ModuleId) {
|
||||
let krate = self.def_collector.def_map.krate;
|
||||
let mac = &self.item_tree[id];
|
||||
let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
|
||||
let mac = &self.item_tree[ast_id];
|
||||
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ast_id.upcast());
|
||||
let f_ast_id = InFile::new(self.file_id(), ast_id.upcast());
|
||||
|
||||
// Case 1: builtin macros
|
||||
let mut helpers_opt = None;
|
||||
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
|
||||
let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() {
|
||||
if let Some(expander) = find_builtin_macro(&mac.name) {
|
||||
match expander {
|
||||
|
|
@ -2435,7 +2397,7 @@ impl ModCollector<'_, '_> {
|
|||
self.def_collector
|
||||
.def_map
|
||||
.diagnostics
|
||||
.push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
|
||||
.push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -2446,16 +2408,13 @@ impl ModCollector<'_, '_> {
|
|||
|
||||
let macro_id = Macro2Loc {
|
||||
container: module,
|
||||
id: InFile::new(self.file_id(), mac.ast_id),
|
||||
id: InFile::new(self.file_id(), ast_id),
|
||||
expander,
|
||||
allow_internal_unsafe,
|
||||
edition: self.def_collector.def_map.data.edition,
|
||||
}
|
||||
.intern(self.def_collector.db);
|
||||
self.def_collector.def_map.macro_def_to_macro_id.insert(
|
||||
InFile::new(self.file_id(), self.item_tree[id].ast_id()).erase(),
|
||||
macro_id.into(),
|
||||
);
|
||||
self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into());
|
||||
self.def_collector.define_macro_def(
|
||||
self.module_id,
|
||||
mac.name.clone(),
|
||||
|
|
@ -2474,9 +2433,10 @@ impl ModCollector<'_, '_> {
|
|||
|
||||
fn collect_macro_call(
|
||||
&mut self,
|
||||
&MacroCall { ref path, ast_id, expand_to, ctxt }: &MacroCall,
|
||||
ast_id: FileAstId<ast::MacroCall>,
|
||||
container: ItemContainerId,
|
||||
) {
|
||||
let &MacroCall { ref path, expand_to, ctxt } = &self.item_tree[ast_id];
|
||||
let ast_id = AstIdWithPath::new(self.file_id(), ast_id, path.clone());
|
||||
let db = self.def_collector.db;
|
||||
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ m!(Z);
|
|||
assert_eq!(module_data.scope.resolutions().count(), 4);
|
||||
});
|
||||
let n_recalculated_item_trees =
|
||||
events.iter().filter(|it| it.contains("file_item_tree_shim")).count();
|
||||
events.iter().filter(|it| it.contains("file_item_tree_query")).count();
|
||||
assert_eq!(n_recalculated_item_trees, 6);
|
||||
let n_reparsed_macros =
|
||||
events.iter().filter(|it| it.contains("parse_macro_expansion_shim")).count();
|
||||
|
|
@ -370,7 +370,7 @@ m!(Z);
|
|||
assert_eq!(module_data.scope.resolutions().count(), 4);
|
||||
});
|
||||
let n_recalculated_item_trees =
|
||||
events.iter().filter(|it| it.contains("file_item_tree_shim")).count();
|
||||
events.iter().filter(|it| it.contains("file_item_tree_query")).count();
|
||||
assert_eq!(n_recalculated_item_trees, 1, "{events:#?}");
|
||||
let n_reparsed_macros =
|
||||
events.iter().filter(|it| it.contains("parse_macro_expansion_shim")).count();
|
||||
|
|
@ -405,10 +405,10 @@ pub type Ty = ();
|
|||
db.file_item_tree(pos.file_id.into());
|
||||
});
|
||||
let n_calculated_item_trees =
|
||||
events.iter().filter(|it| it.contains("file_item_tree_shim")).count();
|
||||
assert_eq!(n_calculated_item_trees, 1);
|
||||
events.iter().filter(|it| it.contains("file_item_tree_query")).count();
|
||||
assert_eq!(n_calculated_item_trees, 1, "{events:#?}");
|
||||
let n_parsed_files = events.iter().filter(|it| it.contains("parse")).count();
|
||||
assert_eq!(n_parsed_files, 1);
|
||||
assert_eq!(n_parsed_files, 1, "{events:#?}");
|
||||
}
|
||||
|
||||
// FIXME(salsa-transition): bring this back
|
||||
|
|
@ -446,6 +446,6 @@ pub type Ty = ();
|
|||
}
|
||||
});
|
||||
let n_reparsed_files = events.iter().filter(|it| it.contains("parse(")).count();
|
||||
assert_eq!(n_reparsed_files, 0);
|
||||
assert_eq!(n_reparsed_files, 0, "{events:?}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ pub struct NewStruct {
|
|||
let expected = vec![
|
||||
"parse_shim".to_owned(),
|
||||
"ast_id_map_shim".to_owned(),
|
||||
"file_item_tree_shim".to_owned(),
|
||||
"file_item_tree_query".to_owned(),
|
||||
"real_span_map_shim".to_owned(),
|
||||
"crate_local_def_map".to_owned(),
|
||||
"trait_impls_in_crate_shim".to_owned(),
|
||||
|
|
@ -216,7 +216,7 @@ pub enum SomeEnum {
|
|||
let expected = vec![
|
||||
"parse_shim".to_owned(),
|
||||
"ast_id_map_shim".to_owned(),
|
||||
"file_item_tree_shim".to_owned(),
|
||||
"file_item_tree_query".to_owned(),
|
||||
"real_span_map_shim".to_owned(),
|
||||
"crate_local_def_map".to_owned(),
|
||||
"trait_impls_in_crate_shim".to_owned(),
|
||||
|
|
@ -273,7 +273,7 @@ fn bar() -> f32 {
|
|||
let expected = vec![
|
||||
"parse_shim".to_owned(),
|
||||
"ast_id_map_shim".to_owned(),
|
||||
"file_item_tree_shim".to_owned(),
|
||||
"file_item_tree_query".to_owned(),
|
||||
"real_span_map_shim".to_owned(),
|
||||
"crate_local_def_map".to_owned(),
|
||||
"trait_impls_in_crate_shim".to_owned(),
|
||||
|
|
@ -342,7 +342,7 @@ impl SomeStruct {
|
|||
let expected = vec![
|
||||
"parse_shim".to_owned(),
|
||||
"ast_id_map_shim".to_owned(),
|
||||
"file_item_tree_shim".to_owned(),
|
||||
"file_item_tree_query".to_owned(),
|
||||
"real_span_map_shim".to_owned(),
|
||||
"crate_local_def_map".to_owned(),
|
||||
"trait_impls_in_crate_shim".to_owned(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue