xref: /llvm-project/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp (revision 1c58208d899285318c89e069268145c85ec33368)
16f6f88ffSksyx //===- DefinitionBlockSeparatorTest.cpp - Formatting unit tests -----------===//
26f6f88ffSksyx //
36f6f88ffSksyx // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46f6f88ffSksyx // See https://llvm.org/LICENSE.txt for license information.
56f6f88ffSksyx // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66f6f88ffSksyx //
76f6f88ffSksyx //===----------------------------------------------------------------------===//
86f6f88ffSksyx 
96f6f88ffSksyx #include "FormatTestUtils.h"
106f6f88ffSksyx #include "clang/Format/Format.h"
116f6f88ffSksyx 
126f6f88ffSksyx #include "llvm/Support/Debug.h"
136f6f88ffSksyx #include "gtest/gtest.h"
146f6f88ffSksyx 
156f6f88ffSksyx #define DEBUG_TYPE "definition-block-separator-test"
166f6f88ffSksyx 
176f6f88ffSksyx namespace clang {
186f6f88ffSksyx namespace format {
196f6f88ffSksyx namespace {
206f6f88ffSksyx 
21*1c58208dSOwen Pan class DefinitionBlockSeparatorTest : public testing::Test {
226f6f88ffSksyx protected:
236f6f88ffSksyx   static std::string
separateDefinitionBlocks(StringRef Code,const std::vector<tooling::Range> & Ranges,const FormatStyle & Style=getLLVMStyle ())24*1c58208dSOwen Pan   separateDefinitionBlocks(StringRef Code,
256f6f88ffSksyx                            const std::vector<tooling::Range> &Ranges,
266f6f88ffSksyx                            const FormatStyle &Style = getLLVMStyle()) {
276f6f88ffSksyx     LLVM_DEBUG(llvm::errs() << "---\n");
286f6f88ffSksyx     LLVM_DEBUG(llvm::errs() << Code << "\n\n");
296f6f88ffSksyx     tooling::Replacements Replaces = reformat(Style, Code, Ranges, "<stdin>");
306f6f88ffSksyx     auto Result = applyAllReplacements(Code, Replaces);
316f6f88ffSksyx     EXPECT_TRUE(static_cast<bool>(Result));
326f6f88ffSksyx     LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
336f6f88ffSksyx     return *Result;
346f6f88ffSksyx   }
356f6f88ffSksyx 
366f6f88ffSksyx   static std::string
separateDefinitionBlocks(StringRef Code,const FormatStyle & Style=getLLVMStyle ())37*1c58208dSOwen Pan   separateDefinitionBlocks(StringRef Code,
386f6f88ffSksyx                            const FormatStyle &Style = getLLVMStyle()) {
396f6f88ffSksyx     return separateDefinitionBlocks(
406f6f88ffSksyx         Code,
416f6f88ffSksyx         /*Ranges=*/{1, tooling::Range(0, Code.size())}, Style);
426f6f88ffSksyx   }
436f6f88ffSksyx 
_verifyFormat(const char * File,int Line,StringRef Code,const FormatStyle & Style=getLLVMStyle (),StringRef ExpectedCode="",bool Inverse=true)44*1c58208dSOwen Pan   static void _verifyFormat(const char *File, int Line, StringRef Code,
456f6f88ffSksyx                             const FormatStyle &Style = getLLVMStyle(),
46*1c58208dSOwen Pan                             StringRef ExpectedCode = "", bool Inverse = true) {
47*1c58208dSOwen Pan     testing::ScopedTrace t(File, Line, testing::Message() << Code.str());
486f6f88ffSksyx     bool HasOriginalCode = true;
496f6f88ffSksyx     if (ExpectedCode == "") {
506f6f88ffSksyx       ExpectedCode = Code;
516f6f88ffSksyx       HasOriginalCode = false;
526f6f88ffSksyx     }
536f6f88ffSksyx 
54b58616c2SMarek Kurdej     EXPECT_EQ(ExpectedCode, separateDefinitionBlocks(ExpectedCode, Style))
55b58616c2SMarek Kurdej         << "Expected code is not stable";
56b58616c2SMarek Kurdej     if (Inverse) {
576f6f88ffSksyx       FormatStyle InverseStyle = Style;
586f6f88ffSksyx       if (Style.SeparateDefinitionBlocks == FormatStyle::SDS_Always)
596f6f88ffSksyx         InverseStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Never;
606f6f88ffSksyx       else
616f6f88ffSksyx         InverseStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
62311a00c3SMarek Kurdej       EXPECT_NE(ExpectedCode,
63311a00c3SMarek Kurdej                 separateDefinitionBlocks(ExpectedCode, InverseStyle))
646f6f88ffSksyx           << "Inverse formatting makes no difference";
65b58616c2SMarek Kurdej     }
666f6f88ffSksyx     std::string CodeToFormat =
676f6f88ffSksyx         HasOriginalCode ? Code.str() : removeEmptyLines(Code);
686f6f88ffSksyx     std::string Result = separateDefinitionBlocks(CodeToFormat, Style);
69311a00c3SMarek Kurdej     EXPECT_EQ(ExpectedCode, Result) << "Test failed. Formatted:\n" << Result;
706f6f88ffSksyx   }
716f6f88ffSksyx 
removeEmptyLines(StringRef Code)72*1c58208dSOwen Pan   static std::string removeEmptyLines(StringRef Code) {
736f6f88ffSksyx     std::string Result = "";
746f6f88ffSksyx     for (auto Char : Code.str()) {
756f6f88ffSksyx       if (Result.size()) {
766f6f88ffSksyx         auto LastChar = Result.back();
776f6f88ffSksyx         if ((Char == '\n' && LastChar == '\n') ||
78554efc22Sowenca             (Char == '\r' && (LastChar == '\r' || LastChar == '\n'))) {
796f6f88ffSksyx           continue;
806f6f88ffSksyx         }
81554efc22Sowenca       }
826f6f88ffSksyx       Result.push_back(Char);
836f6f88ffSksyx     }
846f6f88ffSksyx     return Result;
856f6f88ffSksyx   }
866f6f88ffSksyx };
876f6f88ffSksyx 
8869ecd248SMarek Kurdej #define verifyFormat(...) _verifyFormat(__FILE__, __LINE__, __VA_ARGS__)
8969ecd248SMarek Kurdej 
TEST_F(DefinitionBlockSeparatorTest,Basic)906f6f88ffSksyx TEST_F(DefinitionBlockSeparatorTest, Basic) {
916f6f88ffSksyx   FormatStyle Style = getLLVMStyle();
926f6f88ffSksyx   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
936f6f88ffSksyx   verifyFormat("int foo(int i, int j) {\n"
946f6f88ffSksyx                "  int r = i + j;\n"
956f6f88ffSksyx                "  return r;\n"
966f6f88ffSksyx                "}\n"
976f6f88ffSksyx                "\n"
986f6f88ffSksyx                "int bar(int j, int k) {\n"
996f6f88ffSksyx                "  int r = j + k;\n"
1006f6f88ffSksyx                "  return r;\n"
1016f6f88ffSksyx                "}",
1026f6f88ffSksyx                Style);
1036f6f88ffSksyx 
1046f6f88ffSksyx   verifyFormat("struct foo {\n"
1056f6f88ffSksyx                "  int i, j;\n"
1066f6f88ffSksyx                "};\n"
1076f6f88ffSksyx                "\n"
1086f6f88ffSksyx                "struct bar {\n"
1096f6f88ffSksyx                "  int j, k;\n"
1106f6f88ffSksyx                "};",
1116f6f88ffSksyx                Style);
1126f6f88ffSksyx 
113a70549aeSksyx   verifyFormat("union foo {\n"
114a70549aeSksyx                "  int i, j;\n"
115a70549aeSksyx                "};\n"
116a70549aeSksyx                "\n"
117a70549aeSksyx                "union bar {\n"
118a70549aeSksyx                "  int j, k;\n"
119a70549aeSksyx                "};",
120a70549aeSksyx                Style);
121a70549aeSksyx 
1226f6f88ffSksyx   verifyFormat("class foo {\n"
1236f6f88ffSksyx                "  int i, j;\n"
1246f6f88ffSksyx                "};\n"
1256f6f88ffSksyx                "\n"
1266f6f88ffSksyx                "class bar {\n"
1276f6f88ffSksyx                "  int j, k;\n"
1286f6f88ffSksyx                "};",
1296f6f88ffSksyx                Style);
1306f6f88ffSksyx 
1316f6f88ffSksyx   verifyFormat("namespace foo {\n"
1326f6f88ffSksyx                "int i, j;\n"
1336f6f88ffSksyx                "}\n"
1346f6f88ffSksyx                "\n"
1356f6f88ffSksyx                "namespace bar {\n"
1366f6f88ffSksyx                "int j, k;\n"
1376f6f88ffSksyx                "}",
1386f6f88ffSksyx                Style);
1396f6f88ffSksyx 
1406f6f88ffSksyx   verifyFormat("enum Foo { FOO, BAR };\n"
1416f6f88ffSksyx                "\n"
14288934a82SOwen Pan                "enum Bar { FOOBAR, BARFOO };",
1436f6f88ffSksyx                Style);
1445e5efd8aSksyx 
1455e5efd8aSksyx   FormatStyle BreakAfterReturnTypeStyle = Style;
146d821650eSrmarker   BreakAfterReturnTypeStyle.BreakAfterReturnType = FormatStyle::RTBS_All;
1475e5efd8aSksyx   // Test uppercased long typename
1485e5efd8aSksyx   verifyFormat("class Foo {\n"
1495e5efd8aSksyx                "  void\n"
1505e5efd8aSksyx                "  Bar(int t, int p) {\n"
1515e5efd8aSksyx                "    int r = t + p;\n"
1525e5efd8aSksyx                "    return r;\n"
1535e5efd8aSksyx                "  }\n"
1545e5efd8aSksyx                "\n"
1555e5efd8aSksyx                "  HRESULT\n"
1565e5efd8aSksyx                "  Foobar(int t, int p) {\n"
1575e5efd8aSksyx                "    int r = t * p;\n"
1585e5efd8aSksyx                "    return r;\n"
1595e5efd8aSksyx                "  }\n"
16088934a82SOwen Pan                "}",
1615e5efd8aSksyx                BreakAfterReturnTypeStyle);
1625e5efd8aSksyx }
1635e5efd8aSksyx 
TEST_F(DefinitionBlockSeparatorTest,FormatConflict)1645e5efd8aSksyx TEST_F(DefinitionBlockSeparatorTest, FormatConflict) {
1655e5efd8aSksyx   FormatStyle Style = getLLVMStyle();
1665e5efd8aSksyx   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
167*1c58208dSOwen Pan   StringRef Code = "class Test {\n"
1685e5efd8aSksyx                    "public:\n"
1695e5efd8aSksyx                    "  static void foo() {\n"
1705e5efd8aSksyx                    "    int t;\n"
1715e5efd8aSksyx                    "    return 1;\n"
1725e5efd8aSksyx                    "  }\n"
1735e5efd8aSksyx                    "};";
1745e5efd8aSksyx   std::vector<tooling::Range> Ranges = {1, tooling::Range(0, Code.size())};
1755e5efd8aSksyx   EXPECT_EQ(reformat(Style, Code, Ranges, "<stdin>").size(), 0u);
1765e5efd8aSksyx }
1775e5efd8aSksyx 
TEST_F(DefinitionBlockSeparatorTest,CommentBlock)1785e5efd8aSksyx TEST_F(DefinitionBlockSeparatorTest, CommentBlock) {
1795e5efd8aSksyx   FormatStyle Style = getLLVMStyle();
1805e5efd8aSksyx   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
1815e5efd8aSksyx   std::string Prefix = "enum Foo { FOO, BAR };\n"
1825e5efd8aSksyx                        "\n"
1835e5efd8aSksyx                        "/*\n"
1845e5efd8aSksyx                        "test1\n"
1855e5efd8aSksyx                        "test2\n"
1865e5efd8aSksyx                        "*/\n"
1875e5efd8aSksyx                        "int foo(int i, int j) {\n"
1885e5efd8aSksyx                        "  int r = i + j;\n"
1895e5efd8aSksyx                        "  return r;\n"
1905e5efd8aSksyx                        "}\n";
1915e5efd8aSksyx   std::string Suffix = "enum Bar { FOOBAR, BARFOO };\n"
1925e5efd8aSksyx                        "\n"
1935e5efd8aSksyx                        "/* Comment block in one line*/\n"
1945e5efd8aSksyx                        "int bar3(int j, int k) {\n"
1955e5efd8aSksyx                        "  // A comment\n"
1965e5efd8aSksyx                        "  int r = j % k;\n"
1975e5efd8aSksyx                        "  return r;\n"
1985e5efd8aSksyx                        "}\n";
1995e5efd8aSksyx   std::string CommentedCode = "/*\n"
2005e5efd8aSksyx                               "int bar2(int j, int k) {\n"
2015e5efd8aSksyx                               "  int r = j / k;\n"
2025e5efd8aSksyx                               "  return r;\n"
2035e5efd8aSksyx                               "}\n"
2045e5efd8aSksyx                               "*/\n";
2055e5efd8aSksyx   verifyFormat(removeEmptyLines(Prefix) + "\n" + CommentedCode + "\n" +
2065e5efd8aSksyx                    removeEmptyLines(Suffix),
2075e5efd8aSksyx                Style, Prefix + "\n" + CommentedCode + "\n" + Suffix);
2085e5efd8aSksyx   verifyFormat(removeEmptyLines(Prefix) + "\n" + CommentedCode +
2095e5efd8aSksyx                    removeEmptyLines(Suffix),
2105e5efd8aSksyx                Style, Prefix + "\n" + CommentedCode + Suffix);
2116f6f88ffSksyx }
2126f6f88ffSksyx 
TEST_F(DefinitionBlockSeparatorTest,UntouchBlockStartStyle)213ee25a327Sksyx TEST_F(DefinitionBlockSeparatorTest, UntouchBlockStartStyle) {
214ee25a327Sksyx   // Returns a std::pair of two strings, with the first one for passing into
215ee25a327Sksyx   // Always test and the second one be the expected result of the first string.
216ee25a327Sksyx   auto MakeUntouchTest = [&](std::string BlockHeader, std::string BlockChanger,
217ee25a327Sksyx                              std::string BlockFooter, bool BlockEndNewLine) {
218ee25a327Sksyx     std::string CodePart1 = "enum Foo { FOO, BAR };\n"
219ee25a327Sksyx                             "\n"
220ee25a327Sksyx                             "/*\n"
221ee25a327Sksyx                             "test1\n"
222ee25a327Sksyx                             "test2\n"
223ee25a327Sksyx                             "*/\n"
224ee25a327Sksyx                             "int foo(int i, int j) {\n"
225ee25a327Sksyx                             "  int r = i + j;\n"
226ee25a327Sksyx                             "  return r;\n"
227ee25a327Sksyx                             "}\n";
228ee25a327Sksyx     std::string CodePart2 = "/* Comment block in one line*/\n"
229ee25a327Sksyx                             "enum Bar { FOOBAR, BARFOO };\n"
230ee25a327Sksyx                             "\n"
231ee25a327Sksyx                             "int bar3(int j, int k) {\n"
232ee25a327Sksyx                             "  // A comment\n"
233ee25a327Sksyx                             "  int r = j % k;\n"
234ee25a327Sksyx                             "  return r;\n"
235ee25a327Sksyx                             "}\n";
236ee25a327Sksyx     std::string CodePart3 = "int bar2(int j, int k) {\n"
237ee25a327Sksyx                             "  int r = j / k;\n"
238ee25a327Sksyx                             "  return r;\n"
239ee25a327Sksyx                             "}\n";
240ee25a327Sksyx     std::string ConcatAll = BlockHeader + CodePart1 + BlockChanger + CodePart2 +
241ee25a327Sksyx                             BlockFooter + (BlockEndNewLine ? "\n" : "") +
242ee25a327Sksyx                             CodePart3;
243ee25a327Sksyx     return std::make_pair(BlockHeader + removeEmptyLines(CodePart1) +
244ee25a327Sksyx                               BlockChanger + removeEmptyLines(CodePart2) +
245ee25a327Sksyx                               BlockFooter + removeEmptyLines(CodePart3),
246ee25a327Sksyx                           ConcatAll);
247ee25a327Sksyx   };
248ee25a327Sksyx 
249ee25a327Sksyx   FormatStyle AlwaysStyle = getLLVMStyle();
250ee25a327Sksyx   AlwaysStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
251ee25a327Sksyx 
252ee25a327Sksyx   FormatStyle NeverStyle = getLLVMStyle();
253ee25a327Sksyx   NeverStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Never;
254ee25a327Sksyx 
2555e5efd8aSksyx   auto TestKit = MakeUntouchTest("/* FOOBAR */\n"
2565e5efd8aSksyx                                  "#ifdef FOO\n\n",
2575e5efd8aSksyx                                  "\n#elifndef BAR\n\n", "\n#endif\n\n", false);
258ee25a327Sksyx   verifyFormat(TestKit.first, AlwaysStyle, TestKit.second);
259ee25a327Sksyx   verifyFormat(TestKit.second, NeverStyle, removeEmptyLines(TestKit.second));
260ee25a327Sksyx 
2615e5efd8aSksyx   TestKit = MakeUntouchTest("/* FOOBAR */\n"
2625e5efd8aSksyx                             "#ifdef FOO\n",
2635e5efd8aSksyx                             "#elifndef BAR\n", "#endif\n", false);
264ee25a327Sksyx   verifyFormat(TestKit.first, AlwaysStyle, TestKit.second);
265ee25a327Sksyx   verifyFormat(TestKit.second, NeverStyle, removeEmptyLines(TestKit.second));
266ee25a327Sksyx 
267ee25a327Sksyx   TestKit = MakeUntouchTest("namespace Ns {\n\n",
268ee25a327Sksyx                             "\n} // namespace Ns\n\n"
269ee25a327Sksyx                             "namespace {\n\n",
270ee25a327Sksyx                             "\n} // namespace\n", true);
271ee25a327Sksyx   verifyFormat(TestKit.first, AlwaysStyle, TestKit.second);
272ee25a327Sksyx   verifyFormat(TestKit.second, NeverStyle, removeEmptyLines(TestKit.second));
273ee25a327Sksyx 
274ee25a327Sksyx   TestKit = MakeUntouchTest("namespace Ns {\n",
275ee25a327Sksyx                             "} // namespace Ns\n\n"
276ee25a327Sksyx                             "namespace {\n",
277ee25a327Sksyx                             "} // namespace\n", true);
278ee25a327Sksyx   verifyFormat(TestKit.first, AlwaysStyle, TestKit.second);
279ee25a327Sksyx   verifyFormat(TestKit.second, NeverStyle, removeEmptyLines(TestKit.second));
280ee25a327Sksyx }
281ee25a327Sksyx 
TEST_F(DefinitionBlockSeparatorTest,Always)2826f6f88ffSksyx TEST_F(DefinitionBlockSeparatorTest, Always) {
2836f6f88ffSksyx   FormatStyle Style = getLLVMStyle();
2846f6f88ffSksyx   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
28558a71c66SOwen Pan 
28658a71c66SOwen Pan   verifyFormat("// clang-format off\n"
28758a71c66SOwen Pan                "template<class T>\n"
28858a71c66SOwen Pan                "concept C = not A<S<T>>;\n"
28958a71c66SOwen Pan                "// clang-format on\n"
29058a71c66SOwen Pan                "\n"
29158a71c66SOwen Pan                "struct E {};",
29258a71c66SOwen Pan                Style);
29358a71c66SOwen Pan 
2946f6f88ffSksyx   std::string Prefix = "namespace {\n";
295ee25a327Sksyx   std::string Infix = "\n"
296ee25a327Sksyx                       "// Enum test1\n"
297ee25a327Sksyx                       "// Enum test2\n"
298ee25a327Sksyx                       "enum Foo { FOO, BAR };\n"
2996f6f88ffSksyx                       "\n"
300ee25a327Sksyx                       "/*\n"
301ee25a327Sksyx                       "test1\n"
302ee25a327Sksyx                       "test2\n"
303ee25a327Sksyx                       "*/\n"
3045e5efd8aSksyx                       "/*const*/ int foo(int i, int j) {\n"
3056f6f88ffSksyx                       "  int r = i + j;\n"
3066f6f88ffSksyx                       "  return r;\n"
3076f6f88ffSksyx                       "}\n"
3086f6f88ffSksyx                       "\n"
309ee25a327Sksyx                       "// Foobar\n"
3106f6f88ffSksyx                       "int i, j, k;\n"
3116f6f88ffSksyx                       "\n"
312ee25a327Sksyx                       "// Comment for function\n"
313ee25a327Sksyx                       "// Comment line 2\n"
314ee25a327Sksyx                       "// Comment line 3\n"
3156f6f88ffSksyx                       "int bar(int j, int k) {\n"
3165e5efd8aSksyx                       "  {\n"
3176f6f88ffSksyx                       "    int r = j * k;\n"
3186f6f88ffSksyx                       "    return r;\n"
3196f6f88ffSksyx                       "  }\n"
3205e5efd8aSksyx                       "}\n"
3216f6f88ffSksyx                       "\n"
322ee25a327Sksyx                       "int bar2(int j, int k) {\n"
323ee25a327Sksyx                       "  int r = j / k;\n"
324ee25a327Sksyx                       "  return r;\n"
325ee25a327Sksyx                       "}\n"
326ee25a327Sksyx                       "\n"
327ee25a327Sksyx                       "/* Comment block in one line*/\n"
3286f6f88ffSksyx                       "enum Bar { FOOBAR, BARFOO };\n"
329ee25a327Sksyx                       "\n"
3305e5efd8aSksyx                       "int bar3(int j, int k, const enum Bar b) {\n"
331ee25a327Sksyx                       "  // A comment\n"
332ee25a327Sksyx                       "  int r = j % k;\n"
333a70549aeSksyx                       "  if (struct S = getS()) {\n"
334a70549aeSksyx                       "    // if condition\n"
335a70549aeSksyx                       "  }\n"
336ee25a327Sksyx                       "  return r;\n"
337ee25a327Sksyx                       "}\n";
338ee25a327Sksyx   std::string Postfix = "\n"
339ee25a327Sksyx                         "} // namespace\n"
340ee25a327Sksyx                         "\n"
341ee25a327Sksyx                         "namespace T {\n"
342ee25a327Sksyx                         "int i, j, k;\n"
343ee25a327Sksyx                         "} // namespace T";
344ee25a327Sksyx   verifyFormat(Prefix + removeEmptyLines(Infix) + removeEmptyLines(Postfix),
345ee25a327Sksyx                Style, Prefix + Infix + Postfix);
3466f6f88ffSksyx }
3476f6f88ffSksyx 
TEST_F(DefinitionBlockSeparatorTest,Never)3486f6f88ffSksyx TEST_F(DefinitionBlockSeparatorTest, Never) {
3496f6f88ffSksyx   FormatStyle Style = getLLVMStyle();
3506f6f88ffSksyx   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Never;
3516f6f88ffSksyx   std::string Prefix = "namespace {\n";
352ee25a327Sksyx   std::string Postfix = "// Enum test1\n"
353ee25a327Sksyx                         "// Enum test2\n"
354ee25a327Sksyx                         "enum Foo { FOO, BAR };\n"
3556f6f88ffSksyx                         "\n"
356ee25a327Sksyx                         "/*\n"
357ee25a327Sksyx                         "test1\n"
358ee25a327Sksyx                         "test2\n"
359ee25a327Sksyx                         "*/\n"
3605e5efd8aSksyx                         "/*const*/ int foo(int i, int j) {\n"
3616f6f88ffSksyx                         "  int r = i + j;\n"
3626f6f88ffSksyx                         "  return r;\n"
3636f6f88ffSksyx                         "}\n"
3646f6f88ffSksyx                         "\n"
365ee25a327Sksyx                         "// Foobar\n"
3666f6f88ffSksyx                         "int i, j, k;\n"
3676f6f88ffSksyx                         "\n"
368ee25a327Sksyx                         "// Comment for function\n"
369ee25a327Sksyx                         "// Comment line 2\n"
370ee25a327Sksyx                         "// Comment line 3\n"
3716f6f88ffSksyx                         "int bar(int j, int k) {\n"
3725e5efd8aSksyx                         "  {\n"
3736f6f88ffSksyx                         "    int r = j * k;\n"
3746f6f88ffSksyx                         "    return r;\n"
3756f6f88ffSksyx                         "  }\n"
3765e5efd8aSksyx                         "}\n"
3776f6f88ffSksyx                         "\n"
378ee25a327Sksyx                         "int bar2(int j, int k) {\n"
379ee25a327Sksyx                         "  int r = j / k;\n"
380ee25a327Sksyx                         "  return r;\n"
381ee25a327Sksyx                         "}\n"
382ee25a327Sksyx                         "\n"
383ee25a327Sksyx                         "/* Comment block in one line*/\n"
3846f6f88ffSksyx                         "enum Bar { FOOBAR, BARFOO };\n"
385ee25a327Sksyx                         "\n"
3865e5efd8aSksyx                         "int bar3(int j, int k, const enum Bar b) {\n"
387ee25a327Sksyx                         "  // A comment\n"
388ee25a327Sksyx                         "  int r = j % k;\n"
389a70549aeSksyx                         "  if (struct S = getS()) {\n"
390a70549aeSksyx                         "    // if condition\n"
391a70549aeSksyx                         "  }\n"
392ee25a327Sksyx                         "  return r;\n"
393ee25a327Sksyx                         "}\n"
3946f6f88ffSksyx                         "} // namespace";
3956f6f88ffSksyx   verifyFormat(Prefix + "\n\n\n" + Postfix, Style,
3966f6f88ffSksyx                Prefix + removeEmptyLines(Postfix));
3976f6f88ffSksyx }
3986f6f88ffSksyx 
TEST_F(DefinitionBlockSeparatorTest,OpeningBracketOwnsLine)3996f6f88ffSksyx TEST_F(DefinitionBlockSeparatorTest, OpeningBracketOwnsLine) {
4006f6f88ffSksyx   FormatStyle Style = getLLVMStyle();
4016f6f88ffSksyx   Style.BreakBeforeBraces = FormatStyle::BS_Allman;
4026f6f88ffSksyx   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
403ee25a327Sksyx   verifyFormat("namespace NS\n"
404ee25a327Sksyx                "{\n"
405ee25a327Sksyx                "// Enum test1\n"
406ee25a327Sksyx                "// Enum test2\n"
407ee25a327Sksyx                "enum Foo\n"
4086f6f88ffSksyx                "{\n"
4096f6f88ffSksyx                "  FOO,\n"
4106f6f88ffSksyx                "  BAR\n"
4116f6f88ffSksyx                "};\n"
4126f6f88ffSksyx                "\n"
413ee25a327Sksyx                "/*\n"
414ee25a327Sksyx                "test1\n"
415ee25a327Sksyx                "test2\n"
416ee25a327Sksyx                "*/\n"
4175e5efd8aSksyx                "/*const*/ int foo(int i, int j)\n"
4186f6f88ffSksyx                "{\n"
4196f6f88ffSksyx                "  int r = i + j;\n"
4206f6f88ffSksyx                "  return r;\n"
4216f6f88ffSksyx                "}\n"
4226f6f88ffSksyx                "\n"
423ee25a327Sksyx                "// Foobar\n"
4246f6f88ffSksyx                "int i, j, k;\n"
4256f6f88ffSksyx                "\n"
426ee25a327Sksyx                "// Comment for function\n"
427ee25a327Sksyx                "// Comment line 2\n"
428ee25a327Sksyx                "// Comment line 3\n"
4296f6f88ffSksyx                "int bar(int j, int k)\n"
4306f6f88ffSksyx                "{\n"
4315e5efd8aSksyx                "  {\n"
4326f6f88ffSksyx                "    int r = j * k;\n"
4336f6f88ffSksyx                "    return r;\n"
4346f6f88ffSksyx                "  }\n"
4355e5efd8aSksyx                "}\n"
4366f6f88ffSksyx                "\n"
437ee25a327Sksyx                "int bar2(int j, int k)\n"
438ee25a327Sksyx                "{\n"
439ee25a327Sksyx                "  int r = j / k;\n"
440ee25a327Sksyx                "  return r;\n"
441ee25a327Sksyx                "}\n"
442ee25a327Sksyx                "\n"
4436f6f88ffSksyx                "enum Bar\n"
4446f6f88ffSksyx                "{\n"
4456f6f88ffSksyx                "  FOOBAR,\n"
4466f6f88ffSksyx                "  BARFOO\n"
447ee25a327Sksyx                "};\n"
448ee25a327Sksyx                "\n"
4495e5efd8aSksyx                "int bar3(int j, int k, const enum Bar b)\n"
450ee25a327Sksyx                "{\n"
451ee25a327Sksyx                "  // A comment\n"
452ee25a327Sksyx                "  int r = j % k;\n"
453a70549aeSksyx                "  if (struct S = getS())\n"
454a70549aeSksyx                "  {\n"
455a70549aeSksyx                "    // if condition\n"
456a70549aeSksyx                "  }\n"
457ee25a327Sksyx                "  return r;\n"
458ee25a327Sksyx                "}\n"
459ee25a327Sksyx                "} // namespace NS",
4606f6f88ffSksyx                Style);
4616f6f88ffSksyx }
4626f6f88ffSksyx 
TEST_F(DefinitionBlockSeparatorTest,TryBlocks)463b58616c2SMarek Kurdej TEST_F(DefinitionBlockSeparatorTest, TryBlocks) {
464b58616c2SMarek Kurdej   FormatStyle Style = getLLVMStyle();
465b58616c2SMarek Kurdej   Style.BreakBeforeBraces = FormatStyle::BS_Allman;
466b58616c2SMarek Kurdej   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
467b58616c2SMarek Kurdej   verifyFormat("void FunctionWithInternalTry()\n"
468b58616c2SMarek Kurdej                "{\n"
469b58616c2SMarek Kurdej                "  try\n"
470b58616c2SMarek Kurdej                "  {\n"
471b58616c2SMarek Kurdej                "    return;\n"
472b58616c2SMarek Kurdej                "  }\n"
473b58616c2SMarek Kurdej                "  catch (const std::exception &)\n"
474b58616c2SMarek Kurdej                "  {\n"
475b58616c2SMarek Kurdej                "  }\n"
476b58616c2SMarek Kurdej                "}",
477b58616c2SMarek Kurdej                Style, "", /*Inverse=*/false);
478b58616c2SMarek Kurdej   verifyFormat("void FunctionWithTryBlock()\n"
479b58616c2SMarek Kurdej                "try\n"
480b58616c2SMarek Kurdej                "{\n"
481b58616c2SMarek Kurdej                "  return;\n"
482b58616c2SMarek Kurdej                "}\n"
483b58616c2SMarek Kurdej                "catch (const std::exception &)\n"
484b58616c2SMarek Kurdej                "{\n"
485b58616c2SMarek Kurdej                "}",
486b58616c2SMarek Kurdej                Style, "", /*Inverse=*/false);
487b58616c2SMarek Kurdej }
488b58616c2SMarek Kurdej 
TEST_F(DefinitionBlockSeparatorTest,Leave)4896f6f88ffSksyx TEST_F(DefinitionBlockSeparatorTest, Leave) {
4906f6f88ffSksyx   FormatStyle Style = getLLVMStyle();
4916f6f88ffSksyx   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
4926f6f88ffSksyx   Style.MaxEmptyLinesToKeep = 3;
4936f6f88ffSksyx   std::string LeaveAs = "namespace {\n"
4946f6f88ffSksyx                         "\n"
495ee25a327Sksyx                         "// Enum test1\n"
496ee25a327Sksyx                         "// Enum test2\n"
4976f6f88ffSksyx                         "enum Foo { FOO, BAR };\n"
4986f6f88ffSksyx                         "\n\n\n"
499ee25a327Sksyx                         "/*\n"
500ee25a327Sksyx                         "test1\n"
501ee25a327Sksyx                         "test2\n"
502ee25a327Sksyx                         "*/\n"
5035e5efd8aSksyx                         "/*const*/ int foo(int i, int j) {\n"
5046f6f88ffSksyx                         "  int r = i + j;\n"
5056f6f88ffSksyx                         "  return r;\n"
5066f6f88ffSksyx                         "}\n"
5076f6f88ffSksyx                         "\n"
508ee25a327Sksyx                         "// Foobar\n"
5096f6f88ffSksyx                         "int i, j, k;\n"
5106f6f88ffSksyx                         "\n"
511ee25a327Sksyx                         "// Comment for function\n"
512ee25a327Sksyx                         "// Comment line 2\n"
513ee25a327Sksyx                         "// Comment line 3\n"
5146f6f88ffSksyx                         "int bar(int j, int k) {\n"
5155e5efd8aSksyx                         "  {\n"
5166f6f88ffSksyx                         "    int r = j * k;\n"
5176f6f88ffSksyx                         "    return r;\n"
5186f6f88ffSksyx                         "  }\n"
5195e5efd8aSksyx                         "}\n"
5206f6f88ffSksyx                         "\n"
521ee25a327Sksyx                         "int bar2(int j, int k) {\n"
522ee25a327Sksyx                         "  int r = j / k;\n"
523ee25a327Sksyx                         "  return r;\n"
524ee25a327Sksyx                         "}\n"
525ee25a327Sksyx                         "\n"
526ee25a327Sksyx                         "// Comment for inline enum\n"
5276f6f88ffSksyx                         "enum Bar { FOOBAR, BARFOO };\n"
5285e5efd8aSksyx                         "int bar3(int j, int k, const enum Bar b) {\n"
529ee25a327Sksyx                         "  // A comment\n"
530ee25a327Sksyx                         "  int r = j % k;\n"
531a70549aeSksyx                         "  if (struct S = getS()) {\n"
532a70549aeSksyx                         "    // if condition\n"
533a70549aeSksyx                         "  }\n"
534ee25a327Sksyx                         "  return r;\n"
535ee25a327Sksyx                         "}\n"
5366f6f88ffSksyx                         "} // namespace";
5376f6f88ffSksyx   verifyFormat(LeaveAs, Style, LeaveAs);
5386f6f88ffSksyx }
5396f6f88ffSksyx 
TEST_F(DefinitionBlockSeparatorTest,CSharp)5406f6f88ffSksyx TEST_F(DefinitionBlockSeparatorTest, CSharp) {
5416f6f88ffSksyx   FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp);
5426f6f88ffSksyx   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
5436f6f88ffSksyx   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
5446f6f88ffSksyx   Style.AllowShortEnumsOnASingleLine = false;
5456f6f88ffSksyx   verifyFormat("namespace {\r\n"
5466f6f88ffSksyx                "public class SomeTinyClass {\r\n"
5476f6f88ffSksyx                "  int X;\r\n"
5486f6f88ffSksyx                "}\r\n"
5496f6f88ffSksyx                "\r\n"
5506f6f88ffSksyx                "public class AnotherTinyClass {\r\n"
5516f6f88ffSksyx                "  int Y;\r\n"
5526f6f88ffSksyx                "}\r\n"
5536f6f88ffSksyx                "\r\n"
5546f6f88ffSksyx                "internal static String toString() {\r\n"
5556f6f88ffSksyx                "}\r\n"
5566f6f88ffSksyx                "\r\n"
557ee25a327Sksyx                "// Comment for enum\r\n"
5586f6f88ffSksyx                "public enum var {\r\n"
5596f6f88ffSksyx                "  none,\r\n"
5606f6f88ffSksyx                "  @string,\r\n"
5616f6f88ffSksyx                "  bool,\r\n"
5626f6f88ffSksyx                "  @enum\r\n"
5636f6f88ffSksyx                "}\r\n"
5646f6f88ffSksyx                "\r\n"
565ee25a327Sksyx                "// Test\r\n"
5666f6f88ffSksyx                "[STAThread]\r\n"
5676f6f88ffSksyx                "static void Main(string[] args) {\r\n"
5686f6f88ffSksyx                "  Console.WriteLine(\"HelloWorld\");\r\n"
5696f6f88ffSksyx                "}\r\n"
5706f6f88ffSksyx                "\r\n"
5716f6f88ffSksyx                "static decimal Test() {\r\n"
5726f6f88ffSksyx                "}\r\n"
5736f6f88ffSksyx                "}\r\n"
5746f6f88ffSksyx                "\r\n"
5756f6f88ffSksyx                "public class FoobarClass {\r\n"
5766f6f88ffSksyx                "  int foobar;\r\n"
5776f6f88ffSksyx                "}",
5786f6f88ffSksyx                Style);
5796f6f88ffSksyx }
5806f6f88ffSksyx 
TEST_F(DefinitionBlockSeparatorTest,JavaScript)5816f6f88ffSksyx TEST_F(DefinitionBlockSeparatorTest, JavaScript) {
5826f6f88ffSksyx   FormatStyle Style = getLLVMStyle(FormatStyle::LK_JavaScript);
5836f6f88ffSksyx   Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always;
5846f6f88ffSksyx   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
5856f6f88ffSksyx   Style.AllowShortEnumsOnASingleLine = false;
5866f6f88ffSksyx   verifyFormat("export const enum Foo {\n"
5876f6f88ffSksyx                "  A = 1,\n"
5886f6f88ffSksyx                "  B\n"
5896f6f88ffSksyx                "}\n"
5906f6f88ffSksyx                "\n"
5916f6f88ffSksyx                "export function A() {\n"
5926f6f88ffSksyx                "}\n"
5936f6f88ffSksyx                "\n"
5946f6f88ffSksyx                "export default function B() {\n"
5956f6f88ffSksyx                "}\n"
5966f6f88ffSksyx                "\n"
5976f6f88ffSksyx                "export function C() {\n"
5986f6f88ffSksyx                "}\n"
5996f6f88ffSksyx                "\n"
6006f6f88ffSksyx                "var t, p, q;\n"
6016f6f88ffSksyx                "\n"
6026f6f88ffSksyx                "export abstract class X {\n"
6036f6f88ffSksyx                "  y: number;\n"
6046f6f88ffSksyx                "}\n"
6056f6f88ffSksyx                "\n"
6066f6f88ffSksyx                "export const enum Bar {\n"
6076f6f88ffSksyx                "  D = 1,\n"
6086f6f88ffSksyx                "  E\n"
6096f6f88ffSksyx                "}",
6106f6f88ffSksyx                Style);
6116f6f88ffSksyx }
6126f6f88ffSksyx } // namespace
6136f6f88ffSksyx } // namespace format
6146f6f88ffSksyx } // namespace clang
615