Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #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)
bors 2022-04-28
parent 361cddc · parent fa42888 · commit 241b9f9
-rw-r--r--crates/hir/src/diagnostics.rs3
-rw-r--r--crates/hir/src/lib.rs10
-rw-r--r--crates/hir_def/src/attr.rs7
-rw-r--r--crates/hir_def/src/nameres/collector.rs17
-rw-r--r--crates/hir_def/src/nameres/diagnostics.rs4
-rw-r--r--crates/ide_diagnostics/src/handlers/unresolved_macro_call.rs22
6 files changed, 44 insertions, 19 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index bc43fb15ee..08e239804c 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -67,8 +67,9 @@ pub struct UnresolvedImport {
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct UnresolvedMacroCall {
- pub macro_call: InFile<AstPtr<ast::MacroCall>>,
+ pub macro_call: InFile<SyntaxNodePtr>,
pub path: ModPath,
+ pub is_bang: bool,
}
#[derive(Debug, Clone, Eq, PartialEq)]
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 382d1f9a54..2d73168727 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -701,8 +701,9 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
let node = ast.to_node(db.upcast());
acc.push(
UnresolvedMacroCall {
- macro_call: InFile::new(ast.file_id, AstPtr::new(&node)),
+ macro_call: InFile::new(node.file_id, SyntaxNodePtr::new(&node.value)),
path: path.clone(),
+ is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
}
.into(),
);
@@ -1170,7 +1171,12 @@ impl DefWithBody {
.into(),
),
BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push(
- UnresolvedMacroCall { macro_call: node.clone(), path: path.clone() }.into(),
+ UnresolvedMacroCall {
+ macro_call: node.clone().map(|ast_ptr| ast_ptr.into()),
+ path: path.clone(),
+ is_bang: true,
+ }
+ .into(),
),
}
}
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 81054f83b0..11d3f48b94 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -813,12 +813,15 @@ impl Attr {
let paths = args
.token_trees
.split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))))
- .map(|tts| {
+ .filter_map(|tts| {
+ if tts.is_empty() {
+ return None;
+ }
let segments = tts.iter().filter_map(|tt| match tt {
tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
_ => None,
});
- ModPath::from_segments(PathKind::Plain, segments)
+ Some(ModPath::from_segments(PathKind::Plain, segments))
});
Some(paths)
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 15e93f729a..a9705cf2dc 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -1359,13 +1359,24 @@ impl DefCollector<'_> {
if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
directive.module_id,
- ast_id.ast_id,
+ MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: *expand_to },
path,
));
}
}
- MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
- // FIXME: we might want to diagnose this too
+ MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
+ self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
+ directive.module_id,
+ MacroCallKind::Derive {
+ ast_id: ast_id.ast_id,
+ derive_attr_index: derive_attr.ast_index,
+ derive_index: *derive_pos as u32,
+ },
+ ast_id.path.clone(),
+ ));
+ }
+ MacroDirectiveKind::Attr { .. } => {
+ // FIXME: these should get diagnosed by `reseed_with_unresolved_attribute`
}
}
}
diff --git a/crates/hir_def/src/nameres/diagnostics.rs b/crates/hir_def/src/nameres/diagnostics.rs
index ab7a368268..dd3ff92cb3 100644
--- a/crates/hir_def/src/nameres/diagnostics.rs
+++ b/crates/hir_def/src/nameres/diagnostics.rs
@@ -25,7 +25,7 @@ pub enum DefDiagnosticKind {
UnresolvedProcMacro { ast: MacroCallKind },
- UnresolvedMacroCall { ast: AstId<ast::MacroCall>, path: ModPath },
+ UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
MacroError { ast: MacroCallKind, message: String },
@@ -95,7 +95,7 @@ impl DefDiagnostic {
pub(super) fn unresolved_macro_call(
container: LocalModuleId,
- ast: AstId<ast::MacroCall>,
+ ast: MacroCallKind,
path: ModPath,
) -> Self {
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } }
diff --git a/crates/ide_diagnostics/src/handlers/unresolved_macro_call.rs b/crates/ide_diagnostics/src/handlers/unresolved_macro_call.rs
index ea0f35501b..831d082bc7 100644
--- a/crates/ide_diagnostics/src/handlers/unresolved_macro_call.rs
+++ b/crates/ide_diagnostics/src/handlers/unresolved_macro_call.rs
@@ -1,5 +1,5 @@
use hir::{db::AstDatabase, InFile};
-use syntax::{AstNode, SyntaxNodePtr};
+use syntax::{ast, AstNode, SyntaxNodePtr};
use crate::{Diagnostic, DiagnosticsContext};
@@ -12,19 +12,23 @@ pub(crate) fn unresolved_macro_call(
d: &hir::UnresolvedMacroCall,
) -> Diagnostic {
let last_path_segment = ctx.sema.db.parse_or_expand(d.macro_call.file_id).and_then(|root| {
- d.macro_call
- .value
- .to_node(&root)
- .path()
- .and_then(|it| it.segment())
- .and_then(|it| it.name_ref())
- .map(|it| InFile::new(d.macro_call.file_id, SyntaxNodePtr::new(it.syntax())))
+ let node = d.macro_call.value.to_node(&root);
+ if let Some(macro_call) = ast::MacroCall::cast(node) {
+ macro_call
+ .path()
+ .and_then(|it| it.segment())
+ .and_then(|it| it.name_ref())
+ .map(|it| InFile::new(d.macro_call.file_id, SyntaxNodePtr::new(it.syntax())))
+ } else {
+ None
+ }
});
let diagnostics = last_path_segment.unwrap_or_else(|| d.macro_call.clone().map(|it| it.into()));
+ let bang = if d.is_bang { "!" } else { "" };
Diagnostic::new(
"unresolved-macro-call",
- format!("unresolved macro `{}!`", d.path),
+ format!("unresolved macro `{}{}`", d.path, bang),
ctx.sema.diagnostics_display_range(diagnostics).range,
)
.experimental()