Skip to content

Commit 19bc929

Browse files
committed
feat(linter): add fix for preserve-caught-error
1 parent ffc810d commit 19bc929

File tree

1 file changed

+76
-7
lines changed

1 file changed

+76
-7
lines changed

crates/oxc_linter/src/rules/eslint/preserve_caught_error.rs

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@ use serde::{Deserialize, Serialize};
1414
use crate::{AstNode, context::LintContext, rule::Rule};
1515

1616
fn preserve_caught_error_diagnostic(span: Span) -> OxcDiagnostic {
17-
OxcDiagnostic::warn("preserve-caught-error")
17+
OxcDiagnostic::warn("There is no cause error attached to this new thrown error.")
1818
.with_help(
19-
"When re-throwing an error, preserve the original error using the 'cause' property",
19+
"Preserve the original error by using the `cause` property when re-throwing errors.",
2020
)
2121
.with_label(span)
2222
}
2323

2424
fn missing_catch_parameter_diagnostic(span: Span) -> OxcDiagnostic {
25-
OxcDiagnostic::warn("preserve-caught-error")
26-
.with_help("Catch clause must have a parameter when 'requireCatchParameter' is enabled")
27-
.with_label(span)
25+
OxcDiagnostic::warn(
26+
"The caught error is not accessible because the catch clause has no error parameter.",
27+
)
28+
.with_help("Add an error parameter to the catch clause to access the caught error.")
29+
.with_label(span)
2830
}
2931

3032
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
@@ -66,7 +68,18 @@ impl<'a> Visit<'a> for ThrowFinder<'a, '_> {
6668
return;
6769
}
6870

69-
self.ctx.diagnostic(preserve_caught_error_diagnostic(throw_stmt.span));
71+
if args.len() == 1
72+
&& let Some(ident) = self.catch_param.get_identifier_name()
73+
{
74+
self.ctx.diagnostic_with_fix(
75+
preserve_caught_error_diagnostic(throw_stmt.span),
76+
|fixer| {
77+
fixer.insert_text_after(&args[0], format!(", {{ cause: {} }}", ident.as_str()))
78+
},
79+
);
80+
} else {
81+
self.ctx.diagnostic(preserve_caught_error_diagnostic(throw_stmt.span));
82+
}
7083
}
7184

7285
// Do not traverse into nested functions/closures within the catch block
@@ -162,7 +175,7 @@ declare_oxc_lint!(
162175
PreserveCaughtError,
163176
eslint,
164177
suspicious,
165-
pending,
178+
conditional_fix,
166179
config = PreserveCaughtErrorOptions,
167180
);
168181
impl PreserveCaughtError {
@@ -544,6 +557,62 @@ fn test() {
544557
),
545558
];
546559

560+
let fix = vec![
561+
(
562+
r#"try {
563+
doSomething();
564+
} catch (err) {
565+
throw new Error("Something failed");
566+
}"#,
567+
r#"try {
568+
doSomething();
569+
} catch (err) {
570+
throw new Error("Something failed", { cause: err });
571+
}"#,
572+
None,
573+
),
574+
(
575+
r#"try {
576+
doSomething();
577+
} catch (error) {
578+
throw new Error("Failed");
579+
}"#,
580+
r#"try {
581+
doSomething();
582+
} catch (error) {
583+
throw new Error("Failed", { cause: error });
584+
}"#,
585+
None,
586+
),
587+
(
588+
r#"try {
589+
doSomething();
590+
} catch (error) {
591+
throw new Error("Failed", { existingOption: true });
592+
}"#,
593+
r#"try {
594+
doSomething();
595+
} catch (error) {
596+
throw new Error("Failed", { existingOption: true, cause: error });
597+
}"#,
598+
None,
599+
),
600+
(
601+
r#"try {
602+
doSomething();
603+
} catch (err) {
604+
throw new Error("Something failed", {});
605+
}"#,
606+
r#"try {
607+
doSomething();
608+
} catch (err) {
609+
throw new Error("Something failed", { cause: err });
610+
}"#,
611+
None,
612+
),
613+
];
614+
547615
Tester::new(PreserveCaughtError::NAME, PreserveCaughtError::PLUGIN, pass, fail)
616+
.expect_fix(fix)
548617
.test_and_snapshot();
549618
}

0 commit comments

Comments
 (0)