-
-
Notifications
You must be signed in to change notification settings - Fork 452
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(biome_css_analyzer): implement noDuplicateAtImportRules (#2658)
- Loading branch information
1 parent
7aed8d9
commit 150dd0e
Showing
17 changed files
with
361 additions
and
50 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
crates/biome_css_analyze/src/lint/nursery/no_duplicate_at_import_rules.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
use std::collections::{HashMap, HashSet}; | ||
|
||
use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic, RuleSource}; | ||
use biome_console::markup; | ||
use biome_css_syntax::{AnyCssAtRule, AnyCssRule, CssImportAtRule, CssRuleList}; | ||
use biome_rowan::AstNode; | ||
|
||
declare_rule! { | ||
/// Disallow duplicate `@import` rules. | ||
/// | ||
/// This rule checks if the file urls of the @import rules are duplicates. | ||
/// | ||
/// This rule also checks the imported media queries and alerts of duplicates. | ||
/// | ||
/// ## Examples | ||
/// | ||
/// ### Invalid | ||
/// | ||
/// ```css,expect_diagnostic | ||
/// @import 'a.css'; | ||
/// @import 'a.css'; | ||
/// ``` | ||
/// | ||
/// ```css,expect_diagnostic | ||
/// @import "a.css"; | ||
/// @import 'a.css'; | ||
/// ``` | ||
/// | ||
/// ```css,expect_diagnostic | ||
/// @import url('a.css'); | ||
/// @import url('a.css'); | ||
/// ``` | ||
/// | ||
/// ### Valid | ||
/// | ||
/// ```css | ||
/// @import 'a.css'; | ||
/// @import 'b.css'; | ||
/// ``` | ||
/// | ||
/// ```css | ||
/// @import url('a.css') tv; | ||
/// @import url('a.css') projection; | ||
/// ``` | ||
/// | ||
pub NoDuplicateAtImportRules { | ||
version: "next", | ||
name: "noDuplicateAtImportRules", | ||
recommended: true, | ||
sources: &[RuleSource::Stylelint("no-duplicate-at-import-rules")], | ||
} | ||
} | ||
|
||
impl Rule for NoDuplicateAtImportRules { | ||
type Query = Ast<CssRuleList>; | ||
type State = CssImportAtRule; | ||
type Signals = Option<Self::State>; | ||
type Options = (); | ||
|
||
fn run(ctx: &RuleContext<Self>) -> Option<Self::State> { | ||
let node = ctx.query(); | ||
let mut import_url_map: HashMap<String, HashSet<String>> = HashMap::new(); | ||
for rule in node { | ||
match rule { | ||
AnyCssRule::CssAtRule(item) => match item.rule().ok()? { | ||
AnyCssAtRule::CssImportAtRule(import_rule) => { | ||
let import_url = import_rule | ||
.url() | ||
.ok()? | ||
.text() | ||
.to_lowercase() | ||
.replace("url(", "") | ||
.replace(')', ""); | ||
if let Some(media_query_set) = import_url_map.get_mut(&import_url) { | ||
// if the current import_rule has no media queries or there are no queries saved in the | ||
// media_query_set, this is always a duplicate | ||
if import_rule.media().text().is_empty() || media_query_set.is_empty() { | ||
return Some(import_rule); | ||
} | ||
|
||
for media in import_rule.media() { | ||
match media { | ||
Ok(media) => { | ||
if !media_query_set.insert(media.text().to_lowercase()) { | ||
return Some(import_rule); | ||
} | ||
} | ||
_ => return None, | ||
} | ||
} | ||
} else { | ||
let mut media_set: HashSet<String> = HashSet::new(); | ||
for media in import_rule.media() { | ||
match media { | ||
Ok(media) => { | ||
media_set.insert(media.text().to_lowercase()); | ||
} | ||
_ => return None, | ||
} | ||
} | ||
import_url_map.insert(import_url, media_set); | ||
} | ||
} | ||
_ => return None, | ||
}, | ||
_ => return None, | ||
} | ||
} | ||
None | ||
} | ||
|
||
fn diagnostic(_: &RuleContext<Self>, node: &Self::State) -> Option<RuleDiagnostic> { | ||
let span = node.range(); | ||
Some( | ||
RuleDiagnostic::new( | ||
rule_category!(), | ||
span, | ||
markup! { | ||
"Each "<Emphasis>"@import"</Emphasis>" should be unique unless differing by media queries." | ||
}, | ||
) | ||
.note(markup! { | ||
"Consider removing one of the duplicated imports." | ||
}), | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
crates/biome_css_analyze/tests/specs/nursery/noDuplicateAtImportRules/invalid.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
@import "a.css"; | ||
@import "b.css"; | ||
@import "a.css"; |
28 changes: 28 additions & 0 deletions
28
crates/biome_css_analyze/tests/specs/nursery/noDuplicateAtImportRules/invalid.css.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--- | ||
source: crates/biome_css_analyze/tests/spec_tests.rs | ||
expression: invalid.css | ||
--- | ||
# Input | ||
```css | ||
@import "a.css"; | ||
@import "b.css"; | ||
@import "a.css"; | ||
``` | ||
|
||
# Diagnostics | ||
``` | ||
invalid.css:3:2 lint/nursery/noDuplicateAtImportRules ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
! Each @import should be unique unless differing by media queries. | ||
1 │ @import "a.css"; | ||
2 │ @import "b.css"; | ||
> 3 │ @import "a.css"; | ||
│ ^^^^^^^^^^^^^^^ | ||
4 │ | ||
i Consider removing one of the duplicated imports. | ||
``` |
3 changes: 3 additions & 0 deletions
3
crates/biome_css_analyze/tests/specs/nursery/noDuplicateAtImportRules/invalidMedia.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
@import url("a.css") tv; | ||
@import url("a.css") projection; | ||
@import "a.css"; |
28 changes: 28 additions & 0 deletions
28
crates/biome_css_analyze/tests/specs/nursery/noDuplicateAtImportRules/invalidMedia.css.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--- | ||
source: crates/biome_css_analyze/tests/spec_tests.rs | ||
expression: invalidMedia.css | ||
--- | ||
# Input | ||
```css | ||
@import url("a.css") tv; | ||
@import url("a.css") projection; | ||
@import "a.css"; | ||
``` | ||
|
||
# Diagnostics | ||
``` | ||
invalidMedia.css:3:2 lint/nursery/noDuplicateAtImportRules ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
! Each @import should be unique unless differing by media queries. | ||
1 │ @import url("a.css") tv; | ||
2 │ @import url("a.css") projection; | ||
> 3 │ @import "a.css"; | ||
│ ^^^^^^^^^^^^^^^ | ||
4 │ | ||
i Consider removing one of the duplicated imports. | ||
``` |
3 changes: 3 additions & 0 deletions
3
...s/biome_css_analyze/tests/specs/nursery/noDuplicateAtImportRules/invalidMultipleMedia.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
@import url("a.css") tv, projection; | ||
@import url("a.css") mobile; | ||
@import url("a.css") tv; |
28 changes: 28 additions & 0 deletions
28
...me_css_analyze/tests/specs/nursery/noDuplicateAtImportRules/invalidMultipleMedia.css.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--- | ||
source: crates/biome_css_analyze/tests/spec_tests.rs | ||
expression: invalidMultipleMedia.css | ||
--- | ||
# Input | ||
```css | ||
@import url("a.css") tv, projection; | ||
@import url("a.css") mobile; | ||
@import url("a.css") tv; | ||
``` | ||
|
||
# Diagnostics | ||
``` | ||
invalidMultipleMedia.css:3:2 lint/nursery/noDuplicateAtImportRules ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
! Each @import should be unique unless differing by media queries. | ||
1 │ @import url("a.css") tv, projection; | ||
2 │ @import url("a.css") mobile; | ||
> 3 │ @import url("a.css") tv; | ||
│ ^^^^^^^^^^^^^^^^^^^^^^^ | ||
4 │ | ||
i Consider removing one of the duplicated imports. | ||
``` |
2 changes: 2 additions & 0 deletions
2
crates/biome_css_analyze/tests/specs/nursery/noDuplicateAtImportRules/invalidUrls.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
@import url("c.css"); | ||
@import url("c.css"); |
26 changes: 26 additions & 0 deletions
26
crates/biome_css_analyze/tests/specs/nursery/noDuplicateAtImportRules/invalidUrls.css.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
source: crates/biome_css_analyze/tests/spec_tests.rs | ||
expression: invalidUrls.css | ||
--- | ||
# Input | ||
```css | ||
@import url("c.css"); | ||
@import url("c.css"); | ||
``` | ||
|
||
# Diagnostics | ||
``` | ||
invalidUrls.css:2:2 lint/nursery/noDuplicateAtImportRules ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
! Each @import should be unique unless differing by media queries. | ||
1 │ @import url("c.css"); | ||
> 2 │ @import url("c.css"); | ||
│ ^^^^^^^^^^^^^^^^^^^^ | ||
3 │ | ||
i Consider removing one of the duplicated imports. | ||
``` |
9 changes: 9 additions & 0 deletions
9
crates/biome_css_analyze/tests/specs/nursery/noDuplicateAtImportRules/valid.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* should not generate diagnostics */ | ||
@import "a.css"; | ||
@import "b.css"; | ||
|
||
@import url("c.css"); | ||
@import url("d.css"); | ||
|
||
@import url("e.css") tv; | ||
@import url("e.css") projection; |
17 changes: 17 additions & 0 deletions
17
crates/biome_css_analyze/tests/specs/nursery/noDuplicateAtImportRules/valid.css.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
--- | ||
source: crates/biome_css_analyze/tests/spec_tests.rs | ||
expression: valid.css | ||
--- | ||
# Input | ||
```css | ||
/* should not generate diagnostics */ | ||
@import "a.css"; | ||
@import "b.css"; | ||
@import url("c.css"); | ||
@import url("d.css"); | ||
@import url("e.css") tv; | ||
@import url("e.css") projection; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.