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
This commit is contained in:
Martin Probst 2019-11-07 23:39:03 +01:00
parent 48b7068bec
commit a7638d3849
3 changed files with 24 additions and 0 deletions

View File

@ -60,6 +60,8 @@ namespace format {
TYPE(JsExponentiationEqual) \
TYPE(JsFatArrow) \
TYPE(JsNonNullAssertion) \
TYPE(JsNullishCoalescingOperator) \
TYPE(JsNullPropagatingOperator) \
TYPE(JsPrivateIdentifier) \
TYPE(JsTypeColon) \
TYPE(JsTypeOperator) \

View File

@ -100,6 +100,10 @@ void FormatTokenLexer::tryMergePreviousTokens() {
static const tok::TokenKind JSExponentiation[] = {tok::star, tok::star};
static const tok::TokenKind JSExponentiationEqual[] = {tok::star,
tok::starequal};
static const tok::TokenKind JSNullPropagatingOperator[] = {tok::question,
tok::period};
static const tok::TokenKind JSNullishOperator[] = {tok::question,
tok::question};
// FIXME: Investigate what token type gives the correct operator priority.
if (tryMergeTokens(JSIdentity, TT_BinaryOperator))
@ -116,6 +120,14 @@ void FormatTokenLexer::tryMergePreviousTokens() {
Tokens.back()->Tok.setKind(tok::starequal);
return;
}
if (tryMergeTokens(JSNullishOperator, TT_JsNullishCoalescingOperator))
return;
if (tryMergeTokens(JSNullPropagatingOperator,
TT_JsNullPropagatingOperator)) {
// Treat like a regular "." access.
Tokens.back()->Tok.setKind(tok::period);
return;
}
if (tryMergeJSPrivateIdentifier())
return;
}

View File

@ -2222,6 +2222,16 @@ TEST_F(FormatTestJS, NonNullAssertionOperator) {
verifyFormat("return !!x;\n");
}
TEST_F(FormatTestJS, NullPropagatingOperator) {
verifyFormat("let x = foo?.bar?.baz();\n");
verifyFormat("let x = foo?.(foo);\n");
verifyFormat("let x = foo?.['arr'];\n");
}
TEST_F(FormatTestJS, NullishCoalescingOperator) {
verifyFormat("const val = something ?? 'some other default';\n");
}
TEST_F(FormatTestJS, Conditional) {
verifyFormat("y = x ? 1 : 2;");
verifyFormat("x ? 1 : 2;");