diff --git a/apps/oxlint/fixtures/linter/fix.js b/apps/oxlint/fixtures/fix_argument/fix.js similarity index 100% rename from apps/oxlint/fixtures/linter/fix.js rename to apps/oxlint/fixtures/fix_argument/fix.js diff --git a/apps/oxlint/fixtures/fix_argument/fix.vue b/apps/oxlint/fixtures/fix_argument/fix.vue new file mode 100644 index 0000000000000..ec977d8304df0 --- /dev/null +++ b/apps/oxlint/fixtures/fix_argument/fix.vue @@ -0,0 +1,2 @@ + + diff --git a/apps/oxlint/src/lint.rs b/apps/oxlint/src/lint.rs index bbba5b5f9e31c..53bf04e3e2c00 100644 --- a/apps/oxlint/src/lint.rs +++ b/apps/oxlint/src/lint.rs @@ -863,7 +863,12 @@ mod test { #[test] fn test_fix() { - Tester::test_fix("fixtures/linter/fix.js", "debugger\n", "\n"); + Tester::test_fix("fixtures/fix_argument/fix.js", "debugger\n", "\n"); + Tester::test_fix( + "fixtures/fix_argument/fix.vue", + "\n\n", + "\n\n", + ); } #[test] diff --git a/apps/oxlint/src/snapshots/_-A all fixtures__linter@oxlint.snap b/apps/oxlint/src/snapshots/_-A all fixtures__linter@oxlint.snap index 5b9d90b549c4c..fe6cd3391cc4d 100644 --- a/apps/oxlint/src/snapshots/_-A all fixtures__linter@oxlint.snap +++ b/apps/oxlint/src/snapshots/_-A all fixtures__linter@oxlint.snap @@ -6,7 +6,7 @@ arguments: -A all fixtures/linter working directory: ---------- Found 0 warnings and 0 errors. -Finished in ms on 4 files with 0 rules using 1 threads. +Finished in ms on 3 files with 0 rules using 1 threads. ---------- CLI result: LintSucceeded ---------- diff --git a/apps/oxlint/src/snapshots/_fixtures__linter@oxlint.snap b/apps/oxlint/src/snapshots/_fixtures__linter@oxlint.snap index ff3b945fc4ac7..0c7f9e08250ba 100644 --- a/apps/oxlint/src/snapshots/_fixtures__linter@oxlint.snap +++ b/apps/oxlint/src/snapshots/_fixtures__linter@oxlint.snap @@ -13,13 +13,6 @@ working directory: `---- help: Remove the debugger statement - ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-debugger.html\eslint(no-debugger)]8;;\: `debugger` statement is not allowed - ,-[fixtures/linter/fix.js:1:1] - 1 | debugger - : ^^^^^^^^ - `---- - help: Remove the debugger statement - ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-debugger.html\eslint(no-debugger)]8;;\: `debugger` statement is not allowed ,-[fixtures/linter/js_as_jsx.js:1:1] 1 | debugger; @@ -35,8 +28,8 @@ working directory: `---- help: Use the isNaN function to compare with NaN. -Found 4 warnings and 0 errors. -Finished in ms on 4 files with 87 rules using 1 threads. +Found 3 warnings and 0 errors. +Finished in ms on 3 files with 87 rules 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 c02dc496d6351..d78151251d29d 100644 --- a/crates/oxc_linter/src/fixer/mod.rs +++ b/crates/oxc_linter/src/fixer/mod.rs @@ -292,11 +292,10 @@ impl<'a> Message<'a> { Self { error, span: Span::new(start, end), fixes, fixed: false } } - /// move the offset of all spans to the right + /// move the offset of all spans (except fixes) to the right + /// for moving fixes use [`Message::move_fix_offset`]. pub fn move_offset(&mut self, offset: u32) -> &mut Self { - if offset == 0 { - return self; - } + debug_assert!(offset != 0); self.span = self.span.move_right(offset); @@ -306,6 +305,12 @@ impl<'a> Message<'a> { } } + self + } + + pub fn move_fix_offset(&mut self, offset: u32) -> &mut Self { + debug_assert!(offset != 0); + match &mut self.fixes { PossibleFixes::None => {} PossibleFixes::Single(fix) => { diff --git a/crates/oxc_linter/src/service/runtime.rs b/crates/oxc_linter/src/service/runtime.rs index a0c17efaca7c0..7a886e467b909 100644 --- a/crates/oxc_linter/src/service/runtime.rs +++ b/crates/oxc_linter/src/service/runtime.rs @@ -494,7 +494,7 @@ impl Runtime { // clippy: the source field is checked and assumed to be less than 4GB, and // we assume that the fix offset will not exceed 2GB in either direction - #[expect(clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_sign_loss)] + #[expect(clippy::cast_possible_truncation, clippy::cast_possible_wrap)] pub(super) fn run(&mut self, tx_error: &DiagnosticSender) { rayon::scope(|scope| { self.resolve_modules(scope, true, tx_error, |me, mut module_to_lint| { @@ -544,7 +544,8 @@ impl Runtime { let fix_result = Fixer::new(source_text, messages).fix(); if fix_result.fixed { // write to file, replacing only the changed part - let start = fix_offset as usize; + let start = + section.source.start.saturating_add_signed(fix_offset) as usize; let end = start + source_text.len(); new_source_text .to_mut() @@ -646,7 +647,9 @@ impl Runtime { // adjust offset for multiple source text in a single file if section.source.start != 0 { for message in &mut section_messages { - message.move_offset(section.source.start); + message + .move_offset(section.source.start) + .move_fix_offset(section.source.start); } } @@ -773,7 +776,8 @@ impl Runtime { .into_iter() .map(|mut message| { if section.source.start != 0 { - message.move_offset(section.source.start); + message.move_offset(section.source.start) + .move_fix_offset(section.source.start); } message.clone_in(allocator) }),