Deleted Added
full compact
16a17
> #include "clang-c/Index.h"
20d20
< #include "llvm/Support/Compiler.h"
213,228c213,215
< 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);
---
> static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) {
> OS.write((const char *)&Value, sizeof(unsigned));
> }
230,288c217,224
< // 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();
< }
---
> static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
> unsigned &Value) {
> if (Memory + sizeof(unsigned) > MemoryEnd)
> return true;
>
> memmove(&Value, Memory, sizeof(unsigned));
> Memory += sizeof(unsigned);
> return false;
291a228,230
> // Write the number of chunks.
> WriteUnsigned(OS, size());
>
292a232,233
> WriteUnsigned(OS, C->Kind);
>
295,296d235
< OS << "<typed-text>" << EscapedString(C->Text) << "</>";
< break;
298c237,243
< OS << "<text>" << EscapedString(C->Text) << "</>";
---
> case CK_Placeholder:
> case CK_Informative:
> case CK_CurrentParameter: {
> const char *Text = C->Text;
> unsigned StrLen = strlen(Text);
> WriteUnsigned(OS, StrLen);
> OS.write(Text, StrLen);
299a245,246
> }
>
301d247
< OS << "<optional>";
303d248
< OS << "</>";
305,313c250
< 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;
---
>
315,316d251
< OS << "<lparen/>";
< break;
318,319d252
< OS << "<rparen/>";
< break;
321,322d253
< OS << "<lbracket/>";
< break;
324,325d254
< OS << "<rbracket/>";
< break;
327,328d255
< OS << "<lbrace/>";
< break;
330,331d256
< OS << "<rbrace/>";
< break;
333,334d257
< OS << "<langle/>";
< break;
336,337d258
< OS << "<rangle/>";
< break;
339d259
< OS << "<comma/>";
341c261
< }
---
> }
345,391c265,268
< /// \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;
< }
---
> CodeCompletionString *CodeCompletionString::Deserialize(const char *&Str,
> const char *StrEnd) {
> if (Str == StrEnd || *Str == 0)
> return 0;
393,398d269
< return Str.substr(StartTag + 1, EndTag - 1);
< }
<
< CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
< using llvm::StringRef;
<
400,408c271,276
<
< 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)
---
> unsigned NumBlocks;
> if (ReadUnsigned(Str, StrEnd, NumBlocks))
> return Result;
>
> for (unsigned I = 0; I != NumBlocks; ++I) {
> if (Str + 1 >= StrEnd)
410,436d277
<
< // 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);
438,468c279,296
< // 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;
---
> // Parse the next kind.
> unsigned KindValue;
> if (ReadUnsigned(Str, StrEnd, KindValue))
> return Result;
>
> switch (ChunkKind Kind = (ChunkKind)KindValue) {
> case CK_TypedText:
> case CK_Text:
> case CK_Placeholder:
> case CK_Informative:
> case CK_CurrentParameter: {
> unsigned StrLen;
> if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd))
> return Result;
>
> Result->AddChunk(Chunk(Kind, StringRef(Str, StrLen)));
> Str += StrLen;
> break;
470,473c298,300
<
< if (Kind == CK_Optional) {
< // Deserialize the optional code-completion string.
< std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str));
---
>
> case CK_Optional: {
> std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str, StrEnd));
474a302
> break;
476,507c304,315
<
< 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;
< }
---
>
> 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(Kind));
> break;
509,512c317
<
< // Remove this tag.
< Str = Str.substr(AfterTag);
< } while (!Str.empty());
---
> };
636c441,442
< OS << "COMPLETION:" << Results[I].Rank << ":";
---
> CXCursorKind Kind = CXCursor_NotImplemented;
>
638,663c444,457
< 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()
< << "</>";
< }
---
> case Result::RK_Declaration:
> switch (Results[I].Declaration->getKind()) {
> case Decl::Record:
> case Decl::CXXRecord:
> case Decl::ClassTemplateSpecialization: {
> RecordDecl *Record = cast<RecordDecl>(Results[I].Declaration);
> if (Record->isStruct())
> Kind = CXCursor_StructDecl;
> else if (Record->isUnion())
> Kind = CXCursor_UnionDecl;
> else
> Kind = CXCursor_ClassDecl;
> break;
> }
665c459,464
< OS << '\n';
---
> case Decl::ObjCMethod: {
> ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Results[I].Declaration);
> if (Method->isInstanceMethod())
> Kind = CXCursor_ObjCInstanceMethodDecl;
> else
> Kind = CXCursor_ObjCClassMethodDecl;
666a466
> }
668,669c468,469
< case Result::RK_Keyword:
< OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n";
---
> case Decl::Typedef:
> Kind = CXCursor_TypedefDecl;
672,681c472,473
< 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';
---
> case Decl::Enum:
> Kind = CXCursor_EnumDecl;
683d474
< }
685,688c476,477
< case Result::RK_Pattern: {
< OS << "Pattern:";
< Results[I].Pattern->Serialize(OS);
< OS << '\n';
---
> case Decl::Field:
> Kind = CXCursor_FieldDecl;
689a479,529
>
> case Decl::EnumConstant:
> Kind = CXCursor_EnumConstantDecl;
> break;
>
> case Decl::Function:
> case Decl::CXXMethod:
> case Decl::CXXConstructor:
> case Decl::CXXDestructor:
> case Decl::CXXConversion:
> Kind = CXCursor_FunctionDecl;
> break;
>
> case Decl::Var:
> Kind = CXCursor_VarDecl;
> break;
>
> case Decl::ParmVar:
> Kind = CXCursor_ParmDecl;
> break;
>
> case Decl::ObjCInterface:
> Kind = CXCursor_ObjCInterfaceDecl;
> break;
>
> case Decl::ObjCCategory:
> Kind = CXCursor_ObjCCategoryDecl;
> break;
>
> case Decl::ObjCProtocol:
> Kind = CXCursor_ObjCProtocolDecl;
> break;
>
> case Decl::ObjCProperty:
> Kind = CXCursor_ObjCPropertyDecl;
> break;
>
> case Decl::ObjCIvar:
> Kind = CXCursor_ObjCIvarDecl;
> break;
>
> case Decl::ObjCImplementation:
> Kind = CXCursor_ObjCClassDefn;
> break;
>
> case Decl::ObjCCategoryImpl:
> Kind = CXCursor_ObjCCategoryDefn;
> break;
>
> default:
> break;
690a531,537
> break;
>
> case Result::RK_Keyword:
> case Result::RK_Macro:
> case Result::RK_Pattern:
> Kind = CXCursor_NotImplemented;
> break;
691a539,544
>
> WriteUnsigned(OS, Kind);
> CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef);
> assert(CCS && "No code-completion string?");
> CCS->Serialize(OS);
> delete CCS;
706,712c559,564
< if (CodeCompletionString *CCS
< = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
< OS << "OVERLOAD:";
< CCS->Serialize(OS);
< OS << '\n';
< delete CCS;
< }
---
> WriteUnsigned(OS, CXCursor_NotImplemented);
> CodeCompletionString *CCS
> = Candidates[I].CreateSignatureString(CurrentArg, SemaRef);
> assert(CCS && "No code-completion string?");
> CCS->Serialize(OS);
> delete CCS;