diff --git a/apps/oxlint/fixtures/exhaustive_deps_disable_directive_issue_13311/.oxlintrc.json b/apps/oxlint/fixtures/exhaustive_deps_disable_directive_issue_13311/.oxlintrc.json new file mode 100644 index 0000000000000..ebb97dbdd8791 --- /dev/null +++ b/apps/oxlint/fixtures/exhaustive_deps_disable_directive_issue_13311/.oxlintrc.json @@ -0,0 +1,9 @@ +{ + "plugins": ["react"], + "categories": { + "correctness": "off" + }, + "rules": { + "react/exhaustive-deps": "warn" + } +} \ No newline at end of file diff --git a/apps/oxlint/fixtures/exhaustive_deps_disable_directive_issue_13311/test.jsx b/apps/oxlint/fixtures/exhaustive_deps_disable_directive_issue_13311/test.jsx new file mode 100644 index 0000000000000..1161547bd4db6 --- /dev/null +++ b/apps/oxlint/fixtures/exhaustive_deps_disable_directive_issue_13311/test.jsx @@ -0,0 +1,13 @@ +import React, { useEffect } from 'react'; + +function Component() { + const emit = (event) => console.log(event); + const EVENTS = { CLEAR: 'clear' }; + + useEffect(() => { + emit(EVENTS.CLEAR); + // oxlint-disable-next-line exhaustive-deps + }, []); + + return null; +} \ No newline at end of file diff --git a/apps/oxlint/src/lint.rs b/apps/oxlint/src/lint.rs index db0c318a2e66c..40f41f25bfa7f 100644 --- a/apps/oxlint/src/lint.rs +++ b/apps/oxlint/src/lint.rs @@ -1251,6 +1251,17 @@ mod test { Tester::new().with_cwd("fixtures/dot_folder".into()).test_and_snapshot(&[]); } + #[test] + fn test_exhaustive_deps_disable_directive_issue_13311() { + // Test that exhaustive-deps diagnostics are reported at the dependency array + // so that disable directives work correctly + // Issue: https://github.com/oxc-project/oxc/issues/13311 + let args = &["test.jsx"]; + Tester::new() + .with_cwd("fixtures/exhaustive_deps_disable_directive_issue_13311".into()) + .test_and_snapshot(args); + } + // ToDo: `tsgolint` does not support `big-endian`? #[test] #[cfg(not(target_endian = "big"))] diff --git a/apps/oxlint/src/snapshots/fixtures__exhaustive_deps_disable_directive_issue_13311_test.jsx@oxlint.snap b/apps/oxlint/src/snapshots/fixtures__exhaustive_deps_disable_directive_issue_13311_test.jsx@oxlint.snap new file mode 100644 index 0000000000000..f7ac5d3d86675 --- /dev/null +++ b/apps/oxlint/src/snapshots/fixtures__exhaustive_deps_disable_directive_issue_13311_test.jsx@oxlint.snap @@ -0,0 +1,12 @@ +--- +source: apps/oxlint/src/tester.rs +--- +########## +arguments: test.jsx +working directory: fixtures/exhaustive_deps_disable_directive_issue_13311 +---------- +Found 0 warnings and 0 errors. +Finished in ms on 1 file using 1 threads. +---------- +CLI result: LintSucceeded +---------- diff --git a/crates/oxc_linter/src/fixer/mod.rs b/crates/oxc_linter/src/fixer/mod.rs index 8b934a9565d8c..82f6c1f845a28 100644 --- a/crates/oxc_linter/src/fixer/mod.rs +++ b/crates/oxc_linter/src/fixer/mod.rs @@ -242,20 +242,14 @@ impl<'new> CloneIn<'new> for Message<'_> { impl<'a> Message<'a> { #[expect(clippy::cast_possible_truncation)] // for `as u32` pub fn new(error: OxcDiagnostic, fixes: PossibleFixes<'a>) -> Self { - let (start, end) = if let Some(labels) = &error.labels { - let start = labels - .iter() - .min_by_key(|span| span.offset()) - .map_or(0, |span| span.offset() as u32); - let end = labels - .iter() - .max_by_key(|span| span.offset() + span.len()) - .map_or(0, |span| (span.offset() + span.len()) as u32); - (start, end) - } else { - (0, 0) - }; - Self { error, span: Span::new(start, end), fixes, fixed: false } + let span = error + .labels + .as_ref() + .and_then(|labels| labels.iter().find(|span| span.primary()).or_else(|| labels.first())) + .map(|span| Span::new(span.offset() as u32, (span.offset() + span.len()) as u32)) + .unwrap_or_default(); + + Self { error, span, fixes, fixed: false } } /// move the offset of all spans to the right