From 30141aa46b32b1bc26353bb855e658d4825c82dd Mon Sep 17 00:00:00 2001 From: Kazuhiro-Mimaki Date: Thu, 4 Jul 2024 22:48:40 +0900 Subject: [PATCH 1/7] feat: create new rule by just --- .../biome_configuration/src/linter/rules.rs | 119 ++++++++++-------- crates/biome_css_analyze/src/lint/nursery.rs | 2 + crates/biome_css_analyze/src/options.rs | 1 + .../src/categories.rs | 1 + .../@biomejs/biome/configuration_schema.json | 7 ++ 5 files changed, 79 insertions(+), 51 deletions(-) diff --git a/crates/biome_configuration/src/linter/rules.rs b/crates/biome_configuration/src/linter/rules.rs index 75302e1838ac..65b9d6a836be 100644 --- a/crates/biome_configuration/src/linter/rules.rs +++ b/crates/biome_configuration/src/linter/rules.rs @@ -2894,6 +2894,9 @@ pub struct Nursery { #[serde(skip_serializing_if = "Option::is_none")] pub no_unknown_selector_pseudo_element: Option>, + #[doc = "Disallow unknown type selectors."] + #[serde(skip_serializing_if = "Option::is_none")] + pub no_unknown_type_selector: Option>, #[doc = "Disallow unknown CSS units."] #[serde(skip_serializing_if = "Option::is_none")] pub no_unknown_unit: Option>, @@ -3016,6 +3019,7 @@ impl Nursery { "noUnknownProperty", "noUnknownPseudoClassSelector", "noUnknownSelectorPseudoElement", + "noUnknownTypeSelector", "noUnknownUnit", "noUnmatchableAnbSelector", "noUnusedFunctionParameters", @@ -3080,7 +3084,6 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24]), 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]), @@ -3286,131 +3289,136 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25])); } } - if let Some(rule) = self.no_unknown_unit.as_ref() { + if let Some(rule) = self.no_unknown_type_selector.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26])); } } - if let Some(rule) = self.no_unmatchable_anb_selector.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[27])); } } - if let Some(rule) = self.no_unused_function_parameters.as_ref() { + if let Some(rule) = self.no_unmatchable_anb_selector.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28])); } } - if let Some(rule) = self.no_useless_string_concat.as_ref() { + if let Some(rule) = self.no_unused_function_parameters.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29])); } } - if let Some(rule) = self.no_useless_undefined_initialization.as_ref() { + if let Some(rule) = self.no_useless_string_concat.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30])); } } - if let Some(rule) = self.no_yoda_expression.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[31])); } } - if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { + if let Some(rule) = self.no_yoda_expression.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32])); } } - if let Some(rule) = self.use_consistent_builtin_instantiation.as_ref() { + if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33])); } } - if let Some(rule) = self.use_consistent_grid_areas.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[34])); } } - if let Some(rule) = self.use_date_now.as_ref() { + if let Some(rule) = self.use_consistent_grid_areas.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35])); } } - if let Some(rule) = self.use_default_switch_clause.as_ref() { + if let Some(rule) = self.use_date_now.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36])); } } - if let Some(rule) = self.use_deprecated_reason.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[37])); } } - if let Some(rule) = self.use_error_message.as_ref() { + if let Some(rule) = self.use_deprecated_reason.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38])); } } - if let Some(rule) = self.use_explicit_length_check.as_ref() { + if let Some(rule) = self.use_error_message.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39])); } } - if let Some(rule) = self.use_focusable_interactive.as_ref() { + if let Some(rule) = self.use_explicit_length_check.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[40])); } } - if let Some(rule) = self.use_generic_font_names.as_ref() { + if let Some(rule) = self.use_focusable_interactive.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[41])); } } - if let Some(rule) = self.use_import_extensions.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[42])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.use_import_extensions.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[43])); } } - if let Some(rule) = self.use_number_to_fixed_digits_argument.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[44])); } } - if let Some(rule) = self.use_semantic_elements.as_ref() { + if let Some(rule) = self.use_number_to_fixed_digits_argument.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[45])); } } - if let Some(rule) = self.use_sorted_classes.as_ref() { + if let Some(rule) = self.use_semantic_elements.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[46])); } } - if let Some(rule) = self.use_throw_new_error.as_ref() { + 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[47])); } } - if let Some(rule) = self.use_throw_only_error.as_ref() { + if let Some(rule) = self.use_throw_new_error.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[48])); } } - if let Some(rule) = self.use_top_level_regex.as_ref() { + if let Some(rule) = self.use_throw_only_error.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[49])); } } - if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if let Some(rule) = self.use_top_level_regex.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[50])); } } + if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if rule.is_enabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[51])); + } + } index_set } pub(crate) fn get_disabled_rules(&self) -> FxHashSet> { @@ -3545,131 +3553,136 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25])); } } - if let Some(rule) = self.no_unknown_unit.as_ref() { + if let Some(rule) = self.no_unknown_type_selector.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26])); } } - if let Some(rule) = self.no_unmatchable_anb_selector.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[27])); } } - if let Some(rule) = self.no_unused_function_parameters.as_ref() { + if let Some(rule) = self.no_unmatchable_anb_selector.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28])); } } - if let Some(rule) = self.no_useless_string_concat.as_ref() { + if let Some(rule) = self.no_unused_function_parameters.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29])); } } - if let Some(rule) = self.no_useless_undefined_initialization.as_ref() { + if let Some(rule) = self.no_useless_string_concat.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30])); } } - if let Some(rule) = self.no_yoda_expression.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[31])); } } - if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { + if let Some(rule) = self.no_yoda_expression.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32])); } } - if let Some(rule) = self.use_consistent_builtin_instantiation.as_ref() { + if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33])); } } - if let Some(rule) = self.use_consistent_grid_areas.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[34])); } } - if let Some(rule) = self.use_date_now.as_ref() { + if let Some(rule) = self.use_consistent_grid_areas.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35])); } } - if let Some(rule) = self.use_default_switch_clause.as_ref() { + if let Some(rule) = self.use_date_now.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36])); } } - if let Some(rule) = self.use_deprecated_reason.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[37])); } } - if let Some(rule) = self.use_error_message.as_ref() { + if let Some(rule) = self.use_deprecated_reason.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38])); } } - if let Some(rule) = self.use_explicit_length_check.as_ref() { + if let Some(rule) = self.use_error_message.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39])); } } - if let Some(rule) = self.use_focusable_interactive.as_ref() { + if let Some(rule) = self.use_explicit_length_check.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[40])); } } - if let Some(rule) = self.use_generic_font_names.as_ref() { + if let Some(rule) = self.use_focusable_interactive.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[41])); } } - if let Some(rule) = self.use_import_extensions.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[42])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.use_import_extensions.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[43])); } } - if let Some(rule) = self.use_number_to_fixed_digits_argument.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[44])); } } - if let Some(rule) = self.use_semantic_elements.as_ref() { + if let Some(rule) = self.use_number_to_fixed_digits_argument.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[45])); } } - if let Some(rule) = self.use_sorted_classes.as_ref() { + if let Some(rule) = self.use_semantic_elements.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[46])); } } - if let Some(rule) = self.use_throw_new_error.as_ref() { + 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[47])); } } - if let Some(rule) = self.use_throw_only_error.as_ref() { + if let Some(rule) = self.use_throw_new_error.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[48])); } } - if let Some(rule) = self.use_top_level_regex.as_ref() { + if let Some(rule) = self.use_throw_only_error.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[49])); } } - if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if let Some(rule) = self.use_top_level_regex.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[50])); } } + if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if rule.is_disabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[51])); + } + } index_set } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] @@ -3810,6 +3823,10 @@ impl Nursery { .no_unknown_selector_pseudo_element .as_ref() .map(|conf| (conf.level(), conf.get_options())), + "noUnknownTypeSelector" => self + .no_unknown_type_selector + .as_ref() + .map(|conf| (conf.level(), conf.get_options())), "noUnknownUnit" => self .no_unknown_unit .as_ref() diff --git a/crates/biome_css_analyze/src/lint/nursery.rs b/crates/biome_css_analyze/src/lint/nursery.rs index c1896db729a2..2cccd1556897 100644 --- a/crates/biome_css_analyze/src/lint/nursery.rs +++ b/crates/biome_css_analyze/src/lint/nursery.rs @@ -15,6 +15,7 @@ pub mod no_unknown_media_feature_name; pub mod no_unknown_property; pub mod no_unknown_pseudo_class_selector; pub mod no_unknown_selector_pseudo_element; +pub mod no_unknown_type_selector; pub mod no_unknown_unit; pub mod no_unmatchable_anb_selector; pub mod use_consistent_grid_areas; @@ -37,6 +38,7 @@ declare_lint_group! { self :: no_unknown_property :: NoUnknownProperty , self :: no_unknown_pseudo_class_selector :: NoUnknownPseudoClassSelector , self :: no_unknown_selector_pseudo_element :: NoUnknownSelectorPseudoElement , + self :: no_unknown_type_selector :: NoUnknownTypeSelector , self :: no_unknown_unit :: NoUnknownUnit , self :: no_unmatchable_anb_selector :: NoUnmatchableAnbSelector , self :: use_consistent_grid_areas :: UseConsistentGridAreas , diff --git a/crates/biome_css_analyze/src/options.rs b/crates/biome_css_analyze/src/options.rs index 2628056d6143..b205184cc88b 100644 --- a/crates/biome_css_analyze/src/options.rs +++ b/crates/biome_css_analyze/src/options.rs @@ -19,6 +19,7 @@ pub type NoUnknownProperty = ::Options; pub type NoUnknownPseudoClassSelector = < lint :: nursery :: no_unknown_pseudo_class_selector :: NoUnknownPseudoClassSelector as biome_analyze :: Rule > :: Options ; pub type NoUnknownSelectorPseudoElement = < lint :: nursery :: no_unknown_selector_pseudo_element :: NoUnknownSelectorPseudoElement as biome_analyze :: Rule > :: Options ; +pub type NoUnknownTypeSelector = < lint :: nursery :: no_unknown_type_selector :: NoUnknownTypeSelector as biome_analyze :: Rule > :: Options ; pub type NoUnknownUnit = ::Options; pub type NoUnmatchableAnbSelector = < lint :: nursery :: no_unmatchable_anb_selector :: NoUnmatchableAnbSelector as biome_analyze :: Rule > :: Options ; diff --git a/crates/biome_diagnostics_categories/src/categories.rs b/crates/biome_diagnostics_categories/src/categories.rs index c85668c788c3..9f68d42af8d6 100644 --- a/crates/biome_diagnostics_categories/src/categories.rs +++ b/crates/biome_diagnostics_categories/src/categories.rs @@ -142,6 +142,7 @@ define_categories! { "lint/nursery/noUnknownProperty": "https://biomejs.dev/linter/rules/no-unknown-property", "lint/nursery/noUnknownPseudoClassSelector": "https://biomejs.dev/linter/rules/no-unknown-pseudo-class-selector", "lint/nursery/noUnknownSelectorPseudoElement": "https://biomejs.dev/linter/rules/no-unknown-selector-pseudo-element", + "lint/nursery/noUnknownTypeSelector": "https://biomejs.dev/linter/rules/no-unknown-type-selector", "lint/nursery/noUnknownUnit": "https://biomejs.dev/linter/rules/no-unknown-unit", "lint/nursery/noUnmatchableAnbSelector": "https://biomejs.dev/linter/rules/no-unmatchable-anb-selector", "lint/nursery/noUnusedFunctionParameters": "https://biomejs.dev/linter/rules/no-unused-function-parameters", diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 0de5597190bd..2403bfe49c1d 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -1923,6 +1923,13 @@ { "type": "null" } ] }, + "noUnknownTypeSelector": { + "description": "Disallow unknown type selectors.", + "anyOf": [ + { "$ref": "#/definitions/RuleConfiguration" }, + { "type": "null" } + ] + }, "noUnknownUnit": { "description": "Disallow unknown CSS units.", "anyOf": [ From 5ad6bee0a8e3d56832f81bc9ec1713a00a3a97bb Mon Sep 17 00:00:00 2001 From: Kazuhiro-Mimaki Date: Mon, 24 Jun 2024 10:31:37 +0900 Subject: [PATCH 2/7] feat: implement no_unknown_type_selector --- crates/biome_css_analyze/src/keywords.rs | 302 +++++++++++++++++- .../lint/nursery/no_unknown_type_selector.rs | 95 ++++++ crates/biome_css_analyze/src/utils.rs | 19 +- .../nursery/noUnknownTypeSelector/invalid.css | 25 ++ .../noUnknownTypeSelector/invalid.css.snap | 183 +++++++++++ .../nursery/noUnknownTypeSelector/valid.css | 21 ++ .../noUnknownTypeSelector/valid.css.snap | 29 ++ .../@biomejs/backend-jsonrpc/src/workspace.ts | 5 + 8 files changed, 673 insertions(+), 6 deletions(-) create mode 100644 crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/invalid.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/invalid.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/valid.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/valid.css.snap diff --git a/crates/biome_css_analyze/src/keywords.rs b/crates/biome_css_analyze/src/keywords.rs index 4b41b8dafdf6..e023ec29ff71 100644 --- a/crates/biome_css_analyze/src/keywords.rs +++ b/crates/biome_css_analyze/src/keywords.rs @@ -5433,17 +5433,292 @@ pub const RESET_TO_INITIAL_PROPERTIES_BY_FONT: [&str; 13] = [ "font-variation-settings", ]; +// https://developer.mozilla.org/ja/docs/Web/HTML/Element +// https://github.com/sindresorhus/html-tags/blob/main/html-tags.json +pub const HTML_TAGS: [&str; 148] = [ + "a", + "abbr", + "acronym", + "address", + "applet", + "area", + "article", + "aside", + "audio", + "b", + "base", + "basefont", + "bdi", + "bdo", + "bgsound", + "big", + "blink", + "blockquote", + "body", + "br", + "button", + "canvas", + "caption", + "center", + "cite", + "code", + "col", + "colgroup", + "content", + "data", + "datalist", + "dd", + "del", + "details", + "dfn", + "dir", + "div", + "dl", + "dt", + "em", + "embed", + "fencedframe", + "fieldset", + "figcaption", + "figure", + "font", + "footer", + "form", + "frame", + "frameset", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "head", + "header", + "hgroup", + "hr", + "html", + "i", + "iframe", + "img", + "input", + "ins", + "isindex", + "kbd", + "keygen", + "label", + "legend", + "li", + "link", + "listbox", + "listing", + "main", + "map", + "mark", + "marquee", + "math", + "menu", + "menuitem", + "meta", + "meter", + "model", + "multicol", + "nav", + "nextid", + "nobr", + "noembed", + "noframes", + "noscript", + "object", + "ol", + "optgroup", + "option", + "output", + "p", + "param", + "picture", + "plaintext", + "portal", + "pre", + "progress", + "q", + "rb", + "rp", + "rt", + "rtc", + "ruby", + "s", + "samp", + "script", + "search", + "section", + "select", + "selectlist", + "slot", + "small", + "source", + "spacer", + "span", + "strike", + "strong", + "style", + "sub", + "summary", + "sup", + "svg", + "table", + "tbody", + "td", + "template", + "textarea", + "tfoot", + "th", + "thead", + "time", + "title", + "tr", + "track", + "tt", + "u", + "ul", + "var", + "video", + "wbr", + "xmp", +]; + +// https://developer.mozilla.org/ja/docs/Web/SVG/Element +// https://github.com/element-io/svg-tags/blob/master/lib/svg-tags.json +pub const SVG_TAGS: [&str; 81] = [ + "a", + "altGlyph", + "altGlyphDef", + "altGlyphItem", + "animate", + "animateColor", + "animateMotion", + "animateTransform", + "circle", + "clipPath", + "color-profile", + "cursor", + "defs", + "desc", + "ellipse", + "feBlend", + "feColorMatrix", + "feComponentTransfer", + "feComposite", + "feConvolveMatrix", + "feDiffuseLighting", + "feDisplacementMap", + "feDistantLight", + "feDropShadow", + "feFlood", + "feFuncA", + "feFuncB", + "feFuncG", + "feFuncR", + "feGaussianBlur", + "feImage", + "feMerge", + "feMergeNode", + "feMorphology", + "feOffset", + "fePointLight", + "feSpecularLighting", + "feSpotLight", + "feTile", + "feTurbulence", + "filter", + "font", + "font-face", + "font-face-format", + "font-face-name", + "font-face-src", + "font-face-uri", + "foreignObject", + "g", + "glyph", + "glyphRef", + "hatchpath", + "hkern", + "image", + "line", + "linearGradient", + "marker", + "mask", + "metadata", + "missing-glyph", + "mpath", + "path", + "pattern", + "polygon", + "polyline", + "radialGradient", + "rect", + "script", + "set", + "stop", + "style", + "svg", + "switch", + "symbol", + "text", + "textPath", + "title", + "tspan", + "use", + "view", + "vkern", +]; + +// https://developer.mozilla.org/ja/docs/Web/MathML/Element +pub const MATH_ML_TAGS: [&str; 32] = [ + "annotation", + "annotation-xml", + "maction", + "math", + "menclose", + "merror", + "mfenced", + "mfrac", + "mi", + "mmultiscripts", + "mn", + "mo", + "mover", + "mpadded", + "mphantom", + "mprescripts", + "mroot", + "mrow", + "ms", + "mspace", + "msqrt", + "mstyle", + "msub", + "msubsup", + "msup", + "mtable", + "mtd", + "mtext", + "mtr", + "munder", + "munderover", + "semantics", +]; + #[cfg(test)] mod tests { use std::collections::HashSet; use super::{ - FUNCTION_KEYWORDS, KNOWN_EDGE_PROPERTIES, KNOWN_EXPLORER_PROPERTIES, + FUNCTION_KEYWORDS, HTML_TAGS, KNOWN_EDGE_PROPERTIES, KNOWN_EXPLORER_PROPERTIES, KNOWN_FIREFOX_PROPERTIES, KNOWN_PROPERTIES, KNOWN_SAFARI_PROPERTIES, KNOWN_SAMSUNG_INTERNET_PROPERTIES, KNOWN_US_BROWSER_PROPERTIES, - LONGHAND_SUB_PROPERTIES_OF_SHORTHAND_PROPERTIES, MEDIA_FEATURE_NAMES, + LONGHAND_SUB_PROPERTIES_OF_SHORTHAND_PROPERTIES, MATH_ML_TAGS, MEDIA_FEATURE_NAMES, RESET_TO_INITIAL_PROPERTIES_BY_BORDER, RESET_TO_INITIAL_PROPERTIES_BY_FONT, - SHORTHAND_PROPERTIES, + SHORTHAND_PROPERTIES, SVG_TAGS, }; #[test] @@ -5635,4 +5910,25 @@ mod tests { .any(|&x| !set.insert(x)); assert!(!has_duplicates); } + + #[test] + fn test_selector_types() { + for items in HTML_TAGS.windows(2) { + assert!(items[0] < items[1], "{} < {}", items[0], items[1]); + } + } + + #[test] + fn test_svg_tags() { + for items in SVG_TAGS.windows(2) { + assert!(items[0] < items[1], "{} < {}", items[0], items[1]); + } + } + + #[test] + fn test_math_ml_tags() { + for items in MATH_ML_TAGS.windows(2) { + assert!(items[0] < items[1], "{} < {}", items[0], items[1]); + } + } } diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs new file mode 100644 index 000000000000..b2f0e4a2aaa1 --- /dev/null +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs @@ -0,0 +1,95 @@ +use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic, RuleSource}; +use biome_console::markup; +use biome_css_syntax::CssTypeSelector; +use biome_rowan::AstNode; + +use crate::utils::is_known_type_selector; + +declare_rule! { + /// Disallow unknown type selectors. + /// + /// This rule considers tags defined in the HTML, SVG, and MathML specifications to be known. + /// For details on known CSS type selectors, see the following links + /// - https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors + /// - https://developer.mozilla.org/ja/docs/Web/HTML/Element + /// - https://developer.mozilla.org/ja/docs/Web/SVG/Element + /// - https://developer.mozilla.org/ja/docs/Web/MathML/Element + /// + /// This rule allows custom elements. + /// + /// ## Examples + /// + /// ### Invalid + /// + /// ```css,expect_diagnostic + /// unknown {} + /// ``` + /// + /// ```css,expect_diagnostic + /// unknown > ul {} + /// ``` + /// + /// ```css,expect_diagnostic + /// x-Foo {} + /// ``` + /// + /// ### Valid + /// + /// ```css + /// input {} + /// ``` + /// + /// ```css + /// ul > li {} + /// ``` + /// + /// ```css + /// x-foo {} + /// ``` + /// + pub NoUnknownTypeSelector { + version: "next", + name: "noUnknownTypeSelector", + language: "css", + recommended: true, + sources: &[RuleSource::Stylelint("selector-type-no-unknown")], + } +} + +impl Rule for NoUnknownTypeSelector { + type Query = Ast; + type State = CssTypeSelector; + type Signals = Option; + type Options = (); + + fn run(ctx: &RuleContext) -> Option { + let css_type_selector = ctx.query(); + let type_selector = css_type_selector + .ident() + .ok()? + .value_token() + .ok()? + .token_text_trimmed(); + if !is_known_type_selector(&type_selector) { + return Some(css_type_selector.clone()); + } + None + } + + fn diagnostic(_: &RuleContext, node: &Self::State) -> Option { + let span = node.range(); + Some( + RuleDiagnostic::new( + rule_category!(), + span, + markup! { + "Unknown type selector is not allowed." + }, + ) + .note(markup! { + "See ""MDN web docs"" for more details." + }).note(markup! { + "Consider replacing the unknown type selector with valid one."}) + ) + } +} diff --git a/crates/biome_css_analyze/src/utils.rs b/crates/biome_css_analyze/src/utils.rs index df274dc12ba9..d70c7ebaa99e 100644 --- a/crates/biome_css_analyze/src/utils.rs +++ b/crates/biome_css_analyze/src/utils.rs @@ -2,15 +2,15 @@ use crate::keywords::{ AT_RULE_PAGE_PSEUDO_CLASSES, A_NPLUS_BNOTATION_PSEUDO_CLASSES, A_NPLUS_BOF_SNOTATION_PSEUDO_CLASSES, BASIC_KEYWORDS, FONT_FAMILY_KEYWORDS, FONT_SIZE_KEYWORDS, FONT_STRETCH_KEYWORDS, FONT_STYLE_KEYWORDS, FONT_VARIANTS_KEYWORDS, - FONT_WEIGHT_ABSOLUTE_KEYWORDS, FONT_WEIGHT_NUMERIC_KEYWORDS, FUNCTION_KEYWORDS, + FONT_WEIGHT_ABSOLUTE_KEYWORDS, FONT_WEIGHT_NUMERIC_KEYWORDS, FUNCTION_KEYWORDS, HTML_TAGS, KNOWN_CHROME_PROPERTIES, KNOWN_EDGE_PROPERTIES, KNOWN_EXPLORER_PROPERTIES, KNOWN_FIREFOX_PROPERTIES, KNOWN_PROPERTIES, KNOWN_SAFARI_PROPERTIES, KNOWN_SAMSUNG_INTERNET_PROPERTIES, KNOWN_US_BROWSER_PROPERTIES, LEVEL_ONE_AND_TWO_PSEUDO_ELEMENTS, LINE_HEIGHT_KEYWORDS, LINGUISTIC_PSEUDO_CLASSES, LOGICAL_COMBINATIONS_PSEUDO_CLASSES, LONGHAND_SUB_PROPERTIES_OF_SHORTHAND_PROPERTIES, - MEDIA_FEATURE_NAMES, OTHER_PSEUDO_CLASSES, OTHER_PSEUDO_ELEMENTS, + MATH_ML_TAGS, MEDIA_FEATURE_NAMES, OTHER_PSEUDO_CLASSES, OTHER_PSEUDO_ELEMENTS, RESET_TO_INITIAL_PROPERTIES_BY_BORDER, RESET_TO_INITIAL_PROPERTIES_BY_FONT, - RESOURCE_STATE_PSEUDO_CLASSES, SHADOW_TREE_PSEUDO_ELEMENTS, SHORTHAND_PROPERTIES, + RESOURCE_STATE_PSEUDO_CLASSES, SHADOW_TREE_PSEUDO_ELEMENTS, SHORTHAND_PROPERTIES, SVG_TAGS, SYSTEM_FAMILY_NAME_KEYWORDS, VENDOR_PREFIXES, VENDOR_SPECIFIC_PSEUDO_ELEMENTS, }; use biome_css_syntax::{AnyCssGenericComponentValue, AnyCssValue, CssGenericComponentValueList}; @@ -215,3 +215,16 @@ pub fn get_reset_to_initial_properties(shorthand_property: &str) -> &'static [&' _ => &[], } } + +fn is_custom_element(prop: &str) -> bool { + prop.contains('-') && prop.eq(prop.to_lowercase().as_str()) +} + +/// Check if the input string is a known type selector. +pub fn is_known_type_selector(prop: &str) -> bool { + let input = prop.to_lowercase(); + HTML_TAGS.binary_search(&input.as_str()).is_ok() + || SVG_TAGS.binary_search(&prop).is_ok() + || MATH_ML_TAGS.binary_search(&input.as_str()).is_ok() + || is_custom_element(prop) +} diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/invalid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/invalid.css new file mode 100644 index 000000000000..2fe3d8798769 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/invalid.css @@ -0,0 +1,25 @@ +unknown { +} + +ul unknown { +} + +unknown ul { +} + +li > hoge { +} + +fuga > li { +} + +table, +unknown { +} + +unknown, +article { +} + +x-Foo { +} diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/invalid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/invalid.css.snap new file mode 100644 index 000000000000..ec89dee08aef --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/invalid.css.snap @@ -0,0 +1,183 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: invalid.css +--- +# Input +```css +unknown { +} + +ul unknown { +} + +unknown ul { +} + +li > hoge { +} + +fuga > li { +} + +table, +unknown { +} + +unknown, +article { +} + +x-Foo { +} + +``` + +# Diagnostics +``` +invalid.css:1:1 lint/nursery/noUnknownTypeSelector ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unknown type selector is not allowed. + + > 1 │ unknown { + │ ^^^^^^^ + 2 │ } + 3 │ + + i See MDN web docs for more details. + + i Consider replacing the unknown type selector with valid one. + + +``` + +``` +invalid.css:4:4 lint/nursery/noUnknownTypeSelector ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unknown type selector is not allowed. + + 2 │ } + 3 │ + > 4 │ ul unknown { + │ ^^^^^^^ + 5 │ } + 6 │ + + i See MDN web docs for more details. + + i Consider replacing the unknown type selector with valid one. + + +``` + +``` +invalid.css:7:1 lint/nursery/noUnknownTypeSelector ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unknown type selector is not allowed. + + 5 │ } + 6 │ + > 7 │ unknown ul { + │ ^^^^^^^ + 8 │ } + 9 │ + + i See MDN web docs for more details. + + i Consider replacing the unknown type selector with valid one. + + +``` + +``` +invalid.css:10:6 lint/nursery/noUnknownTypeSelector ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unknown type selector is not allowed. + + 8 │ } + 9 │ + > 10 │ li > hoge { + │ ^^^^ + 11 │ } + 12 │ + + i See MDN web docs for more details. + + i Consider replacing the unknown type selector with valid one. + + +``` + +``` +invalid.css:13:1 lint/nursery/noUnknownTypeSelector ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unknown type selector is not allowed. + + 11 │ } + 12 │ + > 13 │ fuga > li { + │ ^^^^ + 14 │ } + 15 │ + + i See MDN web docs for more details. + + i Consider replacing the unknown type selector with valid one. + + +``` + +``` +invalid.css:17:1 lint/nursery/noUnknownTypeSelector ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unknown type selector is not allowed. + + 16 │ table, + > 17 │ unknown { + │ ^^^^^^^ + 18 │ } + 19 │ + + i See MDN web docs for more details. + + i Consider replacing the unknown type selector with valid one. + + +``` + +``` +invalid.css:20:1 lint/nursery/noUnknownTypeSelector ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unknown type selector is not allowed. + + 18 │ } + 19 │ + > 20 │ unknown, + │ ^^^^^^^ + 21 │ article { + 22 │ } + + i See MDN web docs for more details. + + i Consider replacing the unknown type selector with valid one. + + +``` + +``` +invalid.css:24:1 lint/nursery/noUnknownTypeSelector ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unknown type selector is not allowed. + + 22 │ } + 23 │ + > 24 │ x-Foo { + │ ^^^^^ + 25 │ } + 26 │ + + i See MDN web docs for more details. + + i Consider replacing the unknown type selector with valid one. + + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/valid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/valid.css new file mode 100644 index 000000000000..cbe72617a5c2 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/valid.css @@ -0,0 +1,21 @@ +input { +} + +ul li { +} + +li > a { +} + +table, +tr { +} + +x-foo { +} + +g { +} + +mfrac { +} diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/valid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/valid.css.snap new file mode 100644 index 000000000000..fde7a93556c3 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownTypeSelector/valid.css.snap @@ -0,0 +1,29 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: valid.css +--- +# Input +```css +input { +} + +ul li { +} + +li > a { +} + +table, +tr { +} + +x-foo { +} + +g { +} + +mfrac { +} + +``` diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 9bcc88f7c8a5..b5f7b09079af 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -1143,6 +1143,10 @@ export interface Nursery { * Disallow unknown pseudo-element selectors. */ noUnknownSelectorPseudoElement?: RuleConfiguration_for_Null; + /** + * Disallow unknown type selectors. + */ + noUnknownTypeSelector?: RuleConfiguration_for_Null; /** * Disallow unknown CSS units. */ @@ -2506,6 +2510,7 @@ export type Category = | "lint/nursery/noUnknownProperty" | "lint/nursery/noUnknownPseudoClassSelector" | "lint/nursery/noUnknownSelectorPseudoElement" + | "lint/nursery/noUnknownTypeSelector" | "lint/nursery/noUnknownUnit" | "lint/nursery/noUnmatchableAnbSelector" | "lint/nursery/noUnusedFunctionParameters" From fa81d894da86b0d6ff2aa7698268b6c67604c1cb Mon Sep 17 00:00:00 2001 From: Kazuhiro-Mimaki Date: Wed, 26 Jun 2024 10:12:40 +0900 Subject: [PATCH 3/7] fix: shouldn't expose the keywords --- crates/biome_css_analyze/src/keywords.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/biome_css_analyze/src/keywords.rs b/crates/biome_css_analyze/src/keywords.rs index e023ec29ff71..7e8c93c2cab1 100644 --- a/crates/biome_css_analyze/src/keywords.rs +++ b/crates/biome_css_analyze/src/keywords.rs @@ -5435,7 +5435,7 @@ pub const RESET_TO_INITIAL_PROPERTIES_BY_FONT: [&str; 13] = [ // https://developer.mozilla.org/ja/docs/Web/HTML/Element // https://github.com/sindresorhus/html-tags/blob/main/html-tags.json -pub const HTML_TAGS: [&str; 148] = [ +pub(crate) const HTML_TAGS: [&str; 148] = [ "a", "abbr", "acronym", @@ -5588,7 +5588,7 @@ pub const HTML_TAGS: [&str; 148] = [ // https://developer.mozilla.org/ja/docs/Web/SVG/Element // https://github.com/element-io/svg-tags/blob/master/lib/svg-tags.json -pub const SVG_TAGS: [&str; 81] = [ +pub(crate) const SVG_TAGS: [&str; 81] = [ "a", "altGlyph", "altGlyphDef", @@ -5673,7 +5673,7 @@ pub const SVG_TAGS: [&str; 81] = [ ]; // https://developer.mozilla.org/ja/docs/Web/MathML/Element -pub const MATH_ML_TAGS: [&str; 32] = [ +pub(crate) const MATH_ML_TAGS: [&str; 32] = [ "annotation", "annotation-xml", "maction", From 85d8e2e200bd674e9e9f12ae730b2ed3910732a1 Mon Sep 17 00:00:00 2001 From: Kazuhiro-Mimaki Date: Wed, 26 Jun 2024 10:13:43 +0900 Subject: [PATCH 4/7] feat: add SVG_TAG --- crates/biome_css_analyze/src/keywords.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/biome_css_analyze/src/keywords.rs b/crates/biome_css_analyze/src/keywords.rs index 7e8c93c2cab1..1f09e55b349c 100644 --- a/crates/biome_css_analyze/src/keywords.rs +++ b/crates/biome_css_analyze/src/keywords.rs @@ -5588,7 +5588,7 @@ pub(crate) const HTML_TAGS: [&str; 148] = [ // https://developer.mozilla.org/ja/docs/Web/SVG/Element // https://github.com/element-io/svg-tags/blob/master/lib/svg-tags.json -pub(crate) const SVG_TAGS: [&str; 81] = [ +pub(crate) const SVG_TAGS: [&str; 82] = [ "a", "altGlyph", "altGlyphDef", @@ -5640,6 +5640,7 @@ pub(crate) const SVG_TAGS: [&str; 81] = [ "g", "glyph", "glyphRef", + "hatch", "hatchpath", "hkern", "image", From 6bdea8b4c9b56a88c8b8913aa7a3e88d808a35ef Mon Sep 17 00:00:00 2001 From: Kazuhiro-Mimaki Date: Thu, 4 Jul 2024 22:52:19 +0900 Subject: [PATCH 5/7] fix: add tags --- crates/biome_css_analyze/src/keywords.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/biome_css_analyze/src/keywords.rs b/crates/biome_css_analyze/src/keywords.rs index 1f09e55b349c..08c87bb74044 100644 --- a/crates/biome_css_analyze/src/keywords.rs +++ b/crates/biome_css_analyze/src/keywords.rs @@ -5435,7 +5435,7 @@ pub const RESET_TO_INITIAL_PROPERTIES_BY_FONT: [&str; 13] = [ // https://developer.mozilla.org/ja/docs/Web/HTML/Element // https://github.com/sindresorhus/html-tags/blob/main/html-tags.json -pub(crate) const HTML_TAGS: [&str; 148] = [ +pub(crate) const HTML_TAGS: [&str; 150] = [ "a", "abbr", "acronym", @@ -5471,6 +5471,7 @@ pub(crate) const HTML_TAGS: [&str; 148] = [ "del", "details", "dfn", + "dialog", "dir", "div", "dl", @@ -5553,6 +5554,7 @@ pub(crate) const HTML_TAGS: [&str; 148] = [ "section", "select", "selectlist", + "shadow", "slot", "small", "source", From 50a0cbe5fa958c6e7230b183a9b09678546ba7d8 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Thu, 4 Jul 2024 16:38:16 +0100 Subject: [PATCH 6/7] fix rebase --- .../src/lint/nursery/no_unknown_type_selector.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs index b2f0e4a2aaa1..cbc5b9ef7197 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs @@ -1,11 +1,11 @@ -use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic, RuleSource}; +use biome_analyze::{context::RuleContext, declare_lint_rule, Ast, Rule, RuleDiagnostic, RuleSource}; use biome_console::markup; use biome_css_syntax::CssTypeSelector; use biome_rowan::AstNode; use crate::utils::is_known_type_selector; -declare_rule! { +declare_lint_rule! { /// Disallow unknown type selectors. /// /// This rule considers tags defined in the HTML, SVG, and MathML specifications to be known. From 8df3826c23e2d3a70330e2096aebb0436ea5ceaa Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 17 Jul 2024 09:19:56 +0100 Subject: [PATCH 7/7] rebase and fix format --- .../biome_configuration/src/linter/rules.rs | 137 ++++++++++-------- .../lint/nursery/no_unknown_type_selector.rs | 4 +- 2 files changed, 82 insertions(+), 59 deletions(-) diff --git a/crates/biome_configuration/src/linter/rules.rs b/crates/biome_configuration/src/linter/rules.rs index a2859dc56572..e4be42943c1a 100644 --- a/crates/biome_configuration/src/linter/rules.rs +++ b/crates/biome_configuration/src/linter/rules.rs @@ -2903,6 +2903,9 @@ pub struct Nursery { #[serde(skip_serializing_if = "Option::is_none")] pub no_unknown_selector_pseudo_element: Option>, + #[doc = "Disallow unknown type selectors."] + #[serde(skip_serializing_if = "Option::is_none")] + pub no_unknown_type_selector: Option>, #[doc = "Disallow unknown CSS units."] #[serde(skip_serializing_if = "Option::is_none")] pub no_unknown_unit: Option>, @@ -3034,6 +3037,7 @@ impl Nursery { "noUnknownProperty", "noUnknownPseudoClassSelector", "noUnknownSelectorPseudoElement", + "noUnknownTypeSelector", "noUnknownUnit", "noUnmatchableAnbSelector", "noUnusedFunctionParameters", @@ -3080,6 +3084,7 @@ impl Nursery { "noUnknownProperty", "noUnknownPseudoClassSelector", "noUnknownSelectorPseudoElement", + "noUnknownTypeSelector", "noUnknownUnit", "noUnmatchableAnbSelector", "useDeprecatedReason", @@ -3108,11 +3113,12 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[41]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[44]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[42]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[45]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[49]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[51]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[46]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[50]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[52]), ]; const ALL_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = &[ RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[0]), @@ -3171,6 +3177,7 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[53]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[54]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[55]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[56]), ]; #[doc = r" Retrieves the recommended rules"] pub(crate) fn is_recommended_true(&self) -> bool { @@ -3332,141 +3339,146 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28])); } } - if let Some(rule) = self.no_unknown_unit.as_ref() { + if let Some(rule) = self.no_unknown_type_selector.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29])); } } - if let Some(rule) = self.no_unmatchable_anb_selector.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[30])); } } - if let Some(rule) = self.no_unused_function_parameters.as_ref() { + if let Some(rule) = self.no_unmatchable_anb_selector.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31])); } } - if let Some(rule) = self.no_useless_string_concat.as_ref() { + if let Some(rule) = self.no_unused_function_parameters.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32])); } } - if let Some(rule) = self.no_useless_undefined_initialization.as_ref() { + if let Some(rule) = self.no_useless_string_concat.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33])); } } - if let Some(rule) = self.no_yoda_expression.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[34])); } } - if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { + if let Some(rule) = self.no_yoda_expression.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35])); } } - if let Some(rule) = self.use_consistent_builtin_instantiation.as_ref() { + if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36])); } } - if let Some(rule) = self.use_consistent_curly_braces.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[37])); } } - if let Some(rule) = self.use_consistent_grid_areas.as_ref() { + if let Some(rule) = self.use_consistent_curly_braces.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38])); } } - if let Some(rule) = self.use_date_now.as_ref() { + if let Some(rule) = self.use_consistent_grid_areas.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39])); } } - if let Some(rule) = self.use_default_switch_clause.as_ref() { + if let Some(rule) = self.use_date_now.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[40])); } } - if let Some(rule) = self.use_deprecated_reason.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[41])); } } - if let Some(rule) = self.use_error_message.as_ref() { + if let Some(rule) = self.use_deprecated_reason.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[42])); } } - if let Some(rule) = self.use_explicit_length_check.as_ref() { + if let Some(rule) = self.use_error_message.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[43])); } } - if let Some(rule) = self.use_focusable_interactive.as_ref() { + if let Some(rule) = self.use_explicit_length_check.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[44])); } } - if let Some(rule) = self.use_generic_font_names.as_ref() { + if let Some(rule) = self.use_focusable_interactive.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[45])); } } - if let Some(rule) = self.use_import_extensions.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[46])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.use_import_extensions.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[47])); } } - if let Some(rule) = self.use_number_to_fixed_digits_argument.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[48])); } } - if let Some(rule) = self.use_semantic_elements.as_ref() { + if let Some(rule) = self.use_number_to_fixed_digits_argument.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[49])); } } - if let Some(rule) = self.use_sorted_classes.as_ref() { + if let Some(rule) = self.use_semantic_elements.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[50])); } } - if let Some(rule) = self.use_strict_mode.as_ref() { + 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[51])); } } - if let Some(rule) = self.use_throw_new_error.as_ref() { + if let Some(rule) = self.use_strict_mode.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[52])); } } - if let Some(rule) = self.use_throw_only_error.as_ref() { + if let Some(rule) = self.use_throw_new_error.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[53])); } } - if let Some(rule) = self.use_top_level_regex.as_ref() { + if let Some(rule) = self.use_throw_only_error.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[54])); } } - if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if let Some(rule) = self.use_top_level_regex.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[55])); } } + if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if rule.is_enabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[56])); + } + } index_set } pub(crate) fn get_disabled_rules(&self) -> FxHashSet> { @@ -3616,141 +3628,146 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28])); } } - if let Some(rule) = self.no_unknown_unit.as_ref() { + if let Some(rule) = self.no_unknown_type_selector.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29])); } } - if let Some(rule) = self.no_unmatchable_anb_selector.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[30])); } } - if let Some(rule) = self.no_unused_function_parameters.as_ref() { + if let Some(rule) = self.no_unmatchable_anb_selector.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31])); } } - if let Some(rule) = self.no_useless_string_concat.as_ref() { + if let Some(rule) = self.no_unused_function_parameters.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32])); } } - if let Some(rule) = self.no_useless_undefined_initialization.as_ref() { + if let Some(rule) = self.no_useless_string_concat.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33])); } } - if let Some(rule) = self.no_yoda_expression.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[34])); } } - if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { + if let Some(rule) = self.no_yoda_expression.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35])); } } - if let Some(rule) = self.use_consistent_builtin_instantiation.as_ref() { + if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36])); } } - if let Some(rule) = self.use_consistent_curly_braces.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[37])); } } - if let Some(rule) = self.use_consistent_grid_areas.as_ref() { + if let Some(rule) = self.use_consistent_curly_braces.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38])); } } - if let Some(rule) = self.use_date_now.as_ref() { + if let Some(rule) = self.use_consistent_grid_areas.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39])); } } - if let Some(rule) = self.use_default_switch_clause.as_ref() { + if let Some(rule) = self.use_date_now.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[40])); } } - if let Some(rule) = self.use_deprecated_reason.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[41])); } } - if let Some(rule) = self.use_error_message.as_ref() { + if let Some(rule) = self.use_deprecated_reason.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[42])); } } - if let Some(rule) = self.use_explicit_length_check.as_ref() { + if let Some(rule) = self.use_error_message.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[43])); } } - if let Some(rule) = self.use_focusable_interactive.as_ref() { + if let Some(rule) = self.use_explicit_length_check.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[44])); } } - if let Some(rule) = self.use_generic_font_names.as_ref() { + if let Some(rule) = self.use_focusable_interactive.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[45])); } } - if let Some(rule) = self.use_import_extensions.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[46])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.use_import_extensions.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[47])); } } - if let Some(rule) = self.use_number_to_fixed_digits_argument.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[48])); } } - if let Some(rule) = self.use_semantic_elements.as_ref() { + if let Some(rule) = self.use_number_to_fixed_digits_argument.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[49])); } } - if let Some(rule) = self.use_sorted_classes.as_ref() { + if let Some(rule) = self.use_semantic_elements.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[50])); } } - if let Some(rule) = self.use_strict_mode.as_ref() { + 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[51])); } } - if let Some(rule) = self.use_throw_new_error.as_ref() { + if let Some(rule) = self.use_strict_mode.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[52])); } } - if let Some(rule) = self.use_throw_only_error.as_ref() { + if let Some(rule) = self.use_throw_new_error.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[53])); } } - if let Some(rule) = self.use_top_level_regex.as_ref() { + if let Some(rule) = self.use_throw_only_error.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[54])); } } - if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if let Some(rule) = self.use_top_level_regex.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[55])); } } + if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if rule.is_disabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[56])); + } + } index_set } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] @@ -3903,6 +3920,10 @@ impl Nursery { .no_unknown_selector_pseudo_element .as_ref() .map(|conf| (conf.level(), conf.get_options())), + "noUnknownTypeSelector" => self + .no_unknown_type_selector + .as_ref() + .map(|conf| (conf.level(), conf.get_options())), "noUnknownUnit" => self .no_unknown_unit .as_ref() diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs index cbc5b9ef7197..16f521723d54 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_type_selector.rs @@ -1,4 +1,6 @@ -use biome_analyze::{context::RuleContext, declare_lint_rule, Ast, Rule, RuleDiagnostic, RuleSource}; +use biome_analyze::{ + context::RuleContext, declare_lint_rule, Ast, Rule, RuleDiagnostic, RuleSource, +}; use biome_console::markup; use biome_css_syntax::CssTypeSelector; use biome_rowan::AstNode;