Repository: rust-analyzer/rust-analyzer
Pull request #404 (2019-01-02 14:11:29)

Move FileSymbol to ra_analysis


Patch:
diff --git a/crates/ra_analysis/src/completion/complete_scope.rs b/crates/ra_analysis/src/completion/complete_scope.rs
index 4dead36896..daf666505d 100644
--- a/crates/ra_analysis/src/completion/complete_scope.rs
+++ b/crates/ra_analysis/src/completion/complete_scope.rs
@@ -27,7 +27,7 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) ->
             match res.import {
                 None => true,
                 Some(import) => {
-                    let range = import.range(ctx.db, module.file_id());
+                    let range = import.range(ctx.db, module.source().file_id());
                     !range.is_subrange(&ctx.leaf.range())
                 }
             }
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index d7740f0c4e..b072a5eba0 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,6 +1,7 @@
 use std::{fmt, sync::Arc};
 use salsa::{self, Database};
 use ra_db::{LocationIntener, BaseDatabase};
+use hir::{self, DefId, DefLoc};
 
 use crate::{
     symbol_index,
@@ -14,8 +15,7 @@ pub(crate) struct RootDatabase {
 
 #[derive(Default)]
 struct IdMaps {
-    defs: LocationIntener<hir::DefLoc, hir::DefId>,
-    macros: LocationIntener<hir::MacroCallLoc, hir::MacroCallId>,
+    defs: LocationIntener<DefLoc, DefId>,
 }
 
 impl fmt::Debug for IdMaps {
@@ -59,18 +59,12 @@ impl salsa::ParallelDatabase for RootDatabase {
 
 impl BaseDatabase for RootDatabase {}
 
-impl AsRef<LocationIntener<hir::DefLoc, hir::DefId>> for RootDatabase {
-    fn as_ref(&self) -> &LocationIntener<hir::DefLoc, hir::DefId> {
+impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
+    fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> {
         &self.id_maps.defs
     }
 }
 
-impl AsRef<LocationIntener<hir::MacroCallLoc, hir::MacroCallId>> for RootDatabase {
-    fn as_ref(&self) -> &LocationIntener<hir::MacroCallLoc, hir::MacroCallId> {
-        &self.id_maps.macros
-    }
-}
-
 salsa::database_storage! {
     pub(crate) struct RootDatabaseStorage for RootDatabase {
         impl ra_db::FilesDatabase {
@@ -91,8 +85,6 @@ salsa::database_storage! {
             fn library_symbols() for symbol_index::LibrarySymbolsQuery;
         }
         impl hir::db::HirDatabase {
-            fn hir_source_file() for hir::db::HirSourceFileQuery;
-            fn expand_macro_invocation() for hir::db::ExpandMacroCallQuery;
             fn module_tree() for hir::db::ModuleTreeQuery;
             fn fn_scopes() for hir::db::FnScopesQuery;
             fn file_items() for hir::db::SourceFileItemsQuery;
diff --git a/crates/ra_analysis/src/extend_selection.rs b/crates/ra_analysis/src/extend_selection.rs
index f1b77f9819..805e9059ef 100644
--- a/crates/ra_analysis/src/extend_selection.rs
+++ b/crates/ra_analysis/src/extend_selection.rs
@@ -18,15 +18,15 @@ pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRang
 }
 
 fn extend_selection_in_macro(
-    _db: &RootDatabase,
+    db: &RootDatabase,
     source_file: &SourceFileNode,
     frange: FileRange,
 ) -> Option<TextRange> {
     let macro_call = find_macro_call(source_file.syntax(), frange.range)?;
-    let (off, exp) = hir::MacroDef::ast_expand(macro_call)?;
-    let dst_range = exp.map_range_forward(frange.range - off)?;
-    let dst_range = ra_editor::extend_selection(exp.syntax().borrowed(), dst_range)?;
-    let src_range = exp.map_range_back(dst_range)? + off;
+    let exp = crate::macros::expand(db, frange.file_id, macro_call)?;
+    let dst_range = exp.map_range_forward(frange.range)?;
+    let dst_range = ra_editor::extend_selection(exp.source_file().syntax(), dst_range)?;
+    let src_range = exp.map_range_back(dst_range)?;
     Some(src_range)
 }
 
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index ec7da437a1..b513736bba 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -10,7 +10,7 @@ use hir::{
     self, FnSignatureInfo, Problem, source_binder,
 };
 use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase};
-use ra_editor::{self, FileSymbol, find_node_at_offset, LineIndex, LocalEdit, Severity};
+use ra_editor::{self, find_node_at_offset, LineIndex, LocalEdit, Severity};
 use ra_syntax::{
     algo::find_covering_node,
     ast::{self, ArgListOwner, Expr, FnDef, NameOwner},
@@ -21,11 +21,11 @@ use ra_syntax::{
 
 use crate::{
     AnalysisChange,
-    Cancelable,
+    Cancelable, NavigationTarget,
     completion::{CompletionItem, completions},
     CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit,
     Query, ReferenceResolution, RootChange, SourceChange, SourceFileEdit,
-    symbol_index::{LibrarySymbolsQuery, SymbolIndex, SymbolsDatabase},
+    symbol_index::{LibrarySymbolsQuery, SymbolIndex, SymbolsDatabase, FileSymbol},
 };
 
 #[derive(Debug, Default)]
@@ -205,7 +205,7 @@ impl AnalysisImpl {
 
     /// This returns `Vec` because a module may be included from several places. We
     /// don't handle this case yet though, so the Vec has length at most one.
-    pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
+    pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> {
         let descr = match source_binder::module_from_position(&*self.db, position)? {
             None => return Ok(Vec::new()),
             Some(it) => it,
@@ -216,12 +216,12 @@ impl AnalysisImpl {
         };
         let decl = decl.borrowed();
         let decl_name = decl.name().unwrap();
-        let sym = FileSymbol {
+        let symbol = FileSymbol {
             name: decl_name.text(),
             node_range: decl_name.syntax().range(),
             kind: MODULE,
         };
-        Ok(vec![(file_id, sym)])
+        Ok(vec![NavigationTarget { file_id, symbol }])
     }
     /// Returns `Vec` for the same reason as `parent_module`
     pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
@@ -230,7 +230,7 @@ impl AnalysisImpl {
             Some(it) => it,
         };
         let root = descr.crate_root();
-        let file_id = root.file_id();
+        let file_id = root.source().file_id();
 
         let crate_graph = self.db.crate_graph();
         let crate_id = crate_graph.crate_id_for_crate_root(file_id);
@@ -283,7 +283,7 @@ impl AnalysisImpl {
                     if let Some(child_module) =
                         source_binder::module_from_declaration(&*self.db, position.file_id, module)?
                     {
-                        let file_id = child_module.file_id();
+                        let file_id = child_module.source().file_id();
                         let name = match child_module.name() {
                             Some(name) => name.to_string().into(),
                             None => "".into(),
@@ -355,9 +355,9 @@ impl AnalysisImpl {
             Ok(Some((binding, descr)))
         }
     }
-    pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable<Option<String>> {
-        let file = self.db.source_file(file_id);
-        let result = match (symbol.description(&file), symbol.docs(&file)) {
+    pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> {
+        let file = self.db.source_file(nav.file_id);
+        let result = match (nav.symbol.description(&file), nav.symbol.docs(&file)) {
             (Some(desc), Some(docs)) => {
                 Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs)
             }
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index 08ecb125a3..392437ad98 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -19,26 +19,27 @@ mod runnables;
 
 mod extend_selection;
 mod syntax_highlighting;
+mod macros;
 
 use std::{fmt, sync::Arc};
 
 use rustc_hash::FxHashMap;
-use ra_syntax::{SourceFileNode, TextRange, TextUnit};
+use ra_syntax::{SourceFileNode, TextRange, TextUnit, SmolStr, SyntaxKind};
 use ra_text_edit::TextEdit;
 use rayon::prelude::*;
 use relative_path::RelativePathBuf;
 
 use crate::{
     imp::{AnalysisHostImpl, AnalysisImpl},
-    symbol_index::SymbolIndex,
+    symbol_index::{SymbolIndex, FileSymbol},
 };
 
 pub use crate::{
     completion::{CompletionItem, CompletionItemKind, InsertText},
-    runnables::{Runnable, RunnableKind}
+    runnables::{Runnable, RunnableKind},
 };
 pub use ra_editor::{
-    FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, StructureNode, Severity
+    Fold, FoldKind, HighlightedRange, LineIndex, StructureNode, Severity
 };
 pub use hir::FnSignatureInfo;
 
@@ -242,6 +243,27 @@ impl Query {
     }
 }
 
+#[derive(Debug)]
+pub struct NavigationTarget {
+    file_id: FileId,
+    symbol: FileSymbol,
+}
+
+impl NavigationTarget {
+    pub fn name(&self) -> SmolStr {
+        self.symbol.name.clone()
+    }
+    pub fn kind(&self) -> SyntaxKind {
+        self.symbol.kind
+    }
+    pub fn file_id(&self) -> FileId {
+        self.file_id
+    }
+    pub fn range(&self) -> TextRange {
+        self.symbol.node_range
+    }
+}
+
 /// Result of "goto def" query.
 #[derive(Debug)]
 pub struct ReferenceResolution {
@@ -250,7 +272,7 @@ pub struct ReferenceResolution {
     /// client where the reference was.
     pub reference_range: TextRange,
     /// What this reference resolves to.
-    pub resolves_to: Vec<(FileId, FileSymbol)>,
+    pub resolves_to: Vec<NavigationTarget>,
 }
 
 impl ReferenceResolution {
@@ -262,7 +284,7 @@ impl ReferenceResolution {
     }
 
     fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) {
-        self.resolves_to.push((file_id, symbol))
+        self.resolves_to.push(NavigationTarget { file_id, symbol })
     }
 }
 
@@ -320,8 +342,14 @@ impl Analysis {
         let file = self.imp.file_syntax(file_id);
         ra_editor::folding_ranges(&file)
     }
-    pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> {
-        self.imp.world_symbols(query)
+    pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> {
+        let res = self
+            .imp
+            .world_symbols(query)?
+            .into_iter()
+            .map(|(file_id, symbol)| NavigationTarget { file_id, symbol })
+            .collect();
+        Ok(res)
     }
     pub fn approximately_resolve_symbol(
         &self,
@@ -332,10 +360,10 @@ impl Analysis {
     pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
         self.imp.find_all_refs(position)
     }
-    pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable<Option<String>> {
-        self.imp.doc_text_for(file_id, symbol)
+    pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> {
+        self.imp.doc_text_for(nav)
     }
-    pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
+    pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> {
         self.imp.parent_module(position)
     }
     pub fn module_path(&self, position: FilePosition) -> Cancelable<Option<String>> {
diff --git a/crates/ra_analysis/src/macros.rs b/crates/ra_analysis/src/macros.rs
new file mode 100644
index 0000000000..b9feb7fad4
--- /dev/null
+++ b/crates/ra_analysis/src/macros.rs
@@ -0,0 +1,75 @@
+/// Begining of macro expansion.
+///
+/// This code should be moved out of ra_analysis into hir (?) ideally.
+use ra_syntax::{ast, AstNode, SourceFileNode, TextRange};
+
+use crate::{db::RootDatabase, FileId};
+
+pub(crate) fn expand(
+    _db: &RootDatabase,
+    _file_id: FileId,
+    macro_call: ast::MacroCall,
+) -> Option<MacroExpansion> {
+    let path = macro_call.path()?;
+    if path.qualifier().is_some() {
+        return None;
+    }
+    let name_ref = path.segment()?.name_ref()?;
+    if name_ref.text() != "ctry" {
+        return None;
+    }
+
+    let arg = macro_call.token_tree()?;
+    let text = format!(
+        r"
+        fn dummy() {{
+            match {} {{
+                None => return Ok(None),
+                Some(it) => it,
+            }}
+        }}",
+        arg.syntax().text()
+    );
+    let file = SourceFileNode::parse(&text);
+    let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?;
+    let match_arg = match_expr.expr()?;
+    let ranges_map = vec![(arg.syntax().range(), match_arg.syntax().range())];
+    let res = MacroExpansion {
+        source_file: file,
+        ranges_map,
+    };
+    Some(res)
+}
+
+pub(crate) struct MacroExpansion {
+    pub(crate) source_file: SourceFileNode,
+    pub(crate) ranges_map: Vec<(TextRange, TextRange)>,
+}
+
+impl MacroExpansion {
+    pub(crate) fn source_file(&self) -> &SourceFileNode {
+        &self.source_file
+    }
+    pub(crate) fn map_range_back(&self, tgt_range: TextRange) -> Option<TextRange> {
+        for (s_range, t_range) in self.ranges_map.iter() {
+            if tgt_range.is_subrange(&t_range) {
+                let tgt_at_zero_range = tgt_range - tgt_range.start();
+                let tgt_range_offset = tgt_range.start() - t_range.start();
+                let src_range = tgt_at_zero_range + tgt_range_offset + s_range.start();
+                return Some(src_range);
+            }
+        }
+        None
+    }
+    pub(crate) fn map_range_forward(&self, src_range: TextRange) -> Option<TextRange> {
+        for (s_range, t_range) in self.ranges_map.iter() {
+            if src_range.is_subrange(&s_range) {
+                let src_at_zero_range = src_range - src_range.start();
+                let src_range_offset = src_range.start() - s_range.start();
+                let src_range = src_at_zero_range + src_range_offset + t_range.start();
+                return Some(src_range);
+            }
+        }
+        None
+    }
+}
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs
index e5bdf0aa1c..56a84a8508 100644
--- a/crates/ra_analysis/src/symbol_index.rs
+++ b/crates/ra_analysis/src/symbol_index.rs
@@ -4,10 +4,11 @@ use std::{
 };
 
 use fst::{self, Streamer};
-use ra_editor::{self, FileSymbol};
 use ra_syntax::{
-    SourceFileNode,
+    AstNode, SyntaxNodeRef, SourceFileNode, SmolStr, TextRange,
+    algo::visit::{visitor, Visitor},
     SyntaxKind::{self, *},
+    ast::{self, NameOwner, DocCommentsOwner},
 };
 use ra_db::{SyntaxDatabase, SourceRootId};
 use rayon::prelude::*;
@@ -65,8 +66,9 @@ impl SymbolIndex {
     ) -> SymbolIndex {
         let mut symbols = files
             .flat_map(|(file_id, file)| {
-                ra_editor::file_symbols(&file)
-                    .into_iter()
+                file.syntax()
+                    .descendants()
+                    .filter_map(to_symbol)
                     .map(move |symbol| (symbol.name.as_str().to_lowercase(), (file_id, symbol)))
                     .collect::<Vec<_>>()
             })
@@ -121,3 +123,116 @@ fn is_type(kind: SyntaxKind) -> bool {
         _ => false,
     }
 }
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub(crate) struct FileSymbol {
+    pub(crate) name: SmolStr,
+    pub(crate) node_range: TextRange,
+    pub(crate) kind: SyntaxKind,
+}
+
+impl FileSymbol {
+    pub(crate) fn docs(&self, file: &SourceFileNode) -> Option<String> {
+        file.syntax()
+            .descendants()
+            .filter(|node| node.kind() == self.kind && node.range() == self.node_range)
+            .filter_map(|node: SyntaxNodeRef| {
+                fn doc_comments<'a, N: DocCommentsOwner<'a>>(node: N) -> Option<String> {
+                    let comments = node.doc_comment_text();
+                    if comments.is_empty() {
+                        None
+                    } else {
+                        Some(comments)
+                    }
+                }
+
+                visitor()
+                    .visit(doc_comments::<ast::FnDef>)
+                    .visit(doc_comments::<ast::StructDef>)
+                    .visit(doc_comments::<ast::EnumDef>)
+                    .visit(doc_comments::<ast::TraitDef>)
+                    .visit(doc_comments::<ast::Module>)
+                    .visit(doc_comments::<ast::TypeDef>)
+                    .visit(doc_comments::<ast::ConstDef>)
+                    .visit(doc_comments::<ast::StaticDef>)
+                    .accept(node)?
+            })
+            .nth(0)
+    }
+    /// Get a description of this node.
+    ///
+    /// e.g. `struct Name`, `enum Name`, `fn Name`
+    pub(crate) fn description(&self, file: &SourceFileNode) -> Option<String> {
+        // TODO: After type inference is done, add type information to improve the output
+        file.syntax()
+            .descendants()
+            .filter(|node| node.kind() == self.kind && node.range() == self.node_range)
+            .filter_map(|node: SyntaxNodeRef| {
+                // TODO: Refactor to be have less repetition
+                visitor()
+                    .visit(|node: ast::FnDef| {
+                        let mut string = "fn ".to_string();
+                        node.name()?.syntax().text().push_to(&mut string);
+                        Some(string)
+                    })
+                    .visit(|node: ast::StructDef| {
+                        let mut string = "struct ".to_string();
+                        node.name()?.syntax().text().push_to(&mut string);
+                        Some(string)
+                    })
+                    .visit(|node: ast::EnumDef| {
+                        let mut string = "enum ".to_string();
+                        node.name()?.syntax().text().push_to(&mut string);
+                        Some(string)
+                    })
+                    .visit(|node: ast::TraitDef| {
+                        let mut string = "trait ".to_string();
+                        node.name()?.syntax().text().push_to(&mut string);
+                        Some(string)
+                    })
+                    .visit(|node: ast::Module| {
+                        let mut string = "mod ".to_string();
+                        node.name()?.syntax().text().push_to(&mut string);
+                        Some(string)
+                    })
+                    .visit(|node: ast::TypeDef| {
+                        let mut string = "type ".to_string();
+                        node.name()?.syntax().text().push_to(&mut string);
+                        Some(string)
+                    })
+                    .visit(|node: ast::ConstDef| {
+                        let mut string = "const ".to_string();
+                        node.name()?.syntax().text().push_to(&mut string);
+                        Some(string)
+                    })
+                    .visit(|node: ast::StaticDef| {
+                        let mut string = "static ".to_string();
+                        node.name()?.syntax().text().push_to(&mut string);
+                        Some(string)
+                    })
+                    .accept(node)?
+            })
+            .nth(0)
+    }
+}
+
+fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> {
+    fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<FileSymbol> {
+        let name = node.name()?;
+        Some(FileSymbol {
+            name: name.text(),
+            node_range: node.syntax().range(),
+            kind: node.syntax().kind(),
+        })
+    }
+    visitor()
+        .visit(decl::<ast::FnDef>)
+        .visit(decl::<ast::StructDef>)
+        .visit(decl::<ast::EnumDef>)
+        .visit(decl::<ast::TraitDef>)
+        .visit(decl::<ast::Module>)
+        .visit(decl::<ast::TypeDef>)
+        .visit(decl::<ast::ConstDef>)
+        .visit(decl::<ast::StaticDef>)
+        .accept(node)?
+}
diff --git a/crates/ra_analysis/src/syntax_highlighting.rs b/crates/ra_analysis/src/syntax_highlighting.rs
index ccea4aee39..7e9139a740 100644
--- a/crates/ra_analysis/src/syntax_highlighting.rs
+++ b/crates/ra_analysis/src/syntax_highlighting.rs
@@ -15,13 +15,13 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Cancelable<Vec<Hi
         .descendants()
         .filter_map(ast::MacroCall::cast)
     {
-        if let Some((off, exp)) = hir::MacroDef::ast_expand(macro_call) {
-            let mapped_ranges = ra_editor::highlight(exp.syntax().borrowed())
+        if let Some(exp) = crate::macros::expand(db, file_id, macro_call) {
+            let mapped_ranges = ra_editor::highlight(exp.source_file().syntax())
                 .into_iter()
                 .filter_map(|r| {
                     let mapped_range = exp.map_range_back(r.range)?;
                     let res = HighlightedRange {
-                        range: mapped_range + off,
+                        range: mapped_range,
                         tag: r.tag,
                     };
                     Some(res)
@@ -44,7 +44,7 @@ mod tests {
             fn main() {
                 ctry!({ let x = 92; x});
             }
-            ",
+        ",
         );
         let highlights = analysis.highlight(file_id).unwrap();
         assert_eq_dbg(
@@ -60,26 +60,4 @@ mod tests {
             &highlights,
         )
     }
-
-    // FIXME: this test is not really necessary: artifact of the inital hacky
-    // macros implementation.
-    #[test]
-    fn highlight_query_group_macro() {
-        let (analysis, file_id) = single_file(
-            "
-            salsa::query_group! {
-                pub trait HirDatabase: SyntaxDatabase {}
-            }
-            ",
-        );
-        let highlights = analysis.highlight(file_id).unwrap();
-        assert_eq_dbg(
-            r#"[HighlightedRange { range: [20; 32), tag: "macro" },
-                HighlightedRange { range: [13; 18), tag: "text" },
-                HighlightedRange { range: [51; 54), tag: "keyword" },
-                HighlightedRange { range: [55; 60), tag: "keyword" },
-                HighlightedRange { range: [61; 72), tag: "function" }]"#,
-            &highlights,
-        )
-    }
 }
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs
index b03f9ea541..bfc745e58c 100644
--- a/crates/ra_editor/src/lib.rs
+++ b/crates/ra_editor/src/lib.rs
@@ -3,7 +3,7 @@ mod extend_selection;
 mod folding_ranges;
 mod line_index;
 mod line_index_utils;
-mod symbols;
+mod structure;
 #[cfg(test)]
 mod test_utils;
 mod typing;
@@ -15,7 +15,7 @@ pub use self::{
     folding_ranges::{folding_ranges, Fold, FoldKind},
     line_index::{LineCol, LineIndex},
     line_index_utils::translate_offset_with_edit,
-    symbols::{file_structure, file_symbols, FileSymbol, StructureNode},
+    structure::{file_structure, StructureNode},
     typing::{join_lines, on_enter, on_eq_typed},
     diagnostics::diagnostics
 };
diff --git a/crates/ra_editor/src/structure.rs b/crates/ra_editor/src/structure.rs
new file mode 100644
index 0000000000..2292b1ddf0
--- /dev/null
+++ b/crates/ra_editor/src/structure.rs
@@ -0,0 +1,129 @@
+use crate::TextRange;
+
+use ra_syntax::{
+    algo::visit::{visitor, Visitor},
+    ast::{self, NameOwner},
+    AstNode, SourceFileNode, SyntaxKind, SyntaxNodeRef, WalkEvent,
+};
+
+#[derive(Debug, Clone)]
+pub struct StructureNode {
+    pub parent: Option<usize>,
+    pub label: String,
+    pub navigation_range: TextRange,
+    pub node_range: TextRange,
+    pub kind: SyntaxKind,
+}
+
+pub fn file_structure(file: &SourceFileNode) -> Vec<StructureNode> {
+    let mut res = Vec::new();
+    let mut stack = Vec::new();
+
+    for event in file.syntax().preorder() {
+        match event {
+            WalkEvent::Enter(node) => {
+                if let Some(mut symbol) = structure_node(node) {
+                    symbol.parent = stack.last().map(|&n| n);
+                    stack.push(res.len());
+                    res.push(symbol);
+                }
+            }
+            WalkEvent::Leave(node) => {
+                if structure_node(node).is_some() {
+                    stack.pop().unwrap();
+                }
+            }
+        }
+    }
+    res
+}
+
+fn structure_node(node: SyntaxNodeRef) -> Option<StructureNode> {
+    fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<StructureNode> {
+        let name = node.name()?;
+        Some(StructureNode {
+            parent: None,
+            label: name.text().to_string(),
+            navigation_range: name.syntax().range(),
+            node_range: node.syntax().range(),
+            kind: node.syntax().kind(),
+        })
+    }
+
+    visitor()
+        .visit(decl::<ast::FnDef>)
+        .visit(decl::<ast::StructDef>)
+        .visit(decl::<ast::NamedFieldDef>)
+        .visit(decl::<ast::EnumDef>)
+        .visit(decl::<ast::TraitDef>)
+        .visit(decl::<ast::Module>)
+        .visit(decl::<ast::TypeDef>)
+        .visit(decl::<ast::ConstDef>)
+        .visit(decl::<ast::StaticDef>)
+        .visit(|im: ast::ImplItem| {
+            let target_type = im.target_type()?;
+            let target_trait = im.target_trait();
+            let label = match target_trait {
+                None => format!("impl {}", target_type.syntax().text()),
+                Some(t) => format!(
+                    "impl {} for {}",
+                    t.syntax().text(),
+                    target_type.syntax().text(),
+                ),
+            };
+
+            let node = StructureNode {
+                parent: None,
+                label,
+                navigation_range: target_type.syntax().range(),
+                node_range: im.syntax().range(),
+                kind: im.syntax().kind(),
+            };
+            Some(node)
+        })
+        .accept(node)?
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use test_utils::assert_eq_dbg;
+
+    #[test]
+    fn test_file_structure() {
+        let file = SourceFileNode::parse(
+            r#"
+struct Foo {
+    x: i32
+}
+
+mod m {
+    fn bar() {}
+}
+
+enum E { X, Y(i32) }
+type T = ();
+static S: i32 = 92;
+const C: i32 = 92;
+
+impl E {}
+
+impl fmt::Debug for E {}
+"#,
+        );
+        let structure = file_structure(&file);
+        assert_eq_dbg(
+            r#"[StructureNode { parent: None, label: "Foo", navigation_range: [8; 11), node_range: [1; 26), kind: STRUCT_DEF },
+                StructureNode { parent: Some(0), label: "x", navigation_range: [18; 19), node_range: [18; 24), kind: NAMED_FIELD_DEF },
+                StructureNode { parent: None, label: "m", navigation_range: [32; 33), node_range: [28; 53), kind: MODULE },
+                StructureNode { parent: Some(2), label: "bar", navigation_range: [43; 46), node_range: [40; 51), kind: FN_DEF },
+                StructureNode { parent: None, label: "E", navigation_range: [60; 61), node_range: [55; 75), kind: ENUM_DEF },
+                StructureNode { parent: None, label: "T", navigation_range: [81; 82), node_range: [76; 88), kind: TYPE_DEF },
+                StructureNode { parent: None, label: "S", navigation_range: [96; 97), node_range: [89; 108), kind: STATIC_DEF },
+                StructureNode { parent: None, label: "C", navigation_range: [115; 116), node_range: [109; 127), kind: CONST_DEF },
+                StructureNode { parent: None, label: "impl E", navigation_range: [134; 135), node_range: [129; 138), kind: IMPL_ITEM },
+                StructureNode { parent: None, label: "impl fmt::Debug for E", navigation_range: [160; 161), node_range: [140; 164), kind: IMPL_ITEM }]"#,
+            &structure,
+        )
+    }
+}
diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs
deleted file mode 100644
index 9e25decfbc..0000000000
--- a/crates/ra_editor/src/symbols.rs
+++ /dev/null
@@ -1,246 +0,0 @@
-use crate::TextRange;
-
-use ra_syntax::{
-    algo::visit::{visitor, Visitor},
-    ast::{self, DocCommentsOwner, NameOwner},
-    AstNode, SourceFileNode, SmolStr, SyntaxKind, SyntaxNodeRef, WalkEvent,
-};
-
-#[derive(Debug, Clone)]
-pub struct StructureNode {
-    pub parent: Option<usize>,
-    pub label: String,
-    pub navigation_range: TextRange,
-    pub node_range: TextRange,
-    pub kind: SyntaxKind,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct FileSymbol {
-    pub name: SmolStr,
-    pub node_range: TextRange,
-    pub kind: SyntaxKind,
-}
-
-impl FileSymbol {
-    pub fn docs(&self, file: &SourceFileNode) -> Option<String> {
-        file.syntax()
-            .descendants()
-            .filter(|node| node.kind() == self.kind && node.range() == self.node_range)
-            .filter_map(|node: SyntaxNodeRef| {
-                fn doc_comments<'a, N: DocCommentsOwner<'a>>(node: N) -> Option<String> {
-                    let comments = node.doc_comment_text();
-                    if comments.is_empty() {
-                        None
-                    } else {
-                        Some(comments)
-                    }
-                }
-
-                visitor()
-                    .visit(doc_comments::<ast::FnDef>)
-                    .visit(doc_comments::<ast::StructDef>)
-                    .visit(doc_comments::<ast::EnumDef>)
-                    .visit(doc_comments::<ast::TraitDef>)
-                    .visit(doc_comments::<ast::Module>)
-                    .visit(doc_comments::<ast::TypeDef>)
-                    .visit(doc_comments::<ast::ConstDef>)
-                    .visit(doc_comments::<ast::StaticDef>)
-                    .accept(node)?
-            })
-            .nth(0)
-    }
-    /// Get a description of this node.
-    ///
-    /// e.g. `struct Name`, `enum Name`, `fn Name`
-    pub fn description(&self, file: &SourceFileNode) -> Option<String> {
-        // TODO: After type inference is done, add type information to improve the output
-        file.syntax()
-            .descendants()
-            .filter(|node| node.kind() == self.kind && node.range() == self.node_range)
-            .filter_map(|node: SyntaxNodeRef| {
-                // TODO: Refactor to be have less repetition
-                visitor()
-                    .visit(|node: ast::FnDef| {
-                        let mut string = "fn ".to_string();
-                        node.name()?.syntax().text().push_to(&mut string);
-                        Some(string)
-                    })
-                    .visit(|node: ast::StructDef| {
-                        let mut string = "struct ".to_string();
-                        node.name()?.syntax().text().push_to(&mut string);
-                        Some(string)
-                    })
-                    .visit(|node: ast::EnumDef| {
-                        let mut string = "enum ".to_string();
-                        node.name()?.syntax().text().push_to(&mut string);
-                        Some(string)
-                    })
-                    .visit(|node: ast::TraitDef| {
-                        let mut string = "trait ".to_string();
-                        node.name()?.syntax().text().push_to(&mut string);
-                        Some(string)
-                    })
-                    .visit(|node: ast::Module| {
-                        let mut string = "mod ".to_string();
-                        node.name()?.syntax().text().push_to(&mut string);
-                        Some(string)
-                    })
-                    .visit(|node: ast::TypeDef| {
-                        let mut string = "type ".to_string();
-                        node.name()?.syntax().text().push_to(&mut string);
-                        Some(string)
-                    })
-                    .visit(|node: ast::ConstDef| {
-                        let mut string = "const ".to_string();
-                        node.name()?.syntax().text().push_to(&mut string);
-                        Some(string)
-                    })
-                    .visit(|node: ast::StaticDef| {
-                        let mut string = "static ".to_string();
-                        node.name()?.syntax().text().push_to(&mut string);
-                        Some(string)
-                    })
-                    .accept(node)?
-            })
-            .nth(0)
-    }
-}
-
-pub fn file_symbols(file: &SourceFileNode) -> Vec<FileSymbol> {
-    file.syntax().descendants().filter_map(to_symbol).collect()
-}
-
-fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> {
-    fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<FileSymbol> {
-        let name = node.name()?;
-        Some(FileSymbol {
-            name: name.text(),
-            node_range: node.syntax().range(),
-            kind: node.syntax().kind(),
-        })
-    }
-    visitor()
-        .visit(decl::<ast::FnDef>)
-        .visit(decl::<ast::StructDef>)
-        .visit(decl::<ast::EnumDef>)
-        .visit(decl::<ast::TraitDef>)
-        .visit(decl::<ast::Module>)
-        .visit(decl::<ast::TypeDef>)
-        .visit(decl::<ast::ConstDef>)
-        .visit(decl::<ast::StaticDef>)
-        .accept(node)?
-}
-
-pub fn file_structure(file: &SourceFileNode) -> Vec<StructureNode> {
-    let mut res = Vec::new();
-    let mut stack = Vec::new();
-
-    for event in file.syntax().preorder() {
-        match event {
-            WalkEvent::Enter(node) => {
-                if let Some(mut symbol) = structure_node(node) {
-                    symbol.parent = stack.last().map(|&n| n);
-                    stack.push(res.len());
-                    res.push(symbol);
-                }
-            }
-            WalkEvent::Leave(node) => {
-                if structure_node(node).is_some() {
-                    stack.pop().unwrap();
-                }
-            }
-        }
-    }
-    res
-}
-
-fn structure_node(node: SyntaxNodeRef) -> Option<StructureNode> {
-    fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<StructureNode> {
-        let name = node.name()?;
-        Some(StructureNode {
-            parent: None,
-            label: name.text().to_string(),
-            navigation_range: name.syntax().range(),
-            node_range: node.syntax().range(),
-            kind: node.syntax().kind(),
-        })
-    }
-
-    visitor()
-        .visit(decl::<ast::FnDef>)
-        .visit(decl::<ast::StructDef>)
-        .visit(decl::<ast::NamedFieldDef>)
-        .visit(decl::<ast::EnumDef>)
-        .visit(decl::<ast::TraitDef>)
-        .visit(decl::<ast::Module>)
-        .visit(decl::<ast::TypeDef>)
-        .visit(decl::<ast::ConstDef>)
-        .visit(decl::<ast::StaticDef>)
-        .visit(|im: ast::ImplItem| {
-            let target_type = im.target_type()?;
-            let target_trait = im.target_trait();
-            let label = match target_trait {
-                None => format!("impl {}", target_type.syntax().text()),
-                Some(t) => format!(
-                    "impl {} for {}",
-                    t.syntax().text(),
-                    target_type.syntax().text(),
-                ),
-            };
-
-            let node = StructureNode {
-                parent: None,
-                label,
-                navigation_range: target_type.syntax().range(),
-                node_range: im.syntax().range(),
-                kind: im.syntax().kind(),
-            };
-            Some(node)
-        })
-        .accept(node)?
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use test_utils::assert_eq_dbg;
-
-    #[test]
-    fn test_file_structure() {
-        let file = SourceFileNode::parse(
-            r#"
-struct Foo {
-    x: i32
-}
-
-mod m {
-    fn bar() {}
-}
-
-enum E { X, Y(i32) }
-type T = ();
-static S: i32 = 92;
-const C: i32 = 92;
-
-impl E {}
-
-impl fmt::Debug for E {}
-"#,
-        );
-        let symbols = file_structure(&file);
-        assert_eq_dbg(
-            r#"[StructureNode { parent: None, label: "Foo", navigation_range: [8; 11), node_range: [1; 26), kind: STRUCT_DEF },
-                StructureNode { parent: Some(0), label: "x", navigation_range: [18; 19), node_range: [18; 24), kind: NAMED_FIELD_DEF },
-                StructureNode { parent: None, label: "m", navigation_range: [32; 33), node_range: [28; 53), kind: MODULE },
-                StructureNode { parent: Some(2), label: "bar", navigation_range: [43; 46), node_range: [40; 51), kind: FN_DEF },
-                StructureNode { parent: None, label: "E", navigation_range: [60; 61), node_range: [55; 75), kind: ENUM_DEF },
-                StructureNode { parent: None, label: "T", navigation_range: [81; 82), node_range: [76; 88), kind: TYPE_DEF },
-                StructureNode { parent: None, label: "S", navigation_range: [96; 97), node_range: [89; 108), kind: STATIC_DEF },
-                StructureNode { parent: None, label: "C", navigation_range: [115; 116), node_range: [109; 127), kind: CONST_DEF },
-                StructureNode { parent: None, label: "impl E", navigation_range: [134; 135), node_range: [129; 138), kind: IMPL_ITEM },
-                StructureNode { parent: None, label: "impl fmt::Debug for E", navigation_range: [160; 161), node_range: [140; 164), kind: IMPL_ITEM }]"#,
-            &symbols,
-        )
-    }
-}
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index c6463235c4..e839a5a90d 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -1,10 +1,9 @@
 use std::sync::Arc;
 
-use ra_db::Cancelable;
 use ra_syntax::ast::{self, NameOwner, StructFlavor};
 
 use crate::{
-    DefId, Name, AsName,
+    DefId, Cancelable, Name, AsName,
     db::HirDatabase,
     type_ref::TypeRef,
 };
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 73a4cdc5c8..5a8ca3b47a 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,14 +1,13 @@
 use std::sync::Arc;
 
-use ra_syntax::{SyntaxNode, SourceFileNode};
-use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, Cancelable};
+use ra_syntax::SyntaxNode;
+use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable};
 
 use crate::{
-    DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId,
+    DefLoc, DefId, Name,
     SourceFileItems, SourceItemId,
     query_definitions,
     FnScopes,
-    macros::MacroExpansion,
     module::{ModuleId, ModuleTree, ModuleSource,
     nameres::{ItemMap, InputModuleItems}},
     ty::{InferenceResult, Ty},
@@ -19,17 +18,7 @@ salsa::query_group! {
 
 pub trait HirDatabase: SyntaxDatabase
     + AsRef<LocationIntener<DefLoc, DefId>>
-    + AsRef<LocationIntener<MacroCallLoc, MacroCallId>>
 {
-    fn hir_source_file(file_id: HirFileId) -> SourceFileNode {
-        type HirSourceFileQuery;
-        use fn HirFileId::hir_source_file;
-    }
-    fn expand_macro_invocation(invoc: MacroCallId) -> Option<Arc<MacroExpansion>> {
-        type ExpandMacroCallQuery;
-        use fn crate::macros::expand_macro_invocation;
-    }
-
     fn fn_scopes(def_id: DefId) -> Arc<FnScopes> {
         type FnScopesQuery;
         use fn query_definitions::fn_scopes;
@@ -60,7 +49,7 @@ pub trait HirDatabase: SyntaxDatabase
         use fn crate::ty::type_for_field;
     }
 
-    fn file_items(file_id: HirFileId) -> Arc<SourceFileItems> {
+    fn file_items(file_id: FileId) -> Arc<SourceFileItems> {
         type SourceFileItemsQuery;
         use fn query_definitions::file_items;
     }
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
deleted file mode 100644
index a09dee8b1d..0000000000
--- a/crates/ra_hir/src/ids.rs
+++ /dev/null
@@ -1,280 +0,0 @@
-use ra_db::{SourceRootId, LocationIntener, Cancelable, FileId};
-use ra_syntax::{SourceFileNode, SyntaxKind, SyntaxNode, SyntaxNodeRef, SourceFile, AstNode, ast};
-
-use crate::{
-    HirDatabase, PerNs, ModuleId, Module, Def, Function, Struct, Enum,
-    arena::{Arena, Id},
-};
-
-/// hir makes a heavy use of ids: integer (u32) handlers to various things. You
-/// can think of id as a pointer (but without a lifetime) or a file descriptor
-/// (but for hir objects).
-///
-/// This module defines a bunch of ids we are using. The most important ones are
-/// probably `HirFileId` and `DefId`.
-
-/// Input to the analyzer is a set of file, where each file is indetified by
-/// `FileId` and contains source code. However, another source of source code in
-/// Rust are macros: each macro can be thought of as producing a "temporary
-/// file". To assign id to such file, we use the id of a macro call that
-/// produced the file. So, a `HirFileId` is either a `FileId` (source code
-/// written by user), or a `MacroCallId` (source code produced by macro).
-///
-/// What is a `MacroCallId`? Simplifying, it's a `HirFileId` of a file containin
-/// the call plus the offset of the macro call in the file. Note that this is a
-/// recursive definition! Nethetheless, size_of of `HirFileId` is finite
-/// (because everything bottoms out at the real `FileId`) and small
-/// (`MacroCallId` uses location interner).
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct HirFileId(HirFileIdRepr);
-
-impl HirFileId {
-    /// For macro-expansion files, returns the file original source file the
-    /// expansionoriginated from.
-    pub(crate) fn original_file(self, db: &impl HirDatabase) -> FileId {
-        match self.0 {
-            HirFileIdRepr::File(file_id) => file_id,
-            HirFileIdRepr::Macro(macro_call_id) => {
-                let loc = macro_call_id.loc(db);
-                loc.source_item_id.file_id.original_file(db)
-            }
-        }
-    }
-
-    pub(crate) fn as_original_file(self) -> FileId {
-        match self.0 {
-            HirFileIdRepr::File(file_id) => file_id,
-            HirFileIdRepr::Macro(_r) => panic!("macro generated file: {:?}", self),
-        }
-    }
-
-    pub(crate) fn hir_source_file(db: &impl HirDatabase, file_id: HirFileId) -> SourceFileNode {
-        match file_id.0 {
-            HirFileIdRepr::File(file_id) => db.source_file(file_id),
-            HirFileIdRepr::Macro(m) => {
-                if let Some(exp) = db.expand_macro_invocation(m) {
-                    return exp.file();
-                }
-                // returning an empty string looks fishy...
-                SourceFileNode::parse("")
-            }
-        }
-    }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-enum HirFileIdRepr {
-    File(FileId),
-    Macro(MacroCallId),
-}
-
-impl From<FileId> for HirFileId {
-    fn from(file_id: FileId) -> HirFileId {
-        HirFileId(HirFileIdRepr::File(file_id))
-    }
-}
-
-impl From<MacroCallId> for HirFileId {
-    fn from(macro_call_id: MacroCallId) -> HirFileId {
-        HirFileId(HirFileIdRepr::Macro(macro_call_id))
-    }
-}
-
-/// `MacroCallId` identifies a particular macro invocation, like
-/// `println!("Hello, {}", world)`.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct MacroCallId(u32);
-ra_db::impl_numeric_id!(MacroCallId);
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct MacroCallLoc {
-    pub(crate) source_root_id: SourceRootId,
-    pub(crate) module_id: ModuleId,
-    pub(crate) source_item_id: SourceItemId,
-}
-
-impl MacroCallId {
-    pub(crate) fn loc(
-        self,
-        db: &impl AsRef<LocationIntener<MacroCallLoc, MacroCallId>>,
-    ) -> MacroCallLoc {
-        db.as_ref().id2loc(self)
-    }
-}
-
-impl MacroCallLoc {
-    #[allow(unused)]
-    pub(crate) fn id(
-        &self,
-        db: &impl AsRef<LocationIntener<MacroCallLoc, MacroCallId>>,
-    ) -> MacroCallId {
-        db.as_ref().loc2id(&self)
-    }
-}
-
-/// 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)]
-pub struct DefId(u32);
-ra_db::impl_numeric_id!(DefId);
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct DefLoc {
-    pub(crate) kind: DefKind,
-    pub(crate) source_root_id: SourceRootId,
-    pub(crate) module_id: ModuleId,
-    pub(crate) source_item_id: SourceItemId,
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub(crate) enum DefKind {
-    Module,
-    Function,
-    Struct,
-    Enum,
-    Item,
-
-    StructCtor,
-}
-
-impl DefId {
-    pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
-        db.as_ref().id2loc(self)
-    }
-
-    pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
-        let loc = self.loc(db);
-        let res = match loc.kind {
-            DefKind::Module => {
-                let module = Module::new(db, loc.source_root_id, loc.module_id)?;
-                Def::Module(module)
-            }
-            DefKind::Function => {
-                let function = Function::new(self);
-                Def::Function(function)
-            }
-            DefKind::Struct => {
-                let struct_def = Struct::new(self);
-                Def::Struct(struct_def)
-            }
-            DefKind::Enum => {
-                let enum_def = Enum::new(self);
-                Def::Enum(enum_def)
-            }
-            DefKind::StructCtor => Def::Item,
-            DefKind::Item => Def::Item,
-        };
-        Ok(res)
-    }
-
-    /// For a module, returns that module; for any other def, returns the containing module.
-    pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> {
-        let loc = self.loc(db);
-        Module::new(db, loc.source_root_id, loc.module_id)
-    }
-}
-
-impl DefLoc {
-    pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
-        db.as_ref().loc2id(&self)
-    }
-}
-
-impl DefKind {
-    pub(crate) fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
-        match kind {
-            SyntaxKind::FN_DEF => PerNs::values(DefKind::Function),
-            SyntaxKind::MODULE => PerNs::types(DefKind::Module),
-            SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
-            SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
-            // These define items, but don't have their own DefKinds yet:
-            SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Item),
-            SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Item),
-            SyntaxKind::CONST_DEF => PerNs::values(DefKind::Item),
-            SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Item),
-            _ => PerNs::none(),
-        }
-    }
-}
-
-/// Identifier of item within a specific file. This is stable over reparses, so
-/// it's OK to use it as a salsa key/value.
-pub(crate) type SourceFileItemId = Id<SyntaxNode>;
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct SourceItemId {
-    pub(crate) file_id: HirFileId,
-    /// None for the whole file.
-    pub(crate) item_id: Option<SourceFileItemId>,
-}
-
-/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
-#[derive(Debug, PartialEq, Eq)]
-pub struct SourceFileItems {
-    file_id: HirFileId,
-    arena: Arena<SyntaxNode>,
-}
-
-impl SourceFileItems {
-    pub(crate) fn new(file_id: HirFileId, source_file: SourceFile) -> SourceFileItems {
-        let mut res = SourceFileItems {
-            file_id,
-            arena: Arena::default(),
-        };
-        res.init(source_file);
-        res
-    }
-
-    fn init(&mut self, source_file: SourceFile) {
-        source_file.syntax().descendants().for_each(|it| {
-            if let Some(module_item) = ast::ModuleItem::cast(it) {
-                self.alloc(module_item.syntax().owned());
-            } else if let Some(macro_call) = ast::MacroCall::cast(it) {
-                self.alloc(macro_call.syntax().owned());
-            }
-        });
-    }
-
-    fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
-        self.arena.alloc(item)
-    }
-    pub(crate) fn id_of(&self, file_id: HirFileId, item: SyntaxNodeRef) -> SourceFileItemId {
-        assert_eq!(
-            self.file_id, file_id,
-            "SourceFileItems: wrong file, expected {:?}, got {:?}",
-            self.file_id, file_id
-        );
-        self.id_of_unchecked(item)
-    }
-    pub(crate) fn id_of_unchecked(&self, item: SyntaxNodeRef) -> SourceFileItemId {
-        if let Some((id, _)) = self.arena.iter().find(|(_id, i)| i.borrowed() == item) {
-            return id;
-        }
-        // This should not happen. Let's try to give a sensible diagnostics.
-        if let Some((id, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) {
-            // FIXME(#288): whyyy are we getting here?
-            log::error!(
-                "unequal syntax nodes with the same range:\n{:?}\n{:?}",
-                item,
-                i
-            );
-            return id;
-        }
-        panic!(
-            "Can't find {:?} in SourceFileItems:\n{:?}",
-            item,
-            self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
-        );
-    }
-    pub fn id_of_source_file(&self) -> SourceFileItemId {
-        let (id, _syntax) = self.arena.iter().next().unwrap();
-        id
-    }
-}
-
-impl std::ops::Index<SourceFileItemId> for SourceFileItems {
-    type Output = SyntaxNode;
-    fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
-        &self.arena[idx]
-    }
-}
diff --git a/crates/ra_hir/src/krate.rs b/crates/ra_hir/src/krate.rs
index a0821d15dd..89b1e639ef 100644
--- a/crates/ra_hir/src/krate.rs
+++ b/crates/ra_hir/src/krate.rs
@@ -1,6 +1,6 @@
-pub use ra_db::{CrateId, Cancelable};
+pub use ra_db::CrateId;
 
-use crate::{HirDatabase, Module, Name, AsName, HirFileId};
+use crate::{HirDatabase, Module, Cancelable, Name, AsName};
 
 /// hir::Crate describes a single crate. It's the main inteface with which
 /// crate's dependencies interact. Mostly, it should be just a proxy for the
@@ -35,7 +35,6 @@ impl Crate {
         let crate_graph = db.crate_graph();
         let file_id = crate_graph.crate_root(self.crate_id);
         let source_root_id = db.file_source_root(file_id);
-        let file_id = HirFileId::from(file_id);
         let module_tree = db.module_tree(source_root_id)?;
         // FIXME: teach module tree about crate roots instead of guessing
         let (module_id, _) = ctry!(module_tree
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 8ee52a466d..5bbb09c01c 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -22,10 +22,7 @@ mod path;
 mod arena;
 pub mod source_binder;
 
-mod ids;
-mod macros;
 mod name;
-// can't use `crate` or `r#crate` here :(
 mod krate;
 mod module;
 mod function;
@@ -33,18 +30,21 @@ mod adt;
 mod type_ref;
 mod ty;
 
+use std::ops::Index;
+
+use ra_syntax::{SyntaxNodeRef, SyntaxNode, SyntaxKind};
+use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable};
+
 use crate::{
     db::HirDatabase,
+    arena::{Arena, Id},
     name::{AsName, KnownName},
-    ids::{DefKind, SourceItemId, SourceFileItemId, SourceFileItems},
 };
 
 pub use self::{
     path::{Path, PathKind},
     name::Name,
     krate::Crate,
-    ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc},
-    macros::{MacroDef, MacroInput, MacroExpansion},
     module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution},
     function::{Function, FnScopes},
     adt::{Struct, Enum},
@@ -53,6 +53,60 @@ pub use self::{
 
 pub use self::function::FnSignatureInfo;
 
+/// 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)]
+pub struct DefId(u32);
+ra_db::impl_numeric_id!(DefId);
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub(crate) enum DefKind {
+    Module,
+    Function,
+    Struct,
+    Enum,
+    Item,
+
+    StructCtor,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct DefLoc {
+    pub(crate) kind: DefKind,
+    source_root_id: SourceRootId,
+    module_id: ModuleId,
+    source_item_id: SourceItemId,
+}
+
+impl DefKind {
+    pub(crate) fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
+        match kind {
+            SyntaxKind::FN_DEF => PerNs::values(DefKind::Function),
+            SyntaxKind::MODULE => PerNs::types(DefKind::Module),
+            SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
+            SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
+            // These define items, but don't have their own DefKinds yet:
+            SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Item),
+            SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Item),
+            SyntaxKind::CONST_DEF => PerNs::values(DefKind::Item),
+            SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Item),
+            _ => PerNs::none(),
+        }
+    }
+}
+
+impl DefId {
+    pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
+        db.as_ref().id2loc(self)
+    }
+}
+
+impl DefLoc {
+    pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
+        db.as_ref().loc2id(&self)
+    }
+}
+
 pub enum Def {
     Module(Module),
     Function(Function),
@@ -60,3 +114,106 @@ pub enum Def {
     Enum(Enum),
     Item,
 }
+
+impl DefId {
+    pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
+        let loc = self.loc(db);
+        let res = match loc.kind {
+            DefKind::Module => {
+                let module = Module::new(db, loc.source_root_id, loc.module_id)?;
+                Def::Module(module)
+            }
+            DefKind::Function => {
+                let function = Function::new(self);
+                Def::Function(function)
+            }
+            DefKind::Struct => {
+                let struct_def = Struct::new(self);
+                Def::Struct(struct_def)
+            }
+            DefKind::Enum => {
+                let enum_def = Enum::new(self);
+                Def::Enum(enum_def)
+            }
+            DefKind::StructCtor => Def::Item,
+            DefKind::Item => Def::Item,
+        };
+        Ok(res)
+    }
+
+    /// For a module, returns that module; for any other def, returns the containing module.
+    pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> {
+        let loc = self.loc(db);
+        Module::new(db, loc.source_root_id, loc.module_id)
+    }
+}
+
+/// Identifier of item within a specific file. This is stable over reparses, so
+/// it's OK to use it as a salsa key/value.
+pub(crate) type SourceFileItemId = Id<SyntaxNode>;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct SourceItemId {
+    file_id: FileId,
+    /// None for the whole file.
+    item_id: Option<SourceFileItemId>,
+}
+
+/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
+#[derive(Debug, PartialEq, Eq)]
+pub struct SourceFileItems {
+    file_id: FileId,
+    arena: Arena<SyntaxNode>,
+}
+
+impl SourceFileItems {
+    fn new(file_id: FileId) -> SourceFileItems {
+        SourceFileItems {
+            file_id,
+            arena: Arena::default(),
+        }
+    }
+
+    fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
+        self.arena.alloc(item)
+    }
+    pub fn id_of(&self, file_id: FileId, item: SyntaxNodeRef) -> SourceFileItemId {
+        assert_eq!(
+            self.file_id, file_id,
+            "SourceFileItems: wrong file, expected {:?}, got {:?}",
+            self.file_id, file_id
+        );
+        self.id_of_unchecked(item)
+    }
+    fn id_of_unchecked(&self, item: SyntaxNodeRef) -> SourceFileItemId {
+        if let Some((id, _)) = self.arena.iter().find(|(_id, i)| i.borrowed() == item) {
+            return id;
+        }
+        // This should not happen. Let's try to give a sensible diagnostics.
+        if let Some((id, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) {
+            // FIXME(#288): whyyy are we getting here?
+            log::error!(
+                "unequal syntax nodes with the same range:\n{:?}\n{:?}",
+                item,
+                i
+            );
+            return id;
+        }
+        panic!(
+            "Can't find {:?} in SourceFileItems:\n{:?}",
+            item,
+            self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
+        );
+    }
+    pub fn id_of_source_file(&self) -> SourceFileItemId {
+        let (id, _syntax) = self.arena.iter().next().unwrap();
+        id
+    }
+}
+
+impl Index<SourceFileItemId> for SourceFileItems {
+    type Output = SyntaxNode;
+    fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
+        &self.arena[idx]
+    }
+}
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs
deleted file mode 100644
index b7b75e7022..0000000000
--- a/crates/ra_hir/src/macros.rs
+++ /dev/null
@@ -1,181 +0,0 @@
-/// Machinery for macro expansion.
-///
-/// One of the more complicated things about macros is managing the source code
-/// that is produced after expansion. See `HirFileId` and `MacroCallId` for how
-/// do we do that.
-///
-/// When file-management question is resolved, all that is left is a token tree
-/// to token tree transformation plus hygent. We don't have either of thouse
-/// yet, so all macros are string based at the moment!
-use std::sync::Arc;
-
-use ra_db::LocalSyntaxPtr;
-use ra_syntax::{
-    TextRange, TextUnit, SourceFileNode, AstNode, SyntaxNode,
-    ast::{self, NameOwner},
-};
-
-use crate::{HirDatabase, MacroCallId};
-
-// Hard-coded defs for now :-(
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum MacroDef {
-    CTry,
-    QueryGroup,
-}
-
-impl MacroDef {
-    /// Expands macro call, returning the expansion and offset to be used to
-    /// convert ranges between expansion and original source.
-    pub fn ast_expand(macro_call: ast::MacroCall) -> Option<(TextUnit, MacroExpansion)> {
-        let (def, input) = MacroDef::from_call(macro_call)?;
-        let exp = def.expand(input)?;
-        let off = macro_call.token_tree()?.syntax().range().start();
-        Some((off, exp))
-    }
-
-    fn from_call(macro_call: ast::MacroCall) -> Option<(MacroDef, MacroInput)> {
-        let def = {
-            let path = macro_call.path()?;
-            let name_ref = path.segment()?.name_ref()?;
-            if name_ref.text() == "ctry" {
-                MacroDef::CTry
-            } else if name_ref.text() == "query_group" {
-                MacroDef::QueryGroup
-            } else {
-                return None;
-            }
-        };
-
-        let input = {
-            let arg = macro_call.token_tree()?.syntax();
-            MacroInput {
-                text: arg.text().to_string(),
-            }
-        };
-        Some((def, input))
-    }
-
-    fn expand(self, input: MacroInput) -> Option<MacroExpansion> {
-        match self {
-            MacroDef::CTry => self.expand_ctry(input),
-            MacroDef::QueryGroup => self.expand_query_group(input),
-        }
-    }
-    fn expand_ctry(self, input: MacroInput) -> Option<MacroExpansion> {
-        let text = format!(
-            r"
-                fn dummy() {{
-                    match {} {{
-                        None => return Ok(None),
-                        Some(it) => it,
-                    }}
-                }}",
-            input.text
-        );
-        let file = SourceFileNode::parse(&text);
-        let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?;
-        let match_arg = match_expr.expr()?;
-        let ptr = LocalSyntaxPtr::new(match_arg.syntax());
-        let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text));
-        let ranges_map = vec![(src_range, match_arg.syntax().range())];
-        let res = MacroExpansion {
-            text,
-            ranges_map,
-            ptr,
-        };
-        Some(res)
-    }
-    fn expand_query_group(self, input: MacroInput) -> Option<MacroExpansion> {
-        let anchor = "trait ";
-        let pos = input.text.find(anchor)? + anchor.len();
-        let trait_name = input.text[pos..]
-            .chars()
-            .take_while(|c| c.is_alphabetic())
-            .collect::<String>();
-        if trait_name.is_empty() {
-            return None;
-        }
-        let src_range = TextRange::offset_len((pos as u32).into(), TextUnit::of_str(&trait_name));
-        let text = format!(r"trait {} {{ }}", trait_name);
-        let file = SourceFileNode::parse(&text);
-        let trait_def = file.syntax().descendants().find_map(ast::TraitDef::cast)?;
-        let name = trait_def.name()?;
-        let ptr = LocalSyntaxPtr::new(trait_def.syntax());
-        let ranges_map = vec![(src_range, name.syntax().range())];
-        let res = MacroExpansion {
-            text,
-            ranges_map,
-            ptr,
-        };
-        Some(res)
-    }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MacroInput {
-    // Should be token trees
-    pub text: String,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct MacroExpansion {
-    /// The result of macro expansion. Should be token tree as well.
-    text: String,
-    /// Correspondence between ranges in the original source code and ranges in
-    /// the macro.
-    ranges_map: Vec<(TextRange, TextRange)>,
-    /// Implementation detail: internally, a macro is expanded to the whole file,
-    /// even if it is an expression. This `ptr` selects the actual expansion from
-    /// the expanded file.
-    ptr: LocalSyntaxPtr,
-}
-
-impl MacroExpansion {
-    // FIXME: does not really make sense, macro expansion is not neccessary a
-    // whole file. See `MacroExpansion::ptr` as well.
-    pub(crate) fn file(&self) -> SourceFileNode {
-        SourceFileNode::parse(&self.text)
-    }
-
-    pub fn syntax(&self) -> SyntaxNode {
-        self.ptr.resolve(&self.file())
-    }
-    /// Maps range in the source code to the range in the expanded code.
-    pub fn map_range_forward(&self, src_range: TextRange) -> Option<TextRange> {
-        for (s_range, t_range) in self.ranges_map.iter() {
-            if src_range.is_subrange(&s_range) {
-                let src_at_zero_range = src_range - src_range.start();
-                let src_range_offset = src_range.start() - s_range.start();
-                let src_range = src_at_zero_range + src_range_offset + t_range.start();
-                return Some(src_range);
-            }
-        }
-        None
-    }
-    /// Maps range in the expanded code to the range in the source code.
-    pub fn map_range_back(&self, tgt_range: TextRange) -> Option<TextRange> {
-        for (s_range, t_range) in self.ranges_map.iter() {
-            if tgt_range.is_subrange(&t_range) {
-                let tgt_at_zero_range = tgt_range - tgt_range.start();
-                let tgt_range_offset = tgt_range.start() - t_range.start();
-                let src_range = tgt_at_zero_range + tgt_range_offset + s_range.start();
-                return Some(src_range);
-            }
-        }
-        None
-    }
-}
-
-pub(crate) fn expand_macro_invocation(
-    db: &impl HirDatabase,
-    invoc: MacroCallId,
-) -> Option<Arc<MacroExpansion>> {
-    let loc = invoc.loc(db);
-    let syntax = db.file_item(loc.source_item_id);
-    let syntax = syntax.borrowed();
-    let macro_call = ast::MacroCall::cast(syntax).unwrap();
-
-    let (def, input) = MacroDef::from_call(macro_call)?;
-    def.expand(input).map(Arc::new)
-}
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 89b18194ac..a2507c9b52 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -6,7 +6,7 @@ use ra_db::{LocationIntener, BaseDatabase, FilePosition, FileId, CrateGraph, Sou
 use relative_path::RelativePathBuf;
 use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset};
 
-use crate::{db, DefId, DefLoc, MacroCallId, MacroCallLoc};
+use crate::{db, DefId, DefLoc};
 
 pub const WORKSPACE: SourceRootId = SourceRootId(0);
 
@@ -95,7 +95,6 @@ impl MockDatabase {
 #[derive(Debug, Default)]
 struct IdMaps {
     defs: LocationIntener<DefLoc, DefId>,
-    macros: LocationIntener<MacroCallLoc, MacroCallId>,
 }
 
 impl salsa::Database for MockDatabase {
@@ -145,11 +144,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for MockDatabase {
         &self.id_maps.defs
     }
 }
-impl AsRef<LocationIntener<MacroCallLoc, MacroCallId>> for MockDatabase {
-    fn as_ref(&self) -> &LocationIntener<MacroCallLoc, MacroCallId> {
-        &self.id_maps.macros
-    }
-}
 
 impl MockDatabase {
     pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
@@ -189,8 +183,6 @@ salsa::database_storage! {
             fn file_lines() for ra_db::FileLinesQuery;
         }
         impl db::HirDatabase {
-            fn hir_source_file() for db::HirSourceFileQuery;
-            fn expand_macro_invocation() for db::ExpandMacroCallQuery;
             fn module_tree() for db::ModuleTreeQuery;
             fn fn_scopes() for db::FnScopesQuery;
             fn file_items() for db::SourceFileItemsQuery;
diff --git a/crates/ra_hir/src/module.rs b/crates/ra_hir/src/module.rs
index 26171d27c3..87e30191fb 100644
--- a/crates/ra_hir/src/module.rs
+++ b/crates/ra_hir/src/module.rs
@@ -15,7 +15,6 @@ use relative_path::RelativePathBuf;
 use crate::{
     Def, DefKind, DefLoc, DefId,
     Name, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId, Crate,
-    HirFileId,
     arena::{Arena, Id},
 };
 
@@ -49,17 +48,13 @@ impl Module {
     /// Returns `None` for the root module
     pub fn parent_link_source(&self, db: &impl HirDatabase) -> Option<(FileId, ast::ModuleNode)> {
         let link = self.module_id.parent_link(&self.tree)?;
-        let file_id = link
-            .owner(&self.tree)
-            .source(&self.tree)
-            .file_id()
-            .as_original_file();
+        let file_id = link.owner(&self.tree).source(&self.tree).file_id();
         let src = link.bind_source(&self.tree, db);
         Some((file_id, src))
     }
 
-    pub fn file_id(&self) -> FileId {
-        self.source().file_id().as_original_file()
+    pub fn source(&self) -> ModuleSource {
+        self.module_id.source(&self.tree)
     }
 
     /// Parent module. Returns `None` if this is a root module.
@@ -74,7 +69,7 @@ impl Module {
     /// Returns the crate this module is part of.
     pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> {
         let root_id = self.module_id.crate_root(&self.tree);
-        let file_id = root_id.source(&self.tree).file_id().as_original_file();
+        let file_id = root_id.source(&self.tree).file_id();
         let crate_graph = db.crate_graph();
         let crate_id = crate_graph.crate_id_for_crate_root(file_id)?;
         Some(Crate::new(crate_id))
@@ -167,10 +162,6 @@ impl Module {
     pub fn problems(&self, db: &impl HirDatabase) -> Vec<(SyntaxNode, Problem)> {
         self.module_id.problems(&self.tree, db)
     }
-
-    pub(crate) fn source(&self) -> ModuleSource {
-        self.module_id.source(&self.tree)
-    }
 }
 
 /// Physically, rust source is organized as a set of files, but logically it is
@@ -300,18 +291,18 @@ pub struct ModuleData {
 
 impl ModuleSource {
     // precondition: item_id **must** point to module
-    fn new(file_id: HirFileId, item_id: Option<SourceFileItemId>) -> ModuleSource {
+    fn new(file_id: FileId, item_id: Option<SourceFileItemId>) -> ModuleSource {
         let source_item_id = SourceItemId { file_id, item_id };
         ModuleSource(source_item_id)
     }
 
-    pub(crate) fn new_file(file_id: HirFileId) -> ModuleSource {
+    pub(crate) fn new_file(file_id: FileId) -> ModuleSource {
         ModuleSource::new(file_id, None)
     }
 
     pub(crate) fn new_inline(
         db: &impl HirDatabase,
-        file_id: HirFileId,
+        file_id: FileId,
         m: ast::Module,
     ) -> ModuleSource {
         assert!(!m.has_semi());
@@ -320,7 +311,7 @@ impl ModuleSource {
         ModuleSource::new(file_id, Some(item_id))
     }
 
-    pub(crate) fn file_id(self) -> HirFileId {
+    pub fn file_id(self) -> FileId {
         self.0.file_id
     }
 
diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs
index 3849026dbd..eded85a633 100644
--- a/crates/ra_hir/src/module/imp.rs
+++ b/crates/ra_hir/src/module/imp.rs
@@ -64,7 +64,7 @@ fn create_module_tree<'a>(
 
     let source_root = db.source_root(source_root);
     for &file_id in source_root.files.values() {
-        let source = ModuleSource::new_file(file_id.into());
+        let source = ModuleSource::new_file(file_id);
         if visited.contains(&source) {
             continue; // TODO: use explicit crate_roots here
         }
@@ -123,7 +123,7 @@ fn build_subtree(
                             visited,
                             roots,
                             Some(link),
-                            ModuleSource::new_file(file_id.into()),
+                            ModuleSource::new_file(file_id),
                         ),
                     })
                     .collect::<Cancelable<Vec<_>>>()?;
@@ -155,7 +155,7 @@ fn resolve_submodule(
     name: &Name,
 ) -> (Vec<FileId>, Option<Problem>) {
     // FIXME: handle submodules of inline modules properly
-    let file_id = source.file_id().original_file(db);
+    let file_id = source.file_id();
     let source_root_id = db.file_source_root(file_id);
     let path = db.file_relative_path(file_id);
     let root = RelativePathBuf::default();
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs
index 40aa33ffa7..68eb02a980 100644
--- a/crates/ra_hir/src/module/nameres.rs
+++ b/crates/ra_hir/src/module/nameres.rs
@@ -22,10 +22,10 @@ use ra_syntax::{
     SyntaxKind::{self, *},
     ast::{self, AstNode}
 };
-use ra_db::{SourceRootId, Cancelable, FileId};
+use ra_db::SourceRootId;
 
 use crate::{
-    HirFileId,
+    Cancelable, FileId,
     DefId, DefLoc, DefKind,
     SourceItemId, SourceFileItemId, SourceFileItems,
     Path, PathKind,
@@ -70,7 +70,7 @@ pub struct InputModuleItems {
 
 #[derive(Debug, PartialEq, Eq)]
 struct ModuleItem {
-    id: SourceItemId,
+    id: SourceFileItemId,
     name: Name,
     kind: SyntaxKind,
     vis: Vis,
@@ -95,11 +95,9 @@ pub struct NamedImport {
 }
 
 impl NamedImport {
-    // FIXME: this is only here for one use-case in completion. Seems like a
-    // pretty gross special case.
     pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange {
         let source_item_id = SourceItemId {
-            file_id: file_id.into(),
+            file_id,
             item_id: Some(self.file_item_id),
         };
         let syntax = db.file_item(source_item_id);
@@ -211,28 +209,24 @@ impl<T> PerNs<T> {
 }
 
 impl InputModuleItems {
-    pub(crate) fn add_item(
-        &mut self,
-        file_id: HirFileId,
+    pub(crate) fn new<'a>(
         file_items: &SourceFileItems,
-        item: ast::ModuleItem,
-    ) -> Option<()> {
+        items: impl Iterator<Item = ast::ModuleItem<'a>>,
+    ) -> InputModuleItems {
+        let mut res = InputModuleItems::default();
+        for item in items {
+            res.add_item(file_items, item);
+        }
+        res
+    }
+
+    fn add_item(&mut self, file_items: &SourceFileItems, item: ast::ModuleItem) -> Option<()> {
         match item {
-            ast::ModuleItem::StructDef(it) => {
-                self.items.push(ModuleItem::new(file_id, file_items, it)?)
-            }
-            ast::ModuleItem::EnumDef(it) => {
-                self.items.push(ModuleItem::new(file_id, file_items, it)?)
-            }
-            ast::ModuleItem::FnDef(it) => {
-                self.items.push(ModuleItem::new(file_id, file_items, it)?)
-            }
-            ast::ModuleItem::TraitDef(it) => {
-                self.items.push(ModuleItem::new(file_id, file_items, it)?)
-            }
-            ast::ModuleItem::TypeDef(it) => {
-                self.items.push(ModuleItem::new(file_id, file_items, it)?)
-            }
+            ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
+            ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
+            ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
+            ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
+            ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
             ast::ModuleItem::ImplItem(_) => {
                 // impls don't define items
             }
@@ -240,15 +234,9 @@ impl InputModuleItems {
             ast::ModuleItem::ExternCrateItem(_) => {
                 // TODO
             }
-            ast::ModuleItem::ConstDef(it) => {
-                self.items.push(ModuleItem::new(file_id, file_items, it)?)
-            }
-            ast::ModuleItem::StaticDef(it) => {
-                self.items.push(ModuleItem::new(file_id, file_items, it)?)
-            }
-            ast::ModuleItem::Module(it) => {
-                self.items.push(ModuleItem::new(file_id, file_items, it)?)
-            }
+            ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
+            ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
+            ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(file_items, it)?),
         }
         Some(())
     }
@@ -270,16 +258,11 @@ impl InputModuleItems {
 }
 
 impl ModuleItem {
-    fn new<'a>(
-        file_id: HirFileId,
-        file_items: &SourceFileItems,
-        item: impl ast::NameOwner<'a>,
-    ) -> Option<ModuleItem> {
+    fn new<'a>(file_items: &SourceFileItems, item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
         let name = item.name()?.as_name();
         let kind = item.syntax().kind();
         let vis = Vis::Other;
-        let item_id = Some(file_items.id_of_unchecked(item.syntax()));
-        let id = SourceItemId { file_id, item_id };
+        let id = file_items.id_of_unchecked(item.syntax());
         let res = ModuleItem {
             id,
             name,
@@ -319,7 +302,7 @@ where
 
     pub(crate) fn resolve(mut self) -> Cancelable<ItemMap> {
         for (&module_id, items) in self.input.iter() {
-            self.populate_module(module_id, Arc::clone(items))?;
+            self.populate_module(module_id, items)?;
         }
 
         for &module_id in self.input.keys() {
@@ -329,11 +312,9 @@ where
         Ok(self.result)
     }
 
-    fn populate_module(
-        &mut self,
-        module_id: ModuleId,
-        input: Arc<InputModuleItems>,
-    ) -> Cancelable<()> {
+    fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) -> Cancelable<()> {
+        let file_id = module_id.source(&self.module_tree).file_id();
+
         let mut module_items = ModuleScope::default();
 
         // Populate extern crates prelude
@@ -341,8 +322,7 @@ where
             let root_id = module_id.crate_root(&self.module_tree);
             let file_id = root_id.source(&self.module_tree).file_id();
             let crate_graph = self.db.crate_graph();
-            if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file())
-            {
+            if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id) {
                 let krate = Crate::new(crate_id);
                 for dep in krate.dependencies(self.db) {
                     if let Some(module) = dep.krate.root_module(self.db)? {
@@ -382,7 +362,10 @@ where
                     kind: k,
                     source_root_id: self.source_root,
                     module_id,
-                    source_item_id: item.id,
+                    source_item_id: SourceItemId {
+                        file_id,
+                        item_id: Some(item.id),
+                    },
                 };
                 def_loc.id(self.db)
             });
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index a5d99bedae..721bd4195a 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -8,11 +8,10 @@ use ra_syntax::{
     AstNode, SyntaxNode,
     ast::{self, NameOwner, ModuleItemOwner}
 };
-use ra_db::{SourceRootId, Cancelable,};
+use ra_db::{SourceRootId, FileId, Cancelable,};
 
 use crate::{
-    SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName, HirFileId,
-    MacroCallLoc,
+    SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName,
     db::HirDatabase,
     function::FnScopes,
     module::{
@@ -48,17 +47,25 @@ pub(super) fn enum_data(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<
     Ok(Arc::new(EnumData::new(enum_def.borrowed())))
 }
 
-pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> {
-    let source_file = db.hir_source_file(file_id);
+pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> {
+    let mut res = SourceFileItems::new(file_id);
+    let source_file = db.source_file(file_id);
     let source_file = source_file.borrowed();
-    let res = SourceFileItems::new(file_id, source_file);
+    source_file
+        .syntax()
+        .descendants()
+        .filter_map(ast::ModuleItem::cast)
+        .map(|it| it.syntax().owned())
+        .for_each(|it| {
+            res.alloc(it);
+        });
     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.hir_source_file(source_item_id.file_id).syntax().owned(),
+        None => db.source_file(source_item_id.file_id).syntax().owned(),
     }
 }
 
@@ -80,7 +87,7 @@ pub(crate) fn submodules(
 
     fn collect_submodules<'a>(
         db: &impl HirDatabase,
-        file_id: HirFileId,
+        file_id: FileId,
         root: impl ast::ModuleItemOwner<'a>,
     ) -> Vec<Submodule> {
         modules(root)
@@ -112,48 +119,24 @@ pub(crate) fn modules<'a>(
 
 pub(super) fn input_module_items(
     db: &impl HirDatabase,
-    source_root_id: SourceRootId,
+    source_root: SourceRootId,
     module_id: ModuleId,
 ) -> Cancelable<Arc<InputModuleItems>> {
-    let module_tree = db.module_tree(source_root_id)?;
+    let module_tree = db.module_tree(source_root)?;
     let source = module_id.source(&module_tree);
-    let file_id = source.file_id();
-    let file_items = db.file_items(file_id);
-    let fill = |acc: &mut InputModuleItems, items: &mut Iterator<Item = ast::ItemOrMacro>| {
-        for item in items {
-            match item {
-                ast::ItemOrMacro::Item(it) => {
-                    acc.add_item(file_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 {
-                            file_id,
-                            item_id: Some(item_id),
-                        },
-                    };
-                    let id = loc.id(db);
-                    let file_id = HirFileId::from(id);
-                    let file_items = db.file_items(file_id);
-                    //FIXME: expand recursively
-                    for item in db.hir_source_file(file_id).borrowed().items() {
-                        acc.add_item(file_id, &file_items, item);
-                    }
-                }
-            }
+    let file_items = db.file_items(source.file_id());
+    let res = match source.resolve(db) {
+        ModuleSourceNode::SourceFile(it) => {
+            let items = it.borrowed().items();
+            InputModuleItems::new(&file_items, items)
         }
-    };
-
-    let mut res = InputModuleItems::default();
-    match source.resolve(db) {
-        ModuleSourceNode::SourceFile(it) => fill(&mut res, &mut it.borrowed().items_with_macros()),
         ModuleSourceNode::Module(it) => {
-            if let Some(item_list) = it.borrowed().item_list() {
-                fill(&mut res, &mut item_list.items_with_macros())
-            }
+            let items = it
+                .borrowed()
+                .item_list()
+                .into_iter()
+                .flat_map(|it| it.items());
+            InputModuleItems::new(&file_items, items)
         }
     };
     Ok(Arc::new(res))
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 24490d119c..a0d1daf711 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -20,7 +20,7 @@ use crate::{
 
 /// Locates the module by `FileId`. Picks topmost module in the file.
 pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable<Option<Module>> {
-    let module_source = ModuleSource::new_file(file_id.into());
+    let module_source = ModuleSource::new_file(file_id);
     module_from_source(db, module_source)
 }
 
@@ -50,8 +50,8 @@ pub fn module_from_position(
 ) -> Cancelable<Option<Module>> {
     let file = db.source_file(position.file_id);
     let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) {
-        Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id.into(), m),
-        _ => ModuleSource::new_file(position.file_id.into()),
+        Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m),
+        _ => ModuleSource::new_file(position.file_id),
     };
     module_from_source(db, module_source)
 }
@@ -67,9 +67,9 @@ pub fn module_from_child_node(
         .filter_map(ast::Module::cast)
         .find(|it| !it.has_semi())
     {
-        ModuleSource::new_inline(db, file_id.into(), m)
+        ModuleSource::new_inline(db, file_id, m)
     } else {
-        ModuleSource::new_file(file_id.into())
+        ModuleSource::new_file(file_id)
     };
     module_from_source(db, module_source)
 }
@@ -78,7 +78,7 @@ fn module_from_source(
     db: &impl HirDatabase,
     module_source: ModuleSource,
 ) -> Cancelable<Option<Module>> {
-    let source_root_id = db.file_source_root(module_source.file_id().as_original_file());
+    let source_root_id = db.file_source_root(module_source.file_id());
     let module_tree = db.module_tree(source_root_id)?;
     let m = module_tree
         .modules_with_sources()
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 618486250d..1107ffc8b9 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -2,7 +2,7 @@ use languageserver_types::{
     self, Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier,
     TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, InsertTextFormat,
 };
-use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileEdit, FilePosition,FileRange,  CompletionItem, CompletionItemKind, InsertText};
+use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileEdit, FilePosition,FileRange,  CompletionItem, CompletionItemKind, InsertText, NavigationTarget};
 use ra_editor::{LineCol, LineIndex, translate_offset_with_edit};
 use ra_text_edit::{AtomTextEdit, TextEdit};
 use ra_syntax::{SyntaxKind, TextRange, TextUnit};
@@ -322,6 +322,15 @@ impl TryConvWith for FileSystemEdit {
     }
 }
 
+impl TryConvWith for &NavigationTarget {
+    type Ctx = ServerWorld;
+    type Output = Location;
+    fn try_conv_with(self, world: &ServerWorld) -> Result<Location> {
+        let line_index = world.analysis().file_line_index(self.file_id());
+        to_location(self.file_id(), self.range(), &world, &line_index)
+    }
+}
+
 pub fn to_location(
     file_id: FileId,
     range: TextRange,
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 11825d74e4..26b6c7d8a5 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -188,12 +188,11 @@ pub fn handle_workspace_symbol(
 
     fn exec_query(world: &ServerWorld, query: Query) -> Result<Vec<SymbolInformation>> {
         let mut res = Vec::new();
-        for (file_id, symbol) in world.analysis().symbol_search(query)? {
-            let line_index = world.analysis().file_line_index(file_id);
+        for nav in world.analysis().symbol_search(query)? {
             let info = SymbolInformation {
-                name: symbol.name.to_string(),
-                kind: symbol.kind.conv(),
-                location: to_location(file_id, symbol.node_range, world, &line_index)?,
+                name: nav.name().into(),
+                kind: nav.kind().conv(),
+                location: nav.try_conv_with(world)?,
                 container_name: None,
                 deprecated: None,
             };
@@ -212,12 +211,11 @@ pub fn handle_goto_definition(
         None => return Ok(None),
         Some(it) => it,
     };
-    let mut res = Vec::new();
-    for (file_id, symbol) in rr.resolves_to {
-        let line_index = world.analysis().file_line_index(file_id);
-        let location = to_location(file_id, symbol.node_range, &world, &line_index)?;
-        res.push(location)
-    }
+    let res = rr
+        .resolves_to
+        .into_iter()
+        .map(|nav| nav.try_conv_with(&world))
+        .collect::<Result<Vec<_>>>()?;
     Ok(Some(req::GotoDefinitionResponse::Array(res)))
 }
 
@@ -226,13 +224,12 @@ pub fn handle_parent_module(
     params: req::TextDocumentPositionParams,
 ) -> Result<Vec<Location>> {
     let position = params.try_conv_with(&world)?;
-    let mut res = Vec::new();
-    for (file_id, symbol) in world.analysis().parent_module(position)? {
-        let line_index = world.analysis().file_line_index(file_id);
-        let location = to_location(file_id, symbol.node_range, &world, &line_index)?;
-        res.push(location);
-    }
-    Ok(res)
+    world
+        .analysis()
+        .parent_module(position)?
+        .into_iter()
+        .map(|nav| nav.try_conv_with(&world))
+        .collect::<Result<Vec<_>>>()
 }
 
 pub fn handle_runnables(
@@ -517,8 +514,8 @@ pub fn handle_hover(
         Some(it) => it,
     };
     let mut result = Vec::new();
-    for (file_id, symbol) in rr.resolves_to {
-        if let Some(docs) = world.analysis().doc_text_for(file_id, symbol)? {
+    for nav in rr.resolves_to {
+        if let Some(docs) = world.analysis().doc_text_for(nav)? {
             result.push(docs);
         }
     }
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 3e948800ed..8fb6b64083 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -48,40 +48,10 @@ 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<Self> {
-        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> {
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 6753c513f3..34a3aabef8 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -51,7 +51,7 @@ use ra_text_edit::AtomTextEdit;
 use crate::yellow::GreenNode;
 
 /// `SourceFileNode` represents a parse tree for a single Rust file.
-pub use crate::ast::{SourceFile, SourceFileNode};
+pub use crate::ast::SourceFileNode;
 
 impl SourceFileNode {
     fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SourceFileNode {


Test patch:
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs
index b61ead752c..845fff3c6d 100644
--- a/crates/ra_analysis/tests/tests.rs
+++ b/crates/ra_analysis/tests/tests.rs
@@ -25,7 +25,7 @@ fn approximate_resolve_works_in_items() {
     assert_eq_dbg(
         r#"ReferenceResolution {
             reference_range: [23; 26),
-            resolves_to: [(FileId(1), FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF })]
+            resolves_to: [NavigationTarget { file_id: FileId(1), symbol: FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF } }]
         }"#,
         &symbols,
     );
@@ -46,7 +46,7 @@ fn test_resolve_module() {
     assert_eq_dbg(
         r#"ReferenceResolution {
             reference_range: [4; 7),
-            resolves_to: [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]
+            resolves_to: [NavigationTarget { file_id: FileId(2), symbol: FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE } }]
         }"#,
         &symbols,
     );
@@ -64,7 +64,7 @@ fn test_resolve_module() {
     assert_eq_dbg(
         r#"ReferenceResolution {
             reference_range: [4; 7),
-            resolves_to: [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]
+            resolves_to: [NavigationTarget { file_id: FileId(2), symbol: FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE } }]
         }"#,
         &symbols,
     );
@@ -107,7 +107,7 @@ fn test_resolve_parent_module() {
     );
     let symbols = analysis.parent_module(pos).unwrap();
     assert_eq_dbg(
-        r#"[(FileId(1), FileSymbol { name: "foo", node_range: [4; 7), kind: MODULE })]"#,
+        r#"[NavigationTarget { file_id: FileId(1), symbol: FileSymbol { name: "foo", node_range: [4; 7), kind: MODULE } }]"#,
         &symbols,
     );
 }
@@ -126,7 +126,7 @@ fn test_resolve_parent_module_for_inline() {
     );
     let symbols = analysis.parent_module(pos).unwrap();
     assert_eq_dbg(
-        r#"[(FileId(1), FileSymbol { name: "bar", node_range: [18; 21), kind: MODULE })]"#,
+        r#"[NavigationTarget { file_id: FileId(1), symbol: FileSymbol { name: "bar", node_range: [18; 21), kind: MODULE } }]"#,
         &symbols,
     );
 }
diff --git a/crates/ra_hir/src/module/nameres/tests.rs b/crates/ra_hir/src/module/nameres/tests.rs
index a6a0bea316..ca20f064f1 100644
--- a/crates/ra_hir/src/module/nameres/tests.rs
+++ b/crates/ra_hir/src/module/nameres/tests.rs
@@ -77,35 +77,6 @@ fn item_map_smoke_test() {
     );
 }
 
-#[test]
-fn item_map_contains_items_from_expansions() {
-    let (item_map, module_id) = item_map(
-        "
-        //- /lib.rs
-        mod foo;
-
-        use crate::foo::bar::Baz;
-        <|>
-
-        //- /foo/mod.rs
-        pub mod bar;
-
-        //- /foo/bar.rs
-        salsa::query_group! {
-            trait Baz {}
-        }
-    ",
-    );
-    check_module_item_map(
-        &item_map,
-        module_id,
-        "
-            Baz: t
-            foo: t
-        ",
-    );
-}
-
 #[test]
 fn item_map_using_self() {
     let (item_map, module_id) = item_map(
@@ -170,59 +141,6 @@ fn item_map_across_crates() {
 
 #[test]
 fn typing_inside_a_function_should_not_invalidate_item_map() {
-    let (mut db, pos) = MockDatabase::with_position(
-        "
-        //- /lib.rs
-        mod foo;
-
-        use crate::foo::bar::Baz;
-
-        //- /foo/mod.rs
-        pub mod bar;
-
-        //- /foo/bar.rs
-        <|>
-        salsa::query_group! {
-            trait Baz {
-                fn foo() -> i32 { 1 + 1 }
-            }
-        }
-        ",
-    );
-    let source_root = db.file_source_root(pos.file_id);
-    {
-        let events = db.log_executed(|| {
-            db.item_map(source_root).unwrap();
-        });
-        assert!(format!("{:?}", events).contains("item_map"))
-    }
-
-    let new_text = "
-        salsa::query_group! {
-            trait Baz {
-                fn foo() -> i32 { 92 }
-            }
-        }
-    "
-    .to_string();
-
-    db.query_mut(ra_db::FileTextQuery)
-        .set(pos.file_id, Arc::new(new_text));
-
-    {
-        let events = db.log_executed(|| {
-            db.item_map(source_root).unwrap();
-        });
-        assert!(
-            !format!("{:?}", events).contains("item_map"),
-            "{:#?}",
-            events
-        )
-    }
-}
-
-#[test]
-fn typing_inside_a_function_inside_a_macro_should_not_invalidate_item_map() {
     let (mut db, pos) = MockDatabase::with_position(
         "
         //- /lib.rs
@@ -265,7 +183,7 @@ fn typing_inside_a_function_inside_a_macro_should_not_invalidate_item_map() {
             db.item_map(source_root).unwrap();
         });
         assert!(
-            !format!("{:?}", events).contains("item_map"),
+            !format!("{:?}", events).contains("_item_map"),
             "{:#?}",
             events
         )