//===---- CodeCompleteConsumer.h - Code Completion Interface ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the CodeCompleteConsumer class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
#define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H

#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include <list>
#include <map>
#include <vector>

namespace llvm {
class raw_ostream;
}

namespace clang {
  
class DeclContext;
class NamedDecl;
class Scope;
class Sema;
  
/// \brief Abstract interface for a consumer of code-completion 
/// information.
class CodeCompleteConsumer {
  /// \brief The semantic-analysis object to which this code-completion
  /// consumer is attached.
  Sema &SemaRef;
  
public:
  /// \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;
    };
    
    /// \brief Describes how good this result is, with zero being the best
    /// result and progressively higher numbers representing poorer results.
    unsigned Rank;
    
    /// \brief Whether this result is hidden by another name.
    bool Hidden : 1;
    
    /// \brief Build a result that refers to a declaration.
    Result(NamedDecl *Declaration, unsigned Rank)
      : Kind(RK_Declaration), Declaration(Declaration), Rank(Rank), 
        Hidden(false) { }
    
    /// \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) { }
  };
  
  /// \brief A container of code-completion results.
  class ResultSet {
    /// \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;
    
  public:
    typedef std::vector<Result>::iterator iterator;
    iterator begin() { return Results.begin(); }
    iterator end() { return Results.end(); }
    
    Result *data() { return Results.empty()? 0 : &Results.front(); }
    unsigned size() const { return Results.size(); }
    bool empty() const { return Results.empty(); }
    
    /// \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();
  };
  
  /// \brief Create a new code-completion consumer and registers it with
  /// the given semantic-analysis object.
  explicit CodeCompleteConsumer(Sema &S);
  
  /// \brief Deregisters and destroys this code-completion consumer.
  virtual ~CodeCompleteConsumer();
  
  /// \brief Retrieve the semantic-analysis object to which this code-completion
  /// consumer is attached.
  Sema &getSema() const { return SemaRef; }
  
  /// \name Code-completion callbacks
  //@{
  
  /// \brief Process the finalized code-completion results.
  virtual void ProcessCodeCompleteResults(Result *Results, 
                                          unsigned NumResults) { }
  
  /// \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);
  //@}
  
  /// \name Utility functions
  //@{
  unsigned CollectMemberResults(DeclContext *Ctx, unsigned InitialRank, 
                                ResultSet &Results);
  //@}
};
  
/// \brief A simple code-completion consumer that prints the results it 
/// receives in a simple format.
class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
  /// \brief The raw output stream.
  llvm::raw_ostream &OS;
  
public:
  /// \brief Create a new printing code-completion consumer that prints its
  /// results to the given raw output stream.
  PrintingCodeCompleteConsumer(Sema &S, llvm::raw_ostream &OS)
    : CodeCompleteConsumer(S), OS(OS) { }
  
  /// \brief Prints the finalized code-completion results.
  virtual void ProcessCodeCompleteResults(Result *Results, 
                                          unsigned NumResults);
};
  
} // end namespace clang

#endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
