From 0df6ca848596a3ad6ff88d1fe51dc77d75b387ef Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Wed, 16 Dec 2015 10:10:16 +0000 Subject: [PATCH] clang-format: Extend header sort category implementation. Specifically, it is sometimes necessary to keep certain #includes as the first #include, even before the main #include for a .cc file. Switching the category to be signed instead of unsigned isn't ideal, but it seems as good of an option as any and is fully backwards compatible. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@255757 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Format/Format.h | 12 +++++++----- lib/Format/Format.cpp | 6 +++--- unittests/Format/SortIncludesTest.cpp | 8 ++++++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 36b05516f0..f957f39d88 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -343,7 +343,7 @@ struct FormatStyle { /// \brief The regular expression that this category matches. std::string Regex; /// \brief The priority to assign to this category. - unsigned Priority; + int Priority; bool operator==(const IncludeCategory &Other) const { return Regex == Other.Regex && Priority == Other.Priority; } @@ -358,10 +358,12 @@ struct FormatStyle { /// according to increasing category number and then alphabetically within /// each category. /// - /// If none of the regular expressions match, UINT_MAX is assigned as - /// category. The main header for a source file automatically gets category 0, - /// so that it is kept at the beginning of the #includes - /// (http://llvm.org/docs/CodingStandards.html#include-style). + /// If none of the regular expressions match, INT_MAX is assigned as + /// category. The main header for a source file automatically gets category 0. + /// so that it is generally kept at the beginning of the #includes + /// (http://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. /// /// To configure this in the .clang-format file, use: /// \code diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 896ecad60f..a7e0799c11 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -1684,7 +1684,7 @@ struct IncludeDirective { StringRef Filename; StringRef Text; unsigned Offset; - unsigned Category; + int Category; }; } // end anonymous namespace @@ -1807,11 +1807,11 @@ tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, if (!FormattingOff && !Line.endswith("\\")) { if (IncludeRegex.match(Line, &Matches)) { StringRef IncludeName = Matches[2]; - unsigned Category; + int Category; if (LookForMainHeader && !IncludeName.startswith("<")) { Category = 0; } else { - Category = UINT_MAX; + Category = INT_MAX; for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i) { if (CategoryRegexs[i].match(IncludeName)) { Category = Style.IncludeCategories[i].Priority; diff --git a/unittests/Format/SortIncludesTest.cpp b/unittests/Format/SortIncludesTest.cpp index 70c7960df0..9b0db349b0 100644 --- a/unittests/Format/SortIncludesTest.cpp +++ b/unittests/Format/SortIncludesTest.cpp @@ -185,6 +185,14 @@ TEST_F(SortIncludesTest, LeavesMainHeaderFirst) { "some_header.h")); } +TEST_F(SortIncludesTest, NegativePriorities) { + Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}}; + EXPECT_EQ("#include \"important_os_header.h\"\n" + "#include \"a.h\"\n", + sort("#include \"a.h\"\n" + "#include \"important_os_header.h\"\n")); +} + TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { std::string Code = "#include \n" // Start of line: 0 "#include \n" // Start of line: 15 -- 2.50.1