aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp473
-rw-r--r--lib/Sema/SemaCodeComplete.cpp113
2 files changed, 533 insertions, 53 deletions
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 9b24d55f3e..cb4e8ef826 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -16,6 +16,7 @@
#include "clang/Lex/Preprocessor.h"
#include "Sema.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -26,14 +27,62 @@ using namespace clang;
//===----------------------------------------------------------------------===//
// Code completion string implementation
//===----------------------------------------------------------------------===//
-CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
+CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text)
: Kind(Kind), Text(0)
{
- assert((Kind == CK_Text || Kind == CK_Placeholder || Kind == CK_Informative)
- && "Invalid text chunk kind");
- char *New = new char [std::strlen(Text) + 1];
- std::strcpy(New, Text);
- this->Text = New;
+ switch (Kind) {
+ case CK_TypedText:
+ case CK_Text:
+ case CK_Placeholder:
+ case CK_Informative:
+ case CK_CurrentParameter: {
+ char *New = new char [Text.size() + 1];
+ std::memcpy(New, Text.data(), Text.size());
+ New[Text.size()] = '\0';
+ this->Text = New;
+ break;
+ }
+
+ case CK_Optional:
+ llvm::llvm_unreachable("Optional strings cannot be created from text");
+ break;
+
+ case CK_LeftParen:
+ this->Text = "(";
+ break;
+
+ case CK_RightParen:
+ this->Text = ")";
+ break;
+
+ case CK_LeftBracket:
+ this->Text = "[";
+ break;
+
+ case CK_RightBracket:
+ this->Text = "]";
+ break;
+
+ case CK_LeftBrace:
+ this->Text = "{";
+ break;
+
+ case CK_RightBrace:
+ this->Text = "}";
+ break;
+
+ case CK_LeftAngle:
+ this->Text = "<";
+ break;
+
+ case CK_RightAngle:
+ this->Text = ">";
+ break;
+
+ case CK_Comma:
+ this->Text = ", ";
+ break;
+ }
}
CodeCompletionString::Chunk
@@ -60,6 +109,13 @@ CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
return Chunk(CK_Informative, Informative);
}
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateCurrentParameter(
+ const char *CurrentParameter) {
+ return Chunk(CK_CurrentParameter, CurrentParameter);
+}
+
+
void
CodeCompletionString::Chunk::Destroy() {
switch (Kind) {
@@ -67,10 +123,23 @@ CodeCompletionString::Chunk::Destroy() {
delete Optional;
break;
+ case CK_TypedText:
case CK_Text:
case CK_Placeholder:
case CK_Informative:
- delete [] Text;
+ case CK_CurrentParameter:
+ delete [] Text;
+ break;
+
+ case CK_LeftParen:
+ case CK_RightParen:
+ case CK_LeftBracket:
+ case CK_RightBracket:
+ case CK_LeftBrace:
+ case CK_RightBrace:
+ case CK_LeftAngle:
+ case CK_RightAngle:
+ case CK_Comma:
break;
}
}
@@ -86,16 +155,322 @@ std::string CodeCompletionString::getAsString() const {
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->Text << "#>"; break;
case CK_Informative: OS << "[#" << C->Text << "#]"; break;
+ case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
+ default: OS << C->Text; break;
}
}
OS.flush();
return Result;
}
+
+namespace {
+ // Escape a string for XML-like formatting.
+ struct EscapedString {
+ EscapedString(llvm::StringRef Str) : Str(Str) { }
+
+ llvm::StringRef Str;
+ };
+
+ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EscapedString EStr) {
+ llvm::StringRef Str = EStr.Str;
+ while (!Str.empty()) {
+ // Find the next escaped character.
+ llvm::StringRef::size_type Pos = Str.find_first_of("<>&\"'");
+
+ // Print everything before that escaped character.
+ OS << Str.substr(0, Pos);
+
+ // If we didn't find any escaped characters, we're done.
+ if (Pos == llvm::StringRef::npos)
+ break;
+
+ // Print the appropriate escape sequence.
+ switch (Str[Pos]) {
+ case '<': OS << "&lt;"; break;
+ case '>': OS << "&gt;"; break;
+ case '&': OS << "&amp;"; break;
+ case '"': OS << "&quot;"; break;
+ case '\'': OS << "&apos;"; break;
+ }
+
+ // Remove everything up to and including that escaped character.
+ Str = Str.substr(Pos + 1);
+ }
+
+ return OS;
+ }
+
+ /// \brief Remove XML-like escaping from a string.
+ std::string UnescapeString(llvm::StringRef Str) {
+ using llvm::StringRef;
+
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+
+ while (!Str.empty()) {
+ StringRef::size_type Amp = Str.find('&');
+ OS << Str.substr(0, Amp);
+
+ if (Amp == StringRef::npos)
+ break;
+
+ StringRef::size_type Semi = Str.substr(Amp).find(';');
+ if (Semi == StringRef::npos) {
+ // Malformed input; do the best we can.
+ OS << '&';
+ Str = Str.substr(Amp + 1);
+ continue;
+ }
+
+ char Unescaped = llvm::StringSwitch<char>(Str.substr(Amp + 1, Semi - 1))
+ .Case("lt", '<')
+ .Case("gt", '>')
+ .Case("amp", '&')
+ .Case("quot", '"')
+ .Case("apos", '\'')
+ .Default('\0');
+
+ if (Unescaped)
+ OS << Unescaped;
+ else
+ OS << Str.substr(Amp, Semi + 1);
+ Str = Str.substr(Amp + Semi + 1);
+ }
+
+ return OS.str();
+ }
+}
+
+void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
+ for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
+ switch (C->Kind) {
+ case CK_TypedText:
+ OS << "<typed-text>" << EscapedString(C->Text) << "</>";
+ break;
+ case CK_Text:
+ OS << "<text>" << EscapedString(C->Text) << "</>";
+ break;
+ case CK_Optional:
+ OS << "<optional>";
+ C->Optional->Serialize(OS);
+ OS << "</>";
+ break;
+ case CK_Placeholder:
+ OS << "<placeholder>" << EscapedString(C->Text) << "</>";
+ break;
+ case CK_Informative:
+ OS << "<informative>" << EscapedString(C->Text) << "</>";
+ break;
+ case CK_CurrentParameter:
+ OS << "<current-parameter>" << EscapedString(C->Text) << "</>";
+ break;
+ case CK_LeftParen:
+ OS << "<lparen/>";
+ break;
+ case CK_RightParen:
+ OS << "<rparen/>";
+ break;
+ case CK_LeftBracket:
+ OS << "<lbracket/>";
+ break;
+ case CK_RightBracket:
+ OS << "<rbracket/>";
+ break;
+ case CK_LeftBrace:
+ OS << "<lbrace/>";
+ break;
+ case CK_RightBrace:
+ OS << "<rbrace/>";
+ break;
+ case CK_LeftAngle:
+ OS << "<langle/>";
+ break;
+ case CK_RightAngle:
+ OS << "<rangle/>";
+ break;
+ case CK_Comma:
+ OS << "<comma/>";
+ break;
+ }
+ }
+}
+
+/// \brief Parse the next XML-ish tag of the form <blah>.
+///
+/// \param Str the string in which we're looking for the next tag.
+///
+/// \param TagPos if successful, will be set to the start of the tag we found.
+///
+/// \param Standalone will indicate whether this is a "standalone" tag that
+/// has no associated data, e.g., <comma/>.
+///
+/// \param Terminator will indicate whether this is a terminating tag (that is
+/// or starts with '/').
+///
+/// \returns the tag itself, without the angle brackets.
+static llvm::StringRef ParseNextTag(llvm::StringRef Str,
+ llvm::StringRef::size_type &StartTag,
+ llvm::StringRef::size_type &AfterTag,
+ bool &Standalone, bool &Terminator) {
+ using llvm::StringRef;
+
+ Standalone = false;
+ Terminator = false;
+ AfterTag = StringRef::npos;
+
+ // Find the starting '<'.
+ StartTag = Str.find('<');
+ if (StartTag == StringRef::npos)
+ return llvm::StringRef();
+
+ // Find the corresponding '>'.
+ llvm::StringRef::size_type EndTag = Str.substr(StartTag).find('>');
+ if (EndTag == StringRef::npos)
+ return llvm::StringRef();
+ AfterTag = StartTag + EndTag + 1;
+
+ // Determine whether this is a terminating tag.
+ if (Str[StartTag + 1] == '/') {
+ Terminator = true;
+ Str = Str.substr(1);
+ --EndTag;
+ }
+
+ // Determine whether this is a standalone tag.
+ if (!Terminator && Str[StartTag + EndTag - 1] == '/') {
+ Standalone = true;
+ if (EndTag > 1)
+ --EndTag;
+ }
+
+ return Str.substr(StartTag + 1, EndTag - 1);
+}
+
+CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
+ using llvm::StringRef;
+
+ CodeCompletionString *Result = new CodeCompletionString;
+
+ do {
+ // Parse the next tag.
+ StringRef::size_type StartTag, AfterTag;
+ bool Standalone, Terminator;
+ StringRef Tag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
+ Terminator);
+
+ if (StartTag == StringRef::npos)
+ break;
+
+ // Figure out what kind of chunk we have.
+ const unsigned UnknownKind = 10000;
+ unsigned Kind = llvm::StringSwitch<unsigned>(Tag)
+ .Case("typed-text", CK_TypedText)
+ .Case("text", CK_Text)
+ .Case("optional", CK_Optional)
+ .Case("placeholder", CK_Placeholder)
+ .Case("informative", CK_Informative)
+ .Case("current-parameter", CK_CurrentParameter)
+ .Case("lparen", CK_LeftParen)
+ .Case("rparen", CK_RightParen)
+ .Case("lbracket", CK_LeftBracket)
+ .Case("rbracket", CK_RightBracket)
+ .Case("lbrace", CK_LeftBrace)
+ .Case("rbrace", CK_RightBrace)
+ .Case("langle", CK_LeftAngle)
+ .Case("rangle", CK_RightAngle)
+ .Case("comma", CK_Comma)
+ .Default(UnknownKind);
+
+ // If we've hit a terminator tag, we're done.
+ if (Terminator)
+ break;
+
+ // Consume the tag.
+ Str = Str.substr(AfterTag);
+
+ // Handle standalone tags now, since they don't need to be matched to
+ // anything.
+ if (Standalone) {
+ // Ignore anything we don't know about.
+ if (Kind == UnknownKind)
+ continue;
+
+ switch ((ChunkKind)Kind) {
+ case CK_TypedText:
+ case CK_Text:
+ case CK_Optional:
+ case CK_Placeholder:
+ case CK_Informative:
+ case CK_CurrentParameter:
+ // There is no point in creating empty chunks of these kinds.
+ break;
+
+ case CK_LeftParen:
+ case CK_RightParen:
+ case CK_LeftBracket:
+ case CK_RightBracket:
+ case CK_LeftBrace:
+ case CK_RightBrace:
+ case CK_LeftAngle:
+ case CK_RightAngle:
+ case CK_Comma:
+ Result->AddChunk(Chunk((ChunkKind)Kind));
+ break;
+ }
+
+ continue;
+ }
+
+ if (Kind == CK_Optional) {
+ // Deserialize the optional code-completion string.
+ std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str));
+ Result->AddOptionalChunk(Optional);
+ }
+
+ StringRef EndTag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
+ Terminator);
+ if (StartTag == StringRef::npos || !Terminator || Standalone)
+ break; // Parsing failed; just give up.
+
+ if (EndTag.empty() || Tag == EndTag) {
+ // Found the matching end tag. Add this chunk based on the text
+ // between the tags, then consume that input.
+ StringRef Text = Str.substr(0, StartTag);
+ switch ((ChunkKind)Kind) {
+ case CK_TypedText:
+ case CK_Text:
+ case CK_Placeholder:
+ case CK_Informative:
+ case CK_CurrentParameter:
+ case CK_LeftParen:
+ case CK_RightParen:
+ case CK_LeftBracket:
+ case CK_RightBracket:
+ case CK_LeftBrace:
+ case CK_RightBrace:
+ case CK_LeftAngle:
+ case CK_RightAngle:
+ case CK_Comma:
+ Result->AddChunk(Chunk((ChunkKind)Kind, UnescapeString(Text)));
+ break;
+
+ case CK_Optional:
+ // We've already added the optional chunk.
+ break;
+ }
+ }
+
+ // Remove this tag.
+ Str = Str.substr(AfterTag);
+ } while (!Str.empty());
+
+ return Result;
+}
+
//===----------------------------------------------------------------------===//
// Code completion overload candidate implementation
//===----------------------------------------------------------------------===//
@@ -193,3 +568,85 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
// FIXME: Move this somewhere else!
SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
}
+
+void
+CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
+ unsigned NumResults) {
+ // Print the results.
+ for (unsigned I = 0; I != NumResults; ++I) {
+ OS << "COMPLETION:" << Results[I].Rank << ":";
+ switch (Results[I].Kind) {
+ case Result::RK_Declaration:
+ if (RecordDecl *Record = dyn_cast<RecordDecl>(Results[I].Declaration)) {
+ if (Record->isStruct())
+ OS << "Struct:";
+ else if (Record->isUnion())
+ OS << "Union:";
+ else
+ OS << "Class:";
+ } else if (ObjCMethodDecl *Method
+ = dyn_cast<ObjCMethodDecl>(Results[I].Declaration)) {
+ if (Method->isInstanceMethod())
+ OS << "ObjCInstanceMethod:";
+ else
+ OS << "ObjCClassMethod:";
+ } else {
+ OS << Results[I].Declaration->getDeclKindName() << ":";
+ }
+ if (CodeCompletionString *CCS
+ = Results[I].CreateCodeCompletionString(SemaRef)) {
+ CCS->Serialize(OS);
+ delete CCS;
+ } else {
+ OS << "<typed-text>"
+ << Results[I].Declaration->getNameAsString()
+ << "</>";
+ }
+
+ OS << '\n';
+ break;
+
+ case Result::RK_Keyword:
+ OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n";
+ break;
+
+ case Result::RK_Macro: {
+ OS << "Macro:";
+ if (CodeCompletionString *CCS
+ = Results[I].CreateCodeCompletionString(SemaRef)) {
+ CCS->Serialize(OS);
+ delete CCS;
+ } else {
+ OS << "<typed-text>" << Results[I].Macro->getName() << "</>";
+ }
+ OS << '\n';
+ break;
+ }
+ }
+ }
+
+ // Once we've printed the code-completion results, suppress remaining
+ // diagnostics.
+ // FIXME: Move this somewhere else!
+ SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
+}
+
+void
+CIndexCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates) {
+ for (unsigned I = 0; I != NumCandidates; ++I) {
+ if (CodeCompletionString *CCS
+ = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
+ OS << "OVERLOAD:";
+ CCS->Serialize(OS);
+ OS << '\n';
+ delete CCS;
+ }
+ }
+
+ // Once we've printed the code-completion results, suppress remaining
+ // diagnostics.
+ // FIXME: Move this somewhere else!
+ SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
+}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index e9df17d6a1..9963fc3d45 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -187,8 +187,7 @@ getRequiredQualification(ASTContext &Context,
Context.getTypeDeclType(TD).getTypePtr());
else
assert(Parent->isTranslationUnit());
- }
-
+ }
return Result;
}
@@ -674,6 +673,8 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, unsigned Rank,
static void AddFunctionParameterChunks(ASTContext &Context,
FunctionDecl *Function,
CodeCompletionString *Result) {
+ typedef CodeCompletionString::Chunk Chunk;
+
CodeCompletionString *CCStr = Result;
for (unsigned P = 0, N = Function->getNumParams(); P != N; ++P) {
@@ -688,7 +689,7 @@ static void AddFunctionParameterChunks(ASTContext &Context,
}
if (P != 0)
- CCStr->AddTextChunk(", ");
+ CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma));
// Format the placeholder string.
std::string PlaceholderStr;
@@ -713,6 +714,8 @@ static void AddTemplateParameterChunks(ASTContext &Context,
TemplateDecl *Template,
CodeCompletionString *Result,
unsigned MaxParameters = 0) {
+ typedef CodeCompletionString::Chunk Chunk;
+
CodeCompletionString *CCStr = Result;
bool FirstParameter = true;
@@ -768,7 +771,7 @@ static void AddTemplateParameterChunks(ASTContext &Context,
if (FirstParameter)
FirstParameter = false;
else
- CCStr->AddTextChunk(", ");
+ CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma));
// Add the placeholder string.
CCStr->AddPlaceholderChunk(PlaceholderStr.c_str());
@@ -803,6 +806,8 @@ void AddQualifierToCompletionString(CodeCompletionString *Result,
/// result is all that is needed.
CodeCompletionString *
CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
+ typedef CodeCompletionString::Chunk Chunk;
+
if (Kind == RK_Keyword)
return 0;
@@ -813,12 +818,12 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
// Format a function-like macro with placeholders for the arguments.
CodeCompletionString *Result = new CodeCompletionString;
- Result->AddTextChunk(Macro->getName().str().c_str());
- Result->AddTextChunk("(");
+ Result->AddTypedTextChunk(Macro->getName().str().c_str());
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
A != AEnd; ++A) {
if (A != MI->arg_begin())
- Result->AddTextChunk(", ");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_Comma));
if (!MI->isVariadic() || A != AEnd - 1) {
// Non-variadic argument.
@@ -837,21 +842,28 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
Result->AddPlaceholderChunk(Arg.c_str());
}
}
- Result->AddTextChunk(")");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
return Result;
}
assert(Kind == RK_Declaration && "Missed a macro kind?");
NamedDecl *ND = Declaration;
+ if (StartsNestedNameSpecifier) {
+ CodeCompletionString *Result = new CodeCompletionString;
+ Result->AddTypedTextChunk(ND->getNameAsString().c_str());
+ Result->AddTextChunk("::");
+ return Result;
+ }
+
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
CodeCompletionString *Result = new CodeCompletionString;
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
S.Context);
- Result->AddTextChunk(Function->getNameAsString().c_str());
- Result->AddTextChunk("(");
+ Result->AddTypedTextChunk(Function->getNameAsString().c_str());
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
AddFunctionParameterChunks(S.Context, Function, Result);
- Result->AddTextChunk(")");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
return Result;
}
@@ -860,7 +872,7 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
S.Context);
FunctionDecl *Function = FunTmpl->getTemplatedDecl();
- Result->AddTextChunk(Function->getNameAsString().c_str());
+ Result->AddTypedTextChunk(Function->getNameAsString().c_str());
// Figure out which template parameters are deduced (or have default
// arguments).
@@ -884,7 +896,7 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
else {
assert(isa<TemplateTemplateParmDecl>(Param));
HasDefaultArg
- = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
+ = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
}
if (!HasDefaultArg)
@@ -896,16 +908,16 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
// Some of the function template arguments cannot be deduced from a
// function call, so we introduce an explicit template argument list
// containing all of the arguments up to the first deducible argument.
- Result->AddTextChunk("<");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
AddTemplateParameterChunks(S.Context, FunTmpl, Result,
LastDeducibleArgument);
- Result->AddTextChunk(">");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
}
// Add the function parameters
- Result->AddTextChunk("(");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
AddFunctionParameterChunks(S.Context, Function, Result);
- Result->AddTextChunk(")");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
return Result;
}
@@ -913,20 +925,18 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
CodeCompletionString *Result = new CodeCompletionString;
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
S.Context);
- Result->AddTextChunk(Template->getNameAsString().c_str());
- Result->AddTextChunk("<");
+ Result->AddTypedTextChunk(Template->getNameAsString().c_str());
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
AddTemplateParameterChunks(S.Context, Template, Result);
- Result->AddTextChunk(">");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
return Result;
}
- if (Qualifier || StartsNestedNameSpecifier) {
+ if (Qualifier) {
CodeCompletionString *Result = new CodeCompletionString;
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
S.Context);
- Result->AddTextChunk(ND->getNameAsString().c_str());
- if (StartsNestedNameSpecifier)
- Result->AddTextChunk("::");
+ Result->AddTypedTextChunk(ND->getNameAsString().c_str());
return Result;
}
@@ -937,6 +947,8 @@ CodeCompletionString *
CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
unsigned CurrentArg,
Sema &S) const {
+ typedef CodeCompletionString::Chunk Chunk;
+
CodeCompletionString *Result = new CodeCompletionString;
FunctionDecl *FDecl = getFunction();
const FunctionProtoType *Proto
@@ -947,9 +959,9 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
const FunctionType *FT = getFunctionType();
Result->AddTextChunk(
FT->getResultType().getAsString(S.Context.PrintingPolicy).c_str());
- Result->AddTextChunk("(");
- Result->AddPlaceholderChunk("...");
- Result->AddTextChunk("(");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+ Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
return Result;
}
@@ -959,11 +971,11 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Result->AddTextChunk(
Proto->getResultType().getAsString(S.Context.PrintingPolicy).c_str());
- Result->AddTextChunk("(");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
for (unsigned I = 0; I != NumParams; ++I) {
if (I)
- Result->AddTextChunk(", ");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_Comma));
std::string ArgString;
QualType ArgType;
@@ -978,19 +990,20 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy);
if (I == CurrentArg)
- Result->AddPlaceholderChunk(ArgString.c_str());
+ Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter,
+ ArgString.c_str()));
else
Result->AddTextChunk(ArgString.c_str());
}
if (Proto && Proto->isVariadic()) {
- Result->AddTextChunk(", ");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_Comma));
if (CurrentArg < NumParams)
Result->AddTextChunk("...");
else
- Result->AddPlaceholderChunk("...");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
}
- Result->AddTextChunk(")");
+ Result->AddChunk(Chunk(CodeCompletionString::CK_RightParen));
return Result;
}
@@ -1049,11 +1062,11 @@ namespace {
};
}
-// Add all of the known macros as code-completion results.
static void AddMacroResults(Preprocessor &PP, unsigned Rank,
ResultBuilder &Results) {
Results.EnterNewScope();
- for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end();
+ for (Preprocessor::macro_iterator M = PP.macro_begin(),
+ MEnd = PP.macro_end();
M != MEnd; ++M)
Results.MaybeAddResult(CodeCompleteConsumer::Result(M->first, Rank));
Results.ExitScope();
@@ -1073,7 +1086,8 @@ void Sema::CodeCompleteOrdinaryName(Scope *S) {
ResultBuilder Results(*this, &ResultBuilder::IsOrdinaryName);
unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
0, CurContext, Results);
- AddMacroResults(PP, NextRank, Results);
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1130,7 +1144,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
}
// Add macros
- AddMacroResults(PP, NextRank, Results);
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
// Hand off the results found for code completion.
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
@@ -1177,7 +1192,8 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
NextRank, CurContext, Results);
}
- AddMacroResults(PP, NextRank, Results);
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1255,7 +1271,8 @@ void Sema::CodeCompleteCase(Scope *S) {
}
Results.ExitScope();
- AddMacroResults(PP, 1, Results);
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, 1, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1350,7 +1367,8 @@ void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS,
if (!Results.empty() && NNS->isDependent())
Results.MaybeAddResult(CodeCompleteConsumer::Result("template", NextRank));
- AddMacroResults(PP, NextRank + 1, Results);
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank + 1, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1371,7 +1389,8 @@ void Sema::CodeCompleteUsing(Scope *S) {
0, CurContext, Results);
Results.ExitScope();
- AddMacroResults(PP, NextRank, Results);
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1386,7 +1405,8 @@ void Sema::CodeCompleteUsingDirective(Scope *S) {
unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
0, CurContext, Results);
Results.ExitScope();
- AddMacroResults(PP, NextRank, Results);
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1421,7 +1441,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Results.ExitScope();
}
- AddMacroResults(PP, 1, Results);
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, 1, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1433,7 +1454,8 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
0, CurContext, Results);
- AddMacroResults(PP, NextRank, Results);
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1464,7 +1486,8 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
NextRank + 1, CurContext, Results);
Results.ExitScope();
- AddMacroResults(PP, NextRank, Results);
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}