Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -326,6 +326,10 @@ /// a zero-length name is assumed. bool Cpp11BracedListStyle; + /// \brief Analyze the formatted file for the most used line ending. (``\r\n`` + /// or ``\n``) ``UseCRLF`` is then used only as fallback. + bool DeriveLineEnding; + /// \brief If ``true``, analyze the formatted file for the most common /// alignment of ``&`` and ``*``. ``PointerAlignment`` is then used only as /// fallback. @@ -605,6 +609,9 @@ UT_Always }; + /// \brief Use ``\r\n`` instead of ``\n`` for line breaks. + bool UseCRLF; + /// \brief The way to use tab characters in the resulting file. UseTabStyle UseTab; @@ -661,6 +668,7 @@ R.ConstructorInitializerIndentWidth && ContinuationIndentWidth == R.ContinuationIndentWidth && Cpp11BracedListStyle == R.Cpp11BracedListStyle && + DeriveLineEnding == R.DeriveLineEnding && DerivePointerAlignment == R.DerivePointerAlignment && DisableFormat == R.DisableFormat && ExperimentalAutoDetectBinPacking == @@ -698,7 +706,7 @@ SpacesInParentheses == R.SpacesInParentheses && SpacesInSquareBrackets == R.SpacesInSquareBrackets && Standard == R.Standard && TabWidth == R.TabWidth && - UseTab == R.UseTab && + UseTab == R.UseTab && UseCRLF == R.UseCRLF && JavaScriptQuotes == R.JavaScriptQuotes; } }; Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -294,6 +294,7 @@ Style.ConstructorInitializerIndentWidth); IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth); IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle); + IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding); IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment); IO.mapOptional("DisableFormat", Style.DisableFormat); IO.mapOptional("ExperimentalAutoDetectBinPacking", @@ -343,6 +344,7 @@ IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); IO.mapOptional("Standard", Style.Standard); IO.mapOptional("TabWidth", Style.TabWidth); + IO.mapOptional("UseCRLF", Style.UseCRLF); IO.mapOptional("UseTab", Style.UseTab); IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes); } @@ -510,6 +512,7 @@ LLVMStyle.ConstructorInitializerIndentWidth = 4; LLVMStyle.ContinuationIndentWidth = 4; LLVMStyle.Cpp11BracedListStyle = true; + LLVMStyle.DeriveLineEnding = true; LLVMStyle.DerivePointerAlignment = false; LLVMStyle.ExperimentalAutoDetectBinPacking = false; LLVMStyle.ForEachMacros.push_back("foreach"); @@ -532,6 +535,7 @@ LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; LLVMStyle.SpacesBeforeTrailingComments = 1; LLVMStyle.Standard = FormatStyle::LS_Cpp11; + LLVMStyle.UseCRLF = false; LLVMStyle.UseTab = FormatStyle::UT_Never; LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; LLVMStyle.ReflowComments = true; @@ -1448,8 +1452,11 @@ Formatter(const FormatStyle &Style, SourceManager &SourceMgr, FileID ID, ArrayRef Ranges) : Style(Style), ID(ID), SourceMgr(SourceMgr), - Whitespaces(SourceMgr, Style, - inputUsesCRLF(SourceMgr.getBufferData(ID))), + Whitespaces( + SourceMgr, Style, + Style.DeriveLineEnding + ? inputUsesCRLF(SourceMgr.getBufferData(ID), Style.UseCRLF) + : Style.UseCRLF), Ranges(Ranges.begin(), Ranges.end()), UnwrappedLines(1), Encoding(encoding::detectEncoding(SourceMgr.getBufferData(ID))) { DEBUG(llvm::dbgs() << "File encoding: " @@ -1733,8 +1740,10 @@ return false; } - static bool inputUsesCRLF(StringRef Text) { - return Text.count('\r') * 2 > Text.count('\n'); + static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF) { + size_t LF = Text.count('\n'); + size_t CR = Text.count('\r') * 2; + return LF == CR ? DefaultToCRLF : CR > LF; } bool Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -9908,6 +9908,7 @@ CHECK_PARSE_BOOL(BreakConstructorInitializersBeforeComma); CHECK_PARSE_BOOL(BreakStringLiterals); CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine); + CHECK_PARSE_BOOL(DeriveLineEnding); CHECK_PARSE_BOOL(DerivePointerAlignment); CHECK_PARSE_BOOL_FIELD(DerivePointerAlignment, "DerivePointerBinding"); CHECK_PARSE_BOOL(DisableFormat); @@ -9927,6 +9928,7 @@ CHECK_PARSE_BOOL(SpacesInCStyleCastParentheses); CHECK_PARSE_BOOL(SpaceAfterCStyleCast); CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators); + CHECK_PARSE_BOOL(UseCRLF); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterControlStatement); @@ -11003,6 +11005,94 @@ "should not introduce\r\n" "an extra carriage return\r\n" "*/\r\n")); + + FormatStyle style = getLLVMStyle(); + + style.DeriveLineEnding = true; + style.UseCRLF = false; + EXPECT_EQ("union FooBarBazQux {\n" + " int foo;\n" + " int bar;\n" + " int baz;\n" + "};", + format("union FooBarBazQux {\r\n" + " int foo;\n" + " int bar;\r\n" + " int baz;\n" + "};", + style)); + style.UseCRLF = true; + EXPECT_EQ("union FooBarBazQux {\r\n" + " int foo;\r\n" + " int bar;\r\n" + " int baz;\r\n" + "};", + format("union FooBarBazQux {\r\n" + " int foo;\n" + " int bar;\r\n" + " int baz;\n" + "};", + style)); + + style.DeriveLineEnding = false; + style.UseCRLF = false; + EXPECT_EQ("union FooBarBazQux {\n" + " int foo;\n" + " int bar;\n" + " int baz;\n" + " int qux;\n" + "};", + format("union FooBarBazQux {\r\n" + " int foo;\n" + " int bar;\r\n" + " int baz;\n" + " int qux;\r\n" + "};", + style)); + style.UseCRLF = true; + EXPECT_EQ("union FooBarBazQux {\r\n" + " int foo;\r\n" + " int bar;\r\n" + " int baz;\r\n" + " int qux;\r\n" + "};", + format("union FooBarBazQux {\r\n" + " int foo;\n" + " int bar;\r\n" + " int baz;\n" + " int qux;\n" + "};", + style)); + + style.DeriveLineEnding = true; + style.UseCRLF = false; + EXPECT_EQ("union FooBarBazQux {\r\n" + " int foo;\r\n" + " int bar;\r\n" + " int baz;\r\n" + " int qux;\r\n" + "};", + format("union FooBarBazQux {\r\n" + " int foo;\n" + " int bar;\r\n" + " int baz;\n" + " int qux;\r\n" + "};", + style)); + style.UseCRLF = true; + EXPECT_EQ("union FooBarBazQux {\n" + " int foo;\n" + " int bar;\n" + " int baz;\n" + " int qux;\n" + "};", + format("union FooBarBazQux {\r\n" + " int foo;\n" + " int bar;\r\n" + " int baz;\n" + " int qux;\n" + "};", + style)); } TEST_F(FormatTest, MunchSemicolonAfterBlocks) {