aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/CodeCompleteConsumer.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-09-18 22:15:54 +0000
committerDouglas Gregor <dgregor@apple.com>2009-09-18 22:15:54 +0000
commite6e0361984b077d205e9a45d64257d41d2c788c8 (patch)
tree063c1f7dd2367a4856d73c78919578537d6dea87 /lib/Sema/CodeCompleteConsumer.cpp
parent1131014a6e0302f8040531e227b550230703f613 (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.cpp133
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;