aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-05-31 13:34:01 +0100
committerGitHub <[email protected]>2021-05-31 13:34:01 +0100
commitb8d269990c57634e77f4702afc91041bacb4816a (patch)
treef1d707daa5f4d20abec75299234552b320fa1a42 /crates
parentd7cbb49057c4495307d91f5db32465c29c175124 (diff)
parentcb5454db86bae1e97d86b05607b5c36a89fb749b (diff)
Merge #9060
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 <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/diagnostics.rs24
-rw-r--r--crates/hir/src/lib.rs12
-rw-r--r--crates/hir_def/src/nameres/collector.rs48
-rw-r--r--crates/hir_def/src/nameres/diagnostics.rs9
-rw-r--r--crates/hir_def/src/test_db.rs7
-rw-r--r--crates/ide/src/diagnostics.rs5
6 files changed, 87 insertions, 18 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 22ec7c6ac..2cdbd172a 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -227,3 +227,27 @@ impl Diagnostic for MacroError {
227 true 227 true
228 } 228 }
229} 229}
230
231#[derive(Debug)]
232pub struct UnimplementedBuiltinMacro {
233 pub file: HirFileId,
234 pub node: SyntaxNodePtr,
235}
236
237impl Diagnostic for UnimplementedBuiltinMacro {
238 fn code(&self) -> DiagnosticCode {
239 DiagnosticCode("unimplemented-builtin-macro")
240 }
241
242 fn message(&self) -> String {
243 "unimplemented built-in macro".to_string()
244 }
245
246 fn display_source(&self) -> InFile<SyntaxNodePtr> {
247 InFile::new(self.file, self.node.clone())
248 }
249
250 fn as_any(&self) -> &(dyn Any + Send + 'static) {
251 self
252 }
253}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 975ae4869..d3ef29db4 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -36,8 +36,8 @@ use std::{iter, sync::Arc};
36use arrayvec::ArrayVec; 36use arrayvec::ArrayVec;
37use base_db::{CrateDisplayName, CrateId, Edition, FileId}; 37use base_db::{CrateDisplayName, CrateId, Edition, FileId};
38use diagnostics::{ 38use diagnostics::{
39 InactiveCode, MacroError, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, 39 InactiveCode, MacroError, UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport,
40 UnresolvedModule, UnresolvedProcMacro, 40 UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro,
41}; 41};
42use either::Either; 42use either::Either;
43use hir_def::{ 43use hir_def::{
@@ -565,6 +565,14 @@ impl Module {
565 }; 565 };
566 sink.push(MacroError { file, node: ast, message: message.clone() }); 566 sink.push(MacroError { file, node: ast, message: message.clone() });
567 } 567 }
568
569 DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
570 let node = ast.to_node(db.upcast());
571 // Must have a name, otherwise we wouldn't emit it.
572 let name = node.name().expect("unimplemented builtin macro with no name");
573 let ptr = SyntaxNodePtr::from(AstPtr::new(&name));
574 sink.push(UnimplementedBuiltinMacro { file: ast.file_id, node: ptr });
575 }
568 } 576 }
569 } 577 }
570 for decl in self.declarations(db) { 578 for decl in self.declarations(db) {
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index d9d6c91a8..50b2b0af4 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -1679,14 +1679,22 @@ impl ModCollector<'_, '_> {
1679 None => &mac.name, 1679 None => &mac.name,
1680 }; 1680 };
1681 let krate = self.def_collector.def_map.krate; 1681 let krate = self.def_collector.def_map.krate;
1682 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) { 1682 match find_builtin_macro(name, krate, ast_id) {
1683 self.def_collector.define_macro_rules( 1683 Some(macro_id) => {
1684 self.module_id, 1684 self.def_collector.define_macro_rules(
1685 mac.name.clone(), 1685 self.module_id,
1686 macro_id, 1686 mac.name.clone(),
1687 is_export, 1687 macro_id,
1688 ); 1688 is_export,
1689 return; 1689 );
1690 return;
1691 }
1692 None => {
1693 self.def_collector
1694 .def_map
1695 .diagnostics
1696 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
1697 }
1690 } 1698 }
1691 } 1699 }
1692 1700
@@ -1715,15 +1723,23 @@ impl ModCollector<'_, '_> {
1715 let macro_id = find_builtin_macro(&mac.name, krate, ast_id) 1723 let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
1716 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); 1724 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id));
1717 1725
1718 if let Some(macro_id) = macro_id { 1726 match macro_id {
1719 self.def_collector.define_macro_def( 1727 Some(macro_id) => {
1720 self.module_id, 1728 self.def_collector.define_macro_def(
1721 mac.name.clone(), 1729 self.module_id,
1722 macro_id, 1730 mac.name.clone(),
1723 &self.item_tree[mac.visibility], 1731 macro_id,
1724 ); 1732 &self.item_tree[mac.visibility],
1733 );
1734 return;
1735 }
1736 None => {
1737 self.def_collector
1738 .def_map
1739 .diagnostics
1740 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
1741 }
1725 } 1742 }
1726 return;
1727 } 1743 }
1728 1744
1729 // Case 2: normal `macro` 1745 // Case 2: normal `macro`
diff --git a/crates/hir_def/src/nameres/diagnostics.rs b/crates/hir_def/src/nameres/diagnostics.rs
index 57c36c3c6..95061f601 100644
--- a/crates/hir_def/src/nameres/diagnostics.rs
+++ b/crates/hir_def/src/nameres/diagnostics.rs
@@ -27,6 +27,8 @@ pub enum DefDiagnosticKind {
27 UnresolvedMacroCall { ast: AstId<ast::MacroCall>, path: ModPath }, 27 UnresolvedMacroCall { ast: AstId<ast::MacroCall>, path: ModPath },
28 28
29 MacroError { ast: MacroCallKind, message: String }, 29 MacroError { ast: MacroCallKind, message: String },
30
31 UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
30} 32}
31 33
32#[derive(Debug, PartialEq, Eq)] 34#[derive(Debug, PartialEq, Eq)]
@@ -93,4 +95,11 @@ impl DefDiagnostic {
93 ) -> Self { 95 ) -> Self {
94 Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } } 96 Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } }
95 } 97 }
98
99 pub(super) fn unimplemented_builtin_macro(
100 container: LocalModuleId,
101 ast: AstId<ast::Macro>,
102 ) -> Self {
103 Self { in_module: container, kind: DefDiagnosticKind::UnimplementedBuiltinMacro { ast } }
104 }
96} 105}
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs
index a9c1e13e2..e840fe5e8 100644
--- a/crates/hir_def/src/test_db.rs
+++ b/crates/hir_def/src/test_db.rs
@@ -298,6 +298,13 @@ impl TestDB {
298 DefDiagnosticKind::MacroError { ast, message } => { 298 DefDiagnosticKind::MacroError { ast, message } => {
299 (ast.to_node(self.upcast()), message.as_str()) 299 (ast.to_node(self.upcast()), message.as_str())
300 } 300 }
301 DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
302 let node = ast.to_node(self.upcast());
303 (
304 InFile::new(ast.file_id, node.syntax().clone()),
305 "UnimplementedBuiltinMacro",
306 )
307 }
301 }; 308 };
302 309
303 let frange = node.as_ref().original_file_range(self); 310 let frange = node.as_ref().original_file_range(self);
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 6cf5810fa..d5c954b8b 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -182,6 +182,11 @@ pub(crate) fn diagnostics(
182 res.borrow_mut() 182 res.borrow_mut()
183 .push(Diagnostic::error(display_range, d.message()).with_code(Some(d.code()))); 183 .push(Diagnostic::error(display_range, d.message()).with_code(Some(d.code())));
184 }) 184 })
185 .on::<hir::diagnostics::UnimplementedBuiltinMacro, _>(|d| {
186 let display_range = sema.diagnostics_display_range(d.display_source()).range;
187 res.borrow_mut()
188 .push(Diagnostic::hint(display_range, d.message()).with_code(Some(d.code())));
189 })
185 // Only collect experimental diagnostics when they're enabled. 190 // Only collect experimental diagnostics when they're enabled.
186 .filter(|diag| !(diag.is_experimental() && config.disable_experimental)) 191 .filter(|diag| !(diag.is_experimental() && config.disable_experimental))
187 .filter(|diag| !config.disabled.contains(diag.code().as_str())); 192 .filter(|diag| !config.disabled.contains(diag.code().as_str()));