diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 0844e1f62549..8fcfad20095f 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -778,36 +778,19 @@ impl<'a> InFile<&'a SyntaxNode> { /// For attributes and derives, this will point back to the attribute only. /// For the entire item `InFile::use original_file_range_full`. pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange { - if let Some(res) = self.original_file_range_opt(db) { - return res; - } - - // Fall back to whole macro call. match self.file_id.0 { 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; + } + // Fall back to whole macro call. let loc = db.lookup_intern_macro_call(mac_file.macro_call_id); loc.kind.original_call_range(db) } } } - /// Falls back to the macro call range if the node cannot be mapped up fully. - pub fn original_file_range_full(self, db: &dyn db::AstDatabase) -> FileRange { - if let Some(res) = self.original_file_range_opt(db) { - return res; - } - - // Fall back to whole macro call. - match self.file_id.0 { - HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() }, - HirFileIdRepr::MacroFile(mac_file) => { - let loc = db.lookup_intern_macro_call(mac_file.macro_call_id); - loc.kind.original_call_range_with_body(db) - } - } - } - /// Attempts to map the syntax node back up its macro calls. pub fn original_file_range_opt(self, db: &dyn db::AstDatabase) -> Option { match ascend_node_border_tokens(db, self) { @@ -834,6 +817,49 @@ impl InFile { let expansion = self.file_id.expansion_info(db)?; expansion.map_token_up(db, self.as_ref()).map(|(it, _)| it) } + + /// Falls back to the macro call range if the node cannot be mapped up fully. + pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange { + match self.file_id.0 { + 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; + } + // Fall back to whole macro call. + let loc = db.lookup_intern_macro_call(mac_file.macro_call_id); + loc.kind.original_call_range(db) + } + } + } + + /// Attempts to map the syntax node back up its macro calls. + pub fn original_file_range_opt(self, db: &dyn db::AstDatabase) -> Option { + match self.file_id.0 { + HirFileIdRepr::FileId(file_id) => { + Some(FileRange { file_id, range: self.value.text_range() }) + } + HirFileIdRepr::MacroFile(_) => { + let expansion = self.file_id.expansion_info(db)?; + let InFile { file_id, value } = ascend_call_token(db, &expansion, self)?; + let original_file = file_id.original_file(db); + if file_id != original_file.into() { + return None; + } + Some(FileRange { file_id: original_file, range: value.text_range() }) + } + } + } + + pub fn ancestors_with_macros( + self, + db: &dyn db::AstDatabase, + ) -> impl Iterator> + '_ { + self.value.parent().into_iter().flat_map({ + let file_id = self.file_id; + move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db) + }) + } } fn ascend_node_border_tokens( @@ -867,18 +893,6 @@ fn ascend_call_token( None } -impl InFile { - pub fn ancestors_with_macros( - self, - db: &dyn db::AstDatabase, - ) -> impl Iterator> + '_ { - self.value.parent().into_iter().flat_map({ - let file_id = self.file_id; - move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db) - }) - } -} - impl InFile { pub fn descendants(self) -> impl Iterator> { self.value.syntax().descendants().filter_map(T::cast).map(move |n| self.with_value(n)) diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index c8650979e95b..061a4813447d 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -176,7 +176,7 @@ fn get_adt_source( adt: &hir::Adt, fn_name: &str, ) -> Option<(Option, FileId)> { - let range = adt.source(ctx.sema.db)?.syntax().original_file_range_full(ctx.sema.db); + let range = adt.source(ctx.sema.db)?.syntax().original_file_range(ctx.sema.db); let file = ctx.sema.parse(range.file_id); let adt_source = ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?; diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index ab614b0ace9f..c857adf876ef 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -198,7 +198,7 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()> let fn_body = fn_source.value.body()?; let param_list = fn_source.value.param_list()?; - let FileRange { file_id, range } = fn_source.syntax().original_file_range_full(ctx.sema.db); + let FileRange { file_id, range } = fn_source.syntax().original_file_range(ctx.sema.db); if file_id == ctx.file_id() && range.contains(ctx.offset()) { cov_mark::hit!(inline_call_recursive); return None; diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index e6bd46347d91..4a11fb73cd6d 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -239,14 +239,14 @@ impl Definition { DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()), }; return match def { - Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)), + Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)), None => SearchScope::single_file(file_id), }; } if let Definition::SelfType(impl_) = self { return match impl_.source(db).map(|src| src.syntax().cloned()) { - Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)), + Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)), None => SearchScope::single_file(file_id), }; } @@ -262,7 +262,7 @@ impl Definition { hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()), }; return match def { - Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)), + Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)), None => SearchScope::single_file(file_id), }; } diff --git a/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs b/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs index fde3901a730b..760f51f90498 100644 --- a/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs +++ b/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs @@ -1,4 +1,5 @@ use hir::db::DefDatabase; +use syntax::NodeOrToken; use crate::{Diagnostic, DiagnosticsContext, Severity}; @@ -18,9 +19,16 @@ pub(crate) fn unresolved_proc_macro( proc_attr_macros_enabled: bool, ) -> Diagnostic { // Use more accurate position if available. - let display_range = d - .precise_location - .unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone()).range); + let display_range = (|| { + let precise_location = d.precise_location?; + let root = ctx.sema.parse_or_expand(d.node.file_id)?; + match root.covering_element(precise_location) { + NodeOrToken::Node(it) => Some(ctx.sema.original_range(&it)), + NodeOrToken::Token(it) => d.node.with_value(it).original_file_range_opt(ctx.sema.db), + } + })() + .unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone())) + .range; let config_enabled = match d.kind { hir::MacroKind::Attr => proc_macros_enabled && proc_attr_macros_enabled,