Move the sorting of code-completion results out of the main path and
into the clients, e.g., the printing code-completion consumer and
c-index-test. Clients may want to re-sort the results anyway.

Provide a libclang function that sorts the results.

3rd try. How embarrassing.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112180 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 3f70290..67e0c77 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -1,6 +1,7 @@
 /* c-index-test.c */
 
 #include "clang-c/Index.h"
+#include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -903,6 +904,25 @@
   fprintf(file, "\n");
 }
 
+int my_stricmp(const char *s1, const char *s2) {
+  while (*s1 && *s2) {
+    int c1 = tolower(*s1), c2 = tolower(*s2);
+    if (c1 < c2)
+      return -1;
+    else if (c1 > c2)
+      return 1;
+    
+    ++s1;
+    ++s2;
+  }
+  
+  if (*s1)
+    return 1;
+  else if (*s2)
+    return -1;
+  return 0;
+}
+
 int perform_code_completion(int argc, const char **argv, int timing_only) {
   const char *input = argv[1];
   char *filename = 0;
@@ -958,9 +978,13 @@
 
   if (results) {
     unsigned i, n = results->NumResults;
-    if (!timing_only)
+    if (!timing_only) {      
+      /* Sort the code-completion results based on the typed text. */
+      clang_sortCodeCompletionResults(results->Results, results->NumResults);
+
       for (i = 0; i != n; ++i)
         print_completion_result(results->Results + i, stdout);
+    }
     n = clang_codeCompleteGetNumDiagnostics(results);
     for (i = 0; i != n; ++i) {
       CXDiagnostic diag = clang_codeCompleteGetDiagnostic(results, i);
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 026d0be..825031b 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -582,6 +582,8 @@
         AllocatedResults.Results[I].CompletionString = StoredCompletion;
       }
     }
+    
+    // FIXME: Add ProcessOverloadCandidates?
   };
 }
 
@@ -784,3 +786,36 @@
 
 
 } // end extern "C"
+
+namespace {
+  struct OrderCompletionResults {
+    bool operator()(const CXCompletionResult &XR, 
+                    const CXCompletionResult &YR) const {
+      CXStoredCodeCompletionString *X
+        = (CXStoredCodeCompletionString *)XR.CompletionString;
+      CXStoredCodeCompletionString *Y
+        = (CXStoredCodeCompletionString *)YR.CompletionString;
+      
+      const char *XText = X->getTypedText();
+      const char *YText = Y->getTypedText();
+      if (!XText || !YText)
+        return XText != 0;
+      
+      int result = llvm::StringRef(XText).compare_lower(YText);
+      if (result < 0)
+        return true;
+      if (result > 0)
+        return false;
+      
+      result = llvm::StringRef(XText).compare(YText);
+      return result;
+    }
+  };
+}
+
+extern "C" {
+  void clang_sortCodeCompletionResults(CXCompletionResult *Results,
+                                       unsigned NumResults) {
+    std::stable_sort(Results, Results + NumResults, OrderCompletionResults());
+  }
+}
\ No newline at end of file
diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports
index 6a36966..d779190 100644
--- a/tools/libclang/libclang.darwin.exports
+++ b/tools/libclang/libclang.darwin.exports
@@ -99,5 +99,6 @@
 _clang_reparseTranslationUnit
 _clang_saveTranslationUnit
 _clang_setUseExternalASTGeneration
+_clang_sortCodeCompletionResults
 _clang_tokenize
 _clang_visitChildren
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 8f1d626..df93a79 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -99,5 +99,6 @@
 clang_reparseTranslationUnit
 clang_saveTranslationUnit
 clang_setUseExternalASTGeneration
+clang_sortCodeCompletionResults
 clang_tokenize
 clang_visitChildren