Skip to content

Commit

Permalink
[CodeComplete] Set preferred type for qualified-id
Browse files Browse the repository at this point in the history
Reviewers: kadircet

Reviewed By: kadircet

Subscribers: cfe-commits

Tags: #clang

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

llvm-svn: 361838
  • Loading branch information
ilya-biryukov committed May 28, 2019
1 parent 9bf766c commit b1296fa
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 8 deletions.
4 changes: 2 additions & 2 deletions clang/include/clang/Sema/Sema.h
Expand Up @@ -10646,8 +10646,8 @@ class Sema {
void CodeCompleteInitializer(Scope *S, Decl *D);
void CodeCompleteAfterIf(Scope *S);

void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
bool EnteringContext, QualType BaseType);
void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext,
QualType BaseType, QualType PreferredType);
void CodeCompleteUsing(Scope *S);
void CodeCompleteUsingDirective(Scope *S);
void CodeCompleteNamespaceDecl(Scope *S);
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Parse/ParseExprCXX.cpp
Expand Up @@ -232,13 +232,16 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
HasScopeSpecifier = true;
}

// Preferred type might change when parsing qualifiers, we need the original.
auto SavedType = PreferredType;
while (true) {
if (HasScopeSpecifier) {
if (Tok.is(tok::code_completion)) {
// Code completion for a nested-name-specifier, where the code
// completion token follows the '::'.
Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext,
ObjectType.get());
ObjectType.get(),
SavedType.get(SS.getBeginLoc()));
// Include code completion token into the range of the scope otherwise
// when we try to annotate the scope tokens the dangling code completion
// token will cause assertion in
Expand Down
16 changes: 11 additions & 5 deletions clang/lib/Sema/SemaCodeComplete.cpp
Expand Up @@ -5215,7 +5215,8 @@ void Sema::CodeCompleteAfterIf(Scope *S) {
}

void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
bool EnteringContext, QualType BaseType) {
bool EnteringContext, QualType BaseType,
QualType PreferredType) {
if (SS.isEmpty() || !CodeCompleter)
return;

Expand All @@ -5224,13 +5225,15 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
// 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_Symbol);
CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol, PreferredType);
CC.setCXXScopeSpecifier(SS);
// As SS is invalid, we try to collect accessible contexts from the current
// scope with a dummy lookup so that the completion consumer can try to
// guess what the specified scope is.
ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(), CC);
if (!PreferredType.isNull())
DummyResults.setPreferredType(PreferredType);
if (S->getEntity()) {
CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
BaseType);
Expand All @@ -5253,9 +5256,12 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
return;

ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Symbol);
ResultBuilder Results(
*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext(CodeCompletionContext::CCC_Symbol, PreferredType));
if (!PreferredType.isNull())
Results.setPreferredType(PreferredType);
Results.EnterNewScope();

// The "template" keyword can follow "::" in the grammar, but only
Expand Down
26 changes: 26 additions & 0 deletions clang/unittests/Sema/CodeCompleteTest.cpp
Expand Up @@ -454,5 +454,31 @@ TEST(PreferredTypeTest, FunctionArguments) {
}
)cpp";
EXPECT_THAT(collectPreferredTypes(Code), Each("volatile double *"));

Code = R"cpp(
namespace ns {
struct vector {
};
}
void accepts_vector(ns::vector);
void test() {
accepts_vector(^::^ns::^vector());
}
)cpp";
EXPECT_THAT(collectPreferredTypes(Code), Each("ns::vector"));

Code = R"cpp(
template <class T>
struct vector { using self = vector; };
void accepts_vector(vector<int>);
int foo(int);
void test() {
accepts_vector(^::^vector<decltype(foo(1))>::^self);
}
)cpp";
EXPECT_THAT(collectPreferredTypes(Code), Each("vector<int>"));
}
} // namespace

0 comments on commit b1296fa

Please sign in to comment.