@@ -14,17 +14,19 @@ use serde::{Deserialize, Serialize};
1414use crate :: { AstNode , context:: LintContext , rule:: Rule } ;
1515
1616fn 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
2424fn 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) ;
168181impl 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