//===- UsingDeclarationsSorterTest.cpp - Formatting unit tests ------------===// // // 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 "llvm/Support/Debug.h" #include "gtest/gtest.h" #define DEBUG_TYPE "using-declarations-sorter-test" namespace clang { namespace format { namespace { class UsingDeclarationsSorterTest : public testing::Test { protected: std::string sortUsingDeclarations(StringRef Code, const std::vector &Ranges, const FormatStyle &Style = getLLVMStyle()) { LLVM_DEBUG(llvm::errs() << "---\n"); LLVM_DEBUG(llvm::errs() << Code << "\n\n"); tooling::Replacements Replaces = format::sortUsingDeclarations(Style, Code, Ranges, ""); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast(Result)); LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); return *Result; } std::string sortUsingDeclarations(StringRef Code, const FormatStyle &Style = getLLVMStyle()) { return sortUsingDeclarations(Code, /*Ranges=*/{1, tooling::Range(0, Code.size())}, Style); } }; TEST_F(UsingDeclarationsSorterTest, SwapsTwoConsecutiveUsingDeclarations) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("using a;\n" "using b;", sortUsingDeclarations("using a;\n" "using b;", Style)); EXPECT_EQ("using a;\n" "using aa;", sortUsingDeclarations("using aa;\n" "using a;", Style)); EXPECT_EQ("using a;\n" "using ::a;", sortUsingDeclarations("using a;\n" "using ::a;", Style)); EXPECT_EQ("using a::bcd;\n" "using a::cd;", sortUsingDeclarations("using a::cd;\n" "using a::bcd;", Style)); EXPECT_EQ("using a;\n" "using a::a;", sortUsingDeclarations("using a::a;\n" "using a;", Style)); EXPECT_EQ("using a::ba::aa;\n" "using a::bb::ccc;", sortUsingDeclarations("using a::bb::ccc;\n" "using a::ba::aa;", Style)); EXPECT_EQ("using a;\n" "using typename a;", sortUsingDeclarations("using typename a;\n" "using a;", Style)); EXPECT_EQ("using typename z;\n" "using typenamea;", sortUsingDeclarations("using typenamea;\n" "using typename z;", Style)); EXPECT_EQ("using a, b;\n" "using aa;", sortUsingDeclarations("using aa;\n" "using a, b;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("using a;\n" "using b;", sortUsingDeclarations("using a;\n" "using b;", Style)); EXPECT_EQ("using a;\n" "using aa;", sortUsingDeclarations("using aa;\n" "using a;", Style)); EXPECT_EQ("using a;\n" "using ::a;", sortUsingDeclarations("using a;\n" "using ::a;", Style)); EXPECT_EQ("using a::bcd;\n" "using a::cd;", sortUsingDeclarations("using a::cd;\n" "using a::bcd;", Style)); EXPECT_EQ("using a;\n" "using a::a;", sortUsingDeclarations("using a::a;\n" "using a;", Style)); EXPECT_EQ("using a::ba::aa;\n" "using a::bb::ccc;", sortUsingDeclarations("using a::bb::ccc;\n" "using a::ba::aa;", Style)); EXPECT_EQ("using a;\n" "using typename a;", sortUsingDeclarations("using typename a;\n" "using a;", Style)); EXPECT_EQ("using typename z;\n" "using typenamea;", sortUsingDeclarations("using typenamea;\n" "using typename z;", Style)); EXPECT_EQ("using a, b;\n" "using aa;", sortUsingDeclarations("using aa;\n" "using a, b;", Style)); } TEST_F(UsingDeclarationsSorterTest, UsingDeclarationOrder) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("using A;\n" "using a;", sortUsingDeclarations("using A;\n" "using a;", Style)); EXPECT_EQ("using a;\n" "using A;", sortUsingDeclarations("using a;\n" "using A;", Style)); EXPECT_EQ("using a;\n" "using B;", sortUsingDeclarations("using B;\n" "using a;", Style)); // Ignores leading '::'. EXPECT_EQ("using ::a;\n" "using A;", sortUsingDeclarations("using ::a;\n" "using A;", Style)); EXPECT_EQ("using ::A;\n" "using a;", sortUsingDeclarations("using ::A;\n" "using a;", Style)); // Sorts '_' before 'a' and 'A'. EXPECT_EQ("using _;\n" "using A;", sortUsingDeclarations("using A;\n" "using _;", Style)); EXPECT_EQ("using _;\n" "using a;", sortUsingDeclarations("using a;\n" "using _;", Style)); EXPECT_EQ("using a::_;\n" "using a::a;", sortUsingDeclarations("using a::a;\n" "using a::_;", Style)); // Sorts non-namespace names before namespace names at the same level. EXPECT_EQ("using ::testing::_;\n" "using ::testing::Aardvark;\n" "using ::testing::kMax;\n" "using ::testing::Xylophone;\n" "using ::testing::apple::Honeycrisp;\n" "using ::testing::zebra::Stripes;", sortUsingDeclarations("using ::testing::Aardvark;\n" "using ::testing::Xylophone;\n" "using ::testing::kMax;\n" "using ::testing::_;\n" "using ::testing::apple::Honeycrisp;\n" "using ::testing::zebra::Stripes;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("using A;\n" "using a;", sortUsingDeclarations("using A;\n" "using a;", Style)); EXPECT_EQ("using a;\n" "using A;", sortUsingDeclarations("using a;\n" "using A;", Style)); EXPECT_EQ("using a;\n" "using B;", sortUsingDeclarations("using B;\n" "using a;", Style)); // Ignores leading '::'. EXPECT_EQ("using ::a;\n" "using A;", sortUsingDeclarations("using ::a;\n" "using A;", Style)); EXPECT_EQ("using ::A;\n" "using a;", sortUsingDeclarations("using ::A;\n" "using a;", Style)); // Sorts '_' before 'a' and 'A'. EXPECT_EQ("using _;\n" "using A;", sortUsingDeclarations("using A;\n" "using _;", Style)); EXPECT_EQ("using _;\n" "using a;", sortUsingDeclarations("using a;\n" "using _;", Style)); EXPECT_EQ("using a::_;\n" "using a::a;", sortUsingDeclarations("using a::a;\n" "using a::_;", Style)); // Sorts non-namespace names before namespace names at the same level. EXPECT_EQ("using ::testing::_;\n" "using ::testing::Aardvark;\n" "using ::testing::apple::Honeycrisp;\n" "using ::testing::kMax;\n" "using ::testing::Xylophone;\n" "using ::testing::zebra::Stripes;", sortUsingDeclarations("using ::testing::Aardvark;\n" "using ::testing::Xylophone;\n" "using ::testing::kMax;\n" "using ::testing::_;\n" "using ::testing::apple::Honeycrisp;\n" "using ::testing::zebra::Stripes;", Style)); } TEST_F(UsingDeclarationsSorterTest, SortsStably) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("using a;\n" "using A;\n" "using a;\n" "using A;\n" "using a;\n" "using A;\n" "using a;\n" "using B;\n" "using b;\n" "using B;\n" "using b;\n" "using B;\n" "using b;", sortUsingDeclarations("using a;\n" "using B;\n" "using a;\n" "using b;\n" "using A;\n" "using a;\n" "using b;\n" "using B;\n" "using b;\n" "using A;\n" "using a;\n" "using b;\n" "using b;\n" "using B;\n" "using b;\n" "using A;\n" "using a;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("using a;\n" "using A;\n" "using a;\n" "using A;\n" "using a;\n" "using A;\n" "using a;\n" "using B;\n" "using b;\n" "using B;\n" "using b;\n" "using B;\n" "using b;", sortUsingDeclarations("using a;\n" "using B;\n" "using a;\n" "using b;\n" "using A;\n" "using a;\n" "using b;\n" "using B;\n" "using b;\n" "using A;\n" "using a;\n" "using b;\n" "using b;\n" "using B;\n" "using b;\n" "using A;\n" "using a;", Style)); } TEST_F(UsingDeclarationsSorterTest, SortsMultipleTopLevelDeclarations) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("using a;\n" "using b;\n" "using c;\n" "using d;\n" "using e;", sortUsingDeclarations("using d;\n" "using b;\n" "using e;\n" "using a;\n" "using c;", Style)); EXPECT_EQ("#include \n" "using std::cin;\n" "using std::cout;\n" "using ::std::endl;\n" "int main();", sortUsingDeclarations("#include \n" "using std::cout;\n" "using ::std::endl;\n" "using std::cin;\n" "int main();", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("using a;\n" "using b;\n" "using c;\n" "using d;\n" "using e;", sortUsingDeclarations("using d;\n" "using b;\n" "using e;\n" "using a;\n" "using c;", Style)); EXPECT_EQ("#include \n" "using std::cin;\n" "using std::cout;\n" "using ::std::endl;\n" "int main();", sortUsingDeclarations("#include \n" "using std::cout;\n" "using ::std::endl;\n" "using std::cin;\n" "int main();", Style)); } TEST_F(UsingDeclarationsSorterTest, BreaksOnEmptyLines) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("using b;\n" "using c;\n" "\n" "using a;\n" "using d;", sortUsingDeclarations("using c;\n" "using b;\n" "\n" "using d;\n" "using a;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("using b;\n" "using c;\n" "\n" "using a;\n" "using d;", sortUsingDeclarations("using c;\n" "using b;\n" "\n" "using d;\n" "using a;", Style)); } TEST_F(UsingDeclarationsSorterTest, BreaksOnUsingNamespace) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("using b;\n" "using namespace std;\n" "using a;", sortUsingDeclarations("using b;\n" "using namespace std;\n" "using a;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("using b;\n" "using namespace std;\n" "using a;", sortUsingDeclarations("using b;\n" "using namespace std;\n" "using a;", Style)); } TEST_F(UsingDeclarationsSorterTest, KeepsUsingDeclarationsInPPDirectives) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("#define A \\\n" "using b;\\\n" "using a;", sortUsingDeclarations("#define A \\\n" "using b;\\\n" "using a;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("#define A \\\n" "using b;\\\n" "using a;", sortUsingDeclarations("#define A \\\n" "using b;\\\n" "using a;", Style)); } TEST_F(UsingDeclarationsSorterTest, KeepsTypeAliases) { auto Code = "struct C { struct B { struct A; }; };\n" "using B = C::B;\n" "using A = B::A;"; FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ(Code, sortUsingDeclarations(Code, Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ(Code, sortUsingDeclarations(Code, Style)); } TEST_F(UsingDeclarationsSorterTest, MovesTrailingCommentsWithDeclarations) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("using a; // line a1\n" "using b; /* line b1\n" " * line b2\n" " * line b3 */\n" "using c; // line c1\n" " // line c2", sortUsingDeclarations("using c; // line c1\n" " // line c2\n" "using b; /* line b1\n" " * line b2\n" " * line b3 */\n" "using a; // line a1", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("using a; // line a1\n" "using b; /* line b1\n" " * line b2\n" " * line b3 */\n" "using c; // line c1\n" " // line c2", sortUsingDeclarations("using c; // line c1\n" " // line c2\n" "using b; /* line b1\n" " * line b2\n" " * line b3 */\n" "using a; // line a1", Style)); } TEST_F(UsingDeclarationsSorterTest, SortsInStructScope) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("struct pt3 : pt2 {\n" " using pt2::x;\n" " using pt2::y;\n" " float z;\n" "};", sortUsingDeclarations("struct pt3 : pt2 {\n" " using pt2::y;\n" " using pt2::x;\n" " float z;\n" "};", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("struct pt3 : pt2 {\n" " using pt2::x;\n" " using pt2::y;\n" " float z;\n" "};", sortUsingDeclarations("struct pt3 : pt2 {\n" " using pt2::y;\n" " using pt2::x;\n" " float z;\n" "};", Style)); } TEST_F(UsingDeclarationsSorterTest, KeepsOperators) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("using a::operator();\n" "using a::operator-;\n" "using a::operator+;", sortUsingDeclarations("using a::operator();\n" "using a::operator-;\n" "using a::operator+;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("using a::operator();\n" "using a::operator-;\n" "using a::operator+;", sortUsingDeclarations("using a::operator();\n" "using a::operator-;\n" "using a::operator+;", Style)); } TEST_F(UsingDeclarationsSorterTest, SortsUsingDeclarationsInsideNamespaces) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("namespace A {\n" "struct B;\n" "struct C;\n" "}\n" "namespace X {\n" "using A::B;\n" "using A::C;\n" "}", sortUsingDeclarations("namespace A {\n" "struct B;\n" "struct C;\n" "}\n" "namespace X {\n" "using A::C;\n" "using A::B;\n" "}", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("namespace A {\n" "struct B;\n" "struct C;\n" "}\n" "namespace X {\n" "using A::B;\n" "using A::C;\n" "}", sortUsingDeclarations("namespace A {\n" "struct B;\n" "struct C;\n" "}\n" "namespace X {\n" "using A::C;\n" "using A::B;\n" "}", Style)); } TEST_F(UsingDeclarationsSorterTest, SupportsClangFormatOff) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("// clang-format off\n" "using b;\n" "using a;\n" "// clang-format on\n" "using c;\n" "using d;", sortUsingDeclarations("// clang-format off\n" "using b;\n" "using a;\n" "// clang-format on\n" "using d;\n" "using c;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("// clang-format off\n" "using b;\n" "using a;\n" "// clang-format on\n" "using c;\n" "using d;", sortUsingDeclarations("// clang-format off\n" "using b;\n" "using a;\n" "// clang-format on\n" "using d;\n" "using c;", Style)); } TEST_F(UsingDeclarationsSorterTest, SortsPartialRangeOfUsingDeclarations) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); // Sorts the whole block of using declarations surrounding the range. EXPECT_EQ("using a;\n" "using b;\n" "using c;", sortUsingDeclarations("using b;\n" "using c;\n" // starts at offset 10 "using a;", {tooling::Range(10, 15)}, Style)); EXPECT_EQ("using a;\n" "using b;\n" "using c;\n" "using A = b;", sortUsingDeclarations("using b;\n" "using c;\n" // starts at offset 10 "using a;\n" "using A = b;", {tooling::Range(10, 15)}, Style)); EXPECT_EQ("using d;\n" "using c;\n" "\n" "using a;\n" "using b;\n" "\n" "using f;\n" "using e;", sortUsingDeclarations("using d;\n" "using c;\n" "\n" "using b;\n" // starts at offset 19 "using a;\n" "\n" "using f;\n" "using e;", {tooling::Range(19, 1)}, Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; // Sorts the whole block of using declarations surrounding the range. EXPECT_EQ("using a;\n" "using b;\n" "using c;", sortUsingDeclarations("using b;\n" "using c;\n" // starts at offset 10 "using a;", {tooling::Range(10, 15)}, Style)); EXPECT_EQ("using a;\n" "using b;\n" "using c;\n" "using A = b;", sortUsingDeclarations("using b;\n" "using c;\n" // starts at offset 10 "using a;\n" "using A = b;", {tooling::Range(10, 15)}, Style)); EXPECT_EQ("using d;\n" "using c;\n" "\n" "using a;\n" "using b;\n" "\n" "using f;\n" "using e;", sortUsingDeclarations("using d;\n" "using c;\n" "\n" "using b;\n" // starts at offset 19 "using a;\n" "\n" "using f;\n" "using e;", {tooling::Range(19, 1)}, Style)); } TEST_F(UsingDeclarationsSorterTest, SortsUsingDeclarationsWithLeadingkComments) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("/* comment */ using a;\n" "/* comment */ using b;", sortUsingDeclarations("/* comment */ using b;\n" "/* comment */ using a;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("/* comment */ using a;\n" "/* comment */ using b;", sortUsingDeclarations("/* comment */ using b;\n" "/* comment */ using a;", Style)); } TEST_F(UsingDeclarationsSorterTest, DeduplicatesUsingDeclarations) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("using a;\n" "using b;\n" "using c;\n" "\n" "using a;\n" "using e;", sortUsingDeclarations("using c;\n" "using a;\n" "using b;\n" "using a;\n" "using b;\n" "\n" "using e;\n" "using a;\n" "using e;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("using a;\n" "using b;\n" "using c;\n" "\n" "using a;\n" "using e;", sortUsingDeclarations("using c;\n" "using a;\n" "using b;\n" "using a;\n" "using b;\n" "\n" "using e;\n" "using a;\n" "using e;", Style)); } TEST_F(UsingDeclarationsSorterTest, SortsUsingDeclarationsWithDifferentCountsOfScopes) { FormatStyle Style = getLLVMStyle(); EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations); EXPECT_EQ("using boost::regex;\n" "using boost::regex_constants::icase;\n" "using std::move;\n" "using std::string;\n" "using std::chrono::duration_cast;\n" "using std::chrono::microseconds;\n" "using std::chrono::seconds;\n" "using std::chrono::steady_clock;", sortUsingDeclarations("using boost::regex;\n" "using boost::regex_constants::icase;\n" "using std::chrono::duration_cast;\n" "using std::chrono::microseconds;\n" "using std::chrono::seconds;\n" "using std::chrono::steady_clock;\n" "using std::move;\n" "using std::string;", Style)); Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic; EXPECT_EQ("using boost::regex;\n" "using boost::regex_constants::icase;\n" "using std::chrono::duration_cast;\n" "using std::chrono::microseconds;\n" "using std::chrono::seconds;\n" "using std::chrono::steady_clock;\n" "using std::move;\n" "using std::string;", sortUsingDeclarations("using boost::regex;\n" "using boost::regex_constants::icase;\n" "using std::move;\n" "using std::string;\n" "using std::chrono::duration_cast;\n" "using std::chrono::microseconds;\n" "using std::chrono::seconds;\n" "using std::chrono::steady_clock;", Style)); } } // end namespace } // end namespace format } // end namespace clang