-
-
Notifications
You must be signed in to change notification settings - Fork 526
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(lint): support promise expression in noFloatingPromises #4977
base: next
Are you sure you want to change the base?
Conversation
CodSpeed Performance ReportMerging #4977 will not alter performanceComparing Summary
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! There are other cases we need to cover regarding the Promise
global
is_variable_initializer_a_promise(&js_var_decl).unwrap_or(false) | ||
|| is_variable_annotation_a_promise(&js_var_decl).unwrap_or(false), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is_variable_initializer_a_promise(&js_var_decl).unwrap_or(false) | |
|| is_variable_annotation_a_promise(&js_var_decl).unwrap_or(false), | |
is_variable_initializer_a_promise(&js_var_decl).unwrap_or_default() | |
|| is_variable_annotation_a_promise(&js_var_decl).unwrap_or_default(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated!
return None; | ||
} | ||
|
||
if is_handled_promise(&js_call_expression).unwrap_or(false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if is_handled_promise(&js_call_expression).unwrap_or(false) { | |
if is_handled_promise(&js_call_expression)? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually want to return only when the value is true and continue when the value is false or None so using ?
does not work here
is_expression_an_promise(&js_ident_expr).unwrap_or(false) | ||
|| is_binding_a_promise(&js_ident_expr, model).unwrap_or(false), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is_expression_an_promise(&js_ident_expr).unwrap_or(false) | |
|| is_binding_a_promise(&js_ident_expr, model).unwrap_or(false), | |
is_expression_an_promise(&js_ident_expr).unwrap_or_default() | |
|| is_binding_a_promise(&js_ident_expr, model).unwrap_or_default(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated!
let js_ident_expr = any_js_expr.as_js_identifier_expression()?; | ||
let reference = js_ident_expr.name().ok()?; | ||
Some(reference.has_name("Promise")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, there are few things that we need to handle here (not just here, but in all cases where we check "Promise"
):
- The parenthesis. Unfortunately these are valid cases e.g.
return (new Pormise.resolve())
. You can use the method.omit_parentheses
that can be used fromAnyJsExpression
- Global identifiers. A promise can be used from
window.Promise
orglobalThis.Promise
. You can use the utilityglobal_identifier
- Making sure that
Promise
isn't a binding. You need to use the semantic model to check that.
var Promise = { resolve(): {} };
return Promise.resolve()
This should NOT trigger the rule.
Here's an example of rust code to check:
biome/crates/biome_js_analyze/src/lint/suspicious/no_prototype_builtins.rs
Lines 209 to 214 in 738ad51
fn is_global_object(semantic: &SemanticModel) -> bool { | |
semantic | |
.scopes() | |
.find(|s| s.get_binding("Object").is_some()) | |
.map_or(true, |s| s.is_global_scope()) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the feedback!
I have updated the code to handle 1 and 2. I will probably work on 3 tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The parenthesis. Unfortunately these are valid cases e.g. return (new Pormise.resolve()). You can use the method .omit_parentheses that can be used from AnyJsExpression
- Global identifiers. A promise can be used from window.Promise or globalThis.Promise. You can use the utility global_identifier
- Making sure that Promise isn't a binding. You need to use the semantic model to check that.
I have updated the code to cover all the cases.
For 3 (making sure that Promise isn't a binding), creating a function like is_global_object
for Promise does not work for globally defined variable. Therefore, I decided to use model.binding
instead.
85ab50c
to
20720d7
Compare
Summary
related: #3187 and #4956
This pull request introduces the support for promise expressions in
noFloatingPromises
Example of invalid code:
Example of valid code: