1 //===- CodeCompleteConsumer.cpp - Code Completion Interface ---------------===// 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 14 #include "clang/Sema/CodeCompleteConsumer.h" 15 #include "clang-c/Index.h" 16 #include "clang/AST/Decl.h" 17 #include "clang/AST/DeclBase.h" 18 #include "clang/AST/DeclObjC.h" 19 #include "clang/AST/DeclTemplate.h" 20 #include "clang/AST/DeclarationName.h" 21 #include "clang/AST/Type.h" 22 #include "clang/Basic/IdentifierTable.h" 23 #include "clang/Sema/Sema.h" 24 #include "clang/Lex/Preprocessor.h" 25 #include "llvm/ADT/SmallString.h" 26 #include "llvm/ADT/SmallVector.h" 27 #include "llvm/ADT/StringRef.h" 28 #include "llvm/ADT/Twine.h" 29 #include "llvm/Support/Casting.h" 30 #include "llvm/Support/Compiler.h" 31 #include "llvm/Support/ErrorHandling.h" 32 #include "llvm/Support/raw_ostream.h" 33 #include <algorithm> 34 #include <cassert> 35 #include <cstdint> 36 #include <string> 37 38 using namespace clang; 39 40 //===----------------------------------------------------------------------===// 41 // Code completion context implementation 42 //===----------------------------------------------------------------------===// 43 44 bool CodeCompletionContext::wantConstructorResults() const { 45 switch (CCKind) { 46 case CCC_Recovery: 47 case CCC_Statement: 48 case CCC_Expression: 49 case CCC_ObjCMessageReceiver: 50 case CCC_ParenthesizedExpression: 51 return true; 52 53 case CCC_TopLevel: 54 case CCC_ObjCInterface: 55 case CCC_ObjCImplementation: 56 case CCC_ObjCIvarList: 57 case CCC_ClassStructUnion: 58 case CCC_DotMemberAccess: 59 case CCC_ArrowMemberAccess: 60 case CCC_ObjCPropertyAccess: 61 case CCC_EnumTag: 62 case CCC_UnionTag: 63 case CCC_ClassOrStructTag: 64 case CCC_ObjCProtocolName: 65 case CCC_Namespace: 66 case CCC_Type: 67 case CCC_Name: 68 case CCC_PotentiallyQualifiedName: 69 case CCC_MacroName: 70 case CCC_MacroNameUse: 71 case CCC_PreprocessorExpression: 72 case CCC_PreprocessorDirective: 73 case CCC_NaturalLanguage: 74 case CCC_SelectorName: 75 case CCC_TypeQualifiers: 76 case CCC_Other: 77 case CCC_OtherWithMacros: 78 case CCC_ObjCInstanceMessage: 79 case CCC_ObjCClassMessage: 80 case CCC_ObjCInterfaceName: 81 case CCC_ObjCCategoryName: 82 return false; 83 } 84 85 llvm_unreachable("Invalid CodeCompletionContext::Kind!"); 86 } 87 88 StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) { 89 using CCKind = CodeCompletionContext::Kind; 90 switch (Kind) { 91 case CCKind::CCC_Other: 92 return "Other"; 93 case CCKind::CCC_OtherWithMacros: 94 return "OtherWithMacros"; 95 case CCKind::CCC_TopLevel: 96 return "TopLevel"; 97 case CCKind::CCC_ObjCInterface: 98 return "ObjCInterface"; 99 case CCKind::CCC_ObjCImplementation: 100 return "ObjCImplementation"; 101 case CCKind::CCC_ObjCIvarList: 102 return "ObjCIvarList"; 103 case CCKind::CCC_ClassStructUnion: 104 return "ClassStructUnion"; 105 case CCKind::CCC_Statement: 106 return "Statement"; 107 case CCKind::CCC_Expression: 108 return "Expression"; 109 case CCKind::CCC_ObjCMessageReceiver: 110 return "ObjCMessageReceiver"; 111 case CCKind::CCC_DotMemberAccess: 112 return "DotMemberAccess"; 113 case CCKind::CCC_ArrowMemberAccess: 114 return "ArrowMemberAccess"; 115 case CCKind::CCC_ObjCPropertyAccess: 116 return "ObjCPropertyAccess"; 117 case CCKind::CCC_EnumTag: 118 return "EnumTag"; 119 case CCKind::CCC_UnionTag: 120 return "UnionTag"; 121 case CCKind::CCC_ClassOrStructTag: 122 return "ClassOrStructTag"; 123 case CCKind::CCC_ObjCProtocolName: 124 return "ObjCProtocolName"; 125 case CCKind::CCC_Namespace: 126 return "Namespace"; 127 case CCKind::CCC_Type: 128 return "Type"; 129 case CCKind::CCC_Name: 130 return "Name"; 131 case CCKind::CCC_PotentiallyQualifiedName: 132 return "PotentiallyQualifiedName"; 133 case CCKind::CCC_MacroName: 134 return "MacroName"; 135 case CCKind::CCC_MacroNameUse: 136 return "MacroNameUse"; 137 case CCKind::CCC_PreprocessorExpression: 138 return "PreprocessorExpression"; 139 case CCKind::CCC_PreprocessorDirective: 140 return "PreprocessorDirective"; 141 case CCKind::CCC_NaturalLanguage: 142 return "NaturalLanguage"; 143 case CCKind::CCC_SelectorName: 144 return "SelectorName"; 145 case CCKind::CCC_TypeQualifiers: 146 return "TypeQualifiers"; 147 case CCKind::CCC_ParenthesizedExpression: 148 return "ParenthesizedExpression"; 149 case CCKind::CCC_ObjCInstanceMessage: 150 return "ObjCInstanceMessage"; 151 case CCKind::CCC_ObjCClassMessage: 152 return "ObjCClassMessage"; 153 case CCKind::CCC_ObjCInterfaceName: 154 return "ObjCInterfaceName"; 155 case CCKind::CCC_ObjCCategoryName: 156 return "ObjCCategoryName"; 157 case CCKind::CCC_Recovery: 158 return "Recovery"; 159 } 160 llvm_unreachable("Invalid CodeCompletionContext::Kind!"); 161 } 162 163 //===----------------------------------------------------------------------===// 164 // Code completion string implementation 165 //===----------------------------------------------------------------------===// 166 167 CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) 168 : Kind(Kind), Text("") { 169 switch (Kind) { 170 case CK_TypedText: 171 case CK_Text: 172 case CK_Placeholder: 173 case CK_Informative: 174 case CK_ResultType: 175 case CK_CurrentParameter: 176 this->Text = Text; 177 break; 178 179 case CK_Optional: 180 llvm_unreachable("Optional strings cannot be created from text"); 181 182 case CK_LeftParen: 183 this->Text = "("; 184 break; 185 186 case CK_RightParen: 187 this->Text = ")"; 188 break; 189 190 case CK_LeftBracket: 191 this->Text = "["; 192 break; 193 194 case CK_RightBracket: 195 this->Text = "]"; 196 break; 197 198 case CK_LeftBrace: 199 this->Text = "{"; 200 break; 201 202 case CK_RightBrace: 203 this->Text = "}"; 204 break; 205 206 case CK_LeftAngle: 207 this->Text = "<"; 208 break; 209 210 case CK_RightAngle: 211 this->Text = ">"; 212 break; 213 214 case CK_Comma: 215 this->Text = ", "; 216 break; 217 218 case CK_Colon: 219 this->Text = ":"; 220 break; 221 222 case CK_SemiColon: 223 this->Text = ";"; 224 break; 225 226 case CK_Equal: 227 this->Text = " = "; 228 break; 229 230 case CK_HorizontalSpace: 231 this->Text = " "; 232 break; 233 234 case CK_VerticalSpace: 235 this->Text = "\n"; 236 break; 237 } 238 } 239 240 CodeCompletionString::Chunk 241 CodeCompletionString::Chunk::CreateText(const char *Text) { 242 return Chunk(CK_Text, Text); 243 } 244 245 CodeCompletionString::Chunk 246 CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) { 247 Chunk Result; 248 Result.Kind = CK_Optional; 249 Result.Optional = Optional; 250 return Result; 251 } 252 253 CodeCompletionString::Chunk 254 CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) { 255 return Chunk(CK_Placeholder, Placeholder); 256 } 257 258 CodeCompletionString::Chunk 259 CodeCompletionString::Chunk::CreateInformative(const char *Informative) { 260 return Chunk(CK_Informative, Informative); 261 } 262 263 CodeCompletionString::Chunk 264 CodeCompletionString::Chunk::CreateResultType(const char *ResultType) { 265 return Chunk(CK_ResultType, ResultType); 266 } 267 268 CodeCompletionString::Chunk 269 CodeCompletionString::Chunk::CreateCurrentParameter( 270 const char *CurrentParameter) { 271 return Chunk(CK_CurrentParameter, CurrentParameter); 272 } 273 274 CodeCompletionString::CodeCompletionString(const Chunk *Chunks, 275 unsigned NumChunks, 276 unsigned Priority, 277 CXAvailabilityKind Availability, 278 const char **Annotations, 279 unsigned NumAnnotations, 280 StringRef ParentName, 281 const char *BriefComment) 282 : NumChunks(NumChunks), NumAnnotations(NumAnnotations), 283 Priority(Priority), Availability(Availability), 284 ParentName(ParentName), BriefComment(BriefComment) { 285 assert(NumChunks <= 0xffff); 286 assert(NumAnnotations <= 0xffff); 287 288 Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1); 289 for (unsigned I = 0; I != NumChunks; ++I) 290 StoredChunks[I] = Chunks[I]; 291 292 const char **StoredAnnotations = reinterpret_cast<const char **>(StoredChunks + NumChunks); 293 for (unsigned I = 0; I != NumAnnotations; ++I) 294 StoredAnnotations[I] = Annotations[I]; 295 } 296 297 unsigned CodeCompletionString::getAnnotationCount() const { 298 return NumAnnotations; 299 } 300 301 const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const { 302 if (AnnotationNr < NumAnnotations) 303 return reinterpret_cast<const char * const*>(end())[AnnotationNr]; 304 else 305 return nullptr; 306 } 307 308 std::string CodeCompletionString::getAsString() const { 309 std::string Result; 310 llvm::raw_string_ostream OS(Result); 311 312 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { 313 switch (C->Kind) { 314 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; 315 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; 316 317 case CK_Informative: 318 case CK_ResultType: 319 OS << "[#" << C->Text << "#]"; 320 break; 321 322 case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; 323 default: OS << C->Text; break; 324 } 325 } 326 return OS.str(); 327 } 328 329 const char *CodeCompletionString::getTypedText() const { 330 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) 331 if (C->Kind == CK_TypedText) 332 return C->Text; 333 334 return nullptr; 335 } 336 337 const char *CodeCompletionAllocator::CopyString(const Twine &String) { 338 SmallString<128> Data; 339 StringRef Ref = String.toStringRef(Data); 340 // FIXME: It would be more efficient to teach Twine to tell us its size and 341 // then add a routine there to fill in an allocated char* with the contents 342 // of the string. 343 char *Mem = (char *)Allocate(Ref.size() + 1, 1); 344 std::copy(Ref.begin(), Ref.end(), Mem); 345 Mem[Ref.size()] = 0; 346 return Mem; 347 } 348 349 StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { 350 const NamedDecl *ND = dyn_cast<NamedDecl>(DC); 351 if (!ND) 352 return {}; 353 354 // Check whether we've already cached the parent name. 355 StringRef &CachedParentName = ParentNames[DC]; 356 if (!CachedParentName.empty()) 357 return CachedParentName; 358 359 // If we already processed this DeclContext and assigned empty to it, the 360 // data pointer will be non-null. 361 if (CachedParentName.data() != nullptr) 362 return {}; 363 364 // Find the interesting names. 365 SmallVector<const DeclContext *, 2> Contexts; 366 while (DC && !DC->isFunctionOrMethod()) { 367 if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) { 368 if (ND->getIdentifier()) 369 Contexts.push_back(DC); 370 } 371 372 DC = DC->getParent(); 373 } 374 375 { 376 SmallString<128> S; 377 llvm::raw_svector_ostream OS(S); 378 bool First = true; 379 for (unsigned I = Contexts.size(); I != 0; --I) { 380 if (First) 381 First = false; 382 else { 383 OS << "::"; 384 } 385 386 const DeclContext *CurDC = Contexts[I-1]; 387 if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) 388 CurDC = CatImpl->getCategoryDecl(); 389 390 if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { 391 const ObjCInterfaceDecl *Interface = Cat->getClassInterface(); 392 if (!Interface) { 393 // Assign an empty StringRef but with non-null data to distinguish 394 // between empty because we didn't process the DeclContext yet. 395 CachedParentName = StringRef((const char *)(uintptr_t)~0U, 0); 396 return {}; 397 } 398 399 OS << Interface->getName() << '(' << Cat->getName() << ')'; 400 } else { 401 OS << cast<NamedDecl>(CurDC)->getName(); 402 } 403 } 404 405 CachedParentName = AllocatorRef->CopyString(OS.str()); 406 } 407 408 return CachedParentName; 409 } 410 411 CodeCompletionString *CodeCompletionBuilder::TakeString() { 412 void *Mem = getAllocator().Allocate( 413 sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() + 414 sizeof(const char *) * Annotations.size(), 415 alignof(CodeCompletionString)); 416 CodeCompletionString *Result 417 = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(), 418 Priority, Availability, 419 Annotations.data(), Annotations.size(), 420 ParentName, BriefComment); 421 Chunks.clear(); 422 return Result; 423 } 424 425 void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) { 426 Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text)); 427 } 428 429 void CodeCompletionBuilder::AddTextChunk(const char *Text) { 430 Chunks.push_back(Chunk::CreateText(Text)); 431 } 432 433 void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) { 434 Chunks.push_back(Chunk::CreateOptional(Optional)); 435 } 436 437 void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) { 438 Chunks.push_back(Chunk::CreatePlaceholder(Placeholder)); 439 } 440 441 void CodeCompletionBuilder::AddInformativeChunk(const char *Text) { 442 Chunks.push_back(Chunk::CreateInformative(Text)); 443 } 444 445 void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) { 446 Chunks.push_back(Chunk::CreateResultType(ResultType)); 447 } 448 449 void 450 CodeCompletionBuilder::AddCurrentParameterChunk(const char *CurrentParameter) { 451 Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter)); 452 } 453 454 void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK, 455 const char *Text) { 456 Chunks.push_back(Chunk(CK, Text)); 457 } 458 459 void CodeCompletionBuilder::addParentContext(const DeclContext *DC) { 460 if (DC->isTranslationUnit()) 461 return; 462 463 if (DC->isFunctionOrMethod()) 464 return; 465 466 const NamedDecl *ND = dyn_cast<NamedDecl>(DC); 467 if (!ND) 468 return; 469 470 ParentName = getCodeCompletionTUInfo().getParentName(DC); 471 } 472 473 void CodeCompletionBuilder::addBriefComment(StringRef Comment) { 474 BriefComment = Allocator.CopyString(Comment); 475 } 476 477 //===----------------------------------------------------------------------===// 478 // Code completion overload candidate implementation 479 //===----------------------------------------------------------------------===// 480 FunctionDecl * 481 CodeCompleteConsumer::OverloadCandidate::getFunction() const { 482 if (getKind() == CK_Function) 483 return Function; 484 else if (getKind() == CK_FunctionTemplate) 485 return FunctionTemplate->getTemplatedDecl(); 486 else 487 return nullptr; 488 } 489 490 const FunctionType * 491 CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { 492 switch (Kind) { 493 case CK_Function: 494 return Function->getType()->getAs<FunctionType>(); 495 496 case CK_FunctionTemplate: 497 return FunctionTemplate->getTemplatedDecl()->getType() 498 ->getAs<FunctionType>(); 499 500 case CK_FunctionType: 501 return Type; 502 } 503 504 llvm_unreachable("Invalid CandidateKind!"); 505 } 506 507 //===----------------------------------------------------------------------===// 508 // Code completion consumer implementation 509 //===----------------------------------------------------------------------===// 510 511 CodeCompleteConsumer::~CodeCompleteConsumer() = default; 512 513 bool PrintingCodeCompleteConsumer::isResultFilteredOut(StringRef Filter, 514 CodeCompletionResult Result) { 515 switch (Result.Kind) { 516 case CodeCompletionResult::RK_Declaration: 517 return !(Result.Declaration->getIdentifier() && 518 Result.Declaration->getIdentifier()->getName().startswith(Filter)); 519 case CodeCompletionResult::RK_Keyword: 520 return !StringRef(Result.Keyword).startswith(Filter); 521 case CodeCompletionResult::RK_Macro: 522 return !Result.Macro->getName().startswith(Filter); 523 case CodeCompletionResult::RK_Pattern: 524 return !StringRef(Result.Pattern->getAsString()).startswith(Filter); 525 } 526 llvm_unreachable("Unknown code completion result Kind."); 527 } 528 529 void 530 PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 531 CodeCompletionContext Context, 532 CodeCompletionResult *Results, 533 unsigned NumResults) { 534 std::stable_sort(Results, Results + NumResults); 535 536 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter(); 537 538 // Print the results. 539 for (unsigned I = 0; I != NumResults; ++I) { 540 if(!Filter.empty() && isResultFilteredOut(Filter, Results[I])) 541 continue; 542 OS << "COMPLETION: "; 543 switch (Results[I].Kind) { 544 case CodeCompletionResult::RK_Declaration: 545 OS << *Results[I].Declaration; 546 if (Results[I].Hidden) 547 OS << " (Hidden)"; 548 if (CodeCompletionString *CCS 549 = Results[I].CreateCodeCompletionString(SemaRef, Context, 550 getAllocator(), 551 CCTUInfo, 552 includeBriefComments())) { 553 OS << " : " << CCS->getAsString(); 554 if (const char *BriefComment = CCS->getBriefComment()) 555 OS << " : " << BriefComment; 556 } 557 for (const FixItHint &FixIt : Results[I].FixIts) { 558 const SourceLocation BLoc = FixIt.RemoveRange.getBegin(); 559 const SourceLocation ELoc = FixIt.RemoveRange.getEnd(); 560 561 SourceManager &SM = SemaRef.SourceMgr; 562 std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc); 563 std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc); 564 // Adjust for token ranges. 565 if (FixIt.RemoveRange.isTokenRange()) 566 EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts); 567 568 OS << " (requires fix-it:" 569 << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':' 570 << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' 571 << SM.getLineNumber(EInfo.first, EInfo.second) << ':' 572 << SM.getColumnNumber(EInfo.first, EInfo.second) << "}" 573 << " to \"" << FixIt.CodeToInsert << "\")"; 574 } 575 OS << '\n'; 576 break; 577 578 case CodeCompletionResult::RK_Keyword: 579 OS << Results[I].Keyword << '\n'; 580 break; 581 582 case CodeCompletionResult::RK_Macro: 583 OS << Results[I].Macro->getName(); 584 if (CodeCompletionString *CCS 585 = Results[I].CreateCodeCompletionString(SemaRef, Context, 586 getAllocator(), 587 CCTUInfo, 588 includeBriefComments())) { 589 OS << " : " << CCS->getAsString(); 590 } 591 OS << '\n'; 592 break; 593 594 case CodeCompletionResult::RK_Pattern: 595 OS << "Pattern : " 596 << Results[I].Pattern->getAsString() << '\n'; 597 break; 598 } 599 } 600 } 601 602 // This function is used solely to preserve the former presentation of overloads 603 // by "clang -cc1 -code-completion-at", since CodeCompletionString::getAsString 604 // needs to be improved for printing the newer and more detailed overload 605 // chunks. 606 static std::string getOverloadAsString(const CodeCompletionString &CCS) { 607 std::string Result; 608 llvm::raw_string_ostream OS(Result); 609 610 for (auto &C : CCS) { 611 switch (C.Kind) { 612 case CodeCompletionString::CK_Informative: 613 case CodeCompletionString::CK_ResultType: 614 OS << "[#" << C.Text << "#]"; 615 break; 616 617 case CodeCompletionString::CK_CurrentParameter: 618 OS << "<#" << C.Text << "#>"; 619 break; 620 621 default: OS << C.Text; break; 622 } 623 } 624 return OS.str(); 625 } 626 627 void 628 PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 629 unsigned CurrentArg, 630 OverloadCandidate *Candidates, 631 unsigned NumCandidates) { 632 for (unsigned I = 0; I != NumCandidates; ++I) { 633 if (CodeCompletionString *CCS 634 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef, 635 getAllocator(), CCTUInfo, 636 includeBriefComments())) { 637 OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n"; 638 } 639 } 640 } 641 642 /// Retrieve the effective availability of the given declaration. 643 static AvailabilityResult getDeclAvailability(const Decl *D) { 644 AvailabilityResult AR = D->getAvailability(); 645 if (isa<EnumConstantDecl>(D)) 646 AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability()); 647 return AR; 648 } 649 650 void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { 651 switch (Kind) { 652 case RK_Pattern: 653 if (!Declaration) { 654 // Do nothing: Patterns can come with cursor kinds! 655 break; 656 } 657 LLVM_FALLTHROUGH; 658 659 case RK_Declaration: { 660 // Set the availability based on attributes. 661 switch (getDeclAvailability(Declaration)) { 662 case AR_Available: 663 case AR_NotYetIntroduced: 664 Availability = CXAvailability_Available; 665 break; 666 667 case AR_Deprecated: 668 Availability = CXAvailability_Deprecated; 669 break; 670 671 case AR_Unavailable: 672 Availability = CXAvailability_NotAvailable; 673 break; 674 } 675 676 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration)) 677 if (Function->isDeleted()) 678 Availability = CXAvailability_NotAvailable; 679 680 CursorKind = getCursorKindForDecl(Declaration); 681 if (CursorKind == CXCursor_UnexposedDecl) { 682 // FIXME: Forward declarations of Objective-C classes and protocols 683 // are not directly exposed, but we want code completion to treat them 684 // like a definition. 685 if (isa<ObjCInterfaceDecl>(Declaration)) 686 CursorKind = CXCursor_ObjCInterfaceDecl; 687 else if (isa<ObjCProtocolDecl>(Declaration)) 688 CursorKind = CXCursor_ObjCProtocolDecl; 689 else 690 CursorKind = CXCursor_NotImplemented; 691 } 692 break; 693 } 694 695 case RK_Macro: 696 case RK_Keyword: 697 llvm_unreachable("Macro and keyword kinds are handled by the constructors"); 698 } 699 700 if (!Accessible) 701 Availability = CXAvailability_NotAccessible; 702 } 703 704 /// Retrieve the name that should be used to order a result. 705 /// 706 /// If the name needs to be constructed as a string, that string will be 707 /// saved into Saved and the returned StringRef will refer to it. 708 StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const { 709 switch (Kind) { 710 case RK_Keyword: 711 return Keyword; 712 case RK_Pattern: 713 return Pattern->getTypedText(); 714 case RK_Macro: 715 return Macro->getName(); 716 case RK_Declaration: 717 // Handle declarations below. 718 break; 719 } 720 721 DeclarationName Name = Declaration->getDeclName(); 722 723 // If the name is a simple identifier (by far the common case), or a 724 // zero-argument selector, just return a reference to that identifier. 725 if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) 726 return Id->getName(); 727 if (Name.isObjCZeroArgSelector()) 728 if (IdentifierInfo *Id 729 = Name.getObjCSelector().getIdentifierInfoForSlot(0)) 730 return Id->getName(); 731 732 Saved = Name.getAsString(); 733 return Saved; 734 } 735 736 bool clang::operator<(const CodeCompletionResult &X, 737 const CodeCompletionResult &Y) { 738 std::string XSaved, YSaved; 739 StringRef XStr = X.getOrderedName(XSaved); 740 StringRef YStr = Y.getOrderedName(YSaved); 741 int cmp = XStr.compare_lower(YStr); 742 if (cmp) 743 return cmp < 0; 744 745 // If case-insensitive comparison fails, try case-sensitive comparison. 746 cmp = XStr.compare(YStr); 747 if (cmp) 748 return cmp < 0; 749 750 return false; 751 } 752