//===---------------- SemaCodeComplete.cpp - Code Completion ----*- 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 code-completion semantic actions.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <list>
#include <map>
#include <vector>
using namespace clang;
/// \brief Set the code-completion consumer for semantic analysis.
void Sema::setCodeCompleteConsumer(CodeCompleteConsumer *CCC) {
assert(((CodeCompleter != 0) != (CCC != 0)) &&
"Already set or cleared a code-completion consumer?");
CodeCompleter = CCC;
}
namespace {
/// \brief A container of code-completion results.
class ResultBuilder {
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 (ResultBuilder::*LookupFilter)(NamedDecl *) const;
typedef CodeCompleteConsumer::Result Result;
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 semantic analysis object for which results are being
/// produced.
Sema &SemaRef;
/// \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 ResultBuilder(Sema &SemaRef, LookupFilter Filter = 0)
: SemaRef(SemaRef), 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();
/// \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;
bool IsNamespace(NamedDecl *ND) const;
bool IsNamespaceOrAlias(NamedDecl *ND) const;
bool IsType(NamedDecl *ND) const;
//@}
};
}
/// \brief Determines whether the given hidden result could be found with
/// some extra work, e.g., by qualifying the name.
///
/// \param Hidden the declaration that is hidden by the currenly \p Visible
/// declaration.
///
/// \param Visible the declaration with the same name that is already visible.
///
/// \returns true if the hidden result can be found by some mechanism,
/// false otherwise.
static bool canHiddenResultBeFound(const LangOptions &LangOpts,
NamedDecl *Hidden, NamedDecl *Visible) {
// In C, there is no way to refer to a hidden name.
if (!LangOpts.CPlusPlus)
return false;
DeclContext *HiddenCtx = Hidden->getDeclContext()->getLookupContext();
// There is no way to qualify a name declared in a function or method.
if (HiddenCtx->isFunctionOrMethod())
return false;
// If the hidden and visible declarations are in different name-lookup
// contexts, then we can qualify the name of the hidden declaration.