diff --git a/crates/oxc_linter/src/config/mod.rs b/crates/oxc_linter/src/config/mod.rs index bcd2fb00d..75321da86 100644 --- a/crates/oxc_linter/src/config/mod.rs +++ b/crates/oxc_linter/src/config/mod.rs @@ -19,17 +19,18 @@ pub use self::{env::ESLintEnv, rules::ESLintRules, settings::ESLintSettings}; /// ESLint Config /// -#[derive(Debug, Deserialize)] +#[derive(Debug, Default, Deserialize)] +#[serde(default)] pub struct ESLintConfig { - #[serde(default)] - rules: ESLintRules, - #[serde(default)] - settings: ESLintSettings, - #[serde(default)] - env: ESLintEnv, + pub(crate) rules: ESLintRules, + pub(crate) settings: ESLintSettings, + pub(crate) env: ESLintEnv, } impl ESLintConfig { + /// # Errors + /// + /// * Parse Failure pub fn from_file(path: &Path) -> Result { let mut string = std::fs::read_to_string(path).map_err(|e| { FailedToParseConfigError(vec![Error::new(FailedToOpenFileError(path.to_path_buf(), e))]) @@ -66,10 +67,6 @@ impl ESLintConfig { Ok(config) } - pub fn properties(self) -> (ESLintSettings, ESLintEnv) { - (self.settings, self.env) - } - #[allow(clippy::option_if_let_else)] pub fn override_rules( &self, diff --git a/crates/oxc_linter/src/context.rs b/crates/oxc_linter/src/context.rs index 3b815cf0e..607871268 100644 --- a/crates/oxc_linter/src/context.rs +++ b/crates/oxc_linter/src/context.rs @@ -9,7 +9,7 @@ use crate::{ disable_directives::{DisableDirectives, DisableDirectivesBuilder}, fixer::{Fix, Message}, javascript_globals::GLOBALS, - ESLintEnv, ESLintSettings, + ESLintConfig, ESLintEnv, ESLintSettings, }; pub struct LintContext<'a> { @@ -26,9 +26,7 @@ pub struct LintContext<'a> { file_path: Box, - settings: Arc, - - env: Arc, + pub eslint_config: Arc, } impl<'a> LintContext<'a> { @@ -42,8 +40,7 @@ impl<'a> LintContext<'a> { fix: false, current_rule_name: "", file_path, - settings: Arc::new(ESLintSettings::default()), - env: Arc::new(ESLintEnv::default()), + eslint_config: Arc::new(ESLintConfig::default()), } } @@ -54,14 +51,8 @@ impl<'a> LintContext<'a> { } #[must_use] - pub fn with_settings(mut self, settings: &Arc) -> Self { - self.settings = Arc::clone(settings); - self - } - - #[must_use] - pub fn with_env(mut self, env: &Arc) -> Self { - self.env = Arc::clone(env); + pub fn with_eslint_config(mut self, eslint_config: &Arc) -> Self { + self.eslint_config = Arc::clone(eslint_config); self } @@ -73,10 +64,6 @@ impl<'a> LintContext<'a> { &self.disable_directives } - pub fn settings(&self) -> &ESLintSettings { - &self.settings - } - pub fn source_text(&self) -> &'a str { self.semantic().source_text() } @@ -89,12 +76,16 @@ impl<'a> LintContext<'a> { &self.file_path } - pub fn envs(&self) -> &ESLintEnv { - &self.env + pub fn env(&self) -> &ESLintEnv { + &self.eslint_config.env + } + + pub fn settings(&self) -> &ESLintSettings { + &self.eslint_config.settings } pub fn env_contains_var(&self, var: &str) -> bool { - for env in self.env.iter() { + for env in self.env().iter() { let env = GLOBALS.get(env).unwrap_or(&GLOBALS["builtin"]); if env.get(var).is_some() { return true; diff --git a/crates/oxc_linter/src/lib.rs b/crates/oxc_linter/src/lib.rs index f216bd59c..0a7e99624 100644 --- a/crates/oxc_linter/src/lib.rs +++ b/crates/oxc_linter/src/lib.rs @@ -23,6 +23,12 @@ use std::{io::Write, rc::Rc, sync::Arc}; use oxc_diagnostics::Report; +pub use crate::{ + config::ESLintConfig, + context::LintContext, + options::{AllowWarnDeny, LintOptions}, + service::{LintService, LintServiceOptions}, +}; use crate::{ config::{ESLintEnv, ESLintSettings}, fixer::Fix, @@ -30,11 +36,6 @@ use crate::{ rule::RuleCategory, rules::{RuleEnum, RULES}, }; -pub use crate::{ - context::LintContext, - options::{AllowWarnDeny, LintOptions}, - service::{LintService, LintServiceOptions}, -}; use oxc_semantic::AstNode; #[cfg(target_pointer_width = "64")] @@ -52,8 +53,7 @@ fn size_asserts() { pub struct Linter { rules: Vec<(/* rule name */ &'static str, RuleEnum)>, options: LintOptions, - settings: Arc, - env: Arc, + eslint_config: Arc, } impl Default for Linter { @@ -67,9 +67,9 @@ impl Linter { /// /// Returns `Err` if there are any errors parsing the configuration file. pub fn from_options(options: LintOptions) -> Result { - let (rules, settings, env) = options.derive_rules_and_settings_and_env()?; + let (rules, eslint_config) = options.derive_rules_and_config()?; let rules = rules.into_iter().map(|rule| (rule.name(), rule)).collect(); - Ok(Self { rules, options, settings: Arc::new(settings), env: Arc::new(env) }) + Ok(Self { rules, options, eslint_config: Arc::new(eslint_config) }) } #[must_use] @@ -79,14 +79,14 @@ impl Linter { } #[must_use] - pub fn with_settings(mut self, settings: ESLintSettings) -> Self { - self.settings = Arc::new(settings); + pub fn with_eslint_config(mut self, eslint_config: ESLintConfig) -> Self { + self.eslint_config = Arc::new(eslint_config); self } #[must_use] - pub fn with_envs(mut self, env: ESLintEnv) -> Self { - self.env = Arc::new(env); + pub fn with_fix(mut self, yes: bool) -> Self { + self.options.fix = yes; self } @@ -98,16 +98,9 @@ impl Linter { self.rules.len() } - #[must_use] - pub fn with_fix(mut self, yes: bool) -> Self { - self.options.fix = yes; - self - } - pub fn run<'a>(&self, ctx: LintContext<'a>) -> Vec> { let semantic = Rc::clone(ctx.semantic()); - let mut ctx = - ctx.with_fix(self.options.fix).with_settings(&self.settings).with_env(&self.env); + let mut ctx = ctx.with_fix(self.options.fix).with_eslint_config(&self.eslint_config); for (rule_name, rule) in &self.rules { ctx.with_rule_name(rule_name); diff --git a/crates/oxc_linter/src/options.rs b/crates/oxc_linter/src/options.rs index 37fd69c74..1f9b94472 100644 --- a/crates/oxc_linter/src/options.rs +++ b/crates/oxc_linter/src/options.rs @@ -1,5 +1,10 @@ use std::path::PathBuf; +use rustc_hash::FxHashSet; +use serde_json::{Number, Value}; + +use oxc_diagnostics::Error; + use crate::{ config::{ errors::{ @@ -9,11 +14,8 @@ use crate::{ ESLintConfig, }, rules::RULES, - ESLintEnv, ESLintSettings, RuleCategory, RuleEnum, + RuleCategory, RuleEnum, }; -use oxc_diagnostics::Error; -use rustc_hash::FxHashSet; -use serde_json::{Number, Value}; #[derive(Debug)] pub struct LintOptions { @@ -29,7 +31,6 @@ pub struct LintOptions { pub jsx_a11y_plugin: bool, pub nextjs_plugin: bool, pub react_perf_plugin: bool, - pub env: ESLintEnv, } impl Default for LintOptions { @@ -45,7 +46,6 @@ impl Default for LintOptions { jsx_a11y_plugin: false, nextjs_plugin: false, react_perf_plugin: false, - env: ESLintEnv::default(), } } } @@ -112,12 +112,6 @@ impl LintOptions { self.react_perf_plugin = yes; self } - - #[must_use] - pub fn with_env(mut self, env: Vec) -> Self { - self.env = ESLintEnv::from_vec(env); - self - } } #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -186,9 +180,7 @@ impl LintOptions { /// # Errors /// /// * Returns `Err` if there are any errors parsing the configuration file. - pub fn derive_rules_and_settings_and_env( - &self, - ) -> Result<(Vec, ESLintSettings, ESLintEnv), Error> { + pub fn derive_rules_and_config(&self) -> Result<(Vec, ESLintConfig), Error> { let config = self.config_path.as_ref().map(|path| ESLintConfig::from_file(path)).transpose()?; @@ -238,12 +230,10 @@ impl LintOptions { let mut rules = rules.into_iter().collect::>(); - let (settings, env) = config.map(ESLintConfig::properties).unwrap_or_default(); - // for stable diagnostics output ordering rules.sort_unstable_by_key(RuleEnum::name); - Ok((rules, settings, env)) + Ok((rules, config.unwrap_or_default())) } // get final filtered rules by reading `self.xxx_plugin` diff --git a/crates/oxc_linter/src/rules/jsdoc/check_access.rs b/crates/oxc_linter/src/rules/jsdoc/check_access.rs index 17929575c..6d7f86d98 100644 --- a/crates/oxc_linter/src/rules/jsdoc/check_access.rs +++ b/crates/oxc_linter/src/rules/jsdoc/check_access.rs @@ -111,7 +111,7 @@ fn test() { * */ function quux (foo) { - + } ", None, @@ -123,7 +123,7 @@ fn test() { * @access public */ function quux (foo) { - + } ", None, @@ -135,16 +135,16 @@ fn test() { * @accessLevel package */ function quux (foo) { - + } ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "access": "accessLevel", }, - }, + } }, })), ), ( @@ -165,7 +165,7 @@ fn test() { * @public */ function quux (foo) { - + } ", None, @@ -177,14 +177,14 @@ fn test() { * @private */ function quux (foo) { - + } ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "ignorePrivate": true, - }, + } }, })), ), ( @@ -205,7 +205,7 @@ fn test() { * @access foo */ function quux (foo) { - + } ", None, @@ -217,14 +217,14 @@ fn test() { * @access foo */ function quux (foo) { - + } ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "ignorePrivate": true, - }, + } }, })), ), ( @@ -238,11 +238,11 @@ fn test() { ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "access": "accessLevel", }, - }, + } }, })), ), ( @@ -251,16 +251,16 @@ fn test() { * @access */ function quux (foo) { - + } ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "access": false, }, - }, + } }, })), ), ( @@ -282,7 +282,7 @@ fn test() { * @public */ function quux (foo) { - + } ", None, @@ -295,7 +295,7 @@ fn test() { * @access private */ function quux (foo) { - + } ", None, @@ -308,14 +308,14 @@ fn test() { * @access private */ function quux (foo) { - + } ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "ignorePrivate": true, - }, + } }, })), ), ( @@ -325,7 +325,7 @@ fn test() { * @private */ function quux (foo) { - + } ", None, @@ -338,14 +338,14 @@ fn test() { * @private */ function quux (foo) { - + } ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "ignorePrivate": true, - }, + } }, })), ), ( @@ -355,7 +355,7 @@ fn test() { * @public */ function quux (foo) { - + } ", None, diff --git a/crates/oxc_linter/src/rules/jsdoc/check_property_names.rs b/crates/oxc_linter/src/rules/jsdoc/check_property_names.rs index 5a881b8a6..ded254055 100644 --- a/crates/oxc_linter/src/rules/jsdoc/check_property_names.rs +++ b/crates/oxc_linter/src/rules/jsdoc/check_property_names.rs @@ -318,7 +318,7 @@ fn test() { * @property cfg.foo */ function quux ({foo, bar}) { - + } ", None, @@ -335,7 +335,7 @@ fn test() { * @property cfg.foo */ quux ({foo, bar}) { - + } } ", @@ -352,7 +352,7 @@ fn test() { * @property baz */ function quux ({foo, bar}, baz) { - + } ", None, @@ -368,7 +368,7 @@ fn test() { * @property baz */ function quux ({foo, bar}, baz) { - + } "#, None, @@ -409,11 +409,11 @@ fn test() { ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "property": "prop", }, - }, + } }, })), ), ]; diff --git a/crates/oxc_linter/src/rules/jsdoc/require_property.rs b/crates/oxc_linter/src/rules/jsdoc/require_property.rs index a88303bc6..e1e5fdcda 100644 --- a/crates/oxc_linter/src/rules/jsdoc/require_property.rs +++ b/crates/oxc_linter/src/rules/jsdoc/require_property.rs @@ -135,11 +135,11 @@ fn test() { ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "property": "prop", }, - }, + } }, })), ), ( @@ -201,7 +201,7 @@ fn test() { * @property {anotherType} yetAnotherProp This with a type and desc. */ function quux () { - + } ", None, @@ -250,11 +250,11 @@ fn test() { ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "property": "prop", }, - }, + } }, })), ), ( diff --git a/crates/oxc_linter/src/rules/jsdoc/require_property_description.rs b/crates/oxc_linter/src/rules/jsdoc/require_property_description.rs index 0477d4595..befe68520 100644 --- a/crates/oxc_linter/src/rules/jsdoc/require_property_description.rs +++ b/crates/oxc_linter/src/rules/jsdoc/require_property_description.rs @@ -130,11 +130,11 @@ fn test() { ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "property": "prop", }, - }, + } }, })), ), ]; @@ -179,11 +179,11 @@ fn test() { ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "property": "prop", }, - }, + } }, })), ), ]; diff --git a/crates/oxc_linter/src/rules/jsdoc/require_property_name.rs b/crates/oxc_linter/src/rules/jsdoc/require_property_name.rs index 4555edb60..d01291628 100644 --- a/crates/oxc_linter/src/rules/jsdoc/require_property_name.rs +++ b/crates/oxc_linter/src/rules/jsdoc/require_property_name.rs @@ -140,11 +140,11 @@ fn test() { ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "property": "prop", }, - }, + } }, })), ), ]; diff --git a/crates/oxc_linter/src/rules/jsdoc/require_property_type.rs b/crates/oxc_linter/src/rules/jsdoc/require_property_type.rs index a1fbe2f2b..781046398 100644 --- a/crates/oxc_linter/src/rules/jsdoc/require_property_type.rs +++ b/crates/oxc_linter/src/rules/jsdoc/require_property_type.rs @@ -116,11 +116,11 @@ fn test() { ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "property": "prop", }, - }, + } }, })), ), ]; @@ -165,11 +165,11 @@ fn test() { ", None, Some(serde_json::json!({ - "jsdoc": { + "settings": { "jsdoc": { "tagNamePreference": { "property": "prop", }, - }, + } }, })), ), ]; 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 b352bec67..ce33a3c26 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs @@ -465,7 +465,9 @@ fn test() { ( r#""#, None, - Some(serde_json::json!({ "jsx-a11y": { "polymorphicPropName": "as" } })), + Some( + serde_json::json!({ "settings": { "jsx-a11y": { "polymorphicPropName": "as" } } }), + ), ), (r"", None, None), (r"
", None, None), diff --git a/crates/oxc_linter/src/rules/jsx_a11y/anchor_has_content.rs b/crates/oxc_linter/src/rules/jsx_a11y/anchor_has_content.rs index 860a267dd..153a1790c 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/anchor_has_content.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/anchor_has_content.rs @@ -110,7 +110,9 @@ fn test() { ( r"foo", None, - Some(serde_json::json!({ "jsx-a11y": { "components": { "Link": "a" } } })), + Some( + serde_json::json!({ "settings": { "jsx-a11y": { "components": { "Link": "a" } } } }), + ), ), (r"", None, None), (r"", None, None), @@ -124,7 +126,9 @@ fn test() { ( r"", None, - Some(serde_json::json!({ "jsx-a11y": { "components": { "Link": "a" } } })), + Some( + serde_json::json!({ "settings": { "jsx-a11y": { "components": { "Link": "a" } } } }), + ), ), ]; diff --git a/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs b/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs index 603c5ecad..4c17de4da 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs @@ -295,7 +295,7 @@ fn test() { r"", Some(serde_json::json!({ "validHrefs": ["#foo"] })), Some( - serde_json::json!({ "jsx-a11y": { "components": { "Anchor": "a", "Link": "a" } } }), + serde_json::json!({ "settings": { "jsx-a11y": { "components": { "Anchor": "a", "Link": "a" } } } }), ), ), // (r#""#, Some(serde_json::json!(specialLink))), @@ -578,7 +578,7 @@ fn test() { r" void 0} />", None, Some( - serde_json::json!({ "jsx-a11y": { "components": { "Anchor": "a", "Link": "a" } } }), + serde_json::json!({ "settings": { "jsx-a11y": { "components": { "Anchor": "a", "Link": "a" } } } }), ), ), // (r#""#, Some(serde_json::json!(specialLink))), diff --git a/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs b/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs index 7b604dbd6..98ad800e7 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs @@ -108,11 +108,11 @@ fn test() { fn settings() -> serde_json::Value { serde_json::json!({ - "jsx-a11y": { + "settings": { "jsx-a11y": { "components": { "CustomComponent": "div", } - } + } } }) } diff --git a/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs b/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs index c4174a84f..0e1bba5fc 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs @@ -182,12 +182,12 @@ fn test() { fn settings() -> serde_json::Value { serde_json::json!({ - "jsx-a11y": { + "settings": { "jsx-a11y": { "polymorphicPropName": "asChild", "components": { "Div": "div", } - } + } } }) } diff --git a/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs b/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs index f0f9f8610..c2d39752d 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/autocomplete_valid.rs @@ -215,11 +215,11 @@ fn test() { fn settings() -> serde_json::Value { serde_json::json!({ - "jsx-a11y": { + "settings": { "jsx-a11y": { "components": { "Input": "input", } - } + } } }) } diff --git a/crates/oxc_linter/src/rules/jsx_a11y/click_events_have_key_events.rs b/crates/oxc_linter/src/rules/jsx_a11y/click_events_have_key_events.rs index cdac7d54b..6a7402d3b 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/click_events_have_key_events.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/click_events_have_key_events.rs @@ -137,11 +137,11 @@ fn test() { r"