@@ -5,10 +5,10 @@ use biome_console::markup;
5
5
use biome_js_factory:: make;
6
6
use biome_js_semantic:: SemanticModel ;
7
7
use biome_js_syntax:: {
8
- binding_ext:: AnyJsBindingDeclaration , AnyJsExpression , AnyTsType , JsArrowFunctionExpression ,
9
- JsCallExpression , JsExpressionStatement , JsFunctionDeclaration , JsIdentifierExpression ,
10
- JsMethodClassMember , JsMethodObjectMember , JsStaticMemberExpression , JsSyntaxKind ,
11
- JsVariableDeclarator , TsReturnTypeAnnotation ,
8
+ binding_ext:: AnyJsBindingDeclaration , global_identifier , AnyJsExpression , AnyTsType ,
9
+ JsArrowFunctionExpression , JsCallExpression , JsExpressionStatement , JsFunctionDeclaration ,
10
+ JsIdentifierExpression , JsMethodClassMember , JsMethodObjectMember , JsStaticMemberExpression ,
11
+ JsSyntaxKind , JsVariableDeclarator , TsReturnTypeAnnotation ,
12
12
} ;
13
13
use biome_rowan:: { AstNode , AstSeparatedList , BatchMutationExt , SyntaxNodeCast , TriviaPieceKind } ;
14
14
@@ -376,6 +376,8 @@ fn is_handled_promise(js_call_expression: &JsCallExpression) -> Option<bool> {
376
376
/// async function returnsPromise(): Promise<void> {}
377
377
///
378
378
/// returnsPromise().then(() => null).catch(() => {});
379
+ ///
380
+ /// globalThis.Promise.reject('value').finally();
379
381
/// ```
380
382
///
381
383
/// Example TypeScript code that would return `false`:
@@ -389,6 +391,11 @@ fn is_member_expression_callee_a_promise(
389
391
model : & SemanticModel ,
390
392
) -> Option < bool > {
391
393
let expr = static_member_expr. object ( ) . ok ( ) ?;
394
+
395
+ if is_promise_with_global_identifier ( & expr) {
396
+ return Some ( true ) ;
397
+ }
398
+
392
399
match expr {
393
400
AnyJsExpression :: JsCallExpression ( js_call_expr) => {
394
401
let callee = js_call_expr. callee ( ) . ok ( ) ?;
@@ -495,6 +502,8 @@ fn is_in_async_function(node: &JsExpressionStatement) -> bool {
495
502
/// }
496
503
///
497
504
/// const promise = new Promise((resolve) => resolve('value'));
505
+ ///
506
+ /// const promiseWithGlobalIdentifier = new window.Promise((resolve, reject) => resolve('value'));
498
507
/// ```
499
508
fn is_variable_initializer_a_promise (
500
509
js_variable_declarator : & JsVariableDeclarator ,
@@ -513,6 +522,9 @@ fn is_variable_initializer_a_promise(
513
522
) ,
514
523
AnyJsExpression :: JsNewExpression ( js_new_epr) => {
515
524
let any_js_expr = js_new_epr. callee ( ) . ok ( ) ?;
525
+ if is_promise_with_global_identifier ( & any_js_expr) {
526
+ return Some ( true ) ;
527
+ }
516
528
let js_ident_expr = any_js_expr. as_js_identifier_expression ( ) ?;
517
529
let reference = js_ident_expr. name ( ) . ok ( ) ?;
518
530
Some ( reference. has_name ( "Promise" ) )
@@ -569,3 +581,33 @@ fn is_variable_annotation_a_promise(js_variable_declarator: &JsVariableDeclarato
569
581
_ => Some ( false ) ,
570
582
}
571
583
}
584
+
585
+ /// Checks if an expression is a `Promise` with a global identifier.
586
+ ///
587
+ /// This function inspects a given `AnyJsExpression` to determine if it represents a `Promise`
588
+ /// with a global identifier, such as `window.Promise`. It returns `true` if the expression is a
589
+ /// `Promise` with a global identifier, otherwise `false`.
590
+ ///
591
+ /// # Arguments
592
+ ///
593
+ /// * `expr` - A reference to an `AnyJsExpression` to check.
594
+ ///
595
+ /// # Returns
596
+ ///
597
+ /// * `true` if the expression is a `Promise` with a global identifier.
598
+ /// * `false` otherwise.
599
+ ///
600
+ /// # Examples
601
+ ///
602
+ /// Example TypeScript code that would return `true`:
603
+ /// ```typescript
604
+ /// window.Promise.resolve();
605
+ /// globalThis.Promise.resolve();
606
+ /// ```
607
+ ///
608
+ fn is_promise_with_global_identifier ( expr : & AnyJsExpression ) -> bool {
609
+ if let Some ( ( _, value) ) = global_identifier ( expr) {
610
+ return value. text ( ) == "Promise" ;
611
+ }
612
+ false
613
+ }
0 commit comments