Index: cfe/trunk/docs/ClangFormatStyleOptions.rst =================================================================== --- cfe/trunk/docs/ClangFormatStyleOptions.rst +++ cfe/trunk/docs/ClangFormatStyleOptions.rst @@ -1475,6 +1475,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: cfe/trunk/include/clang/Format/Format.h =================================================================== --- cfe/trunk/include/clang/Format/Format.h +++ cfe/trunk/include/clang/Format/Format.h @@ -1270,6 +1270,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: cfe/trunk/lib/Format/Format.cpp =================================================================== --- cfe/trunk/lib/Format/Format.cpp +++ cfe/trunk/lib/Format/Format.cpp @@ -379,6 +379,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", @@ -619,6 +620,7 @@ LLVMStyle.DisableFormat = false; LLVMStyle.SortIncludes = true; + LLVMStyle.SortUsingDeclarations = true; return LLVMStyle; } @@ -773,6 +775,7 @@ FormatStyle NoStyle = getLLVMStyle(); NoStyle.DisableFormat = true; NoStyle.SortIncludes = false; + NoStyle.SortUsingDeclarations = false; return NoStyle; } @@ -1879,38 +1882,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(); - }; + 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.Language == FormatStyle::LK_Cpp && - Style.FixNamespaceComments) { - NamespaceEndCommentsFixer CommentsFixer(*Env, Expanded); - return reformatAfterApplying(CommentsFixer); + 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: cfe/trunk/unittests/Format/FormatTest.cpp =================================================================== --- cfe/trunk/unittests/Format/FormatTest.cpp +++ cfe/trunk/unittests/Format/FormatTest.cpp @@ -9333,6 +9333,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); @@ -10874,6 +10875,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;