Skip to content

Commit

Permalink
feat(linter): inherit rules via the extended config files
Browse files Browse the repository at this point in the history
  • Loading branch information
camchenry committed Mar 3, 2025
1 parent 7cab29f commit 63b413f
Show file tree
Hide file tree
Showing 14 changed files with 324 additions and 15 deletions.
1 change: 1 addition & 0 deletions apps/oxlint/fixtures/extends_config/console.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("test");
1 change: 1 addition & 0 deletions apps/oxlint/fixtures/extends_config/empty_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["./invalid_config.json"]
}
3 changes: 3 additions & 0 deletions apps/oxlint/fixtures/extends_config/extends_rules_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["./rules_config.json"]
}
3 changes: 3 additions & 0 deletions apps/oxlint/fixtures/extends_config/invalid_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
invalid
}
7 changes: 7 additions & 0 deletions apps/oxlint/fixtures/extends_config/rules_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"rules": {
"no-debugger": "off",
"no-console": "error",
"unicorn/no-null": "error"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"rules": {
"no-console": "off",
"no-var": "off",
"oxc/approx-constant": "off",
"unicorn/no-null": "off",
"unicorn/no-array-for-each": "off"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"rules": {
"no-console": "error",
"no-var": "error",
"oxc/approx-constant": "error",
"unicorn/no-null": "error",
"unicorn/no-array-for-each": "error"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"rules": {
"no-console": "warn",
"no-var": "warn",
"oxc/approx-constant": "warn",
"unicorn/no-null": "warn",
"unicorn/no-array-for-each": "warn"
}
}
50 changes: 45 additions & 5 deletions apps/oxlint/src/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{

use cow_utils::CowUtils;
use ignore::{gitignore::Gitignore, overrides::OverrideBuilder};
use oxc_diagnostics::{DiagnosticService, GraphicalReportHandler};
use oxc_diagnostics::{DiagnosticService, GraphicalReportHandler, OxcDiagnostic};
use oxc_linter::{
AllowWarnDeny, ConfigStore, ConfigStoreBuilder, InvalidFilterKind, LintFilter, LintOptions,
LintService, LintServiceOptions, Linter, Oxlintrc, loader::LINT_PARTIAL_LOADER_EXT,
Expand Down Expand Up @@ -200,9 +200,28 @@ impl Runner for LintRunner {

// iterate over each config and build the ConfigStore
for (dir, oxlintrc) in nested_oxlintrc {
// TODO(refactor): clean up all of the error handling in this function
let builder = match ConfigStoreBuilder::from_oxlintrc(false, oxlintrc) {
Ok(builder) => builder,
Err(e) => {
let handler = GraphicalReportHandler::new();
let mut err = String::new();
handler
.render_report(&mut err, &OxcDiagnostic::error(e.to_string()))
.unwrap();
stdout
.write_all(
format!("Failed to parse configuration file.\n{err}\n").as_bytes(),
)
.or_else(Self::check_for_writer_error)
.unwrap();
stdout.flush().unwrap();

return CliRunResult::InvalidOptionConfig;
}
}
// TODO(perf): figure out if we can avoid cloning `filter`
let builder =
ConfigStoreBuilder::from_oxlintrc(false, oxlintrc).with_filters(filter.clone());
.with_filters(filter.clone());
match builder.build() {
Ok(config) => nested_configs.insert(dir.to_path_buf(), config),
Err(diagnostic) => {
Expand Down Expand Up @@ -230,8 +249,22 @@ impl Runner for LintRunner {
} else {
None
};
let config_builder =
ConfigStoreBuilder::from_oxlintrc(false, oxlintrc).with_filters(filter);
let config_builder = match ConfigStoreBuilder::from_oxlintrc(false, oxlintrc) {
Ok(builder) => builder,
Err(e) => {
let handler = GraphicalReportHandler::new();
let mut err = String::new();
handler.render_report(&mut err, &OxcDiagnostic::error(e.to_string())).unwrap();
stdout
.write_all(format!("Failed to parse configuration file.\n{err}\n").as_bytes())
.or_else(Self::check_for_writer_error)
.unwrap();
stdout.flush().unwrap();

return CliRunResult::InvalidOptionConfig;
}
}
.with_filters(filter);

if let Some(basic_config_file) = oxlintrc_for_print {
let config_file = config_builder.resolve_final_config_file(basic_config_file);
Expand Down Expand Up @@ -982,4 +1015,11 @@ mod test {
];
Tester::new().with_cwd("fixtures/nested_config".into()).test_and_snapshot(args);
}

#[test]
fn test_extends_explicit_config() {
// Check that referencing a config file that extends other config files works as expected
let args = &["--config", "extends_rules_config.json", "console.js"];
Tester::new().with_cwd("fixtures/extends_config".into()).test_and_snapshot(args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
source: apps/oxlint/src/tester.rs
---
##########
arguments: --config extends_rules_config.json console.js
working directory: fixtures/extends_config
----------

x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-console.html\eslint(no-console)]8;;\: eslint(no-console): Unexpected console statement.
,-[console.js:1:1]
1 | console.log("test");
: ^^^^^^^^^^^
`----
help: Delete this console statement.
Found 0 warnings and 1 error.
Finished in <variable>ms on 1 file with 101 rules using 1 threads.
----------
CLI result: LintFoundErrors
----------
1 change: 1 addition & 0 deletions crates/oxc_language_server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ impl Backend {
let config = Oxlintrc::from_file(&config_path)
.expect("should have initialized linter with new options");
let config_store = ConfigStoreBuilder::from_oxlintrc(true, config.clone())
.expect("failed to build config")
.build()
.expect("failed to build config");
*linter = ServerLinter::new_with_linter(
Expand Down
Loading

0 comments on commit 63b413f

Please sign in to comment.