diff options
Diffstat (limited to 'crates/ide/src/diagnostics/inactive_code.rs')
-rw-r--r-- | crates/ide/src/diagnostics/inactive_code.rs | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/crates/ide/src/diagnostics/inactive_code.rs b/crates/ide/src/diagnostics/inactive_code.rs new file mode 100644 index 000000000..afe333204 --- /dev/null +++ b/crates/ide/src/diagnostics/inactive_code.rs | |||
@@ -0,0 +1,117 @@ | |||
1 | use cfg::DnfExpr; | ||
2 | use stdx::format_to; | ||
3 | |||
4 | use crate::{ | ||
5 | diagnostics::{Diagnostic, DiagnosticsContext}, | ||
6 | Severity, | ||
7 | }; | ||
8 | |||
9 | // Diagnostic: inactive-code | ||
10 | // | ||
11 | // This diagnostic is shown for code with inactive `#[cfg]` attributes. | ||
12 | pub(super) fn inactive_code( | ||
13 | ctx: &DiagnosticsContext<'_>, | ||
14 | d: &hir::InactiveCode, | ||
15 | ) -> Option<Diagnostic> { | ||
16 | // If there's inactive code somewhere in a macro, don't propagate to the call-site. | ||
17 | if d.node.file_id.expansion_info(ctx.sema.db).is_some() { | ||
18 | return None; | ||
19 | } | ||
20 | |||
21 | let inactive = DnfExpr::new(d.cfg.clone()).why_inactive(&d.opts); | ||
22 | let mut message = "code is inactive due to #[cfg] directives".to_string(); | ||
23 | |||
24 | if let Some(inactive) = inactive { | ||
25 | format_to!(message, ": {}", inactive); | ||
26 | } | ||
27 | |||
28 | let res = Diagnostic::new( | ||
29 | "inactive-code", | ||
30 | message, | ||
31 | ctx.sema.diagnostics_display_range(d.node.clone()).range, | ||
32 | ) | ||
33 | .severity(Severity::WeakWarning) | ||
34 | .with_unused(true); | ||
35 | Some(res) | ||
36 | } | ||
37 | |||
38 | #[cfg(test)] | ||
39 | mod tests { | ||
40 | use crate::diagnostics::tests::check_diagnostics_with_inactive_code; | ||
41 | |||
42 | #[test] | ||
43 | fn cfg_diagnostics() { | ||
44 | check_diagnostics_with_inactive_code( | ||
45 | r#" | ||
46 | fn f() { | ||
47 | // The three g̶e̶n̶d̶e̶r̶s̶ statements: | ||
48 | |||
49 | #[cfg(a)] fn f() {} // Item statement | ||
50 | //^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
51 | #[cfg(a)] {} // Expression statement | ||
52 | //^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
53 | #[cfg(a)] let x = 0; // let statement | ||
54 | //^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
55 | |||
56 | abc(#[cfg(a)] 0); | ||
57 | //^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
58 | let x = Struct { | ||
59 | #[cfg(a)] f: 0, | ||
60 | //^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
61 | }; | ||
62 | match () { | ||
63 | () => (), | ||
64 | #[cfg(a)] () => (), | ||
65 | //^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
66 | } | ||
67 | |||
68 | #[cfg(a)] 0 // Trailing expression of block | ||
69 | //^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
70 | } | ||
71 | "#, | ||
72 | true, | ||
73 | ); | ||
74 | } | ||
75 | |||
76 | #[test] | ||
77 | fn inactive_item() { | ||
78 | // Additional tests in `cfg` crate. This only tests disabled cfgs. | ||
79 | |||
80 | check_diagnostics_with_inactive_code( | ||
81 | r#" | ||
82 | #[cfg(no)] pub fn f() {} | ||
83 | //^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled | ||
84 | |||
85 | #[cfg(no)] #[cfg(no2)] mod m; | ||
86 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no and no2 are disabled | ||
87 | |||
88 | #[cfg(all(not(a), b))] enum E {} | ||
89 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: b is disabled | ||
90 | |||
91 | #[cfg(feature = "std")] use std; | ||
92 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: feature = "std" is disabled | ||
93 | "#, | ||
94 | true, | ||
95 | ); | ||
96 | } | ||
97 | |||
98 | /// Tests that `cfg` attributes behind `cfg_attr` is handled properly. | ||
99 | #[test] | ||
100 | fn inactive_via_cfg_attr() { | ||
101 | cov_mark::check!(cfg_attr_active); | ||
102 | check_diagnostics_with_inactive_code( | ||
103 | r#" | ||
104 | #[cfg_attr(not(never), cfg(no))] fn f() {} | ||
105 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled | ||
106 | |||
107 | #[cfg_attr(not(never), cfg(not(no)))] fn f() {} | ||
108 | |||
109 | #[cfg_attr(never, cfg(no))] fn g() {} | ||
110 | |||
111 | #[cfg_attr(not(never), inline, cfg(no))] fn h() {} | ||
112 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled | ||
113 | "#, | ||
114 | true, | ||
115 | ); | ||
116 | } | ||
117 | } | ||