[cfe-commits] r82586 - in /cfe/trunk: include/clang/Sema/CodeCompleteConsumer.h lib/Sema/CodeCompleteConsumer.cpp lib/Sema/SemaCodeComplete.cpp test/CodeCompletion/member-access.cpp test/CodeCompletion/namespace-alias.cpp test/CodeCompletion/operator.cpp test/CodeCompletion/tag.cpp test/CodeCompletion/using-namespace.cpp test/CodeCompletion/using.cpp

Douglas Gregor dgregor at apple.com
Tue Sep 22 16:15:58 PDT 2009


Author: dgregor
Date: Tue Sep 22 18:15:58 2009
New Revision: 82586

URL: http://llvm.org/viewvc/llvm-project?rev=82586&view=rev
Log:
Tweak the code-completion results ranking and formation, so that
members found in base classes have the same ranking as members found
in derived classes. However, we will introduce an informative note for
members found in base classes, showing (as a nested-name-specifier)
the qualification to name the base class, to make it clear which
members are from bases.
 

Modified:
    cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
    cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/CodeCompletion/member-access.cpp
    cfe/trunk/test/CodeCompletion/namespace-alias.cpp
    cfe/trunk/test/CodeCompletion/operator.cpp
    cfe/trunk/test/CodeCompletion/tag.cpp
    cfe/trunk/test/CodeCompletion/using-namespace.cpp
    cfe/trunk/test/CodeCompletion/using.cpp

Modified: cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h?rev=82586&r1=82585&r2=82586&view=diff

==============================================================================
--- cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h (original)
+++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Tue Sep 22 18:15:58 2009
@@ -48,7 +48,10 @@
     CK_Optional,
     /// \brief A string that acts as a placeholder for, e.g., a function 
     /// call argument.
-    CK_Placeholder
+    CK_Placeholder,
+    /// \brief A piece of text that describes something about the result but
+    /// should not be inserted into the buffer.
+    CK_Informative
   };
   
   /// \brief One piece of the code completion string.
@@ -58,7 +61,8 @@
     ChunkKind Kind;
     
     union {
-      /// \brief The text string associated with a CK_Text chunk.
+      /// \brief The text string associated with a CK_Text, CK_Placeholder,
+      /// or CK_Informative chunk.
       /// The string is owned by the chunk and will be deallocated 
       /// (with delete[]) when the chunk is destroyed.
       const char *Text;
@@ -67,13 +71,14 @@
       /// The optional code completion string is owned by the chunk, and will
       /// be deallocated (with delete) when the chunk is destroyed.
       CodeCompletionString *Optional;
-      
-      /// \brief Placeholder text associated with a CK_Placeholder chunk.
-      /// The string is owned by the chunk and will be deallocated (with 
-      /// delete[]) when the chunk is destroyed.
-      const char *Placeholder;
     };
     
+    Chunk() : Kind(CK_Text), Text(0) { }
+    
+  private:
+    Chunk(ChunkKind Kind, const char *Text);
+          
+  public:
     /// \brief Create a new text chunk.
     static Chunk CreateText(const char *Text);
 
@@ -82,7 +87,10 @@
 
     /// \brief Create a new placeholder chunk.
     static Chunk CreatePlaceholder(const char *Placeholder);
-    
+
+    /// \brief Create a new informative chunk.
+    static Chunk CreateInformative(const char *Informative);
+
     /// \brief Destroy this chunk, deallocating any memory it owns.
     void Destroy();
   };
@@ -118,6 +126,12 @@
   void AddPlaceholderChunk(const char *Placeholder) {
     Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
   }
+
+  /// \brief Add a new informative chunk.
+  /// The text will be copied.
+  void AddInformativeChunk(const char *Text) {
+    Chunks.push_back(Chunk::CreateInformative(Text));
+  }
   
   /// \brief Retrieve a string representation of the code completion string,
   /// which is mainly useful for debugging.
@@ -156,19 +170,26 @@
     /// \brief Whether this result is hidden by another name.
     bool Hidden : 1;
     
-    /// \brief If the result requires a nested-name-specifier for name lookup
-    /// to function properly, this is the nested-name-specifier.
+    /// \brief Whether this result was found via lookup into a base class.
+    bool QualifierIsInformative : 1;
+    
+    /// \brief If the result should have a nested-name-specifier, this is it.
+    /// When \c QualifierIsInformative, the nested-name-specifier is 
+    /// informative rather than required.
     NestedNameSpecifier *Qualifier;
     
     /// \brief Build a result that refers to a declaration.
     Result(NamedDecl *Declaration, unsigned Rank, 
-           NestedNameSpecifier *Qualifier = 0)
+           NestedNameSpecifier *Qualifier = 0,
+           bool QualifierIsInformative = false)
       : Kind(RK_Declaration), Declaration(Declaration), Rank(Rank), 
-        Hidden(false), Qualifier(Qualifier) { }
+        Hidden(false), QualifierIsInformative(QualifierIsInformative), 
+        Qualifier(Qualifier) { }
     
     /// \brief Build a result that refers to a keyword or symbol.
     Result(const char *Keyword, unsigned Rank)
-      : Kind(RK_Keyword), Keyword(Keyword), Rank(Rank), Hidden(false) { }
+      : Kind(RK_Keyword), Keyword(Keyword), Rank(Rank), Hidden(false),
+        QualifierIsInformative(0), Qualifier(0) { }
     
     /// \brief Retrieve the declaration stored in this result.
     NamedDecl *getDeclaration() const {

Modified: cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp?rev=82586&r1=82585&r2=82586&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp (original)
+++ cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp Tue Sep 22 18:15:58 2009
@@ -26,14 +26,19 @@
 //===----------------------------------------------------------------------===//
 // Code completion string implementation
 //===----------------------------------------------------------------------===//
-CodeCompletionString::Chunk
-CodeCompletionString::Chunk::CreateText(const char *Text) {
-  Chunk Result;
-  Result.Kind = CK_Text;
+CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) 
+  : Kind(Kind), Text(0)
+{
+  assert((Kind == CK_Text || Kind == CK_Placeholder || Kind == CK_Informative)
+         && "Invalid text chunk kind");
   char *New = new char [std::strlen(Text) + 1];
   std::strcpy(New, Text);
-  Result.Text = New;
-  return Result;  
+  this->Text = New;
+}
+
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateText(const char *Text) {
+  return Chunk(CK_Text, Text);
 }
 
 CodeCompletionString::Chunk 
@@ -47,20 +52,26 @@
 
 CodeCompletionString::Chunk 
 CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
-  Chunk Result;
-  Result.Kind = CK_Placeholder;
-  char *New = new char [std::strlen(Placeholder) + 1];
-  std::strcpy(New, Placeholder);
-  Result.Placeholder = New;
-  return Result;
+  return Chunk(CK_Placeholder, Placeholder);
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
+  return Chunk(CK_Informative, Informative);
 }
 
 void
 CodeCompletionString::Chunk::Destroy() {
   switch (Kind) {
-  case CK_Text: delete [] Text; break;
-  case CK_Optional: delete Optional; break;
-  case CK_Placeholder: delete [] Placeholder; break;
+  case CK_Optional: 
+    delete Optional; 
+    break;
+      
+  case CK_Text: 
+  case CK_Placeholder:
+  case CK_Informative:
+    delete [] Text; 
+    break;
   }
 }
 
@@ -77,7 +88,8 @@
     switch (C->Kind) {
     case CK_Text: OS << C->Text; break;
     case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
-    case CK_Placeholder: OS << "<#" << C->Placeholder << "#>"; break;
+    case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
+    case CK_Informative: OS << "[#" << C->Text << "#]"; break;
     }
   }
   

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=82586&r1=82585&r2=82586&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Sep 22 18:15:58 2009
@@ -197,8 +197,8 @@
   
   // Look through using declarations.
   if (UsingDecl *Using = dyn_cast<UsingDecl>(R.Declaration))
-    return MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier),
-                          CurContext);
+    MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier),
+                   CurContext);
   
   // Handle each declaration in an overload set separately.
   if (OverloadedFunctionDecl *Ovl 
@@ -281,6 +281,7 @@
                                  I->second.first)) {
         // Note that this result was hidden.
         R.Hidden = true;
+        R.QualifierIsInformative = false;
         
         if (!R.Qualifier)
           R.Qualifier = getRequiredQualification(SemaRef.Context, 
@@ -300,6 +301,18 @@
   if (!AllDeclsFound.insert(CanonDecl))
     return;
   
+  // If this result is supposed to have an informative qualifier, add one.
+  if (R.QualifierIsInformative && !R.Qualifier) {
+    DeclContext *Ctx = R.Declaration->getDeclContext();
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
+      R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+    else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
+      R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, 
+                             SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+    else
+      R.QualifierIsInformative = false;
+  }
+  
   // Insert this result into the set of results and into the current shadow
   // map.
   SMap.insert(std::make_pair(R.Declaration->getDeclName(),
@@ -398,9 +411,7 @@
 ///
 /// \param Ctx the declaration context from which we will gather results.
 ///
-/// \param InitialRank the initial rank given to results in this declaration
-/// context. Larger rank values will be used for, e.g., members found in
-/// base classes.
+/// \param Rank the rank given to results in this declaration context.
 ///
 /// \param Visited the set of declaration contexts that have already been
 /// visited. Declaration contexts will only be visited once.
@@ -408,18 +419,22 @@
 /// \param Results the result set that will be extended with any results
 /// found within this declaration context (and, for a C++ class, its bases).
 ///
+/// \param InBaseClass whether we are in a base class.
+///
 /// \returns the next higher rank value, after considering all of the
 /// names within this declaration context.
 static unsigned CollectMemberLookupResults(DeclContext *Ctx, 
-                                           unsigned InitialRank,
+                                           unsigned Rank,
                                            DeclContext *CurContext,
                                  llvm::SmallPtrSet<DeclContext *, 16> &Visited,
-                                           ResultBuilder &Results) {
+                                           ResultBuilder &Results,
+                                           bool InBaseClass = false) {
   // Make sure we don't visit the same context twice.
   if (!Visited.insert(Ctx->getPrimaryContext()))
-    return InitialRank;
+    return Rank;
   
   // Enumerate all of the results in this context.
+  typedef CodeCompleteConsumer::Result Result;
   Results.EnterNewScope();
   for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx; 
        CurCtx = CurCtx->getNextContext()) {
@@ -427,13 +442,11 @@
          DEnd = CurCtx->decls_end();
          D != DEnd; ++D) {
       if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
-        Results.MaybeAddResult(CodeCompleteConsumer::Result(ND, InitialRank),
-                               CurContext);
+        Results.MaybeAddResult(Result(ND, Rank, 0, InBaseClass), CurContext);
     }
   }
   
   // Traverse the contexts of inherited classes.
-  unsigned NextRank = InitialRank;
   if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
     for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
          BEnd = Record->bases_end();
@@ -468,19 +481,15 @@
       //   c->A::member
       
       // Collect results from this base class (and its bases).
-      NextRank = std::max(NextRank, 
-                          CollectMemberLookupResults(Record->getDecl(), 
-                                                     InitialRank + 1,
-                                                     CurContext,
-                                                     Visited,
-                                                     Results));
+      CollectMemberLookupResults(Record->getDecl(), Rank, CurContext, Visited,
+                                 Results, /*InBaseClass=*/true);
     }
   }
   
   // FIXME: Look into base classes in Objective-C!
   
   Results.ExitScope();
-  return NextRank;
+  return Rank + 1;
 }
 
 /// \brief Collect the results of searching for members within the given
@@ -735,6 +744,7 @@
 /// provided nested-name-specifier is non-NULL.
 void AddQualifierToCompletionString(CodeCompletionString *Result, 
                                     NestedNameSpecifier *Qualifier, 
+                                    bool QualifierIsInformative,
                                     ASTContext &Context) {
   if (!Qualifier)
     return;
@@ -744,7 +754,10 @@
     llvm::raw_string_ostream OS(PrintedNNS);
     Qualifier->print(OS, Context.PrintingPolicy);
   }
-  Result->AddTextChunk(PrintedNNS.c_str());
+  if (QualifierIsInformative)
+    Result->AddInformativeChunk(PrintedNNS.c_str());
+  else
+    Result->AddTextChunk(PrintedNNS.c_str());
 }
 
 /// \brief If possible, create a new code completion string for the given
@@ -762,7 +775,8 @@
   
   if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
     CodeCompletionString *Result = new CodeCompletionString;
-    AddQualifierToCompletionString(Result, Qualifier, S.Context);
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   S.Context);
     Result->AddTextChunk(Function->getNameAsString().c_str());
     Result->AddTextChunk("(");
     AddFunctionParameterChunks(S.Context, Function, Result);
@@ -772,7 +786,8 @@
   
   if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
     CodeCompletionString *Result = new CodeCompletionString;
-    AddQualifierToCompletionString(Result, Qualifier, S.Context);
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   S.Context);
     FunctionDecl *Function = FunTmpl->getTemplatedDecl();
     Result->AddTextChunk(Function->getNameAsString().c_str());
     
@@ -825,7 +840,8 @@
   
   if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
     CodeCompletionString *Result = new CodeCompletionString;
-    AddQualifierToCompletionString(Result, Qualifier, S.Context);
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   S.Context);
     Result->AddTextChunk(Template->getNameAsString().c_str());
     Result->AddTextChunk("<");
     AddTemplateParameterChunks(S.Context, Template, Result);
@@ -835,7 +851,8 @@
   
   if (Qualifier) {
     CodeCompletionString *Result = new CodeCompletionString;
-    AddQualifierToCompletionString(Result, Qualifier, S.Context);
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   S.Context);
     Result->AddTextChunk(ND->getNameAsString().c_str());
     return Result;
   }

Modified: cfe/trunk/test/CodeCompletion/member-access.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/member-access.cpp?rev=82586&r1=82585&r2=82586&view=diff

==============================================================================
--- cfe/trunk/test/CodeCompletion/member-access.cpp (original)
+++ cfe/trunk/test/CodeCompletion/member-access.cpp Tue Sep 22 18:15:58 2009
@@ -28,15 +28,15 @@
 void test(const Proxy &p) {
   p->
   // RUN: clang-cc -fsyntax-only -code-completion-at=%s:29:6 %s -o - | FileCheck -check-prefix=CC1 %s &&
+  // CHECK-CC1: member1 : 0 : [#Base1::#]member1
+  // CHECK-CC1: member1 : 0 : [#Base2::#]member1
+  // CHECK-CC1: member2 : 0 : [#Base1::#]member2
+  // CHECK-CC1: member3 : 0
   // CHECK-CC1: member4 : 0
-  // CHECK-CC1: memfun3 : 0
-  // CHECK-CC1: memfun1 : 1
-  // CHECK-CC1: memfun1 : 1
-  // CHECK-CC1: memfun2 : 1
-  // CHECK-CC1: member1 : 2
-  // CHECK-CC1: member1 : 2
-  // CHECK-CC1: member2 : 2
-  // CHECK-CC1: member3 : 2
-  // CHECK-CC1: memfun1 : 2 (Hidden) : Base2::memfun1(<#int#>)
+  // CHECK-CC1: memfun1 : 0 : [#Base3::#]memfun1(<#float#>)
+  // CHECK-CC1: memfun1 : 0 : [#Base3::#]memfun1(<#double#>)
+  // CHECK-CC1: memfun2 : 0 : [#Base3::#]memfun2(<#int#>)
+  // CHECK-CC1: memfun3 : 0 : memfun3(<#int#>)
+  // CHECK-CC1: memfun1 : 0 (Hidden) : Base2::memfun1(<#int#>)
   // RUN: true
   

Modified: cfe/trunk/test/CodeCompletion/namespace-alias.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/namespace-alias.cpp?rev=82586&r1=82585&r2=82586&view=diff

==============================================================================
--- cfe/trunk/test/CodeCompletion/namespace-alias.cpp (original)
+++ cfe/trunk/test/CodeCompletion/namespace-alias.cpp Tue Sep 22 18:15:58 2009
@@ -15,7 +15,7 @@
   // CHECK-CC1: I1 : 1
   // CHECK-CC1: I4 : 1
   // CHECK-CC1: I5 : 1
-  // CHECK-CC1: N2 : 2
-  // CHECK-NEXT-CC1: N4 : 2
+  // CHECK-CC1: N2 : 3
+  // CHECK-NEXT-CC1: N4 : 3
   // RUN: true
   
\ No newline at end of file

Modified: cfe/trunk/test/CodeCompletion/operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/operator.cpp?rev=82586&r1=82585&r2=82586&view=diff

==============================================================================
--- cfe/trunk/test/CodeCompletion/operator.cpp (original)
+++ cfe/trunk/test/CodeCompletion/operator.cpp Tue Sep 22 18:15:58 2009
@@ -14,5 +14,5 @@
   // CHECK-CC1: short : 0
   // CHECK-CC1: Integer : 2
   // CHECK-CC1: T : 2
-  // CHECK-CC1: N : 5
+  // CHECK-CC1: N : 6
   // RUN: true

Modified: cfe/trunk/test/CodeCompletion/tag.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/tag.cpp?rev=82586&r1=82585&r2=82586&view=diff

==============================================================================
--- cfe/trunk/test/CodeCompletion/tag.cpp (original)
+++ cfe/trunk/test/CodeCompletion/tag.cpp Tue Sep 22 18:15:58 2009
@@ -18,9 +18,9 @@
     // RUN: clang-cc -fsyntax-only -code-completion-at=%s:17:10 %s -o - | FileCheck -check-prefix=CC1 %s &&
     // CHECK-CC1: Y : 2
     // CHECK-CC1: Z : 2
-    // CHECK-CC1: A : 3
-    // CHECK-CC1: X : 3
-    // CHECK-CC1: Y : 3
-    // CHECK-CC1: M : 6
-    // CHECK-CC1: N : 6
+    // CHECK-CC1: A : 4
+    // CHECK-CC1: X : 4
+    // CHECK-CC1: Y : 4
+    // CHECK-CC1: M : 9
+    // CHECK-CC1: N : 9
     // RUN: true

Modified: cfe/trunk/test/CodeCompletion/using-namespace.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/using-namespace.cpp?rev=82586&r1=82585&r2=82586&view=diff

==============================================================================
--- cfe/trunk/test/CodeCompletion/using-namespace.cpp (original)
+++ cfe/trunk/test/CodeCompletion/using-namespace.cpp Tue Sep 22 18:15:58 2009
@@ -16,6 +16,6 @@
     // CHECK-CC1: I1 : 2
     // CHECK-CC1: I4 : 2
     // CHECK-CC1: I5 : 2
-    // CHECK-CC1: N2 : 3
-    // CHECK-NEXT-CC1: N4 : 3
+    // CHECK-CC1: N2 : 4
+    // CHECK-NEXT-CC1: N4 : 4
     // RUN: true

Modified: cfe/trunk/test/CodeCompletion/using.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/using.cpp?rev=82586&r1=82585&r2=82586&view=diff

==============================================================================
--- cfe/trunk/test/CodeCompletion/using.cpp (original)
+++ cfe/trunk/test/CodeCompletion/using.cpp Tue Sep 22 18:15:58 2009
@@ -18,8 +18,8 @@
     // CHECK-CC1: I1 : 2
     // CHECK-CC1: I4 : 2
     // CHECK-CC1: I5 : 2
-    // CHECK-CC1: N2 : 3
-    // CHECK-CC1: N3 : 3
-    // CHECK-NEXT-CC1: N4 : 3
+    // CHECK-CC1: N2 : 4
+    // CHECK-CC1: N3 : 4
+    // CHECK-NEXT-CC1: N4 : 4
     // RUN: true
 





More information about the cfe-commits mailing list