[SemaCodeComplete] Allow passing out scope specifiers in qualified-id completions via completion context.

Reviewers: ilya-biryukov, arphaman

Reviewed By: arphaman

Subscribers: nik, cfe-commits

Differential Revision: https://reviews.llvm.org/D40563

llvm-svn: 320471
This commit is contained in:
Eric Liu 2017-12-12 11:35:46 +00:00
parent 0f8a5a41cf
commit 06d3402816
2 changed files with 37 additions and 8 deletions

View File

@ -18,6 +18,7 @@
#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"
@ -280,6 +281,10 @@ private:
/// \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) { }
@ -315,8 +320,20 @@ public:
/// \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.

View File

@ -4603,9 +4603,19 @@ void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
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);
@ -4621,7 +4631,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
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();
@ -4635,16 +4645,18 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
// 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) {