new lint: empty_inherit

This commit is contained in:
Akshay 2021-12-04 13:02:57 +05:30
parent 1079486539
commit 21775f28cd
6 changed files with 87 additions and 0 deletions

View File

@ -0,0 +1,3 @@
{
inherit;
}

View File

@ -0,0 +1,13 @@
---
source: bin/tests/main.rs
expression: "&out"
---
[W14] Warning: Found empty inherit statement
╭─[data/empty_inherit.nix:2:3]
2 │ inherit;
· ────┬───
· ╰───── Remove this empty inherit statement
───╯

View File

@ -1,6 +1,7 @@
#![recursion_limit = "1024"]
mod lints;
mod make;
mod utils;
pub use lints::LINTS;

View File

@ -14,4 +14,5 @@ lints! {
redundant_pattern_bind,
unquoted_uri,
deprecated_is_null,
empty_inherit,
}

View File

@ -0,0 +1,53 @@
use crate::{make, utils, Metadata, Report, Rule, Suggestion};
use if_chain::if_chain;
use macros::lint;
use rnix::{
types::{Inherit, TypedNode},
NodeOrToken, SyntaxElement, SyntaxKind,
};
/// ## What it does
/// Checks for empty inherit statements.
///
/// ## Why is this bad?
/// Useless code, probably the result of a refactor.
///
/// ## Example
///
/// ```nix
/// inherit;
/// ```
///
/// Remove it altogether.
#[lint(
name = "empty_inherit",
note = "Found empty inherit statement",
code = 14,
match_with = SyntaxKind::NODE_INHERIT
)]
struct EmptyInherit;
impl Rule for EmptyInherit {
fn validate(&self, node: &SyntaxElement) -> Option<Report> {
if_chain! {
if let NodeOrToken::Node(node) = node;
if let Some(inherit_stmt) = Inherit::cast(node.clone());
if inherit_stmt.from().is_none();
if inherit_stmt.idents().count() == 0;
then {
let at = node.text_range();
let replacement = make::empty().node().clone();
let replacement_at = utils::with_preceeding_whitespace(node);
let message = "Remove this empty `inherit` statement";
Some(
self
.report()
.suggest(at, message, Suggestion::new(replacement_at, replacement))
)
} else {
None
}
}
}
}

16
lib/src/utils.rs Normal file
View File

@ -0,0 +1,16 @@
use rnix::{SyntaxKind, SyntaxNode, TextRange};
pub fn with_preceeding_whitespace(node: &SyntaxNode) -> TextRange {
let start = node
.prev_sibling_or_token()
.map(|t| {
if t.kind() == SyntaxKind::TOKEN_WHITESPACE {
t.text_range().start()
} else {
t.text_range().end()
}
})
.unwrap_or(node.text_range().start());
let end = node.text_range().end();
TextRange::new(start, end)
}