Print the results of code-completion for overloading by displaying the

signature of the function with the current parameter highlighted as a
placeholder.

llvm-svn: 82593
This commit is contained in:
Douglas Gregor 2009-09-23 00:34:09 +00:00
parent 05f477c177
commit f0f51985a1
4 changed files with 76 additions and 25 deletions

View File

@ -273,6 +273,11 @@ public:
/// \brief Retrieve the function type of the entity, regardless of how the
/// function is stored.
const FunctionType *getFunctionType() const;
/// \brief Create a new code-completion string that describes the function
/// signature of this overload candidate.
CodeCompletionString *CreateSignatureString(unsigned CurrentArg,
Sema &S) const;
};
/// \brief Deregisters and destroys this code-completion consumer.

View File

@ -169,26 +169,10 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates) {
for (unsigned I = 0; I != NumCandidates; ++I) {
std::string ArgString;
QualType ArgType;
if (FunctionDecl *Function = Candidates[I].getFunction()) {
if (CurrentArg < Function->getNumParams()) {
ArgString = Function->getParamDecl(CurrentArg)->getNameAsString();
ArgType = Function->getParamDecl(CurrentArg)->getOriginalType();
}
} else if (const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(
Candidates[I].getFunctionType())) {
if (CurrentArg < Proto->getNumArgs())
ArgType = Proto->getArgType(CurrentArg);
}
if (ArgType.isNull())
OS << "...\n"; // We have no prototype or we're matching an ellipsis.
else {
ArgType.getAsStringInternal(ArgString, SemaRef.Context.PrintingPolicy);
OS << ArgString << "\n";
if (CodeCompletionString *CCS
= Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
OS << CCS->getAsString() << "\n";
delete CCS;
}
}

View File

@ -869,6 +869,68 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
return 0;
}
CodeCompletionString *
CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
unsigned CurrentArg,
Sema &S) const {
CodeCompletionString *Result = new CodeCompletionString;
FunctionDecl *FDecl = getFunction();
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(getFunctionType());
if (!FDecl && !Proto) {
// Function without a prototype. Just give the return type and a
// highlighted ellipsis.
const FunctionType *FT = getFunctionType();
Result->AddTextChunk(
FT->getResultType().getAsString(S.Context.PrintingPolicy).c_str());
Result->AddTextChunk("(");
Result->AddPlaceholderChunk("...");
Result->AddTextChunk("(");
return Result;
}
if (FDecl)
Result->AddTextChunk(FDecl->getNameAsString().c_str());
else
Result->AddTextChunk(
Proto->getResultType().getAsString(S.Context.PrintingPolicy).c_str());
Result->AddTextChunk("(");
unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
for (unsigned I = 0; I != NumParams; ++I) {
if (I)
Result->AddTextChunk(", ");
std::string ArgString;
QualType ArgType;
if (FDecl) {
ArgString = FDecl->getParamDecl(I)->getNameAsString();
ArgType = FDecl->getParamDecl(I)->getOriginalType();
} else {
ArgType = Proto->getArgType(I);
}
ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy);
if (I == CurrentArg)
Result->AddPlaceholderChunk(ArgString.c_str());
else
Result->AddTextChunk(ArgString.c_str());
}
if (Proto && Proto->isVariadic()) {
Result->AddTextChunk(", ");
if (CurrentArg < NumParams)
Result->AddTextChunk("...");
else
Result->AddPlaceholderChunk("...");
}
Result->AddTextChunk(")");
return Result;
}
namespace {
struct SortCodeCompleteResult {
typedef CodeCompleteConsumer::Result Result;

View File

@ -18,11 +18,11 @@ void f();
void test() {
f(Y(), 0, 0);
// RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CC1 %s &&
// CHECK-CC1: int ZZ
// CHECK-NEXT-CC1: int j
// CHECK-NEXT-CC1: float y
// CHECK-CC1: f(struct N::Y y, <#int ZZ#>)
// CHECK-NEXT-CC1: f(int i, <#int j#>, int k)
// CHECK-NEXT-CC1: f(float x, <#float y#>)
// RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:13 %s -o - | FileCheck -check-prefix=CC2 %s &&
// FIXME: two ellipses are showing up when they shouldn't
// CHECK-CC2: int k
// FIXME: two extra overloads are showing up!
// CHECK-CC2: f(int i, int j, <#int k#>)
// RUN: true
}