diff options
Diffstat (limited to 'crates/ide/src/diagnostics/unresolved_macro_call.rs')
-rw-r--r-- | crates/ide/src/diagnostics/unresolved_macro_call.rs | 84 |
1 files changed, 84 insertions, 0 deletions
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..15b6a2730 --- /dev/null +++ b/crates/ide/src/diagnostics/unresolved_macro_call.rs | |||
@@ -0,0 +1,84 @@ | |||
1 | use hir::{db::AstDatabase, InFile}; | ||
2 | use syntax::{AstNode, SyntaxNodePtr}; | ||
3 | |||
4 | use 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. | ||
10 | pub(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)] | ||
34 | mod tests { | ||
35 | use crate::diagnostics::tests::check_diagnostics; | ||
36 | |||
37 | #[test] | ||
38 | fn unresolved_macro_diag() { | ||
39 | check_diagnostics( | ||
40 | r#" | ||
41 | fn f() { | ||
42 | m!(); | ||
43 | } //^ unresolved macro `m!` | ||
44 | |||
45 | "#, | ||
46 | ); | ||
47 | } | ||
48 | |||
49 | #[test] | ||
50 | fn test_unresolved_macro_range() { | ||
51 | check_diagnostics( | ||
52 | r#" | ||
53 | foo::bar!(92); | ||
54 | //^^^ unresolved macro `foo::bar!` | ||
55 | "#, | ||
56 | ); | ||
57 | } | ||
58 | |||
59 | #[test] | ||
60 | fn unresolved_legacy_scope_macro() { | ||
61 | check_diagnostics( | ||
62 | r#" | ||
63 | macro_rules! m { () => {} } | ||
64 | |||
65 | m!(); m2!(); | ||
66 | //^^ unresolved macro `self::m2!` | ||
67 | "#, | ||
68 | ); | ||
69 | } | ||
70 | |||
71 | #[test] | ||
72 | fn unresolved_module_scope_macro() { | ||
73 | check_diagnostics( | ||
74 | r#" | ||
75 | mod mac { | ||
76 | #[macro_export] | ||
77 | macro_rules! m { () => {} } } | ||
78 | |||
79 | self::m!(); self::m2!(); | ||
80 | //^^ unresolved macro `self::m2!` | ||
81 | "#, | ||
82 | ); | ||
83 | } | ||
84 | } | ||