[PATCH] D96744: clang-format IncludeBlocks: Regroup determination of "main" for framework-style includes fix
Conrad Poelman via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 15 19:41:21 PST 2021
poelmanc created this revision.
poelmanc added reviewers: MyDeveloperDay, hokein, sammccall.
poelmanc added projects: clang-tools-extra, clang-format.
poelmanc requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Most modern libraries and applications include files with relative paths from a root (e.g. `#include <foo/bar/baz.h>` versus `#include "baz.h"`.) When regrouping, a file's "main include" should be left at the top (given priority 0.) The existing `IncludeCategoryManager::isMainHeader()` checks only the file //stem// (e.g. `baz.h`), and fails to identify main includes with angle brackets despite a comment saying `// remove the surrounding "" or <>`.
This patch fixes these issues by comparing all directory components present in both the `#include` string and the file name, and by allowing angle bracket includes to be considered "main". It adds a new `IsMainHeader` unit test to check behavior of framework-style includes, which would fail without this patch.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D96744
Files:
clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
clang/unittests/Tooling/HeaderIncludesTest.cpp
Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===================================================================
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -91,6 +91,28 @@
EXPECT_EQ(Expected, insert(Code, "\"a.h\""));
}
+TEST_F(HeaderIncludesTest, IsMainHeader) {
+ Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+ .IncludeStyle;
+ std::vector<StringRef> FileNames{"foo/bar/baz.cpp", "foo/bar/baz.cu.cpp",
+ "foo/bar/baz_test.cu.cpp"};
+ for (const StringRef &FileName : FileNames) {
+ IncludeCategoryManager Manager(Style, FileName);
+ // These framework-style includes should all be considered "main".
+ EXPECT_EQ(Manager.getIncludePriority("<foo/bar/baz.h>", true), 0)
+ << "for source file " << FileName;
+ EXPECT_EQ(Manager.getIncludePriority("\"bar/baz.h\"", true), 0)
+ << "for source file " << FileName;
+ EXPECT_EQ(Manager.getIncludePriority("<baz.h>", true), 0)
+ << "for source file " << FileName;
+ // These should not be considered "main" as the paths to baz.h differ.
+ EXPECT_NE(Manager.getIncludePriority("<bar/foo/baz.h>", true), 0)
+ << "for source file " << FileName;
+ EXPECT_NE(Manager.getIncludePriority("\"foo/baz.h\"", true), 0)
+ << "for source file " << FileName;
+ }
+}
+
TEST_F(HeaderIncludesTest, InsertAfterMainHeader) {
std::string Code = "#include \"fix.h\"\n"
"\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===================================================================
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -233,9 +233,6 @@
return Ret;
}
bool IncludeCategoryManager::isMainHeader(StringRef IncludeName) const {
- if (!IncludeName.startswith("\""))
- return false;
-
IncludeName =
IncludeName.drop_front(1).drop_back(1); // remove the surrounding "" or <>
// Not matchingStem: implementation files may have compound extensions but
@@ -259,8 +256,22 @@
if (!Matching.empty()) {
llvm::Regex MainIncludeRegex(HeaderStem.str() + Style.IncludeIsMainRegex,
llvm::Regex::IgnoreCase);
- if (MainIncludeRegex.match(Matching))
+ if (MainIncludeRegex.match(Matching)) {
+ // Matching is non-empty so these should be non-empty as well, making
+ // ++rbegin(IncludeName) and ++rbegin(FileName) safe.
+ assert(!IncludeName.empty());
+ assert(!FileName.empty());
+ // Checked stems above. Check remaining common path components here.
+ auto IncludePathRIter = ++llvm::sys::path::rbegin(IncludeName);
+ auto FilePathRiter = ++llvm::sys::path::rbegin(FileName);
+ for (; IncludePathRIter != llvm::sys::path::rend(IncludeName) &&
+ FilePathRiter != llvm::sys::path::rend(FileName);
+ ++IncludePathRIter, ++FilePathRiter) {
+ if (*IncludePathRIter != *FilePathRiter)
+ return false;
+ }
return true;
+ }
}
return false;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D96744.323865.patch
Type: text/x-patch
Size: 3133 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210216/aa9edb22/attachment.bin>
More information about the cfe-commits
mailing list