diff --git a/apps/oxlint/fixtures/overrides/.oxlintrc.json b/apps/oxlint/fixtures/overrides/.oxlintrc.json index 132ee0cae91c40..e7aaba7bd261cb 100644 --- a/apps/oxlint/fixtures/overrides/.oxlintrc.json +++ b/apps/oxlint/fixtures/overrides/.oxlintrc.json @@ -1,26 +1,49 @@ { + "globals": { + "DefaultFoo": "writeable" + }, "rules": { "no-var": "error", "no-console": "error" }, "overrides": [ { - "files": ["*.js"], + "files": [ + "*.js" + ], "rules": { "no-console": "warn" } }, { - "files": ["*.{js,jsx}"], + "files": [ + "*.{js,jsx}" + ], + "env": { + "es2024": true + }, + "globals": { + "ReadFoo": "readonly", + "WriteBar": "writeable", + "NonBaz": "off" + }, "rules": { "no-console": "off" } }, { - "files": ["*.ts"], + "files": [ + "*.ts" + ], + "env": { + "es2024": false + }, + "globals": { + "DefaultFoo": "off" + }, "rules": { "no-console": "warn" } } ] -} +} \ No newline at end of file diff --git a/apps/oxlint/fixtures/overrides/directories-config.json b/apps/oxlint/fixtures/overrides/directories-config.json index 02c53eda8fcea4..5c0d5c9582749f 100644 --- a/apps/oxlint/fixtures/overrides/directories-config.json +++ b/apps/oxlint/fixtures/overrides/directories-config.json @@ -1,19 +1,41 @@ { + "globals": { + "DefaultFoo": "writeable" + }, "rules": { "no-debugger": "off" }, "overrides": [ { - "files": ["lib/*.{js,ts}", "src/*"], + "files": [ + "lib/*.{js,ts}", + "src/*" + ], + "env": { + "es2024": true + }, + "globals": { + "ReadFoo": "readonly", + "WriteBar": "writeable", + "NonBaz": "off" + }, "rules": { "no-debugger": "error" } }, { - "files": ["**/tests/*"], + "files": [ + "**/tests/*" + ], + "env": { + "es2024": false + }, + "globals": { + "DefaultFoo": "off" + }, "rules": { "no-debugger": "warn" } } ] -} +} \ No newline at end of file diff --git a/apps/oxlint/fixtures/overrides/other.jsx b/apps/oxlint/fixtures/overrides/other.jsx index a6aea4973c4f33..ec1e9f5b3c0607 100644 --- a/apps/oxlint/fixtures/overrides/other.jsx +++ b/apps/oxlint/fixtures/overrides/other.jsx @@ -1,2 +1,12 @@ var msg = "hello"; console.log(msg); + +// for env detection +globalThis = 'abc'; + +// for globals detection +DefaultFoo = 'defaultWriteable'; +ReadFoo = 'readable'; +console.log(ReadFoo); +WriteBar = 'writeable'; +NonBaz = 'alway-soff'; \ No newline at end of file diff --git a/apps/oxlint/fixtures/overrides/src/oxlint.js b/apps/oxlint/fixtures/overrides/src/oxlint.js index eab74692130a60..979aa11a26a0c3 100644 --- a/apps/oxlint/fixtures/overrides/src/oxlint.js +++ b/apps/oxlint/fixtures/overrides/src/oxlint.js @@ -1 +1,12 @@ +// for rules detection debugger; + +// for env detection +globalThis = 'abc'; + +// for globals detection +DefaultFoo = 'defaultWriteable'; +ReadFoo = 'readable'; +console.log(ReadFoo); +WriteBar = 'writeable'; +NonBaz = 'alway-soff'; \ No newline at end of file diff --git a/apps/oxlint/fixtures/overrides/src/tests/index.js b/apps/oxlint/fixtures/overrides/src/tests/index.js index eab74692130a60..979aa11a26a0c3 100644 --- a/apps/oxlint/fixtures/overrides/src/tests/index.js +++ b/apps/oxlint/fixtures/overrides/src/tests/index.js @@ -1 +1,12 @@ +// for rules detection debugger; + +// for env detection +globalThis = 'abc'; + +// for globals detection +DefaultFoo = 'defaultWriteable'; +ReadFoo = 'readable'; +console.log(ReadFoo); +WriteBar = 'writeable'; +NonBaz = 'alway-soff'; \ No newline at end of file diff --git a/apps/oxlint/fixtures/overrides/test.js b/apps/oxlint/fixtures/overrides/test.js index a6aea4973c4f33..ec1e9f5b3c0607 100644 --- a/apps/oxlint/fixtures/overrides/test.js +++ b/apps/oxlint/fixtures/overrides/test.js @@ -1,2 +1,12 @@ var msg = "hello"; console.log(msg); + +// for env detection +globalThis = 'abc'; + +// for globals detection +DefaultFoo = 'defaultWriteable'; +ReadFoo = 'readable'; +console.log(ReadFoo); +WriteBar = 'writeable'; +NonBaz = 'alway-soff'; \ No newline at end of file diff --git a/apps/oxlint/fixtures/overrides/test.ts b/apps/oxlint/fixtures/overrides/test.ts index a6aea4973c4f33..ec1e9f5b3c0607 100644 --- a/apps/oxlint/fixtures/overrides/test.ts +++ b/apps/oxlint/fixtures/overrides/test.ts @@ -1,2 +1,12 @@ var msg = "hello"; console.log(msg); + +// for env detection +globalThis = 'abc'; + +// for globals detection +DefaultFoo = 'defaultWriteable'; +ReadFoo = 'readable'; +console.log(ReadFoo); +WriteBar = 'writeable'; +NonBaz = 'alway-soff'; \ No newline at end of file diff --git a/apps/oxlint/src/snapshots/_-c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.js -c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.ts -c fixtures__overrides__.oxlintrc.json fixtures__overrides__other.jsx@oxlint.snap b/apps/oxlint/src/snapshots/_-c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.js -c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.ts -c fixtures__overrides__.oxlintrc.json fixtures__overrides__other.jsx@oxlint.snap index 50ab81d4bda08a..8baafc1f5c9370 100644 --- a/apps/oxlint/src/snapshots/_-c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.js -c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.ts -c fixtures__overrides__.oxlintrc.json fixtures__overrides__other.jsx@oxlint.snap +++ b/apps/oxlint/src/snapshots/_-c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.js -c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.ts -c fixtures__overrides__.oxlintrc.json fixtures__overrides__other.jsx@oxlint.snap @@ -14,7 +14,16 @@ working directory: `---- help: Replace var with let or const -Found 0 warnings and 1 error. + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-global-assign.html\eslint(no-global-assign)]8;;\: Read-only global 'globalThis' should not be modified. + ,-[fixtures/overrides/test.js:5:1] + 4 | // for env detection + 5 | globalThis = 'abc'; + : ^^^^^|^^^^ + : `-- Read-only global 'globalThis' should not be modified. + 6 | + `---- + +Found 1 warning and 1 error. Finished in ms on 1 file with 99 rules using 1 threads. ---------- CLI result: LintFoundErrors @@ -38,10 +47,29 @@ working directory: 1 | var msg = "hello"; 2 | console.log(msg); : ^^^^^^^^^^^ + 3 | `---- help: Delete this console statement. -Found 1 warning and 1 error. + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-global-assign.html\eslint(no-global-assign)]8;;\: Read-only global 'globalThis' should not be modified. + ,-[fixtures/overrides/test.ts:5:1] + 4 | // for env detection + 5 | globalThis = 'abc'; + : ^^^^^|^^^^ + : `-- Read-only global 'globalThis' should not be modified. + 6 | + `---- + + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-console.html\eslint(no-console)]8;;\: eslint(no-console): Unexpected console statement. + ,-[fixtures/overrides/test.ts:10:1] + 9 | ReadFoo = 'readable'; + 10 | console.log(ReadFoo); + : ^^^^^^^^^^^ + 11 | WriteBar = 'writeable'; + `---- + help: Delete this console statement. + +Found 3 warnings and 1 error. Finished in ms on 1 file with 99 rules using 1 threads. ---------- CLI result: LintFoundErrors @@ -60,7 +88,16 @@ working directory: `---- help: Replace var with let or const -Found 0 warnings and 1 error. + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-global-assign.html\eslint(no-global-assign)]8;;\: Read-only global 'globalThis' should not be modified. + ,-[fixtures/overrides/other.jsx:5:1] + 4 | // for env detection + 5 | globalThis = 'abc'; + : ^^^^^|^^^^ + : `-- Read-only global 'globalThis' should not be modified. + 6 | + `---- + +Found 1 warning and 1 error. Finished in ms on 1 file with 99 rules using 1 threads. ---------- CLI result: LintFoundErrors diff --git a/apps/oxlint/src/snapshots/_-c fixtures__overrides__directories-config.json fixtures__overrides@oxlint.snap b/apps/oxlint/src/snapshots/_-c fixtures__overrides__directories-config.json fixtures__overrides@oxlint.snap index 3f814d0191016d..1edd369d0a766c 100644 --- a/apps/oxlint/src/snapshots/_-c fixtures__overrides__directories-config.json fixtures__overrides@oxlint.snap +++ b/apps/oxlint/src/snapshots/_-c fixtures__overrides__directories-config.json fixtures__overrides@oxlint.snap @@ -21,20 +21,69 @@ working directory: help: Delete this code. x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-debugger.html\eslint(no-debugger)]8;;\: `debugger` statement is not allowed - ,-[fixtures/overrides/src/oxlint.js:1:1] - 1 | debugger; + ,-[fixtures/overrides/src/oxlint.js:2:1] + 1 | // for rules detection + 2 | debugger; : ^^^^^^^^^ + 3 | `---- help: Delete this code. ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-debugger.html\eslint(no-debugger)]8;;\: `debugger` statement is not allowed - ,-[fixtures/overrides/src/tests/index.js:1:1] - 1 | debugger; + ,-[fixtures/overrides/src/tests/index.js:2:1] + 1 | // for rules detection + 2 | debugger; : ^^^^^^^^^ + 3 | `---- help: Delete this code. -Found 2 warnings and 2 errors. + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-global-assign.html\eslint(no-global-assign)]8;;\: Read-only global 'globalThis' should not be modified. + ,-[fixtures/overrides/other.jsx:5:1] + 4 | // for env detection + 5 | globalThis = 'abc'; + : ^^^^^|^^^^ + : `-- Read-only global 'globalThis' should not be modified. + 6 | + `---- + + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-global-assign.html\eslint(no-global-assign)]8;;\: Read-only global 'globalThis' should not be modified. + ,-[fixtures/overrides/src/oxlint.js:5:1] + 4 | // for env detection + 5 | globalThis = 'abc'; + : ^^^^^|^^^^ + : `-- Read-only global 'globalThis' should not be modified. + 6 | + `---- + + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-global-assign.html\eslint(no-global-assign)]8;;\: Read-only global 'globalThis' should not be modified. + ,-[fixtures/overrides/src/tests/index.js:5:1] + 4 | // for env detection + 5 | globalThis = 'abc'; + : ^^^^^|^^^^ + : `-- Read-only global 'globalThis' should not be modified. + 6 | + `---- + + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-global-assign.html\eslint(no-global-assign)]8;;\: Read-only global 'globalThis' should not be modified. + ,-[fixtures/overrides/test.js:5:1] + 4 | // for env detection + 5 | globalThis = 'abc'; + : ^^^^^|^^^^ + : `-- Read-only global 'globalThis' should not be modified. + 6 | + `---- + + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-global-assign.html\eslint(no-global-assign)]8;;\: Read-only global 'globalThis' should not be modified. + ,-[fixtures/overrides/test.ts:5:1] + 4 | // for env detection + 5 | globalThis = 'abc'; + : ^^^^^|^^^^ + : `-- Read-only global 'globalThis' should not be modified. + 6 | + `---- + +Found 7 warnings and 2 errors. Finished in ms on 7 files with 96 rules using 1 threads. ---------- CLI result: LintFoundErrors diff --git a/crates/oxc_linter/src/config/config_store.rs b/crates/oxc_linter/src/config/config_store.rs index 1fa756bd668c0e..c9c1545f5d80b7 100644 --- a/crates/oxc_linter/src/config/config_store.rs +++ b/crates/oxc_linter/src/config/config_store.rs @@ -85,12 +85,9 @@ impl ConfigStore { return config.base.clone(); } + let mut env = config.base.config.env.clone(); + let mut globals = config.base.config.globals.clone(); let mut plugins = config.base.config.plugins; - let all_rules = RULES - .iter() - .filter(|rule| plugins.contains(LintPlugins::from(rule.plugin_name()))) - .cloned() - .collect::>(); let mut rules = config .base .rules @@ -99,6 +96,12 @@ impl ConfigStore { .cloned() .collect::>(); + let all_rules = RULES + .iter() + .filter(|rule| plugins.contains(LintPlugins::from(rule.plugin_name()))) + .cloned() + .collect::>(); + for override_config in overrides_to_apply { if !override_config.rules.is_empty() { override_config.rules.override_rules(&mut rules, &all_rules); @@ -107,18 +110,31 @@ impl ConfigStore { if let Some(override_plugins) = override_config.plugins { plugins |= override_plugins; } + + if let Some(override_env) = &override_config.env { + override_env.override_envs(&mut env); + } + + if let Some(override_globals) = &override_config.globals { + override_globals.override_globals(&mut globals); + } } - let rules = rules.into_iter().collect::>(); - let config = if plugins == config.base.config.plugins { + let config = if plugins == config.base.config.plugins + && env == config.base.config.env + && globals == config.base.config.globals + { Arc::clone(&config.base.config) } else { let mut config = (*config.base.config).clone(); config.plugins = plugins; + config.env = env; + config.globals = globals; Arc::new(config) }; + let rules = rules.into_iter().collect::>(); ResolvedLinterState { rules: Arc::from(rules.into_boxed_slice()), config } } } @@ -282,4 +298,109 @@ mod test { let app = store.resolve("App.tsx".as_ref()).config; assert_eq!(app.plugins, LintPlugins::IMPORT | LintPlugins::REACT | LintPlugins::TYPESCRIPT); } + + #[test] + fn test_add_env() { + let base_config = LintConfig { + env: OxlintEnv::default(), + plugins: LintPlugins::ESLINT, + settings: OxlintSettings::default(), + globals: OxlintGlobals::default(), + path: None, + }; + + let overrides = from_json!([{ + "files": ["*.tsx"], + "env": { + "es2024": true + }, + }]); + + let store = ConfigStore::new(vec![], base_config, overrides); + assert!(!store.base.base.config.env.contains("React")); + + let app = store.resolve("App.tsx".as_ref()).config; + assert!(app.env.contains("es2024")); + } + + #[test] + fn test_replace_env() { + let base_config = LintConfig { + env: OxlintEnv::from_iter(["es2024".into()]), + plugins: LintPlugins::ESLINT, + settings: OxlintSettings::default(), + globals: OxlintGlobals::default(), + path: None, + }; + + let overrides = from_json!([{ + "files": ["*.tsx"], + "env": { + "es2024": false + }, + }]); + + let store = ConfigStore::new(vec![], base_config, overrides); + assert!(store.base.base.config.env.contains("es2024")); + + let app = store.resolve("App.tsx".as_ref()).config; + assert!(!app.env.contains("es2024")); + } + + #[test] + fn test_add_globals() { + let base_config = LintConfig { + env: OxlintEnv::default(), + plugins: LintPlugins::ESLINT, + settings: OxlintSettings::default(), + globals: OxlintGlobals::default(), + path: None, + }; + + let overrides = from_json!([{ + "files": ["*.tsx"], + "globals": { + "React": "readonly", + "Secret": "writeable" + }, + }]); + + let store = ConfigStore::new(vec![], base_config, overrides); + assert!(!store.base.base.config.globals.is_enabled("React")); + assert!(!store.base.base.config.globals.is_enabled("Secret")); + + let app = store.resolve("App.tsx".as_ref()).config; + assert!(app.globals.is_enabled("React")); + assert!(app.globals.is_enabled("Secret")); + } + + #[test] + fn test_replace_globals() { + let base_config = LintConfig { + env: OxlintEnv::default(), + plugins: LintPlugins::ESLINT, + settings: OxlintSettings::default(), + globals: from_json!({ + "React": "readonly", + "Secret": "writeable" + }), + path: None, + }; + + let overrides = from_json!([{ + "files": ["*.tsx"], + "globals": { + "React": "off", + "Secret": "off" + }, + }]); + + let store = ConfigStore::new(vec![], base_config, overrides); + assert!(store.base.base.config.globals.is_enabled("React")); + assert!(store.base.base.config.globals.is_enabled("Secret")); + + let app = store.resolve("App.tsx".as_ref()).config; + assert!(!app.globals.is_enabled("React")); + assert!(!app.globals.is_enabled("Secret")); + } } diff --git a/crates/oxc_linter/src/config/env.rs b/crates/oxc_linter/src/config/env.rs index 9f11447315421f..cab011440a433d 100644 --- a/crates/oxc_linter/src/config/env.rs +++ b/crates/oxc_linter/src/config/env.rs @@ -10,25 +10,9 @@ use serde::{Deserialize, Serialize}; /// list of /// environments](https://eslint.org/docs/v8.x/use/configure/language-options#specifying-environments) /// for what environments are available and what each one provides. -#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)] -#[cfg_attr(test, derive(PartialEq))] +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)] pub struct OxlintEnv(FxHashMap); -impl OxlintEnv { - pub fn contains(&self, key: &Q) -> bool - where - String: Borrow, - Q: ?Sized + Hash + Eq, - { - self.0.get(key).is_some_and(|v| *v) - } - - pub fn iter(&self) -> impl Iterator + '_ { - // Filter out false values - self.0.iter().filter_map(|(k, v)| (*v).then_some(k.as_str())) - } -} - impl FromIterator for OxlintEnv { fn from_iter>(iter: T) -> Self { let map = iter.into_iter().map(|key| (key, true)).collect(); @@ -46,6 +30,27 @@ impl Default for OxlintEnv { } } +impl OxlintEnv { + pub fn contains(&self, key: &Q) -> bool + where + String: Borrow, + Q: ?Sized + Hash + Eq, + { + self.0.get(key).is_some_and(|v| *v) + } + + pub fn iter(&self) -> impl Iterator + '_ { + // Filter out false values + self.0.iter().filter_map(|(k, v)| (*v).then_some(k.as_str())) + } + + pub(crate) fn override_envs(&self, envs_to_override: &mut OxlintEnv) { + for (env, supported) in self.0.clone() { + envs_to_override.0.insert(env, supported); + } + } +} + #[cfg(test)] mod test { use serde::Deserialize; @@ -70,4 +75,17 @@ mod test { assert_eq!(env.iter().count(), 1); assert!(env.contains("builtin")); } + + #[test] + fn test_override_envs() { + let mut env = OxlintEnv::default(); + let override_env = OxlintEnv::deserialize(&serde_json::json!({ + "browser": true, + })) + .unwrap(); + + override_env.override_envs(&mut env); + + assert!(env.contains("browser")); + } } diff --git a/crates/oxc_linter/src/config/globals.rs b/crates/oxc_linter/src/config/globals.rs index 93996ea7820206..b85cd7bcdfbcc6 100644 --- a/crates/oxc_linter/src/config/globals.rs +++ b/crates/oxc_linter/src/config/globals.rs @@ -30,9 +30,18 @@ use serde::{de::Visitor, Deserialize, Serialize}; /// You may also use `"readable"` or `false` to represent `"readonly"`, and /// `"writeable"` or `true` to represent `"writable"`. // -#[derive(Debug, Default, Deserialize, Serialize, JsonSchema, Clone)] +#[derive(Debug, Default, PartialEq, Deserialize, Serialize, JsonSchema, Clone)] pub struct OxlintGlobals(FxHashMap); impl OxlintGlobals { + #[cfg(test)] + pub fn get_copied(&self, name: &Q) -> Option + where + String: borrow::Borrow, + Q: ?Sized + Eq + hash::Hash, + { + self.0.get(name).copied() + } + pub fn is_enabled(&self, name: &Q) -> bool where String: borrow::Borrow, @@ -40,6 +49,12 @@ impl OxlintGlobals { { self.0.get(name).is_some_and(|value| *value != GlobalValue::Off) } + + pub(crate) fn override_globals(&self, globals_to_override: &mut OxlintGlobals) { + for (env, supported) in self.0.clone() { + globals_to_override.0.insert(env, supported); + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, JsonSchema)] @@ -165,4 +180,20 @@ mod test { assert!(globals.is_enabled("foo")); assert!(globals.is_enabled("bar")); } + + #[test] + fn test_override_globals() { + let mut globals = OxlintGlobals::deserialize(&serde_json::json!({ + "Foo": "writeable", + })) + .unwrap(); + let override_globals = OxlintGlobals::deserialize(&serde_json::json!({ + "Foo": "off", + })) + .unwrap(); + + override_globals.override_globals(&mut globals); + + assert!(!globals.is_enabled("Foo")); + } } diff --git a/crates/oxc_linter/src/config/overrides.rs b/crates/oxc_linter/src/config/overrides.rs index 7750d3ec115cf6..83c37907bfd666 100644 --- a/crates/oxc_linter/src/config/overrides.rs +++ b/crates/oxc_linter/src/config/overrides.rs @@ -6,7 +6,7 @@ use serde::{de, ser, Deserialize, Serialize}; use oxc_index::{Idx, IndexVec}; -use crate::{config::OxlintRules, LintPlugins}; +use crate::{config::OxlintRules, LintPlugins, OxlintEnv, OxlintGlobals}; #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct OverrideId(NonMaxU32); @@ -73,6 +73,12 @@ pub struct OxlintOverride { /// `[ "*.test.ts", "*.spec.ts" ]` pub files: GlobSet, + /// Environments enable and disable collections of global variables. + pub env: Option, + + /// Enabled or disabled specific global variables. + pub globals: Option, + /// Optionally change what plugins are enabled for this override. When /// omitted, the base config's plugins are used. #[serde(default)] @@ -153,13 +159,15 @@ impl JsonSchema for GlobSet { } } +#[cfg(test)] mod test { - #[test] - fn test_globset() { - use serde_json::{from_value, json}; + use crate::config::globals::GlobalValue; - use super::*; + use super::*; + use serde_json::{from_value, json}; + #[test] + fn test_globset() { let config: OxlintOverride = from_value(json!({ "files": ["*.tsx",], })) @@ -177,10 +185,6 @@ mod test { #[test] fn test_parsing_plugins() { - use serde_json::{from_value, json}; - - use super::*; - let config: OxlintOverride = from_value(json!({ "files": ["*.tsx"], })) @@ -201,4 +205,44 @@ mod test { .unwrap(); assert_eq!(config.plugins, Some(LintPlugins::REACT | LintPlugins::TYPESCRIPT)); } + + #[test] + fn test_parsing_globals() { + let config: OxlintOverride = from_value(json!({ + "files": ["*.tsx"], + })) + .unwrap(); + assert!(config.globals.is_none()); + + let config: OxlintOverride = from_value(json!({ + "files": ["*.tsx"], + "globals": { + "Foo": "readable" + }, + })) + .unwrap(); + + assert_eq!(config.globals.unwrap().get_copied("Foo").unwrap(), GlobalValue::Readonly); + } + + #[test] + fn test_parsing_env() { + let config: OxlintOverride = from_value(json!({ + "files": ["*.tsx"], + })) + .unwrap(); + assert!(config.env.is_none()); + + let config: OxlintOverride = from_value(json!({ + "files": ["*.tsx"], + "env": { + "es2022": true, + "es2023": false, + }, + })) + .unwrap(); + + assert!(config.env.clone().unwrap().contains("es2022")); + assert!(!config.env.unwrap().contains("es2023")); + } } diff --git a/crates/oxc_linter/src/snapshots/schema_json.snap b/crates/oxc_linter/src/snapshots/schema_json.snap index 25a54c49484166..8b2923340d0c7e 100644 --- a/crates/oxc_linter/src/snapshots/schema_json.snap +++ b/crates/oxc_linter/src/snapshots/schema_json.snap @@ -355,6 +355,17 @@ expression: json "files" ], "properties": { + "env": { + "description": "Environments enable and disable collections of global variables.", + "anyOf": [ + { + "$ref": "#/definitions/OxlintEnv" + }, + { + "type": "null" + } + ] + }, "files": { "description": "A list of glob patterns to override.\n\n## Example `[ \"*.test.ts\", \"*.spec.ts\" ]`", "allOf": [ @@ -363,6 +374,17 @@ expression: json } ] }, + "globals": { + "description": "Enabled or disabled specific global variables.", + "anyOf": [ + { + "$ref": "#/definitions/OxlintGlobals" + }, + { + "type": "null" + } + ] + }, "plugins": { "description": "Optionally change what plugins are enabled for this override. When omitted, the base config's plugins are used.", "default": null, diff --git a/npm/oxlint/configuration_schema.json b/npm/oxlint/configuration_schema.json index 641d05f79b3367..7c3ee3f5015fe7 100644 --- a/npm/oxlint/configuration_schema.json +++ b/npm/oxlint/configuration_schema.json @@ -351,6 +351,17 @@ "files" ], "properties": { + "env": { + "description": "Environments enable and disable collections of global variables.", + "anyOf": [ + { + "$ref": "#/definitions/OxlintEnv" + }, + { + "type": "null" + } + ] + }, "files": { "description": "A list of glob patterns to override.\n\n## Example `[ \"*.test.ts\", \"*.spec.ts\" ]`", "allOf": [ @@ -359,6 +370,17 @@ } ] }, + "globals": { + "description": "Enabled or disabled specific global variables.", + "anyOf": [ + { + "$ref": "#/definitions/OxlintGlobals" + }, + { + "type": "null" + } + ] + }, "plugins": { "description": "Optionally change what plugins are enabled for this override. When omitted, the base config's plugins are used.", "default": null,