diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 289bec5070c..1da3fc1c199 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -1,10 +1,10 @@ use std::sync::Arc; -use ra_syntax::SyntaxNode; +use ra_syntax::{SyntaxNode, SourceFileNode}; use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable}; use crate::{ - DefLoc, DefId, Name, + DefLoc, DefId, Name, MFileId, SourceFileItems, SourceItemId, query_definitions, FnScopes, @@ -21,6 +21,10 @@ pub trait HirDatabase: SyntaxDatabase + AsRef> + AsRef> { + fn m_source_file(mfile_id: MFileId) -> SourceFileNode { + type MSourceFileQuery; + use fn crate::query_definitions::m_source_file; + } fn expand_macro_invocation(invoc: MacroCallId) -> Option> { type ExpandMacroCallQuery; use fn crate::macros::expand_macro_invocation; @@ -56,7 +60,7 @@ fn type_for_field(def_id: DefId, field: Name) -> Cancelable { use fn crate::ty::type_for_field; } - fn file_items(file_id: FileId) -> Arc { + fn file_items(mfile_id: MFileId) -> Arc { type SourceFileItemsQuery; use fn query_definitions::file_items; } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 4c67921bd62..1219b9fbab1 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -57,11 +57,18 @@ macro_rules! ctry { /// An `MFileId` is like a `FileId`, but it can also refer to code generated by /// macros. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum MFileId { File(FileId), Macro(MacroCallId), } +impl From for MFileId { + fn from(file_id: FileId) -> MFileId { + MFileId::File(file_id) + } +} + /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) /// in a specific module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -163,7 +170,7 @@ pub fn module(self, db: &impl HirDatabase) -> Cancelable { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct SourceItemId { - file_id: FileId, + mfile_id: MFileId, /// None for the whole file. item_id: Option, } @@ -171,14 +178,14 @@ pub struct SourceItemId { /// Maps item's `SyntaxNode`s to `SourceFileItemId` and back. #[derive(Debug, PartialEq, Eq)] pub struct SourceFileItems { - file_id: FileId, + mfile_id: MFileId, arena: Arena, } impl SourceFileItems { - fn new(file_id: FileId, source_file: SourceFile) -> SourceFileItems { + fn new(mfile_id: MFileId, source_file: SourceFile) -> SourceFileItems { let mut res = SourceFileItems { - file_id, + mfile_id, arena: Arena::default(), }; res.init(source_file); @@ -198,11 +205,11 @@ fn init(&mut self, source_file: SourceFile) { fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId { self.arena.alloc(item) } - pub fn id_of(&self, file_id: FileId, item: SyntaxNodeRef) -> SourceFileItemId { + pub fn id_of(&self, mfile_id: MFileId, item: SyntaxNodeRef) -> SourceFileItemId { assert_eq!( - self.file_id, file_id, + self.mfile_id, mfile_id, "SourceFileItems: wrong file, expected {:?}, got {:?}", - self.file_id, file_id + self.mfile_id, mfile_id ); self.id_of_unchecked(item) } diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs index 3eedd9e2d1b..1f141dbac1f 100644 --- a/crates/ra_hir/src/macros.rs +++ b/crates/ra_hir/src/macros.rs @@ -147,7 +147,9 @@ pub struct MacroExpansion { } impl MacroExpansion { - pub fn file(&self) -> SourceFileNode { + //FIXME: does not really make sense, macro expansion is not neccessary a + //whole file. + pub(crate) fn file(&self) -> SourceFileNode { SourceFileNode::parse(&self.text) } diff --git a/crates/ra_hir/src/module.rs b/crates/ra_hir/src/module.rs index 87e30191fba..dde036f2c5f 100644 --- a/crates/ra_hir/src/module.rs +++ b/crates/ra_hir/src/module.rs @@ -15,6 +15,7 @@ use crate::{ Def, DefKind, DefLoc, DefId, Name, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId, Crate, + MFileId, arena::{Arena, Id}, }; @@ -292,7 +293,10 @@ pub struct ModuleData { impl ModuleSource { // precondition: item_id **must** point to module fn new(file_id: FileId, item_id: Option) -> ModuleSource { - let source_item_id = SourceItemId { file_id, item_id }; + let source_item_id = SourceItemId { + mfile_id: file_id.into(), + item_id, + }; ModuleSource(source_item_id) } @@ -306,13 +310,16 @@ pub(crate) fn new_inline( m: ast::Module, ) -> ModuleSource { assert!(!m.has_semi()); - let file_items = db.file_items(file_id); - let item_id = file_items.id_of(file_id, m.syntax()); + let file_items = db.file_items(file_id.into()); + let item_id = file_items.id_of(file_id.into(), m.syntax()); ModuleSource::new(file_id, Some(item_id)) } pub fn file_id(self) -> FileId { - self.0.file_id + match self.0.mfile_id { + MFileId::File(file_id) => file_id, + MFileId::Macro(_) => unreachable!(), + } } pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode { diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index 46b1dc0b1c3..94ada73d70f 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs @@ -98,7 +98,7 @@ pub struct NamedImport { impl NamedImport { pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange { let source_item_id = SourceItemId { - file_id, + mfile_id: file_id.into(), item_id: Some(self.file_item_id), }; let syntax = db.file_item(source_item_id); @@ -360,7 +360,7 @@ fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) -> source_root_id: self.source_root, module_id, source_item_id: SourceItemId { - file_id, + mfile_id: file_id.into(), item_id: Some(item.id), }, }; @@ -376,7 +376,7 @@ fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) -> source_root_id: self.source_root, module_id, source_item_id: SourceItemId { - file_id, + mfile_id: file_id.into(), item_id: Some(item.id), }, }; diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index f6623122230..0c07f1444ef 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs @@ -5,13 +5,13 @@ use rustc_hash::FxHashMap; use ra_syntax::{ - AstNode, SyntaxNode, + AstNode, SyntaxNode, SourceFileNode, ast::{self, NameOwner, ModuleItemOwner} }; use ra_db::{SourceRootId, FileId, Cancelable,}; use crate::{ - SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName, + SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName, MFileId, db::HirDatabase, function::FnScopes, module::{ @@ -47,17 +47,29 @@ pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable Arc { - let source_file = db.source_file(file_id); +pub(super) fn m_source_file(db: &impl HirDatabase, mfile_id: MFileId) -> SourceFileNode { + match mfile_id { + MFileId::File(file_id) => db.source_file(file_id), + MFileId::Macro(m) => { + if let Some(exp) = db.expand_macro_invocation(m) { + return exp.file(); + } + SourceFileNode::parse("") + } + } +} + +pub(super) fn file_items(db: &impl HirDatabase, mfile_id: MFileId) -> Arc { + let source_file = db.m_source_file(mfile_id); let source_file = source_file.borrowed(); - let res = SourceFileItems::new(file_id, source_file); + let res = SourceFileItems::new(mfile_id, source_file); Arc::new(res) } pub(super) fn file_item(db: &impl HirDatabase, source_item_id: SourceItemId) -> SyntaxNode { match source_item_id.item_id { - Some(id) => db.file_items(source_item_id.file_id)[id].clone(), - None => db.source_file(source_item_id.file_id).syntax().owned(), + Some(id) => db.file_items(source_item_id.mfile_id)[id].clone(), + None => db.m_source_file(source_item_id.mfile_id).syntax().owned(), } } @@ -116,7 +128,7 @@ pub(super) fn input_module_items( ) -> Cancelable> { let module_tree = db.module_tree(source_root)?; let source = module_id.source(&module_tree); - let file_items = db.file_items(source.file_id()); + let file_items = db.file_items(source.file_id().into()); let res = match source.resolve(db) { ModuleSourceNode::SourceFile(it) => { let items = it.borrowed().items(); diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index a0d1daf7111..4a99dff84f7 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -102,11 +102,11 @@ pub fn function_from_module( module: &Module, fn_def: ast::FnDef, ) -> Function { - let file_id = module.source().file_id(); - let file_items = db.file_items(file_id); - let item_id = file_items.id_of(file_id, fn_def.syntax()); + let mfile_id = module.source().file_id().into(); + let file_items = db.file_items(mfile_id); + let item_id = file_items.id_of(mfile_id, fn_def.syntax()); let source_item_id = SourceItemId { - file_id, + mfile_id, item_id: Some(item_id), }; let def_loc = DefLoc {