mirror of https://github.com/microsoft/clang.git
[CodeComplete] Report location of opening parens for signature help
Summary: Used in clangd. Reviewers: sammccall Reviewed By: sammccall Subscribers: ioeric, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D51436 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@341063 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1e76ac204b
commit
8cd8ed88f9
|
@ -1114,9 +1114,13 @@ public:
|
|||
/// \param Candidates an array of overload candidates.
|
||||
///
|
||||
/// \param NumCandidates the number of overload candidates
|
||||
///
|
||||
/// \param OpenParLoc location of the opening parenthesis of the argument
|
||||
/// list.
|
||||
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||
OverloadCandidate *Candidates,
|
||||
unsigned NumCandidates) {}
|
||||
unsigned NumCandidates,
|
||||
SourceLocation OpenParLoc) {}
|
||||
//@}
|
||||
|
||||
/// Retrieve the allocator that will be used to allocate
|
||||
|
@ -1166,7 +1170,8 @@ public:
|
|||
|
||||
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||
OverloadCandidate *Candidates,
|
||||
unsigned NumCandidates) override;
|
||||
unsigned NumCandidates,
|
||||
SourceLocation OpenParLoc) override;
|
||||
|
||||
bool isResultFilteredOut(StringRef Filter, CodeCompletionResult Results) override;
|
||||
|
||||
|
|
|
@ -10230,9 +10230,11 @@ public:
|
|||
const VirtSpecifiers *VS = nullptr);
|
||||
void CodeCompleteBracketDeclarator(Scope *S);
|
||||
void CodeCompleteCase(Scope *S);
|
||||
void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args);
|
||||
void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args,
|
||||
SourceLocation OpenParLoc);
|
||||
void CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
|
||||
ArrayRef<Expr *> Args);
|
||||
ArrayRef<Expr *> Args,
|
||||
SourceLocation OpenParLoc);
|
||||
void CodeCompleteInitializer(Scope *S, Decl *D);
|
||||
void CodeCompleteReturn(Scope *S);
|
||||
void CodeCompleteAfterIf(Scope *S);
|
||||
|
|
|
@ -1911,8 +1911,10 @@ namespace {
|
|||
|
||||
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||
OverloadCandidate *Candidates,
|
||||
unsigned NumCandidates) override {
|
||||
Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
|
||||
unsigned NumCandidates,
|
||||
SourceLocation OpenParLoc) override {
|
||||
Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,
|
||||
OpenParLoc);
|
||||
}
|
||||
|
||||
CodeCompletionAllocator &getAllocator() override {
|
||||
|
|
|
@ -2304,7 +2304,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
|
|||
auto ConstructorCompleter = [&, ThisVarDecl] {
|
||||
Actions.CodeCompleteConstructor(
|
||||
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
|
||||
ThisDecl->getLocation(), Exprs);
|
||||
ThisDecl->getLocation(), Exprs, T.getOpenLocation());
|
||||
};
|
||||
if (ThisVarDecl) {
|
||||
// ParseExpressionList can sometimes succeed even when ThisDecl is not
|
||||
|
|
|
@ -1650,7 +1650,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
|||
CommaLocsTy CommaLocs;
|
||||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteCall(getCurScope(), LHS.get(), None);
|
||||
Actions.CodeCompleteCall(getCurScope(), LHS.get(), None,
|
||||
PT.getOpenLocation());
|
||||
cutOffParsing();
|
||||
return ExprError();
|
||||
}
|
||||
|
@ -1658,8 +1659,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
|||
if (OpKind == tok::l_paren || !LHS.isInvalid()) {
|
||||
if (Tok.isNot(tok::r_paren)) {
|
||||
if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
|
||||
Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
|
||||
})) {
|
||||
Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs,
|
||||
PT.getOpenLocation());
|
||||
})) {
|
||||
(void)Actions.CorrectDelayedTyposInExpr(LHS);
|
||||
LHS = ExprError();
|
||||
} else if (LHS.isInvalid()) {
|
||||
|
|
|
@ -1687,7 +1687,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
|
|||
if (ParseExpressionList(Exprs, CommaLocs, [&] {
|
||||
Actions.CodeCompleteConstructor(
|
||||
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
|
||||
DS.getEndLoc(), Exprs);
|
||||
DS.getEndLoc(), Exprs, T.getOpenLocation());
|
||||
})) {
|
||||
SkipUntil(tok::r_paren, StopAtSemi);
|
||||
return ExprError();
|
||||
|
@ -2821,7 +2821,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
|
|||
DeclaratorInfo).get();
|
||||
Actions.CodeCompleteConstructor(
|
||||
getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
|
||||
DeclaratorInfo.getEndLoc(), ConstructorArgs);
|
||||
DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
|
||||
})) {
|
||||
SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch);
|
||||
return ExprError();
|
||||
|
|
|
@ -415,11 +415,14 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
|
|||
ExprVector Exprs;
|
||||
CommaLocsTy CommaLocs;
|
||||
|
||||
if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] {
|
||||
Actions.CodeCompleteConstructor(
|
||||
getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
|
||||
OmpPrivParm->getLocation(), Exprs);
|
||||
})) {
|
||||
SourceLocation LParLoc = T.getOpenLocation();
|
||||
if (ParseExpressionList(
|
||||
Exprs, CommaLocs, [this, OmpPrivParm, LParLoc, &Exprs] {
|
||||
Actions.CodeCompleteConstructor(
|
||||
getCurScope(),
|
||||
OmpPrivParm->getType()->getCanonicalTypeInternal(),
|
||||
OmpPrivParm->getLocation(), Exprs, LParLoc);
|
||||
})) {
|
||||
Actions.ActOnInitializerError(OmpPrivParm);
|
||||
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
|
||||
} else {
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
@ -29,6 +29,7 @@
|
|||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
@ -624,16 +625,17 @@ static std::string getOverloadAsString(const CodeCompletionString &CCS) {
|
|||
return OS.str();
|
||||
}
|
||||
|
||||
void
|
||||
PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
|
||||
unsigned CurrentArg,
|
||||
OverloadCandidate *Candidates,
|
||||
unsigned NumCandidates) {
|
||||
void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
|
||||
Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates,
|
||||
unsigned NumCandidates, SourceLocation OpenParLoc) {
|
||||
OS << "OPENING_PAREN_LOC: ";
|
||||
OpenParLoc.print(OS, SemaRef.getSourceManager());
|
||||
OS << "\n";
|
||||
|
||||
for (unsigned I = 0; I != NumCandidates; ++I) {
|
||||
if (CodeCompletionString *CCS
|
||||
= Candidates[I].CreateSignatureString(CurrentArg, SemaRef,
|
||||
getAllocator(), CCTUInfo,
|
||||
includeBriefComments())) {
|
||||
if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(
|
||||
CurrentArg, SemaRef, getAllocator(), CCTUInfo,
|
||||
includeBriefComments())) {
|
||||
OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4435,10 +4435,11 @@ static QualType getParamType(Sema &SemaRef,
|
|||
return ParamType;
|
||||
}
|
||||
|
||||
static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
|
||||
MutableArrayRef<ResultCandidate> Candidates,
|
||||
unsigned CurrentArg,
|
||||
bool CompleteExpressionWithCurrentArg = true) {
|
||||
static void
|
||||
CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
|
||||
MutableArrayRef<ResultCandidate> Candidates,
|
||||
unsigned CurrentArg, SourceLocation OpenParLoc,
|
||||
bool CompleteExpressionWithCurrentArg = true) {
|
||||
QualType ParamType;
|
||||
if (CompleteExpressionWithCurrentArg)
|
||||
ParamType = getParamType(SemaRef, Candidates, CurrentArg);
|
||||
|
@ -4449,12 +4450,12 @@ static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
|
|||
SemaRef.CodeCompleteExpression(S, ParamType);
|
||||
|
||||
if (!Candidates.empty())
|
||||
SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
|
||||
Candidates.data(),
|
||||
Candidates.size());
|
||||
SemaRef.CodeCompleter->ProcessOverloadCandidates(
|
||||
SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
|
||||
void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args,
|
||||
SourceLocation OpenParLoc) {
|
||||
if (!CodeCompleter)
|
||||
return;
|
||||
|
||||
|
@ -4552,12 +4553,13 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
|
|||
}
|
||||
|
||||
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
|
||||
CodeCompleteOverloadResults(*this, S, Results, Args.size(),
|
||||
CodeCompleteOverloadResults(*this, S, Results, Args.size(), OpenParLoc,
|
||||
!CandidateSet.empty());
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
|
||||
ArrayRef<Expr *> Args) {
|
||||
ArrayRef<Expr *> Args,
|
||||
SourceLocation OpenParLoc) {
|
||||
if (!CodeCompleter)
|
||||
return;
|
||||
|
||||
|
@ -4592,7 +4594,7 @@ void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
|
|||
|
||||
SmallVector<ResultCandidate, 8> Results;
|
||||
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
|
||||
CodeCompleteOverloadResults(*this, S, Results, Args.size());
|
||||
CodeCompleteOverloadResults(*this, S, Results, Args.size(), OpenParLoc);
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
void foo(int a, int b);
|
||||
void foo(int a, int b, int c);
|
||||
|
||||
void test() {
|
||||
foo(10, );
|
||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:10 %s -o - \
|
||||
// RUN: | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:5:6
|
||||
|
||||
#define FOO foo(
|
||||
FOO 10, );
|
||||
#undef FOO
|
||||
// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:11:10 %s -o - \
|
||||
// RUN: | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// CHECK-CC2: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:11:3
|
||||
|
||||
struct Foo {
|
||||
Foo(int a, int b);
|
||||
Foo(int a, int b, int c);
|
||||
};
|
||||
Foo a(10, );
|
||||
// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:21:12 %s -o - \
|
||||
// RUN: | FileCheck -check-prefix=CHECK-CC3 %s
|
||||
// CHECK-CC3: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:21:8
|
||||
Foo(10, );
|
||||
// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:25:10 %s -o - \
|
||||
// RUN: | FileCheck -check-prefix=CHECK-CC4 %s
|
||||
// CHECK-CC4: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:25:6
|
||||
new Foo(10, );
|
||||
// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:29:15 %s -o - \
|
||||
// RUN: | FileCheck -check-prefix=CHECK-CC5 %s
|
||||
// CHECK-CC5: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:29:10
|
||||
}
|
|
@ -653,7 +653,8 @@ namespace {
|
|||
|
||||
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||
OverloadCandidate *Candidates,
|
||||
unsigned NumCandidates) override {
|
||||
unsigned NumCandidates,
|
||||
SourceLocation OpenParLoc) override {
|
||||
StoredResults.reserve(StoredResults.size() + NumCandidates);
|
||||
for (unsigned I = 0; I != NumCandidates; ++I) {
|
||||
CodeCompletionString *StoredCompletion
|
||||
|
|
Loading…
Reference in New Issue