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