mirror of
https://github.com/oppiliappan/statix.git
synced 2024-07-07 06:56:20 +03:00
new lint: manual_inherit
This commit is contained in:
parent
088559eedd
commit
c00900120d
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
/target
|
||||
.envrc
|
||||
.direnv
|
||||
result
|
||||
|
|
|
@ -3,4 +3,5 @@ use crate::lint_map;
|
|||
lint_map! {
|
||||
bool_comparison,
|
||||
empty_let_in,
|
||||
manual_inherit,
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@ use crate::{Lint, Metadata, Report, Rule, Suggestion};
|
|||
use if_chain::if_chain;
|
||||
use macros::lint;
|
||||
use rnix::{
|
||||
types::{LetIn, TypedNode,
|
||||
EntryHolder},
|
||||
types::{LetIn, TypedNode, EntryHolder},
|
||||
NodeOrToken, SyntaxElement, SyntaxKind,
|
||||
};
|
||||
|
||||
|
|
43
lib/src/lints/manual_inherit.rs
Normal file
43
lib/src/lints/manual_inherit.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use crate::{make, Lint, Metadata, Report, Rule, Suggestion};
|
||||
|
||||
use if_chain::if_chain;
|
||||
use macros::lint;
|
||||
use rnix::{
|
||||
types::{KeyValue, Ident, TypedNode, TokenWrapper},
|
||||
NodeOrToken, SyntaxElement, SyntaxKind,
|
||||
};
|
||||
|
||||
#[lint(
|
||||
name = "manual inherit",
|
||||
note = "Assignment instead of `inherit` keyword",
|
||||
code = 3,
|
||||
match_with = SyntaxKind::NODE_KEY_VALUE
|
||||
)]
|
||||
struct ManualInherit;
|
||||
|
||||
impl Rule for ManualInherit {
|
||||
fn validate(&self, node: &SyntaxElement) -> Option<Report> {
|
||||
if_chain! {
|
||||
if let NodeOrToken::Node(key_value_node) = node;
|
||||
if let Some(key_value_stmt) = KeyValue::cast(key_value_node.clone());
|
||||
if let Some(key_path) = key_value_stmt.key();
|
||||
if let Some(key_node) = key_path.path().next();
|
||||
if let Some(key) = Ident::cast(key_node);
|
||||
|
||||
if let Some(value_node) = key_value_stmt.value();
|
||||
if let Some(value) = Ident::cast(value_node);
|
||||
|
||||
if key.as_str() == value.as_str();
|
||||
|
||||
then {
|
||||
let at = node.text_range();
|
||||
let replacement = make::inherit_stmt(&[key]).node().clone();
|
||||
let message = format!("The assignment `{}` is better written with `inherit`", node);
|
||||
Some(Self::report().suggest(at, message, Suggestion::new(at, replacement)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
use rnix::{SyntaxNode, types::{TypedNode, self}};
|
||||
use std::iter::IntoIterator;
|
||||
|
||||
use rnix::{SyntaxNode, types::{TypedNode, self, TokenWrapper}};
|
||||
|
||||
fn ast_from_text<N: TypedNode>(text: &str) -> N {
|
||||
let parse = rnix::parse(text);
|
||||
let node = match parse.node().descendants().find_map(N::cast) {
|
||||
Some(it) => it,
|
||||
None => {
|
||||
panic!("Failed to make ast node `{}` from text {}", std::any::type_name::<N>(), text)
|
||||
panic!("Failed to make ast node `{}` from text `{}`", std::any::type_name::<N>(), text)
|
||||
}
|
||||
};
|
||||
node
|
||||
|
@ -18,3 +20,12 @@ pub fn parenthesize(node: &SyntaxNode) -> types::Paren {
|
|||
pub fn unary_not(node: &SyntaxNode) -> types::UnaryOp {
|
||||
ast_from_text(&format!("!{}", node))
|
||||
}
|
||||
|
||||
pub fn inherit_stmt<'a>(nodes: impl IntoIterator<Item = &'a types::Ident>) -> types::Inherit {
|
||||
let inherited_idents = nodes
|
||||
.into_iter()
|
||||
.map(|i| i.as_str().to_owned())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
ast_from_text(&format!("{{ inherit {}; }}", inherited_idents))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user