Skip to content

Commit

Permalink
feat(linter): add suppression action for the css linter (biomejs#3304)
Browse files Browse the repository at this point in the history
  • Loading branch information
togami2864 authored and rishabh3112 committed Jul 6, 2024
1 parent 9e91314 commit 095ce5d
Show file tree
Hide file tree
Showing 7 changed files with 841 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ New entries must be placed in a section entitled `Unreleased`.
Read
our [guidelines for writing a good changelog entry](https://github.com/biomejs/biome/blob/main/CONTRIBUTING.md#changelog).

## Unreleased

- Implement [css suppression action](https://github.com/biomejs/biome/issues/3278). Contributed by @togami2864

## v1.8.3 (2022-06-27)

### CLI
Expand Down
87 changes: 78 additions & 9 deletions crates/biome_css_analyze/src/suppression_action.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use biome_analyze::{ApplySuppression, SuppressionAction};
use biome_css_syntax::CssLanguage;
use biome_rowan::{BatchMutation, SyntaxToken};
use biome_css_syntax::{CssLanguage, CssSyntaxToken};
use biome_rowan::{BatchMutation, TriviaPieceKind};

pub(crate) struct CssSuppressionAction;

Expand All @@ -9,18 +9,87 @@ impl SuppressionAction for CssSuppressionAction {

fn find_token_to_apply_suppression(
&self,
_original_token: SyntaxToken<Self::Language>,
token: CssSyntaxToken,
) -> Option<ApplySuppression<Self::Language>> {
// TODO: property implement. Look for the JsSuppressionAction for an example
None
let mut apply_suppression = ApplySuppression {
token_has_trailing_comments: false,
token_to_apply_suppression: token.clone(),
should_insert_leading_newline: false,
};
let mut current_token = token;
loop {
let trivia = current_token.leading_trivia();
if trivia.pieces().any(|trivia| trivia.kind().is_newline()) {
break;
} else if let Some(prev_token) = current_token.prev_token() {
current_token = prev_token
} else {
break;
}
}

apply_suppression.token_has_trailing_comments = current_token
.trailing_trivia()
.pieces()
.any(|trivia| trivia.kind().is_multiline_comment());
apply_suppression.token_to_apply_suppression = current_token;
Some(apply_suppression)
}

fn apply_suppression(
&self,
_mutation: &mut BatchMutation<Self::Language>,
_apply_suppression: ApplySuppression<Self::Language>,
_suppression_text: &str,
mutation: &mut BatchMutation<Self::Language>,
apply_suppression: ApplySuppression<Self::Language>,
suppression_text: &str,
) {
unreachable!("find_token_to_apply_suppression return None")
let ApplySuppression {
token_to_apply_suppression,
token_has_trailing_comments,
should_insert_leading_newline: _,
} = apply_suppression;

let mut new_token = token_to_apply_suppression.clone();
let has_leading_whitespace = new_token
.leading_trivia()
.pieces()
.any(|trivia| trivia.is_whitespace());

if token_has_trailing_comments {
new_token = new_token.with_trailing_trivia([
(
TriviaPieceKind::SingleLineComment,
format!("/* {}: <explanation> */", suppression_text).as_str(),
),
(TriviaPieceKind::Newline, "\n"),
]);
} else if has_leading_whitespace {
let suppression_comment = format!("/* {}: <explanation> */", suppression_text);
let mut trivia = vec![
(
TriviaPieceKind::SingleLineComment,
suppression_comment.as_str(),
),
(TriviaPieceKind::Newline, "\n"),
];
let leading_whitespace: Vec<_> = new_token
.leading_trivia()
.pieces()
.filter(|p| p.is_whitespace())
.collect();

for w in leading_whitespace.iter() {
trivia.push((TriviaPieceKind::Whitespace, w.text()));
}
new_token = new_token.with_leading_trivia(trivia);
} else {
new_token = new_token.with_leading_trivia([
(
TriviaPieceKind::SingleLineComment,
format!("/* {}: <explanation> */", suppression_text).as_str(),
),
(TriviaPieceKind::Newline, "\n"),
]);
}
mutation.replace_token_transfer_trivia(token_to_apply_suppression, new_token);
}
}
2 changes: 1 addition & 1 deletion crates/biome_css_analyze/tests/spec_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ fn check_code_action(
assert_errors_are_absent(re_parse.tree().syntax(), re_parse.diagnostics(), path);
}

pub(crate) fn _run_suppression_test(input: &'static str, _: &str, _: &str, _: &str) {
pub(crate) fn run_suppression_test(input: &'static str, _: &str, _: &str, _: &str) {
register_leak_checker();

let input_file = Path::new(input);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
a { font-family: "Lucida Grande", 'Arial', sans-serif, sans-serif; }
a { font-family: 'Arial', "Lucida Grande", Arial, sans-serif; }
a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
a { font-family: 'Times', Times }
a { FONT: italic 300 16px/30px Arial, " Arial", serif; }
b { font: normal 14px/32px -apple-system, BlinkMacSystemFont, sans-serif, sans-serif; }
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
---
source: crates/biome_css_analyze/tests/spec_tests.rs
expression: noDuplicateFontNames.css
---
# Input
```css
a { font-family: "Lucida Grande", 'Arial', sans-serif, sans-serif; }
a { font-family: 'Arial', "Lucida Grande", Arial, sans-serif; }
a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
a { font-family: 'Times', Times }
a { FONT: italic 300 16px/30px Arial, " Arial", serif; }
b { font: normal 14px/32px -apple-system, BlinkMacSystemFont, sans-serif, sans-serif; }
```

# Diagnostics
```
noDuplicateFontNames.css:1:56 lint/nursery/noDuplicateFontNames FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━
! Duplicate font names are redundant and unnecessary: sans-serif
> 1 │ a { font-family: "Lucida Grande", 'Arial', sans-serif, sans-serif; }
│ ^^^^^^^^^^
2 │ a { font-family: 'Arial', "Lucida Grande", Arial, sans-serif; }
3 │ a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
i Remove duplicate font names within the property
i Safe fix: Suppress rule lint/nursery/noDuplicateFontNames
1 │ - a·{·font-family"Lucida·Grande"'Arial'sans-serifsans-serif}
1 │ + /*·biome-ignore·lint/nursery/noDuplicateFontNames:·<explanation>·*/
2 │ + a··{·font-family"Lucida·Grande"'Arial'sans-serifsans-serif}
2 3 │ a { font-family: 'Arial', "Lucida Grande", Arial, sans-serif; }
3 4 │ a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
```
```
noDuplicateFontNames.css:2:44 lint/nursery/noDuplicateFontNames FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━
! Duplicate font names are redundant and unnecessary: Arial
1 │ a { font-family: "Lucida Grande", 'Arial', sans-serif, sans-serif; }
> 2 │ a { font-family: 'Arial', "Lucida Grande", Arial, sans-serif; }
│ ^^^^^
3 │ a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
4 │ a { font-family: 'Times', Times }
i Remove duplicate font names within the property
i Safe fix: Suppress rule lint/nursery/noDuplicateFontNames
1 1 │ a { font-family: "Lucida Grande", 'Arial', sans-serif, sans-serif; }
2 │ - a·{·font-family'Arial'"Lucida·Grande"Arialsans-serif}
2 │ + /*·biome-ignore·lint/nursery/noDuplicateFontNames:·<explanation>·*/
3 │ + a··{·font-family'Arial'"Lucida·Grande"Arialsans-serif}
3 4 │ a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
4 5 │ a { font-family: 'Times', Times }
```
```
noDuplicateFontNames.css:3:35 lint/nursery/noDuplicateFontNames FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━
! Duplicate font names are redundant and unnecessary: LucidaGrande
1 │ a { font-family: "Lucida Grande", 'Arial', sans-serif, sans-serif; }
2 │ a { font-family: 'Arial', "Lucida Grande", Arial, sans-serif; }
> 3 │ a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
│ ^^^^^^^^^^^^^^^^^^
4 │ a { font-family: 'Times', Times }
5 │ a { FONT: italic 300 16px/30px Arial, " Arial", serif; }
i Remove duplicate font names within the property
i Safe fix: Suppress rule lint/nursery/noDuplicateFontNames
1 1 │ a { font-family: "Lucida Grande", 'Arial', sans-serif, sans-serif; }
2 2 │ a { font-family: 'Arial', "Lucida Grande", Arial, sans-serif; }
3 │ - a·{·fOnT-fAmIlY"Lucida·Grande"'··Lucida·Grande·'sans-serif}
3 │ + /*·biome-ignore·lint/nursery/noDuplicateFontNames:·<explanation>·*/
4 │ + a··{·fOnT-fAmIlY"Lucida·Grande"'··Lucida·Grande·'sans-serif}
4 5 │ a { font-family: 'Times', Times }
5 6 │ a { FONT: italic 300 16px/30px Arial, " Arial", serif; }
```
```
noDuplicateFontNames.css:4:27 lint/nursery/noDuplicateFontNames FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━
! Duplicate font names are redundant and unnecessary: Times
2 │ a { font-family: 'Arial', "Lucida Grande", Arial, sans-serif; }
3 │ a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
> 4 │ a { font-family: 'Times', Times }
│ ^^^^^
5 │ a { FONT: italic 300 16px/30px Arial, " Arial", serif; }
6 │ b { font: normal 14px/32px -apple-system, BlinkMacSystemFont, sans-serif, sans-serif; }
i Remove duplicate font names within the property
i Safe fix: Suppress rule lint/nursery/noDuplicateFontNames
2 2 │ a { font-family: 'Arial', "Lucida Grande", Arial, sans-serif; }
3 3 │ a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
4 │ - a·{·font-family'Times'Times·}
4 │ + /*·biome-ignore·lint/nursery/noDuplicateFontNames:·<explanation>·*/
5 │ + a··{·font-family'Times'Times·}
5 6 │ a { FONT: italic 300 16px/30px Arial, " Arial", serif; }
6 7 │ b { font: normal 14px/32px -apple-system, BlinkMacSystemFont, sans-serif, sans-serif; }
```
```
noDuplicateFontNames.css:5:39 lint/nursery/noDuplicateFontNames FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━
! Duplicate font names are redundant and unnecessary: Arial
3 │ a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
4 │ a { font-family: 'Times', Times }
> 5 │ a { FONT: italic 300 16px/30px Arial, " Arial", serif; }
│ ^^^^^^^^
6 │ b { font: normal 14px/32px -apple-system, BlinkMacSystemFont, sans-serif, sans-serif; }
i Remove duplicate font names within the property
i Safe fix: Suppress rule lint/nursery/noDuplicateFontNames
3 3 │ a { fOnT-fAmIlY: "Lucida Grande", ' Lucida Grande ', sans-serif; }
4 4 │ a { font-family: 'Times', Times }
5 │ - a·{·FONTitalic·300·16px/30px·Arial"·Arial"serif}
5 │ + /*·biome-ignore·lint/nursery/noDuplicateFontNames:·<explanation>·*/
6 │ + a··{·FONTitalic·300·16px/30px·Arial"·Arial"serif}
6 7 │ b { font: normal 14px/32px -apple-system, BlinkMacSystemFont, sans-serif, sans-serif; }
```
```
noDuplicateFontNames.css:6:75 lint/nursery/noDuplicateFontNames FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━
! Duplicate font names are redundant and unnecessary: sans-serif
4 │ a { font-family: 'Times', Times }
5 │ a { FONT: italic 300 16px/30px Arial, " Arial", serif; }
> 6 │ b { font: normal 14px/32px -apple-system, BlinkMacSystemFont, sans-serif, sans-serif; }
│ ^^^^^^^^^^
i Remove duplicate font names within the property
i Safe fix: Suppress rule lint/nursery/noDuplicateFontNames
4 4 │ a { font-family: 'Times', Times }
5 5 │ a { FONT: italic 300 16px/30px Arial, " Arial", serif; }
6 │ - b·{·fontnormal·14px/32px·-apple-systemBlinkMacSystemFontsans-serifsans-serif}
6 │ + /*·biome-ignore·lint/nursery/noDuplicateFontNames:·<explanation>·*/
7 │ + b··{·fontnormal·14px/32px·-apple-systemBlinkMacSystemFontsans-serifsans-serif}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* CssDeclarationOrRuleBlock */
a {}
a { }
a {

}

.b {}
.b { }
.b {

}

/* CssRuleBlock */
@media print {}
@media print {

}
@media print { a {} }

/* CssDeclarationBlock */
@font-palette-values --ident {}
@font-face {}

/* CssKeyframesBlock */
@keyframes slidein {}
@keyframes slidein {
from {
}

to {
transform: translateX(100%);
}
}

/* CssFontFeatureValuesBlock */
@font-feature-values Font One {
@styleset {

}
}

/* CssPageAtRuleBlock */
@page {}
@page :right {
}


/* CssDeclarationOrAtRuleBlock */
@page :left { @left-middle {} background: red; }
@page {
@top-right {

}
}
Loading

0 comments on commit 095ce5d

Please sign in to comment.