Skip to content

Commit fb7cf10

Browse files
committed
feat(linter): allowing plugins to be extended with extends (#9473)
Adds support for merging the `plugins` arrays in configuration files referenced in `extends` to the top-level `plugins` array of a configuration file. Essentially acts as if you had placed it in the plugins array at the top-level to begin with.
1 parent 5ecda01 commit fb7cf10

File tree

4 files changed

+67
-2
lines changed

4 files changed

+67
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"plugins": ["jest"]
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"plugins": ["react"]
3+
}

crates/oxc_linter/src/config/config_builder.rs

+57-2
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,11 @@ impl ConfigStoreBuilder {
130130
.rules
131131
.override_rules(&mut builder.rules, &builder.cache.borrow());
132132
// Use `ConfigStoreBuilder` to load extended config files and then apply rules from those
133-
let extended_config_store =
133+
let mut extended_config_store =
134134
ConfigStoreBuilder::from_oxlintrc(true, extended_config)?;
135-
builder = builder.with_rules(extended_config_store.rules);
135+
let rules = std::mem::take(&mut extended_config_store.rules);
136+
builder = builder.with_rules(rules);
137+
builder = builder.and_plugins(extended_config_store.plugins(), true);
136138
}
137139
Err(err) => {
138140
return Err(ConfigBuilderError::InvalidConfigFile {
@@ -878,6 +880,59 @@ mod test {
878880
}
879881
}
880882

883+
#[test]
884+
fn test_extends_plugins() {
885+
let config = config_store_from_str(
886+
r#"
887+
{
888+
"extends": [
889+
"../../apps/oxlint/fixtures/extends_config/plugins/jest.json",
890+
"../../apps/oxlint/fixtures/extends_config/plugins/react.json"
891+
]
892+
}
893+
"#,
894+
);
895+
assert!(config.plugins().contains(LintPlugins::default()));
896+
assert!(config.plugins().contains(LintPlugins::JEST));
897+
assert!(config.plugins().contains(LintPlugins::REACT));
898+
899+
// Test adding more plugins
900+
let config = config_store_from_str(
901+
r#"
902+
{
903+
"extends": [
904+
"../../apps/oxlint/fixtures/extends_config/plugins/jest.json",
905+
"../../apps/oxlint/fixtures/extends_config/plugins/react.json"
906+
],
907+
"plugins": ["typescript"]
908+
}
909+
"#,
910+
);
911+
assert_eq!(
912+
config.plugins(),
913+
LintPlugins::JEST | LintPlugins::REACT | LintPlugins::TYPESCRIPT
914+
);
915+
916+
// Test that extended a config with a plugin is the same as adding it directly
917+
let plugin_config = config_store_from_str(r#"{ "plugins": ["jest", "react"] }"#);
918+
let extends_plugin_config = config_store_from_str(
919+
r#"
920+
{
921+
"extends": [
922+
"../../apps/oxlint/fixtures/extends_config/plugins/jest.json",
923+
"../../apps/oxlint/fixtures/extends_config/plugins/react.json"
924+
],
925+
"plugins": []
926+
}
927+
"#,
928+
);
929+
assert_eq!(
930+
plugin_config.plugins(),
931+
extends_plugin_config.plugins(),
932+
"Extending a config with a plugin is the same as adding it directly"
933+
);
934+
}
935+
881936
fn config_store_from_path(path: &str) -> ConfigStore {
882937
ConfigStoreBuilder::from_oxlintrc(true, Oxlintrc::from_file(&PathBuf::from(path)).unwrap())
883938
.unwrap()

crates/oxc_linter/src/config/config_store.rs

+4
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ impl ConfigStore {
5555
&self.base.base.rules
5656
}
5757

58+
pub fn plugins(&self) -> LintPlugins {
59+
self.base.base.config.plugins
60+
}
61+
5862
pub(crate) fn resolve(&self, path: &Path) -> ResolvedLinterState {
5963
// TODO: based on the `path` provided, resolve the configuration file to use.
6064
let resolved_config = &self.base;

0 commit comments

Comments
 (0)