diff options
| -rw-r--r-- | clang/lib/Format/Format.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Format/WhitespaceManager.cpp | 49 | ||||
| -rw-r--r-- | clang/lib/Format/WhitespaceManager.h | 16 | ||||
| -rw-r--r-- | clang/unittests/Format/FormatTest.cpp | 37 |
4 files changed, 78 insertions, 36 deletions
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 07c6cf974da..52f8b07475d 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -631,7 +631,9 @@ private: ++FormatTok->NewlinesBefore; // FIXME: This is technically incorrect, as it could also // be a literal backslash at the end of the line. - if (i == 0 || FormatTok->TokenText[i - 1] != '\\') + if (i == 0 || (FormatTok->TokenText[i - 1] != '\\' && + (FormatTok->TokenText[i - 1] != '\r' || i == 1 || + FormatTok->TokenText[i - 2] != '\\'))) FormatTok->HasUnescapedNewline = true; FormatTok->LastNewlineOffset = WhitespaceLength + i + 1; Column = 0; @@ -745,8 +747,8 @@ public: Formatter(const FormatStyle &Style, Lexer &Lex, SourceManager &SourceMgr, const std::vector<CharSourceRange> &Ranges) : Style(Style), Lex(Lex), SourceMgr(SourceMgr), - Whitespaces(SourceMgr, Style), Ranges(Ranges), - Encoding(encoding::detectEncoding(Lex.getBuffer())) { + Whitespaces(SourceMgr, Style, inputUsesCRLF(Lex.getBuffer())), + Ranges(Ranges), Encoding(encoding::detectEncoding(Lex.getBuffer())) { DEBUG(llvm::dbgs() << "File encoding: " << (Encoding == encoding::Encoding_UTF8 ? "UTF8" : "unknown") @@ -883,6 +885,10 @@ public: } private: + static bool inputUsesCRLF(StringRef Text) { + return Text.count('\r') * 2 > Text.count('\n'); + } + void deriveLocalStyle() { unsigned CountBoundToVariable = 0; unsigned CountBoundToType = 0; diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 0f46e62563a..4138442c0cc 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -221,14 +221,14 @@ void WhitespaceManager::generateChanges() { for (unsigned i = 0, e = Changes.size(); i != e; ++i) { const Change &C = Changes[i]; if (C.CreateReplacement) { - std::string ReplacementText = - C.PreviousLinePostfix + - (C.ContinuesPPDirective - ? getNewlineText(C.NewlinesBefore, C.Spaces, - C.PreviousEndOfTokenColumn, - C.EscapedNewlineColumn) - : getNewlineText(C.NewlinesBefore, C.Spaces)) + - C.CurrentLinePrefix; + std::string ReplacementText = C.PreviousLinePostfix; + if (C.ContinuesPPDirective) + appendNewlineText(ReplacementText, C.NewlinesBefore, + C.PreviousEndOfTokenColumn, C.EscapedNewlineColumn); + else + appendNewlineText(ReplacementText, C.NewlinesBefore); + appendIndentText(ReplacementText, C.Spaces); + ReplacementText.append(C.CurrentLinePrefix); storeReplacement(C.OriginalWhitespaceRange, ReplacementText); } } @@ -246,34 +246,33 @@ void WhitespaceManager::storeReplacement(const SourceRange &Range, SourceMgr, CharSourceRange::getCharRange(Range), Text)); } -std::string WhitespaceManager::getNewlineText(unsigned Newlines, - unsigned Spaces) { - return std::string(Newlines, '\n') + getIndentText(Spaces); +void WhitespaceManager::appendNewlineText(std::string &Text, + unsigned Newlines) { + for (unsigned i = 0; i < Newlines; ++i) + Text.append(UseCRLF ? "\r\n" : "\n"); } -std::string WhitespaceManager::getNewlineText(unsigned Newlines, - unsigned Spaces, - unsigned PreviousEndOfTokenColumn, - unsigned EscapedNewlineColumn) { - std::string NewlineText; +void WhitespaceManager::appendNewlineText(std::string &Text, unsigned Newlines, + unsigned PreviousEndOfTokenColumn, + unsigned EscapedNewlineColumn) { if (Newlines > 0) { unsigned Offset = std::min<int>(EscapedNewlineColumn - 1, PreviousEndOfTokenColumn); for (unsigned i = 0; i < Newlines; ++i) { - NewlineText += std::string(EscapedNewlineColumn - Offset - 1, ' '); - NewlineText += "\\\n"; + Text.append(std::string(EscapedNewlineColumn - Offset - 1, ' ')); + Text.append(UseCRLF ? "\\\r\n" : "\\\n"); Offset = 0; } } - return NewlineText + getIndentText(Spaces); } -std::string WhitespaceManager::getIndentText(unsigned Spaces) { - if (!Style.UseTab) - return std::string(Spaces, ' '); - - return std::string(Spaces / Style.TabWidth, '\t') + - std::string(Spaces % Style.TabWidth, ' '); +void WhitespaceManager::appendIndentText(std::string &Text, unsigned Spaces) { + if (!Style.UseTab) { + Text.append(std::string(Spaces, ' ')); + } else { + Text.append(std::string(Spaces / Style.TabWidth, '\t')); + Text.append(std::string(Spaces % Style.TabWidth, ' ')); + } } } // namespace format diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h index 9ca34806374..2c58216d1cd 100644 --- a/clang/lib/Format/WhitespaceManager.h +++ b/clang/lib/Format/WhitespaceManager.h @@ -37,8 +37,9 @@ namespace format { /// There may be multiple calls to \c breakToken for a given token. class WhitespaceManager { public: - WhitespaceManager(SourceManager &SourceMgr, const FormatStyle &Style) - : SourceMgr(SourceMgr), Style(Style) {} + WhitespaceManager(SourceManager &SourceMgr, const FormatStyle &Style, + bool UseCRLF) + : SourceMgr(SourceMgr), Style(Style), UseCRLF(UseCRLF) {} /// \brief Replaces the whitespace in front of \p Tok. Only call once for /// each \c AnnotatedToken. @@ -152,16 +153,17 @@ private: /// \brief Stores \p Text as the replacement for the whitespace in \p Range. void storeReplacement(const SourceRange &Range, StringRef Text); - std::string getNewlineText(unsigned Newlines, unsigned Spaces); - std::string getNewlineText(unsigned Newlines, unsigned Spaces, - unsigned PreviousEndOfTokenColumn, - unsigned EscapedNewlineColumn); - std::string getIndentText(unsigned Spaces); + void appendNewlineText(std::string &Text, unsigned Newlines); + void appendNewlineText(std::string &Text, unsigned Newlines, + unsigned PreviousEndOfTokenColumn, + unsigned EscapedNewlineColumn); + void appendIndentText(std::string &Text, unsigned Spaces); SmallVector<Change, 16> Changes; SourceManager &SourceMgr; tooling::Replacements Replaces; const FormatStyle &Style; + bool UseCRLF; }; } // namespace format diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 7f6956e8bbf..00ece1a6594 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -116,7 +116,7 @@ TEST_F(FormatTest, DoesNotChangeCorrectlyFormattedCode) { TEST_F(FormatTest, FormatsGlobalStatementsAt0) { EXPECT_EQ("int i;", format(" int i;")); - EXPECT_EQ("\nint i;", format(" \n\t \r int i;")); + EXPECT_EQ("\nint i;", format(" \n\t \v \f int i;")); EXPECT_EQ("int i;\nint j;", format(" int i; int j;")); EXPECT_EQ("int i;\nint j;", format(" int i;\n int j;")); } @@ -6479,5 +6479,40 @@ TEST_F(FormatTest, FormatsBlocks) { "onOperationDone]; }] };"); } +TEST_F(FormatTest, SupportsCRLF) { + EXPECT_EQ("int a;\r\n" + "int b;\r\n" + "int c;\r\n", + format("int a;\r\n" + " int b;\r\n" + " int c;\r\n", + getLLVMStyle())); + EXPECT_EQ("int a;\r\n" + "int b;\r\n" + "int c;\r\n", + format("int a;\r\n" + " int b;\n" + " int c;\r\n", + getLLVMStyle())); + EXPECT_EQ("int a;\n" + "int b;\n" + "int c;\n", + format("int a;\r\n" + " int b;\n" + " int c;\n", + getLLVMStyle())); + EXPECT_EQ("\"aaaaaaa \"\r\n" + "\"bbbbbbb\";\r\n", + format("\"aaaaaaa bbbbbbb\";\r\n", getLLVMStyleWithColumns(10))); + EXPECT_EQ("#define A \\\r\n" + " b; \\\r\n" + " c; \\\r\n" + " d;\r\n", + format("#define A \\\r\n" + " b; \\\r\n" + " c; d; \r\n", + getGoogleStyle())); +} + } // end namespace tooling } // end namespace clang |

