ide_diagnostics/handlers/
inactive_code.rsuse cfg::DnfExpr;
use stdx::format_to;
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, Severity};
pub(crate) fn inactive_code(
ctx: &DiagnosticsContext<'_>,
d: &hir::InactiveCode,
) -> Option<Diagnostic> {
if d.node.file_id.is_macro() {
return None;
}
let inactive = DnfExpr::new(&d.cfg).why_inactive(&d.opts);
let mut message = "code is inactive due to #[cfg] directives".to_owned();
if let Some(inactive) = inactive {
let inactive_reasons = inactive.to_string();
if inactive_reasons.is_empty() {
format_to!(message);
} else {
format_to!(message, ": {}", inactive);
}
}
let res = Diagnostic::new(
DiagnosticCode::Ra("inactive-code", Severity::WeakWarning),
message,
ctx.sema.diagnostics_display_range(d.node),
)
.with_unused(true);
Some(res)
}
#[cfg(test)]
mod tests {
use crate::{tests::check_diagnostics_with_config, DiagnosticsConfig};
pub(crate) fn check(ra_fixture: &str) {
let config = DiagnosticsConfig {
disabled: std::iter::once("unlinked-file".to_owned()).collect(),
..DiagnosticsConfig::test_sample()
};
check_diagnostics_with_config(config, ra_fixture)
}
#[test]
fn cfg_diagnostics() {
check(
r#"
fn f() {
// The three g̶e̶n̶d̶e̶r̶s̶ statements:
#[cfg(a)] fn f() {} // Item statement
//^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
#[cfg(a)] {} // Expression statement
//^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
#[cfg(a)] let x = 0; // let statement
//^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
fn abc() {}
abc(#[cfg(a)] 0);
//^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
let x = Struct {
#[cfg(a)] f: 0,
//^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
};
match () {
() => (),
#[cfg(a)] () => (),
//^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
}
#[cfg(a)] 0 // Trailing expression of block
//^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
}
"#,
);
}
#[test]
fn inactive_item() {
check(
r#"
#[cfg(no)] pub fn f() {}
//^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: no is disabled
#[cfg(no)] #[cfg(no2)] mod m;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: no and no2 are disabled
#[cfg(all(not(a), b))] enum E {}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: b is disabled
#[cfg(feature = "std")] use std;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: feature = "std" is disabled
#[cfg(any())] pub fn f() {}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives
"#,
);
}
#[test]
fn inactive_assoc_item() {
check(
r#"
struct Foo;
impl Foo {
#[cfg(any())] pub fn f() {}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives
}
trait Bar {
#[cfg(any())] pub fn f() {}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives
}
"#,
);
}
#[test]
fn inactive_via_cfg_attr() {
cov_mark::check!(cfg_attr_active);
check(
r#"
#[cfg_attr(not(never), cfg(no))] fn f() {}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: no is disabled
#[cfg_attr(not(never), cfg(not(no)))] fn f() {}
#[cfg_attr(never, cfg(no))] fn g() {}
#[cfg_attr(not(never), inline, cfg(no))] fn h() {}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: no is disabled
"#,
);
}
#[test]
fn inactive_fields_and_variants() {
check(
r#"
enum Foo {
#[cfg(a)] Bar,
//^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
Baz {
#[cfg(a)] baz: String,
//^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
},
Qux(#[cfg(a)] String),
//^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
}
struct Baz {
#[cfg(a)] baz: String,
//^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
}
struct Qux(#[cfg(a)] String);
//^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
union FooBar {
#[cfg(a)] baz: u32,
//^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
}
"#,
);
}
#[test]
fn modules() {
check(
r#"
//- /main.rs
#[cfg(outline)] mod outline;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: outline is disabled
mod outline_inner;
//^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: outline_inner is disabled
#[cfg(inline)] mod inline {}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: inline is disabled
//- /outline_inner.rs
#![cfg(outline_inner)]
//- /outline.rs
"#,
);
}
#[test]
fn cfg_true_false() {
check(
r#"
#[cfg(false)] fn inactive() {}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: false is disabled
#[cfg(true)] fn active() {}
#[cfg(any(not(true)), false)] fn inactive2() {}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: true is enabled
"#,
);
}
}