//===- unittest/Format/BracesInserterTest.cpp -----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/Format/Format.h" #include "../Tooling/ReplacementTest.h" #include "FormatTestUtils.h" #define DEBUG_TYPE "braces-inserter-test" namespace clang { namespace format { namespace { class BracesInserterTest : public ::testing::Test { protected: std::string format(llvm::StringRef Code, const FormatStyle &Style, const std::vector &Ranges) { LLVM_DEBUG(llvm::errs() << "---\n"); LLVM_DEBUG(llvm::errs() << Code << "\n\n"); auto NonEmptyRanges = Ranges; if (Ranges.empty()) NonEmptyRanges = {1, tooling::Range(0, Code.size())}; FormattingAttemptStatus Status; tooling::Replacements Replaces = reformat(Style, Code, NonEmptyRanges, "", &Status); EXPECT_EQ(true, Status.FormatComplete) << Code << "\n\n"; ReplacementCount = Replaces.size(); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast(Result)); LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } void _verifyFormat(const char *File, int Line, llvm::StringRef Expected, llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle(), const std::vector &Ranges = {}) { testing::ScopedTrace t(File, Line, ::testing::Message() << Code.str()); EXPECT_EQ(Expected.str(), format(Expected, Style, Ranges)) << "Expected code is not stable"; EXPECT_EQ(Expected.str(), format(Code, Style, Ranges)); if (Style.Language == FormatStyle::LK_Cpp && Ranges.empty()) { // Objective-C++ is a superset of C++, so everything checked for C++ // needs to be checked for Objective-C++ as well. FormatStyle ObjCStyle = Style; ObjCStyle.Language = FormatStyle::LK_ObjC; EXPECT_EQ(Expected.str(), format(test::messUp(Code), ObjCStyle, Ranges)); } } void _verifyFormat(const char *File, int Line, llvm::StringRef Code, const FormatStyle &Style = getLLVMStyle(), const std::vector &Ranges = {}) { _verifyFormat(File, Line, Code, Code, Style, Ranges); } int ReplacementCount; }; #define verifyFormat(...) _verifyFormat(__FILE__, __LINE__, __VA_ARGS__) TEST_F(BracesInserterTest, InsertBraces) { FormatStyle Style = getLLVMStyle(); Style.InsertBraces = true; verifyFormat("// clang-format off\n" "// comment\n" "if (a) f();\n" "// clang-format on\n" "if (b) {\n" " g();\n" "}", "// clang-format off\n" "// comment\n" "if (a) f();\n" "// clang-format on\n" "if (b) g();", Style); verifyFormat("if (a) {\n" " switch (b) {\n" " case 1:\n" " c = 0;\n" " break;\n" " default:\n" " c = 1;\n" " }\n" "}", "if (a)\n" " switch (b) {\n" " case 1:\n" " c = 0;\n" " break;\n" " default:\n" " c = 1;\n" " }", Style); verifyFormat("for (auto node : nodes) {\n" " if (node) {\n" " break;\n" " }\n" "}", "for (auto node : nodes)\n" " if (node)\n" " break;", Style); verifyFormat("for (auto node : nodes) {\n" " if (node)\n" "}", "for (auto node : nodes)\n" " if (node)", Style); verifyFormat("do {\n" " --a;\n" "} while (a);", "do\n" " --a;\n" "while (a);", Style); verifyFormat("if (i) {\n" " ++i;\n" "} else {\n" " --i;\n" "}", "if (i)\n" " ++i;\n" "else {\n" " --i;\n" "}", Style); verifyFormat("void f() {\n" " while (j--) {\n" " while (i) {\n" " --i;\n" " }\n" " }\n" "}", "void f() {\n" " while (j--)\n" " while (i)\n" " --i;\n" "}", Style); verifyFormat("f({\n" " if (a) {\n" " g();\n" " }\n" "});", "f({\n" " if (a)\n" " g();\n" "});", Style); verifyFormat("if (a) {\n" " f();\n" "} else if (b) {\n" " g();\n" "} else {\n" " h();\n" "}", "if (a)\n" " f();\n" "else if (b)\n" " g();\n" "else\n" " h();", Style); verifyFormat("if (a) {\n" " f();\n" "}\n" "// comment\n" "/* comment */", "if (a)\n" " f();\n" "// comment\n" "/* comment */", Style); verifyFormat("if (a) {\n" " // foo\n" " // bar\n" " f();\n" "}", "if (a)\n" " // foo\n" " // bar\n" " f();", Style); verifyFormat("if (a) { //\n" " b = 1;\n" "}", "if (a) //\n" " b = 1;", Style); verifyFormat("if (a) { // comment\n" " // comment\n" " f();\n" "}", "if (a) // comment\n" " // comment\n" " f();", Style); verifyFormat("if (a) {\n" " f(); // comment\n" "}", "if (a)\n" " f(); // comment", Style); verifyFormat("if (a) {\n" " f();\n" "}\n" "#undef A\n" "#undef B", "if (a)\n" " f();\n" "#undef A\n" "#undef B", Style); verifyFormat("if (a)\n" "#ifdef A\n" " f();\n" "#else\n" " g();\n" "#endif", Style); verifyFormat("#if 0\n" "#elif 1\n" "#endif\n" "void f() {\n" " if (a) {\n" " g();\n" " }\n" "}", "#if 0\n" "#elif 1\n" "#endif\n" "void f() {\n" " if (a) g();\n" "}", Style); verifyFormat("do {\n" "#if 0\n" "#else\n" " if (b) {\n" "#endif\n" " }\n" "} while (0);", Style); Style.RemoveBracesLLVM = true; verifyFormat("if (a) //\n" " return b;", Style); Style.RemoveBracesLLVM = false; Style.ColumnLimit = 15; verifyFormat("#define A \\\n" " if (a) \\\n" " f();", Style); verifyFormat("if (a + b >\n" " c) {\n" " f();\n" "}", "if (a + b > c)\n" " f();", Style); Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; verifyFormat("if (a) //\n" "{\n" " b = 1;\n" "}", "if (a) //\n" " b = 1;", Style); } TEST_F(BracesInserterTest, InsertBracesRange) { FormatStyle Style = getLLVMStyle(); Style.InsertBraces = true; const StringRef Code("while (a)\n" " if (b)\n" " return;"); verifyFormat("while (a) {\n" " if (b)\n" " return;\n" "}", Code, Style, {tooling::Range(0, 9)}); // line 1 verifyFormat("while (a) {\n" " if (b) {\n" " return;\n" " }\n" "}", Code, Style, {tooling::Range(0, 18)}); // lines 1-2 verifyFormat("while (a)\n" " if (b) {\n" " return;\n" " }", Code, Style, {tooling::Range(10, 8)}); // line 2 verifyFormat(Code, Style, {tooling::Range(19, 11)}); // line 3 } } // namespace } // namespace format } // namespace clang