Index: docs/ClangFormatStyleOptions.rst =================================================================== --- docs/ClangFormatStyleOptions.rst +++ docs/ClangFormatStyleOptions.rst @@ -521,11 +521,11 @@ .. code-block:: c++ true: - class foo - {}; + class foo {}; false: - class foo {}; + class foo + {}; * ``bool AfterControlStatement`` Wrap control statements (``if``/``for``/``while``/``switch``/..). @@ -603,12 +603,12 @@ struct foo { int x; - }; + } false: struct foo { int x; - }; + } * ``bool AfterUnion`` Wrap union definitions. @@ -659,6 +659,18 @@ * ``bool IndentBraces`` Indent the wrapped braces themselves. + * ``bool SplitEmptyFunctionBody`` If ``false``, empty function body can be put on a single line. + This option is used only if the opening brace of the function has + already been wrapped, i.e. the `AfterFunction` brace wrapping mode is + set, and the function could/should not be put on a single line (as per + `AllowShortFunctionsOnASingleLine` and constructor formatting options). + + .. code-block:: c++ + + int f() vs. inf f() + {} { + } + **BreakAfterJavaFieldAnnotations** (``bool``) Break after each annotation on a field in Java files. @@ -894,22 +906,45 @@ ? firstValue : SecondValueVeryVeryVeryVeryLong; - false: + true: veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription ? firstValue : SecondValueVeryVeryVeryVeryLong; -**BreakConstructorInitializersBeforeComma** (``bool``) - Always break constructor initializers before commas and align - the commas with the colon. +**BreakConstructorInitializers** (``BreakConstructorInitializersStyle``) + The constructor initializers style to use.. + + Possible values: + + * ``BCIS_BeforeColon`` (in configuration: ``BeforeColon``) + Break constructor initializers before the colon and after the commas. + + .. code-block:: c++ + + Constructor() + : initializer1(), + initializer2() + + * ``BCIS_BeforeComma`` (in configuration: ``BeforeComma``) + Break constructor initializers before the colon and commas, and align + the commas with the colon. + + .. code-block:: c++ + + Constructor() + : initializer1() + , initializer2() + + * ``BCIS_AfterColon`` (in configuration: ``AfterColon``) + Break constructor initializers after the colon and commas. + + .. code-block:: c++ + + Constructor() : + initializer1(), + initializer2() - .. code-block:: c++ - true: false: - SomeClass::Constructor() vs. SomeClass::Constructor() : a(a), - : a(a) b(b), - , b(b) c(c) {} - , c(c) {} **BreakStringLiterals** (``bool``) Allow breaking string literals when formatting. @@ -931,6 +966,31 @@ // Will leave the following line unaffected #include // FOOBAR pragma: keep +**CompactNamespaces** (``bool``) + If ``true``, consecutive namespace declarations will be on the same + line. If ``false``, each namespace is declared on a new line. + + .. code-block:: c++ + + true: + namespace Foo { namespace Bar { + }} + + false: + namespace Foo { + namespace Bar { + } + } + + If it does not fit on a single line, the overflowing namespaces get + wrapped: + + .. code-block:: c++ + + namespace Foo { namespace Bar { + namespace Extra { + }}} + **ConstructorInitializerAllOnOneLineOrOnePerLine** (``bool``) If the constructor initializers don't fit on a line, put each initializer on its own line. @@ -1321,6 +1381,9 @@ Add a space in front of an Objective-C protocol list, i.e. use ``Foo `` instead of ``Foo``. +**PenaltyBreakAssignment** (``unsigned``) + The penalty for breaking around an assignment operator. + **PenaltyBreakBeforeFirstCallParameter** (``unsigned``) The penalty for breaking a function call after ``call(``. @@ -1392,6 +1455,15 @@ #include "b.h" vs. #include "a.h" #include "a.h" #include "b.h" +**SortUsingDeclarations** (``bool``) + If ``true``, clang-format will sort using declarations. + + .. code-block:: c++ + + false: true: + using std::cout; vs. using std::cin; + using std::cin; using std::cout; + **SpaceAfterCStyleCast** (``bool``) If ``true``, a space is inserted after C style casts. Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -723,8 +723,7 @@ bool BreakBeforeTernaryOperators; /// \brief Different ways to break initializers. - enum BreakConstructorInitializersStyle - { + enum BreakConstructorInitializersStyle { /// Break constructor initializers before the colon and after the commas. /// \code /// Constructor() @@ -1253,6 +1252,14 @@ /// \endcode bool SortIncludes; + /// \brief If ``true``, clang-format will sort using declarations. + /// \code + /// false: true: + /// using std::cout; vs. using std::cin; + /// using std::cin; using std::cout; + /// \endcode + bool SortUsingDeclarations; + /// \brief If ``true``, a space is inserted after C style casts. /// \code /// true: false: Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -378,6 +378,7 @@ IO.mapOptional("PointerAlignment", Style.PointerAlignment); IO.mapOptional("ReflowComments", Style.ReflowComments); IO.mapOptional("SortIncludes", Style.SortIncludes); + IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations); IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast); IO.mapOptional("SpaceAfterTemplateKeyword", Style.SpaceAfterTemplateKeyword); IO.mapOptional("SpaceBeforeAssignmentOperators", @@ -1878,38 +1879,53 @@ return tooling::Replacements(); if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) return tooling::Replacements(); - auto Env = Environment::CreateVirtualEnvironment(Code, FileName, Ranges); - - auto reformatAfterApplying = [&] (TokenAnalyzer& Fixer) { - tooling::Replacements Fixes = Fixer.process(); - if (!Fixes.empty()) { - auto NewCode = applyAllReplacements(Code, Fixes); - if (NewCode) { - auto NewEnv = Environment::CreateVirtualEnvironment( - *NewCode, FileName, - tooling::calculateRangesAfterReplacements(Fixes, Ranges)); - Formatter Format(*NewEnv, Expanded, Status); - return Fixes.merge(Format.process()); - } - } - Formatter Format(*Env, Expanded, Status); - return Format.process(); - }; - if (Style.Language == FormatStyle::LK_Cpp && - Style.FixNamespaceComments) { - NamespaceEndCommentsFixer CommentsFixer(*Env, Expanded); - return reformatAfterApplying(CommentsFixer); + typedef std::function + AnalyzerPass; + SmallVector Passes; + + if (Style.Language == FormatStyle::LK_Cpp) { + if (Style.FixNamespaceComments) + Passes.emplace_back([&](const Environment &Env) { + return NamespaceEndCommentsFixer(Env, Expanded).process(); + }); + + if (Style.SortUsingDeclarations) + Passes.emplace_back([&](const Environment &Env) { + return UsingDeclarationsSorter(Env, Expanded).process(); + }); } if (Style.Language == FormatStyle::LK_JavaScript && - Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) { - JavaScriptRequoter Requoter(*Env, Expanded); - return reformatAfterApplying(Requoter); + Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) + Passes.emplace_back([&](const Environment &Env) { + return JavaScriptRequoter(Env, Expanded).process(); + }); + + Passes.emplace_back([&](const Environment &Env) { + return Formatter(Env, Expanded, Status).process(); + }); + + std::unique_ptr Env = + Environment::CreateVirtualEnvironment(Code, FileName, Ranges); + llvm::Optional CurrentCode = None; + tooling::Replacements Fixes; + for (size_t I = 0, E = Passes.size(); I < E; ++I) { + tooling::Replacements PassFixes = Passes[I](*Env); + auto NewCode = applyAllReplacements( + CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes); + if (NewCode) { + Fixes = Fixes.merge(PassFixes); + if (I + 1 < E) { + CurrentCode = std::move(*NewCode); + Env = Environment::CreateVirtualEnvironment( + *CurrentCode, FileName, + tooling::calculateRangesAfterReplacements(Fixes, Ranges)); + } + } } - Formatter Format(*Env, Expanded, Status); - return Format.process(); + return Fixes; } tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -9287,6 +9287,7 @@ CHECK_PARSE_BOOL(Cpp11BracedListStyle); CHECK_PARSE_BOOL(ReflowComments); CHECK_PARSE_BOOL(SortIncludes); + CHECK_PARSE_BOOL(SortUsingDeclarations); CHECK_PARSE_BOOL(SpacesInParentheses); CHECK_PARSE_BOOL(SpacesInSquareBrackets); CHECK_PARSE_BOOL(SpacesInAngles); @@ -10828,6 +10829,13 @@ EXPECT_EQ(Expected, *Result); } +TEST_F(FormatTest, FormatSortsUsingDeclarations) { + EXPECT_EQ("using std::cin;\n" + "using std::cout;", + format("using std::cout;\n" + "using std::cin;", getGoogleStyle())); +} + TEST_F(FormatTest, UTF8CharacterLiteralCpp03) { format::FormatStyle Style = format::getLLVMStyle(); Style.Standard = FormatStyle::LS_Cpp03;