From 44baddbace0bb426ad47c30f438c78096ede7e16 Mon Sep 17 00:00:00 2001
From: heygsc <1596920983@qq.com>
Date: Tue, 13 Aug 2024 14:41:50 +0800
Subject: [PATCH 1/3] feat(linter): add fixer for
 unicorn/prefer-optional-catch-binding

---
 .../unicorn/prefer_optional_catch_binding.rs  | 44 +++++++++++++++++--
 .../prefer_optional_catch_binding.snap        | 10 +++++
 2 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs b/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs
index 3bc7ff458abb5..65daa96b57c78 100644
--- a/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs
+++ b/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs
@@ -39,7 +39,7 @@ declare_oxc_lint!(
     /// ```
     PreferOptionalCatchBinding,
     style,
-    pending
+    fix
 );
 
 impl Rule for PreferOptionalCatchBinding {
@@ -51,7 +51,29 @@ impl Rule for PreferOptionalCatchBinding {
         if references_count != 0 {
             return;
         }
-        ctx.diagnostic(prefer_optional_catch_binding_diagnostic(catch_param.pattern.span()));
+        let Some(parent_node) = ctx.nodes().parent_node(node.id()) else {
+            return;
+        };
+        let AstKind::CatchClause(catch_clause) = parent_node.kind() else {
+            return;
+        };
+        ctx.diagnostic_with_fix(
+            prefer_optional_catch_binding_diagnostic(catch_param.pattern.span()),
+            |fixer| {
+                let mut start = catch_clause.span().start + 5;
+                let total_param = Span::new(start, catch_param.span().start);
+                let value = ctx.source_range(total_param);
+                for char in value.chars() {
+                    if char != ' ' {
+                        break;
+                    }
+                    start += 1;
+                }
+                let end = catch_clause.body.span().start;
+                let span = Span::new(start, end);
+                fixer.delete(&span)
+            },
+        );
     }
 }
 
@@ -110,5 +132,21 @@ fn test() {
         r"try {} catch ({cause: {message}}) {}",
     ];
 
-    Tester::new(PreferOptionalCatchBinding::NAME, pass, fail).test_and_snapshot();
+    let fix = vec![
+        (r"try {} catch (_) {}", r"try {} catch {}"),
+        (r"try {} catch (theRealErrorName) {}", r"try {} catch {}"),
+        (
+            r"try    {    } catch    (e)
+			  	  {    }",
+            r"try    {    } catch    {    }",
+        ),
+        (r"try {} catch(e) {}", r"try {} catch{}"),
+        (r"try {} catch (e){}", r"try {} catch {}"),
+        (r"try {} catch ({}) {}", r"try {} catch {}"),
+        (r"try {} catch ({message}) {}", r"try {} catch {}"),
+        (r"try {} catch ({message: notUsedMessage}) {}", r"try {} catch {}"),
+        (r"try {} catch ({cause: {message}}) {}", r"try {} catch {}"),
+    ];
+
+    Tester::new(PreferOptionalCatchBinding::NAME, pass, fail).expect_fix(fix).test_and_snapshot();
 }
diff --git a/crates/oxc_linter/src/snapshots/prefer_optional_catch_binding.snap b/crates/oxc_linter/src/snapshots/prefer_optional_catch_binding.snap
index f0f8f97ddb811..7889d7c31e4c6 100644
--- a/crates/oxc_linter/src/snapshots/prefer_optional_catch_binding.snap
+++ b/crates/oxc_linter/src/snapshots/prefer_optional_catch_binding.snap
@@ -1,17 +1,20 @@
 ---
 source: crates/oxc_linter/src/tester.rs
+assertion_line: 234
 ---
   ⚠ eslint-plugin-unicorn(prefer-optional-catch-binding): Prefer omitting the catch binding parameter if it is unused
    ╭─[prefer_optional_catch_binding.tsx:1:15]
  1 │ try {} catch (_) {}
    ·               ─
    ╰────
+  help: Delete this code.
 
   ⚠ eslint-plugin-unicorn(prefer-optional-catch-binding): Prefer omitting the catch binding parameter if it is unused
    ╭─[prefer_optional_catch_binding.tsx:1:15]
  1 │ try {} catch (theRealErrorName) {}
    ·               ────────────────
    ╰────
+  help: Delete this code.
 
   ⚠ eslint-plugin-unicorn(prefer-optional-catch-binding): Prefer omitting the catch binding parameter if it is unused
    ╭─[prefer_optional_catch_binding.tsx:1:25]
@@ -19,39 +22,46 @@ source: crates/oxc_linter/src/tester.rs
    ·                         ─
  2 │                   {    }
    ╰────
+  help: Delete this code.
 
   ⚠ eslint-plugin-unicorn(prefer-optional-catch-binding): Prefer omitting the catch binding parameter if it is unused
    ╭─[prefer_optional_catch_binding.tsx:1:14]
  1 │ try {} catch(e) {}
    ·              ─
    ╰────
+  help: Delete this code.
 
   ⚠ eslint-plugin-unicorn(prefer-optional-catch-binding): Prefer omitting the catch binding parameter if it is unused
    ╭─[prefer_optional_catch_binding.tsx:1:15]
  1 │ try {} catch (e){}
    ·               ─
    ╰────
+  help: Delete this code.
 
   ⚠ eslint-plugin-unicorn(prefer-optional-catch-binding): Prefer omitting the catch binding parameter if it is unused
    ╭─[prefer_optional_catch_binding.tsx:1:15]
  1 │ try {} catch ({}) {}
    ·               ──
    ╰────
+  help: Delete this code.
 
   ⚠ eslint-plugin-unicorn(prefer-optional-catch-binding): Prefer omitting the catch binding parameter if it is unused
    ╭─[prefer_optional_catch_binding.tsx:1:15]
  1 │ try {} catch ({message}) {}
    ·               ─────────
    ╰────
+  help: Delete this code.
 
   ⚠ eslint-plugin-unicorn(prefer-optional-catch-binding): Prefer omitting the catch binding parameter if it is unused
    ╭─[prefer_optional_catch_binding.tsx:1:15]
  1 │ try {} catch ({message: notUsedMessage}) {}
    ·               ─────────────────────────
    ╰────
+  help: Delete this code.
 
   ⚠ eslint-plugin-unicorn(prefer-optional-catch-binding): Prefer omitting the catch binding parameter if it is unused
    ╭─[prefer_optional_catch_binding.tsx:1:15]
  1 │ try {} catch ({cause: {message}}) {}
    ·               ──────────────────
    ╰────
+  help: Delete this code.

From 413aa2a10172959adcf1c4d84f611547a94976ee Mon Sep 17 00:00:00 2001
From: heygsc <1596920983@qq.com>
Date: Wed, 14 Aug 2024 11:42:33 +0800
Subject: [PATCH 2/3] update: change from chars to bytes

---
 .../rules/unicorn/prefer_optional_catch_binding.rs | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs b/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs
index 65daa96b57c78..851cab5c71fa6 100644
--- a/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs
+++ b/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs
@@ -63,12 +63,14 @@ impl Rule for PreferOptionalCatchBinding {
                 let mut start = catch_clause.span().start + 5;
                 let total_param = Span::new(start, catch_param.span().start);
                 let value = ctx.source_range(total_param);
-                for char in value.chars() {
-                    if char != ' ' {
-                        break;
-                    }
-                    start += 1;
-                }
+                let x: u32 = value
+                    .as_bytes()
+                    .iter()
+                    .position(|x| !x.is_ascii_whitespace())
+                    .unwrap_or(0)
+                    .try_into()
+                    .unwrap();
+                start += x;
                 let end = catch_clause.body.span().start;
                 let span = Span::new(start, end);
                 fixer.delete(&span)

From 22eff7a9056d2e4c3dfd6001de2b522f24ee9ddd Mon Sep 17 00:00:00 2001
From: heygsc <1596920983@qq.com>
Date: Wed, 14 Aug 2024 12:37:23 +0800
Subject: [PATCH 3/3] chore: optimize the name

---
 .../src/rules/unicorn/prefer_optional_catch_binding.rs      | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs b/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs
index 851cab5c71fa6..5d56e9d172d75 100644
--- a/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs
+++ b/crates/oxc_linter/src/rules/unicorn/prefer_optional_catch_binding.rs
@@ -62,15 +62,15 @@ impl Rule for PreferOptionalCatchBinding {
             |fixer| {
                 let mut start = catch_clause.span().start + 5;
                 let total_param = Span::new(start, catch_param.span().start);
-                let value = ctx.source_range(total_param);
-                let x: u32 = value
+                let total_param_value = ctx.source_range(total_param);
+                let plus_space: u32 = total_param_value
                     .as_bytes()
                     .iter()
                     .position(|x| !x.is_ascii_whitespace())
                     .unwrap_or(0)
                     .try_into()
                     .unwrap();
-                start += x;
+                start += plus_space;
                 let end = catch_clause.body.span().start;
                 let span = Span::new(start, end);
                 fixer.delete(&span)