diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1719,6 +1719,9 @@ priority for order.``SortPriority`` is set to the value of ``Priority`` as default if it is not assigned. + Each regular expression can be marked as case sensitive with the field + ``CaseSensitive``, per default it is not. + To configure this in the .clang-format file, use: .. code-block:: yaml @@ -1727,6 +1730,7 @@ - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 SortPriority: 2 + CaseSensitive: true - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 - Regex: '<[[:alnum:].]+>' diff --git a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h --- a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h +++ b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h @@ -60,8 +60,11 @@ int Priority; /// The custom priority to sort before grouping. int SortPriority; + /// If the regular expression is case sensitive. + bool RegexIsCaseSensitive; bool operator==(const IncludeCategory &Other) const { - return Regex == Other.Regex && Priority == Other.Priority; + return Regex == Other.Regex && Priority == Other.Priority && + RegexIsCaseSensitive == Other.RegexIsCaseSensitive; } }; @@ -84,20 +87,25 @@ /// (https://llvm.org/docs/CodingStandards.html#include-style). However, you /// can also assign negative priorities if you have certain headers that /// always need to be first. - /// + /// /// There is a third and optional field ``SortPriority`` which can used while - /// ``IncludeBloks = IBS_Regroup`` to define the priority in which ``#includes`` - /// should be ordered, and value of ``Priority`` defines the order of + /// ``IncludeBloks = IBS_Regroup`` to define the priority in which + /// ``#includes`` should be ordered, and value of ``Priority`` defines the + /// order of /// ``#include blocks`` and also enables to group ``#includes`` of different /// priority for order.``SortPriority`` is set to the value of ``Priority`` /// as default if it is not assigned. /// + /// Each regular expression can be marked as case sensitive with the field + /// ``CaseSensitive``, per default it is not. + /// /// To configure this in the .clang-format file, use: /// \code{.yaml} /// IncludeCategories: /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/' /// Priority: 2 /// SortPriority: 2 + /// CaseSensitive: true /// - Regex: '^(<|"(gtest|gmock|isl|json)/)' /// Priority: 3 /// - Regex: '<[[:alnum:].]+>' diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -916,9 +916,9 @@ LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); LLVMStyle.IncludeStyle.IncludeCategories = { - {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0}, - {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0}, - {".*", 1, 0}}; + {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false}, + {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false}, + {".*", 1, 0, false}}; LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$"; LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve; LLVMStyle.IndentCaseLabels = false; @@ -1016,10 +1016,10 @@ GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true; GoogleStyle.DerivePointerAlignment = true; - GoogleStyle.IncludeStyle.IncludeCategories = {{"^", 2, 0}, - {"^<.*\\.h>", 1, 0}, - {"^<.*", 2, 0}, - {".*", 3, 0}}; + GoogleStyle.IncludeStyle.IncludeCategories = {{"^", 2, 0, false}, + {"^<.*\\.h>", 1, 0, false}, + {"^<.*", 2, 0, false}, + {".*", 3, 0, false}}; GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; GoogleStyle.IndentCaseLabels = true; diff --git a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp --- a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp +++ b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp @@ -190,8 +190,11 @@ IncludeCategoryManager::IncludeCategoryManager(const IncludeStyle &Style, StringRef FileName) : Style(Style), FileName(FileName) { - for (const auto &Category : Style.IncludeCategories) - CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase); + for (const auto &Category : Style.IncludeCategories) { + CategoryRegexs.emplace_back(Category.Regex, Category.RegexIsCaseSensitive + ? llvm::Regex::NoFlags + : llvm::Regex::IgnoreCase); + } IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") || FileName.endswith(".cpp") || FileName.endswith(".c++") || FileName.endswith(".cxx") || FileName.endswith(".m") || diff --git a/clang/lib/Tooling/Inclusions/IncludeStyle.cpp b/clang/lib/Tooling/Inclusions/IncludeStyle.cpp --- a/clang/lib/Tooling/Inclusions/IncludeStyle.cpp +++ b/clang/lib/Tooling/Inclusions/IncludeStyle.cpp @@ -18,6 +18,7 @@ IO.mapOptional("Regex", Category.Regex); IO.mapOptional("Priority", Category.Priority); IO.mapOptional("SortPriority", Category.SortPriority); + IO.mapOptional("CaseSensitive", Category.RegexIsCaseSensitive); } void ScalarEnumerationTraits::enumeration( diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -14526,12 +14526,13 @@ Style.IncludeStyle.IncludeCategories.clear(); std::vector ExpectedCategories = { - {"abc/.*", 2, 0}, {".*", 1, 0}}; + {"abc/.*", 2, 0, false}, {".*", 1, 0, true}}; CHECK_PARSE("IncludeCategories:\n" " - Regex: abc/.*\n" " Priority: 2\n" " - Regex: .*\n" - " Priority: 1", + " Priority: 1\n" + " CaseSensitive: true\n", IncludeStyle.IncludeCategories, ExpectedCategories); CHECK_PARSE("IncludeIsMainRegex: 'abc$'", IncludeStyle.IncludeIsMainRegex, "abc$"); diff --git a/clang/unittests/Format/SortIncludesTest.cpp b/clang/unittests/Format/SortIncludesTest.cpp --- a/clang/unittests/Format/SortIncludesTest.cpp +++ b/clang/unittests/Format/SortIncludesTest.cpp @@ -72,19 +72,19 @@ TEST_F(SortIncludesTest, SortedIncludesUsingSortPriorityAttribute) { FmtStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; FmtStyle.IncludeStyle.IncludeCategories = { - {"^", 1, 0}, - {"^", 1, 1}, - {"^", 8, 10}, - {"^\".*\\.h\"", 10, 12}}; + {"^", 1, 0, false}, + {"^", 1, 1, false}, + {"^", 8, 10, false}, + {"^\".*\\.h\"", 10, 12, false}}; EXPECT_EQ("#include \n" "#include \n" "#include \n" @@ -600,8 +600,59 @@ "a_TEST.cc")); } +TEST_F(SortIncludesTest, SupportOptionalCaseSensitiveMachting) { + Style.IncludeBlocks = clang::tooling::IncludeStyle::IBS_Regroup; + Style.IncludeCategories = {{"^\"", 1, 0, false}, + {"^<.*\\.h>$", 2, 0, false}, + {"^", 3, 0, false}, + {"^", 4, 0, false}, + {"^<", 5, 0, false}}; + + StringRef UnsortedCode = "#include \n" + "#include \"qt.h\"\n" + "#include \n" + "#include \n" + "#include \n" + "#include \"qa.h\"\n" + "#include \n" + "#include \n" + "#include \n"; + + EXPECT_EQ("#include \"qa.h\"\n" + "#include \"qt.h\"\n" + "\n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "\n" + "#include \n", + sort(UnsortedCode)); + + Style.IncludeCategories[2].RegexIsCaseSensitive = true; + Style.IncludeCategories[3].RegexIsCaseSensitive = true; + EXPECT_EQ("#include \"qa.h\"\n" + "#include \"qt.h\"\n" + "\n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "\n" + "#include \n" + "#include \n", + sort(UnsortedCode)); +} + TEST_F(SortIncludesTest, NegativePriorities) { - Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}}; + Style.IncludeCategories = {{".*important_os_header.*", -1, 0, false}, + {".*", 1, 0, false}}; EXPECT_EQ("#include \"important_os_header.h\"\n" "#include \"c_main.h\"\n" "#include \"a_other.h\"\n", @@ -621,7 +672,8 @@ } TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { - Style.IncludeCategories = {{".*important_os_header.*", -1, 0}, {".*", 1, 0}}; + Style.IncludeCategories = {{".*important_os_header.*", -1, 0, false}, + {".*", 1, 0, false}}; Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; EXPECT_EQ("#include \"important_os_header.h\"\n"