Skip to content

Commit 6036502

Browse files
[clang-format] [PR43372] - clang-format shows replacements in DOS files when no replacement is needed
Summary: This is a patch to fix PR43372 (https://bugs.llvm.org/show_bug.cgi?id=43372) - clang-format can't format file with includes, ( which really keep providing replacements for already sorted headers.) A similar issue was addressed by @krasimir in {D60199}, however, this seemingly only prevented the issue when the files being formatted did not contain windows line endings (\r\n) It's possible this is related to https://twitter.com/StephanTLavavej/status/1176722938243895296 given who @STL_MSFT works for! As people often used the existence of replacements to determine if a file needs clang-formatting, this is probably pretty important for windows users There may be a better way of comparing 2 strings and ignoring \r (which appear in both Results and Code), I couldn't choose between this idiom or the copy_if approach, but I'm happy to change it to whatever people consider more performant. Reviewers: krasimir, klimek, owenpan, ioeric Reviewed By: krasimir Subscribers: cfe-commits, STL_MSFT, krasimir Tags: #clang-format, #clang, #clang-tools-extra Differential Revision: https://reviews.llvm.org/D68227 llvm-svn: 373388
1 parent 2df5f12 commit 6036502

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

clang/lib/Format/Format.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,6 +1825,28 @@ FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
18251825
return std::make_pair(CursorIndex, OffsetToEOL);
18261826
}
18271827

1828+
// Replace all "\r\n" with "\n".
1829+
std::string replaceCRLF(const std::string &Code) {
1830+
std::string NewCode;
1831+
size_t Pos = 0, LastPos = 0;
1832+
1833+
do {
1834+
Pos = Code.find("\r\n", LastPos);
1835+
if (Pos == LastPos) {
1836+
LastPos++;
1837+
continue;
1838+
}
1839+
if (Pos == std::string::npos) {
1840+
NewCode += Code.substr(LastPos);
1841+
break;
1842+
}
1843+
NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
1844+
LastPos = Pos + 2;
1845+
} while (Pos != std::string::npos);
1846+
1847+
return NewCode;
1848+
}
1849+
18281850
// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
18291851
// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
18301852
// source order.
@@ -1898,7 +1920,8 @@ static void sortCppIncludes(const FormatStyle &Style,
18981920

18991921
// If the #includes are out of order, we generate a single replacement fixing
19001922
// the entire range of blocks. Otherwise, no replacement is generated.
1901-
if (result == Code.substr(IncludesBeginOffset, IncludesBlockSize))
1923+
if (replaceCRLF(result) ==
1924+
replaceCRLF(Code.substr(IncludesBeginOffset, IncludesBlockSize)))
19021925
return;
19031926

19041927
auto Err = Replaces.add(tooling::Replacement(
@@ -2066,7 +2089,8 @@ static void sortJavaImports(const FormatStyle &Style,
20662089

20672090
// If the imports are out of order, we generate a single replacement fixing
20682091
// the entire block. Otherwise, no replacement is generated.
2069-
if (result == Code.substr(Imports.front().Offset, ImportsBlockSize))
2092+
if (replaceCRLF(result) ==
2093+
replaceCRLF(Code.substr(Imports.front().Offset, ImportsBlockSize)))
20702094
return;
20712095

20722096
auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
@@ -2356,7 +2380,7 @@ reformat(const FormatStyle &Style, StringRef Code,
23562380

23572381
auto Env =
23582382
std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
2359-
NextStartColumn, LastStartColumn);
2383+
NextStartColumn, LastStartColumn);
23602384
llvm::Optional<std::string> CurrentCode = None;
23612385
tooling::Replacements Fixes;
23622386
unsigned Penalty = 0;

clang/unittests/Format/SortImportsTestJava.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,13 @@ TEST_F(SortImportsTestJava, NoReplacementsForValidImports) {
285285
sortIncludes(FmtStyle, Code, GetCodeRange(Code), "input.java").empty());
286286
}
287287

288+
TEST_F(SortImportsTestJava, NoReplacementsForValidImportsWindows) {
289+
std::string Code = "import org.a;\r\n"
290+
"import org.b;\r\n";
291+
EXPECT_TRUE(
292+
sortIncludes(FmtStyle, Code, GetCodeRange(Code), "input.java").empty());
293+
}
294+
288295
} // end namespace
289296
} // end namespace format
290297
} // end namespace clang

clang/unittests/Format/SortIncludesTest.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,14 @@ TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) {
724724
EXPECT_EQ(Code, sort(Code, "input.h", 0));
725725
}
726726

727+
TEST_F(SortIncludesTest,
728+
DoNotOutputReplacementsForSortedBlocksWithRegroupingWindows) {
729+
Style.IncludeBlocks = Style.IBS_Regroup;
730+
std::string Code = "#include \"b.h\"\r\n"
731+
"\r\n"
732+
"#include <a.h>\r\n";
733+
EXPECT_EQ(Code, sort(Code, "input.h", 0));
734+
}
727735

728736
TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) {
729737
FmtStyle = getGoogleStyle(FormatStyle::LK_ObjC);

0 commit comments

Comments
 (0)