aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/diagnostics.rs35
-rw-r--r--crates/hir/src/lib.rs22
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs31
-rw-r--r--crates/ide/src/diagnostics.rs29
-rw-r--r--crates/ide/src/diagnostics/unresolved_macro_call.rs72
5 files changed, 94 insertions, 95 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 70a4d000d..718c86b3a 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -17,7 +17,7 @@ pub use crate::diagnostics_sink::{
17}; 17};
18 18
19macro_rules! diagnostics { 19macro_rules! diagnostics {
20 ($($diag:ident),*) => { 20 ($($diag:ident,)*) => {
21 pub enum AnyDiagnostic {$( 21 pub enum AnyDiagnostic {$(
22 $diag(Box<$diag>), 22 $diag(Box<$diag>),
23 )*} 23 )*}
@@ -32,7 +32,13 @@ macro_rules! diagnostics {
32 }; 32 };
33} 33}
34 34
35diagnostics![UnresolvedModule, UnresolvedExternCrate, UnresolvedImport, MissingFields]; 35diagnostics![
36 UnresolvedModule,
37 UnresolvedExternCrate,
38 UnresolvedImport,
39 UnresolvedMacroCall,
40 MissingFields,
41];
36 42
37#[derive(Debug)] 43#[derive(Debug)]
38pub struct UnresolvedModule { 44pub struct UnresolvedModule {
@@ -50,35 +56,12 @@ pub struct UnresolvedImport {
50 pub decl: InFile<AstPtr<ast::UseTree>>, 56 pub decl: InFile<AstPtr<ast::UseTree>>,
51} 57}
52 58
53// Diagnostic: unresolved-macro-call
54//
55// This diagnostic is triggered if rust-analyzer is unable to resolve the path to a
56// macro in a macro invocation.
57#[derive(Debug, Clone, Eq, PartialEq)] 59#[derive(Debug, Clone, Eq, PartialEq)]
58pub struct UnresolvedMacroCall { 60pub struct UnresolvedMacroCall {
59 pub file: HirFileId, 61 pub macro_call: InFile<AstPtr<ast::MacroCall>>,
60 pub node: AstPtr<ast::MacroCall>,
61 pub path: ModPath, 62 pub path: ModPath,
62} 63}
63 64
64impl Diagnostic for UnresolvedMacroCall {
65 fn code(&self) -> DiagnosticCode {
66 DiagnosticCode("unresolved-macro-call")
67 }
68 fn message(&self) -> String {
69 format!("unresolved macro `{}!`", self.path)
70 }
71 fn display_source(&self) -> InFile<SyntaxNodePtr> {
72 InFile::new(self.file, self.node.clone().into())
73 }
74 fn as_any(&self) -> &(dyn Any + Send + 'static) {
75 self
76 }
77 fn is_experimental(&self) -> bool {
78 true
79 }
80}
81
82// Diagnostic: inactive-code 65// Diagnostic: inactive-code
83// 66//
84// This diagnostic is shown for code with inactive `#[cfg]` attributes. 67// This diagnostic is shown for code with inactive `#[cfg]` attributes.
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index d32246709..0a9414013 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -580,11 +580,13 @@ impl Module {
580 580
581 DefDiagnosticKind::UnresolvedMacroCall { ast, path } => { 581 DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
582 let node = ast.to_node(db.upcast()); 582 let node = ast.to_node(db.upcast());
583 sink.push(UnresolvedMacroCall { 583 acc.push(
584 file: ast.file_id, 584 UnresolvedMacroCall {
585 node: AstPtr::new(&node), 585 macro_call: InFile::new(ast.file_id, AstPtr::new(&node)),
586 path: path.clone(), 586 path: path.clone(),
587 }); 587 }
588 .into(),
589 );
588 } 590 }
589 591
590 DefDiagnosticKind::MacroError { ast, message } => { 592 DefDiagnosticKind::MacroError { ast, message } => {
@@ -1060,13 +1062,9 @@ impl Function {
1060 precise_location: None, 1062 precise_location: None,
1061 macro_name: None, 1063 macro_name: None,
1062 }), 1064 }),
1063 BodyDiagnostic::UnresolvedMacroCall { node, path } => { 1065 BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push(
1064 sink.push(UnresolvedMacroCall { 1066 UnresolvedMacroCall { macro_call: node.clone(), path: path.clone() }.into(),
1065 file: node.file_id, 1067 ),
1066 node: node.value.clone(),
1067 path: path.clone(),
1068 })
1069 }
1070 } 1068 }
1071 } 1069 }
1072 1070
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index 7b0f42004..5a088b6e5 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -55,37 +55,6 @@ fn inactive_via_cfg_attr() {
55} 55}
56 56
57#[test] 57#[test]
58fn unresolved_legacy_scope_macro() {
59 check_diagnostics(
60 r#"
61 //- /lib.rs
62 macro_rules! m { () => {} }
63
64 m!();
65 m2!();
66 //^^^^^^ UnresolvedMacroCall
67 "#,
68 );
69}
70
71#[test]
72fn unresolved_module_scope_macro() {
73 check_diagnostics(
74 r#"
75 //- /lib.rs
76 mod mac {
77 #[macro_export]
78 macro_rules! m { () => {} }
79 }
80
81 self::m!();
82 self::m2!();
83 //^^^^^^^^^^^^ UnresolvedMacroCall
84 "#,
85 );
86}
87
88#[test]
89fn builtin_macro_fails_expansion() { 58fn builtin_macro_fails_expansion() {
90 check_diagnostics( 59 check_diagnostics(
91 r#" 60 r#"
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 3d05dd093..1a4800832 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -7,6 +7,7 @@
7mod unresolved_module; 7mod unresolved_module;
8mod unresolved_extern_crate; 8mod unresolved_extern_crate;
9mod unresolved_import; 9mod unresolved_import;
10mod unresolved_macro_call;
10mod missing_fields; 11mod missing_fields;
11 12
12mod fixes; 13mod fixes;
@@ -16,9 +17,8 @@ mod unlinked_file;
16use std::cell::RefCell; 17use std::cell::RefCell;
17 18
18use hir::{ 19use hir::{
19 db::AstDatabase,
20 diagnostics::{AnyDiagnostic, Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder}, 20 diagnostics::{AnyDiagnostic, Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder},
21 InFile, Semantics, 21 Semantics,
22}; 22};
23use ide_assists::AssistResolveStrategy; 23use ide_assists::AssistResolveStrategy;
24use ide_db::{base_db::SourceDatabase, RootDatabase}; 24use ide_db::{base_db::SourceDatabase, RootDatabase};
@@ -203,20 +203,6 @@ pub(crate) fn diagnostics(
203 res.borrow_mut() 203 res.borrow_mut()
204 .push(Diagnostic::hint(display_range, d.message()).with_code(Some(d.code()))); 204 .push(Diagnostic::hint(display_range, d.message()).with_code(Some(d.code())));
205 }) 205 })
206 .on::<hir::diagnostics::UnresolvedMacroCall, _>(|d| {
207 let last_path_segment = sema.db.parse_or_expand(d.file).and_then(|root| {
208 d.node
209 .to_node(&root)
210 .path()
211 .and_then(|it| it.segment())
212 .and_then(|it| it.name_ref())
213 .map(|it| InFile::new(d.file, SyntaxNodePtr::new(it.syntax())))
214 });
215 let diagnostics = last_path_segment.unwrap_or_else(|| d.display_source());
216 let display_range = sema.diagnostics_display_range(diagnostics).range;
217 res.borrow_mut()
218 .push(Diagnostic::error(display_range, d.message()).with_code(Some(d.code())));
219 })
220 .on::<hir::diagnostics::UnimplementedBuiltinMacro, _>(|d| { 206 .on::<hir::diagnostics::UnimplementedBuiltinMacro, _>(|d| {
221 let display_range = sema.diagnostics_display_range(d.display_source()).range; 207 let display_range = sema.diagnostics_display_range(d.display_source()).range;
222 res.borrow_mut() 208 res.borrow_mut()
@@ -259,6 +245,7 @@ pub(crate) fn diagnostics(
259 AnyDiagnostic::UnresolvedModule(d) => unresolved_module::unresolved_module(&ctx, &d), 245 AnyDiagnostic::UnresolvedModule(d) => unresolved_module::unresolved_module(&ctx, &d),
260 AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d), 246 AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d),
261 AnyDiagnostic::UnresolvedImport(d) => unresolved_import::unresolved_import(&ctx, &d), 247 AnyDiagnostic::UnresolvedImport(d) => unresolved_import::unresolved_import(&ctx, &d),
248 AnyDiagnostic::UnresolvedMacroCall(d) => unresolved_macro_call::unresolved_macro_call(&ctx, &d),
262 AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d), 249 AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d),
263 }; 250 };
264 if let Some(code) = d.code { 251 if let Some(code) = d.code {
@@ -481,16 +468,6 @@ mod tests {
481 } 468 }
482 469
483 #[test] 470 #[test]
484 fn test_unresolved_macro_range() {
485 check_diagnostics(
486 r#"
487foo::bar!(92);
488 //^^^ unresolved macro `foo::bar!`
489"#,
490 );
491 }
492
493 #[test]
494 fn range_mapping_out_of_macros() { 471 fn range_mapping_out_of_macros() {
495 // FIXME: this is very wrong, but somewhat tricky to fix. 472 // FIXME: this is very wrong, but somewhat tricky to fix.
496 check_fix( 473 check_fix(
diff --git a/crates/ide/src/diagnostics/unresolved_macro_call.rs b/crates/ide/src/diagnostics/unresolved_macro_call.rs
new file mode 100644
index 000000000..a3af332a4
--- /dev/null
+++ b/crates/ide/src/diagnostics/unresolved_macro_call.rs
@@ -0,0 +1,72 @@
1use hir::{db::AstDatabase, InFile};
2use syntax::{AstNode, SyntaxNodePtr};
3
4use crate::diagnostics::{Diagnostic, DiagnosticsContext};
5
6// Diagnostic: unresolved-macro-call
7//
8// This diagnostic is triggered if rust-analyzer is unable to resolve the path
9// to a macro in a macro invocation.
10pub(super) fn unresolved_macro_call(
11 ctx: &DiagnosticsContext<'_>,
12 d: &hir::UnresolvedMacroCall,
13) -> Diagnostic {
14 let last_path_segment = ctx.sema.db.parse_or_expand(d.macro_call.file_id).and_then(|root| {
15 d.macro_call
16 .value
17 .to_node(&root)
18 .path()
19 .and_then(|it| it.segment())
20 .and_then(|it| it.name_ref())
21 .map(|it| InFile::new(d.macro_call.file_id, SyntaxNodePtr::new(it.syntax())))
22 });
23 let diagnostics = last_path_segment.unwrap_or_else(|| d.macro_call.clone().map(|it| it.into()));
24
25 Diagnostic::new(
26 "unresolved-macro-call",
27 format!("unresolved macro `{}!`", d.path),
28 ctx.sema.diagnostics_display_range(diagnostics).range,
29 )
30 .experimental()
31}
32
33#[cfg(test)]
34mod tests {
35 use crate::diagnostics::tests::check_diagnostics;
36
37 #[test]
38 fn test_unresolved_macro_range() {
39 check_diagnostics(
40 r#"
41foo::bar!(92);
42 //^^^ unresolved macro `foo::bar!`
43"#,
44 );
45 }
46
47 #[test]
48 fn unresolved_legacy_scope_macro() {
49 check_diagnostics(
50 r#"
51macro_rules! m { () => {} }
52
53m!(); m2!();
54 //^^ unresolved macro `self::m2!`
55"#,
56 );
57 }
58
59 #[test]
60 fn unresolved_module_scope_macro() {
61 check_diagnostics(
62 r#"
63mod mac {
64#[macro_export]
65macro_rules! m { () => {} } }
66
67self::m!(); self::m2!();
68 //^^ unresolved macro `self::m2!`
69"#,
70 );
71 }
72}