From 86d802e03a267af79663990c39865c67e0645238 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 23 Sep 2009 00:34:09 +0000 Subject: [PATCH] Print the results of code-completion for overloading by displaying the signature of the function with the current parameter highlighted as a placeholder. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82593 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/CodeCompleteConsumer.h | 5 ++ lib/Sema/CodeCompleteConsumer.cpp | 24 ++------- lib/Sema/SemaCodeComplete.cpp | 62 +++++++++++++++++++++++ test/CodeCompletion/call.cpp | 10 ++-- 4 files changed, 76 insertions(+), 25 deletions(-) diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 058012cd12..d2f509df7b 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -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. diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index f1b475a6df..a3d4d92fc3 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -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( - 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; } } diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 754d505bc0..f879dae696 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -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(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; diff --git a/test/CodeCompletion/call.cpp b/test/CodeCompletion/call.cpp index 9a6f578abc..448b8ebb6e 100644 --- a/test/CodeCompletion/call.cpp +++ b/test/CodeCompletion/call.cpp @@ -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 } -- 2.40.0