Skip to content

Commit

Permalink
Auto merge of #16035 - Veykril:macro-diagnostics, r=Veykril
Browse files Browse the repository at this point in the history
fix: Fix diagnostics panicking when resolving to different files due to macros

Fixes #14968
  • Loading branch information
bors committed Dec 6, 2023
2 parents cc8faa6 + ba01ff4 commit 77e362c
Show file tree
Hide file tree
Showing 28 changed files with 294 additions and 252 deletions.
52 changes: 29 additions & 23 deletions crates/hir-def/src/macro_expansion_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::{iter, ops::Range, sync};

use base_db::{fixture::WithFixture, span::SpanData, ProcMacro, SourceDatabase};
use expect_test::Expect;
use hir_expand::{db::ExpandDatabase, span::SpanMapRef, HirFileIdExt, InFile, MacroFileId};
use hir_expand::{db::ExpandDatabase, span::SpanMapRef, InFile, MacroFileId, MacroFileIdExt};
use stdx::format_to;
use syntax::{
ast::{self, edit::IndentLevel},
Expand Down Expand Up @@ -172,35 +172,41 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
};

if let Some(src) = src {
if src.file_id.is_attr_macro(&db) || src.file_id.is_custom_derive(&db) {
let call = src.file_id.call_node(&db).expect("macro file");
let mut show_spans = false;
let mut show_ctxt = false;
for comment in call.value.children_with_tokens().filter(|it| it.kind() == COMMENT) {
show_spans |= comment.to_string().contains("+spans");
show_ctxt |= comment.to_string().contains("+syntaxctxt");
if let Some(file_id) = src.file_id.macro_file() {
if file_id.is_attr_macro(&db) || file_id.is_custom_derive(&db) {
let call = file_id.call_node(&db);
let mut show_spans = false;
let mut show_ctxt = false;
for comment in
call.value.children_with_tokens().filter(|it| it.kind() == COMMENT)
{
show_spans |= comment.to_string().contains("+spans");
show_ctxt |= comment.to_string().contains("+syntaxctxt");
}
let pp = pretty_print_macro_expansion(
src.value,
db.span_map(src.file_id).as_ref(),
show_spans,
show_ctxt,
);
format_to!(expanded_text, "\n{}", pp)
}
let pp = pretty_print_macro_expansion(
src.value,
db.span_map(src.file_id).as_ref(),
show_spans,
show_ctxt,
);
format_to!(expanded_text, "\n{}", pp)
}
}
}

for impl_id in def_map[local_id].scope.impls() {
let src = impl_id.lookup(&db).source(&db);
if src.file_id.is_builtin_derive(&db) {
let pp = pretty_print_macro_expansion(
src.value.syntax().clone(),
db.span_map(src.file_id).as_ref(),
false,
false,
);
format_to!(expanded_text, "\n{}", pp)
if let Some(macro_file) = src.file_id.macro_file() {
if macro_file.is_builtin_derive(&db) {
let pp = pretty_print_macro_expansion(
src.value.syntax().clone(),
db.span_map(macro_file.into()).as_ref(),
false,
false,
);
format_to!(expanded_text, "\n{}", pp)
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/hir-def/src/nameres/mod_resolution.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! This module resolves `mod foo;` declaration to file.
use arrayvec::ArrayVec;
use base_db::{AnchoredPath, FileId};
use hir_expand::{name::Name, HirFileIdExt};
use hir_expand::{name::Name, HirFileIdExt, MacroFileIdExt};
use limit::Limit;
use syntax::SmolStr;

Expand Down Expand Up @@ -73,7 +73,7 @@ impl ModDir {
Some(attr_path) => {
candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner))
}
None if file_id.is_include_macro(db.upcast()) => {
None if file_id.macro_file().map_or(false, |it| it.is_include_macro(db.upcast())) => {
candidate_files.push(format!("{}.rs", name.display(db.upcast())));
candidate_files.push(format!("{}/mod.rs", name.display(db.upcast())));
}
Expand Down
52 changes: 19 additions & 33 deletions crates/hir-expand/src/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use base_db::{
FileId, FileRange,
};
use either::Either;
use syntax::{AstNode, SyntaxNode, SyntaxToken, TextRange};
use syntax::{AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize};

use crate::{db, ExpansionInfo, HirFileIdExt as _};
use crate::{db, ExpansionInfo, MacroFileIdExt};

/// `InFile<T>` stores a value of `T` inside a particular file/syntax tree.
///
Expand Down Expand Up @@ -119,16 +119,6 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
// region:specific impls

impl InFile<&SyntaxNode> {
pub fn ancestors_with_macros(
self,
db: &dyn db::ExpandDatabase,
) -> impl Iterator<Item = InFile<SyntaxNode>> + Clone + '_ {
iter::successors(Some(self.cloned()), move |node| match node.value.parent() {
Some(parent) => Some(node.with_value(parent)),
None => node.file_id.call_node(db),
})
}

/// Skips the attributed item that caused the macro invocation we are climbing up
pub fn ancestors_with_macros_skip_attr_item(
self,
Expand All @@ -137,8 +127,9 @@ impl InFile<&SyntaxNode> {
let succ = move |node: &InFile<SyntaxNode>| match node.value.parent() {
Some(parent) => Some(node.with_value(parent)),
None => {
let parent_node = node.file_id.call_node(db)?;
if node.file_id.is_attr_macro(db) {
let macro_file_id = node.file_id.macro_file()?;
let parent_node = macro_file_id.call_node(db);
if macro_file_id.is_attr_macro(db) {
// macro call was an attributed item, skip it
// FIXME: does this fail if this is a direct expansion of another macro?
parent_node.map(|node| node.parent()).transpose()
Expand Down Expand Up @@ -222,7 +213,7 @@ impl InFile<&SyntaxNode> {
}
HirFileIdRepr::MacroFile(m) => m,
};
if !self.file_id.is_attr_macro(db) {
if !file_id.is_attr_macro(db) {
return None;
}

Expand All @@ -243,21 +234,23 @@ impl InFile<&SyntaxNode> {
}
}

impl InFile<SyntaxToken> {
impl InMacroFile<SyntaxToken> {
pub fn upmap_once(
self,
db: &dyn db::ExpandDatabase,
) -> Option<InFile<smallvec::SmallVec<[TextRange; 1]>>> {
Some(self.file_id.expansion_info(db)?.map_range_up_once(db, self.value.text_range()))
) -> InFile<smallvec::SmallVec<[TextRange; 1]>> {
self.file_id.expansion_info(db).map_range_up_once(db, self.value.text_range())
}
}

impl InFile<SyntaxToken> {
/// Falls back to the macro call range if the node cannot be mapped up fully.
pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> FileRange {
match self.file_id.repr() {
HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
HirFileIdRepr::MacroFile(mac_file) => {
let (range, ctxt) = ExpansionInfo::new(db, mac_file)
.map_token_range_up(db, self.value.text_range());
.span_for_offset(db, self.value.text_range().start());

// FIXME: Figure out an API that makes proper use of ctx, this only exists to
// keep pre-token map rewrite behaviour.
Expand All @@ -280,7 +273,7 @@ impl InFile<SyntaxToken> {
}
HirFileIdRepr::MacroFile(mac_file) => {
let (range, ctxt) = ExpansionInfo::new(db, mac_file)
.map_token_range_up(db, self.value.text_range());
.span_for_offset(db, self.value.text_range().start());

// FIXME: Figure out an API that makes proper use of ctx, this only exists to
// keep pre-token map rewrite behaviour.
Expand All @@ -294,20 +287,13 @@ 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) = 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 InMacroFile<TextSize> {
pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> (FileRange, SyntaxContextId) {
ExpansionInfo::new(db, self.file_id).span_for_offset(db, self.value)
}
}

impl InFile<TextRange> {
pub fn original_node_file_range(
self,
db: &dyn db::ExpandDatabase,
Expand Down Expand Up @@ -353,7 +339,7 @@ impl<N: AstNode> InFile<N> {
}
HirFileIdRepr::MacroFile(m) => m,
};
if !self.file_id.is_attr_macro(db) {
if !file_id.is_attr_macro(db) {
return None;
}

Expand Down
Loading

0 comments on commit 77e362c

Please sign in to comment.