forked from OSchip/llvm-project
[CodeCompletion] Signature help for braced constructor calls
Implementation is based on the "expected type" as used for designated-initializers in braced init lists. This means it can deduce the type in some cases where it's not written: void foo(Widget); foo({ /*help here*/ }); Only basic constructor calls are in scope of this patch, excluded are: - aggregate initialization (no help is offered for aggregates) - initializer_list initialization (no help is offered for these constructors) Fixes https://github.com/clangd/clangd/issues/306 Differential Revision: https://reviews.llvm.org/D116317
This commit is contained in:
parent
a390c9905d
commit
92417eaf33
|
@ -555,7 +555,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
|
||||||
}},
|
}},
|
||||||
{"signatureHelpProvider",
|
{"signatureHelpProvider",
|
||||||
llvm::json::Object{
|
llvm::json::Object{
|
||||||
{"triggerCharacters", {"(", ",", ")", "<", ">"}},
|
{"triggerCharacters", {"(", ")", "{", "}", "<", ">", ","}},
|
||||||
}},
|
}},
|
||||||
{"declarationProvider", true},
|
{"declarationProvider", true},
|
||||||
{"definitionProvider", true},
|
{"definitionProvider", true},
|
||||||
|
|
|
@ -921,7 +921,8 @@ public:
|
||||||
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||||
OverloadCandidate *Candidates,
|
OverloadCandidate *Candidates,
|
||||||
unsigned NumCandidates,
|
unsigned NumCandidates,
|
||||||
SourceLocation OpenParLoc) override {
|
SourceLocation OpenParLoc,
|
||||||
|
bool Braced) override {
|
||||||
assert(!OpenParLoc.isInvalid());
|
assert(!OpenParLoc.isInvalid());
|
||||||
SourceManager &SrcMgr = S.getSourceManager();
|
SourceManager &SrcMgr = S.getSourceManager();
|
||||||
OpenParLoc = SrcMgr.getFileLoc(OpenParLoc);
|
OpenParLoc = SrcMgr.getFileLoc(OpenParLoc);
|
||||||
|
@ -961,8 +962,9 @@ public:
|
||||||
paramIndexForArg(Candidate, SigHelp.activeParameter);
|
paramIndexForArg(Candidate, SigHelp.activeParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto *CCS = Candidate.CreateSignatureString(
|
const auto *CCS =
|
||||||
CurrentArg, S, *Allocator, CCTUInfo, true);
|
Candidate.CreateSignatureString(CurrentArg, S, *Allocator, CCTUInfo,
|
||||||
|
/*IncludeBriefComment=*/true, Braced);
|
||||||
assert(CCS && "Expected the CodeCompletionString to be non-null");
|
assert(CCS && "Expected the CodeCompletionString to be non-null");
|
||||||
ScoredSignatures.push_back(processOverloadCandidate(
|
ScoredSignatures.push_back(processOverloadCandidate(
|
||||||
Candidate, *CCS,
|
Candidate, *CCS,
|
||||||
|
@ -1163,7 +1165,8 @@ public:
|
||||||
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||||
OverloadCandidate *Candidates,
|
OverloadCandidate *Candidates,
|
||||||
unsigned NumCandidates,
|
unsigned NumCandidates,
|
||||||
SourceLocation OpenParLoc) override {
|
SourceLocation OpenParLoc,
|
||||||
|
bool Braced) override {
|
||||||
assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&
|
assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&
|
||||||
"too many arguments");
|
"too many arguments");
|
||||||
|
|
||||||
|
|
|
@ -107,10 +107,12 @@
|
||||||
# CHECK-NEXT: "signatureHelpProvider": {
|
# CHECK-NEXT: "signatureHelpProvider": {
|
||||||
# CHECK-NEXT: "triggerCharacters": [
|
# CHECK-NEXT: "triggerCharacters": [
|
||||||
# CHECK-NEXT: "(",
|
# CHECK-NEXT: "(",
|
||||||
# CHECK-NEXT: ",",
|
|
||||||
# CHECK-NEXT: ")",
|
# CHECK-NEXT: ")",
|
||||||
|
# CHECK-NEXT: "{",
|
||||||
|
# CHECK-NEXT: "}",
|
||||||
# CHECK-NEXT: "<",
|
# CHECK-NEXT: "<",
|
||||||
# CHECK-NEXT: ">"
|
# CHECK-NEXT: ">"
|
||||||
|
# CHECK-NEXT: ","
|
||||||
# CHECK-NEXT: ]
|
# CHECK-NEXT: ]
|
||||||
# CHECK-NEXT: },
|
# CHECK-NEXT: },
|
||||||
# CHECK-NEXT: "textDocumentSync": {
|
# CHECK-NEXT: "textDocumentSync": {
|
||||||
|
|
|
@ -1212,6 +1212,10 @@ struct ExpectedParameter {
|
||||||
std::string Text;
|
std::string Text;
|
||||||
std::pair<unsigned, unsigned> Offsets;
|
std::pair<unsigned, unsigned> Offsets;
|
||||||
};
|
};
|
||||||
|
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
|
||||||
|
const ExpectedParameter &P) {
|
||||||
|
return OS << P.Text;
|
||||||
|
}
|
||||||
MATCHER_P(ParamsAre, P, "") {
|
MATCHER_P(ParamsAre, P, "") {
|
||||||
if (P.size() != arg.parameters.size())
|
if (P.size() != arg.parameters.size())
|
||||||
return false;
|
return false;
|
||||||
|
@ -1260,6 +1264,36 @@ TEST(SignatureHelpTest, Overloads) {
|
||||||
EXPECT_EQ(0, Results.activeParameter);
|
EXPECT_EQ(0, Results.activeParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SignatureHelpTest, Constructors) {
|
||||||
|
std::string Top = R"cpp(
|
||||||
|
struct S {
|
||||||
|
S(int);
|
||||||
|
S(const S &) = delete;
|
||||||
|
};
|
||||||
|
)cpp";
|
||||||
|
|
||||||
|
auto CheckParenInit = [&](std::string Init) {
|
||||||
|
EXPECT_THAT(signatures(Top + Init).signatures,
|
||||||
|
UnorderedElementsAre(Sig("S([[int]])")))
|
||||||
|
<< Init;
|
||||||
|
};
|
||||||
|
CheckParenInit("S s(^);");
|
||||||
|
CheckParenInit("auto s = S(^);");
|
||||||
|
CheckParenInit("auto s = new S(^);");
|
||||||
|
|
||||||
|
auto CheckBracedInit = [&](std::string Init) {
|
||||||
|
EXPECT_THAT(signatures(Top + Init).signatures,
|
||||||
|
UnorderedElementsAre(Sig("S{[[int]]}")))
|
||||||
|
<< Init;
|
||||||
|
};
|
||||||
|
CheckBracedInit("S s{^};");
|
||||||
|
CheckBracedInit("S s = {^};");
|
||||||
|
CheckBracedInit("auto s = S{^};");
|
||||||
|
// FIXME: doesn't work: no ExpectedType set in ParseCXXNewExpression.
|
||||||
|
// CheckBracedInit("auto s = new S{^};");
|
||||||
|
CheckBracedInit("int x(S); int i = x({^});");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(SignatureHelpTest, OverloadInitListRegression) {
|
TEST(SignatureHelpTest, OverloadInitListRegression) {
|
||||||
auto Results = signatures(R"cpp(
|
auto Results = signatures(R"cpp(
|
||||||
struct A {int x;};
|
struct A {int x;};
|
||||||
|
|
|
@ -1081,11 +1081,11 @@ public:
|
||||||
|
|
||||||
/// Create a new code-completion string that describes the function
|
/// Create a new code-completion string that describes the function
|
||||||
/// signature of this overload candidate.
|
/// signature of this overload candidate.
|
||||||
CodeCompletionString *CreateSignatureString(unsigned CurrentArg,
|
CodeCompletionString *
|
||||||
Sema &S,
|
CreateSignatureString(unsigned CurrentArg, Sema &S,
|
||||||
CodeCompletionAllocator &Allocator,
|
CodeCompletionAllocator &Allocator,
|
||||||
CodeCompletionTUInfo &CCTUInfo,
|
CodeCompletionTUInfo &CCTUInfo,
|
||||||
bool IncludeBriefComments) const;
|
bool IncludeBriefComments, bool Braced) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
CodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts)
|
CodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts)
|
||||||
|
@ -1159,7 +1159,8 @@ public:
|
||||||
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||||
OverloadCandidate *Candidates,
|
OverloadCandidate *Candidates,
|
||||||
unsigned NumCandidates,
|
unsigned NumCandidates,
|
||||||
SourceLocation OpenParLoc) {}
|
SourceLocation OpenParLoc,
|
||||||
|
bool Braced) {}
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
/// Retrieve the allocator that will be used to allocate
|
/// Retrieve the allocator that will be used to allocate
|
||||||
|
@ -1210,7 +1211,8 @@ public:
|
||||||
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||||
OverloadCandidate *Candidates,
|
OverloadCandidate *Candidates,
|
||||||
unsigned NumCandidates,
|
unsigned NumCandidates,
|
||||||
SourceLocation OpenParLoc) override;
|
SourceLocation OpenParLoc,
|
||||||
|
bool Braced) override;
|
||||||
|
|
||||||
bool isResultFilteredOut(StringRef Filter, CodeCompletionResult Results) override;
|
bool isResultFilteredOut(StringRef Filter, CodeCompletionResult Results) override;
|
||||||
|
|
||||||
|
|
|
@ -12542,13 +12542,12 @@ public:
|
||||||
QualType ProduceConstructorSignatureHelp(Scope *S, QualType Type,
|
QualType ProduceConstructorSignatureHelp(Scope *S, QualType Type,
|
||||||
SourceLocation Loc,
|
SourceLocation Loc,
|
||||||
ArrayRef<Expr *> Args,
|
ArrayRef<Expr *> Args,
|
||||||
SourceLocation OpenParLoc);
|
SourceLocation OpenParLoc,
|
||||||
QualType ProduceCtorInitMemberSignatureHelp(Scope *S, Decl *ConstructorDecl,
|
bool Braced);
|
||||||
CXXScopeSpec SS,
|
QualType ProduceCtorInitMemberSignatureHelp(
|
||||||
ParsedType TemplateTypeTy,
|
Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS,
|
||||||
ArrayRef<Expr *> ArgExprs,
|
ParsedType TemplateTypeTy, ArrayRef<Expr *> ArgExprs, IdentifierInfo *II,
|
||||||
IdentifierInfo *II,
|
SourceLocation OpenParLoc, bool Braced);
|
||||||
SourceLocation OpenParLoc);
|
|
||||||
QualType ProduceTemplateArgumentSignatureHelp(
|
QualType ProduceTemplateArgumentSignatureHelp(
|
||||||
TemplateTy, ArrayRef<ParsedTemplateArgument>, SourceLocation LAngleLoc);
|
TemplateTy, ArrayRef<ParsedTemplateArgument>, SourceLocation LAngleLoc);
|
||||||
void CodeCompleteInitializer(Scope *S, Decl *D);
|
void CodeCompleteInitializer(Scope *S, Decl *D);
|
||||||
|
|
|
@ -1922,9 +1922,10 @@ namespace {
|
||||||
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||||
OverloadCandidate *Candidates,
|
OverloadCandidate *Candidates,
|
||||||
unsigned NumCandidates,
|
unsigned NumCandidates,
|
||||||
SourceLocation OpenParLoc) override {
|
SourceLocation OpenParLoc,
|
||||||
|
bool Braced) override {
|
||||||
Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,
|
Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,
|
||||||
OpenParLoc);
|
OpenParLoc, Braced);
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeCompletionAllocator &getAllocator() override {
|
CodeCompletionAllocator &getAllocator() override {
|
||||||
|
|
|
@ -2420,7 +2420,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
|
||||||
auto RunSignatureHelp = [&]() {
|
auto RunSignatureHelp = [&]() {
|
||||||
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
|
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
|
||||||
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
|
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
|
||||||
ThisDecl->getLocation(), Exprs, T.getOpenLocation());
|
ThisDecl->getLocation(), Exprs, T.getOpenLocation(),
|
||||||
|
/*Braced=*/false);
|
||||||
CalledSignatureHelp = true;
|
CalledSignatureHelp = true;
|
||||||
return PreferredType;
|
return PreferredType;
|
||||||
};
|
};
|
||||||
|
@ -2440,7 +2441,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
|
||||||
if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
|
if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
|
||||||
Actions.ProduceConstructorSignatureHelp(
|
Actions.ProduceConstructorSignatureHelp(
|
||||||
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
|
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
|
||||||
ThisDecl->getLocation(), Exprs, T.getOpenLocation());
|
ThisDecl->getLocation(), Exprs, T.getOpenLocation(),
|
||||||
|
/*Braced=*/false);
|
||||||
CalledSignatureHelp = true;
|
CalledSignatureHelp = true;
|
||||||
}
|
}
|
||||||
Actions.ActOnInitializerError(ThisDecl);
|
Actions.ActOnInitializerError(ThisDecl);
|
||||||
|
|
|
@ -3740,8 +3740,8 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
|
||||||
if (TemplateTypeTy.isInvalid())
|
if (TemplateTypeTy.isInvalid())
|
||||||
return QualType();
|
return QualType();
|
||||||
QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp(
|
QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp(
|
||||||
getCurScope(), ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II,
|
getCurScope(), ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs,
|
||||||
T.getOpenLocation());
|
II, T.getOpenLocation(), /*Braced=*/false);
|
||||||
CalledSignatureHelp = true;
|
CalledSignatureHelp = true;
|
||||||
return PreferredType;
|
return PreferredType;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1878,7 +1878,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
|
||||||
if (TypeRep)
|
if (TypeRep)
|
||||||
PreferredType = Actions.ProduceConstructorSignatureHelp(
|
PreferredType = Actions.ProduceConstructorSignatureHelp(
|
||||||
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
|
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
|
||||||
DS.getEndLoc(), Exprs, T.getOpenLocation());
|
DS.getEndLoc(), Exprs, T.getOpenLocation(), /*Braced=*/false);
|
||||||
CalledSignatureHelp = true;
|
CalledSignatureHelp = true;
|
||||||
return PreferredType;
|
return PreferredType;
|
||||||
};
|
};
|
||||||
|
@ -3168,7 +3168,8 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
|
||||||
if (TypeRep)
|
if (TypeRep)
|
||||||
PreferredType = Actions.ProduceConstructorSignatureHelp(
|
PreferredType = Actions.ProduceConstructorSignatureHelp(
|
||||||
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
|
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
|
||||||
DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
|
DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen,
|
||||||
|
/*Braced=*/false);
|
||||||
CalledSignatureHelp = true;
|
CalledSignatureHelp = true;
|
||||||
return PreferredType;
|
return PreferredType;
|
||||||
};
|
};
|
||||||
|
|
|
@ -459,12 +459,22 @@ ExprResult Parser::ParseBraceInitializer() {
|
||||||
Actions, EnterExpressionEvaluationContext::InitList);
|
Actions, EnterExpressionEvaluationContext::InitList);
|
||||||
|
|
||||||
bool InitExprsOk = true;
|
bool InitExprsOk = true;
|
||||||
DesignatorCompletionInfo DesignatorCompletion{
|
QualType LikelyType = PreferredType.get(T.getOpenLocation());
|
||||||
InitExprs,
|
DesignatorCompletionInfo DesignatorCompletion{InitExprs, LikelyType};
|
||||||
PreferredType.get(T.getOpenLocation()),
|
bool CalledSignatureHelp = false;
|
||||||
|
auto RunSignatureHelp = [&] {
|
||||||
|
QualType PreferredType;
|
||||||
|
if (!LikelyType.isNull())
|
||||||
|
PreferredType = Actions.ProduceConstructorSignatureHelp(
|
||||||
|
getCurScope(), LikelyType->getCanonicalTypeInternal(),
|
||||||
|
T.getOpenLocation(), InitExprs, T.getOpenLocation(), /*Braced=*/true);
|
||||||
|
CalledSignatureHelp = true;
|
||||||
|
return PreferredType;
|
||||||
};
|
};
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
|
||||||
|
|
||||||
// Handle Microsoft __if_exists/if_not_exists if necessary.
|
// Handle Microsoft __if_exists/if_not_exists if necessary.
|
||||||
if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
|
if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
|
||||||
Tok.is(tok::kw___if_not_exists))) {
|
Tok.is(tok::kw___if_not_exists))) {
|
||||||
|
|
|
@ -471,7 +471,7 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
|
||||||
auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
|
auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
|
||||||
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
|
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
|
||||||
getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
|
getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
|
||||||
OmpPrivParm->getLocation(), Exprs, LParLoc);
|
OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);
|
||||||
CalledSignatureHelp = true;
|
CalledSignatureHelp = true;
|
||||||
return PreferredType;
|
return PreferredType;
|
||||||
};
|
};
|
||||||
|
|
|
@ -656,7 +656,7 @@ static std::string getOverloadAsString(const CodeCompletionString &CCS) {
|
||||||
|
|
||||||
void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
|
void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
|
||||||
Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates,
|
Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates,
|
||||||
unsigned NumCandidates, SourceLocation OpenParLoc) {
|
unsigned NumCandidates, SourceLocation OpenParLoc, bool Braced) {
|
||||||
OS << "OPENING_PAREN_LOC: ";
|
OS << "OPENING_PAREN_LOC: ";
|
||||||
OpenParLoc.print(OS, SemaRef.getSourceManager());
|
OpenParLoc.print(OS, SemaRef.getSourceManager());
|
||||||
OS << "\n";
|
OS << "\n";
|
||||||
|
@ -664,7 +664,7 @@ void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
|
||||||
for (unsigned I = 0; I != NumCandidates; ++I) {
|
for (unsigned I = 0; I != NumCandidates; ++I) {
|
||||||
if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(
|
if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(
|
||||||
CurrentArg, SemaRef, getAllocator(), CCTUInfo,
|
CurrentArg, SemaRef, getAllocator(), CCTUInfo,
|
||||||
includeBriefComments())) {
|
includeBriefComments(), Braced)) {
|
||||||
OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
|
OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3833,7 +3833,8 @@ static CodeCompletionString *createTemplateSignatureString(
|
||||||
CodeCompletionString *
|
CodeCompletionString *
|
||||||
CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
|
CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
|
||||||
unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
|
unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
|
||||||
CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
|
CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments,
|
||||||
|
bool Braced) const {
|
||||||
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
|
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
|
||||||
// Show signatures of constructors as they are declared:
|
// Show signatures of constructors as they are declared:
|
||||||
// vector(int n) rather than vector<string>(int n)
|
// vector(int n) rather than vector<string>(int n)
|
||||||
|
@ -3857,9 +3858,11 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
|
||||||
const FunctionType *FT = getFunctionType();
|
const FunctionType *FT = getFunctionType();
|
||||||
Result.AddResultTypeChunk(Result.getAllocator().CopyString(
|
Result.AddResultTypeChunk(Result.getAllocator().CopyString(
|
||||||
FT->getReturnType().getAsString(Policy)));
|
FT->getReturnType().getAsString(Policy)));
|
||||||
Result.AddChunk(CodeCompletionString::CK_LeftParen);
|
Result.AddChunk(Braced ? CodeCompletionString::CK_LeftBrace
|
||||||
|
: CodeCompletionString::CK_LeftParen);
|
||||||
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
|
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
|
||||||
Result.AddChunk(CodeCompletionString::CK_RightParen);
|
Result.AddChunk(Braced ? CodeCompletionString::CK_RightBrace
|
||||||
|
: CodeCompletionString::CK_RightParen);
|
||||||
return Result.TakeString();
|
return Result.TakeString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3879,10 +3882,12 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
|
||||||
Proto->getReturnType().getAsString(Policy)));
|
Proto->getReturnType().getAsString(Policy)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result.AddChunk(CodeCompletionString::CK_LeftParen);
|
Result.AddChunk(Braced ? CodeCompletionString::CK_LeftBrace
|
||||||
|
: CodeCompletionString::CK_LeftParen);
|
||||||
AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
|
AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
|
||||||
CurrentArg);
|
CurrentArg);
|
||||||
Result.AddChunk(CodeCompletionString::CK_RightParen);
|
Result.AddChunk(Braced ? CodeCompletionString::CK_RightBrace
|
||||||
|
: CodeCompletionString::CK_RightParen);
|
||||||
|
|
||||||
return Result.TakeString();
|
return Result.TakeString();
|
||||||
}
|
}
|
||||||
|
@ -5940,12 +5945,14 @@ static QualType getParamType(Sema &SemaRef,
|
||||||
|
|
||||||
static QualType
|
static QualType
|
||||||
ProduceSignatureHelp(Sema &SemaRef, MutableArrayRef<ResultCandidate> Candidates,
|
ProduceSignatureHelp(Sema &SemaRef, MutableArrayRef<ResultCandidate> Candidates,
|
||||||
unsigned CurrentArg, SourceLocation OpenParLoc) {
|
unsigned CurrentArg, SourceLocation OpenParLoc,
|
||||||
|
bool Braced) {
|
||||||
if (Candidates.empty())
|
if (Candidates.empty())
|
||||||
return QualType();
|
return QualType();
|
||||||
if (SemaRef.getPreprocessor().isCodeCompletionReached())
|
if (SemaRef.getPreprocessor().isCodeCompletionReached())
|
||||||
SemaRef.CodeCompleter->ProcessOverloadCandidates(
|
SemaRef.CodeCompleter->ProcessOverloadCandidates(
|
||||||
SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
|
SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc,
|
||||||
|
Braced);
|
||||||
return getParamType(SemaRef, Candidates, CurrentArg);
|
return getParamType(SemaRef, Candidates, CurrentArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6047,15 +6054,16 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size());
|
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size());
|
||||||
QualType ParamType =
|
QualType ParamType = ProduceSignatureHelp(*this, Results, Args.size(),
|
||||||
ProduceSignatureHelp(*this, Results, Args.size(), OpenParLoc);
|
OpenParLoc, /*Braced=*/false);
|
||||||
return !CandidateSet.empty() ? ParamType : QualType();
|
return !CandidateSet.empty() ? ParamType : QualType();
|
||||||
}
|
}
|
||||||
|
|
||||||
QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
|
QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
|
||||||
SourceLocation Loc,
|
SourceLocation Loc,
|
||||||
ArrayRef<Expr *> Args,
|
ArrayRef<Expr *> Args,
|
||||||
SourceLocation OpenParLoc) {
|
SourceLocation OpenParLoc,
|
||||||
|
bool Braced) {
|
||||||
if (!CodeCompleter)
|
if (!CodeCompleter)
|
||||||
return QualType();
|
return QualType();
|
||||||
|
|
||||||
|
@ -6064,6 +6072,10 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
|
||||||
isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
|
isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
|
||||||
if (!RD)
|
if (!RD)
|
||||||
return Type;
|
return Type;
|
||||||
|
// FIXME: we don't support signature help for aggregate initialization, so
|
||||||
|
// don't offer a confusing partial list (e.g. the copy constructor).
|
||||||
|
if (Braced && RD->isAggregate())
|
||||||
|
return Type;
|
||||||
|
|
||||||
// FIXME: Provide support for member initializers.
|
// FIXME: Provide support for member initializers.
|
||||||
// FIXME: Provide support for variadic template constructors.
|
// FIXME: Provide support for variadic template constructors.
|
||||||
|
@ -6072,12 +6084,20 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
|
||||||
|
|
||||||
for (NamedDecl *C : LookupConstructors(RD)) {
|
for (NamedDecl *C : LookupConstructors(RD)) {
|
||||||
if (auto *FD = dyn_cast<FunctionDecl>(C)) {
|
if (auto *FD = dyn_cast<FunctionDecl>(C)) {
|
||||||
|
// FIXME: we can't yet provide correct signature help for initializer
|
||||||
|
// list constructors, so skip them entirely.
|
||||||
|
if (Braced && LangOpts.CPlusPlus && isInitListConstructor(FD))
|
||||||
|
continue;
|
||||||
AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
|
AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
|
||||||
CandidateSet,
|
CandidateSet,
|
||||||
/*SuppressUserConversions=*/false,
|
/*SuppressUserConversions=*/false,
|
||||||
/*PartialOverloading=*/true,
|
/*PartialOverloading=*/true,
|
||||||
/*AllowExplicit*/ true);
|
/*AllowExplicit*/ true);
|
||||||
} else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
|
} else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
|
||||||
|
if (Braced && LangOpts.CPlusPlus &&
|
||||||
|
isInitListConstructor(FTD->getTemplatedDecl()))
|
||||||
|
continue;
|
||||||
|
|
||||||
AddTemplateOverloadCandidate(
|
AddTemplateOverloadCandidate(
|
||||||
FTD, DeclAccessPair::make(FTD, C->getAccess()),
|
FTD, DeclAccessPair::make(FTD, C->getAccess()),
|
||||||
/*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
|
/*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
|
||||||
|
@ -6088,12 +6108,13 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
|
||||||
|
|
||||||
SmallVector<ResultCandidate, 8> Results;
|
SmallVector<ResultCandidate, 8> Results;
|
||||||
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size());
|
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc, Args.size());
|
||||||
return ProduceSignatureHelp(*this, Results, Args.size(), OpenParLoc);
|
return ProduceSignatureHelp(*this, Results, Args.size(), OpenParLoc, Braced);
|
||||||
}
|
}
|
||||||
|
|
||||||
QualType Sema::ProduceCtorInitMemberSignatureHelp(
|
QualType Sema::ProduceCtorInitMemberSignatureHelp(
|
||||||
Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
|
Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
|
||||||
ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
|
ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc,
|
||||||
|
bool Braced) {
|
||||||
if (!CodeCompleter)
|
if (!CodeCompleter)
|
||||||
return QualType();
|
return QualType();
|
||||||
|
|
||||||
|
@ -6106,7 +6127,7 @@ QualType Sema::ProduceCtorInitMemberSignatureHelp(
|
||||||
Constructor->getParent(), SS, TemplateTypeTy, II))
|
Constructor->getParent(), SS, TemplateTypeTy, II))
|
||||||
return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
|
return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
|
||||||
MemberDecl->getLocation(), ArgExprs,
|
MemberDecl->getLocation(), ArgExprs,
|
||||||
OpenParLoc);
|
OpenParLoc, Braced);
|
||||||
return QualType();
|
return QualType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6159,7 +6180,8 @@ QualType Sema::ProduceTemplateArgumentSignatureHelp(
|
||||||
if (const auto *TD = llvm::dyn_cast<TemplateDecl>(ND))
|
if (const auto *TD = llvm::dyn_cast<TemplateDecl>(ND))
|
||||||
Consider(TD);
|
Consider(TD);
|
||||||
}
|
}
|
||||||
return ProduceSignatureHelp(*this, Results, Args.size(), LAngleLoc);
|
return ProduceSignatureHelp(*this, Results, Args.size(), LAngleLoc,
|
||||||
|
/*Braced=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QualType getDesignatedType(QualType BaseType, const Designation &Desig) {
|
static QualType getDesignatedType(QualType BaseType, const Designation &Desig) {
|
||||||
|
|
|
@ -15,3 +15,40 @@ void foo() {
|
||||||
// CHECK-CC2: OVERLOAD: Foo(<#const Foo<int *> &#>)
|
// CHECK-CC2: OVERLOAD: Foo(<#const Foo<int *> &#>)
|
||||||
// CHECK-CC2: OVERLOAD: Foo(<#Foo<int *> &&#>
|
// CHECK-CC2: OVERLOAD: Foo(<#Foo<int *> &&#>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <typename> struct initializer_list {};
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
struct Bar {
|
||||||
|
// CHECK-BRACED: OVERLOAD: Bar{<#int#>}
|
||||||
|
Bar(int);
|
||||||
|
// CHECK-BRACED: OVERLOAD: Bar{<#double#>, double}
|
||||||
|
Bar(double, double);
|
||||||
|
// FIXME: no support for init-list constructors yet.
|
||||||
|
// CHECK-BRACED-NOT: OVERLOAD: {{.*}}char
|
||||||
|
Bar(std::initializer_list<char> C);
|
||||||
|
// CHECK-BRACED: OVERLOAD: Bar{<#const Bar &#>}
|
||||||
|
// CHECK-BRACED: OVERLOAD: Bar{<#T *Pointer#>}
|
||||||
|
template <typename T> Bar(T *Pointer);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto b1 = Bar{};
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:36:15 %s | FileCheck -check-prefix=CHECK-BRACED %s
|
||||||
|
Bar b2{};
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:38:8 %s | FileCheck -check-prefix=CHECK-BRACED %s
|
||||||
|
static int consumeBar(Bar) { return 0; }
|
||||||
|
int b3 = consumeBar({});
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:41:22 %s | FileCheck -check-prefix=CHECK-BRACED %s
|
||||||
|
|
||||||
|
struct Aggregate {
|
||||||
|
// FIXME: no support for aggregates yet.
|
||||||
|
// CHECK-AGGREGATE-NOT: OVERLOAD: Aggregate{<#const Aggregate &#>}
|
||||||
|
// CHECK-AGGREGATE-NOT: OVERLOAD: {{.*}}first
|
||||||
|
int first;
|
||||||
|
int second;
|
||||||
|
};
|
||||||
|
|
||||||
|
Aggregate a{};
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:52:13 %s | FileCheck -check-prefix=CHECK-AGGREGATE %s
|
||||||
|
|
||||||
|
|
|
@ -656,14 +656,15 @@ namespace {
|
||||||
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||||
OverloadCandidate *Candidates,
|
OverloadCandidate *Candidates,
|
||||||
unsigned NumCandidates,
|
unsigned NumCandidates,
|
||||||
SourceLocation OpenParLoc) override {
|
SourceLocation OpenParLoc,
|
||||||
|
bool Braced) override {
|
||||||
StoredResults.reserve(StoredResults.size() + NumCandidates);
|
StoredResults.reserve(StoredResults.size() + NumCandidates);
|
||||||
for (unsigned I = 0; I != NumCandidates; ++I) {
|
for (unsigned I = 0; I != NumCandidates; ++I) {
|
||||||
CodeCompletionString *StoredCompletion
|
CodeCompletionString *StoredCompletion =
|
||||||
= Candidates[I].CreateSignatureString(CurrentArg, S, getAllocator(),
|
Candidates[I].CreateSignatureString(CurrentArg, S, getAllocator(),
|
||||||
getCodeCompletionTUInfo(),
|
getCodeCompletionTUInfo(),
|
||||||
includeBriefComments());
|
includeBriefComments(), Braced);
|
||||||
|
|
||||||
CXCompletionResult R;
|
CXCompletionResult R;
|
||||||
R.CursorKind = CXCursor_OverloadCandidate;
|
R.CursorKind = CXCursor_OverloadCandidate;
|
||||||
R.CompletionString = StoredCompletion;
|
R.CompletionString = StoredCompletion;
|
||||||
|
|
|
@ -995,7 +995,8 @@ public:
|
||||||
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||||
OverloadCandidate *Candidates,
|
OverloadCandidate *Candidates,
|
||||||
unsigned NumCandidates,
|
unsigned NumCandidates,
|
||||||
SourceLocation OpenParLoc) override {
|
SourceLocation OpenParLoc,
|
||||||
|
bool Braced) override {
|
||||||
// At the moment we don't filter out any overloaded candidates.
|
// At the moment we don't filter out any overloaded candidates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue