mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
Diagnose unresolved derive macros
This commit is contained in:
parent
1ad500beb6
commit
fa42888e27
6 changed files with 44 additions and 19 deletions
|
@ -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)]
|
||||
|
|
|
@ -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(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue