[clang] 58751f9 - [clang-format] SortUsingDeclarations support lexicographic order

via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 20 05:46:40 PST 2023


Author: Backl1ght
Date: 2023-01-20T21:34:57+08:00
New Revision: 58751f943f2f6dd78dd3363fc70ea1728044ee0b

URL: https://github.com/llvm/llvm-project/commit/58751f943f2f6dd78dd3363fc70ea1728044ee0b
DIFF: https://github.com/llvm/llvm-project/commit/58751f943f2f6dd78dd3363fc70ea1728044ee0b.diff

LOG: [clang-format] SortUsingDeclarations support lexicographic order

fix https://github.com/llvm/llvm-project/issues/59930

Differential Revision: https://reviews.llvm.org/D141694

Added: 
    

Modified: 
    clang/docs/ClangFormatStyleOptions.rst
    clang/include/clang/Format/Format.h
    clang/lib/Format/Format.cpp
    clang/lib/Format/UsingDeclarationsSorter.cpp
    clang/unittests/Format/ConfigParseTest.cpp
    clang/unittests/Format/UsingDeclarationsSorterTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 5acaf752826bf..da5af2645f18e 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4505,22 +4505,54 @@ the configuration (without a prefix: ``Auto``).
 
 .. _SortUsingDeclarations:
 
-**SortUsingDeclarations** (``Boolean``) :versionbadge:`clang-format 5` :ref:`¶ <SortUsingDeclarations>`
-  If ``true``, clang-format will sort using declarations.
+**SortUsingDeclarations** (``SortUsingDeclarationsOptions``) :versionbadge:`clang-format 5` :ref:`¶ <SortUsingDeclarations>`
+  Controls if and how clang-format will sort using declarations.
 
-  The order of using declarations is defined as follows:
-  Split the strings by "::" and discard any initial empty strings. The last
-  element of each list is a non-namespace name; all others are namespace
-  names. Sort the lists of names lexicographically, where the sort order of
-  individual names is that all non-namespace names come before all namespace
-  names, and within those groups, names are in case-insensitive
-  lexicographic order.
+  Possible values:
+
+  * ``SUD_Never`` (in configuration: ``Never``)
+    Using declarations are never sorted.
+
+    .. code-block:: c++
+
+       using std::chrono::duration_cast;
+       using std::move;
+       using boost::regex;
+       using boost::regex_constants::icase;
+       using std::string;
+
+  * ``SUD_Lexicographic`` (in configuration: ``Lexicographic``)
+    Using declarations are sorted in the order defined as follows:
+    Split the strings by "::" and discard any initial empty strings. Sort
+    the lists of names lexicographically, and within those groups, names are
+    in case-insensitive lexicographic order.
+
+    .. code-block:: c++
+
+       using boost::regex;
+       using boost::regex_constants::icase;
+       using std::chrono::duration_cast;
+       using std::move;
+       using std::string;
+
+  * ``SUD_LexicographicNumeric`` (in configuration: ``LexicographicNumeric``)
+    Using declarations are sorted in the order defined as follows:
+    Split the strings by "::" and discard any initial empty strings. The
+    last element of each list is a non-namespace name; all others are
+    namespace names. Sort the lists of names lexicographically, where the
+    sort order of individual names is that all non-namespace names come
+    before all namespace names, and within those groups, names are in
+    case-insensitive lexicographic order.
+
+    .. code-block:: c++
+
+       using boost::regex;
+       using boost::regex_constants::icase;
+       using std::move;
+       using std::string;
+       using std::chrono::duration_cast;
 
-  .. code-block:: c++
 
-     false:                                 true:
-     using std::cout;               vs.     using std::cin;
-     using std::cin;                        using std::cout;
 
 .. _SpaceAfterCStyleCast:
 

diff  --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 02d48de59f596..72efd3be1cc72 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -3510,22 +3510,49 @@ struct FormatStyle {
   /// \version 12
   SortJavaStaticImportOptions SortJavaStaticImport;
 
-  /// If ``true``, clang-format will sort using declarations.
-  ///
-  /// The order of using declarations is defined as follows:
-  /// Split the strings by "::" and discard any initial empty strings. The last
-  /// element of each list is a non-namespace name; all others are namespace
-  /// names. Sort the lists of names lexicographically, where the sort order of
-  /// individual names is that all non-namespace names come before all namespace
-  /// names, and within those groups, names are in case-insensitive
-  /// lexicographic order.
-  /// \code
-  ///    false:                                 true:
-  ///    using std::cout;               vs.     using std::cin;
-  ///    using std::cin;                        using std::cout;
-  /// \endcode
+  /// Using declaration sorting options.
+  enum SortUsingDeclarationsOptions : int8_t {
+    /// Using declarations are never sorted.
+    /// \code
+    ///    using std::chrono::duration_cast;
+    ///    using std::move;
+    ///    using boost::regex;
+    ///    using boost::regex_constants::icase;
+    ///    using std::string;
+    /// \endcode
+    SUD_Never,
+    /// Using declarations are sorted in the order defined as follows:
+    /// Split the strings by "::" and discard any initial empty strings. Sort
+    /// the lists of names lexicographically, and within those groups, names are
+    /// in case-insensitive lexicographic order.
+    /// \code
+    ///    using boost::regex;
+    ///    using boost::regex_constants::icase;
+    ///    using std::chrono::duration_cast;
+    ///    using std::move;
+    ///    using std::string;
+    /// \endcode
+    SUD_Lexicographic,
+    /// Using declarations are sorted in the order defined as follows:
+    /// Split the strings by "::" and discard any initial empty strings. The
+    /// last element of each list is a non-namespace name; all others are
+    /// namespace names. Sort the lists of names lexicographically, where the
+    /// sort order of individual names is that all non-namespace names come
+    /// before all namespace names, and within those groups, names are in
+    /// case-insensitive lexicographic order.
+    /// \code
+    ///    using boost::regex;
+    ///    using boost::regex_constants::icase;
+    ///    using std::move;
+    ///    using std::string;
+    ///    using std::chrono::duration_cast;
+    /// \endcode
+    SUD_LexicographicNumeric,
+  };
+
+  /// Controls if and how clang-format will sort using declarations.
   /// \version 5
-  bool SortUsingDeclarations;
+  SortUsingDeclarationsOptions SortUsingDeclarations;
 
   /// If ``true``, a space is inserted after C style casts.
   /// \code

diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 2e8f1301682bd..f37c3f9836350 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -606,6 +606,21 @@ struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
   }
 };
 
+template <>
+struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> {
+  static void enumeration(IO &IO,
+                          FormatStyle::SortUsingDeclarationsOptions &Value) {
+    IO.enumCase(Value, "Never", FormatStyle::SUD_Never);
+    IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic);
+    IO.enumCase(Value, "LexicographicNumeric",
+                FormatStyle::SUD_LexicographicNumeric);
+
+    // For backward compatibility.
+    IO.enumCase(Value, "false", FormatStyle::SUD_Never);
+    IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric);
+  }
+};
+
 template <>
 struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
   static void
@@ -1404,7 +1419,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
-  LLVMStyle.SortUsingDeclarations = true;
+  LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
   LLVMStyle.SpaceAfterCStyleCast = false;
   LLVMStyle.SpaceAfterLogicalNot = false;
   LLVMStyle.SpaceAfterTemplateKeyword = true;
@@ -1772,7 +1787,7 @@ FormatStyle getNoStyle() {
   FormatStyle NoStyle = getLLVMStyle();
   NoStyle.DisableFormat = true;
   NoStyle.SortIncludes = FormatStyle::SI_Never;
-  NoStyle.SortUsingDeclarations = false;
+  NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never;
   return NoStyle;
 }
 
@@ -3480,7 +3495,7 @@ reformat(const FormatStyle &Style, StringRef Code,
       });
     }
 
-    if (Style.SortUsingDeclarations) {
+    if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) {
       Passes.emplace_back([&](const Environment &Env) {
         return UsingDeclarationsSorter(Env, Expanded).process();
       });

diff  --git a/clang/lib/Format/UsingDeclarationsSorter.cpp b/clang/lib/Format/UsingDeclarationsSorter.cpp
index bf5307260c0b0..2f4b1e0e46270 100644
--- a/clang/lib/Format/UsingDeclarationsSorter.cpp
+++ b/clang/lib/Format/UsingDeclarationsSorter.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "UsingDeclarationsSorter.h"
+#include "clang/Format/Format.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Regex.h"
 
@@ -32,7 +33,7 @@ namespace {
 // individual names is that all non-namespace names come before all namespace
 // names, and within those groups, names are in case-insensitive lexicographic
 // order.
-int compareLabels(StringRef A, StringRef B) {
+int compareLabelsLexicographicNumeric(StringRef A, StringRef B) {
   SmallVector<StringRef, 2> NamesA;
   A.split(NamesA, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
   SmallVector<StringRef, 2> NamesB;
@@ -64,16 +65,38 @@ int compareLabels(StringRef A, StringRef B) {
   return 0;
 }
 
+int compareLabelsLexicographic(StringRef A, StringRef B) {
+  SmallVector<StringRef, 2> NamesA;
+  A.split(NamesA, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+  SmallVector<StringRef, 2> NamesB;
+  B.split(NamesB, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+  size_t SizeA = NamesA.size();
+  size_t SizeB = NamesB.size();
+  for (size_t I = 0, E = std::min(SizeA, SizeB); I < E; ++I) {
+    // Two namespaces names within a group compare case-insensitively.
+    int C = NamesA[I].compare_insensitive(NamesB[I]);
+    if (C != 0)
+      return C;
+  }
+  if (SizeA < SizeB)
+    return -1;
+  return SizeA == SizeB ? 0 : 1;
+}
+
+int compareLabels(
+    StringRef A, StringRef B,
+    FormatStyle::SortUsingDeclarationsOptions SortUsingDeclarations) {
+  if (SortUsingDeclarations == FormatStyle::SUD_LexicographicNumeric)
+    return compareLabelsLexicographicNumeric(A, B);
+  return compareLabelsLexicographic(A, B);
+}
+
 struct UsingDeclaration {
   const AnnotatedLine *Line;
   std::string Label;
 
   UsingDeclaration(const AnnotatedLine *Line, const std::string &Label)
       : Line(Line), Label(Label) {}
-
-  bool operator<(const UsingDeclaration &Other) const {
-    return compareLabels(Label, Other.Label) < 0;
-  }
 };
 
 /// Computes the label of a using declaration starting at tthe using token
@@ -113,7 +136,8 @@ std::string computeUsingDeclarationLabel(const FormatToken *UsingTok) {
 
 void endUsingDeclarationBlock(
     SmallVectorImpl<UsingDeclaration> *UsingDeclarations,
-    const SourceManager &SourceMgr, tooling::Replacements *Fixes) {
+    const SourceManager &SourceMgr, tooling::Replacements *Fixes,
+    FormatStyle::SortUsingDeclarationsOptions SortUsingDeclarations) {
   bool BlockAffected = false;
   for (const UsingDeclaration &Declaration : *UsingDeclarations) {
     if (Declaration.Line->Affected) {
@@ -127,7 +151,11 @@ void endUsingDeclarationBlock(
   }
   SmallVector<UsingDeclaration, 4> SortedUsingDeclarations(
       UsingDeclarations->begin(), UsingDeclarations->end());
-  llvm::stable_sort(SortedUsingDeclarations);
+  auto Comp = [SortUsingDeclarations](const UsingDeclaration &Lhs,
+                                      const UsingDeclaration &Rhs) -> bool {
+    return compareLabels(Lhs.Label, Rhs.Label, SortUsingDeclarations) < 0;
+  };
+  llvm::stable_sort(SortedUsingDeclarations, Comp);
   SortedUsingDeclarations.erase(
       std::unique(SortedUsingDeclarations.begin(),
                   SortedUsingDeclarations.end(),
@@ -192,21 +220,26 @@ std::pair<tooling::Replacements, unsigned> UsingDeclarationsSorter::analyze(
     const auto *FirstTok = Line->First;
     if (Line->InPPDirective || !Line->startsWith(tok::kw_using) ||
         FirstTok->Finalized) {
-      endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
+      endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
+                               Style.SortUsingDeclarations);
       continue;
     }
-    if (FirstTok->NewlinesBefore > 1)
-      endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
+    if (FirstTok->NewlinesBefore > 1) {
+      endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
+                               Style.SortUsingDeclarations);
+    }
     const auto *UsingTok =
         FirstTok->is(tok::comment) ? FirstTok->getNextNonComment() : FirstTok;
     std::string Label = computeUsingDeclarationLabel(UsingTok);
     if (Label.empty()) {
-      endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
+      endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
+                               Style.SortUsingDeclarations);
       continue;
     }
     UsingDeclarations.push_back(UsingDeclaration(Line, Label));
   }
-  endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
+  endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
+                           Style.SortUsingDeclarations);
   return {Fixes, 0};
 }
 

diff  --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 89ebb6c20c192..f432c2641b244 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -174,7 +174,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
   CHECK_PARSE_BOOL(ReflowComments);
   CHECK_PARSE_BOOL(RemoveBracesLLVM);
   CHECK_PARSE_BOOL(RemoveSemicolon);
-  CHECK_PARSE_BOOL(SortUsingDeclarations);
   CHECK_PARSE_BOOL(SpacesInParentheses);
   CHECK_PARSE_BOOL(SpacesInSquareBrackets);
   CHECK_PARSE_BOOL(SpacesInConditionalStatement);
@@ -714,6 +713,19 @@ TEST(ConfigParseTest, ParsesConfiguration) {
   CHECK_PARSE("SortJavaStaticImport: Before", SortJavaStaticImport,
               FormatStyle::SJSIO_Before);
 
+  Style.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
+  CHECK_PARSE("SortUsingDeclarations: Never", SortUsingDeclarations,
+              FormatStyle::SUD_Never);
+  CHECK_PARSE("SortUsingDeclarations: Lexicographic", SortUsingDeclarations,
+              FormatStyle::SUD_Lexicographic);
+  CHECK_PARSE("SortUsingDeclarations: LexicographicNumeric",
+              SortUsingDeclarations, FormatStyle::SUD_LexicographicNumeric);
+  // For backward compatibility:
+  CHECK_PARSE("SortUsingDeclarations: false", SortUsingDeclarations,
+              FormatStyle::SUD_Never);
+  CHECK_PARSE("SortUsingDeclarations: true", SortUsingDeclarations,
+              FormatStyle::SUD_LexicographicNumeric);
+
   // FIXME: This is required because parsing a configuration simply overwrites
   // the first N elements of the list instead of resetting it.
   Style.ForEachMacros.clear();

diff  --git a/clang/unittests/Format/UsingDeclarationsSorterTest.cpp b/clang/unittests/Format/UsingDeclarationsSorterTest.cpp
index cd5d456b1d737..6bfee7dd16cc0 100644
--- a/clang/unittests/Format/UsingDeclarationsSorterTest.cpp
+++ b/clang/unittests/Format/UsingDeclarationsSorterTest.cpp
@@ -41,88 +41,162 @@ class UsingDeclarationsSorterTest : public ::testing::Test {
 };
 
 TEST_F(UsingDeclarationsSorterTest, SwapsTwoConsecutiveUsingDeclarations) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
   EXPECT_EQ("using a;\n"
             "using b;",
             sortUsingDeclarations("using a;\n"
-                                  "using b;"));
+                                  "using b;",
+                                  Style));
   EXPECT_EQ("using a;\n"
             "using aa;",
             sortUsingDeclarations("using aa;\n"
-                                  "using a;"));
+                                  "using a;",
+                                  Style));
   EXPECT_EQ("using a;\n"
             "using ::a;",
             sortUsingDeclarations("using a;\n"
-                                  "using ::a;"));
+                                  "using ::a;",
+                                  Style));
 
   EXPECT_EQ("using a::bcd;\n"
             "using a::cd;",
             sortUsingDeclarations("using a::cd;\n"
-                                  "using a::bcd;"));
+                                  "using a::bcd;",
+                                  Style));
 
   EXPECT_EQ("using a;\n"
             "using a::a;",
             sortUsingDeclarations("using a::a;\n"
-                                  "using a;"));
+                                  "using a;",
+                                  Style));
 
   EXPECT_EQ("using a::ba::aa;\n"
             "using a::bb::ccc;",
             sortUsingDeclarations("using a::bb::ccc;\n"
-                                  "using a::ba::aa;"));
+                                  "using a::ba::aa;",
+                                  Style));
 
   EXPECT_EQ("using a;\n"
             "using typename a;",
             sortUsingDeclarations("using typename a;\n"
-                                  "using a;"));
+                                  "using a;",
+                                  Style));
 
   EXPECT_EQ("using typename z;\n"
             "using typenamea;",
             sortUsingDeclarations("using typenamea;\n"
-                                  "using typename z;"));
+                                  "using typename z;",
+                                  Style));
 
   EXPECT_EQ("using a, b;\n"
             "using aa;",
             sortUsingDeclarations("using aa;\n"
-                                  "using a, b;"));
+                                  "using a, b;",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ("using a;\n"
+            "using b;",
+            sortUsingDeclarations("using a;\n"
+                                  "using b;",
+                                  Style));
+  EXPECT_EQ("using a;\n"
+            "using aa;",
+            sortUsingDeclarations("using aa;\n"
+                                  "using a;",
+                                  Style));
+  EXPECT_EQ("using a;\n"
+            "using ::a;",
+            sortUsingDeclarations("using a;\n"
+                                  "using ::a;",
+                                  Style));
+
+  EXPECT_EQ("using a::bcd;\n"
+            "using a::cd;",
+            sortUsingDeclarations("using a::cd;\n"
+                                  "using a::bcd;",
+                                  Style));
+
+  EXPECT_EQ("using a;\n"
+            "using a::a;",
+            sortUsingDeclarations("using a::a;\n"
+                                  "using a;",
+                                  Style));
+
+  EXPECT_EQ("using a::ba::aa;\n"
+            "using a::bb::ccc;",
+            sortUsingDeclarations("using a::bb::ccc;\n"
+                                  "using a::ba::aa;",
+                                  Style));
+
+  EXPECT_EQ("using a;\n"
+            "using typename a;",
+            sortUsingDeclarations("using typename a;\n"
+                                  "using a;",
+                                  Style));
+
+  EXPECT_EQ("using typename z;\n"
+            "using typenamea;",
+            sortUsingDeclarations("using typenamea;\n"
+                                  "using typename z;",
+                                  Style));
+
+  EXPECT_EQ("using a, b;\n"
+            "using aa;",
+            sortUsingDeclarations("using aa;\n"
+                                  "using a, b;",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, UsingDeclarationOrder) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
   EXPECT_EQ("using A;\n"
             "using a;",
             sortUsingDeclarations("using A;\n"
-                                  "using a;"));
+                                  "using a;",
+                                  Style));
   EXPECT_EQ("using a;\n"
             "using A;",
             sortUsingDeclarations("using a;\n"
-                                  "using A;"));
+                                  "using A;",
+                                  Style));
   EXPECT_EQ("using a;\n"
             "using B;",
             sortUsingDeclarations("using B;\n"
-                                  "using a;"));
+                                  "using a;",
+                                  Style));
 
   // Ignores leading '::'.
   EXPECT_EQ("using ::a;\n"
             "using A;",
             sortUsingDeclarations("using ::a;\n"
-                                  "using A;"));
+                                  "using A;",
+                                  Style));
 
   EXPECT_EQ("using ::A;\n"
             "using a;",
             sortUsingDeclarations("using ::A;\n"
-                                  "using a;"));
+                                  "using a;",
+                                  Style));
 
   // Sorts '_' before 'a' and 'A'.
   EXPECT_EQ("using _;\n"
             "using A;",
             sortUsingDeclarations("using A;\n"
-                                  "using _;"));
+                                  "using _;",
+                                  Style));
   EXPECT_EQ("using _;\n"
             "using a;",
             sortUsingDeclarations("using a;\n"
-                                  "using _;"));
+                                  "using _;",
+                                  Style));
   EXPECT_EQ("using a::_;\n"
             "using a::a;",
             sortUsingDeclarations("using a::a;\n"
-                                  "using a::_;"));
+                                  "using a::_;",
+                                  Style));
 
   // Sorts non-namespace names before namespace names at the same level.
   EXPECT_EQ("using ::testing::_;\n"
@@ -136,10 +210,75 @@ TEST_F(UsingDeclarationsSorterTest, UsingDeclarationOrder) {
                                   "using ::testing::kMax;\n"
                                   "using ::testing::_;\n"
                                   "using ::testing::apple::Honeycrisp;\n"
-                                  "using ::testing::zebra::Stripes;"));
+                                  "using ::testing::zebra::Stripes;",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ("using A;\n"
+            "using a;",
+            sortUsingDeclarations("using A;\n"
+                                  "using a;",
+                                  Style));
+  EXPECT_EQ("using a;\n"
+            "using A;",
+            sortUsingDeclarations("using a;\n"
+                                  "using A;",
+                                  Style));
+  EXPECT_EQ("using a;\n"
+            "using B;",
+            sortUsingDeclarations("using B;\n"
+                                  "using a;",
+                                  Style));
+
+  // Ignores leading '::'.
+  EXPECT_EQ("using ::a;\n"
+            "using A;",
+            sortUsingDeclarations("using ::a;\n"
+                                  "using A;",
+                                  Style));
+
+  EXPECT_EQ("using ::A;\n"
+            "using a;",
+            sortUsingDeclarations("using ::A;\n"
+                                  "using a;",
+                                  Style));
+
+  // Sorts '_' before 'a' and 'A'.
+  EXPECT_EQ("using _;\n"
+            "using A;",
+            sortUsingDeclarations("using A;\n"
+                                  "using _;",
+                                  Style));
+  EXPECT_EQ("using _;\n"
+            "using a;",
+            sortUsingDeclarations("using a;\n"
+                                  "using _;",
+                                  Style));
+  EXPECT_EQ("using a::_;\n"
+            "using a::a;",
+            sortUsingDeclarations("using a::a;\n"
+                                  "using a::_;",
+                                  Style));
+
+  // Sorts non-namespace names before namespace names at the same level.
+  EXPECT_EQ("using ::testing::_;\n"
+            "using ::testing::Aardvark;\n"
+            "using ::testing::apple::Honeycrisp;\n"
+            "using ::testing::kMax;\n"
+            "using ::testing::Xylophone;\n"
+            "using ::testing::zebra::Stripes;",
+            sortUsingDeclarations("using ::testing::Aardvark;\n"
+                                  "using ::testing::Xylophone;\n"
+                                  "using ::testing::kMax;\n"
+                                  "using ::testing::_;\n"
+                                  "using ::testing::apple::Honeycrisp;\n"
+                                  "using ::testing::zebra::Stripes;",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, SortsStably) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
   EXPECT_EQ("using a;\n"
             "using A;\n"
             "using a;\n"
@@ -169,10 +308,46 @@ TEST_F(UsingDeclarationsSorterTest, SortsStably) {
                                   "using B;\n"
                                   "using b;\n"
                                   "using A;\n"
-                                  "using a;"));
+                                  "using a;",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ("using a;\n"
+            "using A;\n"
+            "using a;\n"
+            "using A;\n"
+            "using a;\n"
+            "using A;\n"
+            "using a;\n"
+            "using B;\n"
+            "using b;\n"
+            "using B;\n"
+            "using b;\n"
+            "using B;\n"
+            "using b;",
+            sortUsingDeclarations("using a;\n"
+                                  "using B;\n"
+                                  "using a;\n"
+                                  "using b;\n"
+                                  "using A;\n"
+                                  "using a;\n"
+                                  "using b;\n"
+                                  "using B;\n"
+                                  "using b;\n"
+                                  "using A;\n"
+                                  "using a;\n"
+                                  "using b;\n"
+                                  "using b;\n"
+                                  "using B;\n"
+                                  "using b;\n"
+                                  "using A;\n"
+                                  "using a;",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, SortsMultipleTopLevelDeclarations) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
   EXPECT_EQ("using a;\n"
             "using b;\n"
             "using c;\n"
@@ -182,7 +357,8 @@ TEST_F(UsingDeclarationsSorterTest, SortsMultipleTopLevelDeclarations) {
                                   "using b;\n"
                                   "using e;\n"
                                   "using a;\n"
-                                  "using c;"));
+                                  "using c;",
+                                  Style));
 
   EXPECT_EQ("#include <iostream>\n"
             "using std::cin;\n"
@@ -193,10 +369,51 @@ TEST_F(UsingDeclarationsSorterTest, SortsMultipleTopLevelDeclarations) {
                                   "using std::cout;\n"
                                   "using ::std::endl;\n"
                                   "using std::cin;\n"
-                                  "int main();"));
+                                  "int main();",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ("using a;\n"
+            "using b;\n"
+            "using c;\n"
+            "using d;\n"
+            "using e;",
+            sortUsingDeclarations("using d;\n"
+                                  "using b;\n"
+                                  "using e;\n"
+                                  "using a;\n"
+                                  "using c;",
+                                  Style));
+
+  EXPECT_EQ("#include <iostream>\n"
+            "using std::cin;\n"
+            "using std::cout;\n"
+            "using ::std::endl;\n"
+            "int main();",
+            sortUsingDeclarations("#include <iostream>\n"
+                                  "using std::cout;\n"
+                                  "using ::std::endl;\n"
+                                  "using std::cin;\n"
+                                  "int main();",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, BreaksOnEmptyLines) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
+  EXPECT_EQ("using b;\n"
+            "using c;\n"
+            "\n"
+            "using a;\n"
+            "using d;",
+            sortUsingDeclarations("using c;\n"
+                                  "using b;\n"
+                                  "\n"
+                                  "using d;\n"
+                                  "using a;",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
   EXPECT_EQ("using b;\n"
             "using c;\n"
             "\n"
@@ -206,35 +423,68 @@ TEST_F(UsingDeclarationsSorterTest, BreaksOnEmptyLines) {
                                   "using b;\n"
                                   "\n"
                                   "using d;\n"
-                                  "using a;"));
+                                  "using a;",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, BreaksOnUsingNamespace) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
+  EXPECT_EQ("using b;\n"
+            "using namespace std;\n"
+            "using a;",
+            sortUsingDeclarations("using b;\n"
+                                  "using namespace std;\n"
+                                  "using a;",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
   EXPECT_EQ("using b;\n"
             "using namespace std;\n"
             "using a;",
             sortUsingDeclarations("using b;\n"
                                   "using namespace std;\n"
-                                  "using a;"));
+                                  "using a;",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, KeepsUsingDeclarationsInPPDirectives) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
   EXPECT_EQ("#define A \\\n"
             "using b;\\\n"
             "using a;",
             sortUsingDeclarations("#define A \\\n"
                                   "using b;\\\n"
-                                  "using a;"));
+                                  "using a;",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ("#define A \\\n"
+            "using b;\\\n"
+            "using a;",
+            sortUsingDeclarations("#define A \\\n"
+                                  "using b;\\\n"
+                                  "using a;",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, KeepsTypeAliases) {
   auto Code = "struct C { struct B { struct A; }; };\n"
               "using B = C::B;\n"
               "using A = B::A;";
-  EXPECT_EQ(Code, sortUsingDeclarations(Code));
+
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
+  EXPECT_EQ(Code, sortUsingDeclarations(Code, Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ(Code, sortUsingDeclarations(Code, Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, MovesTrailingCommentsWithDeclarations) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
   EXPECT_EQ("using a; // line a1\n"
             "using b; /* line b1\n"
             "          * line b2\n"
@@ -246,10 +496,41 @@ TEST_F(UsingDeclarationsSorterTest, MovesTrailingCommentsWithDeclarations) {
                                   "using b; /* line b1\n"
                                   "          * line b2\n"
                                   "          * line b3 */\n"
-                                  "using a; // line a1"));
+                                  "using a; // line a1",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ("using a; // line a1\n"
+            "using b; /* line b1\n"
+            "          * line b2\n"
+            "          * line b3 */\n"
+            "using c; // line c1\n"
+            "         // line c2",
+            sortUsingDeclarations("using c; // line c1\n"
+                                  "         // line c2\n"
+                                  "using b; /* line b1\n"
+                                  "          * line b2\n"
+                                  "          * line b3 */\n"
+                                  "using a; // line a1",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, SortsInStructScope) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
+  EXPECT_EQ("struct pt3 : pt2 {\n"
+            "  using pt2::x;\n"
+            "  using pt2::y;\n"
+            "  float z;\n"
+            "};",
+            sortUsingDeclarations("struct pt3 : pt2 {\n"
+                                  "  using pt2::y;\n"
+                                  "  using pt2::x;\n"
+                                  "  float z;\n"
+                                  "};",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
   EXPECT_EQ("struct pt3 : pt2 {\n"
             "  using pt2::x;\n"
             "  using pt2::y;\n"
@@ -259,19 +540,53 @@ TEST_F(UsingDeclarationsSorterTest, SortsInStructScope) {
                                   "  using pt2::y;\n"
                                   "  using pt2::x;\n"
                                   "  float z;\n"
-                                  "};"));
+                                  "};",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, KeepsOperators) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
   EXPECT_EQ("using a::operator();\n"
             "using a::operator-;\n"
             "using a::operator+;",
             sortUsingDeclarations("using a::operator();\n"
                                   "using a::operator-;\n"
-                                  "using a::operator+;"));
+                                  "using a::operator+;",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ("using a::operator();\n"
+            "using a::operator-;\n"
+            "using a::operator+;",
+            sortUsingDeclarations("using a::operator();\n"
+                                  "using a::operator-;\n"
+                                  "using a::operator+;",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, SortsUsingDeclarationsInsideNamespaces) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
+  EXPECT_EQ("namespace A {\n"
+            "struct B;\n"
+            "struct C;\n"
+            "}\n"
+            "namespace X {\n"
+            "using A::B;\n"
+            "using A::C;\n"
+            "}",
+            sortUsingDeclarations("namespace A {\n"
+                                  "struct B;\n"
+                                  "struct C;\n"
+                                  "}\n"
+                                  "namespace X {\n"
+                                  "using A::C;\n"
+                                  "using A::B;\n"
+                                  "}",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
   EXPECT_EQ("namespace A {\n"
             "struct B;\n"
             "struct C;\n"
@@ -287,10 +602,28 @@ TEST_F(UsingDeclarationsSorterTest, SortsUsingDeclarationsInsideNamespaces) {
                                   "namespace X {\n"
                                   "using A::C;\n"
                                   "using A::B;\n"
-                                  "}"));
+                                  "}",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, SupportsClangFormatOff) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
+  EXPECT_EQ("// clang-format off\n"
+            "using b;\n"
+            "using a;\n"
+            "// clang-format on\n"
+            "using c;\n"
+            "using d;",
+            sortUsingDeclarations("// clang-format off\n"
+                                  "using b;\n"
+                                  "using a;\n"
+                                  "// clang-format on\n"
+                                  "using d;\n"
+                                  "using c;",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
   EXPECT_EQ("// clang-format off\n"
             "using b;\n"
             "using a;\n"
@@ -302,10 +635,13 @@ TEST_F(UsingDeclarationsSorterTest, SupportsClangFormatOff) {
                                   "using a;\n"
                                   "// clang-format on\n"
                                   "using d;\n"
-                                  "using c;"));
+                                  "using c;",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, SortsPartialRangeOfUsingDeclarations) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
   // Sorts the whole block of using declarations surrounding the range.
   EXPECT_EQ("using a;\n"
             "using b;\n"
@@ -313,7 +649,7 @@ TEST_F(UsingDeclarationsSorterTest, SortsPartialRangeOfUsingDeclarations) {
             sortUsingDeclarations("using b;\n"
                                   "using c;\n" // starts at offset 10
                                   "using a;",
-                                  {tooling::Range(10, 15)}));
+                                  {tooling::Range(10, 15)}, Style));
   EXPECT_EQ("using a;\n"
             "using b;\n"
             "using c;\n"
@@ -322,7 +658,7 @@ TEST_F(UsingDeclarationsSorterTest, SortsPartialRangeOfUsingDeclarations) {
                                   "using c;\n" // starts at offset 10
                                   "using a;\n"
                                   "using A = b;",
-                                  {tooling::Range(10, 15)}));
+                                  {tooling::Range(10, 15)}, Style));
 
   EXPECT_EQ("using d;\n"
             "using c;\n"
@@ -340,18 +676,67 @@ TEST_F(UsingDeclarationsSorterTest, SortsPartialRangeOfUsingDeclarations) {
                                   "\n"
                                   "using f;\n"
                                   "using e;",
-                                  {tooling::Range(19, 1)}));
+                                  {tooling::Range(19, 1)}, Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  // Sorts the whole block of using declarations surrounding the range.
+  EXPECT_EQ("using a;\n"
+            "using b;\n"
+            "using c;",
+            sortUsingDeclarations("using b;\n"
+                                  "using c;\n" // starts at offset 10
+                                  "using a;",
+                                  {tooling::Range(10, 15)}, Style));
+  EXPECT_EQ("using a;\n"
+            "using b;\n"
+            "using c;\n"
+            "using A = b;",
+            sortUsingDeclarations("using b;\n"
+                                  "using c;\n" // starts at offset 10
+                                  "using a;\n"
+                                  "using A = b;",
+                                  {tooling::Range(10, 15)}, Style));
+
+  EXPECT_EQ("using d;\n"
+            "using c;\n"
+            "\n"
+            "using a;\n"
+            "using b;\n"
+            "\n"
+            "using f;\n"
+            "using e;",
+            sortUsingDeclarations("using d;\n"
+                                  "using c;\n"
+                                  "\n"
+                                  "using b;\n" // starts at offset 19
+                                  "using a;\n"
+                                  "\n"
+                                  "using f;\n"
+                                  "using e;",
+                                  {tooling::Range(19, 1)}, Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest,
        SortsUsingDeclarationsWithLeadingkComments) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
   EXPECT_EQ("/* comment */ using a;\n"
             "/* comment */ using b;",
             sortUsingDeclarations("/* comment */ using b;\n"
-                                  "/* comment */ using a;"));
+                                  "/* comment */ using a;",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ("/* comment */ using a;\n"
+            "/* comment */ using b;",
+            sortUsingDeclarations("/* comment */ using b;\n"
+                                  "/* comment */ using a;",
+                                  Style));
 }
 
 TEST_F(UsingDeclarationsSorterTest, DeduplicatesUsingDeclarations) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
   EXPECT_EQ("using a;\n"
             "using b;\n"
             "using c;\n"
@@ -366,7 +751,68 @@ TEST_F(UsingDeclarationsSorterTest, DeduplicatesUsingDeclarations) {
                                   "\n"
                                   "using e;\n"
                                   "using a;\n"
-                                  "using e;"));
+                                  "using e;",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ("using a;\n"
+            "using b;\n"
+            "using c;\n"
+            "\n"
+            "using a;\n"
+            "using e;",
+            sortUsingDeclarations("using c;\n"
+                                  "using a;\n"
+                                  "using b;\n"
+                                  "using a;\n"
+                                  "using b;\n"
+                                  "\n"
+                                  "using e;\n"
+                                  "using a;\n"
+                                  "using e;",
+                                  Style));
+}
+
+TEST_F(UsingDeclarationsSorterTest,
+       SortsUsingDeclarationsWithDifferentCountsOfScopes) {
+  FormatStyle Style = getLLVMStyle();
+  EXPECT_EQ(FormatStyle::SUD_LexicographicNumeric, Style.SortUsingDeclarations);
+  EXPECT_EQ("using boost::regex;\n"
+            "using boost::regex_constants::icase;\n"
+            "using std::move;\n"
+            "using std::string;\n"
+            "using std::chrono::duration_cast;\n"
+            "using std::chrono::microseconds;\n"
+            "using std::chrono::seconds;\n"
+            "using std::chrono::steady_clock;\n",
+            sortUsingDeclarations("using boost::regex;\n"
+                                  "using boost::regex_constants::icase;\n"
+                                  "using std::chrono::duration_cast;\n"
+                                  "using std::chrono::microseconds;\n"
+                                  "using std::chrono::seconds;\n"
+                                  "using std::chrono::steady_clock;\n"
+                                  "using std::move;\n"
+                                  "using std::string;\n",
+                                  Style));
+
+  Style.SortUsingDeclarations = FormatStyle::SUD_Lexicographic;
+  EXPECT_EQ("using boost::regex;\n"
+            "using boost::regex_constants::icase;\n"
+            "using std::chrono::duration_cast;\n"
+            "using std::chrono::microseconds;\n"
+            "using std::chrono::seconds;\n"
+            "using std::chrono::steady_clock;\n"
+            "using std::move;\n"
+            "using std::string;\n",
+            sortUsingDeclarations("using boost::regex;\n"
+                                  "using boost::regex_constants::icase;\n"
+                                  "using std::move;\n"
+                                  "using std::string;\n"
+                                  "using std::chrono::duration_cast;\n"
+                                  "using std::chrono::microseconds;\n"
+                                  "using std::chrono::seconds;\n"
+                                  "using std::chrono::steady_clock;\n",
+                                  Style));
 }
 
 } // end namespace


        


More information about the cfe-commits mailing list