mirror of
https://github.com/nerdypepper/statix.git
synced 2024-08-17 01:10:26 +03:00
add 3 new lints, bump to v0.2.3
- empty_pattern - redundant_pattern_bind - unquoted_splice
This commit is contained in:
parent
f909b20c54
commit
8eccf15964
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -388,7 +388,7 @@ checksum = "b203e79e90905594272c1c97c7af701533d42adaab0beb3859018e477d54a3b0"
|
||||
|
||||
[[package]]
|
||||
name = "statix"
|
||||
version = "0.2.0"
|
||||
version = "0.2.3"
|
||||
dependencies = [
|
||||
"ariadne",
|
||||
"clap",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "statix"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
|
||||
|
@ -49,7 +49,7 @@
|
||||
|
||||
statix = with final; pkgs.stdenv.mkDerivation {
|
||||
pname = "statix";
|
||||
version = "v0.2.2";
|
||||
version = "v0.2.3";
|
||||
src = builtins.path {
|
||||
path = ./.;
|
||||
name = "statix";
|
||||
|
@ -9,4 +9,7 @@ lint_map! {
|
||||
collapsible_let_in,
|
||||
eta_reduction,
|
||||
useless_parens,
|
||||
unquoted_splice,
|
||||
empty_pattern,
|
||||
redundant_pattern_bind,
|
||||
}
|
||||
|
37
lib/src/lints/empty_pattern.rs
Normal file
37
lib/src/lints/empty_pattern.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use crate::{make, Lint, Metadata, Report, Rule, Suggestion};
|
||||
|
||||
use if_chain::if_chain;
|
||||
use macros::lint;
|
||||
use rnix::{
|
||||
types::{Pattern, TypedNode},
|
||||
NodeOrToken, SyntaxElement, SyntaxKind,
|
||||
};
|
||||
|
||||
#[lint(
|
||||
name = "empty pattern",
|
||||
note = "Found empty pattern in function argument",
|
||||
code = 10,
|
||||
match_with = SyntaxKind::NODE_PATTERN
|
||||
)]
|
||||
struct EmptyPattern;
|
||||
|
||||
impl Rule for EmptyPattern {
|
||||
fn validate(&self, node: &SyntaxElement) -> Option<Report> {
|
||||
if_chain! {
|
||||
if let NodeOrToken::Node(node) = node;
|
||||
if let Some(pattern) = Pattern::cast(node.clone());
|
||||
// no patterns within `{ }`
|
||||
if pattern.entries().count() == 0;
|
||||
// pattern is not bound
|
||||
if pattern.at().is_none();
|
||||
then {
|
||||
let at = node.text_range();
|
||||
let message = "This pattern is empty, use `_` instead";
|
||||
let replacement = make::ident("_").node().clone();
|
||||
Some(Self::report().suggest(at, message, Suggestion::new(at, replacement)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
lib/src/lints/redundant_pattern_bind.rs
Normal file
41
lib/src/lints/redundant_pattern_bind.rs
Normal file
@ -0,0 +1,41 @@
|
||||
use crate::{Lint, Metadata, Report, Rule, Suggestion};
|
||||
|
||||
use if_chain::if_chain;
|
||||
use macros::lint;
|
||||
use rnix::{
|
||||
types::{Pattern, TokenWrapper, TypedNode},
|
||||
NodeOrToken, SyntaxElement, SyntaxKind,
|
||||
};
|
||||
|
||||
#[lint(
|
||||
name = "redundant pattern bind",
|
||||
note = "Found redundant pattern bind in function argument",
|
||||
code = 10,
|
||||
match_with = SyntaxKind::NODE_PATTERN
|
||||
)]
|
||||
struct RedundantPatternBind;
|
||||
|
||||
impl Rule for RedundantPatternBind {
|
||||
fn validate(&self, node: &SyntaxElement) -> Option<Report> {
|
||||
if_chain! {
|
||||
if let NodeOrToken::Node(node) = node;
|
||||
if let Some(pattern) = Pattern::cast(node.clone());
|
||||
// no patterns within `{ }`
|
||||
if pattern.entries().count() == 0;
|
||||
|
||||
// pattern is just ellipsis
|
||||
if pattern.ellipsis();
|
||||
|
||||
// pattern is bound
|
||||
if let Some(ident) = pattern.at();
|
||||
then {
|
||||
let at = node.text_range();
|
||||
let message = format!("This pattern bind is redundant, use `{}` instead", ident.as_str());
|
||||
let replacement = ident.node().clone();
|
||||
Some(Self::report().suggest(at, message, Suggestion::new(at, replacement)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
33
lib/src/lints/unquoted_splice.rs
Normal file
33
lib/src/lints/unquoted_splice.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use crate::{make, Lint, Metadata, Report, Rule, Suggestion};
|
||||
|
||||
use if_chain::if_chain;
|
||||
use macros::lint;
|
||||
use rnix::{
|
||||
types::{Dynamic, TypedNode},
|
||||
NodeOrToken, SyntaxElement, SyntaxKind,
|
||||
};
|
||||
|
||||
#[lint(
|
||||
name = "unquoted splice",
|
||||
note = "Found unquoted splice expression",
|
||||
code = 9,
|
||||
match_with = SyntaxKind::NODE_DYNAMIC
|
||||
)]
|
||||
struct UnquotedSplice;
|
||||
|
||||
impl Rule for UnquotedSplice {
|
||||
fn validate(&self, node: &SyntaxElement) -> Option<Report> {
|
||||
if_chain! {
|
||||
if let NodeOrToken::Node(node) = node;
|
||||
if Dynamic::cast(node.clone()).is_some();
|
||||
then {
|
||||
let at = node.text_range();
|
||||
let replacement = make::quote(&node).node().clone();
|
||||
let message = "Consider quoting this splice expression";
|
||||
Some(Self::report().suggest(at, message, Suggestion::new(at, replacement)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,10 @@ pub fn parenthesize(node: &SyntaxNode) -> types::Paren {
|
||||
ast_from_text(&format!("({})", node))
|
||||
}
|
||||
|
||||
pub fn quote(node: &SyntaxNode) -> types::Str {
|
||||
ast_from_text(&format!("\"{}\"", node))
|
||||
}
|
||||
|
||||
pub fn unary_not(node: &SyntaxNode) -> types::UnaryOp {
|
||||
ast_from_text(&format!("!{}", node))
|
||||
}
|
||||
|
@ -40,6 +40,13 @@ Lint ideas
|
||||
- manual map over list
|
||||
- merge inherit
|
||||
- merge inherit-from
|
||||
- empty inherit
|
||||
- useless antiquote/splice (where is antiquote truly
|
||||
required?)
|
||||
- useless variadic (things like `{...} : expr`, replace with
|
||||
`_: expr`)
|
||||
- redundant pattern `{...} @ inputs : expr`, replace with
|
||||
`inputs: expr`
|
||||
|
||||
Extensions
|
||||
----------
|
||||
|
Loading…
Reference in New Issue
Block a user