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/StringRef.h" 27 #include "llvm/ADT/Twine.h" 28 #include "llvm/Support/Casting.h" 29 #include "llvm/Support/Compiler.h" 30 #include "llvm/Support/ErrorHandling.h" 31 #include "llvm/Support/FormatVariadic.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 case CCC_Symbol: 52 case CCC_SymbolOrNewName: 53 return true; 54 55 case CCC_TopLevel: 56 case CCC_ObjCInterface: 57 case CCC_ObjCImplementation: 58 case CCC_ObjCIvarList: 59 case CCC_ClassStructUnion: 60 case CCC_DotMemberAccess: 61 case CCC_ArrowMemberAccess: 62 case CCC_ObjCPropertyAccess: 63 case CCC_EnumTag: 64 case CCC_UnionTag: 65 case CCC_ClassOrStructTag: 66 case CCC_ObjCProtocolName: 67 case CCC_Namespace: 68 case CCC_Type: 69 case CCC_NewName: 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_NewName: 132 return "NewName"; 133 case CCKind::CCC_Symbol: 134 return "Symbol"; 135 case CCKind::CCC_SymbolOrNewName: 136 return "SymbolOrNewName"; 137 case CCKind::CCC_MacroName: 138 return "MacroName"; 139 case CCKind::CCC_MacroNameUse: 140 return "MacroNameUse"; 141 case CCKind::CCC_PreprocessorExpression: 142 return "PreprocessorExpression"; 143 case CCKind::CCC_PreprocessorDirective: 144 return "PreprocessorDirective"; 145 case CCKind::CCC_NaturalLanguage: 146 return "NaturalLanguage"; 147 case CCKind::CCC_SelectorName: 148 return "SelectorName"; 149 case CCKind::CCC_TypeQualifiers: 150 return "TypeQualifiers"; 151 case CCKind::CCC_ParenthesizedExpression: 152 return "ParenthesizedExpression"; 153 case CCKind::CCC_ObjCInstanceMessage: 154 return "ObjCInstanceMessage"; 155 case CCKind::CCC_ObjCClassMessage: 156 return "ObjCClassMessage"; 157 case CCKind::CCC_ObjCInterfaceName: 158 return "ObjCInterfaceName"; 159 case CCKind::CCC_ObjCCategoryName: 160 return "ObjCCategoryName"; 161 case CCKind::CCC_IncludedFile: 162 return "IncludedFile"; 163 case CCKind::CCC_Recovery: 164 return "Recovery"; 165 } 166 llvm_unreachable("Invalid CodeCompletionContext::Kind!"); 167 } 168 169 //===----------------------------------------------------------------------===// 170 // Code completion string implementation 171 //===----------------------------------------------------------------------===// 172 173 CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) 174 : Kind(Kind), Text("") { 175 switch (Kind) { 176 case CK_TypedText: 177 case CK_Text: 178 case CK_Placeholder: 179 case CK_Informative: 180 case CK_ResultType: 181 case CK_CurrentParameter: 182 this->Text = Text; 183 break; 184 185 case CK_Optional: 186 llvm_unreachable("Optional strings cannot be created from text"); 187 188 case CK_LeftParen: 189 this->Text = "("; 190 break; 191 192 case CK_RightParen: 193 this->Text = ")"; 194 break; 195 196 case CK_LeftBracket: 197 this->Text = "["; 198 break; 199 200 case CK_RightBracket: 201 this->Text = "]"; 202 break; 203 204 case CK_LeftBrace: 205 this->Text = "{"; 206 break; 207 208 case CK_RightBrace: 209 this->Text = "}"; 210 break; 211 212 case CK_LeftAngle: 213 this->Text = "<"; 214 break; 215 216 case CK_RightAngle: 217 this->Text = ">"; 218 break; 219 220 case CK_Comma: 221 this->Text = ", "; 222 break; 223 224 case CK_Colon: 225 this->Text = ":"; 226 break; 227 228 case CK_SemiColon: 229 this->Text = ";"; 230 break; 231 232 case CK_Equal: 233 this->Text = " = "; 234 break; 235 236 case CK_HorizontalSpace: 237 this->Text = " "; 238 break; 239 240 case CK_VerticalSpace: 241 this->Text = "\n"; 242 break; 243 } 244 } 245 246 CodeCompletionString::Chunk 247 CodeCompletionString::Chunk::CreateText(const char *Text) { 248 return Chunk(CK_Text, Text); 249 } 250 251 CodeCompletionString::Chunk 252 CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) { 253 Chunk Result; 254 Result.Kind = CK_Optional; 255 Result.Optional = Optional; 256 return Result; 257 } 258 259 CodeCompletionString::Chunk 260 CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) { 261 return Chunk(CK_Placeholder, Placeholder); 262 } 263 264 CodeCompletionString::Chunk 265 CodeCompletionString::Chunk::CreateInformative(const char *Informative) { 266 return Chunk(CK_Informative, Informative); 267 } 268 269 CodeCompletionString::Chunk 270 CodeCompletionString::Chunk::CreateResultType(const char *ResultType) { 271 return Chunk(CK_ResultType, ResultType); 272 } 273 274 CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateCurrentParameter( 275 const char *CurrentParameter) { 276 return Chunk(CK_CurrentParameter, CurrentParameter); 277 } 278 279 CodeCompletionString::CodeCompletionString( 280 const Chunk *Chunks, unsigned NumChunks, unsigned Priority, 281 CXAvailabilityKind Availability, const char **Annotations, 282 unsigned NumAnnotations, StringRef ParentName, const char *BriefComment) 283 : NumChunks(NumChunks), NumAnnotations(NumAnnotations), Priority(Priority), 284 Availability(Availability), ParentName(ParentName), 285 BriefComment(BriefComment) { 286 assert(NumChunks <= 0xffff); 287 assert(NumAnnotations <= 0xffff); 288 289 Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1); 290 for (unsigned I = 0; I != NumChunks; ++I) 291 StoredChunks[I] = Chunks[I]; 292 293 const char **StoredAnnotations = 294 reinterpret_cast<const char **>(StoredChunks + NumChunks); 295 for (unsigned I = 0; I != NumAnnotations; ++I) 296 StoredAnnotations[I] = Annotations[I]; 297 } 298 299 unsigned CodeCompletionString::getAnnotationCount() const { 300 return NumAnnotations; 301 } 302 303 const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const { 304 if (AnnotationNr < NumAnnotations) 305 return reinterpret_cast<const char *const *>(end())[AnnotationNr]; 306 else 307 return nullptr; 308 } 309 310 std::string CodeCompletionString::getAsString() const { 311 std::string Result; 312 llvm::raw_string_ostream OS(Result); 313 314 for (const Chunk &C : *this) { 315 switch (C.Kind) { 316 case CK_Optional: 317 OS << "{#" << C.Optional->getAsString() << "#}"; 318 break; 319 case CK_Placeholder: 320 OS << "<#" << C.Text << "#>"; 321 break; 322 case CK_Informative: 323 case CK_ResultType: 324 OS << "[#" << C.Text << "#]"; 325 break; 326 case CK_CurrentParameter: 327 OS << "<#" << C.Text << "#>"; 328 break; 329 default: 330 OS << C.Text; 331 break; 332 } 333 } 334 return OS.str(); 335 } 336 337 const char *CodeCompletionString::getTypedText() const { 338 for (const Chunk &C : *this) 339 if (C.Kind == CK_TypedText) 340 return C.Text; 341 342 return nullptr; 343 } 344 345 const char *CodeCompletionAllocator::CopyString(const Twine &String) { 346 SmallString<128> Data; 347 StringRef Ref = String.toStringRef(Data); 348 // FIXME: It would be more efficient to teach Twine to tell us its size and 349 // then add a routine there to fill in an allocated char* with the contents 350 // of the string. 351 char *Mem = (char *)Allocate(Ref.size() + 1, 1); 352 std::copy(Ref.begin(), Ref.end(), Mem); 353 Mem[Ref.size()] = 0; 354 return Mem; 355 } 356 357 StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { 358 const NamedDecl *ND = dyn_cast<NamedDecl>(DC); 359 if (!ND) 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 const NamedDecl *ND = dyn_cast<NamedDecl>(DC); 473 if (!ND) 474 return; 475 476 ParentName = getCodeCompletionTUInfo().getParentName(DC); 477 } 478 479 void CodeCompletionBuilder::addBriefComment(StringRef Comment) { 480 BriefComment = Allocator.CopyString(Comment); 481 } 482 483 //===----------------------------------------------------------------------===// 484 // Code completion overload candidate implementation 485 //===----------------------------------------------------------------------===// 486 FunctionDecl *CodeCompleteConsumer::OverloadCandidate::getFunction() const { 487 if (getKind() == CK_Function) 488 return Function; 489 else if (getKind() == CK_FunctionTemplate) 490 return FunctionTemplate->getTemplatedDecl(); 491 else 492 return nullptr; 493 } 494 495 const FunctionType * 496 CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { 497 switch (Kind) { 498 case CK_Function: 499 return Function->getType()->getAs<FunctionType>(); 500 501 case CK_FunctionTemplate: 502 return FunctionTemplate->getTemplatedDecl() 503 ->getType() 504 ->getAs<FunctionType>(); 505 506 case CK_FunctionType: 507 return Type; 508 } 509 510 llvm_unreachable("Invalid CandidateKind!"); 511 } 512 513 //===----------------------------------------------------------------------===// 514 // Code completion consumer implementation 515 //===----------------------------------------------------------------------===// 516 517 CodeCompleteConsumer::~CodeCompleteConsumer() = default; 518 519 bool PrintingCodeCompleteConsumer::isResultFilteredOut( 520 StringRef Filter, CodeCompletionResult Result) { 521 switch (Result.Kind) { 522 case CodeCompletionResult::RK_Declaration: 523 return !(Result.Declaration->getIdentifier() && 524 Result.Declaration->getIdentifier()->getName().startswith(Filter)); 525 case CodeCompletionResult::RK_Keyword: 526 return !StringRef(Result.Keyword).startswith(Filter); 527 case CodeCompletionResult::RK_Macro: 528 return !Result.Macro->getName().startswith(Filter); 529 case CodeCompletionResult::RK_Pattern: 530 return !(Result.Pattern->getTypedText() && 531 StringRef(Result.Pattern->getTypedText()).startswith(Filter)); 532 } 533 llvm_unreachable("Unknown code completion result Kind."); 534 } 535 536 void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults( 537 Sema &SemaRef, CodeCompletionContext Context, CodeCompletionResult *Results, 538 unsigned NumResults) { 539 std::stable_sort(Results, Results + NumResults); 540 541 if (!Context.getPreferredType().isNull()) 542 OS << "PREFERRED-TYPE: " << Context.getPreferredType().getAsString() 543 << "\n"; 544 545 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter(); 546 // Print the completions. 547 for (unsigned I = 0; I != NumResults; ++I) { 548 if (!Filter.empty() && isResultFilteredOut(Filter, Results[I])) 549 continue; 550 OS << "COMPLETION: "; 551 switch (Results[I].Kind) { 552 case CodeCompletionResult::RK_Declaration: 553 OS << *Results[I].Declaration; 554 { 555 std::vector<std::string> Tags; 556 if (Results[I].Hidden) 557 Tags.push_back("Hidden"); 558 if (Results[I].InBaseClass) 559 Tags.push_back("InBase"); 560 if (Results[I].Availability == 561 CXAvailabilityKind::CXAvailability_NotAccessible) 562 Tags.push_back("Inaccessible"); 563 if (!Tags.empty()) 564 OS << " (" << llvm::join(Tags, ",") << ")"; 565 } 566 if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString( 567 SemaRef, Context, getAllocator(), CCTUInfo, 568 includeBriefComments())) { 569 OS << " : " << CCS->getAsString(); 570 if (const char *BriefComment = CCS->getBriefComment()) 571 OS << " : " << BriefComment; 572 } 573 break; 574 575 case CodeCompletionResult::RK_Keyword: 576 OS << Results[I].Keyword; 577 break; 578 579 case CodeCompletionResult::RK_Macro: 580 OS << Results[I].Macro->getName(); 581 if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString( 582 SemaRef, Context, getAllocator(), CCTUInfo, 583 includeBriefComments())) { 584 OS << " : " << CCS->getAsString(); 585 } 586 break; 587 588 case CodeCompletionResult::RK_Pattern: 589 OS << "Pattern : " << Results[I].Pattern->getAsString(); 590 break; 591 } 592 for (const FixItHint &FixIt : Results[I].FixIts) { 593 const SourceLocation BLoc = FixIt.RemoveRange.getBegin(); 594 const SourceLocation ELoc = FixIt.RemoveRange.getEnd(); 595 596 SourceManager &SM = SemaRef.SourceMgr; 597 std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc); 598 std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc); 599 // Adjust for token ranges. 600 if (FixIt.RemoveRange.isTokenRange()) 601 EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts); 602 603 OS << " (requires fix-it:" 604 << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':' 605 << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' 606 << SM.getLineNumber(EInfo.first, EInfo.second) << ':' 607 << SM.getColumnNumber(EInfo.first, EInfo.second) << "}" 608 << " to \"" << FixIt.CodeToInsert << "\")"; 609 } 610 OS << '\n'; 611 } 612 } 613 614 // This function is used solely to preserve the former presentation of overloads 615 // by "clang -cc1 -code-completion-at", since CodeCompletionString::getAsString 616 // needs to be improved for printing the newer and more detailed overload 617 // chunks. 618 static std::string getOverloadAsString(const CodeCompletionString &CCS) { 619 std::string Result; 620 llvm::raw_string_ostream OS(Result); 621 622 for (auto &C : CCS) { 623 switch (C.Kind) { 624 case CodeCompletionString::CK_Informative: 625 case CodeCompletionString::CK_ResultType: 626 OS << "[#" << C.Text << "#]"; 627 break; 628 629 case CodeCompletionString::CK_CurrentParameter: 630 OS << "<#" << C.Text << "#>"; 631 break; 632 633 // FIXME: We can also print optional parameters of an overload. 634 case CodeCompletionString::CK_Optional: 635 break; 636 637 default: 638 OS << C.Text; 639 break; 640 } 641 } 642 return OS.str(); 643 } 644 645 void PrintingCodeCompleteConsumer::ProcessOverloadCandidates( 646 Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates, 647 unsigned NumCandidates, SourceLocation OpenParLoc) { 648 OS << "OPENING_PAREN_LOC: "; 649 OpenParLoc.print(OS, SemaRef.getSourceManager()); 650 OS << "\n"; 651 652 for (unsigned I = 0; I != NumCandidates; ++I) { 653 if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString( 654 CurrentArg, SemaRef, getAllocator(), CCTUInfo, 655 includeBriefComments())) { 656 OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n"; 657 } 658 } 659 } 660 661 /// Retrieve the effective availability of the given declaration. 662 static AvailabilityResult getDeclAvailability(const Decl *D) { 663 AvailabilityResult AR = D->getAvailability(); 664 if (isa<EnumConstantDecl>(D)) 665 AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability()); 666 return AR; 667 } 668 669 void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { 670 switch (Kind) { 671 case RK_Pattern: 672 if (!Declaration) { 673 // Do nothing: Patterns can come with cursor kinds! 674 break; 675 } 676 LLVM_FALLTHROUGH; 677 678 case RK_Declaration: { 679 // Set the availability based on attributes. 680 switch (getDeclAvailability(Declaration)) { 681 case AR_Available: 682 case AR_NotYetIntroduced: 683 Availability = CXAvailability_Available; 684 break; 685 686 case AR_Deprecated: 687 Availability = CXAvailability_Deprecated; 688 break; 689 690 case AR_Unavailable: 691 Availability = CXAvailability_NotAvailable; 692 break; 693 } 694 695 if (const auto *Function = dyn_cast<FunctionDecl>(Declaration)) 696 if (Function->isDeleted()) 697 Availability = CXAvailability_NotAvailable; 698 699 CursorKind = getCursorKindForDecl(Declaration); 700 if (CursorKind == CXCursor_UnexposedDecl) { 701 // FIXME: Forward declarations of Objective-C classes and protocols 702 // are not directly exposed, but we want code completion to treat them 703 // like a definition. 704 if (isa<ObjCInterfaceDecl>(Declaration)) 705 CursorKind = CXCursor_ObjCInterfaceDecl; 706 else if (isa<ObjCProtocolDecl>(Declaration)) 707 CursorKind = CXCursor_ObjCProtocolDecl; 708 else 709 CursorKind = CXCursor_NotImplemented; 710 } 711 break; 712 } 713 714 case RK_Macro: 715 case RK_Keyword: 716 llvm_unreachable("Macro and keyword kinds are handled by the constructors"); 717 } 718 719 if (!Accessible) 720 Availability = CXAvailability_NotAccessible; 721 } 722 723 /// Retrieve the name that should be used to order a result. 724 /// 725 /// If the name needs to be constructed as a string, that string will be 726 /// saved into Saved and the returned StringRef will refer to it. 727 StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const { 728 switch (Kind) { 729 case RK_Keyword: 730 return Keyword; 731 case RK_Pattern: 732 return Pattern->getTypedText(); 733 case RK_Macro: 734 return Macro->getName(); 735 case RK_Declaration: 736 // Handle declarations below. 737 break; 738 } 739 740 DeclarationName Name = Declaration->getDeclName(); 741 742 // If the name is a simple identifier (by far the common case), or a 743 // zero-argument selector, just return a reference to that identifier. 744 if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) 745 return Id->getName(); 746 if (Name.isObjCZeroArgSelector()) 747 if (IdentifierInfo *Id = Name.getObjCSelector().getIdentifierInfoForSlot(0)) 748 return Id->getName(); 749 750 Saved = Name.getAsString(); 751 return Saved; 752 } 753 754 bool clang::operator<(const CodeCompletionResult &X, 755 const CodeCompletionResult &Y) { 756 std::string XSaved, YSaved; 757 StringRef XStr = X.getOrderedName(XSaved); 758 StringRef YStr = Y.getOrderedName(YSaved); 759 int cmp = XStr.compare_lower(YStr); 760 if (cmp) 761 return cmp < 0; 762 763 // If case-insensitive comparison fails, try case-sensitive comparison. 764 return XStr.compare(YStr) < 0; 765 } 766