r209291 - clang-format: [JS] Support different function literal style.
Daniel Jasper
djasper at google.com
Wed May 21 05:51:23 PDT 2014
Author: djasper
Date: Wed May 21 07:51:23 2014
New Revision: 209291
URL: http://llvm.org/viewvc/llvm-project?rev=209291&view=rev
Log:
clang-format: [JS] Support different function literal style.
Before:
goog.array.forEach(array, function() {
doSomething();
doSomething();
},
this);
After:
goog.array.forEach(array, function() {
doSomething();
doSomething();
}, this);
Modified:
cfe/trunk/lib/Format/ContinuationIndenter.cpp
cfe/trunk/lib/Format/ContinuationIndenter.h
cfe/trunk/lib/Format/Format.cpp
cfe/trunk/unittests/Format/FormatTestJS.cpp
Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=209291&r1=209290&r2=209291&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Wed May 21 07:51:23 2014
@@ -420,9 +420,16 @@ unsigned ContinuationIndenter::addTokenO
// Any break on this level means that the parent level has been broken
// and we need to avoid bin packing there.
- for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
- State.Stack[i].BreakBeforeParameter = true;
+ bool JavaScriptFormat = Style.Language == FormatStyle::LK_JavaScript &&
+ Current.is(tok::r_brace) &&
+ State.Stack.size() > 1 &&
+ State.Stack[State.Stack.size() - 2].JSFunctionInlined;
+ if (!JavaScriptFormat) {
+ for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
+ State.Stack[i].BreakBeforeParameter = true;
+ }
}
+
if (PreviousNonComment &&
!PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
PreviousNonComment->Type != TT_TemplateCloser &&
@@ -465,6 +472,9 @@ unsigned ContinuationIndenter::getNewLin
return Current.NestingLevel == 0 ? State.FirstIndent
: State.Stack.back().Indent;
if (Current.isOneOf(tok::r_brace, tok::r_square)) {
+ if (State.Stack.size() > 1 &&
+ State.Stack[State.Stack.size() - 2].JSFunctionInlined)
+ return State.FirstIndent;
if (Current.closesBlockTypeList(Style) ||
(Current.MatchingParen &&
Current.MatchingParen->BlockKind == BK_BracedInit))
@@ -600,6 +610,27 @@ unsigned ContinuationIndenter::moveState
// Insert scopes created by fake parenthesis.
const FormatToken *Previous = Current.getPreviousNonComment();
+
+ // Add special behavior to support a format commonly used for JavaScript
+ // closures:
+ // SomeFunction(function() {
+ // foo();
+ // bar();
+ // }, a, b, c);
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (Current.isNot(tok::comment) && Previous && Previous->is(tok::l_brace) &&
+ State.Stack.size() > 1) {
+ if (State.Stack[State.Stack.size() - 2].JSFunctionInlined && Newline) {
+ for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
+ State.Stack[i].NoLineBreak = true;
+ }
+ }
+ State.Stack[State.Stack.size() - 2].JSFunctionInlined = false;
+ }
+ if (Current.TokenText == "function")
+ State.Stack.back().JSFunctionInlined = !Newline;
+ }
+
// Don't add extra indentation for the first fake parenthesis after
// 'return', assignments or opening <({[. The indentation for these cases
// is special cased.
Modified: cfe/trunk/lib/Format/ContinuationIndenter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.h?rev=209291&r1=209290&r2=209291&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.h (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.h Wed May 21 07:51:23 2014
@@ -139,7 +139,8 @@ struct ParenState {
StartOfFunctionCall(0), StartOfArraySubscripts(0),
NestedNameSpecifierContinuation(0), CallContinuation(0), VariablePos(0),
ContainsLineBreak(false), ContainsUnwrappedBuilder(0),
- AlignColons(true), ObjCSelectorNameFound(false), LambdasFound(0) {}
+ AlignColons(true), ObjCSelectorNameFound(false), LambdasFound(0),
+ JSFunctionInlined(false) {}
/// \brief The position to which a specific parenthesis level needs to be
/// indented.
@@ -240,6 +241,10 @@ struct ParenState {
/// the same token.
unsigned LambdasFound;
+ // \brief The previous JavaScript 'function' keyword is not wrapped to a new
+ // line.
+ bool JSFunctionInlined;
+
bool operator<(const ParenState &Other) const {
if (Indent != Other.Indent)
return Indent < Other.Indent;
@@ -273,6 +278,8 @@ struct ParenState {
return ContainsLineBreak < Other.ContainsLineBreak;
if (ContainsUnwrappedBuilder != Other.ContainsUnwrappedBuilder)
return ContainsUnwrappedBuilder < Other.ContainsUnwrappedBuilder;
+ if (JSFunctionInlined != Other.JSFunctionInlined)
+ return JSFunctionInlined < Other.JSFunctionInlined;
return false;
}
};
Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=209291&r1=209290&r2=209291&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Wed May 21 07:51:23 2014
@@ -1146,8 +1146,13 @@ private:
return true;
if (NewLine) {
- int AdditionalIndent = State.Stack.back().Indent -
- Previous.Children[0]->Level * Style.IndentWidth;
+ int AdditionalIndent = 0;
+ if (State.Stack.size() < 2 ||
+ !State.Stack[State.Stack.size() - 2].JSFunctionInlined) {
+ AdditionalIndent = State.Stack.back().Indent -
+ Previous.Children[0]->Level * Style.IndentWidth;
+ }
+
Penalty += format(Previous.Children, DryRun, AdditionalIndent,
/*FixBadIndentation=*/true);
return true;
Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=209291&r1=209290&r2=209291&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTestJS.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJS.cpp Wed May 21 07:51:23 2014
@@ -120,6 +120,18 @@ TEST_F(FormatTestJS, Closures) {
"};");
EXPECT_EQ("abc = xyz ? function() { return 1; } : function() { return -1; };",
format("abc=xyz?function(){return 1;}:function(){return -1;};"));
+
+ verifyFormat("var closure = goog.bind(\n"
+ " function() { // comment\n"
+ " foo();\n"
+ " bar();\n"
+ " },\n"
+ " this, arg1IsReallyLongAndNeeedsLineBreaks,\n"
+ " arg3IsReallyLongAndNeeedsLineBreaks);");
+ verifyFormat("var closure = goog.bind(function() { // comment\n"
+ " foo();\n"
+ " bar();\n"
+ "}, this);");
}
TEST_F(FormatTestJS, ReturnStatements) {
More information about the cfe-commits
mailing list