diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-18 22:15:54 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-18 22:15:54 +0000 |
commit | e6e0361984b077d205e9a45d64257d41d2c788c8 (patch) | |
tree | 063c1f7dd2367a4856d73c78919578537d6dea87 /lib/Sema/CodeCompleteConsumer.cpp | |
parent | 1131014a6e0302f8040531e227b550230703f613 (diff) |
Introduce code completion strings, which describe how to *use* the
results of code completion, e.g., by providing function call syntax
with placeholders for each of the parameters.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82293 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/CodeCompleteConsumer.cpp')
-rw-r--r-- | lib/Sema/CodeCompleteConsumer.cpp | 133 |
1 files changed, 131 insertions, 2 deletions
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index d82047d912..9bf9e15253 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -19,9 +19,75 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> -#include <string.h> +#include <cstring> +#include <functional> using namespace clang; +//===----------------------------------------------------------------------===// +// Code completion string implementation +//===----------------------------------------------------------------------===// +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateText(const char *Text) { + Chunk Result; + Result.Kind = CK_Text; + char *New = new char [std::strlen(Text) + 1]; + std::strcpy(New, Text); + Result.Text = New; + return Result; +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateOptional( + std::auto_ptr<CodeCompletionString> Optional) { + Chunk Result; + Result.Kind = CK_Optional; + Result.Optional = Optional.release(); + return Result; +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) { + Chunk Result; + Result.Kind = CK_Placeholder; + char *New = new char [std::strlen(Placeholder) + 1]; + std::strcpy(New, Placeholder); + Result.Placeholder = New; + return Result; +} + +void +CodeCompletionString::Chunk::Destroy() { + switch (Kind) { + case CK_Text: delete [] Text; break; + case CK_Optional: delete Optional; break; + case CK_Placeholder: delete [] Placeholder; break; + } +} + +CodeCompletionString::~CodeCompletionString() { + std::for_each(Chunks.begin(), Chunks.end(), + std::mem_fun_ref(&Chunk::Destroy)); +} + +std::string CodeCompletionString::getAsString() const { + std::string Result; + llvm::raw_string_ostream OS(Result); + + for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { + switch (C->Kind) { + case CK_Text: OS << C->Text; break; + case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; + case CK_Placeholder: OS << "<#" << C->Placeholder << "#>"; break; + } + } + + return Result; +} + +//===----------------------------------------------------------------------===// +// Code completion consumer implementation +//===----------------------------------------------------------------------===// + CodeCompleteConsumer::CodeCompleteConsumer(Sema &S) : SemaRef(S) { SemaRef.setCodeCompleteConsumer(this); } @@ -180,7 +246,7 @@ void CodeCompleteConsumer::CodeCompleteOperatorName(Scope *S) { // Add the names of overloadable operators. #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ - if (strcmp(Spelling, "?")) \ + if (std::strcmp(Spelling, "?")) \ Results.MaybeAddResult(Result(Spelling, 0)); #include "clang/Basic/OperatorKinds.def" @@ -663,6 +729,64 @@ void CodeCompleteConsumer::AddTypeSpecifierResults(unsigned Rank, } } +/// \brief Add function parameter chunks to the given code completion string. +static void AddFunctionParameterChunks(ASTContext &Context, + FunctionDecl *Function, + CodeCompletionString *Result) { + CodeCompletionString *CCStr = Result; + + for (unsigned P = 0, N = Function->getNumParams(); P != N; ++P) { + ParmVarDecl *Param = Function->getParamDecl(P); + + if (Param->hasDefaultArg()) { + // When we see an optional default argument, put that argument and + // the remaining default arguments into a new, optional string. + CodeCompletionString *Opt = new CodeCompletionString; + CCStr->AddOptionalChunk(std::auto_ptr<CodeCompletionString>(Opt)); + CCStr = Opt; + } + + if (P != 0) + CCStr->AddTextChunk(", "); + + // Format the placeholder string. + std::string PlaceholderStr; + if (Param->getIdentifier()) + PlaceholderStr = Param->getIdentifier()->getName(); + + Param->getType().getAsStringInternal(PlaceholderStr, + Context.PrintingPolicy); + + // Add the placeholder string. + CCStr->AddPlaceholderChunk(PlaceholderStr.c_str()); + } +} + +/// \brief If possible, create a new code completion string for the given +/// result. +/// +/// \returns Either a new, heap-allocated code completion string describing +/// how to use this result, or NULL to indicate that the string or name of the +/// result is all that is needed. +CodeCompletionString * +CodeCompleteConsumer::CreateCodeCompletionString(Result R) { + if (R.Kind != Result::RK_Declaration) + return 0; + + NamedDecl *ND = R.Declaration; + + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { + CodeCompletionString *Result = new CodeCompletionString; + Result->AddTextChunk(Function->getNameAsString().c_str()); + Result->AddTextChunk("("); + AddFunctionParameterChunks(getSema().Context, Function, Result); + Result->AddTextChunk(")"); + return Result; + } + + return 0; +} + void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results, unsigned NumResults) { @@ -677,6 +801,11 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results, << Results[I].Rank; if (Results[I].Hidden) OS << " (Hidden)"; + if (CodeCompletionString *CCS = CreateCodeCompletionString(Results[I])) { + OS << " : " << CCS->getAsString(); + delete CCS; + } + OS << '\n'; break; |