[cfe-commits] r82293 - in /cfe/trunk: include/clang/Sema/CodeCompleteConsumer.h lib/Sema/CodeCompleteConsumer.cpp test/CodeCompletion/functions.cpp

Chris Lattner clattner at apple.com
Mon Sep 21 14:12:29 PDT 2009


On Sep 18, 2009, at 3:15 PM, Douglas Gregor wrote:

> Author: dgregor
> Date: Fri Sep 18 17:15:54 2009
> New Revision: 82293
>
> URL: http://llvm.org/viewvc/llvm-project?rev=82293&view=rev
> Log:
> Introduce code completion strings, which describe how to *use* the
> results of code completion, e.g., by providing function call syntax
> with placeholders for each of the parameters.

Very nice Doug,

Would it make sense to support "informational" Chunks which would be  
shown in the list of possibilities the user would select from, but  
would not be inserted?  This would allow you to say that "Base::N" is  
hidden in a base class, but "N" is in "class foo".

In fact, when completing P->  for members that are not in P's direct  
class (but are in base classes) it would be nifty to show which base  
class they come from in the popup.  What do you think?

-Chris


>
>
> Added:
>    cfe/trunk/test/CodeCompletion/functions.cpp   (with props)
> Modified:
>    cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
>    cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
>
> Modified: cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h?rev=82293&r1=82292&r2=82293&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h (original)
> +++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Fri Sep 18  
> 17:15:54 2009
> @@ -16,8 +16,11 @@
> #include "clang/AST/DeclarationName.h"
> #include "clang/AST/Type.h"
> #include "llvm/ADT/SmallPtrSet.h"
> +#include "llvm/ADT/SmallVector.h"
> #include <list>
> #include <map>
> +#include <memory>
> +#include <string>
> #include <vector>
>
> namespace llvm {
> @@ -31,6 +34,103 @@
> class NamedDecl;
> class Scope;
> class Sema;
> +
> +/// \brief A "string" used to describe how code completion can
> +/// be performed for an entity.
> +///
> +/// A code completion string typically shows how a particular  
> entity can be
> +/// used. For example, the code completion string for a function  
> would show
> +/// the syntax to call it, including the parentheses, placeholders  
> for the
> +/// arguments, etc.
> +class CodeCompletionString {
> +public:
> +  /// \brief The different kinds of "chunks" that can occur within  
> a code
> +  /// completion string.
> +  enum ChunkKind {
> +    /// \brief A piece of text that should be placed in the buffer,  
> e.g.,
> +    /// parentheses or a comma in a function call.
> +    CK_Text,
> +    /// \brief A code completion string that is entirely optional.  
> For example,
> +    /// an optional code completion string that describes the  
> default arguments
> +    /// in a function call.
> +    CK_Optional,
> +    /// \brief A string that acts as a placeholder for, e.g., a  
> function
> +    /// call argument.
> +    CK_Placeholder
> +  };
> +
> +  /// \brief One piece of the code completion string.
> +  struct Chunk {
> +    /// \brief The kind of data stored in this piece of the code  
> completion
> +    /// string.
> +    ChunkKind Kind;
> +
> +    union {
> +      /// \brief The text string associated with a CK_Text chunk.
> +      /// The string is owned by the chunk and will be deallocated
> +      /// (with delete[]) when the chunk is destroyed.
> +      const char *Text;
> +
> +      /// \brief The code completion string associated with a  
> CK_Optional chunk.
> +      /// 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;
> +    };
> +
> +    /// \brief Create a new text chunk.
> +    static Chunk CreateText(const char *Text);
> +
> +    /// \brief Create a new optional chunk.
> +    static Chunk CreateOptional(std::auto_ptr<CodeCompletionString>  
> Optional);
> +
> +    /// \brief Create a new placeholder chunk.
> +    static Chunk CreatePlaceholder(const char *Placeholder);
> +
> +    /// \brief Destroy this chunk.
> +    void Destroy();
> +  };
> +
> +private:
> +  /// \brief The chunks stored in this string.
> +  llvm::SmallVector<Chunk, 4> Chunks;
> +
> +  CodeCompletionString(const CodeCompletionString &); // DO NOT  
> IMPLEMENT
> +  CodeCompletionString &operator=(const CodeCompletionString &); //  
> DITTO
> +
> +public:
> +  CodeCompletionString() { }
> +  ~CodeCompletionString();
> +
> +  typedef llvm::SmallVector<Chunk, 4>::const_iterator iterator;
> +  iterator begin() const { return Chunks.begin(); }
> +  iterator end() const { return Chunks.end(); }
> +
> +  /// \brief Add a new text chunk.
> +  /// The text string will be copied.
> +  void AddTextChunk(const char *Text) {
> +    Chunks.push_back(Chunk::CreateText(Text));
> +  }
> +
> +  /// \brief Add a new optional chunk.
> +  void AddOptionalChunk(std::auto_ptr<CodeCompletionString>  
> Optional) {
> +    Chunks.push_back(Chunk::CreateOptional(Optional));
> +  }
> +
> +  /// \brief Add a new placeholder chunk.
> +  /// The placeholder text will be copied.
> +  void AddPlaceholderChunk(const char *Placeholder) {
> +    Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
> +  }
> +
> +  /// \brief Retrieve a string representation of the code  
> completion string,
> +  /// which is mainly useful for debugging.
> +  std::string getAsString() const;
> +};
>
> /// \brief Abstract interface for a consumer of code-completion
> /// information.
> @@ -264,6 +364,7 @@
>   //@{
>   bool canHiddenResultBeFound(NamedDecl *Hidden, NamedDecl *Visible);
>   void AddTypeSpecifierResults(unsigned Rank, ResultSet &Results);
> +  CodeCompletionString *CreateCodeCompletionString(Result R);
>   //@}
> };
>
>
> Modified: cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp?rev=82293&r1=82292&r2=82293&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp (original)
> +++ cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp Fri Sep 18 17:15:54  
> 2009
> @@ -19,9 +19,75 @@
> #include "llvm/Support/Compiler.h"
> #include "llvm/Support/raw_ostream.h"
> #include <algorithm>
> -#include <string.h>
> +#include <cstring>
> +#include <functional>
> using namespace clang;
>
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +// Code completion string implementation
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +CodeCompletionString::Chunk
> +CodeCompletionString::Chunk::CreateText(const char *Text) {
> +  Chunk Result;
> +  Result.Kind = CK_Text;
> +  char *New = new char [std::strlen(Text) + 1];
> +  std::strcpy(New, Text);
> +  Result.Text = New;
> +  return Result;
> +}
> +
> +CodeCompletionString::Chunk
> +CodeCompletionString::Chunk::CreateOptional(
> +                                  
> std::auto_ptr<CodeCompletionString> Optional) {
> +  Chunk Result;
> +  Result.Kind = CK_Optional;
> +  Result.Optional = Optional.release();
> +  return Result;
> +}
> +
> +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;
> +}
> +
> +void
> +CodeCompletionString::Chunk::Destroy() {
> +  switch (Kind) {
> +  case CK_Text: delete [] Text; break;
> +  case CK_Optional: delete Optional; break;
> +  case CK_Placeholder: delete [] Placeholder; break;
> +  }
> +}
> +
> +CodeCompletionString::~CodeCompletionString() {
> +  std::for_each(Chunks.begin(), Chunks.end(),
> +                std::mem_fun_ref(&Chunk::Destroy));
> +}
> +
> +std::string CodeCompletionString::getAsString() const {
> +  std::string Result;
> +  llvm::raw_string_ostream OS(Result);
> +
> +  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
> +    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;
> +    }
> +  }
> +
> +  return Result;
> +}
> +
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +// Code completion consumer implementation
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +
> CodeCompleteConsumer::CodeCompleteConsumer(Sema &S) : SemaRef(S) {
>   SemaRef.setCodeCompleteConsumer(this);
> }
> @@ -180,7 +246,7 @@
>
>   // Add the names of overloadable operators.
> #define  
> OVERLOADED_OPERATOR 
> (Name,Spelling,Token,Unary,Binary,MemberOnly)      \
> -  if (strcmp(Spelling,  
> "?"))                                                  \
> +  if (std::strcmp(Spelling,  
> "?"))                                                  \
>     Results.MaybeAddResult(Result(Spelling, 0));
> #include "clang/Basic/OperatorKinds.def"
>
> @@ -663,6 +729,64 @@
>   }
> }
>
> +/// \brief Add function parameter chunks to the given code  
> completion string.
> +static void AddFunctionParameterChunks(ASTContext &Context,
> +                                       FunctionDecl *Function,
> +                                       CodeCompletionString  
> *Result) {
> +  CodeCompletionString *CCStr = Result;
> +
> +  for (unsigned P = 0, N = Function->getNumParams(); P != N; ++P) {
> +    ParmVarDecl *Param = Function->getParamDecl(P);
> +
> +    if (Param->hasDefaultArg()) {
> +      // When we see an optional default argument, put that  
> argument and
> +      // the remaining default arguments into a new, optional string.
> +      CodeCompletionString *Opt = new CodeCompletionString;
> +      CCStr- 
> >AddOptionalChunk(std::auto_ptr<CodeCompletionString>(Opt));
> +      CCStr = Opt;
> +    }
> +
> +    if (P != 0)
> +      CCStr->AddTextChunk(", ");
> +
> +    // Format the placeholder string.
> +    std::string PlaceholderStr;
> +    if (Param->getIdentifier())
> +      PlaceholderStr = Param->getIdentifier()->getName();
> +
> +    Param->getType().getAsStringInternal(PlaceholderStr,
> +                                         Context.PrintingPolicy);
> +
> +    // Add the placeholder string.
> +    CCStr->AddPlaceholderChunk(PlaceholderStr.c_str());
> +  }
> +}
> +
> +/// \brief If possible, create a new code completion string for the  
> given
> +/// result.
> +///
> +/// \returns Either a new, heap-allocated code completion string  
> describing
> +/// how to use this result, or NULL to indicate that the string or  
> name of the
> +/// result is all that is needed.
> +CodeCompletionString *
> +CodeCompleteConsumer::CreateCodeCompletionString(Result R) {
> +  if (R.Kind != Result::RK_Declaration)
> +    return 0;
> +
> +  NamedDecl *ND = R.Declaration;
> +
> +  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
> +    CodeCompletionString *Result = new CodeCompletionString;
> +    Result->AddTextChunk(Function->getNameAsString().c_str());
> +    Result->AddTextChunk("(");
> +    AddFunctionParameterChunks(getSema().Context, Function, Result);
> +    Result->AddTextChunk(")");
> +    return Result;
> +  }
> +
> +  return 0;
> +}
> +
> void
> PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result  
> *Results,
>                                                          unsigned  
> NumResults) {
> @@ -677,6 +801,11 @@
>          << Results[I].Rank;
>       if (Results[I].Hidden)
>         OS << " (Hidden)";
> +      if (CodeCompletionString *CCS =  
> CreateCodeCompletionString(Results[I])) {
> +        OS << " : " << CCS->getAsString();
> +        delete CCS;
> +      }
> +
>       OS << '\n';
>       break;
>
>
> Added: cfe/trunk/test/CodeCompletion/functions.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/functions.cpp?rev=82293&view=auto
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/test/CodeCompletion/functions.cpp (added)
> +++ cfe/trunk/test/CodeCompletion/functions.cpp Fri Sep 18 17:15:54  
> 2009
> @@ -0,0 +1,9 @@
> +// RUN: clang-cc -fsyntax-only -code-completion-dump=1 %s -o - |  
> FileCheck -check-prefix=CC1 %s &&
> +// RUN: true
> +void f(int i, int j = 2, int k = 5);
> +void f(float x, float y);
> +
> +void test() {
> +  // CHECK-CC1: f(<#int i#>{#, <#int j#>{#, <#int k#>#}#})
> +  // CHECK-CC1: f(<#float x#>, <#float y#>)
> +  ::
>
> Propchange: cfe/trunk/test/CodeCompletion/functions.cpp
>
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Propchange: cfe/trunk/test/CodeCompletion/functions.cpp
>
> ------------------------------------------------------------------------------
>    svn:keywords = Id
>
> Propchange: cfe/trunk/test/CodeCompletion/functions.cpp
>
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits




More information about the cfe-commits mailing list