sammccall created this revision.

This scale is much easier to mix with other signals, such as fuzzy match 
strength.
Mostly NFC, but it does reorder some low-priority items that get folded 
together at a score of 0 (see completion-qualifiers.test).
Removed the exact sortText from the testcases, because it's the ranking that we 
want to test.


https://reviews.llvm.org/D40089

Files:
  clangd/ClangdUnit.cpp
  test/clangd/authority-less-uri.test
  test/clangd/completion-items-kinds.test
  test/clangd/completion-priorities.test
  test/clangd/completion-qualifiers.test
  test/clangd/completion-snippet.test
  test/clangd/completion.test
  test/clangd/protocol.test

Index: test/clangd/protocol.test
===================================================================
--- test/clangd/protocol.test
+++ test/clangd/protocol.test
@@ -39,7 +39,7 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 7,
 # CHECK-NEXT:        "label": "fake::",
-# CHECK-NEXT:        "sortText": "000075fake"
+# CHECK-NEXT:        "sortText": "{{.*}}"
 #      CHECK:    ]
 # CHECK-NEXT:  }
 
@@ -68,7 +68,7 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 7,
 # CHECK-NEXT:        "label": "fake::",
-# CHECK-NEXT:        "sortText": "000075fake"
+# CHECK-NEXT:        "sortText": "{{.*}}"
 #      CHECK:    ]
 # CHECK-NEXT:  }
 # STDERR: Warning: Duplicate Content-Length header received. The previous value for this message (10) was ignored.
@@ -97,7 +97,7 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 7,
 # CHECK-NEXT:        "label": "fake::",
-# CHECK-NEXT:        "sortText": "000075fake"
+# CHECK-NEXT:        "sortText": "{{.*}}"
 #      CHECK:    ]
 # CHECK-NEXT:  }
 Content-Length: 1024
Index: test/clangd/completion.test
===================================================================
--- test/clangd/completion.test
+++ test/clangd/completion.test
@@ -24,51 +24,51 @@
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 5,
 # CHECK-NEXT:      "label": "a",
-# CHECK-NEXT:      "sortText": "000035a"
+# CHECK-NEXT:      "sortText": "{{.*}}a"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "int",
 # CHECK-NEXT:      "filterText": "bb",
 # CHECK-NEXT:      "insertText": "bb",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 5,
 # CHECK-NEXT:      "label": "bb",
-# CHECK-NEXT:      "sortText": "000035bb"
+# CHECK-NEXT:      "sortText": "{{.*}}bb"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "int",
 # CHECK-NEXT:      "filterText": "ccc",
 # CHECK-NEXT:      "insertText": "ccc",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 5,
 # CHECK-NEXT:      "label": "ccc",
-# CHECK-NEXT:      "sortText": "000035ccc"
+# CHECK-NEXT:      "sortText": "{{.*}}ccc"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "int",
 # CHECK-NEXT:      "filterText": "f",
 # CHECK-NEXT:      "insertText": "f",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 2,
 # CHECK-NEXT:      "label": "f(int i, const float f) const",
-# CHECK-NEXT:      "sortText": "000035f"
+# CHECK-NEXT:      "sortText": "{{.*}}f"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "filterText": "fake",
 # CHECK-NEXT:      "insertText": "fake",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 7,
 # CHECK-NEXT:      "label": "fake::",
-# CHECK-NEXT:      "sortText": "000075fake"
+# CHECK-NEXT:      "sortText": "{{.*}}fake"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "fake &",
 # CHECK-NEXT:      "filterText": "operator=",
 # CHECK-NEXT:      "insertText": "operator=",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 2,
 # CHECK-NEXT:      "label": "operator=(const fake &)",
-# CHECK-NEXT:      "sortText": "000079operator="
+# CHECK-NEXT:      "sortText": "{{.*}}operator="
 # CHECK-NEXT:    },
 # FIXME: Why do some buildbots show an extra operator==(fake&&) here?
 #      CHECK:    {
@@ -78,7 +78,7 @@
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 4,
 # CHECK-NEXT:      "label": "~fake()",
-# CHECK-NEXT:      "sortText": "000079~fake"
+# CHECK-NEXT:      "sortText": "{{.*}}~fake"
 # CHECK-NEXT:    }
 # CHECK-NEXT:  ]
 Content-Length: 148
@@ -96,60 +96,60 @@
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 5,
 # CHECK-NEXT:      "label": "a",
-# CHECK-NEXT:      "sortText": "000035a"
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "int",
 # CHECK-NEXT:      "filterText": "bb",
 # CHECK-NEXT:      "insertText": "bb",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 5,
 # CHECK-NEXT:      "label": "bb",
-# CHECK-NEXT:      "sortText": "000035bb"
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "int",
 # CHECK-NEXT:      "filterText": "ccc",
 # CHECK-NEXT:      "insertText": "ccc",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 5,
 # CHECK-NEXT:      "label": "ccc",
-# CHECK-NEXT:      "sortText": "000035ccc"
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "int",
 # CHECK-NEXT:      "filterText": "f",
 # CHECK-NEXT:      "insertText": "f",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 2,
 # CHECK-NEXT:      "label": "f(int i, const float f) const",
-# CHECK-NEXT:      "sortText": "000035f"
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "filterText": "fake",
 # CHECK-NEXT:      "insertText": "fake",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 7,
 # CHECK-NEXT:      "label": "fake::",
-# CHECK-NEXT:      "sortText": "000075fake"
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "fake &",
 # CHECK-NEXT:      "filterText": "operator=",
 # CHECK-NEXT:      "insertText": "operator=",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 2,
 # CHECK-NEXT:      "label": "operator=(const fake &)",
-# CHECK-NEXT:      "sortText": "000079operator="
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    },
 #      CHECK:    {
 #      CHECK:      "detail": "void",
 # CHECK-NEXT:      "filterText": "~fake",
 # CHECK-NEXT:      "insertText": "~fake",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 4,
 # CHECK-NEXT:      "label": "~fake()",
-# CHECK-NEXT:      "sortText": "000079~fake"
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    }
 # CHECK-NEXT:  ]
 # Update the source file and check for completions again.
@@ -172,33 +172,33 @@
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 2,
 # CHECK-NEXT:      "label": "func()",
-# CHECK-NEXT:      "sortText": "000034func"
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "filterText": "fancy",
 # CHECK-NEXT:      "insertText": "fancy",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 7,
 # CHECK-NEXT:      "label": "fancy::",
-# CHECK-NEXT:      "sortText": "000075fancy"
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    },
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "fancy &",
 # CHECK-NEXT:      "filterText": "operator=",
 # CHECK-NEXT:      "insertText": "operator=",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 2,
 # CHECK-NEXT:      "label": "operator=(const fancy &)",
-# CHECK-NEXT:      "sortText": "000079operator="
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    },
 #      CHECK:    {
 #      CHECK:      "detail": "void",
 # CHECK-NEXT:      "filterText": "~fancy",
 # CHECK-NEXT:      "insertText": "~fancy",
 # CHECK-NEXT:      "insertTextFormat": 1,
 # CHECK-NEXT:      "kind": 4,
 # CHECK-NEXT:      "label": "~fancy()",
-# CHECK-NEXT:      "sortText": "000079~fancy"
+# CHECK-NEXT:      "sortText": "{{.*}}"
 # CHECK-NEXT:    }
 # CHECK-NEXT:  ]
 Content-Length: 44
Index: test/clangd/completion-snippet.test
===================================================================
--- test/clangd/completion-snippet.test
+++ test/clangd/completion-snippet.test
@@ -24,51 +24,51 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 5,
 # CHECK-NEXT:        "label": "a",
-# CHECK-NEXT:        "sortText": "000035a"
+# CHECK-NEXT:        "sortText": "{{.*}}a"
 # CHECK-NEXT:      },
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "detail": "int",
 # CHECK-NEXT:        "filterText": "bb",
 # CHECK-NEXT:        "insertText": "bb",
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 5,
 # CHECK-NEXT:        "label": "bb",
-# CHECK-NEXT:        "sortText": "000035bb"
+# CHECK-NEXT:        "sortText": "{{.*}}bb"
 # CHECK-NEXT:      },
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "detail": "int",
 # CHECK-NEXT:        "filterText": "ccc",
 # CHECK-NEXT:        "insertText": "ccc",
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 5,
 # CHECK-NEXT:        "label": "ccc",
-# CHECK-NEXT:        "sortText": "000035ccc"
+# CHECK-NEXT:        "sortText": "{{.*}}ccc"
 # CHECK-NEXT:      },
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "detail": "int",
 # CHECK-NEXT:        "filterText": "f",
 # CHECK-NEXT:        "insertText": "f(${1:int i}, ${2:const float f})",
 # CHECK-NEXT:        "insertTextFormat": 2,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "f(int i, const float f) const",
-# CHECK-NEXT:        "sortText": "000035f"
+# CHECK-NEXT:        "sortText": "{{.*}}f"
 # CHECK-NEXT:      },
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "filterText": "fake",
 # CHECK-NEXT:        "insertText": "fake::",
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 7,
 # CHECK-NEXT:        "label": "fake::",
-# CHECK-NEXT:        "sortText": "000075fake"
+# CHECK-NEXT:        "sortText": "{{.*}}fake"
 # CHECK-NEXT:      },
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "detail": "fake &",
 # CHECK-NEXT:        "filterText": "operator=",
 # CHECK-NEXT:        "insertText": "operator=(${1:const fake &})",
 # CHECK-NEXT:        "insertTextFormat": 2,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "operator=(const fake &)",
-# CHECK-NEXT:        "sortText": "000079operator="
+# CHECK-NEXT:        "sortText": "{{.*}}operator="
 # CHECK-NEXT:      },
 # FIXME: Why do some buildbots show an extra operator==(fake&&) here?
 #      CHECK:      {
@@ -78,7 +78,7 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 4,
 # CHECK-NEXT:        "label": "~fake()",
-# CHECK-NEXT:        "sortText": "000079~fake"
+# CHECK-NEXT:        "sortText": "{{.*}}~fake"
 # CHECK-NEXT:      }
 # CHECK-NEXT:    ]
 # CHECK-NEXT:  }
@@ -102,7 +102,7 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "func()",
-# CHECK-NEXT:        "sortText": "000034func"
+# CHECK-NEXT:        "sortText": "{{.*}}func"
 # CHECK-NEXT:      },
 Content-Length: 44
 
Index: test/clangd/completion-qualifiers.test
===================================================================
--- test/clangd/completion-qualifiers.test
+++ test/clangd/completion-qualifiers.test
@@ -21,29 +21,27 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "bar() const",
-# CHECK-NEXT:        "sortText": "000037bar"
+# CHECK-NEXT:        "sortText": "{{.*}}bar"
 # CHECK-NEXT:      },
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "detail": "int",
 # CHECK-NEXT:        "filterText": "foo",
 # CHECK-NEXT:        "insertText": "foo",
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "Foo::foo() const",
-# CHECK-NEXT:        "sortText": "000037foo"
+# CHECK-NEXT:        "sortText": "{{.*}}foo"
 # CHECK-NEXT:      },
-# Ineligible non-const function is at the bottom of the list.
+# Ineligible non-const function is near the bottom of the list.
 # CHECK-NEXT:      {
 #      CHECK:        "detail": "int",
 #      CHECK:        "filterText": "foo",
 # CHECK-NEXT:        "insertText": "foo",
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "foo() const",
-# CHECK-NEXT:        "sortText": "200035foo"
+# CHECK-NEXT:        "sortText": "{{.*}}foo"
 # CHECK-NEXT:      }
-# CHECK-NEXT:    ]
-# CHECK-NEXT:  }
 Content-Length: 44
 
 {"jsonrpc":"2.0","id":4,"method":"shutdown"}
Index: test/clangd/completion-priorities.test
===================================================================
--- test/clangd/completion-priorities.test
+++ test/clangd/completion-priorities.test
@@ -25,25 +25,25 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "priv()",
-# CHECK-NEXT:        "sortText": "000034priv"
+# CHECK-NEXT:        "sortText": "{{.*}}priv"
 # CHECK-NEXT:      },
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "detail": "void",
 # CHECK-NEXT:        "filterText": "prot",
 # CHECK-NEXT:        "insertText": "prot",
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "prot()",
-# CHECK-NEXT:        "sortText": "000034prot"
+# CHECK-NEXT:        "sortText": "{{.*}}prot"
 # CHECK-NEXT:      },
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "detail": "void",
 # CHECK-NEXT:        "filterText": "pub",
 # CHECK-NEXT:        "insertText": "pub",
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "pub()",
-# CHECK-NEXT:        "sortText": "000034pub"
+# CHECK-NEXT:        "sortText": "{{.*}}pub"
 # CHECK-NEXT:      },
 Content-Length: 151
 
@@ -60,7 +60,7 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "pub()",
-# CHECK-NEXT:        "sortText": "000034pub"
+# CHECK-NEXT:        "sortText": "{{.*}}pub"
 # CHECK-NEXT:      },
 # priv() and prot() are at the end of the list
 # CHECK-NEXT:      {
@@ -70,16 +70,16 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "priv()",
-# CHECK-NEXT:        "sortText": "200034priv"
+# CHECK-NEXT:        "sortText": "{{.*}}priv"
 # CHECK-NEXT:      },
 # CHECK-NEXT:      {
 # CHECK-NEXT:        "detail": "void",
 # CHECK-NEXT:        "filterText": "prot",
 # CHECK-NEXT:        "insertText": "prot",
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 2,
 # CHECK-NEXT:        "label": "prot()",
-# CHECK-NEXT:        "sortText": "200034prot"
+# CHECK-NEXT:        "sortText": "{{.*}}prot"
 # CHECK-NEXT:      }
 # CHECK-NEXT:    ]
 # CHECK-NEXT:  }
Index: test/clangd/completion-items-kinds.test
===================================================================
--- test/clangd/completion-items-kinds.test
+++ test/clangd/completion-items-kinds.test
@@ -13,23 +13,23 @@
 Content-Length: 58
 # CHECK: {"id":1,"jsonrpc":"2.0","result":{"isIncomplete":false,"items":
 #
-# Keyword
-# CHECK-DAG: {"filterText":"int","insertText":"int","insertTextFormat":1,"kind":14,"label":"int","sortText":"000050int"}
+# Function
+# CHECK: {"detail":"int","filterText":"function","insertText":"function()","insertTextFormat":1,"kind":3,"label":"function()","sortText":"{{.*}}function"}
+#
+# Variable
+# CHECK: {"detail":"int","filterText":"variable","insertText":"variable","insertTextFormat":1,"kind":6,"label":"variable","sortText":"{{.*}}variable"}
 #
 # Code pattern
-# CHECK-DAG: {"filterText":"static_cast","insertText":"static_cast<${1:type}>(${2:expression})","insertTextFormat":2,"kind":15,"label":"static_cast<type>(expression)","sortText":"000040static_cast"}
+# CHECK: {"filterText":"static_cast","insertText":"static_cast<${1:type}>(${2:expression})","insertTextFormat":2,"kind":15,"label":"static_cast<type>(expression)","sortText":"{{.*}}static_cast"}
+#
+# Keyword
+# CHECK: {"filterText":"int","insertText":"int","insertTextFormat":1,"kind":14,"label":"int","sortText":"{{.*}}int"}
 #
 # Struct
-# CHECK-DAG: {"filterText":"Struct","insertText":"Struct","insertTextFormat":1,"kind":7,"label":"Struct","sortText":"000050Struct"}
+# CHECK: {"filterText":"Struct","insertText":"Struct","insertTextFormat":1,"kind":7,"label":"Struct","sortText":"{{.*}}Struct"}
 #
 # Macro
-# CHECK-DAG: {"filterText":"MACRO","insertText":"MACRO","insertTextFormat":1,"kind":1,"label":"MACRO","sortText":"000070MACRO"}
-#
-# Variable
-# CHECK-DAG: {"detail":"int","filterText":"variable","insertText":"variable","insertTextFormat":1,"kind":6,"label":"variable","sortText":"000012variable"}
-#
-# Function
-# CHECK-DAG: {"detail":"int","filterText":"function","insertText":"function()","insertTextFormat":1,"kind":3,"label":"function()","sortText":"000012function"}
+# CHECK: {"filterText":"MACRO","insertText":"MACRO","insertTextFormat":1,"kind":1,"label":"MACRO","sortText":"{{.*}}MACRO"}
 #
 # CHECK-SAME: ]}}
 
Index: test/clangd/authority-less-uri.test
===================================================================
--- test/clangd/authority-less-uri.test
+++ test/clangd/authority-less-uri.test
@@ -25,7 +25,7 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 7,
 # CHECK-NEXT:        "label": "fake::",
-# CHECK-NEXT:        "sortText": "000075fake"
+# CHECK-NEXT:        "sortText": "{{.*}}fake"
 #      CHECK:    ]
 # CHECK-NEXT:  }
 Content-Length: 172
@@ -43,7 +43,7 @@
 # CHECK-NEXT:        "insertTextFormat": 1,
 # CHECK-NEXT:        "kind": 7,
 # CHECK-NEXT:        "label": "fake::",
-# CHECK-NEXT:        "sortText": "000075fake"
+# CHECK-NEXT:        "sortText": "{{.*}}fake"
 #      CHECK:    ]
 # CHECK-NEXT:  }
 Content-Length: 44
Index: clangd/ClangdUnit.cpp
===================================================================
--- clangd/ClangdUnit.cpp
+++ clangd/ClangdUnit.cpp
@@ -375,50 +375,55 @@
       : Result(&Result), Score(score(Result)) {}
 
   CodeCompletionResult *Result;
-  // Higher score is worse. FIXME: use a more natural scale!
-  int Score;
+  float Score; // 0 to 1, higher is better.
 
   // Comparison reflects rank: better candidates are smaller.
   bool operator<(const CompletionCandidate &C) const {
     if (Score != C.Score)
-      return Score < C.Score;
+      return Score > C.Score;
     return *Result < *C.Result;
   }
 
   std::string sortText() const {
-    // Fill in the sortText of the CompletionItem.
-    assert(Score <= 999999 && "Expecting score to have at most 6-digits");
     std::string S, NameStorage;
-    StringRef Name = Result->getOrderedName(NameStorage);
-    llvm::raw_string_ostream(S)
-        << llvm::format("%06d%.*s", Score, Name.size(), Name.data());
-    return S;
+    llvm::raw_string_ostream OS(S);
+    write_hex(OS, 0 - encodeFloat(Score), llvm::HexPrintStyle::Lower,
+              2 * sizeof(Score));
+    OS << Result->getOrderedName(NameStorage);
+    return OS.str();
   }
 
 private:
-  static int score(const CodeCompletionResult &Result) {
-    int Score = Result.Priority;
-    // Fill in the sortText of the CompletionItem.
-    assert(Score <= 99999 && "Expecting code completion result "
-                             "priority to have at most 5-digits");
+  static float score(const CodeCompletionResult &Result) {
+    // Priority 80 is a really bad score.
+    float Score = 1 - std::min<float>(80, Result.Priority) / 80;
 
-    const int Penalty = 100000;
     switch (static_cast<CXAvailabilityKind>(Result.Availability)) {
     case CXAvailability_Available:
       // No penalty.
       break;
     case CXAvailability_Deprecated:
-      Score += Penalty;
+      Score *= 0.1;
       break;
     case CXAvailability_NotAccessible:
-      Score += 2 * Penalty;
-      break;
     case CXAvailability_NotAvailable:
-      Score += 3 * Penalty;
+      Score = 0;
       break;
     }
     return Score;
   }
+
+  // Produces an integer that sorts in the same order as F.
+  static uint32_t encodeFloat(float F) {
+    // IEEE 754 floats compare like 2s complement integers.
+    static_assert(std::numeric_limits<float>::is_iec559, "");
+    static_assert(sizeof(float) == sizeof(uint32_t), "");
+    uint32_t U;
+    memcpy(&U, &F, sizeof(float));
+    // Convert U from 2s complement to unsigned, preserving order.
+    const uint32_t SignBit = ~(~uint32_t{0} >> 1);
+    return U & SignBit ? 0 - U : U + SignBit;
+  }
 };
 
 class CompletionItemsCollector : public CodeCompleteConsumer {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to