Skip to content

Commit 241b9f9

Browse files
committed
Auto merge of rust-lang#12103 - jonas-schievink:diagnose-unresolved-derives, r=jonas-schievink
feat: diagnose unresolved derive macros ![screenshot-2022-04-27-20:04:59](https://user-images.githubusercontent.com/1786438/165591059-c759f035-2400-4bb1-84b0-9332e86c65d5.png)
2 parents 361cddc + fa42888 commit 241b9f9

File tree

6 files changed

+44
-19
lines changed

6 files changed

+44
-19
lines changed

crates/hir/src/diagnostics.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ pub struct UnresolvedImport {
6767

6868
#[derive(Debug, Clone, Eq, PartialEq)]
6969
pub struct UnresolvedMacroCall {
70-
pub macro_call: InFile<AstPtr<ast::MacroCall>>,
70+
pub macro_call: InFile<SyntaxNodePtr>,
7171
pub path: ModPath,
72+
pub is_bang: bool,
7273
}
7374

7475
#[derive(Debug, Clone, Eq, PartialEq)]

crates/hir/src/lib.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -701,8 +701,9 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
701701
let node = ast.to_node(db.upcast());
702702
acc.push(
703703
UnresolvedMacroCall {
704-
macro_call: InFile::new(ast.file_id, AstPtr::new(&node)),
704+
macro_call: InFile::new(node.file_id, SyntaxNodePtr::new(&node.value)),
705705
path: path.clone(),
706+
is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
706707
}
707708
.into(),
708709
);
@@ -1170,7 +1171,12 @@ impl DefWithBody {
11701171
.into(),
11711172
),
11721173
BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push(
1173-
UnresolvedMacroCall { macro_call: node.clone(), path: path.clone() }.into(),
1174+
UnresolvedMacroCall {
1175+
macro_call: node.clone().map(|ast_ptr| ast_ptr.into()),
1176+
path: path.clone(),
1177+
is_bang: true,
1178+
}
1179+
.into(),
11741180
),
11751181
}
11761182
}

crates/hir_def/src/attr.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -813,12 +813,15 @@ impl Attr {
813813
let paths = args
814814
.token_trees
815815
.split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))))
816-
.map(|tts| {
816+
.filter_map(|tts| {
817+
if tts.is_empty() {
818+
return None;
819+
}
817820
let segments = tts.iter().filter_map(|tt| match tt {
818821
tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
819822
_ => None,
820823
});
821-
ModPath::from_segments(PathKind::Plain, segments)
824+
Some(ModPath::from_segments(PathKind::Plain, segments))
822825
});
823826

824827
Some(paths)

crates/hir_def/src/nameres/collector.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -1359,13 +1359,24 @@ impl DefCollector<'_> {
13591359
if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
13601360
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
13611361
directive.module_id,
1362-
ast_id.ast_id,
1362+
MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: *expand_to },
13631363
path,
13641364
));
13651365
}
13661366
}
1367-
MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
1368-
// FIXME: we might want to diagnose this too
1367+
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
1368+
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1369+
directive.module_id,
1370+
MacroCallKind::Derive {
1371+
ast_id: ast_id.ast_id,
1372+
derive_attr_index: derive_attr.ast_index,
1373+
derive_index: *derive_pos as u32,
1374+
},
1375+
ast_id.path.clone(),
1376+
));
1377+
}
1378+
MacroDirectiveKind::Attr { .. } => {
1379+
// FIXME: these should get diagnosed by `reseed_with_unresolved_attribute`
13691380
}
13701381
}
13711382
}

crates/hir_def/src/nameres/diagnostics.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub enum DefDiagnosticKind {
2525

2626
UnresolvedProcMacro { ast: MacroCallKind },
2727

28-
UnresolvedMacroCall { ast: AstId<ast::MacroCall>, path: ModPath },
28+
UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
2929

3030
MacroError { ast: MacroCallKind, message: String },
3131

@@ -95,7 +95,7 @@ impl DefDiagnostic {
9595

9696
pub(super) fn unresolved_macro_call(
9797
container: LocalModuleId,
98-
ast: AstId<ast::MacroCall>,
98+
ast: MacroCallKind,
9999
path: ModPath,
100100
) -> Self {
101101
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } }

crates/ide_diagnostics/src/handlers/unresolved_macro_call.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use hir::{db::AstDatabase, InFile};
2-
use syntax::{AstNode, SyntaxNodePtr};
2+
use syntax::{ast, AstNode, SyntaxNodePtr};
33

44
use crate::{Diagnostic, DiagnosticsContext};
55

@@ -12,19 +12,23 @@ pub(crate) fn unresolved_macro_call(
1212
d: &hir::UnresolvedMacroCall,
1313
) -> Diagnostic {
1414
let last_path_segment = ctx.sema.db.parse_or_expand(d.macro_call.file_id).and_then(|root| {
15-
d.macro_call
16-
.value
17-
.to_node(&root)
18-
.path()
19-
.and_then(|it| it.segment())
20-
.and_then(|it| it.name_ref())
21-
.map(|it| InFile::new(d.macro_call.file_id, SyntaxNodePtr::new(it.syntax())))
15+
let node = d.macro_call.value.to_node(&root);
16+
if let Some(macro_call) = ast::MacroCall::cast(node) {
17+
macro_call
18+
.path()
19+
.and_then(|it| it.segment())
20+
.and_then(|it| it.name_ref())
21+
.map(|it| InFile::new(d.macro_call.file_id, SyntaxNodePtr::new(it.syntax())))
22+
} else {
23+
None
24+
}
2225
});
2326
let diagnostics = last_path_segment.unwrap_or_else(|| d.macro_call.clone().map(|it| it.into()));
2427

28+
let bang = if d.is_bang { "!" } else { "" };
2529
Diagnostic::new(
2630
"unresolved-macro-call",
27-
format!("unresolved macro `{}!`", d.path),
31+
format!("unresolved macro `{}{}`", d.path, bang),
2832
ctx.sema.diagnostics_display_range(diagnostics).range,
2933
)
3034
.experimental()

0 commit comments

Comments
 (0)