diff options
Diffstat (limited to 'crates/ide/src')
-rw-r--r-- | crates/ide/src/diagnostics.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/macro_error.rs | 163 |
2 files changed, 165 insertions, 0 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index f7965326d..c257ea8e7 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -9,6 +9,7 @@ mod unresolved_extern_crate; | |||
9 | mod unresolved_import; | 9 | mod unresolved_import; |
10 | mod unresolved_macro_call; | 10 | mod unresolved_macro_call; |
11 | mod unresolved_proc_macro; | 11 | mod unresolved_proc_macro; |
12 | mod macro_error; | ||
12 | mod inactive_code; | 13 | mod inactive_code; |
13 | mod missing_fields; | 14 | mod missing_fields; |
14 | 15 | ||
@@ -229,6 +230,7 @@ pub(crate) fn diagnostics( | |||
229 | AnyDiagnostic::UnresolvedMacroCall(d) => unresolved_macro_call::unresolved_macro_call(&ctx, &d), | 230 | AnyDiagnostic::UnresolvedMacroCall(d) => unresolved_macro_call::unresolved_macro_call(&ctx, &d), |
230 | AnyDiagnostic::UnresolvedProcMacro(d) => unresolved_proc_macro::unresolved_proc_macro(&ctx, &d), | 231 | AnyDiagnostic::UnresolvedProcMacro(d) => unresolved_proc_macro::unresolved_proc_macro(&ctx, &d), |
231 | AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d), | 232 | AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d), |
233 | AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d), | ||
232 | 234 | ||
233 | AnyDiagnostic::InactiveCode(d) => match inactive_code::inactive_code(&ctx, &d) { | 235 | AnyDiagnostic::InactiveCode(d) => match inactive_code::inactive_code(&ctx, &d) { |
234 | Some(it) => it, | 236 | Some(it) => it, |
diff --git a/crates/ide/src/diagnostics/macro_error.rs b/crates/ide/src/diagnostics/macro_error.rs new file mode 100644 index 000000000..8cc8cfb48 --- /dev/null +++ b/crates/ide/src/diagnostics/macro_error.rs | |||
@@ -0,0 +1,163 @@ | |||
1 | use crate::diagnostics::{Diagnostic, DiagnosticsContext}; | ||
2 | |||
3 | // Diagnostic: macro-error | ||
4 | // | ||
5 | // This diagnostic is shown for macro expansion errors. | ||
6 | pub(super) fn macro_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroError) -> Diagnostic { | ||
7 | Diagnostic::new( | ||
8 | "macro-error", | ||
9 | d.message.clone(), | ||
10 | ctx.sema.diagnostics_display_range(d.node.clone()).range, | ||
11 | ) | ||
12 | .experimental() | ||
13 | } | ||
14 | |||
15 | #[cfg(test)] | ||
16 | mod tests { | ||
17 | use crate::diagnostics::tests::{check_diagnostics, check_no_diagnostics}; | ||
18 | |||
19 | #[test] | ||
20 | fn builtin_macro_fails_expansion() { | ||
21 | check_diagnostics( | ||
22 | r#" | ||
23 | #[rustc_builtin_macro] | ||
24 | macro_rules! include { () => {} } | ||
25 | |||
26 | include!("doesntexist"); | ||
27 | //^^^^^^^^^^^^^^^^^^^^^^^^ failed to load file `doesntexist` | ||
28 | "#, | ||
29 | ); | ||
30 | } | ||
31 | |||
32 | #[test] | ||
33 | fn include_macro_should_allow_empty_content() { | ||
34 | check_diagnostics( | ||
35 | r#" | ||
36 | //- /lib.rs | ||
37 | #[rustc_builtin_macro] | ||
38 | macro_rules! include { () => {} } | ||
39 | |||
40 | include!("foo/bar.rs"); | ||
41 | //- /foo/bar.rs | ||
42 | // empty | ||
43 | "#, | ||
44 | ); | ||
45 | } | ||
46 | |||
47 | #[test] | ||
48 | fn good_out_dir_diagnostic() { | ||
49 | check_diagnostics( | ||
50 | r#" | ||
51 | #[rustc_builtin_macro] | ||
52 | macro_rules! include { () => {} } | ||
53 | #[rustc_builtin_macro] | ||
54 | macro_rules! env { () => {} } | ||
55 | #[rustc_builtin_macro] | ||
56 | macro_rules! concat { () => {} } | ||
57 | |||
58 | include!(concat!(env!("OUT_DIR"), "/out.rs")); | ||
59 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix | ||
60 | "#, | ||
61 | ); | ||
62 | } | ||
63 | |||
64 | #[test] | ||
65 | fn register_attr_and_tool() { | ||
66 | cov_mark::check!(register_attr); | ||
67 | cov_mark::check!(register_tool); | ||
68 | check_no_diagnostics( | ||
69 | r#" | ||
70 | #![register_tool(tool)] | ||
71 | #![register_attr(attr)] | ||
72 | |||
73 | #[tool::path] | ||
74 | #[attr] | ||
75 | struct S; | ||
76 | "#, | ||
77 | ); | ||
78 | // NB: we don't currently emit diagnostics here | ||
79 | } | ||
80 | |||
81 | #[test] | ||
82 | fn macro_diag_builtin() { | ||
83 | check_diagnostics( | ||
84 | r#" | ||
85 | #[rustc_builtin_macro] | ||
86 | macro_rules! env {} | ||
87 | |||
88 | #[rustc_builtin_macro] | ||
89 | macro_rules! include {} | ||
90 | |||
91 | #[rustc_builtin_macro] | ||
92 | macro_rules! compile_error {} | ||
93 | |||
94 | #[rustc_builtin_macro] | ||
95 | macro_rules! format_args { () => {} } | ||
96 | |||
97 | fn main() { | ||
98 | // Test a handful of built-in (eager) macros: | ||
99 | |||
100 | include!(invalid); | ||
101 | //^^^^^^^^^^^^^^^^^ could not convert tokens | ||
102 | include!("does not exist"); | ||
103 | //^^^^^^^^^^^^^^^^^^^^^^^^^^ failed to load file `does not exist` | ||
104 | |||
105 | env!(invalid); | ||
106 | //^^^^^^^^^^^^^ could not convert tokens | ||
107 | |||
108 | env!("OUT_DIR"); | ||
109 | //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix | ||
110 | |||
111 | compile_error!("compile_error works"); | ||
112 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works | ||
113 | |||
114 | // Lazy: | ||
115 | |||
116 | format_args!(); | ||
117 | //^^^^^^^^^^^^^^ no rule matches input tokens | ||
118 | } | ||
119 | "#, | ||
120 | ); | ||
121 | } | ||
122 | |||
123 | #[test] | ||
124 | fn macro_rules_diag() { | ||
125 | check_diagnostics( | ||
126 | r#" | ||
127 | macro_rules! m { | ||
128 | () => {}; | ||
129 | } | ||
130 | fn f() { | ||
131 | m!(); | ||
132 | |||
133 | m!(hi); | ||
134 | //^^^^^^ leftover tokens | ||
135 | } | ||
136 | "#, | ||
137 | ); | ||
138 | } | ||
139 | #[test] | ||
140 | fn dollar_crate_in_builtin_macro() { | ||
141 | check_diagnostics( | ||
142 | r#" | ||
143 | #[macro_export] | ||
144 | #[rustc_builtin_macro] | ||
145 | macro_rules! format_args {} | ||
146 | |||
147 | #[macro_export] | ||
148 | macro_rules! arg { () => {} } | ||
149 | |||
150 | #[macro_export] | ||
151 | macro_rules! outer { | ||
152 | () => { | ||
153 | $crate::format_args!( "", $crate::arg!(1) ) | ||
154 | }; | ||
155 | } | ||
156 | |||
157 | fn f() { | ||
158 | outer!(); | ||
159 | } //^^^^^^^^ leftover tokens | ||
160 | "#, | ||
161 | ) | ||
162 | } | ||
163 | } | ||