Skip to content

Commit a607119

Browse files
committed
feat(linter): introduce maxWarnings config option (#19777)
1 parent ea11028 commit a607119

File tree

17 files changed

+259
-15
lines changed

17 files changed

+259
-15
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"rules": {
3+
"no-debugger": "warn"
4+
},
5+
"options": {
6+
"maxWarnings": 0
7+
}
8+
}

apps/oxlint/src-js/package/config.generated.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,12 @@ export interface OxlintOptions {
324324
* Equivalent to passing `--type-check` on the CLI.
325325
*/
326326
typeCheck?: boolean | null;
327+
/**
328+
* Specify a warning threshold. Exits with an error status if warnings exceed this value.
329+
*
330+
* Equivalent to passing `--max-warnings` on the CLI.
331+
*/
332+
maxWarnings?: number | null;
327333
}
328334
export interface OxlintOverride {
329335
/**

apps/oxlint/src/config_loader.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,12 @@ impl<'a> ConfigLoader<'a> {
387387
.push(ConfigLoadError::Diagnostic(nested_type_check_not_supported(&path)));
388388
continue;
389389
}
390+
if builder.max_warnings().is_some() {
391+
errors.push(ConfigLoadError::Diagnostic(nested_max_warnings_not_supported(
392+
&path,
393+
)));
394+
continue;
395+
}
390396
}
391397

392398
let extended_paths = builder.extended_paths.clone();
@@ -649,6 +655,14 @@ fn nested_type_check_not_supported(path: &Path) -> OxcDiagnostic {
649655
.with_help("Move `options.typeCheck` to the root configuration file.")
650656
}
651657

658+
fn nested_max_warnings_not_supported(path: &Path) -> OxcDiagnostic {
659+
OxcDiagnostic::error(format!(
660+
"The `options.maxWarnings` option is only supported in the root config, but it was found in {}.",
661+
path.display()
662+
))
663+
.with_help("Move `options.maxWarnings` to the root configuration file.")
664+
}
665+
652666
#[cfg(test)]
653667
mod test {
654668
use std::path::{Path, PathBuf};

apps/oxlint/src/lint.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -338,17 +338,22 @@ impl CliRunner {
338338
let mut options =
339339
LintServiceOptions::new(self.cwd.clone()).with_cross_module(use_cross_module);
340340

341+
let config_store = ConfigStore::new(lint_config, nested_configs, external_plugin_store);
342+
let type_aware = self.options.type_aware || config_store.type_aware_enabled();
343+
let type_check = self.options.type_check || config_store.type_check_enabled();
344+
let max_warnings = warning_options.max_warnings.or(config_store.max_warnings());
345+
341346
let report_unused_directives = match inline_config_options.report_unused_directives {
342347
ReportUnusedDirectives::WithoutSeverity(true) => Some(AllowWarnDeny::Warn),
343348
ReportUnusedDirectives::WithSeverity(Some(severity)) => Some(severity),
344349
_ => None,
345350
};
346-
let (mut diagnostic_service, tx_error) =
347-
Self::get_diagnostic_service(&output_formatter, &warning_options, &misc_options);
348-
349-
let config_store = ConfigStore::new(lint_config, nested_configs, external_plugin_store);
350-
let type_aware = self.options.type_aware || config_store.type_aware_enabled();
351-
let type_check = self.options.type_check || config_store.type_check_enabled();
351+
let (mut diagnostic_service, tx_error) = Self::get_diagnostic_service(
352+
&output_formatter,
353+
&warning_options,
354+
&misc_options,
355+
max_warnings,
356+
);
352357

353358
// Send JS plugins config to JS side
354359
if let Some(external_linter) = &external_linter {
@@ -466,13 +471,14 @@ impl CliRunner {
466471
reporter: &OutputFormatter,
467472
warning_options: &WarningOptions,
468473
misc_options: &MiscOptions,
474+
max_warnings: Option<usize>,
469475
) -> (DiagnosticService, DiagnosticSender) {
470476
let (service, sender) = DiagnosticService::new(reporter.get_diagnostic_reporter());
471477
(
472478
service
473479
.with_quiet(warning_options.quiet)
474480
.with_silent(misc_options.silent)
475-
.with_max_warnings(warning_options.max_warnings),
481+
.with_max_warnings(max_warnings),
476482
sender,
477483
)
478484
}
@@ -1311,6 +1317,18 @@ mod test {
13111317
Tester::new().with_cwd("fixtures/tsgolint_type_error".into()).test_and_snapshot(args);
13121318
}
13131319

1320+
#[test]
1321+
fn test_max_warnings_via_config_file() {
1322+
let args = &["-c", "config-max-warnings.json", "debugger.js"];
1323+
Tester::new().with_cwd("fixtures/linter".into()).test_and_snapshot(args);
1324+
}
1325+
1326+
#[test]
1327+
fn test_max_warnings_overridden_by_cli_flag() {
1328+
let args = &["--max-warnings", "1", "-c", "config-max-warnings.json", "debugger.js"];
1329+
Tester::new().with_cwd("fixtures/linter".into()).test_and_snapshot(args);
1330+
}
1331+
13141332
#[test]
13151333
#[cfg(not(target_endian = "big"))]
13161334
fn test_tsgolint_no_typescript_files() {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
source: apps/oxlint/src/tester.rs
3+
assertion_line: 134
4+
---
5+
##########
6+
arguments: --max-warnings 1 -c config-max-warnings.json debugger.js
7+
working directory: fixtures/linter
8+
----------
9+
10+
! eslint(no-debugger): `debugger` statement is not allowed
11+
,-[debugger.js:1:1]
12+
1 | debugger;
13+
: ^^^^^^^^^
14+
`----
15+
help: Remove the debugger statement
16+
17+
Found 1 warning and 0 errors.
18+
Finished in <variable>ms on 1 file with 93 rules using 1 threads.
19+
----------
20+
CLI result: LintSucceeded
21+
----------
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
source: apps/oxlint/src/tester.rs
3+
assertion_line: 134
4+
---
5+
##########
6+
arguments: -c config-max-warnings.json debugger.js
7+
working directory: fixtures/linter
8+
----------
9+
10+
! eslint(no-debugger): `debugger` statement is not allowed
11+
,-[debugger.js:1:1]
12+
1 | debugger;
13+
: ^^^^^^^^^
14+
`----
15+
help: Remove the debugger statement
16+
17+
Found 1 warning and 0 errors.
18+
Exceeded maximum number of warnings. Found 1.
19+
Finished in <variable>ms on 1 file with 93 rules using 1 threads.
20+
----------
21+
CLI result: LintMaxWarningsExceeded
22+
----------
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
debugger;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Exit code
2+
1
3+
4+
# stdout
5+
```
6+
! eslint(no-debugger): `debugger` statement is not allowed
7+
,-[files/test.js:1:1]
8+
1 | debugger;
9+
: ^^^^^^^^^
10+
`----
11+
help: Remove the debugger statement
12+
13+
Found 1 warning and 0 errors.
14+
Exceeded maximum number of warnings. Found 1.
15+
Finished in Xms on 1 file with 1 rules using X threads.
16+
```
17+
18+
# stderr
19+
```
20+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { defineConfig } from "#oxlint";
2+
3+
const warningLimit = 0;
4+
const options = {
5+
maxWarnings: warningLimit,
6+
};
7+
8+
export default defineConfig({
9+
categories: { correctness: "off" },
10+
rules: {
11+
"no-debugger": "warn",
12+
},
13+
options,
14+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"options": {
3+
"maxWarnings": 0
4+
}
5+
}

0 commit comments

Comments
 (0)