[cfe-commits] r82166 - in /cfe/trunk: include/clang/Basic/ include/clang/Lex/ include/clang/Parse/ include/clang/Sema/ lib/Basic/ lib/Lex/ lib/Parse/ lib/Sema/ test/ test/CodeCompletion/ tools/clang-cc/

Chris Lattner clattner at apple.com
Fri Sep 18 14:08:07 PDT 2009


On Sep 17, 2009, at 2:32 PM, Douglas Gregor wrote:
> URL: http://llvm.org/viewvc/llvm-project?rev=82166&view=rev
> Log:
> Initial implementation of a code-completion interface in Clang. In

Woot!

> +++ cfe/trunk/lib/Lex/Lexer.cpp Thu Sep 17 16:32:03 2009
> @@ -1309,6 +1310,18 @@
>     return true;  // Have a token.
>   }
>
> +  if (IsEofCodeCompletion) {
> +    // We're at the end of the file, but we've been asked to  
> conside the
> +    // end of the file to be a code-completion token. Return the
> +    // code-completion token.
> +    Result.startToken();
> +    FormTokenWithChars(Result, CurPtr, tok::code_completion);
> +
> +    // Only do the eof -> code_completion translation once.
> +    IsEofCodeCompletion = false;
> +    return true;
> +  }

Can this be moved after the "lexing raw mode" case, so that raw mode  
lexing doesn't pay the cost of an extra check?


> +++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Thu Sep 17  
> 16:32:03 2009
> +  /// \brief Captures a result of code completion.
> +  struct Result {
> +    /// \brief Describes the kind of result generated.
> +    enum ResultKind {
> +      RK_Declaration = 0, //< Refers to a declaration
> +      RK_Keyword,        //< Refers to a keyword or symbol.
> +    };
> +
> +    /// \brief The kind of result stored here.
> +    ResultKind Kind;
> +
> +    union {
> +      /// \brief When Kind == RK_Declaration, the declaration we  
> are referring
> +      /// to.
> +      NamedDecl *Declaration;
> +
> +      /// \brief When Kind == RK_Keyword, the string representing  
> the keyword
> +      /// or symbol's spelling.
> +      const char *Keyword;
> +    };

Wouldn't it be nice if PointerIntPair<> fell back to pair<void*,int>  
if the pointer had no extra bits? :)

Should a Result have an optional "extra information" flag or do you  
expect informational stuff to be derived from the decl in all cases?   
i.e. not from sema info?

> +  /// \brief A container of code-completion results.
> +  class ResultSet {

The naming here is a bit strange.  The "Result" of a code completion  
event is a "ResultSet", and a single entry in the result is a  
"Result".  How about naming the classes "ResultEntry" and "Result" or  
something?

> +    /// \brief The actual results we have found.
> +    std::vector<Result> Results;
> +
> +    /// \brief A mapping from declaration names to the declarations  
> that have
> +    /// this name within a particular scope and their index within  
> the list of
> +    /// results.
> +    typedef std::multimap<DeclarationName,
> +                          std::pair<NamedDecl *, unsigned> >  
> ShadowMap;
> +
> +    /// \brief A list of shadow maps, which is used to model name  
> hiding at
> +    /// different levels of, e.g., the inheritance hierarchy.
> +    std::list<ShadowMap> ShadowMaps;

This is a very heavy-weight structure.  I haven't read this in detail  
to understand why you need this, but... do you really need this? :)

> +
> +  public:
> +    typedef std::vector<Result>::iterator iterator;
> +    iterator begin() { return Results.begin(); }
> +    iterator end() { return Results.end(); }

How about just exposing const_iterator instead of iterator?  Do you  
expect clients to want to mutate this?

> +    Result *data() { return Results.empty()? 0 : &Results.front(); }

likewise, const Result*?

> +    /// \brief Add a new result to this result set (if it isn't  
> already in one
> +    /// of the shadow maps), or replace an existing result (for,  
> e.g., a
> +    /// redeclaration).
> +    void MaybeAddResult(Result R);
> +
> +    /// \brief Enter into a new scope.
> +    void EnterNewScope();
> +
> +    /// \brief Exit from the current scope.
> +    void ExitScope();

This style of API seems strange to me: it seems that you'd want to  
pass a fully formed "ResultSet" from Sema into an implementation of  
CodeCompleteConsumer, but ResultSet has a bunch of "builder" APIs.  
Would it make sense to split this out into a CCBuilder thing?

> +  /// \brief Process the finalized code-completion results.
> +  virtual void ProcessCodeCompleteResults(Result *Results,
> +                                          unsigned NumResults) { }

Oh, I see, Sema only gets the array of results.  Given this, should  
"ResultSet" be renamed "ResultBuilder" and moved out of the public  
header file into a private header in the Sema directory?

> +  /// \brief Code completion for a member access expression, e.g.,  
> "x->" or
> +  /// "x.".
> +  ///
> +  /// \param S is the scope in which code-completion occurs.
> +  ///
> +  /// \param BaseType is the type whose members are being accessed.
> +  ///
> +  /// \param IsArrow whether this member referenced was written  
> with an
> +  /// arrow ("->") or a period (".").
> +  virtual void CodeCompleteMemberReferenceExpr(Scope *S, QualType  
> BaseType,
> +                                               bool IsArrow);
> +
> +  /// \brief Code completion for a qualified-id, e.g., "std::"
> +  ///
> +  /// \param S the scope in which the nested-name-specifier occurs.
> +  ///
> +  /// \param NNS the nested-name-specifier before the code- 
> completion location.
> +  ///
> +  /// \param EnteringContext whether the parser will be entering  
> the scope of
> +  /// the qualified-id.
> +  virtual void CodeCompleteQualifiedId(Scope *S,  
> NestedNameSpecifier *NNS,
> +                                       bool EnteringContext);
> +  //@}

Why do these need to be in the public CodeCompleteConsumer interface?   
Doesn't Sema handle all the details of this?  Are implementations of  
consumers expected to implement these?

> +++ cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp Thu Sep 17 16:32:03  
> 2009
> @@ -0,0 +1,314 @@
> +//===---- CodeCompleteConsumer.h - Code Completion Interface ----*-  
> C++ -*-===//

Please update this line

> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open  
> Source
> +// License. See LICENSE.TXT for details.
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +//
> +//  This file implements the CodeCompleteConsumer class.
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +#include "clang/Sema/CodeCompleteConsumer.h"
> +#include "clang/Lex/Preprocessor.h"
> +#include "Sema.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/Support/Compiler.h"

No need to use VISIBILITY_HIDDEN for stuff in anonymous namespaces  
anymore.  We've decided gcc 4.0 doesn't matter for performance anymore.

> +#include "llvm/Support/raw_ostream.h"
> +#include <algorithm>
> +#include <string.h>

<cstring>

Overall, very nice!

-Chris



More information about the cfe-commits mailing list