summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2015-05-21 12:23:34 +0000
committerManuel Klimek <klimek@google.com>2015-05-21 12:23:34 +0000
commit79e06081a331912736fdcdbafd86d81f852d5e59 (patch)
treed83c1a10d7aa4042b60c237b2f221b0ca65517c8 /clang/lib
parent94fd963315fa774451c487bc6bd50fdc4656c70d (diff)
downloadbcm5719-llvm-79e06081a331912736fdcdbafd86d81f852d5e59.tar.gz
bcm5719-llvm-79e06081a331912736fdcdbafd86d81f852d5e59.zip
clang-format: [JS] Better support for fat arrows.
Assigns a token type (TT_JsFatArrow) to => tokens, and uses that to more easily recognize and format fat arrow functions. Improves function parsing to better recognize formal parameter lists and return type declarations. Recognizes arrow functions and parse function bodies as child blocks. Patch by Martin Probst. llvm-svn: 237895
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Format/Format.cpp14
-rw-r--r--clang/lib/Format/FormatToken.h1
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp68
-rw-r--r--clang/lib/Format/UnwrappedLineParser.h5
4 files changed, 70 insertions, 18 deletions
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 98146471af3..10c68f9da61 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -650,15 +650,14 @@ private:
static const tok::TokenKind JSShiftEqual[] = {tok::greater, tok::greater,
tok::greaterequal};
static const tok::TokenKind JSRightArrow[] = {tok::equal, tok::greater};
- // FIXME: We probably need to change token type to mimic operator with the
- // correct priority.
- if (tryMergeTokens(JSIdentity))
+ // FIXME: Investigate what token type gives the correct operator priority.
+ if (tryMergeTokens(JSIdentity, TT_BinaryOperator))
return;
- if (tryMergeTokens(JSNotIdentity))
+ if (tryMergeTokens(JSNotIdentity, TT_BinaryOperator))
return;
- if (tryMergeTokens(JSShiftEqual))
+ if (tryMergeTokens(JSShiftEqual, TT_BinaryOperator))
return;
- if (tryMergeTokens(JSRightArrow))
+ if (tryMergeTokens(JSRightArrow, TT_JsFatArrow))
return;
}
}
@@ -689,7 +688,7 @@ private:
return true;
}
- bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds) {
+ bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType) {
if (Tokens.size() < Kinds.size())
return false;
@@ -709,6 +708,7 @@ private:
First[0]->TokenText = StringRef(First[0]->TokenText.data(),
First[0]->TokenText.size() + AddLength);
First[0]->ColumnWidth += AddLength;
+ First[0]->Type = NewType;
return true;
}
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 9325d0d52e5..ec0fdf4aa81 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -51,6 +51,7 @@ enum TokenType {
TT_InlineASMBrace,
TT_InlineASMColon,
TT_JavaAnnotation,
+ TT_JsFatArrow,
TT_JsTypeColon,
TT_JsTypeOptionalQuestion,
TT_LambdaArrow,
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 5b1a4485673..939528fbffe 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -882,6 +882,17 @@ void UnwrappedLineParser::parseStructuralElement() {
break;
}
case tok::equal:
+ // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType
+ // TT_JsFatArrow. The always start an expression or a child block if
+ // followed by a curly.
+ if (FormatTok->is(TT_JsFatArrow)) {
+ nextToken();
+ if (FormatTok->is(tok::l_brace)) {
+ parseChildBlock();
+ }
+ break;
+ }
+
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
parseBracedList();
@@ -1006,18 +1017,44 @@ void UnwrappedLineParser::tryToParseJSFunction() {
if (FormatTok->isNot(tok::l_paren))
return;
- nextToken();
- while (FormatTok->isNot(tok::l_brace)) {
- // Err on the side of caution in order to avoid consuming the full file in
- // case of incomplete code.
- if (!FormatTok->isOneOf(tok::identifier, tok::comma, tok::r_paren,
- tok::comment))
- return;
+
+ // Parse formal parameter list.
+ parseBalanced(tok::l_paren, tok::r_paren);
+
+ if (FormatTok->is(tok::colon)) {
+ // Parse a type definition.
nextToken();
+
+ // Eat the type declaration. For braced inline object types, balance braces,
+ // otherwise just parse until finding an l_brace for the function body.
+ if (FormatTok->is(tok::l_brace)) {
+ parseBalanced(tok::l_brace, tok::r_brace);
+ } else {
+ while(FormatTok->isNot(tok::l_brace) && !eof()) {
+ nextToken();
+ }
+ }
}
+
parseChildBlock();
}
+void UnwrappedLineParser::parseBalanced(tok::TokenKind OpenKind,
+ tok::TokenKind CloseKind) {
+ assert(FormatTok->is(OpenKind));
+ nextToken();
+ int Depth = 1;
+ while (Depth > 0 && !eof()) {
+ // Parse the formal parameter list.
+ if (FormatTok->is(OpenKind)) {
+ ++Depth;
+ } else if (FormatTok->is(CloseKind)) {
+ --Depth;
+ }
+ nextToken();
+ }
+}
+
bool UnwrappedLineParser::tryToParseBracedList() {
if (FormatTok->BlockKind == BK_Unknown)
calculateBraceTypes();
@@ -1035,10 +1072,19 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
// FIXME: Once we have an expression parser in the UnwrappedLineParser,
// replace this by using parseAssigmentExpression() inside.
do {
- if (Style.Language == FormatStyle::LK_JavaScript &&
- FormatTok->is(Keywords.kw_function)) {
- tryToParseJSFunction();
- continue;
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ if (FormatTok->is(Keywords.kw_function)) {
+ tryToParseJSFunction();
+ continue;
+ } else if (FormatTok->is(TT_JsFatArrow)) {
+ nextToken();
+ // Fat arrows can be followed by simple expressions or by child blocks
+ // in curly braces.
+ if (FormatTok->is(tok::l_brace)){
+ parseChildBlock();
+ continue;
+ }
+ }
}
switch (FormatTok->Tok.getKind()) {
case tok::caret:
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index c2fa0295768..6a6e56fea02 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -107,6 +107,11 @@ private:
bool tryToParseLambda();
bool tryToParseLambdaIntroducer();
void tryToParseJSFunction();
+ /// \brief Parses tokens until encountering the CloseKind token, but balances
+ /// tokens when encountering more OpenKind tokens. Useful for e.g. parsing a
+ /// curly brace delimited block that can contain nested blocks.
+ /// The parser must be positioned on a token of OpenKind.
+ void parseBalanced(tok::TokenKind OpenKind, tok::TokenKind CloseKind);
void addUnwrappedLine();
bool eof() const;
void nextToken();
OpenPOWER on IntegriCloud