[clang-format] Sort using-declarations case sensitively with a special case for '_'
authorKrasimir Georgiev <krasimir@google.com>
Fri, 3 Nov 2017 14:38:07 +0000 (14:38 +0000)
committerKrasimir Georgiev <krasimir@google.com>
Fri, 3 Nov 2017 14:38:07 +0000 (14:38 +0000)
Summary:
This makes clang-format sort using declarations case-sensitive with the
exception that '_' comes just before 'A'. This is better than the current case
insensitive version, because it groups uppercase names in the same namespace
together.

Reviewers: bkramer

Reviewed By: bkramer

Subscribers: cfe-commits, klimek

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

llvm-svn: 317325

clang/lib/Format/UsingDeclarationsSorter.cpp
clang/unittests/Format/UsingDeclarationsSorterTest.cpp

index d6753b5..e9c535d 100644 (file)
@@ -33,8 +33,27 @@ struct UsingDeclaration {
   UsingDeclaration(const AnnotatedLine *Line, const std::string &Label)
       : Line(Line), Label(Label) {}
 
+  // Compares lexicographically with the exception that '_' is just before 'A'.
   bool operator<(const UsingDeclaration &Other) const {
-    return StringRef(Label).compare_lower(Other.Label) < 0;
+    size_t Size = Label.size();
+    size_t OtherSize = Other.Label.size();
+    for (size_t I = 0, E = std::min(Size, OtherSize); I < E; ++I) {
+      char Rank = rank(Label[I]);
+      char OtherRank = rank(Other.Label[I]);
+      if (Rank != OtherRank)
+        return Rank < OtherRank;
+    }
+    return Size < OtherSize;
+  }
+
+  // Returns the position of c in a lexicographic ordering with the exception
+  // that '_' is just before 'A'.
+  static char rank(char c) {
+    if (c == '_')
+      return 'A';
+    if ('A' <= c && c < '_')
+      return c + 1;
+    return c;
   }
 };
 
@@ -77,7 +96,7 @@ void endUsingDeclarationBlock(
     SmallVectorImpl<UsingDeclaration> *UsingDeclarations,
     const SourceManager &SourceMgr, tooling::Replacements *Fixes) {
   bool BlockAffected = false;
-  for (const UsingDeclarationDeclaration : *UsingDeclarations) {
+  for (const UsingDeclaration &Declaration : *UsingDeclarations) {
     if (Declaration.Line->Affected) {
       BlockAffected = true;
       break;
index caa2f43..6ce96ed 100644 (file)
@@ -86,19 +86,25 @@ TEST_F(UsingDeclarationsSorterTest, SwapsTwoConsecutiveUsingDeclarations) {
                                   "using a, b;"));
 }
 
-TEST_F(UsingDeclarationsSorterTest, SortsCaseInsensitively) {
+TEST_F(UsingDeclarationsSorterTest, SortsCaseSensitively) {
   EXPECT_EQ("using A;\n"
             "using a;",
             sortUsingDeclarations("using A;\n"
                                   "using a;"));
-  EXPECT_EQ("using a;\n"
-            "using A;",
+  EXPECT_EQ("using A;\n"
+            "using a;",
             sortUsingDeclarations("using a;\n"
                                   "using A;"));
-  EXPECT_EQ("using a;\n"
-            "using B;",
+  EXPECT_EQ("using B;\n"
+            "using a;",
             sortUsingDeclarations("using B;\n"
                                   "using a;"));
+
+  // Sorts '_' right before 'A'.
+  EXPECT_EQ("using _;\n"
+            "using A;",
+            sortUsingDeclarations("using A;\n"
+                                  "using _;"));
   EXPECT_EQ("using _;\n"
             "using a;",
             sortUsingDeclarations("using a;\n"
@@ -110,8 +116,8 @@ TEST_F(UsingDeclarationsSorterTest, SortsCaseInsensitively) {
 
   EXPECT_EQ("using ::testing::_;\n"
             "using ::testing::Aardvark;\n"
-            "using ::testing::apple::Honeycrisp;\n"
             "using ::testing::Xylophone;\n"
+            "using ::testing::apple::Honeycrisp;\n"
             "using ::testing::zebra::Stripes;",
             sortUsingDeclarations("using ::testing::Aardvark;\n"
                                   "using ::testing::Xylophone;\n"
@@ -120,43 +126,6 @@ TEST_F(UsingDeclarationsSorterTest, SortsCaseInsensitively) {
                                   "using ::testing::zebra::Stripes;"));
 }
 
-TEST_F(UsingDeclarationsSorterTest, SortsStably) {
-  EXPECT_EQ("using a;\n"
-            "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;\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;"));
-}
-
 TEST_F(UsingDeclarationsSorterTest, SortsMultipleTopLevelDeclarations) {
   EXPECT_EQ("using a;\n"
             "using b;\n"