]> granicus.if.org Git - clang/commitdiff
Move the sorting of code-completion results out of the main path and
authorDouglas Gregor <dgregor@apple.com>
Wed, 25 Aug 2010 22:15:42 +0000 (22:15 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 25 Aug 2010 22:15:42 +0000 (22:15 +0000)
into the clients, e.g., the printing code-completion consumer and
c-index-test. Clients may want to re-sort the results anyway.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112095 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Frontend/ASTUnit.cpp
lib/Sema/CodeCompleteConsumer.cpp
lib/Sema/SemaCodeComplete.cpp
test/Index/code-completion.cpp
test/Index/complete-method-decls.m
test/Index/complete-objc-message.m
tools/c-index-test/c-index-test.c
tools/libclang/CIndexCodeCompletion.cpp

index 452803acd29bfd353f10cfa4b90a6d055a87276a..874fd012b3c9ed8695f71609720f568720d9ebd7 100644 (file)
@@ -1678,9 +1678,7 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
     Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
     return;
   }
-
-  // Sort the completion results before passing them on to the actual consumer.
-  std::stable_sort(AllResults.begin(), AllResults.end());
+  
   Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
                                   AllResults.size());
   
index 43451235589e1579269dea12fa1656ec752d49e3..c4e7bb4269d1d19d2222c8146be11102ed430625 100644 (file)
@@ -443,6 +443,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
                                                  CodeCompletionContext Context,
                                                  CodeCompletionResult *Results,
                                                          unsigned NumResults) {
+  std::stable_sort(Results, Results + NumResults);
+  
   // Print the results.
   for (unsigned I = 0; I != NumResults; ++I) {
     OS << "COMPLETION: ";
@@ -660,6 +662,11 @@ bool clang::operator<(const CodeCompletionResult &X,
   if (cmp)
     return cmp < 0;
   
+  // If case-insensitive comparison fails, try case-sensitive comparison.
+  cmp = XStr.compare(YStr);
+  if (cmp)
+    return cmp < 0;
+
   // Non-hidden names precede hidden names.
   if (X.Hidden != Y.Hidden)
     return !X.Hidden;
@@ -695,7 +702,7 @@ CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
                                                        unsigned NumCandidates) {
   for (unsigned I = 0; I != NumCandidates; ++I) {
     WriteUnsigned(OS, CXCursor_NotImplemented);
-    WriteUnsigned(OS, /*Priority=*/0);
+    WriteUnsigned(OS, /*Priority=*/I);
     WriteUnsigned(OS, /*Availability=*/CXAvailability_Available);
     CodeCompletionString *CCS
       = Candidates[I].CreateSignatureString(CurrentArg, SemaRef);
index fed65365706c82030f8b48123f6d48ba60a74afd..d61ddcdf758a31e259a89c57ee915bd4e82182e0 100644 (file)
@@ -2277,8 +2277,6 @@ static void HandleCodeCompleteResults(Sema *S,
                                       CodeCompletionContext Context,
                                       CodeCompletionResult *Results,
                                       unsigned NumResults) {
-  std::stable_sort(Results, Results + NumResults);
-
   if (CodeCompleter)
     CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
   
index 354e7461660a5a9fb4037491435177ca26efe6c2..8efac1fea1d32e19a8710d87df2f49392aa94abf 100644 (file)
@@ -60,8 +60,8 @@ Z::operator int() const {
 // RUN: c-index-test -code-completion-at=%s:37:10 %s | FileCheck -check-prefix=CHECK-EXPR %s
 // CHECK-EXPR: NotImplemented:{TypedText int} (65)
 // CHECK-EXPR: NotImplemented:{TypedText long} (65)
-// CHECK-EXPR: FieldDecl:{ResultType double}{TypedText member} (10)
 // CHECK-EXPR: FieldDecl:{ResultType int}{Text X::}{TypedText member} (5)
+// CHECK-EXPR: FieldDecl:{ResultType double}{TypedText member} (10)
 // CHECK-EXPR: FieldDecl:{ResultType float}{Text Y::}{TypedText member} (11)
 // CHECK-EXPR: FunctionDecl:{ResultType void}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )} (22)
 // CHECK-EXPR: NotImplemented:{TypedText N}{Text ::} (75)
index 1324ae4a6970d5a6c5b57145335be431d2bddeb7..0c9a55a2b3710639e100ec974963586c583853b7 100644 (file)
 // CHECK-CCC: ObjCInstanceMethodDecl:{TypedText first}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace  }{Text second2}{Colon :}{LeftParen (}{Text float}{RightParen )}{Text y}{HorizontalSpace  }{Text third}{Colon :}{LeftParen (}{Text double}{RightParen )}{Text z} (30)
 // RUN: c-index-test -code-completion-at=%s:56:21 %s | FileCheck -check-prefix=CHECK-CCD %s
 // FIXME: These results could be more precise.
-// CHECK-CCD: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{TypedText second2:}{Text (float)y2}{HorizontalSpace  }{Text third:}{Text (double)z} (20)
 // CHECK-CCD: ObjCInstanceMethodDecl:{ResultType int}{Informative first:}{TypedText second2:}{Text (float)y}{HorizontalSpace  }{Text third:}{Text (double)z} (5)
+// CHECK-CCD: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{TypedText second2:}{Text (float)y2}{HorizontalSpace  }{Text third:}{Text (double)z} (20)
 // CHECK-CCD: ObjCInstanceMethodDecl:{ResultType void *}{Informative first:}{TypedText second3:}{Text (float)y3}{HorizontalSpace  }{Text third:}{Text (double)z} (20)
 // CHECK-CCD: ObjCInstanceMethodDecl:{ResultType int}{Informative first:}{TypedText second:}{Text (float)y}{HorizontalSpace  }{Text third:}{Text (double)z} (5)
 // RUN: c-index-test -code-completion-at=%s:56:38 %s | FileCheck -check-prefix=CHECK-CCE %s
-// CHECK-CCE: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{Informative second2:}{TypedText third:}{Text (double)z} (20)
 // CHECK-CCE: ObjCInstanceMethodDecl:{ResultType int}{Informative first:}{Informative second2:}{TypedText third:}{Text (double)z} (5)
+// CHECK-CCE: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{Informative second2:}{TypedText third:}{Text (double)z} (20)
 // RUN: c-index-test -code-completion-at=%s:60:4 %s | FileCheck -check-prefix=CHECK-CCF %s
 // CHECK-CCF: ObjCInterfaceDecl:{TypedText A} (65)
 // CHECK-CCF: ObjCInterfaceDecl:{TypedText B} (65)
index 54f62a045db3b9cd432a4844684cf40192623d28..1f96bb61e3b7b9a24b2ec5e271f16de79d65e9d2 100644 (file)
@@ -209,20 +209,23 @@ void test_ranking(B *b) {
 // CHECK-CCF: {ResultType Class}{TypedText self}
 // CHECK-CCF: {TypedText super}
 // RUN: c-index-test -code-completion-at=%s:120:6 %s | FileCheck -check-prefix=CHECK-CCG %s
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType id}{TypedText categoryInstanceMethod}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType id}{TypedText instanceMethod1}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int)i}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace  }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace  }{Text Arg2:}{Placeholder (int)i2}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace  }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace  }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace  }{Text SomeArg:}{Placeholder (int)i1}{HorizontalSpace  }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)x}{HorizontalSpace  }{Text second:}{Placeholder (id)y}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyPrivateInstMethod}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MySubInstMethod}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MySubInstMethod:}{Placeholder (id)obj}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)f}{HorizontalSpace  }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace  }{Text Arg2:}{Placeholder (int)i2}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType id}{TypedText protocolInstanceMethod:}{Placeholder (int)value}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText secondProtocolInstanceMethod}
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType id}{TypedText categoryInstanceMethod} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType id}{TypedText instanceMethod1} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int)i} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace  }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace  }{Text Arg2:}{Placeholder (int)i2} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace  }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace  }{Text OtherArg:}{Placeholder (id)obj} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace  }{Text SomeArg:}{Placeholder (int)i1}{HorizontalSpace  }{Text OtherArg:}{Placeholder (id)obj} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)x}{HorizontalSpace  }{Text second:}{Placeholder (id)y} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyPrivateInstMethod} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MySubInstMethod} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MySubInstMethod:}{Placeholder (id)obj} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)f}{HorizontalSpace  }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace  }{Text Arg2:}{Placeholder (int)i2} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType id}{TypedText protocolInstanceMethod:}{Placeholder (int)value} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText secondProtocolInstanceMethod} (20)
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText SentinelMethod:}{Placeholder (int)i}{Placeholder , ...}{Text , nil} (20)
+
+                    
 // RUN: c-index-test -code-completion-at=%s:121:14 %s | FileCheck -check-prefix=CHECK-CCG %s
 // RUN: c-index-test -code-completion-at=%s:122:7 %s | FileCheck -check-prefix=CHECK-CCH %s
 // CHECK-CCH: ObjCClassMethodDecl:{ResultType id}{TypedText categoryClassMethod}
index 330fa545f9310fb1cc86f8caebc77ed78acf9ce6..c13ae91cb656d28a4bdf9df46814520a49089fb3 100644 (file)
@@ -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>
@@ -895,6 +896,84 @@ void print_completion_result(CXCompletionResult *completion_result,
   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 compare_completion_string(const void *xv, const void *yv) {
+  CXCompletionString x = ((CXCompletionResult *)xv)->CompletionString;
+  CXCompletionString y = ((CXCompletionResult *)yv)->CompletionString;
+  CXString xText, yText;
+  int I, N;
+  int result;
+  int FoundXText = 0, FoundYText = 0;
+  
+  /* Find the typed text in x. */
+  for (I = 0, N = clang_getNumCompletionChunks(x); I != N; ++I) {
+    if (clang_getCompletionChunkKind(x, I) == CXCompletionChunk_TypedText) {
+      xText = clang_getCompletionChunkText(x, I);
+      FoundXText = 1;
+      break;
+    }
+  }
+  
+  /* Find the typed text in x. */
+  for (I = 0, N = clang_getNumCompletionChunks(y); I != N; ++I) {
+    if (clang_getCompletionChunkKind(y, I) == CXCompletionChunk_TypedText) {
+      yText = clang_getCompletionChunkText(y, I);
+      FoundYText = 1;
+      break;
+    }
+  }
+  
+  if (!FoundXText || !FoundYText) {
+    /* At least one of the results is missing a TypedText chunk. */
+    if (FoundXText)
+      clang_disposeString(xText);
+    if (FoundYText)
+      clang_disposeString(xText);
+    
+    if (FoundXText || FoundYText)
+      return FoundXText? -1 : 1;
+  } else {
+    /* First, try case-insensitive comparisons. */
+    result = my_stricmp(clang_getCString(xText), clang_getCString(yText));
+
+    /* If that fails, try case-sensitive comparison. */
+    if (!result)
+      result = strcmp(clang_getCString(xText), clang_getCString(yText));
+    
+    clang_disposeString(xText);
+    clang_disposeString(yText);
+    if (result)
+      return result;
+  }
+  
+  /* The completion strings appear to be the same; try to order based on
+     priority. */
+  if (clang_getCompletionPriority(x) < clang_getCompletionPriority(y))
+    return -1;
+  else if (clang_getCompletionPriority(x) > clang_getCompletionPriority(y))
+    return 1;
+  
+  return 0;
+}
+
 int perform_code_completion(int argc, const char **argv, int timing_only) {
   const char *input = argv[1];
   char *filename = 0;
@@ -950,9 +1029,14 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
 
   if (results) {
     unsigned i, n = results->NumResults;
-    if (!timing_only)
+    if (!timing_only) {      
+      /* Sort the code-completion results based on the typed text. */
+      mergesort(results->Results, results->NumResults, 
+                sizeof(CXCompletionResult), &compare_completion_string);
+
       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);
index 026d0be4ba4abad3ad7360d394a37fdc5784e917..7cf8f9f7792fdb44b4c1354ae49232576f8336ec 100644 (file)
@@ -582,6 +582,8 @@ namespace {
         AllocatedResults.Results[I].CompletionString = StoredCompletion;
       }
     }
+    
+    // FIXME: Add ProcessOverloadCandidates?
   };
 }