From 3506666c31935cf432089af0872e6e16701c57dd Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Tue, 31 Jan 2017 13:03:07 +0000 Subject: [PATCH] clang-format: [JS] Properly set scopes inside template strings. Before: var f = `aaaaaaaaaaaaa:${aaaaaaa .aaaaa} aaaaaaaa aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa`; After: var f = `aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa`; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@293622 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/FormatToken.h | 4 ++++ lib/Format/TokenAnnotator.cpp | 4 +++- unittests/Format/FormatTestJS.cpp | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h index b22e4c5d7c..c838cfbe1d 100644 --- a/lib/Format/FormatToken.h +++ b/lib/Format/FormatToken.h @@ -337,11 +337,15 @@ struct FormatToken { /// \brief Returns whether \p Tok is ([{ or a template opening <. bool opensScope() const { + if (is(TT_TemplateString) && TokenText.endswith("${")) + return true; return isOneOf(tok::l_paren, tok::l_brace, tok::l_square, TT_TemplateOpener); } /// \brief Returns whether \p Tok is )]} or a template closing >. bool closesScope() const { + if (is(TT_TemplateString) && TokenText.startswith("}")) + return true; return isOneOf(tok::r_paren, tok::r_brace, tok::r_square, TT_TemplateCloser); } diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index e58ca6d803..2785ca45e7 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -1454,7 +1454,9 @@ public: // Consume scopes: (), [], <> and {} if (Current->opensScope()) { - while (Current && !Current->closesScope()) { + // In fragment of a JavaScript template string can look like '}..${' and + // thus close a scope and open a new one at the same time. + while (Current && (!Current->closesScope() || Current->opensScope())) { next(); parse(); } diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index 71821a0649..6cc3bcd16c 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -1392,6 +1392,13 @@ TEST_F(FormatTestJS, TemplateStrings) { // The token stream can contain two string_literals in sequence, but that // doesn't mean that they are implicitly concatenated in JavaScript. verifyFormat("var f = `aaaa ${a ? 'a' : 'b'}`;"); + + // Ensure that scopes are appropriately set around evaluated expressions in + // template strings. + verifyFormat("var f = `aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa\n" + " aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa`;", + "var f = `aaaaaaaaaaaaa:${aaaaaaa. aaaaa} aaaaaaaa\n" + " aaaaaaaaaaaaa:${ aaaaaaa. aaaaa} aaaaaaaa`;"); } TEST_F(FormatTestJS, TemplateStringASI) { -- 2.40.0