@@ -5,9 +5,9 @@ use oxc_ast::{
5
5
use oxc_diagnostics:: OxcDiagnostic ;
6
6
7
7
use oxc_macros:: declare_oxc_lint;
8
- use oxc_span:: Span ;
8
+ use oxc_span:: { GetSpan , Span } ;
9
9
10
- use crate :: { ast_util:: is_method_call, context:: LintContext , rule:: Rule , AstNode } ;
10
+ use crate :: { ast_util:: is_method_call, context:: LintContext , fixer :: Fix , rule:: Rule , AstNode } ;
11
11
12
12
fn no_single_promise_in_promise_methods_diagnostic ( span0 : Span , x1 : & str ) -> OxcDiagnostic {
13
13
OxcDiagnostic :: warn ( format ! ( "eslint-plugin-unicorn(no-single-promise-in-promise-methods): Wrapping single-element array with `Promise.{x1}()` is unnecessary." ) )
@@ -57,7 +57,23 @@ impl Rule for NoSinglePromiseInPromiseMethods {
57
57
return ;
58
58
} ;
59
59
60
- if !is_promise_method_with_single_element_array ( call_expr) {
60
+ if !is_promise_method_with_single_argument ( call_expr) {
61
+ return ;
62
+ }
63
+ let Some ( first_argument) = call_expr. arguments [ 0 ] . as_expression ( ) else {
64
+ return ;
65
+ } ;
66
+ let first_argument = first_argument. without_parenthesized ( ) ;
67
+ let Expression :: ArrayExpression ( first_argument_array_expr) = first_argument else {
68
+ return ;
69
+ } ;
70
+
71
+ if first_argument_array_expr. elements . len ( ) != 1 {
72
+ return ;
73
+ }
74
+
75
+ let first = & first_argument_array_expr. elements [ 0 ] ;
76
+ if !first. is_expression ( ) {
61
77
return ;
62
78
}
63
79
@@ -68,34 +84,33 @@ impl Rule for NoSinglePromiseInPromiseMethods {
68
84
. static_property_info ( )
69
85
. expect ( "callee is a static property" ) ;
70
86
71
- ctx. diagnostic ( no_single_promise_in_promise_methods_diagnostic ( info. 0 , info. 1 ) ) ;
87
+ let diagnostic = no_single_promise_in_promise_methods_diagnostic ( info. 0 , info. 1 ) ;
88
+ ctx. diagnostic_with_fix ( diagnostic, || {
89
+ let elem_text = first. span ( ) . source_text ( ctx. source_text ( ) ) ;
90
+
91
+ let is_directly_in_await = ctx
92
+ . semantic ( )
93
+ . nodes ( )
94
+ // get first non-parenthesis parent node
95
+ . iter_parents ( node. id ( ) )
96
+ . skip ( 1 ) // first node is the call expr
97
+ . find ( |parent| !matches ! ( parent. kind( ) , AstKind :: ParenthesizedExpression ( _) ) )
98
+ // check if it's an `await ...` expression
99
+ . is_some_and ( |parent| matches ! ( parent. kind( ) , AstKind :: AwaitExpression ( _) ) ) ;
100
+
101
+ let call_span = call_expr. span ;
102
+
103
+ if is_directly_in_await {
104
+ Fix :: new ( elem_text, call_span)
105
+ } else {
106
+ Fix :: new ( format ! ( "Promise.resolve({elem_text})" ) , call_span)
107
+ }
108
+ } ) ;
72
109
}
73
110
}
74
111
75
- fn is_promise_method_with_single_element_array ( call_expr : & CallExpression ) -> bool {
76
- if !is_method_call (
77
- call_expr,
78
- Some ( & [ "Promise" ] ) ,
79
- Some ( & [ "all" , "any" , "race" ] ) ,
80
- Some ( 1 ) ,
81
- Some ( 1 ) ,
82
- ) {
83
- return false ;
84
- }
85
-
86
- let Some ( first_argument) = call_expr. arguments [ 0 ] . as_expression ( ) else {
87
- return false ;
88
- } ;
89
- let first_argument = first_argument. without_parenthesized ( ) ;
90
- let Expression :: ArrayExpression ( first_argument_array_expr) = first_argument else {
91
- return false ;
92
- } ;
93
-
94
- if first_argument_array_expr. elements . len ( ) != 1 {
95
- return false ;
96
- }
97
-
98
- first_argument_array_expr. elements [ 0 ] . is_expression ( )
112
+ fn is_promise_method_with_single_argument ( call_expr : & CallExpression ) -> bool {
113
+ is_method_call ( call_expr, Some ( & [ "Promise" ] ) , Some ( & [ "all" , "any" , "race" ] ) , Some ( 1 ) , Some ( 1 ) )
99
114
}
100
115
101
116
#[ test]
@@ -183,5 +198,13 @@ fn test() {
183
198
"Promise.all([null]).then()" ,
184
199
] ;
185
200
186
- Tester :: new ( NoSinglePromiseInPromiseMethods :: NAME , pass, fail) . test_and_snapshot ( ) ;
201
+ let fix = vec ! [
202
+ ( "Promise.all([null]).then()" , "Promise.resolve(null).then()" , None ) ,
203
+ ( "let x = await Promise.all([foo()])" , "let x = await foo()" , None ) ,
204
+ ( "let x = await (Promise.all([foo()]))" , "let x = await (foo())" , None ) ,
205
+ ] ;
206
+
207
+ Tester :: new ( NoSinglePromiseInPromiseMethods :: NAME , pass, fail)
208
+ . expect_fix ( fix)
209
+ . test_and_snapshot ( ) ;
187
210
}
0 commit comments