diff --git a/Cargo.lock b/Cargo.lock index 66aa52862cfaa..0eeb1d15e62bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1691,6 +1691,7 @@ dependencies = [ "oxc_ast", "oxc_diagnostics", "oxc_formatter", + "oxc_index", "oxc_macros", "oxc_parser", "oxc_resolver", diff --git a/crates/oxc_linter/Cargo.toml b/crates/oxc_linter/Cargo.toml index f2f2ebc3fa17a..475e34d25e193 100644 --- a/crates/oxc_linter/Cargo.toml +++ b/crates/oxc_linter/Cargo.toml @@ -28,6 +28,7 @@ oxc_macros = { workspace = true } oxc_semantic = { workspace = true } oxc_syntax = { workspace = true } oxc_formatter = { workspace = true } +oxc_index = { workspace = true } oxc_resolver = { version = "1.0.1" } rayon = { workspace = true } diff --git a/crates/oxc_linter/src/lib.rs b/crates/oxc_linter/src/lib.rs index afe0a7d3cc041..0295442d06482 100644 --- a/crates/oxc_linter/src/lib.rs +++ b/crates/oxc_linter/src/lib.rs @@ -33,6 +33,17 @@ pub use crate::{ }; pub(crate) use rules::{RuleEnum, RULES}; +#[cfg(target_pointer_width = "64")] +#[test] +fn size_asserts() { + use oxc_index::assert_eq_size; + + // `RuleEnum` runs in a really tight loop, make sure it is small for CPU cache. + // A reduction from 168 bytes to 16 results 15% performance improvement. + // See codspeed in https://github.com/oxc-project/oxc/pull/1783 + assert_eq_size!(RuleEnum, [u8; 16]); +} + #[derive(Debug, Clone)] pub struct LintSettings { jsx_a11y: JsxA11y, diff --git a/crates/oxc_linter/src/rules/eslint/no_bitwise.rs b/crates/oxc_linter/src/rules/eslint/no_bitwise.rs index 619e8116a14bb..cf99941386938 100644 --- a/crates/oxc_linter/src/rules/eslint/no_bitwise.rs +++ b/crates/oxc_linter/src/rules/eslint/no_bitwise.rs @@ -18,11 +18,22 @@ use crate::{context::LintContext, rule::Rule, AstNode}; struct NoBitwiseDiagnostic(&'static str, #[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct NoBitwise { +pub struct NoBitwise(Box); + +#[derive(Debug, Default, Clone)] +pub struct NoBitwiseConfig { allow: Vec, int32_hint: bool, } +impl std::ops::Deref for NoBitwise { + type Target = NoBitwiseConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + declare_oxc_lint!( /// ### What it does /// @@ -46,7 +57,7 @@ impl Rule for NoBitwise { fn from_configuration(value: serde_json::Value) -> Self { let obj = value.get(0); - Self { + Self(Box::new(NoBitwiseConfig { allow: obj .and_then(|v| v.get("allow")) .and_then(serde_json::Value::as_array) @@ -61,7 +72,7 @@ impl Rule for NoBitwise { .and_then(|v| v.get("int32Hint")) .and_then(serde_json::Value::as_bool) .unwrap_or_default(), - } + })) } fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { diff --git a/crates/oxc_linter/src/rules/eslint/no_console.rs b/crates/oxc_linter/src/rules/eslint/no_console.rs index 25053fed5a16e..1526f7d64f55f 100644 --- a/crates/oxc_linter/src/rules/eslint/no_console.rs +++ b/crates/oxc_linter/src/rules/eslint/no_console.rs @@ -14,7 +14,10 @@ use crate::{context::LintContext, rule::Rule, AstNode}; struct NoConsoleDiagnostic(#[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct NoConsole { +pub struct NoConsole(Box); + +#[derive(Debug, Default, Clone)] +pub struct NoConsoleConfig { /// A list of methods allowed to be used. /// /// ```javascript @@ -25,6 +28,14 @@ pub struct NoConsole { pub allow: Vec, } +impl std::ops::Deref for NoConsole { + type Target = NoConsoleConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + declare_oxc_lint!( /// ### What it does /// Disallows using the global console object. @@ -45,7 +56,7 @@ declare_oxc_lint!( impl Rule for NoConsole { fn from_configuration(value: serde_json::Value) -> Self { - Self { + Self(Box::new(NoConsoleConfig { allow: value .get(0) .and_then(|v| v.get("allow")) @@ -57,7 +68,7 @@ impl Rule for NoConsole { .collect() }) .unwrap_or_default(), - } + })) } fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { diff --git a/crates/oxc_linter/src/rules/eslint/no_global_assign.rs b/crates/oxc_linter/src/rules/eslint/no_global_assign.rs index 66e291315bc25..629928e814618 100644 --- a/crates/oxc_linter/src/rules/eslint/no_global_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_global_assign.rs @@ -16,10 +16,21 @@ struct NoGlobalAssignDiagnostic( ); #[derive(Debug, Default, Clone)] -pub struct NoGlobalAssign { +pub struct NoGlobalAssign(Box); + +#[derive(Debug, Default, Clone)] +pub struct NoGlobalAssignConfig { excludes: Vec, } +impl std::ops::Deref for NoGlobalAssign { + type Target = NoGlobalAssignConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + declare_oxc_lint!( /// ### What it does /// Disallow modifications to read-only global variables. @@ -39,7 +50,7 @@ impl Rule for NoGlobalAssign { fn from_configuration(value: serde_json::Value) -> Self { let obj = value.get(0); - Self { + Self(Box::new(NoGlobalAssignConfig { excludes: obj .and_then(|v| v.get("exceptions")) .and_then(serde_json::Value::as_array) @@ -49,7 +60,7 @@ impl Rule for NoGlobalAssign { .filter(std::option::Option::is_some) .map(|x| Atom::from(x.unwrap().to_string())) .collect::>(), - } + })) } fn run_once(&self, ctx: &LintContext) { diff --git a/crates/oxc_linter/src/rules/eslint/no_mixed_operators.rs b/crates/oxc_linter/src/rules/eslint/no_mixed_operators.rs index 64e73a8dbdeee..cc0fc9c6665fb 100644 --- a/crates/oxc_linter/src/rules/eslint/no_mixed_operators.rs +++ b/crates/oxc_linter/src/rules/eslint/no_mixed_operators.rs @@ -22,15 +22,26 @@ struct NoMixedOperatorsDiagnostic( #[label] pub Span, /*Span of the parent operator */ ); -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct NoMixedOperators { +#[derive(Debug, Default, Clone, Eq, PartialEq)] +pub struct NoMixedOperators(Box); + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct NoMixedOperatorsConfig { /// Disallow Mixed operators within one group. groups: Vec>, /// Allow operators of the same precedence to be mixed. allow_same_precedence: bool, } -impl Default for NoMixedOperators { +impl std::ops::Deref for NoMixedOperators { + type Target = NoMixedOperatorsConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Default for NoMixedOperatorsConfig { fn default() -> Self { Self { groups: default_groups(), allow_same_precedence: true } } @@ -116,7 +127,7 @@ impl NoMixedOperators { let allow_same_precedence = config.get("allowSamePrecedence").map_or(true, |val| val.as_bool().unwrap_or_default()); - Some(Self { groups, allow_same_precedence }) + Some(Self(Box::new(NoMixedOperatorsConfig { groups, allow_same_precedence }))) } fn is_mixed_with_parent(node: AstKind, parent: AstKind) -> bool { @@ -356,7 +367,10 @@ mod internal_tests { ]); let rule = NoMixedOperators::try_from_configuration(&config); // missing groups should fall back to default - let expected = NoMixedOperators { groups: default_groups(), allow_same_precedence: false }; + let expected = NoMixedOperators(Box::new(NoMixedOperatorsConfig { + groups: default_groups(), + allow_same_precedence: false, + })); assert_eq!(Some(expected), rule); } } diff --git a/crates/oxc_linter/src/rules/jest/expect_expect.rs b/crates/oxc_linter/src/rules/jest/expect_expect.rs index f05405852527f..da8cc2ea73c5f 100644 --- a/crates/oxc_linter/src/rules/jest/expect_expect.rs +++ b/crates/oxc_linter/src/rules/jest/expect_expect.rs @@ -25,13 +25,24 @@ use crate::{ #[diagnostic(severity(warning), help("Add assertion(s) in this Test"))] struct ExpectExpectDiagnostic(#[label] pub Span); +#[derive(Debug, Default, Clone)] +pub struct ExpectExpect(Box); + #[derive(Debug, Clone)] -pub struct ExpectExpect { +pub struct ExpectExpectConfig { assert_function_names: Vec, additional_test_block_functions: Vec, } -impl Default for ExpectExpect { +impl std::ops::Deref for ExpectExpect { + type Target = ExpectExpectConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Default for ExpectExpectConfig { fn default() -> Self { Self { assert_function_names: vec![String::from("expect")], @@ -81,7 +92,10 @@ impl Rule for ExpectExpect { }) .unwrap_or_default(); - Self { assert_function_names, additional_test_block_functions } + Self(Box::new(ExpectExpectConfig { + assert_function_names, + additional_test_block_functions, + })) } fn run_once(&self, ctx: &LintContext) { for possible_jest_node in &collect_possible_jest_call_node(ctx) { diff --git a/crates/oxc_linter/src/rules/jest/no_deprecated_functions.rs b/crates/oxc_linter/src/rules/jest/no_deprecated_functions.rs index 0a803b5c98bd2..2cadbd68a5199 100644 --- a/crates/oxc_linter/src/rules/jest/no_deprecated_functions.rs +++ b/crates/oxc_linter/src/rules/jest/no_deprecated_functions.rs @@ -17,12 +17,23 @@ pub struct DeprecatedFunction(pub String, pub String, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct JestConfig { - pub version: String, + version: String, } #[derive(Debug, Default, Clone)] -pub struct NoDeprecatedFunctions { - pub jest: JestConfig, +pub struct NoDeprecatedFunctions(Box); + +#[derive(Debug, Default, Clone)] +pub struct NoDeprecatedFunctionsConfig { + jest: JestConfig, +} + +impl std::ops::Deref for NoDeprecatedFunctions { + type Target = NoDeprecatedFunctionsConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } } declare_oxc_lint!( @@ -91,7 +102,9 @@ impl Rule for NoDeprecatedFunctions { let major: Vec<&str> = version.split('.').collect(); - Self { jest: JestConfig { version: major[0].to_string() } } + Self(Box::new(NoDeprecatedFunctionsConfig { + jest: JestConfig { version: major[0].to_string() }, + })) } fn run<'a>(&self, node: &oxc_semantic::AstNode<'a>, ctx: &LintContext<'a>) { diff --git a/crates/oxc_linter/src/rules/jest/no_hooks.rs b/crates/oxc_linter/src/rules/jest/no_hooks.rs index dcea3c3dc9c7a..0e3fa9705e9a7 100644 --- a/crates/oxc_linter/src/rules/jest/no_hooks.rs +++ b/crates/oxc_linter/src/rules/jest/no_hooks.rs @@ -21,8 +21,19 @@ use crate::{ pub struct UnexpectedHookDiagonsitc(#[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct NoHooks { - pub allow: Vec, +pub struct NoHooks(Box); + +#[derive(Debug, Default, Clone)] +pub struct NoHooksConfig { + allow: Vec, +} + +impl std::ops::Deref for NoHooks { + type Target = NoHooksConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } } declare_oxc_lint!( @@ -84,7 +95,7 @@ impl Rule for NoHooks { }) .unwrap_or_default(); - Self { allow } + Self(Box::new(NoHooksConfig { allow })) } fn run_once(&self, ctx: &LintContext) { diff --git a/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs b/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs index 2738b20c41947..6d9c8d389e40e 100644 --- a/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs +++ b/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs @@ -27,10 +27,21 @@ struct NoStandaloneExpectDiagnostic(#[label] pub Span); /// #[derive(Debug, Default, Clone)] -pub struct NoStandaloneExpect { +pub struct NoStandaloneExpect(Box); + +#[derive(Debug, Default, Clone)] +pub struct NoStandaloneExpectConfig { additional_test_block_functions: Vec, } +impl std::ops::Deref for NoStandaloneExpect { + type Target = NoStandaloneExpectConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + declare_oxc_lint!( /// ### What it does /// @@ -62,7 +73,7 @@ impl Rule for NoStandaloneExpect { }) .unwrap_or_default(); - Self { additional_test_block_functions } + Self(Box::new(NoStandaloneExpectConfig { additional_test_block_functions })) } fn run_once(&self, ctx: &LintContext<'_>) { let possible_jest_nodes = collect_possible_jest_call_node(ctx); diff --git a/crates/oxc_linter/src/rules/jest/valid_expect.rs b/crates/oxc_linter/src/rules/jest/valid_expect.rs index 552df3fecb61f..73f0941949447 100644 --- a/crates/oxc_linter/src/rules/jest/valid_expect.rs +++ b/crates/oxc_linter/src/rules/jest/valid_expect.rs @@ -23,15 +23,26 @@ use crate::{ #[diagnostic(severity(warning), help("{1:?}"))] struct ValidExpectDiagnostic(pub Atom, pub &'static str, #[label] pub Span); +#[derive(Debug, Default, Clone)] +pub struct ValidExpect(Box); + #[derive(Debug, Clone)] -pub struct ValidExpect { +pub struct ValidExpectConfig { async_matchers: Vec, min_args: usize, max_args: usize, always_await: bool, } -impl Default for ValidExpect { +impl std::ops::Deref for ValidExpect { + type Target = ValidExpectConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Default for ValidExpectConfig { fn default() -> Self { Self { async_matchers: vec![String::from("toResolve"), String::from("toReject")], @@ -88,7 +99,7 @@ impl Rule for ValidExpect { .and_then(serde_json::Value::as_bool) .unwrap_or(false); - Self { async_matchers, min_args, max_args, always_await } + Self(Box::new(ValidExpectConfig { async_matchers, min_args, max_args, always_await })) } fn run_once(&self, ctx: &LintContext) { for possible_jest_node in &collect_possible_jest_call_node(ctx) { diff --git a/crates/oxc_linter/src/rules/jest/valid_title.rs b/crates/oxc_linter/src/rules/jest/valid_title.rs index 5d15434a66b97..37b70fa41e963 100644 --- a/crates/oxc_linter/src/rules/jest/valid_title.rs +++ b/crates/oxc_linter/src/rules/jest/valid_title.rs @@ -27,7 +27,10 @@ use crate::{ struct ValidTitleDiagnostic(Atom, &'static str, #[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct ValidTitle { +pub struct ValidTitle(Box); + +#[derive(Debug, Default, Clone)] +pub struct ValidTitleConfig { ignore_type_of_describe_name: bool, disallowed_words: Vec, ignore_space: bool, @@ -35,6 +38,14 @@ pub struct ValidTitle { must_match_patterns: HashMap, } +impl std::ops::Deref for ValidTitle { + type Target = ValidTitleConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + declare_oxc_lint!( /// ### What it does /// @@ -88,13 +99,13 @@ impl Rule for ValidTitle { .and_then(|v| v.get("mustMatch")) .and_then(compile_matcher_patterns) .unwrap_or_default(); - Self { + Self(Box::new(ValidTitleConfig { ignore_type_of_describe_name, disallowed_words, ignore_space, must_not_match_patterns, must_match_patterns, - } + })) } fn run_once(&self, ctx: &LintContext) { diff --git a/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs b/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs index 2fc345fa0e76e..83d2031f2febe 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs @@ -60,14 +60,36 @@ enum AltTextDiagnostic { InputTypeImage(#[label] Span), } -#[derive(Debug, Clone)] -pub struct AltText { +#[derive(Debug, Default, Clone)] +pub struct AltText(Box); + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct AltTextConfig { img: Option>, object: Option>, area: Option>, input_type_image: Option>, } +impl std::ops::Deref for AltText { + type Target = AltTextConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::default::Default for AltTextConfig { + fn default() -> Self { + Self { + img: Some(vec![]), + object: Some(vec![]), + area: Some(vec![]), + input_type_image: Some(vec![]), + } + } +} + declare_oxc_lint!( /// ### What it does /// @@ -102,23 +124,13 @@ declare_oxc_lint!( correctness ); -impl std::default::Default for AltText { - fn default() -> Self { - Self { - img: Some(vec![]), - object: Some(vec![]), - area: Some(vec![]), - input_type_image: Some(vec![]), - } - } -} - impl Rule for AltText { fn from_configuration(value: serde_json::Value) -> Self { - let mut alt_text = Self::default(); + let mut alt_text = AltTextConfig::default(); if let Some(config) = value.get(0) { if let Some(elements) = config.get("elements").and_then(|v| v.as_array()) { - alt_text = Self { img: None, object: None, area: None, input_type_image: None }; + alt_text = + AltTextConfig { img: None, object: None, area: None, input_type_image: None }; for el in elements { match el.as_str() { Some("img") => alt_text.img = Some(vec![]), @@ -146,8 +158,9 @@ impl Rule for AltText { } } - alt_text + Self(Box::new(alt_text)) } + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { let AstKind::JSXOpeningElement(jsx_el) = node.kind() else { return }; let JSXElementName::Identifier(iden) = &jsx_el.name else { return }; diff --git a/crates/oxc_linter/src/rules/jsx_a11y/heading_has_content.rs b/crates/oxc_linter/src/rules/jsx_a11y/heading_has_content.rs index 5bb312b2fb94e..e589bdf470a21 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/heading_has_content.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/heading_has_content.rs @@ -22,10 +22,21 @@ use crate::{ struct HeadingHasContentDiagnostic(#[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct HeadingHasContent { +pub struct HeadingHasContent(Box); + +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct HeadingHasContentConfig { components: Option>, } +impl std::ops::Deref for HeadingHasContent { + type Target = HeadingHasContentConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + declare_oxc_lint!( /// ### What it does /// @@ -57,7 +68,7 @@ const DEFAULT_COMPONENTS: [&str; 6] = ["h1", "h2", "h3", "h4", "h5", "h6"]; impl Rule for HeadingHasContent { fn from_configuration(value: serde_json::Value) -> Self { - Self { + Self(Box::new(HeadingHasContentConfig { components: value .get(0) .and_then(|v| v.get("components")) @@ -68,7 +79,7 @@ impl Rule for HeadingHasContent { .map(ToString::to_string) .collect() }), - } + })) } fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { diff --git a/crates/oxc_linter/src/rules/jsx_a11y/img_redundant_alt.rs b/crates/oxc_linter/src/rules/jsx_a11y/img_redundant_alt.rs index 939b0af169c23..380676483010c 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/img_redundant_alt.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/img_redundant_alt.rs @@ -22,6 +22,35 @@ use crate::{context::LintContext, rule::Rule, AstNode}; #[diagnostic(severity(warning), help("Provide no redundant alt text for image. Screen-readers already announce `img` tags as an image. You don’t need to use the words `image`, `photo,` or `picture` (or any specified custom words) in the alt prop."))] struct ImgRedundantAltDiagnostic(#[label] pub Span); +#[derive(Debug, Default, Clone)] +pub struct ImgRedundantAlt(Box); + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ImgRedundantAltConfig { + types_to_validate: Vec, + redundant_words: Vec, +} + +impl std::ops::Deref for ImgRedundantAlt { + type Target = ImgRedundantAltConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Default for ImgRedundantAltConfig { + fn default() -> Self { + Self { + types_to_validate: COMPONENTS_FIXED_TO_VALIDATE + .iter() + .map(|&s| s.to_string()) + .collect(), + redundant_words: REDUNDANT_WORDS.iter().map(|&s| s.to_string()).collect(), + } + } +} + declare_oxc_lint!( /// ### What it does /// @@ -54,31 +83,12 @@ declare_oxc_lint!( ImgRedundantAlt, correctness ); - -#[derive(Debug, Clone)] -pub struct ImgRedundantAlt { - types_to_validate: Vec, - redundant_words: Vec, -} - -impl std::default::Default for ImgRedundantAlt { - fn default() -> Self { - Self { - types_to_validate: COMPONENTS_FIXED_TO_VALIDATE - .iter() - .map(|&s| s.to_string()) - .collect(), - redundant_words: REDUNDANT_WORDS.iter().map(|&s| s.to_string()).collect(), - } - } -} - const COMPONENTS_FIXED_TO_VALIDATE: [&str; 1] = ["img"]; const REDUNDANT_WORDS: [&str; 3] = ["image", "photo", "picture"]; impl Rule for ImgRedundantAlt { fn from_configuration(value: serde_json::Value) -> Self { - let mut img_redundant_alt = Self::default(); + let mut img_redundant_alt = ImgRedundantAltConfig::default(); if let Some(config) = value.get(0) { if let Some(components) = config.get("components").and_then(|v| v.as_array()) { img_redundant_alt @@ -93,7 +103,7 @@ impl Rule for ImgRedundantAlt { } } - img_redundant_alt + Self(Box::new(img_redundant_alt)) } fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { let AstKind::JSXOpeningElement(jsx_el) = node.kind() else { return }; diff --git a/crates/oxc_linter/src/rules/typescript/ban_ts_comment.rs b/crates/oxc_linter/src/rules/typescript/ban_ts_comment.rs index 6d3f6c03c41a2..b16a4fa886d15 100644 --- a/crates/oxc_linter/src/rules/typescript/ban_ts_comment.rs +++ b/crates/oxc_linter/src/rules/typescript/ban_ts_comment.rs @@ -23,8 +23,11 @@ pub enum BanTsCommentDiagnostic { CommentDescriptionNotMatchPattern(String, String, #[label] Span), } +#[derive(Debug, Default, Clone)] +pub struct BanTsComment(Box); + #[derive(Debug, Clone)] -pub struct BanTsComment { +pub struct BanTsCommentConfig { ts_expect_error: DirectiveConfig, ts_ignore: DirectiveConfig, ts_nocheck: DirectiveConfig, @@ -32,7 +35,15 @@ pub struct BanTsComment { minimum_description_length: u64, } -impl std::default::Default for BanTsComment { +impl std::ops::Deref for BanTsComment { + type Target = BanTsCommentConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Default for BanTsCommentConfig { fn default() -> Self { Self { ts_expect_error: DirectiveConfig::RequireDescription, @@ -95,7 +106,7 @@ declare_oxc_lint!( impl Rule for BanTsComment { fn from_configuration(value: serde_json::Value) -> Self { - Self { + Self(Box::new(BanTsCommentConfig { ts_expect_error: value .get(0) .and_then(|x| x.get("ts-expect-error")) @@ -121,7 +132,7 @@ impl Rule for BanTsComment { .and_then(|x| x.get("minimumDescriptionLength")) .and_then(serde_json::Value::as_u64) .unwrap_or(3), - } + })) } fn run_once(&self, ctx: &LintContext) { diff --git a/crates/oxc_linter/src/rules/typescript/no_this_alias.rs b/crates/oxc_linter/src/rules/typescript/no_this_alias.rs index c4f86640a8d2a..ae2296548108f 100644 --- a/crates/oxc_linter/src/rules/typescript/no_this_alias.rs +++ b/crates/oxc_linter/src/rules/typescript/no_this_alias.rs @@ -31,13 +31,24 @@ struct NoThisAliasDiagnostic(#[label] pub Span); )] struct NoThisDestructureDiagnostic(#[label] pub Span); +#[derive(Debug, Default, Clone)] +pub struct NoThisAlias(Box); + #[derive(Debug, Clone)] -pub struct NoThisAlias { +pub struct NoThisAliasConfig { allow_destructuring: bool, allow_names: Vec, } -impl Default for NoThisAlias { +impl std::ops::Deref for NoThisAlias { + type Target = NoThisAliasConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Default for NoThisAliasConfig { fn default() -> Self { Self { allow_destructuring: true, allow_names: vec![] } } @@ -75,13 +86,13 @@ impl Rule for NoThisAlias { .map(|x| Atom::from(x.unwrap().to_string())) .collect::>(); - Self { + Self(Box::new(NoThisAliasConfig { allow_destructuring: obj .and_then(|v| v.get("allow_destructuring")) .and_then(serde_json::Value::as_bool) .unwrap_or_default(), allow_names: allowed_names, - } + })) } fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { diff --git a/crates/oxc_linter/src/rules/unicorn/catch_error_name.rs b/crates/oxc_linter/src/rules/unicorn/catch_error_name.rs index a188d211ee670..b541a3417b514 100644 --- a/crates/oxc_linter/src/rules/unicorn/catch_error_name.rs +++ b/crates/oxc_linter/src/rules/unicorn/catch_error_name.rs @@ -17,13 +17,24 @@ use crate::{context::LintContext, rule::Rule, AstNode}; #[diagnostic(severity(warning))] struct CatchErrorNameDiagnostic(Atom, Atom, #[label] pub Span); +#[derive(Debug, Default, Clone)] +pub struct CatchErrorName(Box); + #[derive(Debug, Clone)] -pub struct CatchErrorName { +pub struct CatchErrorNameConfig { ignore: Vec, name: Atom, } -impl Default for CatchErrorName { +impl std::ops::Deref for CatchErrorName { + type Target = CatchErrorNameConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Default for CatchErrorNameConfig { fn default() -> Self { Self { ignore: vec![], name: Atom::new_inline("error") } } @@ -69,7 +80,7 @@ impl Rule for CatchErrorName { .unwrap_or("error"), ); - Self { ignore: ignored_names, name: allowed_name } + Self(Box::new(CatchErrorNameConfig { ignore: ignored_names, name: allowed_name })) } fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { diff --git a/crates/oxc_linter/src/rules/unicorn/numeric_separators_style.rs b/crates/oxc_linter/src/rules/unicorn/numeric_separators_style.rs index 4dd3d33331bb2..7782c3659f2ae 100644 --- a/crates/oxc_linter/src/rules/unicorn/numeric_separators_style.rs +++ b/crates/oxc_linter/src/rules/unicorn/numeric_separators_style.rs @@ -21,15 +21,27 @@ use crate::{context::LintContext, fixer::Fix, rule::Rule, AstNode}; )] struct NumericSeparatorsStyleDiagnostic(#[label] pub Span); +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct NumericSeparatorsStyle(Box); + #[derive(Debug, Clone, PartialEq, Eq)] -pub struct NumericSeparatorsStyle { +pub struct NumericSeparatorsStyleConfig { only_if_contains_separator: bool, hexadecimal: NumericBaseConfig, binary: NumericBaseConfig, octal: NumericBaseConfig, number: NumericBaseConfig, } -impl Default for NumericSeparatorsStyle { + +impl std::ops::Deref for NumericSeparatorsStyle { + type Target = NumericSeparatorsStyleConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Default for NumericSeparatorsStyleConfig { fn default() -> Self { Self { only_if_contains_separator: false, @@ -111,7 +123,7 @@ impl Rule for NumericSeparatorsStyle { } fn from_configuration(value: serde_json::Value) -> Self { - let mut cfg = Self::default(); + let mut cfg = NumericSeparatorsStyleConfig::default(); if let Some(config) = value.get(0) { if let Some(config) = config.get("binary") { @@ -134,7 +146,7 @@ impl Rule for NumericSeparatorsStyle { } } - cfg + Self(Box::new(cfg)) } }