diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index 86c15f4ee09..adfec56d852 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs @@ -91,6 +91,7 @@ salsa::database_storage! { fn library_symbols() for symbol_index::LibrarySymbolsQuery; } impl hir::db::HirDatabase { + fn m_source_file() for hir::db::MSourceFileQuery; fn expand_macro_invocation() for hir::db::ExpandMacroCallQuery; fn module_tree() for hir::db::ModuleTreeQuery; fn fn_scopes() for hir::db::FnScopesQuery; diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 3c90e29fe0f..3b73208e6e0 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs @@ -12,6 +12,7 @@ use ra_db::{SourceRootId, FileId, Cancelable,}; use crate::{ SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName, MFileId, + macros::MacroCallLoc, db::HirDatabase, function::FnScopes, module::{ @@ -123,25 +124,48 @@ pub(crate) fn modules<'a>( pub(super) fn input_module_items( db: &impl HirDatabase, - source_root: SourceRootId, + source_root_id: SourceRootId, module_id: ModuleId, ) -> Cancelable> { - let module_tree = db.module_tree(source_root)?; + let module_tree = db.module_tree(source_root_id)?; let source = module_id.source(&module_tree); let mfile_id = source.file_id().into(); let file_items = db.file_items(mfile_id); - let res = match source.resolve(db) { - ModuleSourceNode::SourceFile(it) => { - let items = it.borrowed().items(); - InputModuleItems::new(mfile_id, &file_items, items) + let fill = |acc: &mut InputModuleItems, items: &mut Iterator| { + for item in items { + match item { + ast::ItemOrMacro::Item(it) => { + acc.add_item(mfile_id, &file_items, it); + } + ast::ItemOrMacro::Macro(macro_call) => { + let item_id = file_items.id_of_unchecked(macro_call.syntax()); + let loc = MacroCallLoc { + source_root_id, + module_id, + source_item_id: SourceItemId { + mfile_id, + item_id: Some(item_id), + }, + }; + let id = loc.id(db); + let mfile_id = MFileId::Macro(id); + let file_items = db.file_items(mfile_id); + //FIXME: expand recursively + for item in db.m_source_file(mfile_id).borrowed().items() { + acc.add_item(mfile_id, &file_items, item); + } + } + } } + }; + + let mut res = InputModuleItems::default(); + match source.resolve(db) { + ModuleSourceNode::SourceFile(it) => fill(&mut res, &mut it.borrowed().items_with_macros()), ModuleSourceNode::Module(it) => { - let items = it - .borrowed() - .item_list() - .into_iter() - .flat_map(|it| it.items()); - InputModuleItems::new(mfile_id, &file_items, items) + if let Some(item_list) = it.borrowed().item_list() { + fill(&mut res, &mut item_list.items_with_macros()) + } } }; Ok(Arc::new(res)) diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 8fb6b64083f..3e948800ede 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -48,10 +48,40 @@ pub trait FnDefOwner<'a>: AstNode<'a> { } } +// ModuleItem +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ItemOrMacro<'a> { + Item(ModuleItem<'a>), + Macro(MacroCall<'a>), +} + +impl<'a> AstNode<'a> for ItemOrMacro<'a> { + fn cast(syntax: SyntaxNodeRef<'a>) -> Option { + let res = if let Some(item) = ModuleItem::cast(syntax) { + ItemOrMacro::Item(item) + } else if let Some(macro_call) = MacroCall::cast(syntax) { + ItemOrMacro::Macro(macro_call) + } else { + return None; + }; + Some(res) + } + fn syntax(self) -> SyntaxNodeRef<'a> { + match self { + ItemOrMacro::Item(it) => it.syntax(), + ItemOrMacro::Macro(it) => it.syntax(), + } + } +} + pub trait ModuleItemOwner<'a>: AstNode<'a> { fn items(self) -> AstChildren<'a, ModuleItem<'a>> { children(self) } + + fn items_with_macros(self) -> AstChildren<'a, ItemOrMacro<'a>> { + children(self) + } } pub trait TypeParamsOwner<'a>: AstNode<'a> {