blob: a1d07a0fb39e07b8f780ee303bac3575d657d91a [file] [log] [blame]
//===---- 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 "llvm/ADT/SmallPtrSet.h"
#include <list>
#include <map>
#include <vector>
namespace llvm {
class raw_ostream;
}
namespace clang {
class Decl;
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 {
public:
/// \brief The type of a name-lookup filter, which can be provided to the
/// name-lookup routines to specify which declarations should be included in
/// the result set (when it returns true) and which declarations should be
/// filtered out (returns false).
typedef bool (CodeCompleteConsumer::*LookupFilter)(NamedDecl *) const;
private:
/// \brief The actual results we have found.
std::vector<Result> Results;
/// \brief A record of all of the declarations we have found and placed
/// into the result set, used to ensure that no declaration ever gets into
/// the result set twice.
llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
/// \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 The code-completion consumer that is producing these results.
CodeCompleteConsumer &Completer;
/// \brief If non-NULL, a filter function used to remove any code-completion
/// results that are not desirable.
LookupFilter Filter;
/// \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:
explicit ResultSet(CodeCompleteConsumer &Completer,
LookupFilter Filter = 0)
: Completer(Completer), Filter(Filter) { }
/// \brief Set the filter used for code-completion results.
void setFilter(LookupFilter Filter) {
this->Filter = Filter;
}
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 tag name following an enum, class, struct,
/// or union keyword.
virtual void CodeCompleteTag(Scope *S, ElaboratedType::TagKind TK);
/// \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 Name lookup functions
///
/// The name lookup functions in this group collect code-completion results
/// by performing a form of name looking into a scope or declaration context.
//@{
unsigned CollectLookupResults(Scope *S, unsigned InitialRank,
ResultSet &Results);
unsigned CollectMemberLookupResults(DeclContext *Ctx, unsigned InitialRank,
ResultSet &Results);
unsigned CollectMemberLookupResults(DeclContext *Ctx, unsigned InitialRank,
llvm::SmallPtrSet<DeclContext *, 16> &Visited,
ResultSet &Results);
//@}
/// \name Name lookup predicates
///
/// These predicates can be passed to the name lookup functions to filter the
/// results of name lookup. All of the predicates have the same type, so that
///
//@{
bool IsNestedNameSpecifier(NamedDecl *ND) const;
bool IsEnum(NamedDecl *ND) const;
bool IsClassOrStruct(NamedDecl *ND) const;
bool IsUnion(NamedDecl *ND) const;
//@}
/// \name Utility functions
///
//@{
bool canHiddenResultBeFound(NamedDecl *Hidden, NamedDecl *Visible);
//@}
};
/// \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