Skip to content

Commit 925bb20

Browse files
committed
[clang-format] Do not emit replacements while regrouping if Cpp includes are OK
Summary: Currently clang-format would always emit a replacement for multi-block #include sections if `IBS_Regroup`, even if the sections are correct: ``` % cat ~/test.h #include <a.h> #include "b.h" % bin/clang-format --output-replacements-xml -style=google ~/test.h <?xml version='1.0'?> <replacements xml:space='preserve' incomplete_format='false'> <replacement offset='0' length='30'>#include &lt;a.h>&#10;&#10;#include "b.h"</replacement> </replacements> % ``` This change makes clang-format not emit replacements in this case. The logic is similar to the one implemented for Java in r354452. Reviewers: ioeric Reviewed By: ioeric Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D60199 llvm-svn: 357599
1 parent d4e5500 commit 925bb20

File tree

2 files changed

+41
-13
lines changed

2 files changed

+41
-13
lines changed

clang/lib/Format/Format.cpp

+16-4
Original file line numberDiff line numberDiff line change
@@ -1753,6 +1753,7 @@ FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
17531753
static void sortCppIncludes(const FormatStyle &Style,
17541754
const SmallVectorImpl<IncludeDirective> &Includes,
17551755
ArrayRef<tooling::Range> Ranges, StringRef FileName,
1756+
StringRef Code,
17561757
tooling::Replacements &Replaces, unsigned *Cursor) {
17571758
unsigned IncludesBeginOffset = Includes.front().Offset;
17581759
unsigned IncludesEndOffset =
@@ -1788,6 +1789,10 @@ static void sortCppIncludes(const FormatStyle &Style,
17881789

17891790
// If the #includes are out of order, we generate a single replacement fixing
17901791
// the entire block. Otherwise, no replacement is generated.
1792+
// In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
1793+
// enough as additional newlines might be added or removed across #include
1794+
// blocks. This we handle below by generating the updated #imclude blocks and
1795+
// comparing it to the original.
17911796
if (Indices.size() == Includes.size() &&
17921797
std::is_sorted(Indices.begin(), Indices.end()) &&
17931798
Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve)
@@ -1808,6 +1813,11 @@ static void sortCppIncludes(const FormatStyle &Style,
18081813
CurrentCategory = Includes[Index].Category;
18091814
}
18101815

1816+
// If the #includes are out of order, we generate a single replacement fixing
1817+
// the entire range of blocks. Otherwise, no replacement is generated.
1818+
if (result == Code.substr(IncludesBeginOffset, IncludesBlockSize))
1819+
return;
1820+
18111821
auto Err = Replaces.add(tooling::Replacement(
18121822
FileName, Includes.front().Offset, IncludesBlockSize, result));
18131823
// FIXME: better error handling. For now, just skip the replacement for the
@@ -1876,8 +1886,8 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
18761886
MainIncludeFound = true;
18771887
IncludesInBlock.push_back({IncludeName, Line, Prev, Category});
18781888
} else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
1879-
sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces,
1880-
Cursor);
1889+
sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
1890+
Replaces, Cursor);
18811891
IncludesInBlock.clear();
18821892
FirstIncludeBlock = false;
18831893
}
@@ -1887,8 +1897,10 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
18871897
break;
18881898
SearchFrom = Pos + 1;
18891899
}
1890-
if (!IncludesInBlock.empty())
1891-
sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor);
1900+
if (!IncludesInBlock.empty()) {
1901+
sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
1902+
Cursor);
1903+
}
18921904
return Replaces;
18931905
}
18941906

clang/unittests/Format/SortIncludesTest.cpp

+25-9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "FormatTestUtils.h"
1010
#include "clang/Format/Format.h"
11+
#include "llvm/ADT/None.h"
1112
#include "llvm/Support/Debug.h"
1213
#include "gtest/gtest.h"
1314

@@ -24,9 +25,11 @@ class SortIncludesTest : public ::testing::Test {
2425
}
2526

2627
std::string sort(StringRef Code, std::vector<tooling::Range> Ranges,
27-
StringRef FileName = "input.cc") {
28+
StringRef FileName = "input.cc",
29+
unsigned ExpectedNumRanges = 1) {
2830
auto Replaces = sortIncludes(FmtStyle, Code, Ranges, FileName);
2931
Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
32+
EXPECT_EQ(ExpectedNumRanges, Replaces.size());
3033
auto Sorted = applyAllReplacements(Code, Replaces);
3134
EXPECT_TRUE(static_cast<bool>(Sorted));
3235
auto Result = applyAllReplacements(
@@ -35,8 +38,10 @@ class SortIncludesTest : public ::testing::Test {
3538
return *Result;
3639
}
3740

38-
std::string sort(StringRef Code, StringRef FileName = "input.cpp") {
39-
return sort(Code, GetCodeRange(Code), FileName);
41+
std::string sort(StringRef Code,
42+
StringRef FileName = "input.cpp",
43+
unsigned ExpectedNumRanges = 1) {
44+
return sort(Code, GetCodeRange(Code), FileName, ExpectedNumRanges);
4045
}
4146

4247
unsigned newCursor(llvm::StringRef Code, unsigned Cursor) {
@@ -151,7 +156,7 @@ TEST_F(SortIncludesTest, SupportClangFormatOffCStyle) {
151156
"#include <b>\n"
152157
"#include <a>\n"
153158
"#include <c>\n"
154-
"/* clang-format onwards */\n"));
159+
"/* clang-format onwards */\n", "input.h", 2));
155160
}
156161

157162
TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) {
@@ -161,7 +166,8 @@ TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) {
161166
"#include \"b.h\"\n",
162167
sort("#include \"a.h\"\n"
163168
"#include \"c.h\"\n"
164-
"#include \"b.h\"\n"));
169+
"#include \"b.h\"\n",
170+
"input.h", 0));
165171
}
166172

167173
TEST_F(SortIncludesTest, MixIncludeAndImport) {
@@ -214,7 +220,7 @@ TEST_F(SortIncludesTest, SortsLocallyInEachBlock) {
214220
sort("#include \"a.h\"\n"
215221
"#include \"c.h\"\n"
216222
"\n"
217-
"#include \"b.h\"\n"));
223+
"#include \"b.h\"\n", "input.h", 0));
218224
}
219225

220226
TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) {
@@ -458,7 +464,7 @@ TEST_F(SortIncludesTest, NegativePriorities) {
458464
sort("#include \"important_os_header.h\"\n"
459465
"#include \"c_main.h\"\n"
460466
"#include \"a_other.h\"\n",
461-
"c_main.cc"));
467+
"c_main.cc", 0));
462468
}
463469

464470
TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) {
@@ -486,7 +492,7 @@ TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) {
486492
"#include \"c_main.h\"\n"
487493
"\n"
488494
"#include \"a_other.h\"\n",
489-
"c_main.cc"));
495+
"c_main.cc", 0));
490496
}
491497

492498
TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) {
@@ -634,7 +640,17 @@ TEST_F(SortIncludesTest, DoNotSortLikelyXml) {
634640
sort("<!--;\n"
635641
"#include <b>\n"
636642
"#include <a>\n"
637-
"-->"));
643+
"-->", "input.h", 0));
644+
}
645+
646+
TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) {
647+
Style.IncludeBlocks = Style.IBS_Regroup;
648+
std::string Code = R"(
649+
#include "b.h"
650+
651+
#include <a.h>
652+
)";
653+
EXPECT_EQ(Code, sort(Code, "input.h", 0));
638654
}
639655

640656
} // end namespace

0 commit comments

Comments
 (0)