summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/docs/ClangFormatStyleOptions.rst9
-rw-r--r--clang/include/clang/Tooling/Inclusions/HeaderIncludes.h1
-rw-r--r--clang/include/clang/Tooling/Inclusions/IncludeStyle.h2
-rw-r--r--clang/lib/Format/Format.cpp14
-rw-r--r--clang/lib/Tooling/Inclusions/HeaderIncludes.cpp14
-rw-r--r--clang/lib/Tooling/Inclusions/IncludeStyle.cpp1
-rw-r--r--clang/unittests/Format/SortIncludesTest.cpp71
7 files changed, 108 insertions, 4 deletions
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 6a42da71b96..bd50943dfd8 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -1511,6 +1511,13 @@ the configuration (without a prefix: ``Auto``).
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
+ ``#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.
+
To configure this in the .clang-format file, use:
.. code-block:: yaml
@@ -1518,12 +1525,14 @@ the configuration (without a prefix: ``Auto``).
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
+ SortPriority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '<[[:alnum:].]+>'
Priority: 4
- Regex: '.*'
Priority: 1
+ SortPriority: 0
**IncludeIsMainRegex** (``std::string``)
Specify a regular expression of suffixes that are allowed in the
diff --git a/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h b/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
index ec6f0ea45ff..6e6d6d8fb02 100644
--- a/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ b/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -32,6 +32,7 @@ public:
/// 0. Otherwise, returns the priority of the matching category or INT_MAX.
/// NOTE: this API is not thread-safe!
int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
+ int getSortIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
private:
bool isMainHeader(StringRef IncludeName) const;
diff --git a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
index a0f236e6fc4..266763a5b1b 100644
--- a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
+++ b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
@@ -58,6 +58,8 @@ struct IncludeStyle {
std::string Regex;
/// The priority to assign to this category.
int Priority;
+ /// The custom priority to sort before grouping.
+ int SortPriority;
bool operator==(const IncludeCategory &Other) const {
return Regex == Other.Regex && Priority == Other.Priority;
}
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index ba76ba083a6..b64d4825240 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1771,6 +1771,7 @@ struct IncludeDirective {
StringRef Text;
unsigned Offset;
int Category;
+ int Priority;
};
struct JavaImportDirective {
@@ -1834,6 +1835,7 @@ static void sortCppIncludes(const FormatStyle &Style,
ArrayRef<tooling::Range> Ranges, StringRef FileName,
StringRef Code, tooling::Replacements &Replaces,
unsigned *Cursor) {
+ tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
unsigned IncludesBeginOffset = Includes.front().Offset;
unsigned IncludesEndOffset =
Includes.back().Offset + Includes.back().Text.size();
@@ -1841,11 +1843,12 @@ static void sortCppIncludes(const FormatStyle &Style,
if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
return;
SmallVector<unsigned, 16> Indices;
- for (unsigned i = 0, e = Includes.size(); i != e; ++i)
+ for (unsigned i = 0, e = Includes.size(); i != e; ++i) {
Indices.push_back(i);
+ }
llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
- return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
+ return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
+ std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
});
// The index of the include on which the cursor will be put after
// sorting/deduplicating.
@@ -1960,9 +1963,12 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
int Category = Categories.getIncludePriority(
IncludeName,
/*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
+ int Priority = Categories.getSortIncludePriority(
+ IncludeName, !MainIncludeFound && FirstIncludeBlock);
if (Category == 0)
MainIncludeFound = true;
- IncludesInBlock.push_back({IncludeName, Line, Prev, Category});
+ IncludesInBlock.push_back(
+ {IncludeName, Line, Prev, Category, Priority});
} else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
Replaces, Cursor);
diff --git a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
index a7f79c33bc5..e746bbb7f87 100644
--- a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -199,6 +199,20 @@ int IncludeCategoryManager::getIncludePriority(StringRef IncludeName,
return Ret;
}
+int IncludeCategoryManager::getSortIncludePriority(StringRef IncludeName,
+ bool CheckMainHeader) const {
+ int Ret = INT_MAX;
+ for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i)
+ if (CategoryRegexs[i].match(IncludeName)) {
+ Ret = Style.IncludeCategories[i].SortPriority;
+ if (Ret == 0)
+ Ret = Style.IncludeCategories[i].Priority;
+ break;
+ }
+ if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName))
+ Ret = 0;
+ return Ret;
+}
bool IncludeCategoryManager::isMainHeader(StringRef IncludeName) const {
if (!IncludeName.startswith("\""))
return false;
diff --git a/clang/lib/Tooling/Inclusions/IncludeStyle.cpp b/clang/lib/Tooling/Inclusions/IncludeStyle.cpp
index c53c82c8363..26dc0b87cf9 100644
--- a/clang/lib/Tooling/Inclusions/IncludeStyle.cpp
+++ b/clang/lib/Tooling/Inclusions/IncludeStyle.cpp
@@ -17,6 +17,7 @@ void MappingTraits<IncludeStyle::IncludeCategory>::mapping(
IO &IO, IncludeStyle::IncludeCategory &Category) {
IO.mapOptional("Regex", Category.Regex);
IO.mapOptional("Priority", Category.Priority);
+ IO.mapOptional("SortPriority", Category.SortPriority);
}
void ScalarEnumerationTraits<IncludeStyle::IncludeBlocksStyle>::enumeration(
diff --git a/clang/unittests/Format/SortIncludesTest.cpp b/clang/unittests/Format/SortIncludesTest.cpp
index c00d3cb747d..ef67586f1f0 100644
--- a/clang/unittests/Format/SortIncludesTest.cpp
+++ b/clang/unittests/Format/SortIncludesTest.cpp
@@ -70,6 +70,77 @@ TEST_F(SortIncludesTest, BasicSorting) {
{tooling::Range(25, 1)}));
}
+TEST_F(SortIncludesTest, SortedIncludesUsingSortPriorityAttribute) {
+ FmtStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
+ FmtStyle.IncludeStyle.IncludeCategories = {
+ {"^<sys/param\\.h>", 1, 0},
+ {"^<sys/types\\.h>", 1, 1},
+ {"^<sys.*/", 1, 2},
+ {"^<uvm/", 2, 3},
+ {"^<machine/", 3, 4},
+ {"^<dev/", 4, 5},
+ {"^<net.*/", 5, 6},
+ {"^<protocols/", 5, 7},
+ {"^<(fs|miscfs|msdosfs|nfs|ntfs|ufs)/", 6, 8},
+ {"^<(x86|amd64|i386|xen)/", 7, 8},
+ {"<path", 9, 11},
+ {"^<[^/].*\\.h>", 8, 10},
+ {"^\".*\\.h\"", 10, 12}};
+ EXPECT_EQ("#include <sys/param.h>\n"
+ "#include <sys/types.h>\n"
+ "#include <sys/ioctl.h>\n"
+ "#include <sys/socket.h>\n"
+ "#include <sys/stat.h>\n"
+ "#include <sys/wait.h>\n"
+ "\n"
+ "#include <net/if.h>\n"
+ "#include <net/if_dl.h>\n"
+ "#include <net/route.h>\n"
+ "#include <netinet/in.h>\n"
+ "#include <protocols/rwhod.h>\n"
+ "\n"
+ "#include <assert.h>\n"
+ "#include <errno.h>\n"
+ "#include <inttypes.h>\n"
+ "#include <stdio.h>\n"
+ "#include <stdlib.h>\n"
+ "\n"
+ "#include <paths.h>\n"
+ "\n"
+ "#include \"pathnames.h\"\n",
+ sort("#include <sys/param.h>\n"
+ "#include <sys/types.h>\n"
+ "#include <sys/ioctl.h>\n"
+ "#include <net/if_dl.h>\n"
+ "#include <net/route.h>\n"
+ "#include <netinet/in.h>\n"
+ "#include <sys/socket.h>\n"
+ "#include <sys/stat.h>\n"
+ "#include <sys/wait.h>\n"
+ "#include <net/if.h>\n"
+ "#include <protocols/rwhod.h>\n"
+ "#include <assert.h>\n"
+ "#include <paths.h>\n"
+ "#include \"pathnames.h\"\n"
+ "#include <errno.h>\n"
+ "#include <inttypes.h>\n"
+ "#include <stdio.h>\n"
+ "#include <stdlib.h>\n"));
+}
+TEST_F(SortIncludesTest, SortPriorityNotDefined) {
+ FmtStyle = getLLVMStyle();
+ EXPECT_EQ("#include \"FormatTestUtils.h\"\n"
+ "#include \"clang/Format/Format.h\"\n"
+ "#include \"llvm/ADT/None.h\"\n"
+ "#include \"llvm/Support/Debug.h\"\n"
+ "#include \"gtest/gtest.h\"\n",
+ sort("#include \"clang/Format/Format.h\"\n"
+ "#include \"llvm/ADT/None.h\"\n"
+ "#include \"FormatTestUtils.h\"\n"
+ "#include \"gtest/gtest.h\"\n"
+ "#include \"llvm/Support/Debug.h\"\n"));
+}
+
TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) {
// Identical #includes have led to a failure with an unstable sort.
std::string Code = "#include <a>\n"
OpenPOWER on IntegriCloud