#include "clang/AST/DeclBase.h"
#include "clang/AST/Type.h"
#include "clang/Sema/CodeCompleteOptions.h"
+#include "clang/Sema/DeclSpec.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
/// \brief The identifiers for Objective-C selector parts.
ArrayRef<IdentifierInfo *> SelIdents;
+ /// \brief The scope specifier that comes before the completion token e.g.
+ /// "a::b::"
+ llvm::Optional<CXXScopeSpec> ScopeSpecifier;
+
public:
/// \brief Construct a new code-completion context of the given kind.
CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(None) { }
/// \brief Determines whether we want C++ constructors as results within this
/// context.
bool wantConstructorResults() const;
-};
+ /// \brief Sets the scope specifier that comes before the completion token.
+ /// This is expected to be set in code completions on qualfied specifiers
+ /// (e.g. "a::b::").
+ void setCXXScopeSpecifier(CXXScopeSpec SS) {
+ this->ScopeSpecifier = std::move(SS);
+ }
+
+ llvm::Optional<const CXXScopeSpec *> getCXXScopeSpecifier() {
+ if (ScopeSpecifier)
+ return ScopeSpecifier.getPointer();
+ return llvm::None;
+ }
+};
/// \brief A "string" used to describe how code completion can
/// be performed for an entity.
void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
bool EnteringContext) {
- if (!SS.getScopeRep() || !CodeCompleter)
+ if (SS.isEmpty() || !CodeCompleter)
return;
+ // We want to keep the scope specifier even if it's invalid (e.g. the scope
+ // "a::b::" is not corresponding to any context/namespace in the AST), since
+ // it can be useful for global code completion which have information about
+ // contexts/symbols that are not in the AST.
+ if (SS.isInvalid()) {
+ CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
+ CC.setCXXScopeSpecifier(SS);
+ HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
+ return;
+ }
// Always pretend to enter a context to ensure that a dependent type
// resolves to a dependent record.
DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Name);
Results.EnterNewScope();
-
+
// The "template" keyword can follow "::" in the grammar, but only
// put it into the grammar if the nested-name-specifier is dependent.
NestedNameSpecifier *NNS = SS.getScopeRep();
// qualified-id completions.
if (!EnteringContext)
MaybeAddOverrideCalls(*this, Ctx, Results);
- Results.ExitScope();
-
+ Results.ExitScope();
+
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
/*IncludeGlobalScope=*/true,
/*IncludeDependentBases=*/true);
- HandleCodeCompleteResults(this, CodeCompleter,
- Results.getCompletionContext(),
- Results.data(),Results.size());
+ auto CC = Results.getCompletionContext();
+ CC.setCXXScopeSpecifier(SS);
+
+ HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
+ Results.size());
}
void Sema::CodeCompleteUsing(Scope *S) {