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 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 276 CodeCompletionString::Chunk::CreateCurrentParameter( 277 const char *CurrentParameter) { 278 return Chunk(CK_CurrentParameter, CurrentParameter); 279 } 280 281 CodeCompletionString::CodeCompletionString(const Chunk *Chunks, 282 unsigned NumChunks, 283 unsigned Priority, 284 CXAvailabilityKind Availability, 285 const char **Annotations, 286 unsigned NumAnnotations, 287 StringRef ParentName, 288 const char *BriefComment) 289 : NumChunks(NumChunks), NumAnnotations(NumAnnotations), 290 Priority(Priority), Availability(Availability), 291 ParentName(ParentName), BriefComment(BriefComment) { 292 assert(NumChunks <= 0xffff); 293 assert(NumAnnotations <= 0xffff); 294 295 Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1); 296 for (unsigned I = 0; I != NumChunks; ++I) 297 StoredChunks[I] = Chunks[I]; 298 299 const char **StoredAnnotations = reinterpret_cast<const char **>(StoredChunks + NumChunks); 300 for (unsigned I = 0; I != NumAnnotations; ++I) 301 StoredAnnotations[I] = Annotations[I]; 302 } 303 304 unsigned CodeCompletionString::getAnnotationCount() const { 305 return NumAnnotations; 306 } 307 308 const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const { 309 if (AnnotationNr < NumAnnotations) 310 return reinterpret_cast<const char * const*>(end())[AnnotationNr]; 311 else 312 return nullptr; 313 } 314 315 std::string CodeCompletionString::getAsString() const { 316 std::string Result; 317 llvm::raw_string_ostream OS(Result); 318 319 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { 320 switch (C->Kind) { 321 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; 322 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; 323 324 case CK_Informative: 325 case CK_ResultType: 326 OS << "[#" << C->Text << "#]"; 327 break; 328 329 case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; 330 default: OS << C->Text; break; 331 } 332 } 333 return OS.str(); 334 } 335 336 const char *CodeCompletionString::getTypedText() const { 337 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) 338 if (C->Kind == CK_TypedText) 339 return C->Text; 340 341 return nullptr; 342 } 343 344 const char *CodeCompletionAllocator::CopyString(const Twine &String) { 345 SmallString<128> Data; 346 StringRef Ref = String.toStringRef(Data); 347 // FIXME: It would be more efficient to teach Twine to tell us its size and 348 // then add a routine there to fill in an allocated char* with the contents 349 // of the string. 350 char *Mem = (char *)Allocate(Ref.size() + 1, 1); 351 std::copy(Ref.begin(), Ref.end(), Mem); 352 Mem[Ref.size()] = 0; 353 return Mem; 354 } 355 356 StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { 357 const NamedDecl *ND = dyn_cast<NamedDecl>(DC); 358 if (!ND) 359 return {}; 360 361 // Check whether we've already cached the parent name. 362 StringRef &CachedParentName = ParentNames[DC]; 363 if (!CachedParentName.empty()) 364 return CachedParentName; 365 366 // If we already processed this DeclContext and assigned empty to it, the 367 // data pointer will be non-null. 368 if (CachedParentName.data() != nullptr) 369 return {}; 370 371 // Find the interesting names. 372 SmallVector<const DeclContext *, 2> Contexts; 373 while (DC && !DC->isFunctionOrMethod()) { 374 if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) { 375 if (ND->getIdentifier()) 376 Contexts.push_back(DC); 377 } 378 379 DC = DC->getParent(); 380 } 381 382 { 383 SmallString<128> S; 384 llvm::raw_svector_ostream OS(S); 385 bool First = true; 386 for (unsigned I = Contexts.size(); I != 0; --I) { 387 if (First) 388 First = false; 389 else { 390 OS << "::"; 391 } 392 393 const DeclContext *CurDC = Contexts[I-1]; 394 if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) 395 CurDC = CatImpl->getCategoryDecl(); 396 397 if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { 398 const ObjCInterfaceDecl *Interface = Cat->getClassInterface(); 399 if (!Interface) { 400 // Assign an empty StringRef but with non-null data to distinguish 401 // between empty because we didn't process the DeclContext yet. 402 CachedParentName = StringRef((const char *)(uintptr_t)~0U, 0); 403 return {}; 404 } 405 406 OS << Interface->getName() << '(' << Cat->getName() << ')'; 407 } else { 408 OS << cast<NamedDecl>(CurDC)->getName(); 409 } 410 } 411 412 CachedParentName = AllocatorRef->CopyString(OS.str()); 413 } 414 415 return CachedParentName; 416 } 417 418 CodeCompletionString *CodeCompletionBuilder::TakeString() { 419 void *Mem = getAllocator().Allocate( 420 sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() + 421 sizeof(const char *) * Annotations.size(), 422 alignof(CodeCompletionString)); 423 CodeCompletionString *Result 424 = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(), 425 Priority, Availability, 426 Annotations.data(), Annotations.size(), 427 ParentName, BriefComment); 428 Chunks.clear(); 429 return Result; 430 } 431 432 void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) { 433 Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text)); 434 } 435 436 void CodeCompletionBuilder::AddTextChunk(const char *Text) { 437 Chunks.push_back(Chunk::CreateText(Text)); 438 } 439 440 void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) { 441 Chunks.push_back(Chunk::CreateOptional(Optional)); 442 } 443 444 void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) { 445 Chunks.push_back(Chunk::CreatePlaceholder(Placeholder)); 446 } 447 448 void CodeCompletionBuilder::AddInformativeChunk(const char *Text) { 449 Chunks.push_back(Chunk::CreateInformative(Text)); 450 } 451 452 void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) { 453 Chunks.push_back(Chunk::CreateResultType(ResultType)); 454 } 455 456 void 457 CodeCompletionBuilder::AddCurrentParameterChunk(const char *CurrentParameter) { 458 Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter)); 459 } 460 461 void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK, 462 const char *Text) { 463 Chunks.push_back(Chunk(CK, Text)); 464 } 465 466 void CodeCompletionBuilder::addParentContext(const DeclContext *DC) { 467 if (DC->isTranslationUnit()) 468 return; 469 470 if (DC->isFunctionOrMethod()) 471 return; 472 473 const NamedDecl *ND = dyn_cast<NamedDecl>(DC); 474 if (!ND) 475 return; 476 477 ParentName = getCodeCompletionTUInfo().getParentName(DC); 478 } 479 480 void CodeCompletionBuilder::addBriefComment(StringRef Comment) { 481 BriefComment = Allocator.CopyString(Comment); 482 } 483 484 //===----------------------------------------------------------------------===// 485 // Code completion overload candidate implementation 486 //===----------------------------------------------------------------------===// 487 FunctionDecl * 488 CodeCompleteConsumer::OverloadCandidate::getFunction() const { 489 if (getKind() == CK_Function) 490 return Function; 491 else if (getKind() == CK_FunctionTemplate) 492 return FunctionTemplate->getTemplatedDecl(); 493 else 494 return nullptr; 495 } 496 497 const FunctionType * 498 CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { 499 switch (Kind) { 500 case CK_Function: 501 return Function->getType()->getAs<FunctionType>(); 502 503 case CK_FunctionTemplate: 504 return FunctionTemplate->getTemplatedDecl()->getType() 505 ->getAs<FunctionType>(); 506 507 case CK_FunctionType: 508 return Type; 509 } 510 511 llvm_unreachable("Invalid CandidateKind!"); 512 } 513 514 //===----------------------------------------------------------------------===// 515 // Code completion consumer implementation 516 //===----------------------------------------------------------------------===// 517 518 CodeCompleteConsumer::~CodeCompleteConsumer() = default; 519 520 bool PrintingCodeCompleteConsumer::isResultFilteredOut(StringRef Filter, 521 CodeCompletionResult Result) { 522 switch (Result.Kind) { 523 case CodeCompletionResult::RK_Declaration: 524 return !(Result.Declaration->getIdentifier() && 525 Result.Declaration->getIdentifier()->getName().startswith(Filter)); 526 case CodeCompletionResult::RK_Keyword: 527 return !StringRef(Result.Keyword).startswith(Filter); 528 case CodeCompletionResult::RK_Macro: 529 return !Result.Macro->getName().startswith(Filter); 530 case CodeCompletionResult::RK_Pattern: 531 return !(Result.Pattern->getTypedText() && 532 StringRef(Result.Pattern->getTypedText()).startswith(Filter)); 533 } 534 llvm_unreachable("Unknown code completion result Kind."); 535 } 536 537 void 538 PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 539 CodeCompletionContext Context, 540 CodeCompletionResult *Results, 541 unsigned NumResults) { 542 std::stable_sort(Results, Results + NumResults); 543 544 StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter(); 545 546 // Print the results. 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 (!Tags.empty()) 561 OS << " (" << llvm::join(Tags, ",") << ")"; 562 } 563 if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString( 564 SemaRef, Context, getAllocator(), CCTUInfo, 565 includeBriefComments())) { 566 OS << " : " << CCS->getAsString(); 567 if (const char *BriefComment = CCS->getBriefComment()) 568 OS << " : " << BriefComment; 569 } 570 for (const FixItHint &FixIt : Results[I].FixIts) { 571 const SourceLocation BLoc = FixIt.RemoveRange.getBegin(); 572 const SourceLocation ELoc = FixIt.RemoveRange.getEnd(); 573 574 SourceManager &SM = SemaRef.SourceMgr; 575 std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc); 576 std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc); 577 // Adjust for token ranges. 578 if (FixIt.RemoveRange.isTokenRange()) 579 EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts); 580 581 OS << " (requires fix-it:" 582 << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':' 583 << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' 584 << SM.getLineNumber(EInfo.first, EInfo.second) << ':' 585 << SM.getColumnNumber(EInfo.first, EInfo.second) << "}" 586 << " to \"" << FixIt.CodeToInsert << "\")"; 587 } 588 OS << '\n'; 589 break; 590 591 case CodeCompletionResult::RK_Keyword: 592 OS << Results[I].Keyword << '\n'; 593 break; 594 595 case CodeCompletionResult::RK_Macro: 596 OS << Results[I].Macro->getName(); 597 if (CodeCompletionString *CCS 598 = Results[I].CreateCodeCompletionString(SemaRef, Context, 599 getAllocator(), 600 CCTUInfo, 601 includeBriefComments())) { 602 OS << " : " << CCS->getAsString(); 603 } 604 OS << '\n'; 605 break; 606 607 case CodeCompletionResult::RK_Pattern: 608 OS << "Pattern : " 609 << Results[I].Pattern->getAsString() << '\n'; 610 break; 611 } 612 } 613 } 614 615 // This function is used solely to preserve the former presentation of overloads 616 // by "clang -cc1 -code-completion-at", since CodeCompletionString::getAsString 617 // needs to be improved for printing the newer and more detailed overload 618 // chunks. 619 static std::string getOverloadAsString(const CodeCompletionString &CCS) { 620 std::string Result; 621 llvm::raw_string_ostream OS(Result); 622 623 for (auto &C : CCS) { 624 switch (C.Kind) { 625 case CodeCompletionString::CK_Informative: 626 case CodeCompletionString::CK_ResultType: 627 OS << "[#" << C.Text << "#]"; 628 break; 629 630 case CodeCompletionString::CK_CurrentParameter: 631 OS << "<#" << C.Text << "#>"; 632 break; 633 634 // FIXME: We can also print optional parameters of an overload. 635 case CodeCompletionString::CK_Optional: 636 break; 637 638 default: OS << C.Text; 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 FunctionDecl *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 747 = 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 cmp = XStr.compare(YStr); 765 if (cmp) 766 return cmp < 0; 767 768 return false; 769 } 770