9060: feat: Diagnose unimplemented built-in macros r=matklad a=jonas-schievink

A number of built-in attribute macros are unsupported, I thought it might be useful to put a diagnostic on their definition in libcore. Not sure.

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2021-05-31 12:34:01 +00:00 committed by GitHub
commit b8d269990c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 18 deletions

View File

@ -227,3 +227,27 @@ impl Diagnostic for MacroError {
true
}
}
#[derive(Debug)]
pub struct UnimplementedBuiltinMacro {
pub file: HirFileId,
pub node: SyntaxNodePtr,
}
impl Diagnostic for UnimplementedBuiltinMacro {
fn code(&self) -> DiagnosticCode {
DiagnosticCode("unimplemented-builtin-macro")
}
fn message(&self) -> String {
"unimplemented built-in macro".to_string()
}
fn display_source(&self) -> InFile<SyntaxNodePtr> {
InFile::new(self.file, self.node.clone())
}
fn as_any(&self) -> &(dyn Any + Send + 'static) {
self
}
}

View File

@ -36,8 +36,8 @@ use std::{iter, sync::Arc};
use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateId, Edition, FileId};
use diagnostics::{
InactiveCode, MacroError, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall,
UnresolvedModule, UnresolvedProcMacro,
InactiveCode, MacroError, UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport,
UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro,
};
use either::Either;
use hir_def::{
@ -565,6 +565,14 @@ impl Module {
};
sink.push(MacroError { file, node: ast, message: message.clone() });
}
DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
let node = ast.to_node(db.upcast());
// Must have a name, otherwise we wouldn't emit it.
let name = node.name().expect("unimplemented builtin macro with no name");
let ptr = SyntaxNodePtr::from(AstPtr::new(&name));
sink.push(UnimplementedBuiltinMacro { file: ast.file_id, node: ptr });
}
}
}
for decl in self.declarations(db) {

View File

@ -1679,14 +1679,22 @@ impl ModCollector<'_, '_> {
None => &mac.name,
};
let krate = self.def_collector.def_map.krate;
if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) {
self.def_collector.define_macro_rules(
self.module_id,
mac.name.clone(),
macro_id,
is_export,
);
return;
match find_builtin_macro(name, krate, ast_id) {
Some(macro_id) => {
self.def_collector.define_macro_rules(
self.module_id,
mac.name.clone(),
macro_id,
is_export,
);
return;
}
None => {
self.def_collector
.def_map
.diagnostics
.push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
}
}
}
@ -1715,15 +1723,23 @@ impl ModCollector<'_, '_> {
let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
.or_else(|| find_builtin_derive(&mac.name, krate, ast_id));
if let Some(macro_id) = macro_id {
self.def_collector.define_macro_def(
self.module_id,
mac.name.clone(),
macro_id,
&self.item_tree[mac.visibility],
);
match macro_id {
Some(macro_id) => {
self.def_collector.define_macro_def(
self.module_id,
mac.name.clone(),
macro_id,
&self.item_tree[mac.visibility],
);
return;
}
None => {
self.def_collector
.def_map
.diagnostics
.push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
}
}
return;
}
// Case 2: normal `macro`

View File

@ -27,6 +27,8 @@ pub enum DefDiagnosticKind {
UnresolvedMacroCall { ast: AstId<ast::MacroCall>, path: ModPath },
MacroError { ast: MacroCallKind, message: String },
UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
}
#[derive(Debug, PartialEq, Eq)]
@ -93,4 +95,11 @@ impl DefDiagnostic {
) -> Self {
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } }
}
pub(super) fn unimplemented_builtin_macro(
container: LocalModuleId,
ast: AstId<ast::Macro>,
) -> Self {
Self { in_module: container, kind: DefDiagnosticKind::UnimplementedBuiltinMacro { ast } }
}
}

View File

@ -298,6 +298,13 @@ impl TestDB {
DefDiagnosticKind::MacroError { ast, message } => {
(ast.to_node(self.upcast()), message.as_str())
}
DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
let node = ast.to_node(self.upcast());
(
InFile::new(ast.file_id, node.syntax().clone()),
"UnimplementedBuiltinMacro",
)
}
};
let frange = node.as_ref().original_file_range(self);

View File

@ -182,6 +182,11 @@ pub(crate) fn diagnostics(
res.borrow_mut()
.push(Diagnostic::error(display_range, d.message()).with_code(Some(d.code())));
})
.on::<hir::diagnostics::UnimplementedBuiltinMacro, _>(|d| {
let display_range = sema.diagnostics_display_range(d.display_source()).range;
res.borrow_mut()
.push(Diagnostic::hint(display_range, d.message()).with_code(Some(d.code())));
})
// Only collect experimental diagnostics when they're enabled.
.filter(|diag| !(diag.is_experimental() && config.disable_experimental))
.filter(|diag| !config.disabled.contains(diag.code().as_str()));