mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 17:54:15 +03:00
feat(css/lints): Add selector-max-combinators
rule (#3789)
This commit is contained in:
parent
761fb9c244
commit
e389bef3ad
@ -5,7 +5,8 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::rules::{
|
||||
at_rule_no_unknown::AtRuleNoUnknownConfig, color_hex_length::ColorHexLengthConfig,
|
||||
no_invalid_position_at_import_rule::NoInvalidPositionAtImportRuleConfig,
|
||||
selector_max_class::SelectorMaxClassConfig, unit_no_unknown::UnitNoUnknownConfig,
|
||||
selector_max_class::SelectorMaxClassConfig,
|
||||
selector_max_combinators::SelectorMaxCombinatorsConfig, unit_no_unknown::UnitNoUnknownConfig,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
@ -99,6 +100,9 @@ pub struct RulesConfig {
|
||||
|
||||
#[serde(default, alias = "unitNoUnknown")]
|
||||
pub unit_no_unknown: RuleConfig<UnitNoUnknownConfig>,
|
||||
|
||||
#[serde(default, alias = "selectorMaxCombinators")]
|
||||
pub selector_max_combinators: RuleConfig<SelectorMaxCombinatorsConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
|
@ -8,7 +8,8 @@ use crate::{
|
||||
keyframe_declaration_no_important::keyframe_declaration_no_important,
|
||||
no_empty_source::no_empty_source,
|
||||
no_invalid_position_at_import_rule::no_invalid_position_at_import_rule,
|
||||
selector_max_class::selector_max_class, unit_no_unknown::unit_no_unknown,
|
||||
selector_max_class::selector_max_class, selector_max_combinators::selector_max_combinators,
|
||||
unit_no_unknown::unit_no_unknown,
|
||||
},
|
||||
};
|
||||
|
||||
@ -21,6 +22,7 @@ pub mod keyframe_declaration_no_important;
|
||||
pub mod no_empty_source;
|
||||
pub mod no_invalid_position_at_import_rule;
|
||||
pub mod selector_max_class;
|
||||
pub mod selector_max_combinators;
|
||||
pub mod unit_no_unknown;
|
||||
|
||||
pub struct LintParams<'a> {
|
||||
@ -53,6 +55,9 @@ pub fn get_rules(LintParams { lint_config }: &LintParams) -> Vec<Box<dyn LintRul
|
||||
(&rules_config.color_no_invalid_hex).into(),
|
||||
));
|
||||
rules.push(unit_no_unknown((&rules_config.unit_no_unknown).into()));
|
||||
rules.push(selector_max_combinators(
|
||||
(&rules_config.selector_max_combinators).into(),
|
||||
));
|
||||
|
||||
rules
|
||||
}
|
||||
|
49
crates/swc_css_lints/src/rules/selector_max_combinators.rs
Normal file
49
crates/swc_css_lints/src/rules/selector_max_combinators.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use swc_css_ast::*;
|
||||
use swc_css_visit::{Visit, VisitWith};
|
||||
|
||||
use crate::rule::{visitor_rule, LintRule, LintRuleContext};
|
||||
|
||||
pub type SelectorMaxCombinatorsConfig = Option<usize>;
|
||||
|
||||
pub fn selector_max_combinators(
|
||||
ctx: LintRuleContext<SelectorMaxCombinatorsConfig>,
|
||||
) -> Box<dyn LintRule> {
|
||||
let max = ctx.config().unwrap_or(3);
|
||||
visitor_rule(SelectorMaxCombinators { ctx, max })
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct SelectorMaxCombinators {
|
||||
ctx: LintRuleContext<SelectorMaxCombinatorsConfig>,
|
||||
max: usize,
|
||||
}
|
||||
|
||||
impl SelectorMaxCombinators {
|
||||
fn build_message(&self, count: usize) -> String {
|
||||
let combinators = if self.max == 1 {
|
||||
"combinator"
|
||||
} else {
|
||||
"combinators"
|
||||
};
|
||||
format!(
|
||||
"Expected selector to have no more than {} {}, but {} actually.",
|
||||
self.max, combinators, count
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for SelectorMaxCombinators {
|
||||
fn visit_complex_selector(&mut self, complex_selector: &ComplexSelector) {
|
||||
let count = complex_selector
|
||||
.children
|
||||
.iter()
|
||||
.filter(|child| matches!(child, ComplexSelectorChildren::Combinator(..)))
|
||||
.count();
|
||||
|
||||
if count > self.max {
|
||||
self.ctx.report(complex_selector, self.build_message(count));
|
||||
}
|
||||
|
||||
complex_selector.visit_children_with(self);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"rules": {
|
||||
"selector-max-combinators": ["error", 2]
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
.a {}
|
||||
.a .b {}
|
||||
.a .b .c .d {}
|
||||
.a + .b > .c ~ .d {}
|
||||
.a ~ .b || .c + .d {}
|
@ -0,0 +1,18 @@
|
||||
error: Expected selector to have no more than 2 combinators, but 3 actually.
|
||||
--> $DIR/tests/rules/fail/selector-max-combinators/custom/input.css:3:1
|
||||
|
|
||||
3 | .a .b .c .d {}
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: Expected selector to have no more than 2 combinators, but 3 actually.
|
||||
--> $DIR/tests/rules/fail/selector-max-combinators/custom/input.css:4:1
|
||||
|
|
||||
4 | .a + .b > .c ~ .d {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: Expected selector to have no more than 2 combinators, but 3 actually.
|
||||
--> $DIR/tests/rules/fail/selector-max-combinators/custom/input.css:5:1
|
||||
|
|
||||
5 | .a ~ .b || .c + .d {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"rules": {
|
||||
"selector-max-combinators": ["error"]
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
.a ~ .b + .c .d > .e {}
|
||||
.a .b .c .d .e {}
|
@ -0,0 +1,12 @@
|
||||
error: Expected selector to have no more than 3 combinators, but 4 actually.
|
||||
--> $DIR/tests/rules/fail/selector-max-combinators/default/input.css:1:1
|
||||
|
|
||||
1 | .a ~ .b + .c .d > .e {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: Expected selector to have no more than 3 combinators, but 4 actually.
|
||||
--> $DIR/tests/rules/fail/selector-max-combinators/default/input.css:2:1
|
||||
|
|
||||
2 | .a .b .c .d .e {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"rules": {
|
||||
"selector-max-combinators": ["error", 5]
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
.a {}
|
||||
.a .b {}
|
||||
.a .b .c {}
|
||||
.a .b .c .d {}
|
||||
.a .b .c .d .e {}
|
||||
.a + .b ~ .c > .d .e {}
|
||||
.a + .b ~ .c > .d .e || .f {}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"rules": {
|
||||
"selector-max-combinators": ["error"]
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
.a.b.c.d {}
|
||||
.a .b.c.d {}
|
||||
.a .b .c.d {}
|
||||
.a .b .c .d {}
|
||||
.a + .b .c > .d {}
|
||||
.a ~ .b > .c + .d {}
|
||||
.a .b + .c {}
|
||||
.a + .b ~ .c > .d, .e > .f + .g ~ .h {}
|
Loading…
Reference in New Issue
Block a user