[clang-format] Add a NamespaceEndCommentsFixer

Summary:
This patch adds a NamespaceEndCommentsFixer TokenAnalyzer for clang-format,
which fixes end namespace comments.
It currently supports inserting and updating existing wrong comments.

Example source:
```
namespace A {
int i;
}

namespace B {
int j;
} // namespace A
```

after formatting:
```
namespace A {
int i;
} // namespace A

namespace B {
int j;
} // namespace B
```

Reviewers: klimek, djasper

Reviewed By: djasper

Subscribers: klimek, mgorny

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

llvm-svn: 296341
diff --git a/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp b/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
new file mode 100644
index 0000000..09f2192
--- /dev/null
+++ b/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
@@ -0,0 +1,350 @@
+//===- NamespaceEndCommentsFixerTest.cpp - Formatting unit tests ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Format/Format.h"
+
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "llvm/Support/Debug.h"
+#include "gtest/gtest.h"
+
+#define DEBUG_TYPE "namespace-end-comments-fixer-test"
+
+namespace clang {
+namespace format {
+namespace {
+
+class NamespaceEndCommentsFixerTest : public ::testing::Test {
+protected:
+  std::string
+  fixNamespaceEndComments(llvm::StringRef Code,
+                          std::vector<tooling::Range> Ranges,
+                          const FormatStyle &Style = getLLVMStyle()) {
+    DEBUG(llvm::errs() << "---\n");
+    DEBUG(llvm::errs() << Code << "\n\n");
+    tooling::Replacements Replaces =
+        clang::format::fixNamespaceEndComments(Style, Code, Ranges, "<stdin>");
+    auto Result = applyAllReplacements(Code, Replaces);
+    EXPECT_TRUE(static_cast<bool>(Result));
+    DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+    return *Result;
+  }
+
+  std::string
+  fixNamespaceEndComments(llvm::StringRef Code,
+                          const FormatStyle &Style = getLLVMStyle()) {
+    return fixNamespaceEndComments(
+        Code,
+        /*Ranges=*/{1, tooling::Range(0, Code.size())}, Style);
+  }
+};
+
+TEST_F(NamespaceEndCommentsFixerTest, AddsEndComment) {
+  EXPECT_EQ("namespace {\n"
+            "  int i;\n"
+            "}// namespace",
+            fixNamespaceEndComments("namespace {\n"
+                                    "  int i;\n"
+                                    "}"));
+  EXPECT_EQ("namespace {\n"
+            "  int i;\n"
+            "}// namespace\n",
+            fixNamespaceEndComments("namespace {\n"
+                                    "  int i;\n"
+                                    "}\n"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "}// namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "}"));
+  EXPECT_EQ("inline namespace A {\n"
+            "  int i;\n"
+            "}// namespace A",
+            fixNamespaceEndComments("inline namespace A {\n"
+                                    "  int i;\n"
+                                    "}"));
+  EXPECT_EQ("namespace ::A {\n"
+            "  int i;\n"
+            "}// namespace ::A",
+            fixNamespaceEndComments("namespace ::A {\n"
+                                    "  int i;\n"
+                                    "}"));
+  EXPECT_EQ("namespace ::A::B {\n"
+            "  int i;\n"
+            "}// namespace ::A::B",
+            fixNamespaceEndComments("namespace ::A::B {\n"
+                                    "  int i;\n"
+                                    "}"));
+  EXPECT_EQ("namespace /**/::/**/A/**/::/**/B/**/ {\n"
+            "  int i;\n"
+            "}// namespace ::A::B",
+            fixNamespaceEndComments("namespace /**/::/**/A/**/::/**/B/**/ {\n"
+                                    "  int i;\n"
+                                    "}"));
+  EXPECT_EQ("namespace A {\n"
+            "namespace B {\n"
+            "  int i;\n"
+            "}// namespace B\n"
+            "}// namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "namespace B {\n"
+                                    "  int i;\n"
+                                    "}\n"
+                                    "}"));
+  EXPECT_EQ("namespace A {\n"
+            "  int a;\n"
+            "}// namespace A\n"
+            "namespace B {\n"
+            "  int b;\n"
+            "}// namespace B",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int a;\n"
+                                    "}\n"
+                                    "namespace B {\n"
+                                    "  int b;\n"
+                                    "}"));
+  EXPECT_EQ("namespace A {\n"
+            "  int a1;\n"
+            "}// namespace A\n"
+            "namespace A {\n"
+            "  int a2;\n"
+            "}// namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int a1;\n"
+                                    "}\n"
+                                    "namespace A {\n"
+                                    "  int a2;\n"
+                                    "}"));
+  EXPECT_EQ("namespace A {\n"
+            "  int a;\n"
+            "}// namespace A\n"
+            "// comment about b\n"
+            "int b;",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int a;\n"
+                                    "}\n"
+                                    "// comment about b\n"
+                                    "int b;"));
+
+  EXPECT_EQ("namespace A {\n"
+            "namespace B {\n"
+            "namespace C {\n"
+            "namespace D {\n"
+            "}// namespace D\n"
+            "}// namespace C\n"
+            "}// namespace B\n"
+            "}// namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "namespace B {\n"
+                                    "namespace C {\n"
+                                    "namespace D {\n"
+                                    "}\n"
+                                    "}\n"
+                                    "}\n"
+                                    "}"));
+}
+
+TEST_F(NamespaceEndCommentsFixerTest, AddsNewlineIfNeeded) {
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "}// namespace A\n"
+            " int j;",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "} int j;"));
+  EXPECT_EQ("namespace {\n"
+            "  int i;\n"
+            "}// namespace\n"
+            " int j;",
+            fixNamespaceEndComments("namespace {\n"
+                                    "  int i;\n"
+                                    "} int j;"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "}// namespace A\n"
+            " namespace B {\n"
+            "  int j;\n"
+            "}// namespace B",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "} namespace B {\n"
+                                    "  int j;\n"
+                                    "}"));
+}
+
+TEST_F(NamespaceEndCommentsFixerTest, DoesNotAddEndCommentForShortNamespace) {
+  EXPECT_EQ("namespace {}", fixNamespaceEndComments("namespace {}"));
+  EXPECT_EQ("namespace A {}", fixNamespaceEndComments("namespace A {}"));
+  EXPECT_EQ("namespace A { int i; }",
+            fixNamespaceEndComments("namespace A { int i; }"));
+}
+
+TEST_F(NamespaceEndCommentsFixerTest, DoesNotAddCommentAfterUnaffectedRBrace) {
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "}",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "}",
+                                    // The range (16, 3) spans the 'int' above.
+                                    /*Ranges=*/{1, tooling::Range(16, 3)}));
+}
+
+TEST_F(NamespaceEndCommentsFixerTest, DoesNotAddCommentAfterRBraceInPPDirective) {
+  EXPECT_EQ("#define SAD \\\n"
+            "namespace A { \\\n"
+            "  int i; \\\n"
+            "}",
+            fixNamespaceEndComments("#define SAD \\\n"
+                                    "namespace A { \\\n"
+                                    "  int i; \\\n"
+                                    "}"));
+}
+
+TEST_F(NamespaceEndCommentsFixerTest, KeepsValidEndComment) {
+  EXPECT_EQ("namespace {\n"
+            "  int i;\n"
+            "} // end anonymous namespace",
+            fixNamespaceEndComments("namespace {\n"
+                                    "  int i;\n"
+                                    "} // end anonymous namespace"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "} /* end of namespace A */",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "} /* end of namespace A */"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "}   //   namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "}   //   namespace A"));
+  EXPECT_EQ("namespace A::B {\n"
+            "  int i;\n"
+            "} // end namespace A::B",
+            fixNamespaceEndComments("namespace A::B {\n"
+                                    "  int i;\n"
+                                    "} // end namespace A::B"));
+}
+
+TEST_F(NamespaceEndCommentsFixerTest, UpdatesInvalidEndLineComment) {
+  EXPECT_EQ("namespace {\n"
+            "  int i;\n"
+            "} // namespace",
+            fixNamespaceEndComments("namespace {\n"
+                                    "  int i;\n"
+                                    "} // namespace A"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "} // namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "} // namespace"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "} // namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "} //"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "} // namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "} //"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "} // namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "} // banamespace A"));
+
+  // Updates invalid line comments even for short namespaces.
+  EXPECT_EQ("namespace A {} // namespace A",
+            fixNamespaceEndComments("namespace A {} // namespace"));
+}
+
+TEST_F(NamespaceEndCommentsFixerTest, UpdatesInvalidEndBlockComment) {
+  EXPECT_EQ("namespace {\n"
+            "  int i;\n"
+            "} // namespace",
+            fixNamespaceEndComments("namespace {\n"
+                                    "  int i;\n"
+                                    "} /* namespace A */"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "}  // namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "}  /* end namespace */"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "} // namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "} /**/"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "} // namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "} /* end unnamed namespace */"));
+  EXPECT_EQ("namespace A {\n"
+            "  int i;\n"
+            "} // namespace A",
+            fixNamespaceEndComments("namespace A {\n"
+                                    "  int i;\n"
+                                    "} /* banamespace A */"));
+  EXPECT_EQ("namespace A {} // namespace A",
+            fixNamespaceEndComments("namespace A {} /**/"));
+}
+
+TEST_F(NamespaceEndCommentsFixerTest,
+       DoesNotAddEndCommentForNamespacesControlledByMacros) {
+  EXPECT_EQ("#ifdef 1\n"
+            "namespace A {\n"
+            "#elseif\n"
+            "namespace B {\n"
+            "#endif\n"
+            "  int i;\n"
+            "}\n"
+            "}\n",
+            fixNamespaceEndComments("#ifdef 1\n"
+                                    "namespace A {\n"
+                                    "#elseif\n"
+                                    "namespace B {\n"
+                                    "#endif\n"
+                                    "  int i;\n"
+                                    "}\n"
+                                    "}\n"));
+}
+
+TEST_F(NamespaceEndCommentsFixerTest,
+       DoesNotAddEndCommentForNamespacesInMacroDeclarations) {
+  EXPECT_EQ("#ifdef 1\n"
+            "namespace A {\n"
+            "#elseif\n"
+            "namespace B {\n"
+            "#endif\n"
+            "  int i;\n"
+            "}\n"
+            "}\n",
+            fixNamespaceEndComments("#ifdef 1\n"
+                                    "namespace A {\n"
+                                    "#elseif\n"
+                                    "namespace B {\n"
+                                    "#endif\n"
+                                    "  int i;\n"
+                                    "}\n"
+                                    "}\n"));
+}
+} // end namespace
+} // end namespace format
+} // end namespace clang