clang-format: Add CompactNamespaces option

Summary:
Add CompactNamespaces option, to pack namespace declarations on the
same line (somewhat similar to C++17 nested namespace definition).

With this option, consecutive namespace declarations are kept on the
same line:

  namespace foo { namespace bar {
      ...
  }} // namespace foo::bar

Reviewers: krasimir, djasper, klimek

Reviewed By: djasper

Subscribers: kimgr, cfe-commits, klimek

Tags: #clang-tools-extra

Differential Revision: https://reviews.llvm.org/D32480

llvm-svn: 305384
diff --git a/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp b/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
index 6c2d369..92f3421 100644
--- a/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
+++ b/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
@@ -185,6 +185,41 @@
                                     "}\n"
                                     "}"));
 
+  // Add comment for namespaces which will be 'compacted'
+  FormatStyle CompactNamespacesStyle = getLLVMStyle();
+  CompactNamespacesStyle.CompactNamespaces = true;
+  EXPECT_EQ("namespace out { namespace in {\n"
+            "int i;\n"
+            "int j;\n"
+            "}}// namespace out::in",
+            fixNamespaceEndComments("namespace out { namespace in {\n"
+                                    "int i;\n"
+                                    "int j;\n"
+                                    "}}",
+                                    CompactNamespacesStyle));
+  EXPECT_EQ("namespace out {\n"
+            "namespace in {\n"
+            "int i;\n"
+            "int j;\n"
+            "}\n"
+            "}// namespace out::in",
+            fixNamespaceEndComments("namespace out {\n"
+                                    "namespace in {\n"
+                                    "int i;\n"
+                                    "int j;\n"
+                                    "}\n"
+                                    "}",
+                                    CompactNamespacesStyle));
+  EXPECT_EQ("namespace out { namespace in {\n"
+            "int i;\n"
+            "int j;\n"
+            "};}// namespace out::in",
+            fixNamespaceEndComments("namespace out { namespace in {\n"
+                                    "int i;\n"
+                                    "int j;\n"
+                                    "};}",
+                                    CompactNamespacesStyle));
+
   // Adds an end comment after a semicolon.
   EXPECT_EQ("namespace {\n"
             "  int i;\n"
@@ -388,6 +423,27 @@
             fixNamespaceEndComments("namespace A {} // namespace"));
   EXPECT_EQ("namespace A {}; // namespace A",
             fixNamespaceEndComments("namespace A {}; // namespace"));
+
+  // Update invalid comments for compacted namespaces.
+  FormatStyle CompactNamespacesStyle = getLLVMStyle();
+  CompactNamespacesStyle.CompactNamespaces = true;
+  EXPECT_EQ("namespace out { namespace in {\n"
+            "}} // namespace out::in",
+            fixNamespaceEndComments("namespace out { namespace in {\n"
+                                    "}} // namespace out",
+                                    CompactNamespacesStyle));
+  EXPECT_EQ("namespace out { namespace in {\n"
+            "}} // namespace out::in",
+            fixNamespaceEndComments("namespace out { namespace in {\n"
+                                    "}} // namespace in",
+                                    CompactNamespacesStyle));
+  EXPECT_EQ("namespace out { namespace in {\n"
+            "}\n"
+            "} // namespace out::in",
+            fixNamespaceEndComments("namespace out { namespace in {\n"
+                                    "}// banamespace in\n"
+                                    "} // namespace out",
+                                    CompactNamespacesStyle));
 }
 
 TEST_F(NamespaceEndCommentsFixerTest, UpdatesInvalidEndBlockComment) {