1//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the CodeCompleteConsumer class. 11// 12//===----------------------------------------------------------------------===// 13#include "clang/Sema/CodeCompleteConsumer.h" 14#include "clang/AST/DeclCXX.h" 15#include "clang/Parse/Scope.h" 16#include "clang/Lex/Preprocessor.h"
|
17#include "clang-c/Index.h" |
18#include "Sema.h" 19#include "llvm/ADT/STLExtras.h" 20#include "llvm/ADT/StringSwitch.h"
|
20#include "llvm/Support/Compiler.h"
|
21#include "llvm/Support/raw_ostream.h" 22#include <algorithm> 23#include <cstring> 24#include <functional> 25 26using namespace clang; 27using llvm::StringRef; 28 29//===----------------------------------------------------------------------===// 30// Code completion string implementation 31//===----------------------------------------------------------------------===// 32CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text) 33 : Kind(Kind), Text("") 34{ 35 switch (Kind) { 36 case CK_TypedText: 37 case CK_Text: 38 case CK_Placeholder: 39 case CK_Informative: 40 case CK_CurrentParameter: { 41 char *New = new char [Text.size() + 1]; 42 std::memcpy(New, Text.data(), Text.size()); 43 New[Text.size()] = '\0'; 44 this->Text = New; 45 break; 46 } 47 48 case CK_Optional: 49 llvm::llvm_unreachable("Optional strings cannot be created from text"); 50 break; 51 52 case CK_LeftParen: 53 this->Text = "("; 54 break; 55 56 case CK_RightParen: 57 this->Text = ")"; 58 break; 59 60 case CK_LeftBracket: 61 this->Text = "["; 62 break; 63 64 case CK_RightBracket: 65 this->Text = "]"; 66 break; 67 68 case CK_LeftBrace: 69 this->Text = "{"; 70 break; 71 72 case CK_RightBrace: 73 this->Text = "}"; 74 break; 75 76 case CK_LeftAngle: 77 this->Text = "<"; 78 break; 79 80 case CK_RightAngle: 81 this->Text = ">"; 82 break; 83 84 case CK_Comma: 85 this->Text = ", "; 86 break; 87 } 88} 89 90CodeCompletionString::Chunk 91CodeCompletionString::Chunk::CreateText(StringRef Text) { 92 return Chunk(CK_Text, Text); 93} 94 95CodeCompletionString::Chunk 96CodeCompletionString::Chunk::CreateOptional( 97 std::auto_ptr<CodeCompletionString> Optional) { 98 Chunk Result; 99 Result.Kind = CK_Optional; 100 Result.Optional = Optional.release(); 101 return Result; 102} 103 104CodeCompletionString::Chunk 105CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) { 106 return Chunk(CK_Placeholder, Placeholder); 107} 108 109CodeCompletionString::Chunk 110CodeCompletionString::Chunk::CreateInformative(StringRef Informative) { 111 return Chunk(CK_Informative, Informative); 112} 113 114CodeCompletionString::Chunk 115CodeCompletionString::Chunk::CreateCurrentParameter( 116 StringRef CurrentParameter) { 117 return Chunk(CK_CurrentParameter, CurrentParameter); 118} 119 120CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const { 121 switch (Kind) { 122 case CK_TypedText: 123 case CK_Text: 124 case CK_Placeholder: 125 case CK_Informative: 126 case CK_CurrentParameter: 127 case CK_LeftParen: 128 case CK_RightParen: 129 case CK_LeftBracket: 130 case CK_RightBracket: 131 case CK_LeftBrace: 132 case CK_RightBrace: 133 case CK_LeftAngle: 134 case CK_RightAngle: 135 case CK_Comma: 136 return Chunk(Kind, Text); 137 138 case CK_Optional: { 139 std::auto_ptr<CodeCompletionString> Opt(Optional->Clone()); 140 return CreateOptional(Opt); 141 } 142 } 143 144 // Silence GCC warning. 145 return Chunk(); 146} 147 148void 149CodeCompletionString::Chunk::Destroy() { 150 switch (Kind) { 151 case CK_Optional: 152 delete Optional; 153 break; 154 155 case CK_TypedText: 156 case CK_Text: 157 case CK_Placeholder: 158 case CK_Informative: 159 case CK_CurrentParameter: 160 delete [] Text; 161 break; 162 163 case CK_LeftParen: 164 case CK_RightParen: 165 case CK_LeftBracket: 166 case CK_RightBracket: 167 case CK_LeftBrace: 168 case CK_RightBrace: 169 case CK_LeftAngle: 170 case CK_RightAngle: 171 case CK_Comma: 172 break; 173 } 174} 175 176CodeCompletionString::~CodeCompletionString() { 177 std::for_each(Chunks.begin(), Chunks.end(), 178 std::mem_fun_ref(&Chunk::Destroy)); 179} 180 181std::string CodeCompletionString::getAsString() const { 182 std::string Result; 183 llvm::raw_string_ostream OS(Result); 184 185 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { 186 switch (C->Kind) { 187 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; 188 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; 189 case CK_Informative: OS << "[#" << C->Text << "#]"; break; 190 case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; 191 default: OS << C->Text; break; 192 } 193 } 194 OS.flush(); 195 return Result; 196} 197 198const char *CodeCompletionString::getTypedText() const { 199 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) 200 if (C->Kind == CK_TypedText) 201 return C->Text; 202 203 return 0; 204} 205 206CodeCompletionString *CodeCompletionString::Clone() const { 207 CodeCompletionString *Result = new CodeCompletionString; 208 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) 209 Result->AddChunk(C->Clone()); 210 return Result; 211} 212
|
213namespace {
214 // Escape a string for XML-like formatting.
215 struct EscapedString {
216 EscapedString(llvm::StringRef Str) : Str(Str) { }
217
218 llvm::StringRef Str;
219 };
220
221 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EscapedString EStr) {
222 llvm::StringRef Str = EStr.Str;
223 while (!Str.empty()) {
224 // Find the next escaped character.
225 llvm::StringRef::size_type Pos = Str.find_first_of("<>&\"'");
226
227 // Print everything before that escaped character.
228 OS << Str.substr(0, Pos);
|
213static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) { 214 OS.write((const char *)&Value, sizeof(unsigned)); 215} |
216
|
230 // If we didn't find any escaped characters, we're done.
231 if (Pos == llvm::StringRef::npos)
232 break;
233
234 // Print the appropriate escape sequence.
235 switch (Str[Pos]) {
236 case '<': OS << "<"; break;
237 case '>': OS << ">"; break;
238 case '&': OS << "&"; break;
239 case '"': OS << """; break;
240 case '\'': OS << "'"; break;
241 }
242
243 // Remove everything up to and including that escaped character.
244 Str = Str.substr(Pos + 1);
245 }
246
247 return OS;
248 }
249
250 /// \brief Remove XML-like escaping from a string.
251 std::string UnescapeString(llvm::StringRef Str) {
252 using llvm::StringRef;
253
254 std::string Result;
255 llvm::raw_string_ostream OS(Result);
256
257 while (!Str.empty()) {
258 StringRef::size_type Amp = Str.find('&');
259 OS << Str.substr(0, Amp);
260
261 if (Amp == StringRef::npos)
262 break;
263
264 StringRef::size_type Semi = Str.substr(Amp).find(';');
265 if (Semi == StringRef::npos) {
266 // Malformed input; do the best we can.
267 OS << '&';
268 Str = Str.substr(Amp + 1);
269 continue;
270 }
271
272 char Unescaped = llvm::StringSwitch<char>(Str.substr(Amp + 1, Semi - 1))
273 .Case("lt", '<')
274 .Case("gt", '>')
275 .Case("amp", '&')
276 .Case("quot", '"')
277 .Case("apos", '\'')
278 .Default('\0');
279
280 if (Unescaped)
281 OS << Unescaped;
282 else
283 OS << Str.substr(Amp, Semi + 1);
284 Str = Str.substr(Amp + Semi + 1);
285 }
286
287 return OS.str();
288 }
|
217static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd, 218 unsigned &Value) { 219 if (Memory + sizeof(unsigned) > MemoryEnd) 220 return true; 221 222 memmove(&Value, Memory, sizeof(unsigned)); 223 Memory += sizeof(unsigned); 224 return false; |
225} 226 227void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
|
228 // Write the number of chunks. 229 WriteUnsigned(OS, size()); 230 |
231 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
|
232 WriteUnsigned(OS, C->Kind); 233 |
234 switch (C->Kind) { 235 case CK_TypedText:
|
295 OS << "<typed-text>" << EscapedString(C->Text) << "</>";
296 break;
|
236 case CK_Text:
|
298 OS << "<text>" << EscapedString(C->Text) << "</>";
|
237 case CK_Placeholder: 238 case CK_Informative: 239 case CK_CurrentParameter: { 240 const char *Text = C->Text; 241 unsigned StrLen = strlen(Text); 242 WriteUnsigned(OS, StrLen); 243 OS.write(Text, StrLen); |
244 break;
|
245 } 246 |
247 case CK_Optional:
|
301 OS << "<optional>";
|
248 C->Optional->Serialize(OS);
|
303 OS << "</>";
|
249 break;
|
305 case CK_Placeholder:
306 OS << "<placeholder>" << EscapedString(C->Text) << "</>";
307 break;
308 case CK_Informative:
309 OS << "<informative>" << EscapedString(C->Text) << "</>";
310 break;
311 case CK_CurrentParameter:
312 OS << "<current-parameter>" << EscapedString(C->Text) << "</>";
313 break;
|
250 |
251 case CK_LeftParen:
|
315 OS << "<lparen/>";
316 break;
|
252 case CK_RightParen:
|
318 OS << "<rparen/>";
319 break;
|
253 case CK_LeftBracket:
|
321 OS << "<lbracket/>";
322 break;
|
254 case CK_RightBracket:
|
324 OS << "<rbracket/>";
325 break;
|
255 case CK_LeftBrace:
|
327 OS << "<lbrace/>";
328 break;
|
256 case CK_RightBrace:
|
330 OS << "<rbrace/>";
331 break;
|
257 case CK_LeftAngle:
|
333 OS << "<langle/>";
334 break;
|
258 case CK_RightAngle:
|
336 OS << "<rangle/>";
337 break;
|
259 case CK_Comma:
|
339 OS << "<comma/>";
|
260 break;
|
341 }
|
261 } |
262 } 263} 264
|
345/// \brief Parse the next XML-ish tag of the form <blah>.
346///
347/// \param Str the string in which we're looking for the next tag.
348///
349/// \param TagPos if successful, will be set to the start of the tag we found.
350///
351/// \param Standalone will indicate whether this is a "standalone" tag that
352/// has no associated data, e.g., <comma/>.
353///
354/// \param Terminator will indicate whether this is a terminating tag (that is
355/// or starts with '/').
356///
357/// \returns the tag itself, without the angle brackets.
358static llvm::StringRef ParseNextTag(llvm::StringRef Str,
359 llvm::StringRef::size_type &StartTag,
360 llvm::StringRef::size_type &AfterTag,
361 bool &Standalone, bool &Terminator) {
362 using llvm::StringRef;
363
364 Standalone = false;
365 Terminator = false;
366 AfterTag = StringRef::npos;
367
368 // Find the starting '<'.
369 StartTag = Str.find('<');
370 if (StartTag == StringRef::npos)
371 return llvm::StringRef();
372
373 // Find the corresponding '>'.
374 llvm::StringRef::size_type EndTag = Str.substr(StartTag).find('>');
375 if (EndTag == StringRef::npos)
376 return llvm::StringRef();
377 AfterTag = StartTag + EndTag + 1;
378
379 // Determine whether this is a terminating tag.
380 if (Str[StartTag + 1] == '/') {
381 Terminator = true;
382 Str = Str.substr(1);
383 --EndTag;
384 }
385
386 // Determine whether this is a standalone tag.
387 if (!Terminator && Str[StartTag + EndTag - 1] == '/') {
388 Standalone = true;
389 if (EndTag > 1)
390 --EndTag;
391 }
|
265CodeCompletionString *CodeCompletionString::Deserialize(const char *&Str, 266 const char *StrEnd) { 267 if (Str == StrEnd || *Str == 0) 268 return 0; |
269
|
393 return Str.substr(StartTag + 1, EndTag - 1);
394}
395
396CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
397 using llvm::StringRef;
398
|
270 CodeCompletionString *Result = new CodeCompletionString;
|
400
401 do {
402 // Parse the next tag.
403 StringRef::size_type StartTag, AfterTag;
404 bool Standalone, Terminator;
405 StringRef Tag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
406 Terminator);
407
408 if (StartTag == StringRef::npos)
|
271 unsigned NumBlocks; 272 if (ReadUnsigned(Str, StrEnd, NumBlocks)) 273 return Result; 274 275 for (unsigned I = 0; I != NumBlocks; ++I) { 276 if (Str + 1 >= StrEnd) |
277 break;
|
410
411 // Figure out what kind of chunk we have.
412 const unsigned UnknownKind = 10000;
413 unsigned Kind = llvm::StringSwitch<unsigned>(Tag)
414 .Case("typed-text", CK_TypedText)
415 .Case("text", CK_Text)
416 .Case("optional", CK_Optional)
417 .Case("placeholder", CK_Placeholder)
418 .Case("informative", CK_Informative)
419 .Case("current-parameter", CK_CurrentParameter)
420 .Case("lparen", CK_LeftParen)
421 .Case("rparen", CK_RightParen)
422 .Case("lbracket", CK_LeftBracket)
423 .Case("rbracket", CK_RightBracket)
424 .Case("lbrace", CK_LeftBrace)
425 .Case("rbrace", CK_RightBrace)
426 .Case("langle", CK_LeftAngle)
427 .Case("rangle", CK_RightAngle)
428 .Case("comma", CK_Comma)
429 .Default(UnknownKind);
430
431 // If we've hit a terminator tag, we're done.
432 if (Terminator)
433 break;
434
435 // Consume the tag.
436 Str = Str.substr(AfterTag);
|
278
|
438 // Handle standalone tags now, since they don't need to be matched to
439 // anything.
440 if (Standalone) {
441 // Ignore anything we don't know about.
442 if (Kind == UnknownKind)
443 continue;
444
445 switch ((ChunkKind)Kind) {
446 case CK_TypedText:
447 case CK_Text:
448 case CK_Optional:
449 case CK_Placeholder:
450 case CK_Informative:
451 case CK_CurrentParameter:
452 // There is no point in creating empty chunks of these kinds.
453 break;
454
455 case CK_LeftParen:
456 case CK_RightParen:
457 case CK_LeftBracket:
458 case CK_RightBracket:
459 case CK_LeftBrace:
460 case CK_RightBrace:
461 case CK_LeftAngle:
462 case CK_RightAngle:
463 case CK_Comma:
464 Result->AddChunk(Chunk((ChunkKind)Kind));
465 break;
466 }
467
468 continue;
|
279 // Parse the next kind. 280 unsigned KindValue; 281 if (ReadUnsigned(Str, StrEnd, KindValue)) 282 return Result; 283 284 switch (ChunkKind Kind = (ChunkKind)KindValue) { 285 case CK_TypedText: 286 case CK_Text: 287 case CK_Placeholder: 288 case CK_Informative: 289 case CK_CurrentParameter: { 290 unsigned StrLen; 291 if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd)) 292 return Result; 293 294 Result->AddChunk(Chunk(Kind, StringRef(Str, StrLen))); 295 Str += StrLen; 296 break; |
297 }
|
470
471 if (Kind == CK_Optional) {
472 // Deserialize the optional code-completion string.
473 std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str));
|
298 299 case CK_Optional: { 300 std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str, StrEnd)); |
301 Result->AddOptionalChunk(Optional);
|
302 break; |
303 }
|
476
477 StringRef EndTag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
478 Terminator);
479 if (StartTag == StringRef::npos || !Terminator || Standalone)
480 break; // Parsing failed; just give up.
481
482 if (EndTag.empty() || Tag == EndTag) {
483 // Found the matching end tag. Add this chunk based on the text
484 // between the tags, then consume that input.
485 StringRef Text = Str.substr(0, StartTag);
486 switch ((ChunkKind)Kind) {
487 case CK_TypedText:
488 case CK_Text:
489 case CK_Placeholder:
490 case CK_Informative:
491 case CK_CurrentParameter:
492 case CK_LeftParen:
493 case CK_RightParen:
494 case CK_LeftBracket:
495 case CK_RightBracket:
496 case CK_LeftBrace:
497 case CK_RightBrace:
498 case CK_LeftAngle:
499 case CK_RightAngle:
500 case CK_Comma:
501 Result->AddChunk(Chunk((ChunkKind)Kind, UnescapeString(Text)));
502 break;
503
504 case CK_Optional:
505 // We've already added the optional chunk.
506 break;
507 }
|
304 305 case CK_LeftParen: 306 case CK_RightParen: 307 case CK_LeftBracket: 308 case CK_RightBracket: 309 case CK_LeftBrace: 310 case CK_RightBrace: 311 case CK_LeftAngle: 312 case CK_RightAngle: 313 case CK_Comma: 314 Result->AddChunk(Chunk(Kind)); 315 break; |
316 }
|
509
510 // Remove this tag.
511 Str = Str.substr(AfterTag);
512 } while (!Str.empty());
|
317 }; |
318 319 return Result; 320} 321 322void CodeCompleteConsumer::Result::Destroy() { 323 if (Kind == RK_Pattern) { 324 delete Pattern; 325 Pattern = 0; 326 } 327} 328 329//===----------------------------------------------------------------------===// 330// Code completion overload candidate implementation 331//===----------------------------------------------------------------------===// 332FunctionDecl * 333CodeCompleteConsumer::OverloadCandidate::getFunction() const { 334 if (getKind() == CK_Function) 335 return Function; 336 else if (getKind() == CK_FunctionTemplate) 337 return FunctionTemplate->getTemplatedDecl(); 338 else 339 return 0; 340} 341 342const FunctionType * 343CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { 344 switch (Kind) { 345 case CK_Function: 346 return Function->getType()->getAs<FunctionType>(); 347 348 case CK_FunctionTemplate: 349 return FunctionTemplate->getTemplatedDecl()->getType() 350 ->getAs<FunctionType>(); 351 352 case CK_FunctionType: 353 return Type; 354 } 355 356 return 0; 357} 358 359//===----------------------------------------------------------------------===// 360// Code completion consumer implementation 361//===----------------------------------------------------------------------===// 362 363CodeCompleteConsumer::~CodeCompleteConsumer() { } 364 365void 366PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 367 Result *Results, 368 unsigned NumResults) { 369 // Print the results. 370 for (unsigned I = 0; I != NumResults; ++I) { 371 OS << "COMPLETION: "; 372 switch (Results[I].Kind) { 373 case Result::RK_Declaration: 374 OS << Results[I].Declaration->getNameAsString() << " : " 375 << Results[I].Rank; 376 if (Results[I].Hidden) 377 OS << " (Hidden)"; 378 if (CodeCompletionString *CCS 379 = Results[I].CreateCodeCompletionString(SemaRef)) { 380 OS << " : " << CCS->getAsString(); 381 delete CCS; 382 } 383 384 OS << '\n'; 385 break; 386 387 case Result::RK_Keyword: 388 OS << Results[I].Keyword << " : " << Results[I].Rank << '\n'; 389 break; 390 391 case Result::RK_Macro: { 392 OS << Results[I].Macro->getName() << " : " << Results[I].Rank; 393 if (CodeCompletionString *CCS 394 = Results[I].CreateCodeCompletionString(SemaRef)) { 395 OS << " : " << CCS->getAsString(); 396 delete CCS; 397 } 398 OS << '\n'; 399 break; 400 } 401 402 case Result::RK_Pattern: { 403 OS << "Pattern : " << Results[I].Rank << " : " 404 << Results[I].Pattern->getAsString() << '\n'; 405 break; 406 } 407 } 408 } 409 410 // Once we've printed the code-completion results, suppress remaining 411 // diagnostics. 412 // FIXME: Move this somewhere else! 413 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 414} 415 416void 417PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 418 unsigned CurrentArg, 419 OverloadCandidate *Candidates, 420 unsigned NumCandidates) { 421 for (unsigned I = 0; I != NumCandidates; ++I) { 422 if (CodeCompletionString *CCS 423 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) { 424 OS << "OVERLOAD: " << CCS->getAsString() << "\n"; 425 delete CCS; 426 } 427 } 428 429 // Once we've printed the code-completion results, suppress remaining 430 // diagnostics. 431 // FIXME: Move this somewhere else! 432 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 433} 434 435void 436CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 437 Result *Results, 438 unsigned NumResults) { 439 // Print the results. 440 for (unsigned I = 0; I != NumResults; ++I) {
|
636 OS << "COMPLETION:" << Results[I].Rank << ":";
|
441 CXCursorKind Kind = CXCursor_NotImplemented; 442 |
443 switch (Results[I].Kind) {
|
638 case Result::RK_Declaration:
639 if (RecordDecl *Record = dyn_cast<RecordDecl>(Results[I].Declaration)) {
640 if (Record->isStruct())
641 OS << "Struct:";
642 else if (Record->isUnion())
643 OS << "Union:";
644 else
645 OS << "Class:";
646 } else if (ObjCMethodDecl *Method
647 = dyn_cast<ObjCMethodDecl>(Results[I].Declaration)) {
648 if (Method->isInstanceMethod())
649 OS << "ObjCInstanceMethod:";
650 else
651 OS << "ObjCClassMethod:";
652 } else {
653 OS << Results[I].Declaration->getDeclKindName() << ":";
654 }
655 if (CodeCompletionString *CCS
656 = Results[I].CreateCodeCompletionString(SemaRef)) {
657 CCS->Serialize(OS);
658 delete CCS;
659 } else {
660 OS << "<typed-text>"
661 << Results[I].Declaration->getNameAsString()
662 << "</>";
663 }
|
444 case Result::RK_Declaration: 445 switch (Results[I].Declaration->getKind()) { 446 case Decl::Record: 447 case Decl::CXXRecord: 448 case Decl::ClassTemplateSpecialization: { 449 RecordDecl *Record = cast<RecordDecl>(Results[I].Declaration); 450 if (Record->isStruct()) 451 Kind = CXCursor_StructDecl; 452 else if (Record->isUnion()) 453 Kind = CXCursor_UnionDecl; 454 else 455 Kind = CXCursor_ClassDecl; 456 break; 457 } |
458
|
665 OS << '\n';
|
459 case Decl::ObjCMethod: { 460 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Results[I].Declaration); 461 if (Method->isInstanceMethod()) 462 Kind = CXCursor_ObjCInstanceMethodDecl; 463 else 464 Kind = CXCursor_ObjCClassMethodDecl; |
465 break;
|
466 } |
467
|
668 case Result::RK_Keyword:
669 OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n";
|
468 case Decl::Typedef: 469 Kind = CXCursor_TypedefDecl; |
470 break; 471
|
672 case Result::RK_Macro: {
673 OS << "Macro:";
674 if (CodeCompletionString *CCS
675 = Results[I].CreateCodeCompletionString(SemaRef)) {
676 CCS->Serialize(OS);
677 delete CCS;
678 } else {
679 OS << "<typed-text>" << Results[I].Macro->getName() << "</>";
680 }
681 OS << '\n';
|
472 case Decl::Enum: 473 Kind = CXCursor_EnumDecl; |
474 break;
|
683 }
|
475
|
685 case Result::RK_Pattern: {
686 OS << "Pattern:";
687 Results[I].Pattern->Serialize(OS);
688 OS << '\n';
|
476 case Decl::Field: 477 Kind = CXCursor_FieldDecl; |
478 break;
|
479 480 case Decl::EnumConstant: 481 Kind = CXCursor_EnumConstantDecl; 482 break; 483 484 case Decl::Function: 485 case Decl::CXXMethod: 486 case Decl::CXXConstructor: 487 case Decl::CXXDestructor: 488 case Decl::CXXConversion: 489 Kind = CXCursor_FunctionDecl; 490 break; 491 492 case Decl::Var: 493 Kind = CXCursor_VarDecl; 494 break; 495 496 case Decl::ParmVar: 497 Kind = CXCursor_ParmDecl; 498 break; 499 500 case Decl::ObjCInterface: 501 Kind = CXCursor_ObjCInterfaceDecl; 502 break; 503 504 case Decl::ObjCCategory: 505 Kind = CXCursor_ObjCCategoryDecl; 506 break; 507 508 case Decl::ObjCProtocol: 509 Kind = CXCursor_ObjCProtocolDecl; 510 break; 511 512 case Decl::ObjCProperty: 513 Kind = CXCursor_ObjCPropertyDecl; 514 break; 515 516 case Decl::ObjCIvar: 517 Kind = CXCursor_ObjCIvarDecl; 518 break; 519 520 case Decl::ObjCImplementation: 521 Kind = CXCursor_ObjCClassDefn; 522 break; 523 524 case Decl::ObjCCategoryImpl: 525 Kind = CXCursor_ObjCCategoryDefn; 526 break; 527 528 default: 529 break; |
530 }
|
531 break; 532 533 case Result::RK_Keyword: 534 case Result::RK_Macro: 535 case Result::RK_Pattern: 536 Kind = CXCursor_NotImplemented; 537 break; |
538 }
|
539 540 WriteUnsigned(OS, Kind); 541 CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef); 542 assert(CCS && "No code-completion string?"); 543 CCS->Serialize(OS); 544 delete CCS; |
545 } 546 547 // Once we've printed the code-completion results, suppress remaining 548 // diagnostics. 549 // FIXME: Move this somewhere else! 550 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 551} 552 553void 554CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 555 unsigned CurrentArg, 556 OverloadCandidate *Candidates, 557 unsigned NumCandidates) { 558 for (unsigned I = 0; I != NumCandidates; ++I) {
|
706 if (CodeCompletionString *CCS
707 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
708 OS << "OVERLOAD:";
709 CCS->Serialize(OS);
710 OS << '\n';
711 delete CCS;
712 }
|
559 WriteUnsigned(OS, CXCursor_NotImplemented); 560 CodeCompletionString *CCS 561 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef); 562 assert(CCS && "No code-completion string?"); 563 CCS->Serialize(OS); 564 delete CCS; |
565 } 566 567 // Once we've printed the code-completion results, suppress remaining 568 // diagnostics. 569 // FIXME: Move this somewhere else! 570 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 571}
|