CodeCompleteConsumer.cpp revision 360660
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
38using namespace clang;
39
40//===----------------------------------------------------------------------===//
41// Code completion context implementation
42//===----------------------------------------------------------------------===//
43
44bool 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
90StringRef 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
173CodeCompletionString::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
246CodeCompletionString::Chunk
247CodeCompletionString::Chunk::CreateText(const char *Text) {
248  return Chunk(CK_Text, Text);
249}
250
251CodeCompletionString::Chunk
252CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) {
253  Chunk Result;
254  Result.Kind = CK_Optional;
255  Result.Optional = Optional;
256  return Result;
257}
258
259CodeCompletionString::Chunk
260CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
261  return Chunk(CK_Placeholder, Placeholder);
262}
263
264CodeCompletionString::Chunk
265CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
266  return Chunk(CK_Informative, Informative);
267}
268
269CodeCompletionString::Chunk
270CodeCompletionString::Chunk::CreateResultType(const char *ResultType) {
271  return Chunk(CK_ResultType, ResultType);
272}
273
274CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateCurrentParameter(
275    const char *CurrentParameter) {
276  return Chunk(CK_CurrentParameter, CurrentParameter);
277}
278
279CodeCompletionString::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
299unsigned CodeCompletionString::getAnnotationCount() const {
300  return NumAnnotations;
301}
302
303const 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
310std::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
337const 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
345const 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
357StringRef 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
419CodeCompletionString *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
431void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) {
432  Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text));
433}
434
435void CodeCompletionBuilder::AddTextChunk(const char *Text) {
436  Chunks.push_back(Chunk::CreateText(Text));
437}
438
439void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) {
440  Chunks.push_back(Chunk::CreateOptional(Optional));
441}
442
443void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) {
444  Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
445}
446
447void CodeCompletionBuilder::AddInformativeChunk(const char *Text) {
448  Chunks.push_back(Chunk::CreateInformative(Text));
449}
450
451void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) {
452  Chunks.push_back(Chunk::CreateResultType(ResultType));
453}
454
455void CodeCompletionBuilder::AddCurrentParameterChunk(
456    const char *CurrentParameter) {
457  Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter));
458}
459
460void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK,
461                                     const char *Text) {
462  Chunks.push_back(Chunk(CK, Text));
463}
464
465void 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
479void CodeCompletionBuilder::addBriefComment(StringRef Comment) {
480  BriefComment = Allocator.CopyString(Comment);
481}
482
483//===----------------------------------------------------------------------===//
484// Code completion overload candidate implementation
485//===----------------------------------------------------------------------===//
486FunctionDecl *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
495const FunctionType *
496CodeCompleteConsumer::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
517CodeCompleteConsumer::~CodeCompleteConsumer() = default;
518
519bool 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
536void 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      for (const FixItHint &FixIt : Results[I].FixIts) {
574        const SourceLocation BLoc = FixIt.RemoveRange.getBegin();
575        const SourceLocation ELoc = FixIt.RemoveRange.getEnd();
576
577        SourceManager &SM = SemaRef.SourceMgr;
578        std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
579        std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
580        // Adjust for token ranges.
581        if (FixIt.RemoveRange.isTokenRange())
582          EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts);
583
584        OS << " (requires fix-it:"
585           << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
586           << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
587           << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
588           << SM.getColumnNumber(EInfo.first, EInfo.second) << "}"
589           << " to \"" << FixIt.CodeToInsert << "\")";
590      }
591      OS << '\n';
592      break;
593
594    case CodeCompletionResult::RK_Keyword:
595      OS << Results[I].Keyword << '\n';
596      break;
597
598    case CodeCompletionResult::RK_Macro:
599      OS << Results[I].Macro->getName();
600      if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(
601              SemaRef, Context, getAllocator(), CCTUInfo,
602              includeBriefComments())) {
603        OS << " : " << CCS->getAsString();
604      }
605      OS << '\n';
606      break;
607
608    case CodeCompletionResult::RK_Pattern:
609      OS << "Pattern : " << 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.
619static 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:
639      OS << C.Text;
640      break;
641    }
642  }
643  return OS.str();
644}
645
646void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
647    Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates,
648    unsigned NumCandidates, SourceLocation OpenParLoc) {
649  OS << "OPENING_PAREN_LOC: ";
650  OpenParLoc.print(OS, SemaRef.getSourceManager());
651  OS << "\n";
652
653  for (unsigned I = 0; I != NumCandidates; ++I) {
654    if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(
655            CurrentArg, SemaRef, getAllocator(), CCTUInfo,
656            includeBriefComments())) {
657      OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
658    }
659  }
660}
661
662/// Retrieve the effective availability of the given declaration.
663static AvailabilityResult getDeclAvailability(const Decl *D) {
664  AvailabilityResult AR = D->getAvailability();
665  if (isa<EnumConstantDecl>(D))
666    AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability());
667  return AR;
668}
669
670void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
671  switch (Kind) {
672  case RK_Pattern:
673    if (!Declaration) {
674      // Do nothing: Patterns can come with cursor kinds!
675      break;
676    }
677    LLVM_FALLTHROUGH;
678
679  case RK_Declaration: {
680    // Set the availability based on attributes.
681    switch (getDeclAvailability(Declaration)) {
682    case AR_Available:
683    case AR_NotYetIntroduced:
684      Availability = CXAvailability_Available;
685      break;
686
687    case AR_Deprecated:
688      Availability = CXAvailability_Deprecated;
689      break;
690
691    case AR_Unavailable:
692      Availability = CXAvailability_NotAvailable;
693      break;
694    }
695
696    if (const auto *Function = dyn_cast<FunctionDecl>(Declaration))
697      if (Function->isDeleted())
698        Availability = CXAvailability_NotAvailable;
699
700    CursorKind = getCursorKindForDecl(Declaration);
701    if (CursorKind == CXCursor_UnexposedDecl) {
702      // FIXME: Forward declarations of Objective-C classes and protocols
703      // are not directly exposed, but we want code completion to treat them
704      // like a definition.
705      if (isa<ObjCInterfaceDecl>(Declaration))
706        CursorKind = CXCursor_ObjCInterfaceDecl;
707      else if (isa<ObjCProtocolDecl>(Declaration))
708        CursorKind = CXCursor_ObjCProtocolDecl;
709      else
710        CursorKind = CXCursor_NotImplemented;
711    }
712    break;
713  }
714
715  case RK_Macro:
716  case RK_Keyword:
717    llvm_unreachable("Macro and keyword kinds are handled by the constructors");
718  }
719
720  if (!Accessible)
721    Availability = CXAvailability_NotAccessible;
722}
723
724/// Retrieve the name that should be used to order a result.
725///
726/// If the name needs to be constructed as a string, that string will be
727/// saved into Saved and the returned StringRef will refer to it.
728StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const {
729  switch (Kind) {
730  case RK_Keyword:
731    return Keyword;
732  case RK_Pattern:
733    return Pattern->getTypedText();
734  case RK_Macro:
735    return Macro->getName();
736  case RK_Declaration:
737    // Handle declarations below.
738    break;
739  }
740
741  DeclarationName Name = Declaration->getDeclName();
742
743  // If the name is a simple identifier (by far the common case), or a
744  // zero-argument selector, just return a reference to that identifier.
745  if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
746    return Id->getName();
747  if (Name.isObjCZeroArgSelector())
748    if (IdentifierInfo *Id = Name.getObjCSelector().getIdentifierInfoForSlot(0))
749      return Id->getName();
750
751  Saved = Name.getAsString();
752  return Saved;
753}
754
755bool clang::operator<(const CodeCompletionResult &X,
756                      const CodeCompletionResult &Y) {
757  std::string XSaved, YSaved;
758  StringRef XStr = X.getOrderedName(XSaved);
759  StringRef YStr = Y.getOrderedName(YSaved);
760  int cmp = XStr.compare_lower(YStr);
761  if (cmp)
762    return cmp < 0;
763
764  // If case-insensitive comparison fails, try case-sensitive comparison.
765  return XStr.compare(YStr) < 0;
766}
767