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