Skip to content

Commit 976d07e

Browse files
committed
fix: Fix unresolved proc macro diagnostics pointing to macro expansions
1 parent ed44fe5 commit 976d07e

File tree

5 files changed

+63
-41
lines changed

5 files changed

+63
-41
lines changed

crates/hir-expand/src/lib.rs

+47-33
Original file line numberDiff line numberDiff line change
@@ -778,36 +778,19 @@ impl<'a> InFile<&'a SyntaxNode> {
778778
/// For attributes and derives, this will point back to the attribute only.
779779
/// For the entire item `InFile::use original_file_range_full`.
780780
pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange {
781-
if let Some(res) = self.original_file_range_opt(db) {
782-
return res;
783-
}
784-
785-
// Fall back to whole macro call.
786781
match self.file_id.0 {
787782
HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
788783
HirFileIdRepr::MacroFile(mac_file) => {
784+
if let Some(res) = self.original_file_range_opt(db) {
785+
return res;
786+
}
787+
// Fall back to whole macro call.
789788
let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
790789
loc.kind.original_call_range(db)
791790
}
792791
}
793792
}
794793

795-
/// Falls back to the macro call range if the node cannot be mapped up fully.
796-
pub fn original_file_range_full(self, db: &dyn db::AstDatabase) -> FileRange {
797-
if let Some(res) = self.original_file_range_opt(db) {
798-
return res;
799-
}
800-
801-
// Fall back to whole macro call.
802-
match self.file_id.0 {
803-
HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
804-
HirFileIdRepr::MacroFile(mac_file) => {
805-
let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
806-
loc.kind.original_call_range_with_body(db)
807-
}
808-
}
809-
}
810-
811794
/// Attempts to map the syntax node back up its macro calls.
812795
pub fn original_file_range_opt(self, db: &dyn db::AstDatabase) -> Option<FileRange> {
813796
match ascend_node_border_tokens(db, self) {
@@ -834,6 +817,49 @@ impl InFile<SyntaxToken> {
834817
let expansion = self.file_id.expansion_info(db)?;
835818
expansion.map_token_up(db, self.as_ref()).map(|(it, _)| it)
836819
}
820+
821+
/// Falls back to the macro call range if the node cannot be mapped up fully.
822+
pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange {
823+
match self.file_id.0 {
824+
HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
825+
HirFileIdRepr::MacroFile(mac_file) => {
826+
if let Some(res) = self.original_file_range_opt(db) {
827+
return res;
828+
}
829+
// Fall back to whole macro call.
830+
let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
831+
loc.kind.original_call_range(db)
832+
}
833+
}
834+
}
835+
836+
/// Attempts to map the syntax node back up its macro calls.
837+
pub fn original_file_range_opt(self, db: &dyn db::AstDatabase) -> Option<FileRange> {
838+
match self.file_id.0 {
839+
HirFileIdRepr::FileId(file_id) => {
840+
Some(FileRange { file_id, range: self.value.text_range() })
841+
}
842+
HirFileIdRepr::MacroFile(_) => {
843+
let expansion = self.file_id.expansion_info(db)?;
844+
let InFile { file_id, value } = ascend_call_token(db, &expansion, self)?;
845+
let original_file = file_id.original_file(db);
846+
if file_id != original_file.into() {
847+
return None;
848+
}
849+
Some(FileRange { file_id: original_file, range: value.text_range() })
850+
}
851+
}
852+
}
853+
854+
pub fn ancestors_with_macros(
855+
self,
856+
db: &dyn db::AstDatabase,
857+
) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
858+
self.value.parent().into_iter().flat_map({
859+
let file_id = self.file_id;
860+
move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db)
861+
})
862+
}
837863
}
838864

839865
fn ascend_node_border_tokens(
@@ -867,18 +893,6 @@ fn ascend_call_token(
867893
None
868894
}
869895

870-
impl InFile<SyntaxToken> {
871-
pub fn ancestors_with_macros(
872-
self,
873-
db: &dyn db::AstDatabase,
874-
) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
875-
self.value.parent().into_iter().flat_map({
876-
let file_id = self.file_id;
877-
move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db)
878-
})
879-
}
880-
}
881-
882896
impl<N: AstNode> InFile<N> {
883897
pub fn descendants<T: AstNode>(self) -> impl Iterator<Item = InFile<T>> {
884898
self.value.syntax().descendants().filter_map(T::cast).map(move |n| self.with_value(n))

crates/ide-assists/src/handlers/generate_function.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ fn get_adt_source(
176176
adt: &hir::Adt,
177177
fn_name: &str,
178178
) -> Option<(Option<ast::Impl>, FileId)> {
179-
let range = adt.source(ctx.sema.db)?.syntax().original_file_range_full(ctx.sema.db);
179+
let range = adt.source(ctx.sema.db)?.syntax().original_file_range(ctx.sema.db);
180180
let file = ctx.sema.parse(range.file_id);
181181
let adt_source =
182182
ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?;

crates/ide-assists/src/handlers/inline_call.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
198198
let fn_body = fn_source.value.body()?;
199199
let param_list = fn_source.value.param_list()?;
200200

201-
let FileRange { file_id, range } = fn_source.syntax().original_file_range_full(ctx.sema.db);
201+
let FileRange { file_id, range } = fn_source.syntax().original_file_range(ctx.sema.db);
202202
if file_id == ctx.file_id() && range.contains(ctx.offset()) {
203203
cov_mark::hit!(inline_call_recursive);
204204
return None;

crates/ide-db/src/search.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,14 @@ impl Definition {
239239
DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
240240
};
241241
return match def {
242-
Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)),
242+
Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
243243
None => SearchScope::single_file(file_id),
244244
};
245245
}
246246

247247
if let Definition::SelfType(impl_) = self {
248248
return match impl_.source(db).map(|src| src.syntax().cloned()) {
249-
Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)),
249+
Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
250250
None => SearchScope::single_file(file_id),
251251
};
252252
}
@@ -262,7 +262,7 @@ impl Definition {
262262
hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()),
263263
};
264264
return match def {
265-
Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)),
265+
Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
266266
None => SearchScope::single_file(file_id),
267267
};
268268
}

crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use hir::db::DefDatabase;
2+
use syntax::NodeOrToken;
23

34
use crate::{Diagnostic, DiagnosticsContext, Severity};
45

@@ -18,9 +19,16 @@ pub(crate) fn unresolved_proc_macro(
1819
proc_attr_macros_enabled: bool,
1920
) -> Diagnostic {
2021
// Use more accurate position if available.
21-
let display_range = d
22-
.precise_location
23-
.unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone()).range);
22+
let display_range = (|| {
23+
let precise_location = d.precise_location?;
24+
let root = ctx.sema.parse_or_expand(d.node.file_id)?;
25+
match root.covering_element(precise_location) {
26+
NodeOrToken::Node(it) => Some(ctx.sema.original_range(&it)),
27+
NodeOrToken::Token(it) => d.node.with_value(it).original_file_range_opt(ctx.sema.db),
28+
}
29+
})()
30+
.unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone()))
31+
.range;
2432

2533
let config_enabled = match d.kind {
2634
hir::MacroKind::Attr => proc_macros_enabled && proc_attr_macros_enabled,

0 commit comments

Comments
 (0)