r221895 - clang-format: [Java] Support Java enums.
Daniel Jasper
djasper at google.com
Thu Nov 13 07:56:28 PST 2014
Author: djasper
Date: Thu Nov 13 09:56:28 2014
New Revision: 221895
URL: http://llvm.org/viewvc/llvm-project?rev=221895&view=rev
Log:
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.
Modified:
cfe/trunk/lib/Format/UnwrappedLineParser.cpp
cfe/trunk/lib/Format/UnwrappedLineParser.h
cfe/trunk/unittests/Format/FormatTestJava.cpp
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=221895&r1=221894&r2=221895&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Thu Nov 13 09:56:28 2014
@@ -311,7 +311,6 @@ void UnwrappedLineParser::calculateBrace
// 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::calculateBrace
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::parseAccessSpe
}
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() {
Modified: cfe/trunk/lib/Format/UnwrappedLineParser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.h?rev=221895&r1=221894&r2=221895&view=diff
==============================================================================
--- cfe/trunk/lib/Format/UnwrappedLineParser.h (original)
+++ cfe/trunk/lib/Format/UnwrappedLineParser.h Thu Nov 13 09:56:28 2014
@@ -97,6 +97,7 @@ private:
void parseNamespace();
void parseAccessSpecifier();
void parseEnum();
+ void parseJavaEnumBody();
void parseRecord();
void parseObjCProtocolList();
void parseObjCUntilAtEnd();
Modified: cfe/trunk/unittests/Format/FormatTestJava.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJava.cpp?rev=221895&r1=221894&r2=221895&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTestJava.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestJava.cpp Thu Nov 13 09:56:28 2014
@@ -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) {
More information about the cfe-commits
mailing list