From a33755bb7215e2e52bccfc55185879037fd3037b Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 09:47:24 +0900 Subject: [PATCH 01/17] feat: noInvalidPositionAtImportRule --- .../biome_configuration/src/linter/rules.rs | 84 +++++++++------ crates/biome_css_analyze/src/lint/nursery.rs | 2 + .../no_invalid_position_at_import_rule.rs | 101 ++++++++++++++++++ crates/biome_css_analyze/src/options.rs | 1 + .../noInvalidPositionAtImportRule/invalid.css | 2 + .../invalid.css.snap | 28 +++++ .../invalidBetweenImport.css | 3 + .../invalidBetweenImport.css.snap | 30 ++++++ .../invalidMediaImport.css | 2 + .../invalidMediaImport.css.snap | 28 +++++ .../invalidMediaImportUpperCase.css | 2 + .../invalidMediaImportUpperCase.css.snap | 28 +++++ .../noInvalidPositionAtImportRule/valid.css | 2 + .../valid.css.snap | 10 ++ .../validCharset.css | 2 + .../validCharset.css.snap | 10 ++ .../validCharsetMultipleImport.css | 3 + .../validCharsetMultipleImport.css.snap | 11 ++ .../validComment.css | 2 + .../validComment.css.snap | 10 ++ .../validLayerImport.css | 2 + .../validLayerImport.css.snap | 10 ++ .../validMultipleImport.css | 2 + .../validMultipleImport.css.snap | 10 ++ .../validNoImportant.css | 1 + .../validNoImportant.css.snap | 9 ++ .../src/categories.rs | 1 + .../@biomejs/backend-jsonrpc/src/workspace.ts | 5 + .../@biomejs/biome/configuration_schema.json | 7 ++ 29 files changed, 376 insertions(+), 32 deletions(-) create mode 100644 crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/valid.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/valid.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharset.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharset.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharsetMultipleImport.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharsetMultipleImport.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validComment.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validComment.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validLayerImport.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validLayerImport.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validMultipleImport.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validMultipleImport.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validNoImportant.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validNoImportant.css.snap diff --git a/crates/biome_configuration/src/linter/rules.rs b/crates/biome_configuration/src/linter/rules.rs index 19b5a58c189..37d0f4e34d1 100644 --- a/crates/biome_configuration/src/linter/rules.rs +++ b/crates/biome_configuration/src/linter/rules.rs @@ -2687,6 +2687,10 @@ pub struct Nursery { #[doc = "Disallow invalid !important within keyframe declarations"] #[serde(skip_serializing_if = "Option::is_none")] pub no_important_in_keyframe: Option>, + #[doc = "Succinct description of the rule."] + #[serde(skip_serializing_if = "Option::is_none")] + pub no_invalid_position_at_import_rule: + Option>, #[doc = "Checks that the assertion function, for example expect, is placed inside an it() function call."] #[serde(skip_serializing_if = "Option::is_none")] pub no_misplaced_assertion: Option>, @@ -2766,6 +2770,7 @@ impl Nursery { "noEvolvingAny", "noFlatMapIdentity", "noImportantInKeyframe", + "noInvalidPositionAtImportRule", "noMisplacedAssertion", "noNodejsModules", "noReactSpecificProps", @@ -2809,10 +2814,10 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[10]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[11]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[12]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]), ]; const ALL_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = &[ RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[0]), @@ -2843,6 +2848,7 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28]), ]; #[doc = r" Retrieves the recommended rules"] pub(crate) fn is_recommended_true(&self) -> bool { @@ -2924,81 +2930,86 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[12])); } } - if let Some(rule) = self.no_misplaced_assertion.as_ref() { + if let Some(rule) = self.no_invalid_position_at_import_rule.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13])); } } - if let Some(rule) = self.no_nodejs_modules.as_ref() { + if let Some(rule) = self.no_misplaced_assertion.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14])); } } - if let Some(rule) = self.no_react_specific_props.as_ref() { + if let Some(rule) = self.no_nodejs_modules.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15])); } } - if let Some(rule) = self.no_restricted_imports.as_ref() { + if let Some(rule) = self.no_react_specific_props.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16])); } } - if let Some(rule) = self.no_undeclared_dependencies.as_ref() { + if let Some(rule) = self.no_restricted_imports.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17])); } } - if let Some(rule) = self.no_unknown_function.as_ref() { + if let Some(rule) = self.no_undeclared_dependencies.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18])); } } - if let Some(rule) = self.no_unknown_selector_pseudo_element.as_ref() { + if let Some(rule) = self.no_unknown_function.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19])); } } - if let Some(rule) = self.no_unknown_unit.as_ref() { + if let Some(rule) = self.no_unknown_selector_pseudo_element.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20])); } } - if let Some(rule) = self.no_useless_undefined_initialization.as_ref() { + if let Some(rule) = self.no_unknown_unit.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21])); } } - if let Some(rule) = self.use_array_literals.as_ref() { + if let Some(rule) = self.no_useless_undefined_initialization.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22])); } } - if let Some(rule) = self.use_consistent_builtin_instantiation.as_ref() { + if let Some(rule) = self.use_array_literals.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23])); } } - if let Some(rule) = self.use_default_switch_clause.as_ref() { + if let Some(rule) = self.use_consistent_builtin_instantiation.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24])); } } - if let Some(rule) = self.use_generic_font_names.as_ref() { + if let Some(rule) = self.use_default_switch_clause.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.use_generic_font_names.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26])); } } - if let Some(rule) = self.use_sorted_classes.as_ref() { + if let Some(rule) = self.use_import_restrictions.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27])); } } + if let Some(rule) = self.use_sorted_classes.as_ref() { + if rule.is_enabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28])); + } + } index_set } pub(crate) fn get_disabled_rules(&self) -> IndexSet { @@ -3068,81 +3079,86 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[12])); } } - if let Some(rule) = self.no_misplaced_assertion.as_ref() { + if let Some(rule) = self.no_invalid_position_at_import_rule.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13])); } } - if let Some(rule) = self.no_nodejs_modules.as_ref() { + if let Some(rule) = self.no_misplaced_assertion.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14])); } } - if let Some(rule) = self.no_react_specific_props.as_ref() { + if let Some(rule) = self.no_nodejs_modules.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15])); } } - if let Some(rule) = self.no_restricted_imports.as_ref() { + if let Some(rule) = self.no_react_specific_props.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16])); } } - if let Some(rule) = self.no_undeclared_dependencies.as_ref() { + if let Some(rule) = self.no_restricted_imports.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17])); } } - if let Some(rule) = self.no_unknown_function.as_ref() { + if let Some(rule) = self.no_undeclared_dependencies.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18])); } } - if let Some(rule) = self.no_unknown_selector_pseudo_element.as_ref() { + if let Some(rule) = self.no_unknown_function.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19])); } } - if let Some(rule) = self.no_unknown_unit.as_ref() { + if let Some(rule) = self.no_unknown_selector_pseudo_element.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20])); } } - if let Some(rule) = self.no_useless_undefined_initialization.as_ref() { + if let Some(rule) = self.no_unknown_unit.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21])); } } - if let Some(rule) = self.use_array_literals.as_ref() { + if let Some(rule) = self.no_useless_undefined_initialization.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22])); } } - if let Some(rule) = self.use_consistent_builtin_instantiation.as_ref() { + if let Some(rule) = self.use_array_literals.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23])); } } - if let Some(rule) = self.use_default_switch_clause.as_ref() { + if let Some(rule) = self.use_consistent_builtin_instantiation.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24])); } } - if let Some(rule) = self.use_generic_font_names.as_ref() { + if let Some(rule) = self.use_default_switch_clause.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.use_generic_font_names.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26])); } } - if let Some(rule) = self.use_sorted_classes.as_ref() { + if let Some(rule) = self.use_import_restrictions.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27])); } } + if let Some(rule) = self.use_sorted_classes.as_ref() { + if rule.is_disabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28])); + } + } index_set } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] @@ -3231,6 +3247,10 @@ impl Nursery { .no_important_in_keyframe .as_ref() .map(|conf| (conf.level(), conf.get_options())), + "noInvalidPositionAtImportRule" => self + .no_invalid_position_at_import_rule + .as_ref() + .map(|conf| (conf.level(), conf.get_options())), "noMisplacedAssertion" => self .no_misplaced_assertion .as_ref() diff --git a/crates/biome_css_analyze/src/lint/nursery.rs b/crates/biome_css_analyze/src/lint/nursery.rs index 2ad4f01e119..a093dd504d4 100644 --- a/crates/biome_css_analyze/src/lint/nursery.rs +++ b/crates/biome_css_analyze/src/lint/nursery.rs @@ -8,6 +8,7 @@ pub mod no_duplicate_at_import_rules; pub mod no_duplicate_font_names; pub mod no_duplicate_selectors_keyframe_block; pub mod no_important_in_keyframe; +pub mod no_invalid_position_at_import_rule; pub mod no_unknown_function; pub mod no_unknown_selector_pseudo_element; pub mod no_unknown_unit; @@ -23,6 +24,7 @@ declare_group! { self :: no_duplicate_font_names :: NoDuplicateFontNames , self :: no_duplicate_selectors_keyframe_block :: NoDuplicateSelectorsKeyframeBlock , self :: no_important_in_keyframe :: NoImportantInKeyframe , + self :: no_invalid_position_at_import_rule :: NoInvalidPositionAtImportRule , self :: no_unknown_function :: NoUnknownFunction , self :: no_unknown_selector_pseudo_element :: NoUnknownSelectorPseudoElement , self :: no_unknown_unit :: NoUnknownUnit , diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs new file mode 100644 index 00000000000..e51747700cd --- /dev/null +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -0,0 +1,101 @@ +use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic, RuleSource}; +use biome_console::markup; +use biome_css_syntax::{AnyCssRule, CssRuleList, CssImportAtRule}; +use biome_rowan::AstNode; + +declare_rule! { + /// Disallow invalid position @import rules. + /// + /// Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + /// + /// ## Examples + /// + /// ### Invalid + /// + /// ```css,expect_diagnostic + /// a {} + /// @import 'foo.css'; + /// /** ↑ + /// * This @import */ + /// ``` + /// + /// ### Valid + /// + /// ```css + /// @import 'foo.css'; + /// a {} + /// ``` + /// + pub NoInvalidPositionAtImportRule { + version: "next", + name: "noInvalidPositionAtImportRule", + recommended: true, + sources: &[RuleSource::Stylelint("no-invalid-position-at-import-rule")], + } +} + +impl Rule for NoInvalidPositionAtImportRule { + type Query = Ast; + type State = CssImportAtRule; + type Signals = Option; + type Options = (); + + fn run(ctx: &RuleContext) -> Option { + let node = ctx.query(); + let mut is_invalid_position = false; + + for rule in node { + + let any_css_at_rule_result = match rule { + AnyCssRule::CssAtRule(item) => { + item.rule().ok() + }, + _ => { + None + } + }; + + if let Some(any_css_at_rule) = any_css_at_rule_result { + + // Ignore @charset, @layer + if any_css_at_rule.as_css_charset_at_rule().is_some() { continue;} + if any_css_at_rule.as_css_layer_at_rule().is_some() { continue;} + + let import_rule = any_css_at_rule.as_css_import_at_rule().cloned(); + if let Some(current_import_rule) = import_rule { + if is_invalid_position { + return Some(current_import_rule); + } + } else { + is_invalid_position = true; + } + } else { + is_invalid_position = true; + } + } + + None + } + + fn diagnostic(_: &RuleContext, node: &Self::State) -> Option { + // + // Read our guidelines to write great diagnostics: + // https://docs.rs/biome_analyze/latest/biome_analyze/#what-a-rule-should-say-to-the-user + // + let span = node.range(); + Some( + RuleDiagnostic::new( + rule_category!(), + span, + markup! { + "Unexpected import position." + }, + ) + .note(markup! { + "Consider moving import position." + }).note(markup! { + "Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid." + }), + ) + } +} diff --git a/crates/biome_css_analyze/src/options.rs b/crates/biome_css_analyze/src/options.rs index 7c3fc0b8b39..aa6cab523b5 100644 --- a/crates/biome_css_analyze/src/options.rs +++ b/crates/biome_css_analyze/src/options.rs @@ -11,6 +11,7 @@ pub type NoDuplicateFontNames = ::Options; pub type NoDuplicateSelectorsKeyframeBlock = < lint :: nursery :: no_duplicate_selectors_keyframe_block :: NoDuplicateSelectorsKeyframeBlock as biome_analyze :: Rule > :: Options ; pub type NoImportantInKeyframe = < lint :: nursery :: no_important_in_keyframe :: NoImportantInKeyframe as biome_analyze :: Rule > :: Options ; +pub type NoInvalidPositionAtImportRule = < lint :: nursery :: no_invalid_position_at_import_rule :: NoInvalidPositionAtImportRule as biome_analyze :: Rule > :: Options ; pub type NoUnknownFunction = ::Options; pub type NoUnknownSelectorPseudoElement = < lint :: nursery :: no_unknown_selector_pseudo_element :: NoUnknownSelectorPseudoElement as biome_analyze :: Rule > :: Options ; diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css new file mode 100644 index 00000000000..d560d0b7994 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css @@ -0,0 +1,2 @@ +a {} +@import 'foo.css'; diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap new file mode 100644 index 00000000000..8dc1c28132e --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap @@ -0,0 +1,28 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: invalid.css +--- +# Input +```css +a {} +@import 'foo.css'; + +``` + +# Diagnostics +``` +invalid.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected import position. + + 1 │ a {} + > 2 │ @import 'foo.css'; + │ ^^^^^^^^^^^^^^^^^ + 3 │ + + i Consider moving import position. + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css new file mode 100644 index 00000000000..9fcd4fcc3f4 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css @@ -0,0 +1,3 @@ +@import 'foo.css'; +a {} +@import 'bar.css'; diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap new file mode 100644 index 00000000000..f66d9586c46 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap @@ -0,0 +1,30 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: invalidBetweenImport.css +--- +# Input +```css +@import 'foo.css'; +a {} +@import 'bar.css'; + +``` + +# Diagnostics +``` +invalidBetweenImport.css:3:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected import position. + + 1 │ @import 'foo.css'; + 2 │ a {} + > 3 │ @import 'bar.css'; + │ ^^^^^^^^^^^^^^^^^ + 4 │ + + i Consider moving import position. + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css new file mode 100644 index 00000000000..6ff0a8c64a4 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css @@ -0,0 +1,2 @@ +@media print {} +@import url('foo.css'); diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap new file mode 100644 index 00000000000..055485bdad4 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap @@ -0,0 +1,28 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: invalidMediaImport.css +--- +# Input +```css +@media print {} +@import url('foo.css'); + +``` + +# Diagnostics +``` +invalidMediaImport.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected import position. + + 1 │ @media print {} + > 2 │ @import url('foo.css'); + │ ^^^^^^^^^^^^^^^^^^^^^^ + 3 │ + + i Consider moving import position. + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css new file mode 100644 index 00000000000..794c2a32860 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css @@ -0,0 +1,2 @@ +@media print {} +@imPort URl('foo.css'); diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap new file mode 100644 index 00000000000..732ab6a1e58 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap @@ -0,0 +1,28 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: invalidMediaImportUpperCase.css +--- +# Input +```css +@media print {} +@imPort URl('foo.css'); + +``` + +# Diagnostics +``` +invalidMediaImportUpperCase.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected import position. + + 1 │ @media print {} + > 2 │ @imPort URl('foo.css'); + │ ^^^^^^^^^^^^^^^^^^^^^^ + 3 │ + + i Consider moving import position. + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/valid.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/valid.css new file mode 100644 index 00000000000..23287742faa --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/valid.css @@ -0,0 +1,2 @@ +@import 'foo.css'; +a {} diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/valid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/valid.css.snap new file mode 100644 index 00000000000..6bd51b3be1d --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/valid.css.snap @@ -0,0 +1,10 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: valid.css +--- +# Input +```css +@import 'foo.css'; +a {} + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharset.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharset.css new file mode 100644 index 00000000000..503ea6d801b --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharset.css @@ -0,0 +1,2 @@ +@charset 'utf-8'; +@import 'foo.css'; diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharset.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharset.css.snap new file mode 100644 index 00000000000..44ae2a61459 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharset.css.snap @@ -0,0 +1,10 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: validCharset.css +--- +# Input +```css +@charset 'utf-8'; +@import 'foo.css'; + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharsetMultipleImport.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharsetMultipleImport.css new file mode 100644 index 00000000000..63701e78fe0 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharsetMultipleImport.css @@ -0,0 +1,3 @@ +@CHARSET 'utf-8'; +@imPORT 'foo.css'; +@import 'bar.css'; diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharsetMultipleImport.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharsetMultipleImport.css.snap new file mode 100644 index 00000000000..567c8f1c851 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validCharsetMultipleImport.css.snap @@ -0,0 +1,11 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: validCharsetMultipleImport.css +--- +# Input +```css +@CHARSET 'utf-8'; +@imPORT 'foo.css'; +@import 'bar.css'; + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validComment.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validComment.css new file mode 100644 index 00000000000..48452540502 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validComment.css @@ -0,0 +1,2 @@ +/* some comment */ +@import 'foo.css'; diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validComment.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validComment.css.snap new file mode 100644 index 00000000000..f160d5557eb --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validComment.css.snap @@ -0,0 +1,10 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: validComment.css +--- +# Input +```css +/* some comment */ +@import 'foo.css'; + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validLayerImport.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validLayerImport.css new file mode 100644 index 00000000000..5f244da1ddf --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validLayerImport.css @@ -0,0 +1,2 @@ +@layer default; +@import url(theme.css) layer(theme); diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validLayerImport.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validLayerImport.css.snap new file mode 100644 index 00000000000..3c6a7575812 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validLayerImport.css.snap @@ -0,0 +1,10 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: validLayerImport.css +--- +# Input +```css +@layer default; +@import url(theme.css) layer(theme); + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validMultipleImport.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validMultipleImport.css new file mode 100644 index 00000000000..b4b870461af --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validMultipleImport.css @@ -0,0 +1,2 @@ +@import 'foo.css'; +@import 'bar.css'; diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validMultipleImport.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validMultipleImport.css.snap new file mode 100644 index 00000000000..b6bec00915d --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validMultipleImport.css.snap @@ -0,0 +1,10 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: validMultipleImport.css +--- +# Input +```css +@import 'foo.css'; +@import 'bar.css'; + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validNoImportant.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validNoImportant.css new file mode 100644 index 00000000000..077f6dd7c01 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validNoImportant.css @@ -0,0 +1 @@ +a {} diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validNoImportant.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validNoImportant.css.snap new file mode 100644 index 00000000000..556deac7695 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/validNoImportant.css.snap @@ -0,0 +1,9 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: validNoImportant.css +--- +# Input +```css +a {} + +``` diff --git a/crates/biome_diagnostics_categories/src/categories.rs b/crates/biome_diagnostics_categories/src/categories.rs index 218c023ec03..bd0ba9e5434 100644 --- a/crates/biome_diagnostics_categories/src/categories.rs +++ b/crates/biome_diagnostics_categories/src/categories.rs @@ -123,6 +123,7 @@ define_categories! { "lint/nursery/noEvolvingAny": "https://biomejs.dev/linter/rules/no-evolving-any", "lint/nursery/noFlatMapIdentity": "https://biomejs.dev/linter/rules/no-flat-map-identity", "lint/nursery/noImportantInKeyframe": "https://biomejs.dev/linter/rules/no-important-in-keyframe", + "lint/nursery/noInvalidPositionAtImportRule": "https://biomejs.dev/linter/rules/no-invalid-position-at-import-rule", "lint/nursery/noMisplacedAssertion": "https://biomejs.dev/linter/rules/no-misplaced-assertion", "lint/nursery/noMissingGenericFamilyKeyword": "https://biomejs.dev/linter/rules/no-missing-generic-family-keyword", "lint/nursery/noNodejsModules": "https://biomejs.dev/linter/rules/no-nodejs-modules", diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 82549c69344..9d442d7fe57 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -960,6 +960,10 @@ export interface Nursery { * Disallow invalid !important within keyframe declarations */ noImportantInKeyframe?: RuleConfiguration_for_Null; + /** + * Succinct description of the rule. + */ + noInvalidPositionAtImportRule?: RuleConfiguration_for_Null; /** * Checks that the assertion function, for example expect, is placed inside an it() function call. */ @@ -2002,6 +2006,7 @@ export type Category = | "lint/nursery/noEvolvingAny" | "lint/nursery/noFlatMapIdentity" | "lint/nursery/noImportantInKeyframe" + | "lint/nursery/noInvalidPositionAtImportRule" | "lint/nursery/noMisplacedAssertion" | "lint/nursery/noMissingGenericFamilyKeyword" | "lint/nursery/noNodejsModules" diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index a383697a81b..b2977edf2cf 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -1524,6 +1524,13 @@ { "type": "null" } ] }, + "noInvalidPositionAtImportRule": { + "description": "Succinct description of the rule.", + "anyOf": [ + { "$ref": "#/definitions/RuleConfiguration" }, + { "type": "null" } + ] + }, "noMisplacedAssertion": { "description": "Checks that the assertion function, for example expect, is placed inside an it() function call.", "anyOf": [ From eb0c07dd988166a5d3235b8afc3ea21bec3c9a87 Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 10:01:06 +0900 Subject: [PATCH 02/17] chore: refactor --- .../no_invalid_position_at_import_rule.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index e51747700cd..dab0b57a88b 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -46,25 +46,21 @@ impl Rule for NoInvalidPositionAtImportRule { for rule in node { - let any_css_at_rule_result = match rule { - AnyCssRule::CssAtRule(item) => { - item.rule().ok() - }, - _ => { - None - } + let any_css_at_rule = match rule { + AnyCssRule::CssAtRule(item) => item.rule().ok(), + _ => None }; - if let Some(any_css_at_rule) = any_css_at_rule_result { + if let Some(any_css_at_rule) = any_css_at_rule { // Ignore @charset, @layer if any_css_at_rule.as_css_charset_at_rule().is_some() { continue;} if any_css_at_rule.as_css_layer_at_rule().is_some() { continue;} let import_rule = any_css_at_rule.as_css_import_at_rule().cloned(); - if let Some(current_import_rule) = import_rule { + if let Some(import_rule) = import_rule { if is_invalid_position { - return Some(current_import_rule); + return Some(import_rule); } } else { is_invalid_position = true; From 6e3c7e4b12dd2d56498e42d2944008fce27ccf37 Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 17:09:30 +0900 Subject: [PATCH 03/17] Update crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs Co-authored-by: Emanuele Stoppa --- .../src/lint/nursery/no_invalid_position_at_import_rule.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index ee191c49f2e..4892f79d963 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -15,8 +15,6 @@ declare_rule! { /// ```css,expect_diagnostic /// a {} /// @import 'foo.css'; - /// /** ↑ - /// * This @import */ /// ``` /// /// ### Valid From f757457b0819e991e6bac94c2862463e6ed5f9e7 Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 17:09:39 +0900 Subject: [PATCH 04/17] Update crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs Co-authored-by: Emanuele Stoppa --- .../src/lint/nursery/no_invalid_position_at_import_rule.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index 4892f79d963..b6a2bae512a 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -74,10 +74,6 @@ impl Rule for NoInvalidPositionAtImportRule { } fn diagnostic(_: &RuleContext, node: &Self::State) -> Option { - // - // Read our guidelines to write great diagnostics: - // https://docs.rs/biome_analyze/latest/biome_analyze/#what-a-rule-should-say-to-the-user - // let span = node.range(); Some( RuleDiagnostic::new( From 981c14be98151d2cf0b2358b11188ef14a1bde00 Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 17:10:33 +0900 Subject: [PATCH 05/17] Update crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs Co-authored-by: Emanuele Stoppa --- .../src/lint/nursery/no_invalid_position_at_import_rule.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index b6a2bae512a..45a63d1a8a9 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -4,7 +4,7 @@ use biome_css_syntax::{AnyCssRule, CssImportAtRule, CssRuleList}; use biome_rowan::AstNode; declare_rule! { - /// Disallow invalid position @import rules. + /// Disallow the use of `@import` at-rules in invalid positions. /// /// Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. /// From 9f715bd6ec5e9a80728f3b2cdebd5eb5449917f2 Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 17:10:40 +0900 Subject: [PATCH 06/17] Update crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs Co-authored-by: Emanuele Stoppa --- .../src/lint/nursery/no_invalid_position_at_import_rule.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index 45a63d1a8a9..c306f7bf884 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -6,7 +6,7 @@ use biome_rowan::AstNode; declare_rule! { /// Disallow the use of `@import` at-rules in invalid positions. /// - /// Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + /// Any `@import` rules must precede all other valid at-rules and style rules in a stylesheet (ignoring `@charset` and `@layer`), or else the `@import` rule is invalid. /// /// ## Examples /// From e97271bf4a17f4ae93969ac2379373776d660cf5 Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 17:11:42 +0900 Subject: [PATCH 07/17] Update crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs Co-authored-by: Emanuele Stoppa --- .../src/lint/nursery/no_invalid_position_at_import_rule.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index c306f7bf884..f7ad3de9b08 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -80,7 +80,7 @@ impl Rule for NoInvalidPositionAtImportRule { rule_category!(), span, markup! { - "Unexpected import position." + "This @import is in the wrong position." }, ) .note(markup! { From 7495e81564d7059d8bb185f8faf4b903d6d480b4 Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 17:51:44 +0900 Subject: [PATCH 08/17] fix: Emphasis @import --- .../no_invalid_position_at_import_rule.rs | 4 +-- .../invalid.css.snap.new | 29 +++++++++++++++++ .../invalidBetweenImport.css.snap.new | 31 +++++++++++++++++++ .../invalidMediaImport.css.snap.new | 29 +++++++++++++++++ .../invalidMediaImportUpperCase.css.snap.new | 29 +++++++++++++++++ 5 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index f7ad3de9b08..5c611db9fd3 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -80,13 +80,13 @@ impl Rule for NoInvalidPositionAtImportRule { rule_category!(), span, markup! { - "This @import is in the wrong position." + "This ""@import"" is in the wrong position." }, ) .note(markup! { "Consider moving import position." }).note(markup! { - "Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid." + "Any ""@import"" rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the ""@import"" rule is invalid." }), ) } diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new new file mode 100644 index 00000000000..e56958de398 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new @@ -0,0 +1,29 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +assertion_line: 83 +expression: invalid.css +--- +# Input +```css +a {} +@import 'foo.css'; + +``` + +# Diagnostics +``` +invalid.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This @import is in the wrong position. + + 1 │ a {} + > 2 │ @import 'foo.css'; + │ ^^^^^^^^^^^^^^^^^ + 3 │ + + i Consider moving import position. + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new new file mode 100644 index 00000000000..3f3cebb65e0 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new @@ -0,0 +1,31 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +assertion_line: 83 +expression: invalidBetweenImport.css +--- +# Input +```css +@import 'foo.css'; +a {} +@import 'bar.css'; + +``` + +# Diagnostics +``` +invalidBetweenImport.css:3:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This @import is in the wrong position. + + 1 │ @import 'foo.css'; + 2 │ a {} + > 3 │ @import 'bar.css'; + │ ^^^^^^^^^^^^^^^^^ + 4 │ + + i Consider moving import position. + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new new file mode 100644 index 00000000000..c65fff1fad8 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new @@ -0,0 +1,29 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +assertion_line: 83 +expression: invalidMediaImport.css +--- +# Input +```css +@media print {} +@import url('foo.css'); + +``` + +# Diagnostics +``` +invalidMediaImport.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This @import is in the wrong position. + + 1 │ @media print {} + > 2 │ @import url('foo.css'); + │ ^^^^^^^^^^^^^^^^^^^^^^ + 3 │ + + i Consider moving import position. + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new new file mode 100644 index 00000000000..71dc605e223 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new @@ -0,0 +1,29 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +assertion_line: 83 +expression: invalidMediaImportUpperCase.css +--- +# Input +```css +@media print {} +@imPort URl('foo.css'); + +``` + +# Diagnostics +``` +invalidMediaImportUpperCase.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━ + + ! This @import is in the wrong position. + + 1 │ @media print {} + > 2 │ @imPort URl('foo.css'); + │ ^^^^^^^^^^^^^^^^^^^^^^ + 3 │ + + i Consider moving import position. + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + +``` From c6f45ab2cbb9b59801a65d71ad685069b0fa7355 Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 17:56:01 +0900 Subject: [PATCH 09/17] fix: correct the order of notes --- .../src/lint/nursery/no_invalid_position_at_import_rule.rs | 6 +++--- .../noInvalidPositionAtImportRule/invalid.css.snap.new | 4 ++-- .../invalidBetweenImport.css.snap.new | 4 ++-- .../invalidMediaImport.css.snap.new | 4 ++-- .../invalidMediaImportUpperCase.css.snap.new | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index 5c611db9fd3..38a184208c2 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -84,10 +84,10 @@ impl Rule for NoInvalidPositionAtImportRule { }, ) .note(markup! { - "Consider moving import position." - }).note(markup! { "Any ""@import"" rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the ""@import"" rule is invalid." - }), + }).note(markup! { + "Consider moving import position." + }) ) } } diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new index e56958de398..886a8c5ff5b 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new @@ -21,9 +21,9 @@ invalid.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━ │ ^^^^^^^^^^^^^^^^^ 3 │ - i Consider moving import position. - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + i Consider moving import position. + ``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new index 3f3cebb65e0..d72d6883664 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new @@ -23,9 +23,9 @@ invalidBetweenImport.css:3:2 lint/nursery/noInvalidPositionAtImportRule ━━ │ ^^^^^^^^^^^^^^^^^ 4 │ - i Consider moving import position. - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + i Consider moving import position. + ``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new index c65fff1fad8..fb0313c0c86 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new @@ -21,9 +21,9 @@ invalidMediaImport.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━ │ ^^^^^^^^^^^^^^^^^^^^^^ 3 │ - i Consider moving import position. - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + i Consider moving import position. + ``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new index 71dc605e223..73684cbb5bb 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new @@ -21,9 +21,9 @@ invalidMediaImportUpperCase.css:2:2 lint/nursery/noInvalidPositionAtImportRule │ ^^^^^^^^^^^^^^^^^^^^^^ 3 │ - i Consider moving import position. - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + i Consider moving import position. + ``` From 9ca1793d562753cd71d6f802f04552fc481b79ae Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 18:28:18 +0900 Subject: [PATCH 10/17] chore: refactor --- .../no_invalid_position_at_import_rule.rs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index 38a184208c2..6e4b84fce7f 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -1,7 +1,7 @@ use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic, RuleSource}; use biome_console::markup; -use biome_css_syntax::{AnyCssRule, CssImportAtRule, CssRuleList}; -use biome_rowan::AstNode; +use biome_css_syntax::{AnyCssRule, CssRuleList}; +use biome_rowan::{AstNode, TextRange}; declare_rule! { /// Disallow the use of `@import` at-rules in invalid positions. @@ -32,9 +32,13 @@ declare_rule! { } } +pub struct RuleState { + span: TextRange, +} + impl Rule for NoInvalidPositionAtImportRule { type Query = Ast; - type State = CssImportAtRule; + type State = RuleState; type Signals = Option; type Options = (); @@ -57,10 +61,12 @@ impl Rule for NoInvalidPositionAtImportRule { continue; } - let import_rule = any_css_at_rule.as_css_import_at_rule().cloned(); + let import_rule = any_css_at_rule.as_css_import_at_rule(); if let Some(import_rule) = import_rule { if is_invalid_position { - return Some(import_rule); + return Some(RuleState { + span: import_rule.range(), + }); } } else { is_invalid_position = true; @@ -73,8 +79,8 @@ impl Rule for NoInvalidPositionAtImportRule { None } - fn diagnostic(_: &RuleContext, node: &Self::State) -> Option { - let span = node.range(); + fn diagnostic(_: &RuleContext, state: &Self::State) -> Option { + let span = state.span; Some( RuleDiagnostic::new( rule_category!(), From b3cfcf48cb4e16cc9f2e546ee262f6054976d68d Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 19:56:25 +0900 Subject: [PATCH 11/17] update: snap --- .../invalid.css.snap | 6 ++-- .../invalid.css.snap.new | 29 ----------------- .../invalidBetweenImport.css.snap | 6 ++-- .../invalidBetweenImport.css.snap.new | 31 ------------------- .../invalidMediaImport.css.snap | 6 ++-- .../invalidMediaImport.css.snap.new | 29 ----------------- .../invalidMediaImportUpperCase.css.snap | 6 ++-- .../invalidMediaImportUpperCase.css.snap.new | 29 ----------------- 8 files changed, 12 insertions(+), 130 deletions(-) delete mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new delete mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new delete mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new delete mode 100644 crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap index 8dc1c28132e..78c86c1aecb 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap @@ -13,16 +13,16 @@ a {} ``` invalid.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Unexpected import position. + ! This @import is in the wrong position. 1 │ a {} > 2 │ @import 'foo.css'; │ ^^^^^^^^^^^^^^^^^ 3 │ - i Consider moving import position. - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + i Consider moving import position. + ``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new deleted file mode 100644 index 886a8c5ff5b..00000000000 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap.new +++ /dev/null @@ -1,29 +0,0 @@ ---- -source: crates/biome_css_analyze/tests/spec_tests.rs -assertion_line: 83 -expression: invalid.css ---- -# Input -```css -a {} -@import 'foo.css'; - -``` - -# Diagnostics -``` -invalid.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This @import is in the wrong position. - - 1 │ a {} - > 2 │ @import 'foo.css'; - │ ^^^^^^^^^^^^^^^^^ - 3 │ - - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. - - i Consider moving import position. - - -``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap index f66d9586c46..09442657f34 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap @@ -14,7 +14,7 @@ a {} ``` invalidBetweenImport.css:3:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Unexpected import position. + ! This @import is in the wrong position. 1 │ @import 'foo.css'; 2 │ a {} @@ -22,9 +22,9 @@ invalidBetweenImport.css:3:2 lint/nursery/noInvalidPositionAtImportRule ━━ │ ^^^^^^^^^^^^^^^^^ 4 │ - i Consider moving import position. - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + i Consider moving import position. + ``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new deleted file mode 100644 index d72d6883664..00000000000 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap.new +++ /dev/null @@ -1,31 +0,0 @@ ---- -source: crates/biome_css_analyze/tests/spec_tests.rs -assertion_line: 83 -expression: invalidBetweenImport.css ---- -# Input -```css -@import 'foo.css'; -a {} -@import 'bar.css'; - -``` - -# Diagnostics -``` -invalidBetweenImport.css:3:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This @import is in the wrong position. - - 1 │ @import 'foo.css'; - 2 │ a {} - > 3 │ @import 'bar.css'; - │ ^^^^^^^^^^^^^^^^^ - 4 │ - - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. - - i Consider moving import position. - - -``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap index 055485bdad4..57c9bdb3996 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap @@ -13,16 +13,16 @@ expression: invalidMediaImport.css ``` invalidMediaImport.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Unexpected import position. + ! This @import is in the wrong position. 1 │ @media print {} > 2 │ @import url('foo.css'); │ ^^^^^^^^^^^^^^^^^^^^^^ 3 │ - i Consider moving import position. - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + i Consider moving import position. + ``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new deleted file mode 100644 index fb0313c0c86..00000000000 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImport.css.snap.new +++ /dev/null @@ -1,29 +0,0 @@ ---- -source: crates/biome_css_analyze/tests/spec_tests.rs -assertion_line: 83 -expression: invalidMediaImport.css ---- -# Input -```css -@media print {} -@import url('foo.css'); - -``` - -# Diagnostics -``` -invalidMediaImport.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This @import is in the wrong position. - - 1 │ @media print {} - > 2 │ @import url('foo.css'); - │ ^^^^^^^^^^^^^^^^^^^^^^ - 3 │ - - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. - - i Consider moving import position. - - -``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap index 732ab6a1e58..db77e54e7ff 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap @@ -13,16 +13,16 @@ expression: invalidMediaImportUpperCase.css ``` invalidMediaImportUpperCase.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━ - ! Unexpected import position. + ! This @import is in the wrong position. 1 │ @media print {} > 2 │ @imPort URl('foo.css'); │ ^^^^^^^^^^^^^^^^^^^^^^ 3 │ - i Consider moving import position. - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + i Consider moving import position. + ``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new deleted file mode 100644 index 73684cbb5bb..00000000000 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidMediaImportUpperCase.css.snap.new +++ /dev/null @@ -1,29 +0,0 @@ ---- -source: crates/biome_css_analyze/tests/spec_tests.rs -assertion_line: 83 -expression: invalidMediaImportUpperCase.css ---- -# Input -```css -@media print {} -@imPort URl('foo.css'); - -``` - -# Diagnostics -``` -invalidMediaImportUpperCase.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━ - - ! This @import is in the wrong position. - - 1 │ @media print {} - > 2 │ @imPort URl('foo.css'); - │ ^^^^^^^^^^^^^^^^^^^^^^ - 3 │ - - i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. - - i Consider moving import position. - - -``` From f53625151b7d4f09aabe35e574aeadc39a2b3ce6 Mon Sep 17 00:00:00 2001 From: takashi Date: Sun, 5 May 2024 20:39:44 +0900 Subject: [PATCH 12/17] chore: refactor --- .../nursery/no_invalid_position_at_import_rule.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index 6e4b84fce7f..95ce0f26185 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -32,13 +32,9 @@ declare_rule! { } } -pub struct RuleState { - span: TextRange, -} - impl Rule for NoInvalidPositionAtImportRule { type Query = Ast; - type State = RuleState; + type State = TextRange; type Signals = Option; type Options = (); @@ -64,9 +60,7 @@ impl Rule for NoInvalidPositionAtImportRule { let import_rule = any_css_at_rule.as_css_import_at_rule(); if let Some(import_rule) = import_rule { if is_invalid_position { - return Some(RuleState { - span: import_rule.range(), - }); + return Some(import_rule.range()); } } else { is_invalid_position = true; @@ -80,11 +74,10 @@ impl Rule for NoInvalidPositionAtImportRule { } fn diagnostic(_: &RuleContext, state: &Self::State) -> Option { - let span = state.span; Some( RuleDiagnostic::new( rule_category!(), - span, + state, markup! { "This ""@import"" is in the wrong position." }, From 6f752eded56e1130c35d5f49d23d629e7bc3b8be Mon Sep 17 00:00:00 2001 From: takashi Date: Mon, 6 May 2024 09:10:43 +0900 Subject: [PATCH 13/17] fix: multiple diagnostic --- .../no_invalid_position_at_import_rule.rs | 10 +-- .../noInvalidPositionAtImportRule/invalid.css | 1 + .../invalid.css.snap | 22 +++++- .../invalidBetweenImport.css | 6 +- .../invalidBetweenImport.css.snap | 69 +++++++++++++++++-- 5 files changed, 97 insertions(+), 11 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs index 95ce0f26185..49d804f3c59 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_invalid_position_at_import_rule.rs @@ -35,12 +35,13 @@ declare_rule! { impl Rule for NoInvalidPositionAtImportRule { type Query = Ast; type State = TextRange; - type Signals = Option; + type Signals = Vec; type Options = (); - fn run(ctx: &RuleContext) -> Option { + fn run(ctx: &RuleContext) -> Vec { let node = ctx.query(); let mut is_invalid_position = false; + let mut invalid_import_list = Vec::new(); for rule in node { let any_css_at_rule = match rule { @@ -60,7 +61,7 @@ impl Rule for NoInvalidPositionAtImportRule { let import_rule = any_css_at_rule.as_css_import_at_rule(); if let Some(import_rule) = import_rule { if is_invalid_position { - return Some(import_rule.range()); + invalid_import_list.push(import_rule.range()); } } else { is_invalid_position = true; @@ -69,8 +70,7 @@ impl Rule for NoInvalidPositionAtImportRule { is_invalid_position = true; } } - - None + invalid_import_list } fn diagnostic(_: &RuleContext, state: &Self::State) -> Option { diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css index d560d0b7994..164019d2849 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css @@ -1,2 +1,3 @@ a {} @import 'foo.css'; +@import 'bar.css'; diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap index 78c86c1aecb..7e3d9b5f3b0 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalid.css.snap @@ -6,6 +6,7 @@ expression: invalid.css ```css a {} @import 'foo.css'; +@import 'bar.css'; ``` @@ -18,7 +19,26 @@ invalid.css:2:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━ 1 │ a {} > 2 │ @import 'foo.css'; │ ^^^^^^^^^^^^^^^^^ - 3 │ + 3 │ @import 'bar.css'; + 4 │ + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + i Consider moving import position. + + +``` + +``` +invalid.css:3:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This @import is in the wrong position. + + 1 │ a {} + 2 │ @import 'foo.css'; + > 3 │ @import 'bar.css'; + │ ^^^^^^^^^^^^^^^^^ + 4 │ i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css index 9fcd4fcc3f4..5e622126b8c 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css @@ -1,3 +1,7 @@ @import 'foo.css'; a {} -@import 'bar.css'; +@import 'bar1.css'; +@import 'bar2.css'; +a {} +@import 'bar3.css'; +@import 'bar4.css'; diff --git a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap index 09442657f34..640f7bb2b5a 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noInvalidPositionAtImportRule/invalidBetweenImport.css.snap @@ -6,7 +6,11 @@ expression: invalidBetweenImport.css ```css @import 'foo.css'; a {} -@import 'bar.css'; +@import 'bar1.css'; +@import 'bar2.css'; +a {} +@import 'bar3.css'; +@import 'bar4.css'; ``` @@ -18,9 +22,66 @@ invalidBetweenImport.css:3:2 lint/nursery/noInvalidPositionAtImportRule ━━ 1 │ @import 'foo.css'; 2 │ a {} - > 3 │ @import 'bar.css'; - │ ^^^^^^^^^^^^^^^^^ - 4 │ + > 3 │ @import 'bar1.css'; + │ ^^^^^^^^^^^^^^^^^^ + 4 │ @import 'bar2.css'; + 5 │ a {} + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + i Consider moving import position. + + +``` + +``` +invalidBetweenImport.css:4:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This @import is in the wrong position. + + 2 │ a {} + 3 │ @import 'bar1.css'; + > 4 │ @import 'bar2.css'; + │ ^^^^^^^^^^^^^^^^^^ + 5 │ a {} + 6 │ @import 'bar3.css'; + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + i Consider moving import position. + + +``` + +``` +invalidBetweenImport.css:6:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This @import is in the wrong position. + + 4 │ @import 'bar2.css'; + 5 │ a {} + > 6 │ @import 'bar3.css'; + │ ^^^^^^^^^^^^^^^^^^ + 7 │ @import 'bar4.css'; + 8 │ + + i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. + + i Consider moving import position. + + +``` + +``` +invalidBetweenImport.css:7:2 lint/nursery/noInvalidPositionAtImportRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This @import is in the wrong position. + + 5 │ a {} + 6 │ @import 'bar3.css'; + > 7 │ @import 'bar4.css'; + │ ^^^^^^^^^^^^^^^^^^ + 8 │ i Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid. From 83b81acc16ffc82909b99742eacd843f5316c105 Mon Sep 17 00:00:00 2001 From: takashi Date: Tue, 7 May 2024 09:17:20 +0900 Subject: [PATCH 14/17] update: - Merge branch 'main' into feature/noInvalidPositionAtImportRule - fix conflicts (rules.rs) --- .github/workflows/bench_cli.yml | 14 +- .github/workflows/benchmark.yml | 6 +- .github/workflows/main.yml | 22 +- .github/workflows/parser_conformance.yml | 8 +- .github/workflows/prepare_release.yml | 2 +- .github/workflows/publish_container_ci.yaml | 2 +- .github/workflows/pull_request.yml | 30 +- .github/workflows/pull_request_js.yml | 4 +- .../workflows/pull_request_title_lint.yaml | 2 +- .github/workflows/release_cli.yml | 24 +- .github/workflows/release_js_api.yml | 20 +- CHANGELOG.md | 51 +- Cargo.lock | 35 +- Cargo.toml | 4 +- benchmark/package-lock.json | 44 +- benchmark/package.json | 4 +- .../migrate/eslint_any_rule_to_biome.rs | 10 + crates/biome_cli/src/execute/traverse.rs | 30 +- crates/biome_cli/tests/commands/check.rs | 25 + crates/biome_cli/tests/commands/ci.rs | 25 + crates/biome_cli/tests/commands/format.rs | 27 ++ crates/biome_cli/tests/commands/lint.rs | 27 +- .../lint_error_without_file_paths.snap | 70 +++ ...s_formatting_error_without_file_paths.snap | 39 ++ .../format_without_file_paths.snap | 39 ++ ...vel_recommended_false_enable_specific.snap | 4 +- .../lint_error_without_file_paths.snap | 60 +++ crates/biome_configuration/src/lib.rs | 8 +- .../biome_configuration/src/linter/rules.rs | 55 ++- .../src/categories.rs | 1 + crates/biome_grit_patterns/Cargo.toml | 2 + .../biome_grit_patterns/src/grit_binding.rs | 15 +- .../biome_grit_patterns/src/grit_context.rs | 4 +- crates/biome_grit_patterns/src/grit_node.rs | 4 + .../src/grit_node_patterns.rs | 4 +- .../src/grit_target_language.rs | 123 ++++- .../js_target_language.rs | 58 +++ .../src/grit_target_node.rs | 298 ++++++++++++ crates/biome_grit_patterns/src/grit_tree.rs | 12 +- crates/biome_grit_patterns/src/lib.rs | 3 +- .../correctness/use_jsx_key_in_iterable.rs | 13 + crates/biome_js_analyze/src/lint/nursery.rs | 2 + .../lint/nursery/no_useless_string_concat.rs | 436 ++++++++++++++++++ .../lint/nursery/use_explicit_length_check.rs | 76 ++- crates/biome_js_analyze/src/options.rs | 1 + .../useJsxKeyInIterable/invalid.jsx.snap | 19 + .../correctness/useJsxKeyInIterable/valid.jsx | 2 + .../useJsxKeyInIterable/valid.jsx.snap | 2 + .../nursery/noUselessStringConcat/invalid.js | 15 + .../noUselessStringConcat/invalid.js.snap | 398 ++++++++++++++++ .../nursery/noUselessStringConcat/valid.js | 14 + .../noUselessStringConcat/valid.js.snap | 22 + crates/biome_js_syntax/src/generated/kind.rs | 1 + crates/biome_lsp/Cargo.toml | 2 +- .../biome_lsp/src/handlers/text_document.rs | 9 +- crates/biome_lsp/src/server.rs | 52 ++- crates/biome_lsp/src/session.rs | 107 +++-- crates/biome_lsp/src/utils.rs | 9 +- crates/biome_lsp/tests/server.rs | 164 ++++++- crates/biome_service/src/configuration.rs | 8 +- crates/biome_service/src/settings.rs | 90 ++-- crates/biome_service/src/workspace.rs | 31 +- crates/biome_service/src/workspace/client.rs | 9 +- crates/biome_service/src/workspace/server.rs | 22 +- package.json | 2 +- .../@biomejs/backend-jsonrpc/package.json | 6 +- .../@biomejs/backend-jsonrpc/src/workspace.ts | 7 +- .../@biomejs/biome/configuration_schema.json | 9 +- packages/@biomejs/biome/package.json | 2 +- packages/@biomejs/js-api/package.json | 19 +- .../tailwindcss-config-analyzer/package.json | 2 +- pnpm-lock.yaml | 134 +++--- xtask/codegen/src/js_kinds_src.rs | 2 + 73 files changed, 2501 insertions(+), 401 deletions(-) create mode 100644 crates/biome_cli/tests/snapshots/main_commands_check/lint_error_without_file_paths.snap create mode 100644 crates/biome_cli/tests/snapshots/main_commands_ci/does_formatting_error_without_file_paths.snap create mode 100644 crates/biome_cli/tests/snapshots/main_commands_format/format_without_file_paths.snap create mode 100644 crates/biome_cli/tests/snapshots/main_commands_lint/lint_error_without_file_paths.snap create mode 100644 crates/biome_grit_patterns/src/grit_target_language/js_target_language.rs create mode 100644 crates/biome_grit_patterns/src/grit_target_node.rs create mode 100644 crates/biome_js_analyze/src/lint/nursery/no_useless_string_concat.rs create mode 100644 crates/biome_js_analyze/tests/specs/nursery/noUselessStringConcat/invalid.js create mode 100644 crates/biome_js_analyze/tests/specs/nursery/noUselessStringConcat/invalid.js.snap create mode 100644 crates/biome_js_analyze/tests/specs/nursery/noUselessStringConcat/valid.js create mode 100644 crates/biome_js_analyze/tests/specs/nursery/noUselessStringConcat/valid.js.snap diff --git a/.github/workflows/bench_cli.yml b/.github/workflows/bench_cli.yml index e43c3c4f90c..256ccdbf860 100644 --- a/.github/workflows/bench_cli.yml +++ b/.github/workflows/bench_cli.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Get PR SHA id: sha - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: result-encoding: string script: | @@ -29,12 +29,12 @@ jobs: return response.data.head.sha; - name: Checkout PR Branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: ref: ${{ steps.sha.outputs.result }} - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: channel: stable cache-target: release @@ -50,7 +50,7 @@ jobs: cp target/release/biome benchmark/target/biome_pr - name: Checkout Main Branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: clean: false ref: main @@ -61,17 +61,17 @@ jobs: cp target/release/biome benchmark/target/biome_main - name: Checkout webpack - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: repository: webpack/webpack path: benchmark/target/webpack - name: Checkout prettier - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: repository: prettier/prettier path: benchmark/target/prettier - name: Checkout eslint - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: repository: eslint/eslint path: benchmark/target/eslint diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 56acfe412ee..614e9d9c965 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -33,12 +33,12 @@ jobs: steps: - name: Checkout PR Branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: ref: ${{ steps.sha.outputs.result }} - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: channel: stable cache-target: release @@ -49,7 +49,7 @@ jobs: run: cargo codspeed build --features codspeed -p xtask_bench - name: Run the benchmarks - uses: CodSpeedHQ/action@1dbf41f0ae41cebfe61e084e535aebe533409b4d # v2 + uses: CodSpeedHQ/action@0b631f8998f2389eb5144632b6f9f8fabd33a86e # v2.4.1 timeout-minutes: 30 with: run: cargo codspeed run diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 39001f7b958..acb5ad69ab7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,15 +20,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Support longpaths run: git config core.longpaths true - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: components: rustfmt bins: taplo-cli @@ -43,11 +43,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: components: clippy cache-base: main @@ -61,11 +61,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: channel: nightly cache: false @@ -85,11 +85,11 @@ jobs: - os: macos-latest steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: bins: cargo-nextest cache-base: main @@ -111,13 +111,13 @@ jobs: if: matrix.os == 'windows-latest' run: git config --system core.longpaths true - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: submodules: recursive - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: cache-target: release cache-base: main diff --git a/.github/workflows/parser_conformance.yml b/.github/workflows/parser_conformance.yml index 329fe53863b..40fe17cf0a8 100644 --- a/.github/workflows/parser_conformance.yml +++ b/.github/workflows/parser_conformance.yml @@ -25,13 +25,13 @@ jobs: steps: - name: Checkout PR Branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Support longpaths run: git config core.longpaths true - name: Checkout PR Branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: submodules: recursive @@ -39,7 +39,7 @@ jobs: uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: cache-target: release cache-base: main @@ -52,7 +52,7 @@ jobs: run: cargo coverage --json > new_results.json - name: Checkout main Branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: clean: false ref: main diff --git a/.github/workflows/prepare_release.yml b/.github/workflows/prepare_release.yml index 6573ef01e87..637f612197f 100644 --- a/.github/workflows/prepare_release.yml +++ b/.github/workflows/prepare_release.yml @@ -13,7 +13,7 @@ jobs: if: "!contains(github.event.head_commit.message, 'chore: prepare release')" # Skip merges from releases runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 - name: Configure Git diff --git a/.github/workflows/publish_container_ci.yaml b/.github/workflows/publish_container_ci.yaml index 6d29bcd469e..811079f8ef6 100644 --- a/.github/workflows/publish_container_ci.yaml +++ b/.github/workflows/publish_container_ci.yaml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Login to GitHub Container Registry - uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index c13d8b6b0aa..ba7ebe84a95 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -28,11 +28,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: components: rustfmt bins: taplo-cli @@ -47,11 +47,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR Branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: components: clippy cache-base: main @@ -63,7 +63,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR Branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain @@ -83,11 +83,11 @@ jobs: - os: ubuntu-latest steps: - name: Checkout PR branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: bins: cargo-nextest cache-base: main @@ -101,22 +101,22 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: cache-target: release cache-base: main - name: Build main binary run: cargo build -p biome_cli --release - name: Install Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: 20 - name: Cache pnpm modules - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/.pnpm-store key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} @@ -145,11 +145,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: cache-base: main - name: Run doc command @@ -160,11 +160,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + uses: moonrepo/setup-rust@d8048d4fdff0633123678b093726e6d7c8ad6de5 # v1.2.0 with: cache-base: main - name: Run the grammar codegen diff --git a/.github/workflows/pull_request_js.yml b/.github/workflows/pull_request_js.yml index 6cd7279cfb9..cef2cc64a05 100644 --- a/.github/workflows/pull_request_js.yml +++ b/.github/workflows/pull_request_js.yml @@ -24,11 +24,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Cache pnpm modules - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/.pnpm-store key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} diff --git a/.github/workflows/pull_request_title_lint.yaml b/.github/workflows/pull_request_title_lint.yaml index 9b3ac35a4eb..7b35a6d7d3d 100644 --- a/.github/workflows/pull_request_title_lint.yaml +++ b/.github/workflows/pull_request_title_lint.yaml @@ -15,7 +15,7 @@ jobs: name: Validate PR title runs-on: ubuntu-latest steps: - - uses: amannn/action-semantic-pull-request@e9fabac35e210fea40ca5b14c0da95a099eff26f # v5 + - uses: amannn/action-semantic-pull-request@cfb60706e18bc85e8aec535e3c577abe8f70378e # v5.5.2 id: lint_pr_title env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release_cli.yml b/.github/workflows/release_cli.yml index ef7976859b1..35b2762b2ed 100644 --- a/.github/workflows/release_cli.yml +++ b/.github/workflows/release_cli.yml @@ -19,7 +19,7 @@ jobs: nightly: ${{ env.nightly }} version_changed: ${{ steps.version.outputs.changed }} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Check nightly status id: nightly @@ -27,7 +27,7 @@ jobs: run: echo "nightly=true" >> $GITHUB_ENV - name: Check version changes - uses: EndBug/version-check@d4be4219408b50d1bbbfd350a47cbcb126878692 # v2 + uses: EndBug/version-check@d4be4219408b50d1bbbfd350a47cbcb126878692 # v2.1.4 if: env.nightly != 'true' id: version with: @@ -88,10 +88,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Install Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: 20 @@ -144,7 +144,7 @@ jobs: # Upload the CLI binary as a build artifact - name: Upload CLI artifact - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: cli-${{ matrix.target }} path: ./dist/biome-* @@ -156,7 +156,7 @@ jobs: needs: check steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh @@ -169,7 +169,7 @@ jobs: run: wasm-pack build --out-dir ../../packages/@biomejs/wasm-web --target web --release --scope biomedev crates/biome_wasm - name: Upload WASM artifact - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: wasm-${{ matrix.target }} path: | @@ -189,22 +189,22 @@ jobs: contents: write id-token: write steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Download CLI artifacts - uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4 + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 with: pattern: cli-* merge-multiple: true - name: Download WASM artifacts - uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4 + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 with: pattern: wasm-* merge-multiple: true path: packages/@biomejs - name: Install Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: 20 registry-url: 'https://registry.npmjs.org' @@ -230,7 +230,7 @@ jobs: run: | bash scripts/print-changelog.sh ${{ needs.build.outputs.version }} >| ${{ github.workspace }}/RELEASE_NOTES - name: Create GitHub release and tag - uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v2 + uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v2.0.4 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/release_js_api.yml b/.github/workflows/release_js_api.yml index 5d39fe35976..a1ab07db0d5 100644 --- a/.github/workflows/release_js_api.yml +++ b/.github/workflows/release_js_api.yml @@ -19,7 +19,7 @@ jobs: nightly: ${{ env.nightly }} version_changed: ${{ steps.version.outputs.changed }} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Check nightly status id: nightly @@ -27,7 +27,7 @@ jobs: run: echo "nightly=true" >> $GITHUB_ENV - name: Check version changes - uses: EndBug/version-check@d4be4219408b50d1bbbfd350a47cbcb126878692 # v2 + uses: EndBug/version-check@d4be4219408b50d1bbbfd350a47cbcb126878692 # v2.1.4 if: env.nightly != 'true' id: version with: @@ -58,10 +58,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Install Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: 20 @@ -69,7 +69,7 @@ jobs: run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - name: Cache pnpm modules - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/.pnpm-store key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} @@ -102,7 +102,7 @@ jobs: pnpm --filter @biomejs/js-api run build - name: Upload JS API artifact - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: js-api path: | @@ -118,16 +118,16 @@ jobs: contents: write id-token: write steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Download package artifact - uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4 + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 with: name: js-api path: packages/@biomejs/js-api/dist - name: Install Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: 20 registry-url: 'https://registry.npmjs.org' @@ -151,7 +151,7 @@ jobs: run: | bash scripts/print-changelog.sh ${{ needs.build.outputs.version }} >| ${{ github.workspace }}/RELEASE_NOTES - name: Create GitHub release and tag - uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v2 + uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v2.0.4 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 3066b71f780..e41b71b3cb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,28 +15,51 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b ### CLI -#### Bug fixes - -- The [stdin-file-path](https://biomejs.dev/guides/integrate-in-editor/#use-stdin) option now works correctly for Astro/Svelte/Vue files ([#2686](https://github.com/biomejs/biome/pull/2686)) - - Fix [#2225](https://github.com/biomejs/biome/issues/2225) where lint output become empty for Vue files. +#### Enhancements - Contributed by @tasshi-me - -- `biome migrate eslint` now correctly resolve `@scope/eslint-config` ([#2705](https://github.com/biomejs/biome/issues/2705)). Contributed by @Conaclos +- Biome now executes commands (lint, format, check and ci) on the working directory by default. [#2266](https://github.com/biomejs/biome/issues/2266) Contributed by @unvalley + ```diff + - biome check . + + biome check # You can run the command without the path + ``` + ### Configuration ### Editors +#### New features + +- Add support for LSP Workspaces + ### Formatter ### JavaScript APIs ### Linter +### Parser + + +## 1.7.3 (2024-05-06) + +### CLI + +#### Bug fixes + +- The [stdin-file-path](https://biomejs.dev/guides/integrate-in-editor/#use-stdin) option now works correctly for Astro/Svelte/Vue files ([#2686](https://github.com/biomejs/biome/pull/2686)) + + Fix [#2225](https://github.com/biomejs/biome/issues/2225) where lint output become empty for Vue files. + + Contributed by @tasshi-me + +- `biome migrate eslint` now correctly resolve `@scope/eslint-config` ([#2705](https://github.com/biomejs/biome/issues/2705)). Contributed by @Conaclos + +### Linter + #### New features +- Add [nursery/noUselessStringConcat](https://biomejs.dev/linter/rules/no-useless-string-concat/). - Add [nursery/useExplicitLengthCheck](https://biomejs.dev/linter/rules/use-explicit-length-check/). #### Bug fixes @@ -86,11 +109,19 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b Contributed by @Conaclos +- [useJsxKeyInIterable](https://biomejs.dev/linter/rules/use-jsx-key-in-iterable/) no longer reports false positive when iterating on non-jsx items ([#2590](https://github.com/biomejs/biome/issues/2590)). + + The following snipet of code no longer triggers the rule: + + ```jsx + <>{data.reduce((total, next) => total + next, 0)} + ``` + + Contributed by @dyc3 + - Fix typo by renaming `useConsistentBuiltinInstatiation` to `useConsistentBuiltinInstantiation` Contributed by @minht11 -### Parser - ## 1.7.2 (2024-04-30) diff --git a/Cargo.lock b/Cargo.lock index e60300a431a..09432f138f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -523,6 +523,8 @@ dependencies = [ "biome_diagnostics", "biome_grit_parser", "biome_grit_syntax", + "biome_js_syntax", + "biome_parser", "biome_rowan", "grit-pattern-matcher", "grit-util", @@ -2905,9 +2907,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.199" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] @@ -2925,9 +2927,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.199" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", @@ -3372,9 +3374,9 @@ checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" [[package]] name = "tower-lsp" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b38fb0e6ce037835174256518aace3ca621c4f96383c56bb846cfc11b341910" +checksum = "d4ba052b54a6627628d9b3c34c176e7eda8359b7da9acd497b9f20998d118508" dependencies = [ "async-trait", "auto_impl", @@ -3395,13 +3397,13 @@ dependencies = [ [[package]] name = "tower-lsp-macros" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34723c06344244474fdde365b76aebef8050bf6be61a935b91ee9ff7c4e91157" +checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.59", ] [[package]] @@ -3412,11 +3414,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -3437,20 +3438,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.59", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", diff --git a/Cargo.toml b/Cargo.toml index 39305a8fab4..7cbd01d9fee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -171,7 +171,7 @@ rayon = "1.8.1" regex = "1.10.4" rustc-hash = "1.1.0" schemars = "0.8.17" -serde = { version = "1.0.199", features = ["derive"] } +serde = { version = "1.0.200", features = ["derive"] } serde_json = "1.0.116" similar = "2.5.0" slotmap = "1.0.7" @@ -179,7 +179,7 @@ smallvec = { version = "1.10.0", features = ["union", "const_new"] } syn = "1.0.109" termcolor = "1.4.1" tokio = "1.36.0" -tracing = { version = "0.1.37", default-features = false, features = ["std"] } +tracing = { version = "0.1.40", default-features = false, features = ["std"] } tracing-subscriber = "0.3.18" unicode-bom = "2.0.3" unicode-width = "0.1.12" diff --git a/benchmark/package-lock.json b/benchmark/package-lock.json index 0899c4d9113..ed3f3936f76 100644 --- a/benchmark/package-lock.json +++ b/benchmark/package-lock.json @@ -11,8 +11,8 @@ "devDependencies": { "@mixer/parallel-prettier": "2.0.3", "dprint": "0.45.1", - "eslint": "9.1.1", - "prettier": "3.1.0" + "eslint": "9.2.0", + "prettier": "3.2.5" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -163,9 +163,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.1.1.tgz", - "integrity": "sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.2.0.tgz", + "integrity": "sha512-ESiIudvhoYni+MdsI8oD7skpprZ89qKocwRM2KEvhhBJ9nl5MRh7BXU5GTod7Mdygq+AUl+QzId6iWJKR/wABA==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -625,15 +625,15 @@ } }, "node_modules/eslint": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.1.1.tgz", - "integrity": "sha512-b4cRQ0BeZcSEzPpY2PjFY70VbO32K7BStTGtBsnIGdTSEEQzBi8hPBcGQmTG2zUvFr9uLe0TK42bw8YszuHEqg==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.2.0.tgz", + "integrity": "sha512-0n/I88vZpCOzO+PQpt0lbsqmn9AsnsJAQseIqhZFI8ibQT0U1AkEKRxA3EVMos0BoHSXDQvCXY25TUjB5tr8Og==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^3.0.2", - "@eslint/js": "9.1.1", + "@eslint/js": "9.2.0", "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.2.3", @@ -1423,9 +1423,9 @@ } }, "node_modules/prettier": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", - "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -1911,9 +1911,9 @@ } }, "@eslint/js": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.1.1.tgz", - "integrity": "sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.2.0.tgz", + "integrity": "sha512-ESiIudvhoYni+MdsI8oD7skpprZ89qKocwRM2KEvhhBJ9nl5MRh7BXU5GTod7Mdygq+AUl+QzId6iWJKR/wABA==", "dev": true }, "@humanwhocodes/config-array": { @@ -2231,15 +2231,15 @@ "dev": true }, "eslint": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.1.1.tgz", - "integrity": "sha512-b4cRQ0BeZcSEzPpY2PjFY70VbO32K7BStTGtBsnIGdTSEEQzBi8hPBcGQmTG2zUvFr9uLe0TK42bw8YszuHEqg==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.2.0.tgz", + "integrity": "sha512-0n/I88vZpCOzO+PQpt0lbsqmn9AsnsJAQseIqhZFI8ibQT0U1AkEKRxA3EVMos0BoHSXDQvCXY25TUjB5tr8Og==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^3.0.2", - "@eslint/js": "9.1.1", + "@eslint/js": "9.2.0", "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.2.3", @@ -2826,9 +2826,9 @@ "dev": true }, "prettier": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", - "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true }, "process-nextick-args": { diff --git a/benchmark/package.json b/benchmark/package.json index 8213b0d9721..e24900f9e32 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -10,7 +10,7 @@ "devDependencies": { "@mixer/parallel-prettier": "2.0.3", "dprint": "0.45.1", - "eslint": "9.1.1", - "prettier": "3.1.0" + "eslint": "9.2.0", + "prettier": "3.2.5" } } diff --git a/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs b/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs index c46feab3002..9671393b7da 100644 --- a/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs +++ b/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs @@ -1058,6 +1058,16 @@ pub(crate) fn migrate_eslint_any_rule( let rule = group.no_useless_catch.get_or_insert(Default::default()); rule.set_level(rule_severity.into()); } + "no-useless-concat" => { + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group + .no_useless_string_concat + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } "no-useless-constructor" => { let group = rules.complexity.get_or_insert_with(Default::default); let rule = group diff --git a/crates/biome_cli/src/execute/traverse.rs b/crates/biome_cli/src/execute/traverse.rs index 6db15bff064..f4e78e2ac30 100644 --- a/crates/biome_cli/src/execute/traverse.rs +++ b/crates/biome_cli/src/execute/traverse.rs @@ -17,6 +17,7 @@ use crossbeam::channel::{unbounded, Receiver, Sender}; use rustc_hash::FxHashSet; use std::sync::atomic::AtomicU32; use std::{ + env::current_dir, ffi::OsString, panic::catch_unwind, path::{Path, PathBuf}, @@ -32,17 +33,28 @@ pub(crate) fn traverse( execution: &Execution, session: &mut CliSession, cli_options: &CliOptions, - inputs: Vec, + mut inputs: Vec, ) -> Result<(TraversalSummary, Vec), CliDiagnostic> { init_thread_pool(); - if inputs.is_empty() - && execution.as_stdin_file().is_none() - && !cli_options.no_errors_on_unmatched - { - return Err(CliDiagnostic::missing_argument( - "", - format!("{}", execution.traversal_mode), - )); + + if inputs.is_empty() { + match execution.traversal_mode { + TraversalMode::Check { .. } + | TraversalMode::Lint { .. } + | TraversalMode::Format { .. } + | TraversalMode::CI { .. } => match current_dir() { + Ok(current_dir) => inputs.push(current_dir.into_os_string()), + Err(err) => return Err(CliDiagnostic::io_error(err)), + }, + _ => { + if execution.as_stdin_file().is_none() && !cli_options.no_errors_on_unmatched { + return Err(CliDiagnostic::missing_argument( + "", + format!("{}", execution.traversal_mode), + )); + } + } + } } let (interner, recv_files) = PathInterner::new(); diff --git a/crates/biome_cli/tests/commands/check.rs b/crates/biome_cli/tests/commands/check.rs index 42c80ed85f0..b59a6dcfcb3 100644 --- a/crates/biome_cli/tests/commands/check.rs +++ b/crates/biome_cli/tests/commands/check.rs @@ -2897,3 +2897,28 @@ fn print_json_pretty() { result, )); } + +#[test] +fn lint_error_without_file_paths() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("check.js"); + fs.insert(file_path.into(), LINT_ERROR.as_bytes()); + + let result: Result<(), biome_cli::CliDiagnostic> = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("check"), ""].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "lint_error_without_file_paths", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/commands/ci.rs b/crates/biome_cli/tests/commands/ci.rs index aea7cc6f96e..f41bca32dcb 100644 --- a/crates/biome_cli/tests/commands/ci.rs +++ b/crates/biome_cli/tests/commands/ci.rs @@ -1025,3 +1025,28 @@ A = 0; result, )); } + +#[test] +fn does_formatting_error_without_file_paths() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("ci.js"); + fs.insert(file_path.into(), UNFORMATTED.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("ci"), ""].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "does_formatting_error_without_file_paths", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/commands/format.rs b/crates/biome_cli/tests/commands/format.rs index ef0e1dcbd5a..1decf72ded5 100644 --- a/crates/biome_cli/tests/commands/format.rs +++ b/crates/biome_cli/tests/commands/format.rs @@ -3585,3 +3585,30 @@ fn print_json_pretty() { result, )); } + +#[test] +fn format_without_file_paths() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("format.js"); + fs.insert(file_path.into(), UNFORMATTED.as_bytes()); + + let result: Result<(), biome_cli::CliDiagnostic> = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("format"), ""].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_file_contents(&fs, file_path, UNFORMATTED); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "format_without_file_paths", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/commands/lint.rs b/crates/biome_cli/tests/commands/lint.rs index ba5253458db..e15a4b66e5c 100644 --- a/crates/biome_cli/tests/commands/lint.rs +++ b/crates/biome_cli/tests/commands/lint.rs @@ -1966,7 +1966,7 @@ fn group_level_recommended_false_enable_specific() { let code = r#" function SubmitButton() { return ; - } + } "#; let file_path = Path::new("fix.jsx"); @@ -3246,3 +3246,28 @@ import "lodash"; result, )); } + +#[test] +fn should_lint_error_without_file_paths() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("check.js"); + fs.insert(file_path.into(), LINT_ERROR.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("lint"), ""].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "lint_error_without_file_paths", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/snapshots/main_commands_check/lint_error_without_file_paths.snap b/crates/biome_cli/tests/snapshots/main_commands_check/lint_error_without_file_paths.snap new file mode 100644 index 00000000000..2d4b249e7dd --- /dev/null +++ b/crates/biome_cli/tests/snapshots/main_commands_check/lint_error_without_file_paths.snap @@ -0,0 +1,70 @@ +--- +source: crates/biome_cli/tests/snap_test.rs +expression: content +--- +## `check.js` + +```js +for(;true;); + +``` + +# Termination Message + +```block +check ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Some errors were emitted while running checks. + + + +``` + +# Emitted Messages + +```block +check.js:1:1 lint/style/useWhile FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Use a while loop instead of a for loop. + + > 1 │ for(;true;); + │ ^^^^^^^^^^^ + 2 │ + + i Prefer a while loop over a for loop without initialization and update. + + i Safe fix: Use a while loop. + + 1 │ - for(;true;); + 1 │ + while(true); + 2 2 │ + + +``` + +```block +check.js:1:6 lint/correctness/noConstantCondition ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected constant condition. + + > 1 │ for(;true;); + │ ^^^^ + 2 │ + + +``` + +```block +check.js format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Formatter would have printed the following content: + + 1 │ for·(;·true;·); + │ + + + + +``` + +```block +Checked 1 file in