mprobst updated this revision to Diff 112858.
mprobst added a comment.
- clang-format: [JS] wrap calls w/ literals in template strings.
https://reviews.llvm.org/D37142
Files:
lib/Format/ContinuationIndenter.cpp
unittests/Format/FormatTestJS.cpp
Index: unittests/Format/FormatTestJS.cpp
===================================================================
--- unittests/Format/FormatTestJS.cpp
+++ unittests/Format/FormatTestJS.cpp
@@ -1793,43 +1793,38 @@
verifyFormat("var x = someFunction(`${})`) //\n"
" .oooooooooooooooooon();");
verifyFormat("var x = someFunction(`${aaaa}${\n"
- " aaaaa( //\n"
- " aaaaa)\n"
- " })`);");
+ " aaaaa( //\n"
+ " aaaaa)})`);");
}
TEST_F(FormatTestJS, TemplateStringMultiLineExpression) {
verifyFormat("var f = `aaaaaaaaaaaaaaaaaa: ${\n"
- " aaaaa + //\n"
- " bbbb\n"
- " }`;",
+ " aaaaa + //\n"
+ " bbbb}`;",
"var f = `aaaaaaaaaaaaaaaaaa: ${aaaaa + //\n"
" bbbb}`;");
verifyFormat("var f = `\n"
" aaaaaaaaaaaaaaaaaa: ${\n"
- " aaaaa + //\n"
- " bbbb\n"
- " }`;",
+ " aaaaa + //\n"
+ " bbbb}`;",
"var f = `\n"
" aaaaaaaaaaaaaaaaaa: ${ aaaaa + //\n"
" bbbb }`;");
verifyFormat("var f = `\n"
" aaaaaaaaaaaaaaaaaa: ${\n"
- " someFunction(\n"
- " aaaaa + //\n"
- " bbbb)\n"
- " }`;",
+ " someFunction(\n"
+ " aaaaa + //\n"
+ " bbbb)}`;",
"var f = `\n"
" aaaaaaaaaaaaaaaaaa: ${someFunction (\n"
" aaaaa + //\n"
" bbbb)}`;");
-
- // It might be preferable to wrap before "someFunction".
verifyFormat("var f = `\n"
- " aaaaaaaaaaaaaaaaaa: ${someFunction({\n"
- " aaaa: aaaaa,\n"
- " bbbb: bbbbb,\n"
- " })}`;",
+ " aaaaaaaaaaaaaaaaaa: ${\n"
+ " someFunction({\n"
+ " aaaa: aaaaa,\n"
+ " bbbb: bbbbb,\n"
+ " })}`;",
"var f = `\n"
" aaaaaaaaaaaaaaaaaa: ${someFunction ({\n"
" aaaa: aaaaa,\n"
Index: lib/Format/ContinuationIndenter.cpp
===================================================================
--- lib/Format/ContinuationIndenter.cpp
+++ lib/Format/ContinuationIndenter.cpp
@@ -661,9 +661,7 @@
// before the corresponding } or ].
if (PreviousNonComment &&
(PreviousNonComment->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
- opensProtoMessageField(*PreviousNonComment, Style) ||
- (PreviousNonComment->is(TT_TemplateString) &&
- PreviousNonComment->opensScope())))
+ opensProtoMessageField(*PreviousNonComment, Style)))
State.Stack.back().BreakBeforeClosingBrace = true;
if (State.Stack.back().AvoidBinPacking) {
@@ -925,11 +923,6 @@
moveStatePastFakeLParens(State, Newline);
moveStatePastScopeCloser(State);
- if (Current.is(TT_TemplateString) && Current.opensScope())
- State.Stack.back().LastSpace =
- (Current.IsMultiline ? Current.LastLineColumnWidth
- : State.Column + Current.ColumnWidth) -
- strlen("${");
bool CanBreakProtrudingToken = !State.Stack.back().NoLineBreak &&
!State.Stack.back().NoLineBreakInOperand;
moveStatePastScopeOpener(State, Newline);
@@ -1101,18 +1094,6 @@
LastSpace = std::max(LastSpace, State.Stack.back().Indent);
}
- // JavaScript template strings are special as we always want to indent
- // nested expressions relative to the ${}. Otherwise, this can create quite
- // a mess.
- if (Current.is(TT_TemplateString)) {
- unsigned Column = Current.IsMultiline
- ? Current.LastLineColumnWidth
- : State.Column + Current.ColumnWidth;
- NewIndent = Column;
- LastSpace = Column;
- NestedBlockIndent = Column;
- }
-
bool EndsInComma =
Current.MatchingParen &&
Current.MatchingParen->getPreviousNonComment() &&
@@ -1154,9 +1135,28 @@
// Generally inherit NoLineBreak from the current scope to nested scope.
// However, don't do this for non-empty nested blocks, dict literals and
// array literals as these follow different indentation rules.
+
+ // On lines containing template strings, propagate NoLineBreak even for dict
+ // and array literals. This is to force wrapping an initial function call if
+ // the literal inside wraps:
+ // const x = `aaa${
+ // myFunc({
+ // a: 1,
+ // b: 1,
+ // })}aaa`;
+ bool HasTemplateStr = false;
+ for (const FormatToken *Tok = State.Line->First;
+ Tok != &Current && Tok != nullptr; Tok = Tok->Next) {
+ if (Tok->is(TT_TemplateString)) {
+ HasTemplateStr = true;
+ break;
+ }
+ }
+
bool NoLineBreak =
Current.Children.empty() &&
- !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) &&
+ (HasTemplateStr ||
+ !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare)) &&
(State.Stack.back().NoLineBreak ||
State.Stack.back().NoLineBreakInOperand ||
(Current.is(TT_TemplateOpener) &&
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits