-
-
Notifications
You must be signed in to change notification settings - Fork 475
/
await_expression.rs
126 lines (100 loc) · 4.66 KB
/
await_expression.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use crate::prelude::*;
use biome_formatter::write;
use crate::parentheses::{
is_binary_like_left_or_right, is_callee, is_conditional_test, is_member_object, is_spread,
update_or_lower_expression_needs_parentheses, NeedsParentheses,
};
use biome_js_syntax::{JsAwaitExpression, JsSyntaxNode};
use biome_js_syntax::{JsAwaitExpressionFields, JsSyntaxKind};
#[derive(Debug, Clone, Default)]
pub(crate) struct FormatJsAwaitExpression;
impl FormatNodeRule<JsAwaitExpression> for FormatJsAwaitExpression {
fn fmt_fields(&self, node: &JsAwaitExpression, f: &mut JsFormatter) -> FormatResult<()> {
let JsAwaitExpressionFields {
await_token,
argument,
} = node.as_fields();
let format_inner =
format_with(|f| write![f, [await_token.format(), space(), argument.format()]]);
let parent = node.syntax().parent();
if let Some(parent) = parent {
if is_callee(node.syntax(), &parent) || is_member_object(node.syntax(), &parent) {
let ancestor_await_or_block = parent.ancestors().skip(1).find(|ancestor| {
matches!(
ancestor.kind(),
JsSyntaxKind::JS_AWAIT_EXPRESSION
// Stop at statement boundaries.
| JsSyntaxKind::JS_STATEMENT_LIST
| JsSyntaxKind::JS_MODULE_ITEM_LIST
)
});
let indented = format_with(|f| write!(f, [soft_block_indent(&format_inner)]));
return if let Some(parent_js_await_expression) =
ancestor_await_or_block.and_then(JsAwaitExpression::cast)
{
if !parent_js_await_expression.needs_parentheses() {
return write!(f, [group(&indented)]);
}
write!(f, [indented])
} else {
write!(f, [group(&indented)])
};
}
}
write!(f, [format_inner])
}
fn needs_parentheses(&self, item: &JsAwaitExpression) -> bool {
item.needs_parentheses()
}
}
impl NeedsParentheses for JsAwaitExpression {
fn needs_parentheses_with_parent(&self, parent: &JsSyntaxNode) -> bool {
await_or_yield_needs_parens(parent, self.syntax())
}
}
pub(super) fn await_or_yield_needs_parens(parent: &JsSyntaxNode, node: &JsSyntaxNode) -> bool {
debug_assert!(matches!(
node.kind(),
JsSyntaxKind::JS_AWAIT_EXPRESSION | JsSyntaxKind::JS_YIELD_EXPRESSION
));
match parent.kind() {
JsSyntaxKind::JS_UNARY_EXPRESSION
| JsSyntaxKind::TS_AS_EXPRESSION
| JsSyntaxKind::TS_SATISFIES_EXPRESSION => true,
_ => {
let expression = node;
is_conditional_test(node, parent)
|| update_or_lower_expression_needs_parentheses(expression, parent)
|| is_spread(expression, parent)
|| is_binary_like_left_or_right(node, parent)
}
}
}
#[cfg(test)]
mod tests {
use crate::{assert_needs_parentheses, assert_not_needs_parentheses};
use biome_js_syntax::JsAwaitExpression;
#[test]
fn needs_parentheses() {
assert_needs_parentheses!("(await a)`template`", JsAwaitExpression);
assert_needs_parentheses!("+(await a)", JsAwaitExpression);
assert_needs_parentheses!("(await a).b", JsAwaitExpression);
assert_needs_parentheses!("(await a)[b]", JsAwaitExpression);
assert_not_needs_parentheses!("a[await b]", JsAwaitExpression);
assert_needs_parentheses!("(await a)()", JsAwaitExpression);
assert_needs_parentheses!("new (await a)()", JsAwaitExpression);
assert_needs_parentheses!("(await a) && b", JsAwaitExpression);
assert_needs_parentheses!("(await a) + b", JsAwaitExpression);
assert_needs_parentheses!("(await a) instanceof b", JsAwaitExpression);
assert_needs_parentheses!("(await a) in b", JsAwaitExpression);
assert_needs_parentheses!("[...(await a)]", JsAwaitExpression);
assert_needs_parentheses!("({...(await b)})", JsAwaitExpression);
assert_needs_parentheses!("call(...(await b))", JsAwaitExpression);
assert_needs_parentheses!("class A extends (await b) {}", JsAwaitExpression);
assert_needs_parentheses!("(await b) as number", JsAwaitExpression);
assert_needs_parentheses!("(await b)!", JsAwaitExpression);
assert_needs_parentheses!("(await b) ? b : c", JsAwaitExpression);
assert_not_needs_parentheses!("a ? await b : c", JsAwaitExpression);
assert_not_needs_parentheses!("a ? b : await c", JsAwaitExpression);
}
}