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