clang-format: Add more options to namespace indentation.

With this patch, clang-format can be configured to:
* not indent in namespace at all (former behavior).
* indent in namespace as in other blocks.
* indent only in inner namespaces (as required by WebKit style).

Also fix alignment of access specifiers in WebKit style.

Patch started by Marek Kurdej. Thank you!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187540 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 0086936..65b1a26 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -53,6 +53,18 @@
   }
 };
 
+template <>
+struct ScalarEnumerationTraits<
+    clang::format::FormatStyle::NamespaceIndentationKind> {
+  static void
+  enumeration(IO &IO,
+              clang::format::FormatStyle::NamespaceIndentationKind &Value) {
+    IO.enumCase(Value, "None", clang::format::FormatStyle::NI_None);
+    IO.enumCase(Value, "Inner", clang::format::FormatStyle::NI_Inner);
+    IO.enumCase(Value, "All", clang::format::FormatStyle::NI_All);
+  }
+};
+
 template <> struct MappingTraits<clang::format::FormatStyle> {
   static void mapping(llvm::yaml::IO &IO, clang::format::FormatStyle &Style) {
     if (IO.outputting()) {
@@ -102,6 +114,7 @@
                    Style.ExperimentalAutoDetectBinPacking);
     IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
     IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
+    IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
     IO.mapOptional("ObjCSpaceBeforeProtocolList",
                    Style.ObjCSpaceBeforeProtocolList);
     IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
@@ -158,6 +171,7 @@
   LLVMStyle.IndentFunctionDeclarationAfterType = false;
   LLVMStyle.IndentWidth = 2;
   LLVMStyle.MaxEmptyLinesToKeep = 1;
+  LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
   LLVMStyle.PointerBindsToType = false;
   LLVMStyle.SpacesBeforeTrailingComments = 1;
@@ -192,6 +206,7 @@
   GoogleStyle.IndentFunctionDeclarationAfterType = true;
   GoogleStyle.IndentWidth = 2;
   GoogleStyle.MaxEmptyLinesToKeep = 1;
+  GoogleStyle.NamespaceIndentation = FormatStyle::NI_None;
   GoogleStyle.ObjCSpaceBeforeProtocolList = false;
   GoogleStyle.PointerBindsToType = true;
   GoogleStyle.SpacesBeforeTrailingComments = 2;
@@ -229,11 +244,13 @@
 
 FormatStyle getWebKitStyle() {
   FormatStyle Style = getLLVMStyle();
-  Style.ColumnLimit = 0;
-  Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
+  Style.AccessModifierOffset = -4;
   Style.BreakBeforeBinaryOperators = true;
+  Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
   Style.BreakConstructorInitializersBeforeComma = true;
+  Style.ColumnLimit = 0;
   Style.IndentWidth = 4;
+  Style.NamespaceIndentation = FormatStyle::NI_Inner;
   Style.PointerBindsToType = true;
   return Style;
 }
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index 939a301..94fbf07 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -319,8 +319,7 @@
   FormatTok = Tokens->setPosition(StoredPosition);
 }
 
-void UnwrappedLineParser::parseBlock(bool MustBeDeclaration,
-                                     unsigned AddLevels) {
+void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel) {
   assert(FormatTok->Tok.is(tok::l_brace) && "'{' expected");
   unsigned InitialLevel = Line->Level;
   nextToken();
@@ -329,7 +328,8 @@
 
   ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
                                           MustBeDeclaration);
-  Line->Level += AddLevels;
+  if (AddLevel)
+    ++Line->Level;
   parseLevel(/*HasOpeningBrace=*/true);
 
   if (!FormatTok->Tok.is(tok::r_brace)) {
@@ -550,7 +550,7 @@
     if (FormatTok->Tok.is(tok::string_literal)) {
       nextToken();
       if (FormatTok->Tok.is(tok::l_brace)) {
-        parseBlock(/*MustBeDeclaration=*/true, 0);
+        parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/false);
         addUnwrappedLine();
         return;
       }
@@ -794,7 +794,10 @@
     if (Style.BreakBeforeBraces == FormatStyle::BS_Linux)
       addUnwrappedLine();
 
-    parseBlock(/*MustBeDeclaration=*/true, 0);
+    bool AddLevel = Style.NamespaceIndentation == FormatStyle::NI_All ||
+                    (Style.NamespaceIndentation == FormatStyle::NI_Inner &&
+                     DeclarationScopeStack.size() > 1);
+    parseBlock(/*MustBeDeclaration=*/true, AddLevel);
     // Munch the semicolon after a namespace. This is more common than one would
     // think. Puttin the semicolon into its own line is very ugly.
     if (FormatTok->Tok.is(tok::semi))
@@ -874,7 +877,7 @@
   if (FormatTok->Tok.is(tok::l_paren))
     parseParens();
   if (FormatTok->Tok.is(tok::l_brace)) {
-    parseBlock(/*MustBeDeclaration=*/false, 1);
+    parseBlock(/*MustBeDeclaration=*/false);
     addUnwrappedLine();
   } else {
     addUnwrappedLine();
diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h
index 0624c4f..d23d157 100644
--- a/lib/Format/UnwrappedLineParser.h
+++ b/lib/Format/UnwrappedLineParser.h
@@ -65,7 +65,7 @@
 private:
   void parseFile();
   void parseLevel(bool HasOpeningBrace);
-  void parseBlock(bool MustBeDeclaration, unsigned AddLevels = 1);
+  void parseBlock(bool MustBeDeclaration, bool AddLevel = true);
   void parsePPDirective();
   void parsePPDefine();
   void parsePPIf();