Skip to content

Commit a7638d3

Browse files
committed
clang-format: [JS] support null operators.
Summary: JavaScript / TypeScript is adding two new operators: the null propagating operator `?.` and the nullish coalescing operator `??`. const x = foo ?? 'default'; const z = foo?.bar?.baz; This change adds support to lex and format both. Reviewers: krasimir Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D69971
1 parent 48b7068 commit a7638d3

File tree

3 files changed

+24
-0
lines changed

3 files changed

+24
-0
lines changed

clang/lib/Format/FormatToken.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ namespace format {
6060
TYPE(JsExponentiationEqual) \
6161
TYPE(JsFatArrow) \
6262
TYPE(JsNonNullAssertion) \
63+
TYPE(JsNullishCoalescingOperator) \
64+
TYPE(JsNullPropagatingOperator) \
6365
TYPE(JsPrivateIdentifier) \
6466
TYPE(JsTypeColon) \
6567
TYPE(JsTypeOperator) \

clang/lib/Format/FormatTokenLexer.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ void FormatTokenLexer::tryMergePreviousTokens() {
100100
static const tok::TokenKind JSExponentiation[] = {tok::star, tok::star};
101101
static const tok::TokenKind JSExponentiationEqual[] = {tok::star,
102102
tok::starequal};
103+
static const tok::TokenKind JSNullPropagatingOperator[] = {tok::question,
104+
tok::period};
105+
static const tok::TokenKind JSNullishOperator[] = {tok::question,
106+
tok::question};
103107

104108
// FIXME: Investigate what token type gives the correct operator priority.
105109
if (tryMergeTokens(JSIdentity, TT_BinaryOperator))
@@ -116,6 +120,14 @@ void FormatTokenLexer::tryMergePreviousTokens() {
116120
Tokens.back()->Tok.setKind(tok::starequal);
117121
return;
118122
}
123+
if (tryMergeTokens(JSNullishOperator, TT_JsNullishCoalescingOperator))
124+
return;
125+
if (tryMergeTokens(JSNullPropagatingOperator,
126+
TT_JsNullPropagatingOperator)) {
127+
// Treat like a regular "." access.
128+
Tokens.back()->Tok.setKind(tok::period);
129+
return;
130+
}
119131
if (tryMergeJSPrivateIdentifier())
120132
return;
121133
}

clang/unittests/Format/FormatTestJS.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2222,6 +2222,16 @@ TEST_F(FormatTestJS, NonNullAssertionOperator) {
22222222
verifyFormat("return !!x;\n");
22232223
}
22242224

2225+
TEST_F(FormatTestJS, NullPropagatingOperator) {
2226+
verifyFormat("let x = foo?.bar?.baz();\n");
2227+
verifyFormat("let x = foo?.(foo);\n");
2228+
verifyFormat("let x = foo?.['arr'];\n");
2229+
}
2230+
2231+
TEST_F(FormatTestJS, NullishCoalescingOperator) {
2232+
verifyFormat("const val = something ?? 'some other default';\n");
2233+
}
2234+
22252235
TEST_F(FormatTestJS, Conditional) {
22262236
verifyFormat("y = x ? 1 : 2;");
22272237
verifyFormat("x ? 1 : 2;");

0 commit comments

Comments
 (0)