diff options
| author | Daniel Jasper <djasper@google.com> | 2014-11-13 15:56:28 +0000 |
|---|---|---|
| committer | Daniel Jasper <djasper@google.com> | 2014-11-13 15:56:28 +0000 |
| commit | 6be0f55d440d50dc1df829932f0ed9e11c8740c7 (patch) | |
| tree | 8f566c382d26de8c56b9cfd6009cf9b411a94670 /clang | |
| parent | 9074b18785c42d86bd6f8ee31cbdb76a34101bea (diff) | |
| download | bcm5719-llvm-6be0f55d440d50dc1df829932f0ed9e11c8740c7.tar.gz bcm5719-llvm-6be0f55d440d50dc1df829932f0ed9e11c8740c7.zip | |
clang-format: [Java] Support Java enums.
In Java, enums can contain a class body and enum constants can have
arguments as well as class bodies. Support most of that.
llvm-svn: 221895
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Format/UnwrappedLineParser.cpp | 103 | ||||
| -rw-r--r-- | clang/lib/Format/UnwrappedLineParser.h | 1 | ||||
| -rw-r--r-- | clang/unittests/Format/FormatTestJava.cpp | 38 |
3 files changed, 124 insertions, 18 deletions
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 10b4aeaca33..d94e6c414e4 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -311,7 +311,6 @@ void UnwrappedLineParser::calculateBraceTypes() { // parse macros, so this will magically work inside macro // definitions, too. unsigned StoredPosition = Tokens->getPosition(); - unsigned Position = StoredPosition; FormatToken *Tok = FormatTok; // Keep a stack of positions of lbrace tokens. We will // update information about whether an lbrace starts a @@ -382,7 +381,6 @@ void UnwrappedLineParser::calculateBraceTypes() { break; } Tok = NextTok; - Position += ReadTokens; } while (Tok->Tok.isNot(tok::eof) && !LBraceStack.empty()); // Assume other blocks for all unclosed opening braces. for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) { @@ -1331,10 +1329,10 @@ void UnwrappedLineParser::parseAccessSpecifier() { } void UnwrappedLineParser::parseEnum() { - if (FormatTok->Tok.is(tok::kw_enum)) { - // Won't be 'enum' for NS_ENUMs. - nextToken(); - } + // Won't be 'enum' for NS_ENUMs. + if (FormatTok->Tok.is(tok::kw_enum)) + nextToken(); + // Eat up enum class ... if (FormatTok->Tok.is(tok::kw_class) || FormatTok->Tok.is(tok::kw_struct)) nextToken(); @@ -1342,27 +1340,96 @@ void UnwrappedLineParser::parseEnum() { FormatTok->isOneOf(tok::colon, tok::coloncolon)) { nextToken(); // We can have macros or attributes in between 'enum' and the enum name. - if (FormatTok->Tok.is(tok::l_paren)) { + if (FormatTok->Tok.is(tok::l_paren)) parseParens(); - } if (FormatTok->Tok.is(tok::identifier)) nextToken(); } - if (FormatTok->Tok.is(tok::l_brace)) { - FormatTok->BlockKind = BK_Block; - bool HasError = !parseBracedList(/*ContinueOnSemicolons=*/true); - if (HasError) { - if (FormatTok->is(tok::semi)) - nextToken(); - addUnwrappedLine(); - } + + // Just a declaration or something is wrong. + if (!FormatTok->is(tok::l_brace)) + return; + FormatTok->BlockKind = BK_Block; + + if (Style.Language == FormatStyle::LK_Java) { + // Java enums are different. + parseJavaEnumBody(); + return; } + + // Parse enum body. + bool HasError = !parseBracedList(/*ContinueOnSemicolons=*/true); + if (HasError) { + if (FormatTok->is(tok::semi)) + nextToken(); + addUnwrappedLine(); + } + // We fall through to parsing a structural element afterwards, so that in // enum A {} n, m; // "} n, m;" will end up in one unwrapped line. - // This does not apply for Java. - if (Style.Language == FormatStyle::LK_Java) +} + +void UnwrappedLineParser::parseJavaEnumBody() { + // Determine whether the enum is simple, i.e. does not have a semicolon or + // constants with class bodies. Simple enums can be formatted like braced + // lists, contracted to a single line, etc. + unsigned StoredPosition = Tokens->getPosition(); + bool IsSimple = true; + FormatToken *Tok = Tokens->getNextToken(); + while (Tok) { + if (Tok->is(tok::r_brace)) + break; + if (Tok->isOneOf(tok::l_brace, tok::semi)) { + IsSimple = false; + break; + } + // FIXME: This will also mark enums with braces in the arguments to enum + // constants as "not simple". This is probably fine in practice, though. + Tok = Tokens->getNextToken(); + } + FormatTok = Tokens->setPosition(StoredPosition); + + if (IsSimple) { + parseBracedList(); addUnwrappedLine(); + return; + } + + // Parse the body of a more complex enum. + // First add a line for everything up to the "{". + nextToken(); + addUnwrappedLine(); + ++Line->Level; + + // Parse the enum constants. + while (FormatTok) { + if (FormatTok->is(tok::l_brace)) { + // Parse the constant's class body. + parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true, + /*MunchSemi=*/false); + } else if (FormatTok->is(tok::l_paren)) { + parseParens(); + } else if (FormatTok->is(tok::comma)) { + nextToken(); + addUnwrappedLine(); + } else if (FormatTok->is(tok::semi)) { + nextToken(); + addUnwrappedLine(); + break; + } else if (FormatTok->is(tok::r_brace)) { + addUnwrappedLine(); + break; + } else { + nextToken(); + } + } + + // Parse the class body after the enum's ";" if any. + parseLevel(/*HasOpeningBrace=*/true); + nextToken(); + --Line->Level; + addUnwrappedLine(); } void UnwrappedLineParser::parseRecord() { diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index f047540cf5f..3218afecad3 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -97,6 +97,7 @@ private: void parseNamespace(); void parseAccessSpecifier(); void parseEnum(); + void parseJavaEnumBody(); void parseRecord(); void parseObjCProtocolList(); void parseObjCUntilAtEnd(); diff --git a/clang/unittests/Format/FormatTestJava.cpp b/clang/unittests/Format/FormatTestJava.cpp index 44a7910e989..0ee398aa322 100644 --- a/clang/unittests/Format/FormatTestJava.cpp +++ b/clang/unittests/Format/FormatTestJava.cpp @@ -116,6 +116,44 @@ TEST_F(FormatTestJava, EnumDeclarations) { " void f() {\n" " }\n" "}"); + verifyFormat("public class SomeClass implements SomeInterface {\n" + " enum SomeThing { ABC, CDE }\n" + " void f() {\n" + " }\n" + "}"); + verifyFormat("enum SomeThing {\n" + " ABC,\n" + " CDE;\n" + " void f() {\n" + " }\n" + "}"); + verifyFormat("enum SomeThing {\n" + " ABC(1, \"ABC\"),\n" + " CDE(2, \"CDE\");\n" + " Something(int i, String s) {\n" + " }\n" + "}"); + verifyFormat("enum SomeThing {\n" + " ABC(new int[]{1, 2}),\n" + " CDE(new int[]{2, 3});\n" + " Something(int[] i) {\n" + " }\n" + "}"); + verifyFormat("public enum SomeThing {\n" + " ABC {\n" + " public String toString() {\n" + " return \"ABC\";\n" + " }\n" + " },\n" + " CDE {\n" + " @Override\n" + " public String toString() {\n" + " return \"CDE\";\n" + " }\n" + " };\n" + " public void f() {\n" + " }\n" + "}"); } TEST_F(FormatTestJava, ThrowsDeclarations) { |

