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