diff options
author | Aleksey Kladov <[email protected]> | 2021-06-13 15:29:25 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-06-13 15:29:25 +0100 |
commit | f85e383b94376d55bb5ee6be375ef3dc0006590f (patch) | |
tree | 03e3c3685a893891c7b9f144597362a5e57c02ca /crates/ide/src/diagnostics | |
parent | fa9ed4e0ce633e51d1411951bf044719e6837457 (diff) |
internal: refactor inactive code diagnostics
Diffstat (limited to 'crates/ide/src/diagnostics')
-rw-r--r-- | crates/ide/src/diagnostics/inactive_code.rs | 113 |
1 files changed, 113 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..52f97cb4c --- /dev/null +++ b/crates/ide/src/diagnostics/inactive_code.rs | |||
@@ -0,0 +1,113 @@ | |||
1 | use cfg::DnfExpr; | ||
2 | use stdx::format_to; | ||
3 | |||
4 | use crate::diagnostics::{Diagnostic, DiagnosticsContext}; | ||
5 | |||
6 | // Diagnostic: inactive-code | ||
7 | // | ||
8 | // This diagnostic is shown for code with inactive `#[cfg]` attributes. | ||
9 | pub(super) 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 | .with_unused(true); | ||
31 | Some(res) | ||
32 | } | ||
33 | |||
34 | #[cfg(test)] | ||
35 | mod tests { | ||
36 | use crate::diagnostics::tests::check_diagnostics_with_inactive_code; | ||
37 | |||
38 | #[test] | ||
39 | fn cfg_diagnostics() { | ||
40 | check_diagnostics_with_inactive_code( | ||
41 | r#" | ||
42 | fn f() { | ||
43 | // The three g̶e̶n̶d̶e̶r̶s̶ statements: | ||
44 | |||
45 | #[cfg(a)] fn f() {} // Item statement | ||
46 | //^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
47 | #[cfg(a)] {} // Expression statement | ||
48 | //^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
49 | #[cfg(a)] let x = 0; // let statement | ||
50 | //^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
51 | |||
52 | abc(#[cfg(a)] 0); | ||
53 | //^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
54 | let x = Struct { | ||
55 | #[cfg(a)] f: 0, | ||
56 | //^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
57 | }; | ||
58 | match () { | ||
59 | () => (), | ||
60 | #[cfg(a)] () => (), | ||
61 | //^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
62 | } | ||
63 | |||
64 | #[cfg(a)] 0 // Trailing expression of block | ||
65 | //^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled | ||
66 | } | ||
67 | "#, | ||
68 | true, | ||
69 | ); | ||
70 | } | ||
71 | |||
72 | #[test] | ||
73 | fn inactive_item() { | ||
74 | // Additional tests in `cfg` crate. This only tests disabled cfgs. | ||
75 | |||
76 | check_diagnostics_with_inactive_code( | ||
77 | r#" | ||
78 | #[cfg(no)] pub fn f() {} | ||
79 | //^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled | ||
80 | |||
81 | #[cfg(no)] #[cfg(no2)] mod m; | ||
82 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no and no2 are disabled | ||
83 | |||
84 | #[cfg(all(not(a), b))] enum E {} | ||
85 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: b is disabled | ||
86 | |||
87 | #[cfg(feature = "std")] use std; | ||
88 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: feature = "std" is disabled | ||
89 | "#, | ||
90 | true, | ||
91 | ); | ||
92 | } | ||
93 | |||
94 | /// Tests that `cfg` attributes behind `cfg_attr` is handled properly. | ||
95 | #[test] | ||
96 | fn inactive_via_cfg_attr() { | ||
97 | cov_mark::check!(cfg_attr_active); | ||
98 | check_diagnostics_with_inactive_code( | ||
99 | r#" | ||
100 | #[cfg_attr(not(never), cfg(no))] fn f() {} | ||
101 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled | ||
102 | |||
103 | #[cfg_attr(not(never), cfg(not(no)))] fn f() {} | ||
104 | |||
105 | #[cfg_attr(never, cfg(no))] fn g() {} | ||
106 | |||
107 | #[cfg_attr(not(never), inline, cfg(no))] fn h() {} | ||
108 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled | ||
109 | "#, | ||
110 | true, | ||
111 | ); | ||
112 | } | ||
113 | } | ||