diff --git a/apps/oxlint/fixtures/report_unused_directives/.oxlintrc-with-rudd.json b/apps/oxlint/fixtures/report_unused_directives/.oxlintrc-with-rudd.json new file mode 100644 index 0000000000000..58647de4d5e63 --- /dev/null +++ b/apps/oxlint/fixtures/report_unused_directives/.oxlintrc-with-rudd.json @@ -0,0 +1,9 @@ +{ + "options": { + "reportUnusedDisableDirectives": "warn" + }, + "rules": { + "no-console": "warn", + "no-debugger": "warn" + } +} diff --git a/apps/oxlint/src-js/package/config.generated.ts b/apps/oxlint/src-js/package/config.generated.ts index 27904512297c4..f3328f62cadf4 100644 --- a/apps/oxlint/src-js/package/config.generated.ts +++ b/apps/oxlint/src-js/package/config.generated.ts @@ -313,7 +313,7 @@ export interface OxlintGlobals { */ export interface OxlintOptions { /** - * Report unused disable directives (e.g. `// eslint-disable-line`). + * Report unused disable directives (e.g. `// oxlint-disable-line` or `// eslint-disable-line`). * * Equivalent to passing `--report-unused-disable-directives-severity` on the CLI. * CLI flags take precedence over this value when both are set. diff --git a/apps/oxlint/src/lint.rs b/apps/oxlint/src/lint.rs index 76672ebdcc992..4b0dc7ea998bc 100644 --- a/apps/oxlint/src/lint.rs +++ b/apps/oxlint/src/lint.rs @@ -343,10 +343,17 @@ impl CliRunner { let config_store = ConfigStore::new(lint_config, nested_configs, external_plugin_store); + // Only propagate Warn/Deny; treat Allow (off) as disabling reports. let report_unused_directives = match inline_config_options.report_unused_directives { ReportUnusedDirectives::WithoutSeverity(true) => Some(AllowWarnDeny::Warn), - ReportUnusedDirectives::WithSeverity(Some(severity)) => Some(severity), - _ => config_store.report_unused_disable_directives(), + ReportUnusedDirectives::WithSeverity(Some(severity)) if severity.is_warn_deny() => { + Some(severity) + } + ReportUnusedDirectives::WithSeverity(Some(_)) => None, + _ => match config_store.report_unused_disable_directives() { + Some(severity) if severity.is_warn_deny() => Some(severity), + _ => None, + }, }; let type_aware = self.options.type_aware || config_store.type_aware_enabled(); let type_check = self.options.type_check || config_store.type_check_enabled(); @@ -1053,6 +1060,26 @@ mod test { Tester::new().with_cwd("fixtures/report_unused_directives".into()).test_and_snapshot(args); } + #[test] + fn test_report_unused_directives_from_config() { + // Verify that `reportUnusedDisableDirectives` in the config file enables reporting + // without needing a CLI flag. + let args = &["-c", ".oxlintrc-with-rudd.json"]; + + Tester::new().with_cwd("fixtures/report_unused_directives".into()).test_and_snapshot(args); + } + + #[test] + fn test_report_unused_directives_cli_overrides_config() { + // Verify that the CLI flag takes precedence over the config file value. + // Config has `reportUnusedDisableDirectives: "warn"`, but CLI passes `off`, + // so no unused-directive diagnostics should be reported. + let args = + &["-c", ".oxlintrc-with-rudd.json", "--report-unused-disable-directives-severity=off"]; + + Tester::new().with_cwd("fixtures/report_unused_directives".into()).test_and_snapshot(args); + } + #[test] fn test_nested_config() { let args = &[]; diff --git a/apps/oxlint/src/snapshots/fixtures__report_unused_directives_-c .oxlintrc-with-rudd.json --report-unused-disable-directives-severity=off@oxlint.snap b/apps/oxlint/src/snapshots/fixtures__report_unused_directives_-c .oxlintrc-with-rudd.json --report-unused-disable-directives-severity=off@oxlint.snap new file mode 100644 index 0000000000000..a6beb55c4e14e --- /dev/null +++ b/apps/oxlint/src/snapshots/fixtures__report_unused_directives_-c .oxlintrc-with-rudd.json --report-unused-disable-directives-severity=off@oxlint.snap @@ -0,0 +1,112 @@ +--- +source: apps/oxlint/src/tester.rs +--- +########## +arguments: -c .oxlintrc-with-rudd.json --report-unused-disable-directives-severity=off +working directory: fixtures/report_unused_directives +---------- + + ! eslint(no-console): Unexpected console statement. + ,-[test-multiple-scripts.vue:7:1] + 6 | // eslint-disable-next-line no-debugger + 7 | console.log('regular script'); + : ^^^^^^^^^^^ + 8 | + `---- + help: Delete this console statement. + + ! eslint(no-debugger): `debugger` statement is not allowed + ,-[test-multiple-scripts.vue:10:1] + 9 | // eslint-disable-next-line no-console + 10 | debugger; + : ^^^^^^^^^ + 11 | + `---- + help: Remove the debugger statement + + ! eslint(no-console): Unexpected console statement. + ,-[test-multiple-scripts.vue:31:1] + 30 | // oxlint-disable-next-line no-debugger, no-for-loop + 31 | console.log("complete line"); + : ^^^^^^^^^^^ + 32 | + `---- + help: Delete this console statement. + + ! eslint(no-debugger): `debugger` statement is not allowed + ,-[test.astro:11:1] + 10 | // eslint-disable-next-line no-console + 11 | debugger; + : ^^^^^^^^^ + 12 | --- + `---- + help: Remove the debugger statement + + ! eslint(no-console): Unexpected console statement. + ,-[test.astro:32:1] + 31 | // oxlint-disable-next-line no-debugger, no-for-loop + 32 | console.log("complete line"); + : ^^^^^^^^^^^ + 33 | + `---- + help: Delete this console statement. + + ! eslint(no-debugger): `debugger` statement is not allowed + ,-[test.js:10:1] + 9 | // eslint-disable-next-line no-console + 10 | debugger; + : ^^^^^^^^^ + 11 | + `---- + help: Remove the debugger statement + + ! eslint(no-console): Unexpected console statement. + ,-[test.js:27:1] + 26 | // oxlint-disable-next-line no-debugger, no-for-loop + 27 | console.log("complete line"); + : ^^^^^^^^^^^ + 28 | + `---- + help: Delete this console statement. + + ! eslint(no-debugger): `debugger` statement is not allowed + ,-[test.svelte:11:1] + 10 | // eslint-disable-next-line no-console + 11 | debugger; + : ^^^^^^^^^ + 12 | + `---- + help: Remove the debugger statement + + ! eslint(no-console): Unexpected console statement. + ,-[test.svelte:28:1] + 27 | // oxlint-disable-next-line no-debugger, no-for-loop + 28 | console.log("complete line"); + : ^^^^^^^^^^^ + 29 | + `---- + help: Delete this console statement. + + ! eslint(no-debugger): `debugger` statement is not allowed + ,-[test.vue:15:1] + 14 | // eslint-disable-next-line no-console + 15 | debugger; + : ^^^^^^^^^ + 16 | + `---- + help: Remove the debugger statement + + ! eslint(no-console): Unexpected console statement. + ,-[test.vue:32:1] + 31 | // oxlint-disable-next-line no-debugger, no-for-loop + 32 | console.log("complete line"); + : ^^^^^^^^^^^ + 33 | + `---- + help: Delete this console statement. + +Found 11 warnings and 0 errors. +Finished in ms on 5 files with 94 rules using 1 threads. +---------- +CLI result: LintSucceeded +---------- diff --git a/apps/oxlint/src/snapshots/fixtures__report_unused_directives_-c .oxlintrc-with-rudd.json@oxlint.snap b/apps/oxlint/src/snapshots/fixtures__report_unused_directives_-c .oxlintrc-with-rudd.json@oxlint.snap new file mode 100644 index 0000000000000..74bafbdac250d --- /dev/null +++ b/apps/oxlint/src/snapshots/fixtures__report_unused_directives_-c .oxlintrc-with-rudd.json@oxlint.snap @@ -0,0 +1,327 @@ +--- +source: apps/oxlint/src/tester.rs +--- +########## +arguments: -c .oxlintrc-with-rudd.json +working directory: fixtures/report_unused_directives +---------- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test-multiple-scripts.vue:6:3] + 5 | + `---- + help: Remove the debugger statement + + ! Unused eslint-disable directive (no problems were reported). + ,-[test-multiple-scripts.vue:17:3] + 16 | + 17 | // eslint-disable-next-line no-unused-vars + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 18 | const unusedVariable2 = 100; + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test-multiple-scripts.vue:30:3] + 29 | + 30 | // oxlint-disable-next-line no-debugger, no-for-loop + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 31 | console.log("complete line"); + `---- + + ! eslint(no-console): Unexpected console statement. + ,-[test-multiple-scripts.vue:31:1] + 30 | // oxlint-disable-next-line no-debugger, no-for-loop + 31 | console.log("complete line"); + : ^^^^^^^^^^^ + 32 | + `---- + help: Delete this console statement. + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.astro:5:3] + 4 | + 5 | // eslint-disable-next-line no-debugger + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 6 | console.log('This is a test'); + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.astro:10:3] + 9 | + 10 | // eslint-disable-next-line no-console + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 11 | debugger; + `---- + + ! eslint(no-debugger): `debugger` statement is not allowed + ,-[test.astro:11:1] + 10 | // eslint-disable-next-line no-console + 11 | debugger; + : ^^^^^^^^^ + 12 | --- + `---- + help: Remove the debugger statement + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.astro:17:3] + 16 | + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.js:4:3] + 3 | + 4 | // eslint-disable-next-line no-debugger + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 5 | console.log('This is a test'); + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.js:9:3] + 8 | + 9 | // eslint-disable-next-line no-console + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 10 | debugger; + `---- + + ! eslint(no-debugger): `debugger` statement is not allowed + ,-[test.js:10:1] + 9 | // eslint-disable-next-line no-console + 10 | debugger; + : ^^^^^^^^^ + 11 | + `---- + help: Remove the debugger statement + + ! Unused eslint-disable directive (no problems were reported from no-debugger). + ,-[test.js:23:41] + 22 | + 23 | // eslint-disable-next-line no-console, no-debugger + : ^^^^^^^^^^^ + 24 | console.log('no'); + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.js:26:3] + 25 | + 26 | // oxlint-disable-next-line no-debugger, no-for-loop + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 27 | console.log("complete line"); + `---- + + ! eslint(no-console): Unexpected console statement. + ,-[test.js:27:1] + 26 | // oxlint-disable-next-line no-debugger, no-for-loop + 27 | console.log("complete line"); + : ^^^^^^^^^^^ + 28 | + `---- + help: Delete this console statement. + + ! Unused eslint-enable directive (no matching eslint-disable directives were found). + ,-[test.js:31:3] + 30 | + 31 | // eslint-enable + : ^^^^^^^^^^^^^^ + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.svelte:5:3] + 4 | + 5 | // eslint-disable-next-line no-debugger + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 6 | console.log('This is a test'); + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.svelte:10:3] + 9 | + 10 | // eslint-disable-next-line no-console + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 11 | debugger; + `---- + + ! eslint(no-debugger): `debugger` statement is not allowed + ,-[test.svelte:11:1] + 10 | // eslint-disable-next-line no-console + 11 | debugger; + : ^^^^^^^^^ + 12 | + `---- + help: Remove the debugger statement + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.svelte:13:3] + 12 | + 13 | // eslint-disable-next-line no-unused-vars + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 14 | const unusedVariable2 = 100; + `---- + + ! Unused eslint-disable directive (no problems were reported from no-debugger). + ,-[test.svelte:24:41] + 23 | + 24 | // eslint-disable-next-line no-console, no-debugger + : ^^^^^^^^^^^ + 25 | console.log('no'); + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.svelte:27:3] + 26 | + 27 | // oxlint-disable-next-line no-debugger, no-for-loop + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 28 | console.log("complete line"); + `---- + + ! eslint(no-console): Unexpected console statement. + ,-[test.svelte:28:1] + 27 | // oxlint-disable-next-line no-debugger, no-for-loop + 28 | console.log("complete line"); + : ^^^^^^^^^^^ + 29 | + `---- + help: Delete this console statement. + + ! Unused eslint-enable directive (no matching eslint-disable directives were found). + ,-[test.svelte:32:3] + 31 | + 32 | // eslint-enable + : ^^^^^^^^^^^^^^ + 33 | + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.vue:9:3] + 8 | + 9 | // eslint-disable-next-line no-debugger + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 10 | console.log('This is a test'); + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.vue:14:3] + 13 | + 14 | // eslint-disable-next-line no-console + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 15 | debugger; + `---- + + ! eslint(no-debugger): `debugger` statement is not allowed + ,-[test.vue:15:1] + 14 | // eslint-disable-next-line no-console + 15 | debugger; + : ^^^^^^^^^ + 16 | + `---- + help: Remove the debugger statement + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.vue:17:3] + 16 | + 17 | // eslint-disable-next-line no-unused-vars + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 18 | const unusedVariable2 = 100; + `---- + + ! Unused eslint-disable directive (no problems were reported from no-debugger). + ,-[test.vue:28:41] + 27 | + 28 | // eslint-disable-next-line no-console, no-debugger + : ^^^^^^^^^^^ + 29 | console.log('no'); + `---- + + ! Unused eslint-disable directive (no problems were reported). + ,-[test.vue:31:3] + 30 | + 31 | // oxlint-disable-next-line no-debugger, no-for-loop + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 32 | console.log("complete line"); + `---- + + ! eslint(no-console): Unexpected console statement. + ,-[test.vue:32:1] + 31 | // oxlint-disable-next-line no-debugger, no-for-loop + 32 | console.log("complete line"); + : ^^^^^^^^^^^ + 33 | + `---- + help: Delete this console statement. + + ! Unused eslint-enable directive (no matching eslint-disable directives were found). + ,-[test.vue:36:3] + 35 | + 36 | // eslint-enable + : ^^^^^^^^^^^^^^ + 37 | + `---- + +Found 38 warnings and 0 errors. +Finished in ms on 5 files with 94 rules using 1 threads. +---------- +CLI result: LintSucceeded +---------- diff --git a/crates/oxc_linter/src/config/oxlintrc.rs b/crates/oxc_linter/src/config/oxlintrc.rs index c8fd314dabc28..7a2bf57cdfd31 100644 --- a/crates/oxc_linter/src/config/oxlintrc.rs +++ b/crates/oxc_linter/src/config/oxlintrc.rs @@ -36,7 +36,7 @@ pub struct OxlintOptions { /// Equivalent to passing `--type-check` on the CLI. #[serde(skip_serializing_if = "Option::is_none")] pub type_check: Option, - /// Report unused disable directives (e.g. `// eslint-disable-line`). + /// Report unused disable directives (e.g. `// oxlint-disable-line` or `// eslint-disable-line`). /// /// Equivalent to passing `--report-unused-disable-directives-severity` on the CLI. /// CLI flags take precedence over this value when both are set. diff --git a/npm/oxlint/configuration_schema.json b/npm/oxlint/configuration_schema.json index 887b229ca26d2..60f6186ed1437 100644 --- a/npm/oxlint/configuration_schema.json +++ b/npm/oxlint/configuration_schema.json @@ -495,7 +495,7 @@ "type": "object", "properties": { "reportUnusedDisableDirectives": { - "description": "Report unused disable directives (e.g. `// eslint-disable-line`).\n\nEquivalent to passing `--report-unused-disable-directives-severity` on the CLI.\nCLI flags take precedence over this value when both are set.\nOnly supported in the root configuration file.", + "description": "Report unused disable directives (e.g. `// oxlint-disable-line` or `// eslint-disable-line`).\n\nEquivalent to passing `--report-unused-disable-directives-severity` on the CLI.\nCLI flags take precedence over this value when both are set.\nOnly supported in the root configuration file.", "anyOf": [ { "$ref": "#/definitions/AllowWarnDeny" @@ -504,7 +504,7 @@ "type": "null" } ], - "markdownDescription": "Report unused disable directives (e.g. `// eslint-disable-line`).\n\nEquivalent to passing `--report-unused-disable-directives-severity` on the CLI.\nCLI flags take precedence over this value when both are set.\nOnly supported in the root configuration file." + "markdownDescription": "Report unused disable directives (e.g. `// oxlint-disable-line` or `// eslint-disable-line`).\n\nEquivalent to passing `--report-unused-disable-directives-severity` on the CLI.\nCLI flags take precedence over this value when both are set.\nOnly supported in the root configuration file." }, "typeAware": { "description": "Enable rules that require type information.\n\nEquivalent to passing `--type-aware` on the CLI.", diff --git a/tasks/website_linter/src/snapshots/schema_json.snap b/tasks/website_linter/src/snapshots/schema_json.snap index 3020c5b70f56d..68e252d29df81 100644 --- a/tasks/website_linter/src/snapshots/schema_json.snap +++ b/tasks/website_linter/src/snapshots/schema_json.snap @@ -499,7 +499,7 @@ expression: json "type": "object", "properties": { "reportUnusedDisableDirectives": { - "description": "Report unused disable directives (e.g. `// eslint-disable-line`).\n\nEquivalent to passing `--report-unused-disable-directives-severity` on the CLI.\nCLI flags take precedence over this value when both are set.\nOnly supported in the root configuration file.", + "description": "Report unused disable directives (e.g. `// oxlint-disable-line` or `// eslint-disable-line`).\n\nEquivalent to passing `--report-unused-disable-directives-severity` on the CLI.\nCLI flags take precedence over this value when both are set.\nOnly supported in the root configuration file.", "anyOf": [ { "$ref": "#/definitions/AllowWarnDeny" @@ -508,7 +508,7 @@ expression: json "type": "null" } ], - "markdownDescription": "Report unused disable directives (e.g. `// eslint-disable-line`).\n\nEquivalent to passing `--report-unused-disable-directives-severity` on the CLI.\nCLI flags take precedence over this value when both are set.\nOnly supported in the root configuration file." + "markdownDescription": "Report unused disable directives (e.g. `// oxlint-disable-line` or `// eslint-disable-line`).\n\nEquivalent to passing `--report-unused-disable-directives-severity` on the CLI.\nCLI flags take precedence over this value when both are set.\nOnly supported in the root configuration file." }, "typeAware": { "description": "Enable rules that require type information.\n\nEquivalent to passing `--type-aware` on the CLI.", diff --git a/tasks/website_linter/src/snapshots/schema_markdown.snap b/tasks/website_linter/src/snapshots/schema_markdown.snap index 71c0b7bf41959..d49a8946cb9e3 100644 --- a/tasks/website_linter/src/snapshots/schema_markdown.snap +++ b/tasks/website_linter/src/snapshots/schema_markdown.snap @@ -308,7 +308,7 @@ Options for the linter. -Report unused disable directives (e.g. `// eslint-disable-line`). +Report unused disable directives (e.g. `// oxlint-disable-line` or `// eslint-disable-line`). Equivalent to passing `--report-unused-disable-directives-severity` on the CLI. CLI flags take precedence over this value when both are set.