Extend code-completion results with the type of each result

llvm-svn: 91702
diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp
index d8ed894..b9b85df 100644
--- a/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -37,6 +37,7 @@
   case CK_Text:
   case CK_Placeholder:
   case CK_Informative:
+  case CK_ResultType:
   case CK_CurrentParameter: {
     char *New = new char [Text.size() + 1];
     std::memcpy(New, Text.data(), Text.size());
@@ -112,6 +113,11 @@
 }
 
 CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreateResultType(StringRef ResultType) {
+  return Chunk(CK_ResultType, ResultType);
+}
+
+CodeCompletionString::Chunk 
 CodeCompletionString::Chunk::CreateCurrentParameter(
                                                 StringRef CurrentParameter) {
   return Chunk(CK_CurrentParameter, CurrentParameter);
@@ -123,6 +129,7 @@
   case CK_Text:
   case CK_Placeholder:
   case CK_Informative:
+  case CK_ResultType:
   case CK_CurrentParameter:
   case CK_LeftParen:
   case CK_RightParen:
@@ -156,6 +163,7 @@
   case CK_Text: 
   case CK_Placeholder:
   case CK_Informative:
+  case CK_ResultType:
   case CK_CurrentParameter:
     delete [] Text;
     break;
@@ -186,7 +194,12 @@
     switch (C->Kind) {
     case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
     case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
-    case CK_Informative: OS << "[#" << C->Text << "#]"; break;
+        
+    case CK_Informative: 
+    case CK_ResultType:
+      OS << "[#" << C->Text << "#]"; 
+      break;
+        
     case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
     default: OS << C->Text; break;
     }
@@ -236,6 +249,7 @@
     case CK_Text:
     case CK_Placeholder:
     case CK_Informative:
+    case CK_ResultType:
     case CK_CurrentParameter: {
       const char *Text = C->Text;
       unsigned StrLen = strlen(Text);
@@ -286,6 +300,7 @@
     case CK_Text:
     case CK_Placeholder:
     case CK_Informative:
+    case CK_ResultType:
     case CK_CurrentParameter: {
       unsigned StrLen;
       if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd))
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 6b485ba..1391adf 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -829,6 +829,39 @@
   }
 }
 
+/// \brief If the given declaration has an associated type, add it as a result 
+/// type chunk.
+static void AddResultTypeChunk(ASTContext &Context,
+                               NamedDecl *ND,
+                               CodeCompletionString *Result) {
+  if (!ND)
+    return;
+  
+  // Determine the type of the declaration (if it has a type).
+  QualType T;
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+    T = Function->getResultType();
+  else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+    T = Method->getResultType();
+  else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+    T = FunTmpl->getTemplatedDecl()->getResultType();
+  else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+    T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
+  else if (isa<UnresolvedUsingValueDecl>(ND)) {
+    /* Do nothing: ignore unresolved using declarations*/
+  } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
+    T = Value->getType();
+  else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+    T = Property->getType();
+  
+  if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
+    return;
+  
+  std::string TypeStr;
+  T.getAsStringInternal(TypeStr, Context.PrintingPolicy);
+  Result->AddResultTypeChunk(TypeStr);
+}
+
 /// \brief Add function parameter chunks to the given code completion string.
 static void AddFunctionParameterChunks(ASTContext &Context,
                                        FunctionDecl *Function,
@@ -1042,6 +1075,8 @@
     return Result;
   }
   
+  AddResultTypeChunk(S.Context, ND, Result);
+  
   if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
     AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
                                    S.Context);
@@ -1189,6 +1224,7 @@
   
   CodeCompletionString *Result = new CodeCompletionString;
   FunctionDecl *FDecl = getFunction();
+  AddResultTypeChunk(S.Context, FDecl, Result);
   const FunctionProtoType *Proto 
     = dyn_cast<FunctionProtoType>(getFunctionType());
   if (!FDecl && !Proto) {