about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-expand/src/files.rs79
-rw-r--r--crates/hir-expand/src/lib.rs13
-rw-r--r--crates/ide-assists/src/handlers/remove_unused_imports.rs4
-rw-r--r--crates/ide-db/src/search.rs7
-rw-r--r--crates/ide/src/navigation_target.rs9
5 files changed, 64 insertions, 48 deletions
diff --git a/crates/hir-expand/src/files.rs b/crates/hir-expand/src/files.rs
index 36eb2dbb27c..ed8639d7a1d 100644
--- a/crates/hir-expand/src/files.rs
+++ b/crates/hir-expand/src/files.rs
@@ -83,26 +83,41 @@ impl<FileKind, L, R> InFileWrapper<FileKind, Either<L, R>> {
 
 // endregion:transpose impls
 
-// region:specific impls
+trait FileIdToSyntax: Copy {
+    fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode;
+}
 
-impl<T> InFile<T> {
-    pub fn file_syntax(&self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
-        db.parse_or_expand(self.file_id)
+impl FileIdToSyntax for FileId {
+    fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
+        db.parse(self).syntax_node()
+    }
+}
+impl FileIdToSyntax for MacroFileId {
+    fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
+        db.parse_macro_expansion(self).value.0.syntax_node()
+    }
+}
+impl FileIdToSyntax for HirFileId {
+    fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
+        db.parse_or_expand(self)
     }
 }
 
-impl<T> InRealFile<T> {
+#[allow(private_bounds)]
+impl<FileId: FileIdToSyntax, T> InFileWrapper<FileId, T> {
     pub fn file_syntax(&self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
-        db.parse(self.file_id).syntax_node()
+        FileIdToSyntax::file_syntax(self.file_id, db)
     }
 }
 
-impl<T> InMacroFile<T> {
-    pub fn file_syntax(&self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
-        db.parse_macro_expansion(self.file_id).value.0.syntax_node()
+impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
+    pub fn syntax(&self) -> InFileWrapper<FileId, &SyntaxNode> {
+        self.with_value(self.value.syntax())
     }
 }
 
+// region:specific impls
+
 impl InFile<&SyntaxNode> {
     pub fn ancestors_with_macros(
         self,
@@ -241,9 +256,15 @@ impl InFile<SyntaxToken> {
         match self.file_id.repr() {
             HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
             HirFileIdRepr::MacroFile(mac_file) => {
-                if let Some(res) = self.original_file_range_opt(db) {
-                    return res;
+                let (range, ctxt) = ExpansionInfo::new(db, mac_file)
+                    .map_token_range_up(db, self.value.text_range());
+
+                // FIXME: Figure out an API that makes proper use of ctx, this only exists to
+                // keep pre-token map rewrite behaviour.
+                if ctxt.is_root() {
+                    return range;
                 }
+
                 // Fall back to whole macro call.
                 let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
                 loc.kind.original_call_range(db)
@@ -257,8 +278,9 @@ impl InFile<SyntaxToken> {
             HirFileIdRepr::FileId(file_id) => {
                 Some(FileRange { file_id, range: self.value.text_range() })
             }
-            HirFileIdRepr::MacroFile(_) => {
-                let (range, ctxt) = ascend_range_up_macros(db, self.map(|it| it.text_range()));
+            HirFileIdRepr::MacroFile(mac_file) => {
+                let (range, ctxt) = ExpansionInfo::new(db, mac_file)
+                    .map_token_range_up(db, self.value.text_range());
 
                 // FIXME: Figure out an API that makes proper use of ctx, this only exists to
                 // keep pre-token map rewrite behaviour.
@@ -275,16 +297,19 @@ impl InFile<SyntaxToken> {
 impl InFile<TextRange> {
     /// Attempts to map the syntax node back up its macro calls.
     pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> FileRange {
-        let (range, _ctxt) = ascend_range_up_macros(db, self);
+        let (range, _ctxt) = match self.file_id.repr() {
+            HirFileIdRepr::FileId(file_id) => {
+                (FileRange { file_id, range: self.value }, SyntaxContextId::ROOT)
+            }
+            HirFileIdRepr::MacroFile(m) => {
+                ExpansionInfo::new(db, m).map_token_range_up(db, self.value)
+            }
+        };
         range
     }
 }
 
 impl<N: AstNode> InFile<N> {
-    pub fn descendants<T: AstNode>(self) -> impl Iterator<Item = InFile<T>> {
-        self.value.syntax().descendants().filter_map(T::cast).map(move |n| self.with_value(n))
-    }
-
     pub fn original_ast_node(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<N>> {
         // This kind of upmapping can only be achieved in attribute expanded files,
         // as we don't have node inputs otherwise and therefore can't find an `N` node in the input
@@ -312,22 +337,4 @@ impl<N: AstNode> InFile<N> {
         let value = anc.ancestors().find_map(N::cast)?;
         Some(InRealFile::new(file_id, value))
     }
-
-    pub fn syntax(&self) -> InFile<&SyntaxNode> {
-        self.with_value(self.value.syntax())
-    }
-}
-
-fn ascend_range_up_macros(
-    db: &dyn db::ExpandDatabase,
-    range: InFile<TextRange>,
-) -> (FileRange, SyntaxContextId) {
-    match range.file_id.repr() {
-        HirFileIdRepr::FileId(file_id) => {
-            (FileRange { file_id, range: range.value }, SyntaxContextId::ROOT)
-        }
-        HirFileIdRepr::MacroFile(m) => {
-            ExpansionInfo::new(db, m).map_token_range_up(db, range.value)
-        }
-    }
 }
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index f328431372e..1d5b7dfa594 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -172,17 +172,18 @@ pub enum MacroCallKind {
 }
 
 pub trait HirFileIdExt {
-    /// For macro-expansion files, returns the file original source file the
-    /// expansion originated from.
+    /// Returns the original file of this macro call hierarchy.
     fn original_file(self, db: &dyn db::ExpandDatabase) -> FileId;
 
+    /// Returns the original file of this macro call hierarchy while going into the included file if
+    /// one of the calls comes from an `include!``.
     fn original_file_respecting_includes(self, db: &dyn db::ExpandDatabase) -> FileId;
 
     /// If this is a macro call, returns the syntax node of the call.
     fn call_node(self, db: &dyn db::ExpandDatabase) -> Option<InFile<SyntaxNode>>;
 
     /// If this is a macro call, returns the syntax node of the very first macro call this file resides in.
-    fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option<(FileId, SyntaxNode)>;
+    fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<SyntaxNode>>;
 
     /// Return expansion information if it is a macro-expansion file
     fn expansion_info(self, db: &dyn db::ExpandDatabase) -> Option<ExpansionInfo>;
@@ -246,11 +247,13 @@ impl HirFileIdExt for HirFileId {
         Some(loc.to_node(db))
     }
 
-    fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option<(FileId, SyntaxNode)> {
+    fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<SyntaxNode>> {
         let mut call = db.lookup_intern_macro_call(self.macro_file()?.macro_call_id).to_node(db);
         loop {
             match call.file_id.repr() {
-                HirFileIdRepr::FileId(file_id) => break Some((file_id, call.value)),
+                HirFileIdRepr::FileId(file_id) => {
+                    break Some(InRealFile { file_id, value: call.value })
+                }
                 HirFileIdRepr::MacroFile(MacroFileId { macro_call_id }) => {
                     call = db.lookup_intern_macro_call(macro_call_id).to_node(db);
                 }
diff --git a/crates/ide-assists/src/handlers/remove_unused_imports.rs b/crates/ide-assists/src/handlers/remove_unused_imports.rs
index 10076e60c3e..ee44064e7c5 100644
--- a/crates/ide-assists/src/handlers/remove_unused_imports.rs
+++ b/crates/ide-assists/src/handlers/remove_unused_imports.rs
@@ -1,6 +1,6 @@
 use std::collections::{hash_map::Entry, HashMap};
 
-use hir::{HirFileIdExt, InFile, Module, ModuleSource};
+use hir::{HirFileIdExt, InFile, InRealFile, Module, ModuleSource};
 use ide_db::{
     base_db::FileRange,
     defs::Definition,
@@ -167,7 +167,7 @@ fn used_once_in_scope(ctx: &AssistContext<'_>, def: Definition, scopes: &Vec<Sea
 fn module_search_scope(db: &RootDatabase, module: hir::Module) -> Vec<SearchScope> {
     let (file_id, range) = {
         let InFile { file_id, value } = module.definition_source(db);
-        if let Some((file_id, call_source)) = file_id.original_call_node(db) {
+        if let Some(InRealFile { file_id, value: call_source }) = file_id.original_call_node(db) {
             (file_id, Some(call_source.text_range()))
         } else {
             (
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 68f2ad49457..2ce036c044a 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -8,8 +8,8 @@ use std::mem;
 
 use base_db::{salsa::Database, FileId, FileRange, SourceDatabase, SourceDatabaseExt};
 use hir::{
-    AsAssocItem, DefWithBody, HasAttrs, HasSource, HirFileIdExt, InFile, ModuleSource, Semantics,
-    Visibility,
+    AsAssocItem, DefWithBody, HasAttrs, HasSource, HirFileIdExt, InFile, InRealFile, ModuleSource,
+    Semantics, Visibility,
 };
 use memchr::memmem::Finder;
 use nohash_hasher::IntMap;
@@ -133,7 +133,8 @@ impl SearchScope {
 
         let (file_id, range) = {
             let InFile { file_id, value } = module.definition_source(db);
-            if let Some((file_id, call_source)) = file_id.original_call_node(db) {
+            if let Some(InRealFile { file_id, value: call_source }) = file_id.original_call_node(db)
+            {
                 (file_id, Some(call_source.text_range()))
             } else {
                 (
diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs
index 1e4d0e8cdc6..df0c4a6adee 100644
--- a/crates/ide/src/navigation_target.rs
+++ b/crates/ide/src/navigation_target.rs
@@ -169,8 +169,13 @@ impl TryToNav for FileSymbol {
     fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
         let full_range = self.loc.original_range(db);
         let focus_range = self.loc.original_name_range(db);
-        let focus_range =
-            if focus_range.file_id == full_range.file_id { Some(focus_range.range) } else { None };
+        let focus_range = if focus_range.file_id == full_range.file_id
+            && full_range.range.contains_range(focus_range.range)
+        {
+            Some(focus_range.range)
+        } else {
+            None
+        };
 
         Some(NavigationTarget {
             file_id: full_range.file_id,