diff --git a/crates/oxc_linter/src/fixer.rs b/crates/oxc_linter/src/fixer.rs index 03ff13b92..d80cd060d 100644 --- a/crates/oxc_linter/src/fixer.rs +++ b/crates/oxc_linter/src/fixer.rs @@ -19,14 +19,12 @@ impl<'a> Fix<'a> { } } -#[derive(Debug)] pub struct FixResult<'a> { pub fixed: bool, pub fixed_code: Cow<'a, str>, pub messages: Vec>, } -#[derive(Debug)] pub struct Message<'a> { pub error: Error, start: u32, @@ -108,7 +106,7 @@ impl<'a> Fixer<'a> { let mut messages = self.messages.into_iter().filter(|m| !m.fixed).collect::>(); messages.sort_by_key(|m| (m.start, m.end)); - return FixResult { fixed, fixed_code: Cow::Owned(output), messages }; + FixResult { fixed, fixed_code: Cow::Owned(output), messages } } } @@ -116,103 +114,101 @@ impl<'a> Fixer<'a> { mod test { use std::borrow::Cow; - use oxc_diagnostics::{ - miette::{self, Diagnostic}, - thiserror::Error, - Error, - }; + use oxc_diagnostics::{Error, OxcDiagnostic}; use oxc_span::Span; use super::{Fix, FixResult, Fixer, Message}; + fn insert_at_end() -> OxcDiagnostic { + OxcDiagnostic::warning("End") + } + + fn insert_at_start() -> OxcDiagnostic { + OxcDiagnostic::warning("Start") + } + + fn insert_at_middle() -> OxcDiagnostic { + OxcDiagnostic::warning("Multiply") + } + + fn replace_id() -> OxcDiagnostic { + OxcDiagnostic::warning("foo") + } + + fn replace_var() -> OxcDiagnostic { + OxcDiagnostic::warning("let") + } + + fn replace_num() -> OxcDiagnostic { + OxcDiagnostic::warning("5") + } + + fn remove_start() -> OxcDiagnostic { + OxcDiagnostic::warning("removestart") + } + + fn remove_middle(span0: Span) -> OxcDiagnostic { + OxcDiagnostic::warning("removemiddle").with_labels([span0.into()]) + } + + fn remove_end() -> OxcDiagnostic { + OxcDiagnostic::warning("removeend") + } + + fn reverse_range() -> OxcDiagnostic { + OxcDiagnostic::warning("reversed range") + } + + fn no_fix(span0: Span) -> OxcDiagnostic { + OxcDiagnostic::warning("nofix").with_labels([span0.into()]) + } + + fn no_fix_1(span0: Span) -> OxcDiagnostic { + OxcDiagnostic::warning("nofix1").with_labels([span0.into()]) + } + + fn no_fix_2(span0: Span) -> OxcDiagnostic { + OxcDiagnostic::warning("nofix2").with_labels([span0.into()]) + } + const TEST_CODE: &str = "var answer = 6 * 7;"; - - #[derive(Debug, Error, Diagnostic)] - #[error("End")] - struct InsertAtEnd; const INSERT_AT_END: Fix = Fix { span: Span::new(19, 19), content: Cow::Borrowed("// end") }; - - #[derive(Debug, Error, Diagnostic)] - #[error("Start")] - struct InsertAtStart; const INSERT_AT_START: Fix = Fix { span: Span::new(0, 0), content: Cow::Borrowed("// start") }; - - #[derive(Debug, Error, Diagnostic)] - #[error("Multiply")] - struct InsertAtMiddle; const INSERT_AT_MIDDLE: Fix = Fix { span: Span::new(13, 13), content: Cow::Borrowed("5 *") }; - - #[derive(Debug, Error, Diagnostic)] - #[error("foo")] - struct ReplaceId; const REPLACE_ID: Fix = Fix { span: Span::new(4, 10), content: Cow::Borrowed("foo") }; - #[derive(Debug, Error, Diagnostic)] - #[error("let")] - struct ReplaceVar; const REPLACE_VAR: Fix = Fix { span: Span::new(0, 3), content: Cow::Borrowed("let") }; - - #[derive(Debug, Error, Diagnostic)] - #[error("5")] - struct ReplaceNum; const REPLACE_NUM: Fix = Fix { span: Span::new(13, 14), content: Cow::Borrowed("5") }; - - #[derive(Debug, Error, Diagnostic)] - #[error("removestart")] - struct RemoveStart; const REMOVE_START: Fix = Fix::delete(Span::new(0, 4)); - - #[derive(Debug, Error, Diagnostic)] - #[error("removemiddle")] - struct RemoveMiddle(#[label] pub Span); const REMOVE_MIDDLE: Fix = Fix::delete(Span::new(5, 10)); - - #[derive(Debug, Error, Diagnostic)] - #[error("removeend")] - struct RemoveEnd; const REMOVE_END: Fix = Fix::delete(Span::new(14, 18)); - - #[derive(Debug, Error, Diagnostic)] - #[error("reversed range")] - struct ReverseRange; const REVERSE_RANGE: Fix = Fix { span: Span::new(3, 0), content: Cow::Borrowed(" ") }; - #[derive(Debug, Error, Diagnostic)] - #[error("nofix")] - struct NoFix(#[label] pub Span); - - #[derive(Debug, Error, Diagnostic)] - #[error("nofix1")] - struct NoFix1(#[label] pub Span); - - #[derive(Debug, Error, Diagnostic)] - #[error("nofix2")] - struct NoFix2(#[label] pub Span); - fn get_fix_result(messages: Vec) -> FixResult { Fixer::new(TEST_CODE, messages).fix() } - fn create_message>(error: T, fix: Option) -> Message { - Message::new(error.into(), fix) + fn create_message(error: OxcDiagnostic, fix: Option) -> Message { + Message::new(Error::from(error), fix) } #[test] fn insert_at_the_end() { - let result = get_fix_result(vec![create_message(InsertAtEnd, Some(INSERT_AT_END))]); + let result = get_fix_result(vec![create_message(insert_at_end(), Some(INSERT_AT_END))]); assert_eq!(result.fixed_code, TEST_CODE.to_string() + INSERT_AT_END.content.as_ref()); assert_eq!(result.messages.len(), 0); } #[test] fn insert_at_the_start() { - let result = get_fix_result(vec![create_message(InsertAtStart, Some(INSERT_AT_START))]); + let result = get_fix_result(vec![create_message(insert_at_start(), Some(INSERT_AT_START))]); assert_eq!(result.fixed_code, INSERT_AT_START.content.to_string() + TEST_CODE); assert_eq!(result.messages.len(), 0); } #[test] fn insert_at_the_middle() { - let result = get_fix_result(vec![create_message(InsertAtMiddle, Some(INSERT_AT_MIDDLE))]); + let result = + get_fix_result(vec![create_message(insert_at_middle(), Some(INSERT_AT_MIDDLE))]); assert_eq!( result.fixed_code, TEST_CODE.replace("6 *", &format!("{}{}", INSERT_AT_MIDDLE.content, "6 *")) @@ -223,9 +219,9 @@ mod test { #[test] fn insert_at_the_start_middle_end() { let messages = vec![ - create_message(InsertAtMiddle, Some(INSERT_AT_MIDDLE)), - create_message(InsertAtStart, Some(INSERT_AT_START)), - create_message(InsertAtEnd, Some(INSERT_AT_END)), + create_message(insert_at_middle(), Some(INSERT_AT_MIDDLE)), + create_message(insert_at_start(), Some(INSERT_AT_START)), + create_message(insert_at_end(), Some(INSERT_AT_END)), ]; let result = get_fix_result(messages); assert_eq!( @@ -242,13 +238,13 @@ mod test { #[test] fn ignore_reverse_range() { - let result = get_fix_result(vec![create_message(ReverseRange, Some(REVERSE_RANGE))]); + let result = get_fix_result(vec![create_message(reverse_range(), Some(REVERSE_RANGE))]); assert_eq!(result.fixed_code, TEST_CODE); } #[test] fn replace_at_the_start() { - let result = get_fix_result(vec![create_message(ReplaceVar, Some(REPLACE_VAR))]); + let result = get_fix_result(vec![create_message(replace_var(), Some(REPLACE_VAR))]); assert_eq!(result.fixed_code, TEST_CODE.replace("var", "let")); assert_eq!(result.messages.len(), 0); assert!(result.fixed); @@ -256,7 +252,7 @@ mod test { #[test] fn replace_at_the_middle() { - let result = get_fix_result(vec![create_message(ReplaceId, Some(REPLACE_ID))]); + let result = get_fix_result(vec![create_message(replace_id(), Some(REPLACE_ID))]); assert_eq!(result.fixed_code, TEST_CODE.replace("answer", "foo")); assert_eq!(result.messages.len(), 0); assert!(result.fixed); @@ -264,7 +260,7 @@ mod test { #[test] fn replace_at_the_end() { - let result = get_fix_result(vec![create_message(ReplaceNum, Some(REPLACE_NUM))]); + let result = get_fix_result(vec![create_message(replace_num(), Some(REPLACE_NUM))]); assert_eq!(result.fixed_code, TEST_CODE.replace('6', "5")); assert_eq!(result.messages.len(), 0); assert!(result.fixed); @@ -273,9 +269,9 @@ mod test { #[test] fn replace_at_the_start_middle_end() { let messages = vec![ - create_message(ReplaceId, Some(REPLACE_ID)), - create_message(ReplaceVar, Some(REPLACE_VAR)), - create_message(ReplaceNum, Some(REPLACE_NUM)), + create_message(replace_id(), Some(REPLACE_ID)), + create_message(replace_var(), Some(REPLACE_VAR)), + create_message(replace_num(), Some(REPLACE_NUM)), ]; let result = get_fix_result(messages); assert_eq!(result.fixed_code, "let foo = 5 * 7;"); @@ -285,7 +281,7 @@ mod test { #[test] fn remove_at_the_start() { - let result = get_fix_result(vec![create_message(RemoveStart, Some(REMOVE_START))]); + let result = get_fix_result(vec![create_message(remove_start(), Some(REMOVE_START))]); assert_eq!(result.fixed_code, TEST_CODE.replace("var ", "")); assert_eq!(result.messages.len(), 0); assert!(result.fixed); @@ -294,7 +290,7 @@ mod test { #[test] fn remove_at_the_middle() { let result = get_fix_result(vec![create_message( - RemoveMiddle(Span::default()), + remove_middle(Span::default()), Some(REMOVE_MIDDLE), )]); assert_eq!(result.fixed_code, TEST_CODE.replace("answer", "a")); @@ -304,7 +300,7 @@ mod test { #[test] fn remove_at_the_end() { - let result = get_fix_result(vec![create_message(RemoveEnd, Some(REMOVE_END))]); + let result = get_fix_result(vec![create_message(remove_end(), Some(REMOVE_END))]); assert_eq!(result.fixed_code, TEST_CODE.replace(" * 7", "")); assert_eq!(result.messages.len(), 0); assert!(result.fixed); @@ -313,9 +309,9 @@ mod test { #[test] fn replace_at_start_remove_at_middle_insert_at_end() { let result = get_fix_result(vec![ - create_message(InsertAtEnd, Some(INSERT_AT_END)), - create_message(RemoveEnd, Some(REMOVE_END)), - create_message(ReplaceVar, Some(REPLACE_VAR)), + create_message(insert_at_end(), Some(INSERT_AT_END)), + create_message(remove_end(), Some(REMOVE_END)), + create_message(replace_var(), Some(REPLACE_VAR)), ]); assert_eq!(result.fixed_code, "let answer = 6;// end"); assert_eq!(result.messages.len(), 0); @@ -325,8 +321,8 @@ mod test { #[test] fn apply_one_fix_when_spans_overlap() { let result = get_fix_result(vec![ - create_message(RemoveMiddle(Span::default()), Some(REMOVE_MIDDLE)), - create_message(ReplaceId, Some(REPLACE_ID)), + create_message(remove_middle(Span::default()), Some(REMOVE_MIDDLE)), + create_message(replace_id(), Some(REPLACE_ID)), ]); assert_eq!(result.fixed_code, TEST_CODE.replace("answer", "foo")); assert_eq!(result.messages.len(), 1); @@ -337,8 +333,8 @@ mod test { #[test] fn apply_one_fix_when_the_start_the_same_as_the_previous_end() { let result = get_fix_result(vec![ - create_message(RemoveStart, Some(REMOVE_START)), - create_message(ReplaceId, Some(REPLACE_ID)), + create_message(remove_start(), Some(REMOVE_START)), + create_message(replace_id(), Some(REPLACE_ID)), ]); assert_eq!(result.fixed_code, TEST_CODE.replace("var ", "")); assert_eq!(result.messages.len(), 1); @@ -349,9 +345,9 @@ mod test { #[test] fn apply_one_fix_when_range_overlap_and_one_message_has_no_fix() { let result = get_fix_result(vec![ - create_message(RemoveMiddle(Span::default()), Some(REMOVE_MIDDLE)), - create_message(ReplaceId, Some(REPLACE_ID)), - create_message(NoFix(Span::default()), None), + create_message(remove_middle(Span::default()), Some(REMOVE_MIDDLE)), + create_message(replace_id(), Some(REPLACE_ID)), + create_message(no_fix(Span::default()), None), ]); assert_eq!(result.fixed_code, TEST_CODE.replace("answer", "foo")); assert_eq!(result.messages.len(), 2); @@ -363,19 +359,19 @@ mod test { #[test] fn apply_same_fix_when_span_overlap_regardless_of_order() { let result1 = get_fix_result(vec![ - create_message(RemoveMiddle(Span::default()), Some(REMOVE_MIDDLE)), - create_message(ReplaceId, Some(REPLACE_ID)), + create_message(remove_middle(Span::default()), Some(REMOVE_MIDDLE)), + create_message(replace_id(), Some(REPLACE_ID)), ]); let result2 = get_fix_result(vec![ - create_message(ReplaceId, Some(REPLACE_ID)), - create_message(RemoveMiddle(Span::default()), Some(REMOVE_MIDDLE)), + create_message(replace_id(), Some(REPLACE_ID)), + create_message(remove_middle(Span::default()), Some(REMOVE_MIDDLE)), ]); assert_eq!(result1.fixed_code, result2.fixed_code); } #[test] fn should_not_apply_fix_with_one_no_fix() { - let result = get_fix_result(vec![create_message(NoFix(Span::default()), None)]); + let result = get_fix_result(vec![create_message(no_fix(Span::default()), None)]); assert_eq!(result.fixed_code, TEST_CODE); assert_eq!(result.messages.len(), 1); assert_eq!(result.messages[0].error.to_string(), "nofix"); @@ -385,9 +381,9 @@ mod test { #[test] fn sort_no_fix_messages_correctly() { let result = get_fix_result(vec![ - create_message(ReplaceId, Some(REPLACE_ID)), - Message::new(NoFix2(Span::new(1, 7)).into(), None), - Message::new(NoFix1(Span::new(1, 3)).into(), None), + create_message(replace_id(), Some(REPLACE_ID)), + Message::new(no_fix_2(Span::new(1, 7)).into(), None), + Message::new(no_fix_1(Span::new(1, 3)).into(), None), ]); assert_eq!(result.fixed_code, TEST_CODE.replace("answer", "foo")); assert_eq!(result.messages.len(), 2);