diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1217,6 +1217,10 @@ /// \endcode bool Cpp11BracedListStyle; + /// \brief Analyze the formatted file for the most used line ending (``\r\n`` + /// or ``\n``). ``UseCRLF`` is only used as a fallback if none can be derived. + bool DeriveLineEnding; + /// If ``true``, analyze the formatted file for the most common /// alignment of ``&`` and ``*``. /// Pointer and reference alignment styles are going to be updated according @@ -2032,6 +2036,10 @@ UT_Always }; + /// \brief Use ``\r\n`` instead of ``\n`` for line breaks. + /// Also used as fallback if ``DeriveLineEnding`` is true. + bool UseCRLF; + /// The way to use tab characters in the resulting file. UseTabStyle UseTab; @@ -2079,6 +2087,7 @@ R.ConstructorInitializerIndentWidth && ContinuationIndentWidth == R.ContinuationIndentWidth && Cpp11BracedListStyle == R.Cpp11BracedListStyle && + DeriveLineEnding == R.DeriveLineEnding && DerivePointerAlignment == R.DerivePointerAlignment && DisableFormat == R.DisableFormat && ExperimentalAutoDetectBinPacking == @@ -2143,6 +2152,7 @@ SpacesInSquareBrackets == R.SpacesInSquareBrackets && Standard == R.Standard && TabWidth == R.TabWidth && StatementMacros == R.StatementMacros && UseTab == R.UseTab && + UseCRLF == R.UseCRLF && TypenameMacros == R.TypenameMacros; } diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -467,6 +467,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", @@ -546,6 +547,7 @@ IO.mapOptional("StatementMacros", Style.StatementMacros); IO.mapOptional("TabWidth", Style.TabWidth); IO.mapOptional("TypenameMacros", Style.TypenameMacros); + IO.mapOptional("UseCRLF", Style.UseCRLF); IO.mapOptional("UseTab", Style.UseTab); } }; @@ -762,6 +764,7 @@ LLVMStyle.ConstructorInitializerIndentWidth = 4; LLVMStyle.ContinuationIndentWidth = 4; LLVMStyle.Cpp11BracedListStyle = true; + LLVMStyle.DeriveLineEnding = true; LLVMStyle.DerivePointerAlignment = false; LLVMStyle.ExperimentalAutoDetectBinPacking = false; LLVMStyle.FixNamespaceComments = true; @@ -792,6 +795,7 @@ LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; LLVMStyle.SpacesBeforeTrailingComments = 1; LLVMStyle.Standard = FormatStyle::LS_Latest; + LLVMStyle.UseCRLF = false; LLVMStyle.UseTab = FormatStyle::UT_Never; LLVMStyle.ReflowComments = true; LLVMStyle.SpacesInParentheses = false; @@ -1350,7 +1354,10 @@ WhitespaceManager Whitespaces( Env.getSourceManager(), Style, - inputUsesCRLF(Env.getSourceManager().getBufferData(Env.getFileID()))); + Style.DeriveLineEnding ? + inputUsesCRLF(Env.getSourceManager().getBufferData(Env.getFileID()), + Style.UseCRLF) : + Style.UseCRLF); ContinuationIndenter Indenter(Style, Tokens.getKeywords(), Env.getSourceManager(), Whitespaces, Encoding, BinPackInconclusiveFunctions); @@ -1371,8 +1378,10 @@ } private: - 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 diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -12500,6 +12500,7 @@ CHECK_PARSE_BOOL(BreakStringLiterals); CHECK_PARSE_BOOL(CompactNamespaces); CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine); + CHECK_PARSE_BOOL(DeriveLineEnding); CHECK_PARSE_BOOL(DerivePointerAlignment); CHECK_PARSE_BOOL_FIELD(DerivePointerAlignment, "DerivePointerBinding"); CHECK_PARSE_BOOL(DisableFormat); @@ -12528,6 +12529,7 @@ CHECK_PARSE_BOOL(SpaceBeforeCtorInitializerColon); CHECK_PARSE_BOOL(SpaceBeforeInheritanceColon); CHECK_PARSE_BOOL(SpaceBeforeRangeBasedForLoopColon); + CHECK_PARSE_BOOL(UseCRLF); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterCaseLabel); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass); @@ -14056,6 +14058,94 @@ format("/*\r\n" " \r\r\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) {