additional checks for conditionally compiled code
This commit is contained in:
parent
1a5ff38f92
commit
7192297c28
@ -1,8 +1,10 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_opt};
|
||||
use rustc_ast::ast::{Item, ItemKind, VariantData};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lexer::TokenKind;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -28,9 +30,9 @@
|
||||
|
||||
impl EarlyLintPass for UnitLikeStructBrackets {
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
if let ItemKind::Struct(var_data, _) = &item.kind && has_no_fields(var_data) {
|
||||
let span_after_ident = item.span.with_lo(item.ident.span.hi());
|
||||
let span_after_ident = item.span.with_lo(item.ident.span.hi());
|
||||
|
||||
if let ItemKind::Struct(var_data, _) = &item.kind && has_no_fields(cx, var_data, span_after_ident) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
UNIT_LIKE_STRUCT_BRACKETS,
|
||||
@ -44,9 +46,51 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
}
|
||||
}
|
||||
|
||||
fn has_no_fields(var_data: &VariantData) -> bool {
|
||||
fn has_fields_in_hir(var_data: &VariantData) -> bool {
|
||||
match var_data {
|
||||
VariantData::Struct(defs, _) | VariantData::Tuple(defs, _) => defs.is_empty(),
|
||||
VariantData::Unit(_) => false,
|
||||
VariantData::Struct(defs, _) | VariantData::Tuple(defs, _) => !defs.is_empty(),
|
||||
VariantData::Unit(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn has_no_ident_token(braces_span_str: &str) -> bool {
|
||||
!rustc_lexer::tokenize(braces_span_str).any(|t| t.kind == TokenKind::Ident)
|
||||
}
|
||||
|
||||
fn has_no_fields(cx: &EarlyContext<'_>, var_data: &VariantData, braces_span: Span) -> bool {
|
||||
if has_fields_in_hir(var_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// there might still be field declarations hidden from HIR
|
||||
// (conditionaly compiled code using #[cfg(..)])
|
||||
|
||||
let Some(braces_span_str) = snippet_opt(cx, braces_span) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
has_no_ident_token(braces_span_str.as_ref())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_has_no_ident_token() {
|
||||
let input = "{ field: u8 }";
|
||||
assert!(!has_no_ident_token(input));
|
||||
|
||||
let input = "(u8, String);";
|
||||
assert!(!has_no_ident_token(input));
|
||||
|
||||
let input = " {
|
||||
// test = 5
|
||||
}
|
||||
";
|
||||
assert!(has_no_ident_token(input));
|
||||
|
||||
let input = " ();";
|
||||
assert!(has_no_ident_token(input));
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,17 @@
|
||||
pub struct MyEmptyStruct; // should trigger lint
|
||||
struct MyEmptyTupleStruct; // should trigger lint
|
||||
|
||||
// should not trigger lint
|
||||
struct MyCfgStruct {
|
||||
#[cfg(feature = "thisisneverenabled")]
|
||||
field: u8,
|
||||
}
|
||||
|
||||
// should not trigger lint
|
||||
struct MyCfgTupleStruct(#[cfg(feature = "thisisneverenabled")] u8);
|
||||
|
||||
// should not trigger lint
|
||||
struct MyStruct {
|
||||
// should not trigger lint
|
||||
field: u8,
|
||||
}
|
||||
struct MyTupleStruct(usize, String); // should not trigger lint
|
||||
|
@ -5,8 +5,17 @@
|
||||
pub struct MyEmptyStruct {} // should trigger lint
|
||||
struct MyEmptyTupleStruct(); // should trigger lint
|
||||
|
||||
// should not trigger lint
|
||||
struct MyCfgStruct {
|
||||
#[cfg(feature = "thisisneverenabled")]
|
||||
field: u8,
|
||||
}
|
||||
|
||||
// should not trigger lint
|
||||
struct MyCfgTupleStruct(#[cfg(feature = "thisisneverenabled")] u8);
|
||||
|
||||
// should not trigger lint
|
||||
struct MyStruct {
|
||||
// should not trigger lint
|
||||
field: u8,
|
||||
}
|
||||
struct MyTupleStruct(usize, String); // should not trigger lint
|
||||
|
Loading…
Reference in New Issue
Block a user