[clang] Make sure codecompletion is called for calls even when inside a token.

Summary:
Currently CodeCompleteCall only gets called after a comma or parantheses. This
patch makes sure it is called even at the cases like:
```foo(1^);```

Reviewers: ilya-biryukov, ioeric, hokein

Reviewed By: ilya-biryukov

Subscribers: MaskRay, jkorous, arphaman, cfe-commits

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

llvm-svn: 341824
This commit is contained in:
Kadir Cetinkaya 2018-09-10 13:46:28 +00:00
parent cc08366035
commit a32d253f10
8 changed files with 88 additions and 4 deletions

View File

@ -214,6 +214,11 @@ class Parser : public CodeCompletionHandler {
/// should not be set directly.
bool InMessageExpression;
/// Gets set to true after calling ProduceSignatureHelp, it is for a
/// workaround to make sure ProduceSignatureHelp is only called at the deepest
/// function call.
bool CalledSignatureHelp = false;
/// The "depth" of the template parameters currently being parsed.
unsigned TemplateParameterDepth;

View File

@ -2305,6 +2305,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
ThisDecl->getLocation(), Exprs, T.getOpenLocation());
CalledSignatureHelp = true;
Actions.CodeCompleteExpression(getCurScope(), PreferredType);
};
if (ThisVarDecl) {
@ -2317,6 +2318,12 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
}
if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) {
if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
Actions.ProduceConstructorSignatureHelp(
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
ThisDecl->getLocation(), Exprs, T.getOpenLocation());
CalledSignatureHelp = true;
}
Actions.ActOnInitializerError(ThisDecl);
SkipUntil(tok::r_paren, StopAtSemi);
} else {

View File

@ -1652,6 +1652,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (Tok.is(tok::code_completion)) {
QualType PreferredType = Actions.ProduceCallSignatureHelp(
getCurScope(), LHS.get(), None, PT.getOpenLocation());
CalledSignatureHelp = true;
Actions.CodeCompleteExpression(getCurScope(), PreferredType);
cutOffParsing();
return ExprError();
@ -1662,9 +1663,19 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
QualType PreferredType = Actions.ProduceCallSignatureHelp(
getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation());
CalledSignatureHelp = true;
Actions.CodeCompleteExpression(getCurScope(), PreferredType);
})) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
// If we got an error when parsing expression list, we don't call
// the CodeCompleteCall handler inside the parser. So call it here
// to make sure we get overload suggestions even when we are in the
// middle of a parameter.
if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
Actions.ProduceCallSignatureHelp(getCurScope(), LHS.get(),
ArgExprs, PT.getOpenLocation());
CalledSignatureHelp = true;
}
LHS = ExprError();
} else if (LHS.isInvalid()) {
for (auto &E : ArgExprs)

View File

@ -1688,8 +1688,15 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
DS.getEndLoc(), Exprs, T.getOpenLocation());
CalledSignatureHelp = true;
Actions.CodeCompleteExpression(getCurScope(), PreferredType);
})) {
if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
Actions.ProduceConstructorSignatureHelp(
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
DS.getEndLoc(), Exprs, T.getOpenLocation());
CalledSignatureHelp = true;
}
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@ -2818,13 +2825,22 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
if (Tok.isNot(tok::r_paren)) {
CommaLocsTy CommaLocs;
if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] {
ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(),
DeclaratorInfo).get();
ParsedType TypeRep =
Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
CalledSignatureHelp = true;
Actions.CodeCompleteExpression(getCurScope(), PreferredType);
})) {
})) {
if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
ParsedType TypeRep =
Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
Actions.ProduceConstructorSignatureHelp(
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
CalledSignatureHelp = true;
}
SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch);
return ExprError();
}

View File

@ -422,8 +422,15 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
getCurScope(),
OmpPrivParm->getType()->getCanonicalTypeInternal(),
OmpPrivParm->getLocation(), Exprs, LParLoc);
CalledSignatureHelp = true;
Actions.CodeCompleteExpression(getCurScope(), PreferredType);
})) {
if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
Actions.ProduceConstructorSignatureHelp(
getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
OmpPrivParm->getLocation(), Exprs, LParLoc);
CalledSignatureHelp = true;
}
Actions.ActOnInitializerError(OmpPrivParm);
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
} else {

View File

@ -619,6 +619,10 @@ static std::string getOverloadAsString(const CodeCompletionString &CCS) {
OS << "<#" << C.Text << "#>";
break;
// FIXME: We can also print optional parameters of an overload.
case CodeCompletionString::CK_Optional:
break;
default: OS << C.Text; break;
}
}

View File

@ -0,0 +1,27 @@
int f(int i, int j = 2, int k = 5);
int f(float x, float y...);
class A {
public:
A(int, int, int);
};
void test() {
A a(f(1, 2, 3, 4), 2, 3);
}
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:10 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:17 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:19 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:20 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
// CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y)
// CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>)
// CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A(
// CHECK-CC2: OVERLOAD: [#int#]f(float x, float y)
// CHECK-CC2-NOT: OVERLOAD: [#int#]f(int i)
// CHECK-CC3: OVERLOAD: A(<#int#>, int, int)
// CHECK-CC3: OVERLOAD: A(<#const A &#>)
// CHECK-CC3: OVERLOAD: A(<#A &&#>)
// CHECK-CC4: OVERLOAD: A(int, <#int#>, int)

View File

@ -60,7 +60,6 @@ typedef void (^FooBlock)(Foo *someParameter);
// RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck -check-prefix=CHECK-NO %s
// RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck -check-prefix=CHECK-NO %s
// RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck -check-prefix=CHECK-NO %s
// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO %s
// RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck -check-prefix=CHECK-NO %s
// CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
@ -69,4 +68,12 @@ typedef void (^FooBlock)(Foo *someParameter);
// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO1 %s
// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
// CHECK-NO1-NEXT: OverloadCandidate:{ResultType void}{Text func}{LeftParen (}{CurrentParameter int x}{RightParen )} (1)
@end