Skip to content

Commit

Permalink
refactor: avoid recursions
Browse files Browse the repository at this point in the history
  • Loading branch information
Kazuhiro-Mimaki committed May 8, 2024
1 parent 673d24e commit 51ec481
Showing 1 changed file with 108 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use biome_console::markup;
use biome_css_syntax::{
AnyCssMediaAndCombinableCondition, AnyCssMediaCondition, AnyCssMediaInParens,
AnyCssMediaOrCombinableCondition, AnyCssMediaQuery, AnyCssMediaTypeCondition,
AnyCssMediaTypeQuery, AnyCssQueryFeature, CssMediaConditionQuery, CssMediaQueryList,
AnyCssMediaTypeQuery, AnyCssQueryFeature, CssMediaAndCondition, CssMediaConditionQuery,
CssMediaOrCondition, CssMediaQueryList,
};
use biome_rowan::AstNode;

Expand All @@ -14,7 +15,7 @@ declare_rule! {
///
/// This rule considers media feature names defined in the CSS Specifications, up to and including Editor's Drafts, to be known.
/// This rule also checks vendor-prefixed media feature names.
///
///
/// Data sources of known CSS media feature are:
/// - MDN reference on [CSS media feature](https://developer.mozilla.org/en-US/docs/Web/CSS/@media)
/// - W3C reference on [Media Queries Level 3](https://www.w3.org/TR/mediaqueries-3/)
Expand Down Expand Up @@ -79,8 +80,7 @@ impl Rule for NoUnknownMediaFeatureName {
fn run(ctx: &RuleContext<Self>) -> Option<Self::State> {
let media_query_list = ctx.query();
for any_css_media_query in media_query_list.into_iter() {
let any_css_media_query = any_css_media_query.ok()?;
match any_css_media_query {
match any_css_media_query.ok()? {
AnyCssMediaQuery::CssMediaConditionQuery(css_media_condition_query) => {
if is_invalid_feature_name_included_in_css_media_condition_query(
css_media_condition_query,
Expand Down Expand Up @@ -124,28 +124,15 @@ impl Rule for NoUnknownMediaFeatureName {
fn is_invalid_feature_name_included_in_css_media_condition_query(
css_media_condition_query: CssMediaConditionQuery,
) -> Option<bool> {
let any_css_media_condition = css_media_condition_query.condition().ok()?;
match any_css_media_condition {
match css_media_condition_query.condition().ok()? {
AnyCssMediaCondition::AnyCssMediaInParens(any_css_media_in_parens) => {
has_invalid_media_feature_name(any_css_media_in_parens)
}
AnyCssMediaCondition::CssMediaAndCondition(css_media_and_condition) => {
let left = css_media_and_condition.left().ok()?;
let has_invalid_query = has_invalid_media_feature_name(left)?;
if has_invalid_query {
return Some(true);
}
let right = css_media_and_condition.right().ok()?;
check_any_css_media_and_combinable_condition(right)
is_css_media_and_condition_invalid(css_media_and_condition)
}
AnyCssMediaCondition::CssMediaOrCondition(css_media_or_condition) => {
let left = css_media_or_condition.left().ok()?;
let has_invalid_query = has_invalid_media_feature_name(left)?;
if has_invalid_query {
return Some(true);
}
let right = css_media_or_condition.right().ok()?;
check_any_css_media_or_combinable_condition(right)
is_css_media_or_condition_invalid(css_media_or_condition)
}
AnyCssMediaCondition::CssMediaNotCondition(css_media_not_condition) => {
has_invalid_media_feature_name(css_media_not_condition.condition().ok()?)
Expand All @@ -159,19 +146,12 @@ fn is_invalid_feature_name_included_in_css_media_type_query(
match any_css_media_type_query {
AnyCssMediaTypeQuery::CssMediaTypeQuery(_) => Some(false),
AnyCssMediaTypeQuery::CssMediaAndTypeQuery(css_media_and_type_query) => {
let any_css_media_type_condition = css_media_and_type_query.right().ok()?;
match any_css_media_type_condition {
match css_media_and_type_query.right().ok()? {
AnyCssMediaTypeCondition::AnyCssMediaInParens(any_css_media_in_parens) => {
has_invalid_media_feature_name(any_css_media_in_parens)
}
AnyCssMediaTypeCondition::CssMediaAndCondition(css_media_and_condition) => {
let left = css_media_and_condition.left().ok()?;
let has_invalid_query = has_invalid_media_feature_name(left)?;
if has_invalid_query {
return Some(true);
}
let right = css_media_and_condition.right().ok()?;
check_any_css_media_and_combinable_condition(right)
is_css_media_and_condition_invalid(css_media_and_condition)
}
AnyCssMediaTypeCondition::CssMediaNotCondition(css_media_not_condition) => {
has_invalid_media_feature_name(css_media_not_condition.condition().ok()?)
Expand All @@ -181,83 +161,124 @@ fn is_invalid_feature_name_included_in_css_media_type_query(
}
}

fn check_any_css_media_and_combinable_condition(
any_css_media_and_combinable_condition: AnyCssMediaAndCombinableCondition,
fn is_css_media_and_condition_invalid(
css_media_and_condition: CssMediaAndCondition,
) -> Option<bool> {
match any_css_media_and_combinable_condition {
AnyCssMediaAndCombinableCondition::AnyCssMediaInParens(any_css_media_in_parens) => {
has_invalid_media_feature_name(any_css_media_in_parens)
}
AnyCssMediaAndCombinableCondition::CssMediaAndCondition(css_media_and_condition) => {
let left = css_media_and_condition.left().ok()?;
let has_invalid_query = has_invalid_media_feature_name(left)?;
if has_invalid_query {
return Some(true);
if has_invalid_media_feature_name(css_media_and_condition.left().ok()?)? {
return Some(true);
}
let mut stack = vec![css_media_and_condition.right().ok()?];
while stack.len() > 0 {
let element = stack.pop()?;
match element {
AnyCssMediaAndCombinableCondition::AnyCssMediaInParens(any_css_media_in_parens) => {
return has_invalid_media_feature_name(any_css_media_in_parens);
}
AnyCssMediaAndCombinableCondition::CssMediaAndCondition(css_media_and_condition) => {
if has_invalid_media_feature_name(css_media_and_condition.left().ok()?)? {
return Some(true);
}
stack.push(css_media_and_condition.right().ok()?);
}
let right = css_media_and_condition.right().ok()?;
check_any_css_media_and_combinable_condition(right)
}
}
Some(false)
}

fn check_any_css_media_or_combinable_condition(
any_css_media_or_combinable_condition: AnyCssMediaOrCombinableCondition,
) -> Option<bool> {
match any_css_media_or_combinable_condition {
AnyCssMediaOrCombinableCondition::AnyCssMediaInParens(any_css_media_in_parens) => {
has_invalid_media_feature_name(any_css_media_in_parens)
}
AnyCssMediaOrCombinableCondition::CssMediaOrCondition(css_media_or_condition) => {
let left = css_media_or_condition.left().ok()?;
let has_invalid_query = has_invalid_media_feature_name(left)?;
if has_invalid_query {
return Some(true);
fn is_css_media_or_condition_invalid(css_media_or_condition: CssMediaOrCondition) -> Option<bool> {
if has_invalid_media_feature_name(css_media_or_condition.left().ok()?)? {
return Some(true);
}
let mut stack = vec![css_media_or_condition.right().ok()?];
while stack.len() > 0 {
let element = stack.pop()?;
match element {
AnyCssMediaOrCombinableCondition::AnyCssMediaInParens(any_css_media_in_parens) => {
return has_invalid_media_feature_name(any_css_media_in_parens);
}
AnyCssMediaOrCombinableCondition::CssMediaOrCondition(css_media_or_condition) => {
if has_invalid_media_feature_name(css_media_or_condition.left().ok()?)? {
return Some(true);
}
stack.push(css_media_or_condition.right().ok()?);
}
let right = css_media_or_condition.right().ok()?;
check_any_css_media_or_combinable_condition(right)
}
}
Some(false)
}

fn has_invalid_media_feature_name(any_css_media_in_parens: AnyCssMediaInParens) -> Option<bool> {
match any_css_media_in_parens {
AnyCssMediaInParens::CssMediaFeatureInParens(css_media_feature_in_parens) => {
let feature_name = get_feature_name(css_media_feature_in_parens.feature().ok()?)?;
if is_media_feature_name(&feature_name) {
return Some(false);
}
Some(true)
}
AnyCssMediaInParens::CssMediaConditionInParens(css_media_condition_in_parens) => {
let any_css_media_condition = css_media_condition_in_parens.condition().ok()?;
match any_css_media_condition {
AnyCssMediaCondition::AnyCssMediaInParens(any_css_media_in_parens) => {
has_invalid_media_feature_name(any_css_media_in_parens)
let mut any_css_media_in_parens_stack = vec![any_css_media_in_parens];
while any_css_media_in_parens_stack.len() > 0 {
let any_css_media_in_parens = any_css_media_in_parens_stack.pop()?;
match any_css_media_in_parens {
AnyCssMediaInParens::CssMediaFeatureInParens(css_media_feature_in_parens) => {
let feature_name = get_feature_name(css_media_feature_in_parens.feature().ok()?)?;
if is_media_feature_name(&feature_name) {
continue;
}
AnyCssMediaCondition::CssMediaAndCondition(css_media_and_condition) => {
let left = css_media_and_condition.left().ok()?;
let has_invalid_query = has_invalid_media_feature_name(left)?;
if has_invalid_query {
return Some(true);
return Some(true);
}
AnyCssMediaInParens::CssMediaConditionInParens(css_media_condition_in_parens) => {
match css_media_condition_in_parens.condition().ok()? {
AnyCssMediaCondition::AnyCssMediaInParens(any_css_media_in_parens) => {
any_css_media_in_parens_stack.push(any_css_media_in_parens);
}
let right = css_media_and_condition.right().ok()?;
check_any_css_media_and_combinable_condition(right)
}
AnyCssMediaCondition::CssMediaOrCondition(css_media_or_condition) => {
let left = css_media_or_condition.left().ok()?;
let has_invalid_query = has_invalid_media_feature_name(left)?;
if has_invalid_query {
return Some(true);
AnyCssMediaCondition::CssMediaAndCondition(css_media_and_condition) => {
any_css_media_in_parens_stack.push(css_media_and_condition.left().ok()?);
let mut css_media_and_condition_stack =
vec![css_media_and_condition.right().ok()?];
while css_media_and_condition_stack.len() > 0 {
let element = css_media_and_condition_stack.pop()?;
match element {
AnyCssMediaAndCombinableCondition::AnyCssMediaInParens(
any_css_media_in_parens,
) => {
any_css_media_in_parens_stack.push(any_css_media_in_parens);
}
AnyCssMediaAndCombinableCondition::CssMediaAndCondition(
css_media_and_condition,
) => {
any_css_media_in_parens_stack
.push(css_media_and_condition.left().ok()?);
css_media_and_condition_stack
.push(css_media_and_condition.right().ok()?);
}
}
}
}
AnyCssMediaCondition::CssMediaOrCondition(css_media_or_condition) => {
any_css_media_in_parens_stack.push(css_media_or_condition.left().ok()?);
let mut css_media_or_condition_stack =
vec![css_media_or_condition.right().ok()?];
while css_media_or_condition_stack.len() > 0 {
let element = css_media_or_condition_stack.pop()?;
match element {
AnyCssMediaOrCombinableCondition::AnyCssMediaInParens(
any_css_media_in_parens,
) => {
any_css_media_in_parens_stack.push(any_css_media_in_parens);
}
AnyCssMediaOrCombinableCondition::CssMediaOrCondition(
css_media_or_condition,
) => {
any_css_media_in_parens_stack
.push(css_media_or_condition.left().ok()?);
css_media_or_condition_stack
.push(css_media_or_condition.right().ok()?);
}
}
}
}
AnyCssMediaCondition::CssMediaNotCondition(css_media_not_condition) => {
any_css_media_in_parens_stack
.push(css_media_not_condition.condition().ok()?);
}
let right = css_media_or_condition.right().ok()?;
check_any_css_media_or_combinable_condition(right)
}
AnyCssMediaCondition::CssMediaNotCondition(css_media_not_condition) => {
has_invalid_media_feature_name(css_media_not_condition.condition().ok()?)
}
}
}
}
Some(false)
}

fn get_feature_name(any_css_query_feature: AnyCssQueryFeature) -> Option<String> {
Expand Down

0 comments on commit 51ec481

Please sign in to comment.