Introduce priorities into the code-completion results.

llvm-svn: 104751
diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp
index 52562f6..6cefc61 100644
--- a/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -210,9 +210,10 @@
   }
 }
 
-CodeCompletionString::~CodeCompletionString() {
+void CodeCompletionString::clear() {
   std::for_each(Chunks.begin(), Chunks.end(), 
                 std::mem_fun_ref(&Chunk::Destroy));
+  Chunks.clear();
 }
 
 std::string CodeCompletionString::getAsString() const {
@@ -310,15 +311,13 @@
   }
 }
 
-CodeCompletionString *CodeCompletionString::Deserialize(const char *&Str,
-                                                        const char *StrEnd) {
+bool CodeCompletionString::Deserialize(const char *&Str, const char *StrEnd) {
   if (Str == StrEnd || *Str == 0)
-    return 0;
+    return false;
 
-  CodeCompletionString *Result = new CodeCompletionString;
   unsigned NumBlocks;
   if (ReadUnsigned(Str, StrEnd, NumBlocks))
-    return Result;
+    return false;
 
   for (unsigned I = 0; I != NumBlocks; ++I) {
     if (Str + 1 >= StrEnd)
@@ -327,7 +326,7 @@
     // Parse the next kind.
     unsigned KindValue;
     if (ReadUnsigned(Str, StrEnd, KindValue))
-      return Result;
+      return false;
 
     switch (ChunkKind Kind = (ChunkKind)KindValue) {
     case CK_TypedText:
@@ -338,16 +337,17 @@
     case CK_CurrentParameter: {
       unsigned StrLen;
       if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd))
-        return Result;
+        return false;
 
-      Result->AddChunk(Chunk(Kind, StringRef(Str, StrLen)));
+      AddChunk(Chunk(Kind, StringRef(Str, StrLen)));
       Str += StrLen;
       break;
     }
 
     case CK_Optional: {
-      std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str, StrEnd));
-      Result->AddOptionalChunk(Optional);
+      std::auto_ptr<CodeCompletionString> Optional(new CodeCompletionString());
+      if (Optional->Deserialize(Str, StrEnd))
+        AddOptionalChunk(Optional);
       break;
     }
 
@@ -365,12 +365,12 @@
     case CK_Equal:
     case CK_HorizontalSpace:
     case CK_VerticalSpace:
-      Result->AddChunk(Chunk(Kind));
+      AddChunk(Chunk(Kind));
       break;      
     }
   };
   
-  return Result;
+  return true;
 }
 
 void CodeCompleteConsumer::Result::Destroy() {
@@ -380,6 +380,25 @@
   }
 }
 
+unsigned CodeCompleteConsumer::Result::getPriorityFromDecl(NamedDecl *ND) {
+  if (!ND)
+    return CCP_Unlikely;
+  
+  // Context-based decisions.
+  DeclContext *DC = ND->getDeclContext()->getLookupContext();
+  if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC))
+    return CCP_LocalDeclaration;
+  if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
+    return CCP_MemberDeclaration;
+  
+  // Content-based decisions.
+  if (isa<EnumConstantDecl>(ND))
+    return CCP_Constant;
+  if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
+    return CCP_Type;
+  return CCP_Declaration;
+}
+
 //===----------------------------------------------------------------------===//
 // Code completion overload candidate implementation
 //===----------------------------------------------------------------------===//
@@ -584,6 +603,7 @@
     }
 
     WriteUnsigned(OS, Kind);
+    WriteUnsigned(OS, Results[I].Priority);
     CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef);
     assert(CCS && "No code-completion string?");
     CCS->Serialize(OS);
@@ -598,6 +618,7 @@
                                                        unsigned NumCandidates) {
   for (unsigned I = 0; I != NumCandidates; ++I) {
     WriteUnsigned(OS, CXCursor_NotImplemented);
+    WriteUnsigned(OS, /*Priority=*/0);
     CodeCompletionString *CCS
       = Candidates[I].CreateSignatureString(CurrentArg, SemaRef);
     assert(CCS && "No code-completion string?");
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index e001943..d8c1a5c 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -539,8 +539,10 @@
   
   // If the filter is for nested-name-specifiers, then this result starts a
   // nested-name-specifier.
-  if (AsNestedNameSpecifier)
+  if (AsNestedNameSpecifier) {
     R.StartsNestedNameSpecifier = true;
+    R.Priority = CCP_NestedNameSpecifier;
+  }
   
   // If this result is supposed to have an informative qualifier, add one.
   if (R.QualifierIsInformative && !R.Qualifier &&
@@ -588,8 +590,10 @@
   
   // If the filter is for nested-name-specifiers, then this result starts a
   // nested-name-specifier.
-  if (AsNestedNameSpecifier)
+  if (AsNestedNameSpecifier) {
     R.StartsNestedNameSpecifier = true;
+    R.Priority = CCP_NestedNameSpecifier;
+  }
   else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
            isa<CXXRecordDecl>(R.Declaration->getDeclContext()
                                                   ->getLookupContext()))
@@ -608,6 +612,10 @@
       R.QualifierIsInformative = false;
   }
   
+  // Adjust the priority if this result comes from a base class.
+  if (InBaseClass)
+    R.Priority += CCD_InBaseClass;
+  
   // Insert this result into the set of results.
   Results.push_back(R);
 }
@@ -751,34 +759,34 @@
 static void AddTypeSpecifierResults(const LangOptions &LangOpts,
                                     ResultBuilder &Results) {
   typedef CodeCompleteConsumer::Result Result;
-  Results.AddResult(Result("short"));
-  Results.AddResult(Result("long"));
-  Results.AddResult(Result("signed"));
-  Results.AddResult(Result("unsigned"));
-  Results.AddResult(Result("void"));
-  Results.AddResult(Result("char"));
-  Results.AddResult(Result("int"));
-  Results.AddResult(Result("float"));
-  Results.AddResult(Result("double"));
-  Results.AddResult(Result("enum"));
-  Results.AddResult(Result("struct"));
-  Results.AddResult(Result("union"));
-  Results.AddResult(Result("const"));
-  Results.AddResult(Result("volatile"));
+  Results.AddResult(Result("short", CCP_Type));
+  Results.AddResult(Result("long", CCP_Type));
+  Results.AddResult(Result("signed", CCP_Type));
+  Results.AddResult(Result("unsigned", CCP_Type));
+  Results.AddResult(Result("void", CCP_Type));
+  Results.AddResult(Result("char", CCP_Type));
+  Results.AddResult(Result("int", CCP_Type));
+  Results.AddResult(Result("float", CCP_Type));
+  Results.AddResult(Result("double", CCP_Type));
+  Results.AddResult(Result("enum", CCP_Type));
+  Results.AddResult(Result("struct", CCP_Type));
+  Results.AddResult(Result("union", CCP_Type));
+  Results.AddResult(Result("const", CCP_Type));
+  Results.AddResult(Result("volatile", CCP_Type));
 
   if (LangOpts.C99) {
     // C99-specific
-    Results.AddResult(Result("_Complex"));
-    Results.AddResult(Result("_Imaginary"));
-    Results.AddResult(Result("_Bool"));
-    Results.AddResult(Result("restrict"));
+    Results.AddResult(Result("_Complex", CCP_Type));
+    Results.AddResult(Result("_Imaginary", CCP_Type));
+    Results.AddResult(Result("_Bool", CCP_Type));
+    Results.AddResult(Result("restrict", CCP_Type));
   }
   
   if (LangOpts.CPlusPlus) {
     // C++-specific
-    Results.AddResult(Result("bool"));
-    Results.AddResult(Result("class"));
-    Results.AddResult(Result("wchar_t"));
+    Results.AddResult(Result("bool", CCP_Type));
+    Results.AddResult(Result("class", CCP_Type));
+    Results.AddResult(Result("wchar_t", CCP_Type));
     
     if (Results.includeCodePatterns()) {
       // typename qualified-id
@@ -790,10 +798,17 @@
     }
     
     if (LangOpts.CPlusPlus0x) {
-      Results.AddResult(Result("auto"));
-      Results.AddResult(Result("char16_t"));
-      Results.AddResult(Result("char32_t"));
-      Results.AddResult(Result("decltype"));
+      Results.AddResult(Result("auto", CCP_Type));
+      Results.AddResult(Result("char16_t", CCP_Type));
+      Results.AddResult(Result("char32_t", CCP_Type));
+      if (Results.includeCodePatterns()) {
+        CodeCompletionString *Pattern = new CodeCompletionString;
+        Pattern->AddTypedTextChunk("decltype");
+        Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+        Pattern->AddPlaceholderChunk("expression-or-type");
+        Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+        Results.AddResult(Result(Pattern));
+      }
     }
   }
   
@@ -1299,6 +1314,8 @@
         Pattern->AddPlaceholderChunk("expression");
         Results.AddResult(Result(Pattern));
       }
+      
+      // FIXME: Rethrow?
     }
 
     if (SemaRef.getLangOptions().ObjC1) {