diff --git a/crates/rome_aria/src/lib.rs b/crates/rome_aria/src/lib.rs index 71c1db2006aa..00007b9bc513 100644 --- a/crates/rome_aria/src/lib.rs +++ b/crates/rome_aria/src/lib.rs @@ -5,7 +5,6 @@ mod macros; pub mod properties; pub mod roles; -pub use iso::AriaIso; pub use properties::AriaProperties; pub(crate) use roles::AriaRoleDefinition; pub use roles::AriaRoles; diff --git a/crates/rome_js_analyze/src/aria_analyzers/nursery/use_valid_lang.rs b/crates/rome_js_analyze/src/aria_analyzers/nursery/use_valid_lang.rs index b8f7a6c207a0..5c2751a0a472 100644 --- a/crates/rome_js_analyze/src/aria_analyzers/nursery/use_valid_lang.rs +++ b/crates/rome_js_analyze/src/aria_analyzers/nursery/use_valid_lang.rs @@ -19,6 +19,10 @@ declare_rule! { /// /// ``` /// + /// ```jsx,expect_diagnostic + /// + /// ``` + /// /// ### Valid /// /// ```jsx @@ -58,35 +62,33 @@ impl Rule for UseValidLang { let mut split_value = attribute_text.text().split('-'); match (split_value.next(), split_value.next()) { (Some(language), Some(country)) => { - if !ctx.is_valid_language(language) { + if !ctx.is_valid_iso_language(language) { return Some(UseValidLangState { attribute_range: attribute_value.range(), error_kind: ErrorKind::InvalidLanguage, }); - } else if !ctx.is_valid_country(country) { + } else if !ctx.is_valid_iso_country(country) { return Some(UseValidLangState { attribute_range: attribute_value.range(), error_kind: ErrorKind::InvalidCountry, }); - } - } - - (Some(language), None) => { - if !ctx.is_valid_language(language) { + } else if split_value.next().is_some() { return Some(UseValidLangState { attribute_range: attribute_value.range(), - error_kind: ErrorKind::InvalidLanguage, + error_kind: ErrorKind::InvalidValue, }); } } - _ => { - if split_value.next().is_some() { + + (Some(language), None) => { + if !ctx.is_valid_iso_language(language) { return Some(UseValidLangState { attribute_range: attribute_value.range(), - error_kind: ErrorKind::InvalidValue, + error_kind: ErrorKind::InvalidLanguage, }); } } + _ => {} } } @@ -123,7 +125,7 @@ impl Rule for UseValidLang { diagnostic.footer_list("Some of valid countries:", countries) } ErrorKind::InvalidValue => diagnostic, - };y + }; Some(diagnostic) } } diff --git a/crates/rome_js_analyze/src/aria_services.rs b/crates/rome_js_analyze/src/aria_services.rs index 2a9f69ad38e3..942aa6b606bf 100644 --- a/crates/rome_js_analyze/src/aria_services.rs +++ b/crates/rome_js_analyze/src/aria_services.rs @@ -3,7 +3,7 @@ use rome_analyze::{ RuleKey, ServiceBag, }; use rome_aria::iso::{countries, is_valid_country, is_valid_language, languages}; -use rome_aria::{AriaIso, AriaProperties, AriaRoles}; +use rome_aria::{AriaProperties, AriaRoles}; use rome_js_syntax::JsLanguage; use rome_rowan::AstNode; use std::sync::Arc; @@ -51,13 +51,9 @@ impl FromServices for AriaServices { let properties: &Arc = services.get_service().ok_or_else(|| { MissingServicesDiagnostic::new(rule_key.rule_name(), &["AriaProperties"]) })?; - let iso: &Arc = services - .get_service() - .ok_or_else(|| MissingServicesDiagnostic::new(rule_key.rule_name(), &["AriaIso"]))?; Ok(Self { roles: roles.clone(), properties: properties.clone(), - iso: iso.clone(), }) } } diff --git a/crates/rome_js_analyze/src/lib.rs b/crates/rome_js_analyze/src/lib.rs index a79b82b2f88d..aa50e0f01d14 100644 --- a/crates/rome_js_analyze/src/lib.rs +++ b/crates/rome_js_analyze/src/lib.rs @@ -9,7 +9,7 @@ use rome_analyze::{ DeserializableRuleOptions, InspectMatcher, LanguageRoot, MatchQueryParams, MetadataRegistry, Phases, RuleAction, RuleRegistry, ServiceBag, SuppressionKind, SyntaxVisitor, }; -use rome_aria::{AriaIso, AriaProperties, AriaRoles}; +use rome_aria::{AriaProperties, AriaRoles}; use rome_diagnostics::{category, Diagnostic, FileId}; use rome_js_syntax::suppression::SuppressionDiagnostic; use rome_js_syntax::{suppression::parse_suppression_comment, JsLanguage}; @@ -174,7 +174,6 @@ where services.insert_service(Arc::new(AriaRoles::default())); services.insert_service(Arc::new(AriaProperties::default())); - services.insert_service(Arc::new(AriaIso::default())); analyzer.run(AnalyzerContext { file_id, root: root.clone(), diff --git a/crates/rome_js_analyze/tests/specs/nursery/useValidLang.jsx b/crates/rome_js_analyze/tests/specs/nursery/useValidLang.jsx index 604f72fad44d..40ae2babad2f 100644 --- a/crates/rome_js_analyze/tests/specs/nursery/useValidLang.jsx +++ b/crates/rome_js_analyze/tests/specs/nursery/useValidLang.jsx @@ -1,6 +1,7 @@ // invalid let a = ; let a = ; +let a = ; // valid let a = ; diff --git a/crates/rome_js_analyze/tests/specs/nursery/useValidLang.jsx.snap b/crates/rome_js_analyze/tests/specs/nursery/useValidLang.jsx.snap index 7e3cf1baf731..6265fbedaa43 100644 --- a/crates/rome_js_analyze/tests/specs/nursery/useValidLang.jsx.snap +++ b/crates/rome_js_analyze/tests/specs/nursery/useValidLang.jsx.snap @@ -7,6 +7,7 @@ expression: useValidLang.jsx // invalid let a = ; let a = ; +let a = ; // valid let a = ; @@ -26,7 +27,7 @@ useValidLang.jsx:2:20 lint/nursery/useValidLang ━━━━━━━━━━ > 2 │ let a = ; │ ^^^^^^^ 3 │ let a = ; - 4 │ + 4 │ let a = ; i Some of valid languages: @@ -58,8 +59,8 @@ useValidLang.jsx:3:20 lint/nursery/useValidLang ━━━━━━━━━━ 2 │ let a = ; > 3 │ let a = ; │ ^^^^^^^^^^ - 4 │ - 5 │ // valid + 4 │ let a = ; + 5 │ i Some of valid countries: @@ -82,4 +83,19 @@ useValidLang.jsx:3:20 lint/nursery/useValidLang ━━━━━━━━━━ ``` +``` +useValidLang.jsx:4:20 lint/nursery/useValidLang ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Provide a valid value for the lang attribute. + + 2 │ let a = ; + 3 │ let a = ; + > 4 │ let a = ; + │ ^^^^^^^^^^^^^^^^^ + 5 │ + 6 │ // valid + + +``` + diff --git a/crates/rome_service/src/configuration/linter/rules.rs b/crates/rome_service/src/configuration/linter/rules.rs index 6eb3b710466a..d614ffbb99f4 100644 --- a/crates/rome_service/src/configuration/linter/rules.rs +++ b/crates/rome_service/src/configuration/linter/rules.rs @@ -184,9 +184,7 @@ impl Rules { None } } - pub(crate) fn is_recommended(&self) -> bool { - !matches!(self.recommended, Some(false)) - } + pub(crate) fn is_recommended(&self) -> bool { !matches!(self.recommended, Some(false)) } #[doc = r" It returns a tuple of filters. The first element of the tuple are the enabled rules,"] #[doc = r" while the second element are the disabled rules."] #[doc = r""] @@ -421,9 +419,7 @@ impl A11y { RuleFilter::Rule("a11y", Self::CATEGORY_RULES[7]), RuleFilter::Rule("a11y", Self::CATEGORY_RULES[8]), ]; - pub(crate) fn is_recommended(&self) -> bool { - !matches!(self.recommended, Some(false)) - } + pub(crate) fn is_recommended(&self) -> bool { !matches!(self.recommended, Some(false)) } pub(crate) fn get_enabled_rules(&self) -> IndexSet { IndexSet::from_iter(self.rules.iter().filter_map(|(key, conf)| { if conf.is_enabled() { @@ -443,9 +439,7 @@ impl A11y { })) } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] - pub(crate) fn has_rule(rule_name: &str) -> bool { - Self::CATEGORY_RULES.contains(&rule_name) - } + pub(crate) fn has_rule(rule_name: &str) -> bool { Self::CATEGORY_RULES.contains(&rule_name) } #[doc = r" Checks if, given a rule name, it is marked as recommended"] pub(crate) fn is_recommended_rule(rule_name: &str) -> bool { Self::RECOMMENDED_RULES.contains(&rule_name) @@ -531,9 +525,7 @@ impl Complexity { RuleFilter::Rule("complexity", Self::CATEGORY_RULES[4]), RuleFilter::Rule("complexity", Self::CATEGORY_RULES[5]), ]; - pub(crate) fn is_recommended(&self) -> bool { - !matches!(self.recommended, Some(false)) - } + pub(crate) fn is_recommended(&self) -> bool { !matches!(self.recommended, Some(false)) } pub(crate) fn get_enabled_rules(&self) -> IndexSet { IndexSet::from_iter(self.rules.iter().filter_map(|(key, conf)| { if conf.is_enabled() { @@ -553,9 +545,7 @@ impl Complexity { })) } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] - pub(crate) fn has_rule(rule_name: &str) -> bool { - Self::CATEGORY_RULES.contains(&rule_name) - } + pub(crate) fn has_rule(rule_name: &str) -> bool { Self::CATEGORY_RULES.contains(&rule_name) } #[doc = r" Checks if, given a rule name, it is marked as recommended"] pub(crate) fn is_recommended_rule(rule_name: &str) -> bool { Self::RECOMMENDED_RULES.contains(&rule_name) @@ -664,9 +654,7 @@ impl Correctness { RuleFilter::Rule("correctness", Self::CATEGORY_RULES[9]), RuleFilter::Rule("correctness", Self::CATEGORY_RULES[10]), ]; - pub(crate) fn is_recommended(&self) -> bool { - !matches!(self.recommended, Some(false)) - } + pub(crate) fn is_recommended(&self) -> bool { !matches!(self.recommended, Some(false)) } pub(crate) fn get_enabled_rules(&self) -> IndexSet { IndexSet::from_iter(self.rules.iter().filter_map(|(key, conf)| { if conf.is_enabled() { @@ -686,9 +674,7 @@ impl Correctness { })) } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] - pub(crate) fn has_rule(rule_name: &str) -> bool { - Self::CATEGORY_RULES.contains(&rule_name) - } + pub(crate) fn has_rule(rule_name: &str) -> bool { Self::CATEGORY_RULES.contains(&rule_name) } #[doc = r" Checks if, given a rule name, it is marked as recommended"] pub(crate) fn is_recommended_rule(rule_name: &str) -> bool { Self::RECOMMENDED_RULES.contains(&rule_name) @@ -743,6 +729,8 @@ struct NurserySchema { no_assign_in_expressions: Option, #[doc = "Disallow certain types."] no_banned_types: Option, + #[doc = "Disallow comma operator."] + no_comma_operator: Option, #[doc = "Disallow TypeScript const enum"] no_const_enum: Option, #[doc = "Disallow returning a value from a constructor."] @@ -781,6 +769,8 @@ struct NurserySchema { no_var: Option, #[doc = "Disallow returning a value from a function with the return type 'void'"] no_void_type_return: Option, + #[doc = "Disallow with statements in non-strict contexts."] + no_with: Option, #[doc = "Enforce that ARIA state and property values are valid."] use_aria_prop_types: Option, #[doc = "Enforce that elements with ARIA roles must have all required ARIA attributes for that role."] @@ -808,10 +798,11 @@ struct NurserySchema { } impl Nursery { const CATEGORY_NAME: &'static str = "nursery"; - pub(crate) const CATEGORY_RULES: [&'static str; 34] = [ + pub(crate) const CATEGORY_RULES: [&'static str; 36] = [ "noAccessKey", "noAssignInExpressions", "noBannedTypes", + "noCommaOperator", "noConstEnum", "noConstructorReturn", "noDistractingElements", @@ -831,6 +822,7 @@ impl Nursery { "noUselessSwitchCase", "noVar", "noVoidTypeReturn", + "noWith", "useAriaPropTypes", "useAriaPropsForRole", "useCamelCase", @@ -844,9 +836,10 @@ impl Nursery { "useNumericLiterals", "useValidLang", ]; - const RECOMMENDED_RULES: [&'static str; 25] = [ + const RECOMMENDED_RULES: [&'static str; 27] = [ "noAssignInExpressions", "noBannedTypes", + "noCommaOperator", "noConstEnum", "noConstructorReturn", "noDistractingElements", @@ -862,6 +855,7 @@ impl Nursery { "noUselessSwitchCase", "noVar", "noVoidTypeReturn", + "noWith", "useAriaPropsForRole", "useConst", "useDefaultParameterLast", @@ -871,7 +865,7 @@ impl Nursery { "useNumericLiterals", "useValidLang", ]; - const RECOMMENDED_RULES_AS_FILTERS: [RuleFilter<'static>; 25] = [ + const RECOMMENDED_RULES_AS_FILTERS: [RuleFilter<'static>; 27] = [ RuleFilter::Rule("nursery", Self::CATEGORY_RULES[1]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[2]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[3]), @@ -882,25 +876,25 @@ impl Nursery { RuleFilter::Rule("nursery", Self::CATEGORY_RULES[8]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[9]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[10]), - RuleFilter::Rule("nursery", Self::CATEGORY_RULES[13]), - RuleFilter::Rule("nursery", Self::CATEGORY_RULES[16]), + RuleFilter::Rule("nursery", Self::CATEGORY_RULES[11]), + RuleFilter::Rule("nursery", Self::CATEGORY_RULES[14]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[17]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[18]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[19]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[20]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[21]), + RuleFilter::Rule("nursery", Self::CATEGORY_RULES[22]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[23]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[25]), - RuleFilter::Rule("nursery", Self::CATEGORY_RULES[26]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[27]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[28]), RuleFilter::Rule("nursery", Self::CATEGORY_RULES[29]), - RuleFilter::Rule("nursery", Self::CATEGORY_RULES[32]), - RuleFilter::Rule("nursery", Self::CATEGORY_RULES[33]), + RuleFilter::Rule("nursery", Self::CATEGORY_RULES[30]), + RuleFilter::Rule("nursery", Self::CATEGORY_RULES[31]), + RuleFilter::Rule("nursery", Self::CATEGORY_RULES[34]), + RuleFilter::Rule("nursery", Self::CATEGORY_RULES[35]), ]; - pub(crate) fn is_recommended(&self) -> bool { - !matches!(self.recommended, Some(false)) - } + pub(crate) fn is_recommended(&self) -> bool { !matches!(self.recommended, Some(false)) } pub(crate) fn get_enabled_rules(&self) -> IndexSet { IndexSet::from_iter(self.rules.iter().filter_map(|(key, conf)| { if conf.is_enabled() { @@ -920,14 +914,12 @@ impl Nursery { })) } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] - pub(crate) fn has_rule(rule_name: &str) -> bool { - Self::CATEGORY_RULES.contains(&rule_name) - } + pub(crate) fn has_rule(rule_name: &str) -> bool { Self::CATEGORY_RULES.contains(&rule_name) } #[doc = r" Checks if, given a rule name, it is marked as recommended"] pub(crate) fn is_recommended_rule(rule_name: &str) -> bool { Self::RECOMMENDED_RULES.contains(&rule_name) } - pub(crate) fn recommended_rules_as_filters() -> [RuleFilter<'static>; 25] { + pub(crate) fn recommended_rules_as_filters() -> [RuleFilter<'static>; 27] { Self::RECOMMENDED_RULES_AS_FILTERS } } @@ -980,9 +972,7 @@ impl Performance { const RECOMMENDED_RULES: [&'static str; 1] = ["noDelete"]; const RECOMMENDED_RULES_AS_FILTERS: [RuleFilter<'static>; 1] = [RuleFilter::Rule("performance", Self::CATEGORY_RULES[0])]; - pub(crate) fn is_recommended(&self) -> bool { - !matches!(self.recommended, Some(false)) - } + pub(crate) fn is_recommended(&self) -> bool { !matches!(self.recommended, Some(false)) } pub(crate) fn get_enabled_rules(&self) -> IndexSet { IndexSet::from_iter(self.rules.iter().filter_map(|(key, conf)| { if conf.is_enabled() { @@ -1002,9 +992,7 @@ impl Performance { })) } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] - pub(crate) fn has_rule(rule_name: &str) -> bool { - Self::CATEGORY_RULES.contains(&rule_name) - } + pub(crate) fn has_rule(rule_name: &str) -> bool { Self::CATEGORY_RULES.contains(&rule_name) } #[doc = r" Checks if, given a rule name, it is marked as recommended"] pub(crate) fn is_recommended_rule(rule_name: &str) -> bool { Self::RECOMMENDED_RULES.contains(&rule_name) @@ -1072,9 +1060,7 @@ impl Security { RuleFilter::Rule("security", Self::CATEGORY_RULES[0]), RuleFilter::Rule("security", Self::CATEGORY_RULES[1]), ]; - pub(crate) fn is_recommended(&self) -> bool { - !matches!(self.recommended, Some(false)) - } + pub(crate) fn is_recommended(&self) -> bool { !matches!(self.recommended, Some(false)) } pub(crate) fn get_enabled_rules(&self) -> IndexSet { IndexSet::from_iter(self.rules.iter().filter_map(|(key, conf)| { if conf.is_enabled() { @@ -1094,9 +1080,7 @@ impl Security { })) } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] - pub(crate) fn has_rule(rule_name: &str) -> bool { - Self::CATEGORY_RULES.contains(&rule_name) - } + pub(crate) fn has_rule(rule_name: &str) -> bool { Self::CATEGORY_RULES.contains(&rule_name) } #[doc = r" Checks if, given a rule name, it is marked as recommended"] pub(crate) fn is_recommended_rule(rule_name: &str) -> bool { Self::RECOMMENDED_RULES.contains(&rule_name) @@ -1205,9 +1189,7 @@ impl Style { RuleFilter::Rule("style", Self::CATEGORY_RULES[11]), RuleFilter::Rule("style", Self::CATEGORY_RULES[12]), ]; - pub(crate) fn is_recommended(&self) -> bool { - !matches!(self.recommended, Some(false)) - } + pub(crate) fn is_recommended(&self) -> bool { !matches!(self.recommended, Some(false)) } pub(crate) fn get_enabled_rules(&self) -> IndexSet { IndexSet::from_iter(self.rules.iter().filter_map(|(key, conf)| { if conf.is_enabled() { @@ -1227,9 +1209,7 @@ impl Style { })) } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] - pub(crate) fn has_rule(rule_name: &str) -> bool { - Self::CATEGORY_RULES.contains(&rule_name) - } + pub(crate) fn has_rule(rule_name: &str) -> bool { Self::CATEGORY_RULES.contains(&rule_name) } #[doc = r" Checks if, given a rule name, it is marked as recommended"] pub(crate) fn is_recommended_rule(rule_name: &str) -> bool { Self::RECOMMENDED_RULES.contains(&rule_name) @@ -1367,9 +1347,7 @@ impl Suspicious { RuleFilter::Rule("suspicious", Self::CATEGORY_RULES[14]), RuleFilter::Rule("suspicious", Self::CATEGORY_RULES[15]), ]; - pub(crate) fn is_recommended(&self) -> bool { - !matches!(self.recommended, Some(false)) - } + pub(crate) fn is_recommended(&self) -> bool { !matches!(self.recommended, Some(false)) } pub(crate) fn get_enabled_rules(&self) -> IndexSet { IndexSet::from_iter(self.rules.iter().filter_map(|(key, conf)| { if conf.is_enabled() { @@ -1389,9 +1367,7 @@ impl Suspicious { })) } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] - pub(crate) fn has_rule(rule_name: &str) -> bool { - Self::CATEGORY_RULES.contains(&rule_name) - } + pub(crate) fn has_rule(rule_name: &str) -> bool { Self::CATEGORY_RULES.contains(&rule_name) } #[doc = r" Checks if, given a rule name, it is marked as recommended"] pub(crate) fn is_recommended_rule(rule_name: &str) -> bool { Self::RECOMMENDED_RULES.contains(&rule_name) diff --git a/website/src/pages/lint/rules/useValidLang.md b/website/src/pages/lint/rules/useValidLang.md index a119ae9eca26..f729cd1e3673 100644 --- a/website/src/pages/lint/rules/useValidLang.md +++ b/website/src/pages/lint/rules/useValidLang.md @@ -75,6 +75,20 @@ Ensure that the attribute passed to the `lang` attribute is a correct ISO langua +```jsx + +``` + +
nursery/useValidLang.js:1:12 lint/nursery/useValidLang ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+   Provide a valid value for the lang attribute.
+  
+  > 1 │ <html lang="en-GB-typo" />
+              ^^^^^^^^^^^^
+    2 │ 
+  
+
+ ### Valid ```jsx