Diagnose unresolved derive macros

This commit is contained in:
Jonas Schievink 2022-04-27 20:03:57 +02:00
parent 1ad500beb6
commit fa42888e27
6 changed files with 44 additions and 19 deletions

View file

@ -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)]

View file

@ -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(),
),
}
}

View file

@ -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)

View file

@ -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`
}
}
}

View file

@ -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 } }

View file

@ -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()