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