148675466SDimitry Andric //===- CodeCompleteConsumer.cpp - Code Completion Interface ---------------===//
24c8b2481SRoman Divacky //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64c8b2481SRoman Divacky //
74c8b2481SRoman Divacky //===----------------------------------------------------------------------===//
84c8b2481SRoman Divacky //
94c8b2481SRoman Divacky // This file implements the CodeCompleteConsumer class.
104c8b2481SRoman Divacky //
114c8b2481SRoman Divacky //===----------------------------------------------------------------------===//
1248675466SDimitry Andric
134c8b2481SRoman Divacky #include "clang/Sema/CodeCompleteConsumer.h"
14809500fcSDimitry Andric #include "clang-c/Index.h"
1548675466SDimitry Andric #include "clang/AST/Decl.h"
1648675466SDimitry Andric #include "clang/AST/DeclBase.h"
173d1dcd9bSDimitry Andric #include "clang/AST/DeclObjC.h"
183d1dcd9bSDimitry Andric #include "clang/AST/DeclTemplate.h"
1948675466SDimitry Andric #include "clang/AST/DeclarationName.h"
2048675466SDimitry Andric #include "clang/AST/Type.h"
2148675466SDimitry Andric #include "clang/Basic/IdentifierTable.h"
22bab175ecSDimitry Andric #include "clang/Lex/Preprocessor.h"
23676fbe81SDimitry Andric #include "clang/Sema/Sema.h"
24809500fcSDimitry Andric #include "llvm/ADT/SmallString.h"
2548675466SDimitry Andric #include "llvm/ADT/SmallVector.h"
26cfca06d7SDimitry Andric #include "llvm/ADT/StringExtras.h"
2748675466SDimitry Andric #include "llvm/ADT/StringRef.h"
28bca07a45SDimitry Andric #include "llvm/ADT/Twine.h"
2948675466SDimitry Andric #include "llvm/Support/Casting.h"
3048675466SDimitry Andric #include "llvm/Support/Compiler.h"
3148675466SDimitry Andric #include "llvm/Support/ErrorHandling.h"
32676fbe81SDimitry Andric #include "llvm/Support/FormatVariadic.h"
334c8b2481SRoman Divacky #include "llvm/Support/raw_ostream.h"
344c8b2481SRoman Divacky #include <algorithm>
3548675466SDimitry Andric #include <cassert>
3648675466SDimitry Andric #include <cstdint>
3748675466SDimitry Andric #include <string>
38b3d5a323SRoman Divacky
394c8b2481SRoman Divacky using namespace clang;
404c8b2481SRoman Divacky
414c8b2481SRoman Divacky //===----------------------------------------------------------------------===//
42bca07a45SDimitry Andric // Code completion context implementation
43bca07a45SDimitry Andric //===----------------------------------------------------------------------===//
44bca07a45SDimitry Andric
wantConstructorResults() const45bca07a45SDimitry Andric bool CodeCompletionContext::wantConstructorResults() const {
4648675466SDimitry Andric switch (CCKind) {
47bca07a45SDimitry Andric case CCC_Recovery:
48bca07a45SDimitry Andric case CCC_Statement:
49bca07a45SDimitry Andric case CCC_Expression:
50bca07a45SDimitry Andric case CCC_ObjCMessageReceiver:
51bca07a45SDimitry Andric case CCC_ParenthesizedExpression:
52676fbe81SDimitry Andric case CCC_Symbol:
53676fbe81SDimitry Andric case CCC_SymbolOrNewName:
54b1c73532SDimitry Andric case CCC_TopLevelOrExpression:
55bca07a45SDimitry Andric return true;
56bca07a45SDimitry Andric
57bca07a45SDimitry Andric case CCC_TopLevel:
58bca07a45SDimitry Andric case CCC_ObjCInterface:
59bca07a45SDimitry Andric case CCC_ObjCImplementation:
60bca07a45SDimitry Andric case CCC_ObjCIvarList:
61bca07a45SDimitry Andric case CCC_ClassStructUnion:
62180abc3dSDimitry Andric case CCC_DotMemberAccess:
63180abc3dSDimitry Andric case CCC_ArrowMemberAccess:
64180abc3dSDimitry Andric case CCC_ObjCPropertyAccess:
65bca07a45SDimitry Andric case CCC_EnumTag:
66bca07a45SDimitry Andric case CCC_UnionTag:
67bca07a45SDimitry Andric case CCC_ClassOrStructTag:
68bca07a45SDimitry Andric case CCC_ObjCProtocolName:
69bca07a45SDimitry Andric case CCC_Namespace:
70bca07a45SDimitry Andric case CCC_Type:
71676fbe81SDimitry Andric case CCC_NewName:
72bca07a45SDimitry Andric case CCC_MacroName:
73bca07a45SDimitry Andric case CCC_MacroNameUse:
74bca07a45SDimitry Andric case CCC_PreprocessorExpression:
75bca07a45SDimitry Andric case CCC_PreprocessorDirective:
76bca07a45SDimitry Andric case CCC_NaturalLanguage:
77bca07a45SDimitry Andric case CCC_SelectorName:
78bca07a45SDimitry Andric case CCC_TypeQualifiers:
79bca07a45SDimitry Andric case CCC_Other:
80bca07a45SDimitry Andric case CCC_OtherWithMacros:
81180abc3dSDimitry Andric case CCC_ObjCInstanceMessage:
82180abc3dSDimitry Andric case CCC_ObjCClassMessage:
8336981b17SDimitry Andric case CCC_ObjCInterfaceName:
84180abc3dSDimitry Andric case CCC_ObjCCategoryName:
85676fbe81SDimitry Andric case CCC_IncludedFile:
86c0981da4SDimitry Andric case CCC_Attribute:
877fa27ce4SDimitry Andric case CCC_ObjCClassForwardDecl:
88bca07a45SDimitry Andric return false;
89bca07a45SDimitry Andric }
90bca07a45SDimitry Andric
91dbe13110SDimitry Andric llvm_unreachable("Invalid CodeCompletionContext::Kind!");
92bca07a45SDimitry Andric }
93bca07a45SDimitry Andric
getCompletionKindString(CodeCompletionContext::Kind Kind)9448675466SDimitry Andric StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) {
9548675466SDimitry Andric using CCKind = CodeCompletionContext::Kind;
9648675466SDimitry Andric switch (Kind) {
9748675466SDimitry Andric case CCKind::CCC_Other:
9848675466SDimitry Andric return "Other";
9948675466SDimitry Andric case CCKind::CCC_OtherWithMacros:
10048675466SDimitry Andric return "OtherWithMacros";
10148675466SDimitry Andric case CCKind::CCC_TopLevel:
10248675466SDimitry Andric return "TopLevel";
10348675466SDimitry Andric case CCKind::CCC_ObjCInterface:
10448675466SDimitry Andric return "ObjCInterface";
10548675466SDimitry Andric case CCKind::CCC_ObjCImplementation:
10648675466SDimitry Andric return "ObjCImplementation";
10748675466SDimitry Andric case CCKind::CCC_ObjCIvarList:
10848675466SDimitry Andric return "ObjCIvarList";
10948675466SDimitry Andric case CCKind::CCC_ClassStructUnion:
11048675466SDimitry Andric return "ClassStructUnion";
11148675466SDimitry Andric case CCKind::CCC_Statement:
11248675466SDimitry Andric return "Statement";
11348675466SDimitry Andric case CCKind::CCC_Expression:
11448675466SDimitry Andric return "Expression";
11548675466SDimitry Andric case CCKind::CCC_ObjCMessageReceiver:
11648675466SDimitry Andric return "ObjCMessageReceiver";
11748675466SDimitry Andric case CCKind::CCC_DotMemberAccess:
11848675466SDimitry Andric return "DotMemberAccess";
11948675466SDimitry Andric case CCKind::CCC_ArrowMemberAccess:
12048675466SDimitry Andric return "ArrowMemberAccess";
12148675466SDimitry Andric case CCKind::CCC_ObjCPropertyAccess:
12248675466SDimitry Andric return "ObjCPropertyAccess";
12348675466SDimitry Andric case CCKind::CCC_EnumTag:
12448675466SDimitry Andric return "EnumTag";
12548675466SDimitry Andric case CCKind::CCC_UnionTag:
12648675466SDimitry Andric return "UnionTag";
12748675466SDimitry Andric case CCKind::CCC_ClassOrStructTag:
12848675466SDimitry Andric return "ClassOrStructTag";
12948675466SDimitry Andric case CCKind::CCC_ObjCProtocolName:
13048675466SDimitry Andric return "ObjCProtocolName";
13148675466SDimitry Andric case CCKind::CCC_Namespace:
13248675466SDimitry Andric return "Namespace";
13348675466SDimitry Andric case CCKind::CCC_Type:
13448675466SDimitry Andric return "Type";
135676fbe81SDimitry Andric case CCKind::CCC_NewName:
136676fbe81SDimitry Andric return "NewName";
137676fbe81SDimitry Andric case CCKind::CCC_Symbol:
138676fbe81SDimitry Andric return "Symbol";
139676fbe81SDimitry Andric case CCKind::CCC_SymbolOrNewName:
140676fbe81SDimitry Andric return "SymbolOrNewName";
14148675466SDimitry Andric case CCKind::CCC_MacroName:
14248675466SDimitry Andric return "MacroName";
14348675466SDimitry Andric case CCKind::CCC_MacroNameUse:
14448675466SDimitry Andric return "MacroNameUse";
14548675466SDimitry Andric case CCKind::CCC_PreprocessorExpression:
14648675466SDimitry Andric return "PreprocessorExpression";
14748675466SDimitry Andric case CCKind::CCC_PreprocessorDirective:
14848675466SDimitry Andric return "PreprocessorDirective";
14948675466SDimitry Andric case CCKind::CCC_NaturalLanguage:
15048675466SDimitry Andric return "NaturalLanguage";
15148675466SDimitry Andric case CCKind::CCC_SelectorName:
15248675466SDimitry Andric return "SelectorName";
15348675466SDimitry Andric case CCKind::CCC_TypeQualifiers:
15448675466SDimitry Andric return "TypeQualifiers";
15548675466SDimitry Andric case CCKind::CCC_ParenthesizedExpression:
15648675466SDimitry Andric return "ParenthesizedExpression";
15748675466SDimitry Andric case CCKind::CCC_ObjCInstanceMessage:
15848675466SDimitry Andric return "ObjCInstanceMessage";
15948675466SDimitry Andric case CCKind::CCC_ObjCClassMessage:
16048675466SDimitry Andric return "ObjCClassMessage";
16148675466SDimitry Andric case CCKind::CCC_ObjCInterfaceName:
16248675466SDimitry Andric return "ObjCInterfaceName";
16348675466SDimitry Andric case CCKind::CCC_ObjCCategoryName:
16448675466SDimitry Andric return "ObjCCategoryName";
165676fbe81SDimitry Andric case CCKind::CCC_IncludedFile:
166676fbe81SDimitry Andric return "IncludedFile";
167c0981da4SDimitry Andric case CCKind::CCC_Attribute:
168c0981da4SDimitry Andric return "Attribute";
16948675466SDimitry Andric case CCKind::CCC_Recovery:
17048675466SDimitry Andric return "Recovery";
1717fa27ce4SDimitry Andric case CCKind::CCC_ObjCClassForwardDecl:
1727fa27ce4SDimitry Andric return "ObjCClassForwardDecl";
173b1c73532SDimitry Andric case CCKind::CCC_TopLevelOrExpression:
174b1c73532SDimitry Andric return "ReplTopLevel";
17548675466SDimitry Andric }
17648675466SDimitry Andric llvm_unreachable("Invalid CodeCompletionContext::Kind!");
17748675466SDimitry Andric }
17848675466SDimitry Andric
179bca07a45SDimitry Andric //===----------------------------------------------------------------------===//
1804c8b2481SRoman Divacky // Code completion string implementation
1814c8b2481SRoman Divacky //===----------------------------------------------------------------------===//
18248675466SDimitry Andric
Chunk(ChunkKind Kind,const char * Text)183bca07a45SDimitry Andric CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
18448675466SDimitry Andric : Kind(Kind), Text("") {
185b3d5a323SRoman Divacky switch (Kind) {
186b3d5a323SRoman Divacky case CK_TypedText:
187b3d5a323SRoman Divacky case CK_Text:
188b3d5a323SRoman Divacky case CK_Placeholder:
189b3d5a323SRoman Divacky case CK_Informative:
190abe15e55SRoman Divacky case CK_ResultType:
191bca07a45SDimitry Andric case CK_CurrentParameter:
192bca07a45SDimitry Andric this->Text = Text;
193b3d5a323SRoman Divacky break;
194b3d5a323SRoman Divacky
195b3d5a323SRoman Divacky case CK_Optional:
19634d02d0bSRoman Divacky llvm_unreachable("Optional strings cannot be created from text");
197b3d5a323SRoman Divacky
198b3d5a323SRoman Divacky case CK_LeftParen:
199b3d5a323SRoman Divacky this->Text = "(";
200b3d5a323SRoman Divacky break;
201b3d5a323SRoman Divacky
202b3d5a323SRoman Divacky case CK_RightParen:
203b3d5a323SRoman Divacky this->Text = ")";
204b3d5a323SRoman Divacky break;
205b3d5a323SRoman Divacky
206b3d5a323SRoman Divacky case CK_LeftBracket:
207b3d5a323SRoman Divacky this->Text = "[";
208b3d5a323SRoman Divacky break;
209b3d5a323SRoman Divacky
210b3d5a323SRoman Divacky case CK_RightBracket:
211b3d5a323SRoman Divacky this->Text = "]";
212b3d5a323SRoman Divacky break;
213b3d5a323SRoman Divacky
214b3d5a323SRoman Divacky case CK_LeftBrace:
215b3d5a323SRoman Divacky this->Text = "{";
216b3d5a323SRoman Divacky break;
217b3d5a323SRoman Divacky
218b3d5a323SRoman Divacky case CK_RightBrace:
219b3d5a323SRoman Divacky this->Text = "}";
220b3d5a323SRoman Divacky break;
221b3d5a323SRoman Divacky
222b3d5a323SRoman Divacky case CK_LeftAngle:
223b3d5a323SRoman Divacky this->Text = "<";
224b3d5a323SRoman Divacky break;
225b3d5a323SRoman Divacky
226b3d5a323SRoman Divacky case CK_RightAngle:
227b3d5a323SRoman Divacky this->Text = ">";
228b3d5a323SRoman Divacky break;
229b3d5a323SRoman Divacky
230b3d5a323SRoman Divacky case CK_Comma:
231b3d5a323SRoman Divacky this->Text = ", ";
232b3d5a323SRoman Divacky break;
233ee791ddeSRoman Divacky
234ee791ddeSRoman Divacky case CK_Colon:
235ee791ddeSRoman Divacky this->Text = ":";
236ee791ddeSRoman Divacky break;
237ee791ddeSRoman Divacky
238ee791ddeSRoman Divacky case CK_SemiColon:
239ee791ddeSRoman Divacky this->Text = ";";
240ee791ddeSRoman Divacky break;
241ee791ddeSRoman Divacky
242ee791ddeSRoman Divacky case CK_Equal:
243ee791ddeSRoman Divacky this->Text = " = ";
244ee791ddeSRoman Divacky break;
245ee791ddeSRoman Divacky
246ee791ddeSRoman Divacky case CK_HorizontalSpace:
247ee791ddeSRoman Divacky this->Text = " ";
248ee791ddeSRoman Divacky break;
249ee791ddeSRoman Divacky
250ee791ddeSRoman Divacky case CK_VerticalSpace:
251ee791ddeSRoman Divacky this->Text = "\n";
252ee791ddeSRoman Divacky break;
253b3d5a323SRoman Divacky }
2544c8b2481SRoman Divacky }
2554c8b2481SRoman Divacky
2564c8b2481SRoman Divacky CodeCompletionString::Chunk
CreateText(const char * Text)257bca07a45SDimitry Andric CodeCompletionString::Chunk::CreateText(const char *Text) {
2584c8b2481SRoman Divacky return Chunk(CK_Text, Text);
2594c8b2481SRoman Divacky }
2604c8b2481SRoman Divacky
2614c8b2481SRoman Divacky CodeCompletionString::Chunk
CreateOptional(CodeCompletionString * Optional)262bca07a45SDimitry Andric CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) {
2634c8b2481SRoman Divacky Chunk Result;
2644c8b2481SRoman Divacky Result.Kind = CK_Optional;
265bca07a45SDimitry Andric Result.Optional = Optional;
2664c8b2481SRoman Divacky return Result;
2674c8b2481SRoman Divacky }
2684c8b2481SRoman Divacky
2694c8b2481SRoman Divacky CodeCompletionString::Chunk
CreatePlaceholder(const char * Placeholder)270bca07a45SDimitry Andric CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
2714c8b2481SRoman Divacky return Chunk(CK_Placeholder, Placeholder);
2724c8b2481SRoman Divacky }
2734c8b2481SRoman Divacky
2744c8b2481SRoman Divacky CodeCompletionString::Chunk
CreateInformative(const char * Informative)275bca07a45SDimitry Andric CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
2764c8b2481SRoman Divacky return Chunk(CK_Informative, Informative);
2774c8b2481SRoman Divacky }
2784c8b2481SRoman Divacky
279b3d5a323SRoman Divacky CodeCompletionString::Chunk
CreateResultType(const char * ResultType)280bca07a45SDimitry Andric CodeCompletionString::Chunk::CreateResultType(const char *ResultType) {
281abe15e55SRoman Divacky return Chunk(CK_ResultType, ResultType);
282abe15e55SRoman Divacky }
283abe15e55SRoman Divacky
CreateCurrentParameter(const char * CurrentParameter)284676fbe81SDimitry Andric CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateCurrentParameter(
285bca07a45SDimitry Andric const char *CurrentParameter) {
286b3d5a323SRoman Divacky return Chunk(CK_CurrentParameter, CurrentParameter);
287b3d5a323SRoman Divacky }
288b3d5a323SRoman Divacky
CodeCompletionString(const Chunk * Chunks,unsigned NumChunks,unsigned Priority,CXAvailabilityKind Availability,const char ** Annotations,unsigned NumAnnotations,StringRef ParentName,const char * BriefComment)289676fbe81SDimitry Andric CodeCompletionString::CodeCompletionString(
290676fbe81SDimitry Andric const Chunk *Chunks, unsigned NumChunks, unsigned Priority,
291676fbe81SDimitry Andric CXAvailabilityKind Availability, const char **Annotations,
292676fbe81SDimitry Andric unsigned NumAnnotations, StringRef ParentName, const char *BriefComment)
293676fbe81SDimitry Andric : NumChunks(NumChunks), NumAnnotations(NumAnnotations), Priority(Priority),
294676fbe81SDimitry Andric Availability(Availability), ParentName(ParentName),
295676fbe81SDimitry Andric BriefComment(BriefComment) {
29636981b17SDimitry Andric assert(NumChunks <= 0xffff);
29736981b17SDimitry Andric assert(NumAnnotations <= 0xffff);
29836981b17SDimitry Andric
299bca07a45SDimitry Andric Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1);
300bca07a45SDimitry Andric for (unsigned I = 0; I != NumChunks; ++I)
301bca07a45SDimitry Andric StoredChunks[I] = Chunks[I];
30236981b17SDimitry Andric
303676fbe81SDimitry Andric const char **StoredAnnotations =
304676fbe81SDimitry Andric reinterpret_cast<const char **>(StoredChunks + NumChunks);
30536981b17SDimitry Andric for (unsigned I = 0; I != NumAnnotations; ++I)
30636981b17SDimitry Andric StoredAnnotations[I] = Annotations[I];
3074c8b2481SRoman Divacky }
3084c8b2481SRoman Divacky
getAnnotationCount() const30936981b17SDimitry Andric unsigned CodeCompletionString::getAnnotationCount() const {
31036981b17SDimitry Andric return NumAnnotations;
31136981b17SDimitry Andric }
31236981b17SDimitry Andric
getAnnotation(unsigned AnnotationNr) const31336981b17SDimitry Andric const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const {
31436981b17SDimitry Andric if (AnnotationNr < NumAnnotations)
31536981b17SDimitry Andric return reinterpret_cast<const char *const *>(end())[AnnotationNr];
31636981b17SDimitry Andric else
3179f4dbff6SDimitry Andric return nullptr;
31836981b17SDimitry Andric }
31936981b17SDimitry Andric
getAsString() const3204c8b2481SRoman Divacky std::string CodeCompletionString::getAsString() const {
3214c8b2481SRoman Divacky std::string Result;
3224c8b2481SRoman Divacky llvm::raw_string_ostream OS(Result);
3234c8b2481SRoman Divacky
324676fbe81SDimitry Andric for (const Chunk &C : *this) {
325676fbe81SDimitry Andric switch (C.Kind) {
326676fbe81SDimitry Andric case CK_Optional:
327676fbe81SDimitry Andric OS << "{#" << C.Optional->getAsString() << "#}";
328676fbe81SDimitry Andric break;
329676fbe81SDimitry Andric case CK_Placeholder:
330676fbe81SDimitry Andric OS << "<#" << C.Text << "#>";
331676fbe81SDimitry Andric break;
332abe15e55SRoman Divacky case CK_Informative:
333abe15e55SRoman Divacky case CK_ResultType:
334676fbe81SDimitry Andric OS << "[#" << C.Text << "#]";
335abe15e55SRoman Divacky break;
336676fbe81SDimitry Andric case CK_CurrentParameter:
337676fbe81SDimitry Andric OS << "<#" << C.Text << "#>";
338676fbe81SDimitry Andric break;
339676fbe81SDimitry Andric default:
340676fbe81SDimitry Andric OS << C.Text;
341676fbe81SDimitry Andric break;
3424c8b2481SRoman Divacky }
3434c8b2481SRoman Divacky }
34477fc4c14SDimitry Andric return Result;
3454c8b2481SRoman Divacky }
3464c8b2481SRoman Divacky
getTypedText() const347f5bd02d2SRoman Divacky const char *CodeCompletionString::getTypedText() const {
348676fbe81SDimitry Andric for (const Chunk &C : *this)
349676fbe81SDimitry Andric if (C.Kind == CK_TypedText)
350676fbe81SDimitry Andric return C.Text;
351f5bd02d2SRoman Divacky
3529f4dbff6SDimitry Andric return nullptr;
353f5bd02d2SRoman Divacky }
354f5bd02d2SRoman Divacky
getAllTypedText() const355145449b1SDimitry Andric std::string CodeCompletionString::getAllTypedText() const {
356145449b1SDimitry Andric std::string Res;
357145449b1SDimitry Andric for (const Chunk &C : *this)
358145449b1SDimitry Andric if (C.Kind == CK_TypedText)
359145449b1SDimitry Andric Res += C.Text;
360145449b1SDimitry Andric
361145449b1SDimitry Andric return Res;
362145449b1SDimitry Andric }
363145449b1SDimitry Andric
CopyString(const Twine & String)3645e20cdd8SDimitry Andric const char *CodeCompletionAllocator::CopyString(const Twine &String) {
3655e20cdd8SDimitry Andric SmallString<128> Data;
3665e20cdd8SDimitry Andric StringRef Ref = String.toStringRef(Data);
367bca07a45SDimitry Andric // FIXME: It would be more efficient to teach Twine to tell us its size and
368bca07a45SDimitry Andric // then add a routine there to fill in an allocated char* with the contents
369bca07a45SDimitry Andric // of the string.
3705e20cdd8SDimitry Andric char *Mem = (char *)Allocate(Ref.size() + 1, 1);
3715e20cdd8SDimitry Andric std::copy(Ref.begin(), Ref.end(), Mem);
3725e20cdd8SDimitry Andric Mem[Ref.size()] = 0;
3735e20cdd8SDimitry Andric return Mem;
374bca07a45SDimitry Andric }
375bca07a45SDimitry Andric
getParentName(const DeclContext * DC)376809500fcSDimitry Andric StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
377b60736ecSDimitry Andric if (!isa<NamedDecl>(DC))
37848675466SDimitry Andric return {};
379dbe13110SDimitry Andric
380dbe13110SDimitry Andric // Check whether we've already cached the parent name.
381dbe13110SDimitry Andric StringRef &CachedParentName = ParentNames[DC];
382dbe13110SDimitry Andric if (!CachedParentName.empty())
383dbe13110SDimitry Andric return CachedParentName;
384dbe13110SDimitry Andric
385dbe13110SDimitry Andric // If we already processed this DeclContext and assigned empty to it, the
386dbe13110SDimitry Andric // data pointer will be non-null.
3879f4dbff6SDimitry Andric if (CachedParentName.data() != nullptr)
38848675466SDimitry Andric return {};
389dbe13110SDimitry Andric
390dbe13110SDimitry Andric // Find the interesting names.
391809500fcSDimitry Andric SmallVector<const DeclContext *, 2> Contexts;
392dbe13110SDimitry Andric while (DC && !DC->isFunctionOrMethod()) {
393676fbe81SDimitry Andric if (const auto *ND = dyn_cast<NamedDecl>(DC)) {
394dbe13110SDimitry Andric if (ND->getIdentifier())
395dbe13110SDimitry Andric Contexts.push_back(DC);
396dbe13110SDimitry Andric }
397dbe13110SDimitry Andric
398dbe13110SDimitry Andric DC = DC->getParent();
399dbe13110SDimitry Andric }
400dbe13110SDimitry Andric
401dbe13110SDimitry Andric {
402809500fcSDimitry Andric SmallString<128> S;
403dbe13110SDimitry Andric llvm::raw_svector_ostream OS(S);
404dbe13110SDimitry Andric bool First = true;
405c0981da4SDimitry Andric for (const DeclContext *CurDC : llvm::reverse(Contexts)) {
406dbe13110SDimitry Andric if (First)
407dbe13110SDimitry Andric First = false;
408dbe13110SDimitry Andric else {
409dbe13110SDimitry Andric OS << "::";
410dbe13110SDimitry Andric }
411dbe13110SDimitry Andric
412676fbe81SDimitry Andric if (const auto *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
413dbe13110SDimitry Andric CurDC = CatImpl->getCategoryDecl();
414dbe13110SDimitry Andric
415676fbe81SDimitry Andric if (const auto *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
416809500fcSDimitry Andric const ObjCInterfaceDecl *Interface = Cat->getClassInterface();
417dbe13110SDimitry Andric if (!Interface) {
418dbe13110SDimitry Andric // Assign an empty StringRef but with non-null data to distinguish
419dbe13110SDimitry Andric // between empty because we didn't process the DeclContext yet.
4202b6b257fSDimitry Andric CachedParentName = StringRef((const char *)(uintptr_t)~0U, 0);
42148675466SDimitry Andric return {};
422dbe13110SDimitry Andric }
423dbe13110SDimitry Andric
424dbe13110SDimitry Andric OS << Interface->getName() << '(' << Cat->getName() << ')';
425dbe13110SDimitry Andric } else {
426dbe13110SDimitry Andric OS << cast<NamedDecl>(CurDC)->getName();
427dbe13110SDimitry Andric }
428dbe13110SDimitry Andric }
429dbe13110SDimitry Andric
430dbe13110SDimitry Andric CachedParentName = AllocatorRef->CopyString(OS.str());
431dbe13110SDimitry Andric }
432dbe13110SDimitry Andric
433dbe13110SDimitry Andric return CachedParentName;
434dbe13110SDimitry Andric }
435dbe13110SDimitry Andric
TakeString()436bca07a45SDimitry Andric CodeCompletionString *CodeCompletionBuilder::TakeString() {
437dbe13110SDimitry Andric void *Mem = getAllocator().Allocate(
438bab175ecSDimitry Andric sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() +
439bab175ecSDimitry Andric sizeof(const char *) * Annotations.size(),
440bab175ecSDimitry Andric alignof(CodeCompletionString));
441676fbe81SDimitry Andric CodeCompletionString *Result = new (Mem) CodeCompletionString(
442676fbe81SDimitry Andric Chunks.data(), Chunks.size(), Priority, Availability, Annotations.data(),
443676fbe81SDimitry Andric Annotations.size(), ParentName, BriefComment);
444bca07a45SDimitry Andric Chunks.clear();
445f5bd02d2SRoman Divacky return Result;
446f5bd02d2SRoman Divacky }
447b3d5a323SRoman Divacky
AddTypedTextChunk(const char * Text)448dbe13110SDimitry Andric void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) {
449dbe13110SDimitry Andric Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text));
450dbe13110SDimitry Andric }
451dbe13110SDimitry Andric
AddTextChunk(const char * Text)452dbe13110SDimitry Andric void CodeCompletionBuilder::AddTextChunk(const char *Text) {
453dbe13110SDimitry Andric Chunks.push_back(Chunk::CreateText(Text));
454dbe13110SDimitry Andric }
455dbe13110SDimitry Andric
AddOptionalChunk(CodeCompletionString * Optional)456dbe13110SDimitry Andric void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) {
457dbe13110SDimitry Andric Chunks.push_back(Chunk::CreateOptional(Optional));
458dbe13110SDimitry Andric }
459dbe13110SDimitry Andric
AddPlaceholderChunk(const char * Placeholder)460dbe13110SDimitry Andric void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) {
461dbe13110SDimitry Andric Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
462dbe13110SDimitry Andric }
463dbe13110SDimitry Andric
AddInformativeChunk(const char * Text)464dbe13110SDimitry Andric void CodeCompletionBuilder::AddInformativeChunk(const char *Text) {
465dbe13110SDimitry Andric Chunks.push_back(Chunk::CreateInformative(Text));
466dbe13110SDimitry Andric }
467dbe13110SDimitry Andric
AddResultTypeChunk(const char * ResultType)468dbe13110SDimitry Andric void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) {
469dbe13110SDimitry Andric Chunks.push_back(Chunk::CreateResultType(ResultType));
470dbe13110SDimitry Andric }
471dbe13110SDimitry Andric
AddCurrentParameterChunk(const char * CurrentParameter)472676fbe81SDimitry Andric void CodeCompletionBuilder::AddCurrentParameterChunk(
473676fbe81SDimitry Andric const char *CurrentParameter) {
474dbe13110SDimitry Andric Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter));
475dbe13110SDimitry Andric }
476dbe13110SDimitry Andric
AddChunk(CodeCompletionString::ChunkKind CK,const char * Text)477dbe13110SDimitry Andric void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK,
478dbe13110SDimitry Andric const char *Text) {
479dbe13110SDimitry Andric Chunks.push_back(Chunk(CK, Text));
480dbe13110SDimitry Andric }
481dbe13110SDimitry Andric
addParentContext(const DeclContext * DC)482809500fcSDimitry Andric void CodeCompletionBuilder::addParentContext(const DeclContext *DC) {
48348675466SDimitry Andric if (DC->isTranslationUnit())
484dbe13110SDimitry Andric return;
485dbe13110SDimitry Andric
486dbe13110SDimitry Andric if (DC->isFunctionOrMethod())
487dbe13110SDimitry Andric return;
488dbe13110SDimitry Andric
489b60736ecSDimitry Andric if (!isa<NamedDecl>(DC))
490dbe13110SDimitry Andric return;
491dbe13110SDimitry Andric
492dbe13110SDimitry Andric ParentName = getCodeCompletionTUInfo().getParentName(DC);
493dbe13110SDimitry Andric }
494dbe13110SDimitry Andric
addBriefComment(StringRef Comment)49556d91b49SDimitry Andric void CodeCompletionBuilder::addBriefComment(StringRef Comment) {
49656d91b49SDimitry Andric BriefComment = Allocator.CopyString(Comment);
49756d91b49SDimitry Andric }
49856d91b49SDimitry Andric
4994c8b2481SRoman Divacky //===----------------------------------------------------------------------===//
5004c8b2481SRoman Divacky // Code completion overload candidate implementation
5014c8b2481SRoman Divacky //===----------------------------------------------------------------------===//
getFunction() const502676fbe81SDimitry Andric FunctionDecl *CodeCompleteConsumer::OverloadCandidate::getFunction() const {
5034c8b2481SRoman Divacky if (getKind() == CK_Function)
5044c8b2481SRoman Divacky return Function;
5054c8b2481SRoman Divacky else if (getKind() == CK_FunctionTemplate)
5064c8b2481SRoman Divacky return FunctionTemplate->getTemplatedDecl();
5074c8b2481SRoman Divacky else
5089f4dbff6SDimitry Andric return nullptr;
5094c8b2481SRoman Divacky }
5104c8b2481SRoman Divacky
5114c8b2481SRoman Divacky const FunctionType *
getFunctionType() const5124c8b2481SRoman Divacky CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
5134c8b2481SRoman Divacky switch (Kind) {
5144c8b2481SRoman Divacky case CK_Function:
5154c8b2481SRoman Divacky return Function->getType()->getAs<FunctionType>();
5164c8b2481SRoman Divacky
5174c8b2481SRoman Divacky case CK_FunctionTemplate:
518676fbe81SDimitry Andric return FunctionTemplate->getTemplatedDecl()
519676fbe81SDimitry Andric ->getType()
5204c8b2481SRoman Divacky ->getAs<FunctionType>();
5214c8b2481SRoman Divacky
5224c8b2481SRoman Divacky case CK_FunctionType:
5234c8b2481SRoman Divacky return Type;
5244b4fe385SDimitry Andric case CK_FunctionProtoTypeLoc:
5254b4fe385SDimitry Andric return ProtoTypeLoc.getTypePtr();
5266f8fc217SDimitry Andric case CK_Template:
5276f8fc217SDimitry Andric case CK_Aggregate:
5286f8fc217SDimitry Andric return nullptr;
5294c8b2481SRoman Divacky }
5304c8b2481SRoman Divacky
531dbe13110SDimitry Andric llvm_unreachable("Invalid CandidateKind!");
5324c8b2481SRoman Divacky }
5334c8b2481SRoman Divacky
5344b4fe385SDimitry Andric const FunctionProtoTypeLoc
getFunctionProtoTypeLoc() const5354b4fe385SDimitry Andric CodeCompleteConsumer::OverloadCandidate::getFunctionProtoTypeLoc() const {
5364b4fe385SDimitry Andric if (Kind == CK_FunctionProtoTypeLoc)
5374b4fe385SDimitry Andric return ProtoTypeLoc;
5384b4fe385SDimitry Andric return FunctionProtoTypeLoc();
5394b4fe385SDimitry Andric }
5404b4fe385SDimitry Andric
getNumParams() const5416f8fc217SDimitry Andric unsigned CodeCompleteConsumer::OverloadCandidate::getNumParams() const {
5426f8fc217SDimitry Andric if (Kind == CK_Template)
5436f8fc217SDimitry Andric return Template->getTemplateParameters()->size();
5446f8fc217SDimitry Andric
5456f8fc217SDimitry Andric if (Kind == CK_Aggregate) {
5466f8fc217SDimitry Andric unsigned Count =
5476f8fc217SDimitry Andric std::distance(AggregateType->field_begin(), AggregateType->field_end());
5486f8fc217SDimitry Andric if (const auto *CRD = dyn_cast<CXXRecordDecl>(AggregateType))
5496f8fc217SDimitry Andric Count += CRD->getNumBases();
5506f8fc217SDimitry Andric return Count;
5516f8fc217SDimitry Andric }
5526f8fc217SDimitry Andric
5536f8fc217SDimitry Andric if (const auto *FT = getFunctionType())
5546f8fc217SDimitry Andric if (const auto *FPT = dyn_cast<FunctionProtoType>(FT))
5556f8fc217SDimitry Andric return FPT->getNumParams();
5566f8fc217SDimitry Andric
5576f8fc217SDimitry Andric return 0;
5586f8fc217SDimitry Andric }
5596f8fc217SDimitry Andric
5606f8fc217SDimitry Andric QualType
getParamType(unsigned N) const5616f8fc217SDimitry Andric CodeCompleteConsumer::OverloadCandidate::getParamType(unsigned N) const {
5626f8fc217SDimitry Andric if (Kind == CK_Aggregate) {
5636f8fc217SDimitry Andric if (const auto *CRD = dyn_cast<CXXRecordDecl>(AggregateType)) {
5646f8fc217SDimitry Andric if (N < CRD->getNumBases())
5656f8fc217SDimitry Andric return std::next(CRD->bases_begin(), N)->getType();
5666f8fc217SDimitry Andric N -= CRD->getNumBases();
5676f8fc217SDimitry Andric }
5686f8fc217SDimitry Andric for (const auto *Field : AggregateType->fields())
5696f8fc217SDimitry Andric if (N-- == 0)
5706f8fc217SDimitry Andric return Field->getType();
5716f8fc217SDimitry Andric return QualType();
5726f8fc217SDimitry Andric }
5736f8fc217SDimitry Andric
5746f8fc217SDimitry Andric if (Kind == CK_Template) {
5756f8fc217SDimitry Andric TemplateParameterList *TPL = getTemplate()->getTemplateParameters();
5766f8fc217SDimitry Andric if (N < TPL->size())
5776f8fc217SDimitry Andric if (const auto *D = dyn_cast<NonTypeTemplateParmDecl>(TPL->getParam(N)))
5786f8fc217SDimitry Andric return D->getType();
5796f8fc217SDimitry Andric return QualType();
5806f8fc217SDimitry Andric }
5816f8fc217SDimitry Andric
5826f8fc217SDimitry Andric if (const auto *FT = getFunctionType())
5836f8fc217SDimitry Andric if (const auto *FPT = dyn_cast<FunctionProtoType>(FT))
5846f8fc217SDimitry Andric if (N < FPT->getNumParams())
5856f8fc217SDimitry Andric return FPT->getParamType(N);
5866f8fc217SDimitry Andric return QualType();
5876f8fc217SDimitry Andric }
5886f8fc217SDimitry Andric
5896f8fc217SDimitry Andric const NamedDecl *
getParamDecl(unsigned N) const5906f8fc217SDimitry Andric CodeCompleteConsumer::OverloadCandidate::getParamDecl(unsigned N) const {
5916f8fc217SDimitry Andric if (Kind == CK_Aggregate) {
5926f8fc217SDimitry Andric if (const auto *CRD = dyn_cast<CXXRecordDecl>(AggregateType)) {
5936f8fc217SDimitry Andric if (N < CRD->getNumBases())
5946f8fc217SDimitry Andric return std::next(CRD->bases_begin(), N)->getType()->getAsTagDecl();
5956f8fc217SDimitry Andric N -= CRD->getNumBases();
5966f8fc217SDimitry Andric }
5976f8fc217SDimitry Andric for (const auto *Field : AggregateType->fields())
5986f8fc217SDimitry Andric if (N-- == 0)
5996f8fc217SDimitry Andric return Field;
6006f8fc217SDimitry Andric return nullptr;
6016f8fc217SDimitry Andric }
6026f8fc217SDimitry Andric
6036f8fc217SDimitry Andric if (Kind == CK_Template) {
6046f8fc217SDimitry Andric TemplateParameterList *TPL = getTemplate()->getTemplateParameters();
6056f8fc217SDimitry Andric if (N < TPL->size())
6066f8fc217SDimitry Andric return TPL->getParam(N);
6076f8fc217SDimitry Andric return nullptr;
6086f8fc217SDimitry Andric }
6096f8fc217SDimitry Andric
6106f8fc217SDimitry Andric // Note that if we only have a FunctionProtoType, we don't have param decls.
6116f8fc217SDimitry Andric if (const auto *FD = getFunction()) {
6126f8fc217SDimitry Andric if (N < FD->param_size())
6136f8fc217SDimitry Andric return FD->getParamDecl(N);
6144b4fe385SDimitry Andric } else if (Kind == CK_FunctionProtoTypeLoc) {
6154b4fe385SDimitry Andric if (N < ProtoTypeLoc.getNumParams()) {
6164b4fe385SDimitry Andric return ProtoTypeLoc.getParam(N);
6176f8fc217SDimitry Andric }
6184b4fe385SDimitry Andric }
6194b4fe385SDimitry Andric
6206f8fc217SDimitry Andric return nullptr;
6216f8fc217SDimitry Andric }
6226f8fc217SDimitry Andric
6234c8b2481SRoman Divacky //===----------------------------------------------------------------------===//
6244c8b2481SRoman Divacky // Code completion consumer implementation
6254c8b2481SRoman Divacky //===----------------------------------------------------------------------===//
6264c8b2481SRoman Divacky
62748675466SDimitry Andric CodeCompleteConsumer::~CodeCompleteConsumer() = default;
6284c8b2481SRoman Divacky
isResultFilteredOut(StringRef Filter,CodeCompletionResult Result)629676fbe81SDimitry Andric bool PrintingCodeCompleteConsumer::isResultFilteredOut(
630676fbe81SDimitry Andric StringRef Filter, CodeCompletionResult Result) {
631bab175ecSDimitry Andric switch (Result.Kind) {
63248675466SDimitry Andric case CodeCompletionResult::RK_Declaration:
633312c0ed1SDimitry Andric return !(
634312c0ed1SDimitry Andric Result.Declaration->getIdentifier() &&
635312c0ed1SDimitry Andric Result.Declaration->getIdentifier()->getName().starts_with(Filter));
63648675466SDimitry Andric case CodeCompletionResult::RK_Keyword:
637312c0ed1SDimitry Andric return !StringRef(Result.Keyword).starts_with(Filter);
63848675466SDimitry Andric case CodeCompletionResult::RK_Macro:
639312c0ed1SDimitry Andric return !Result.Macro->getName().starts_with(Filter);
64048675466SDimitry Andric case CodeCompletionResult::RK_Pattern:
641676fbe81SDimitry Andric return !(Result.Pattern->getTypedText() &&
642312c0ed1SDimitry Andric StringRef(Result.Pattern->getTypedText()).starts_with(Filter));
643bab175ecSDimitry Andric }
644bab175ecSDimitry Andric llvm_unreachable("Unknown code completion result Kind.");
645bab175ecSDimitry Andric }
646bab175ecSDimitry Andric
ProcessCodeCompleteResults(Sema & SemaRef,CodeCompletionContext Context,CodeCompletionResult * Results,unsigned NumResults)647676fbe81SDimitry Andric void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(
648676fbe81SDimitry Andric Sema &SemaRef, CodeCompletionContext Context, CodeCompletionResult *Results,
6494c8b2481SRoman Divacky unsigned NumResults) {
6503d1dcd9bSDimitry Andric std::stable_sort(Results, Results + NumResults);
6513d1dcd9bSDimitry Andric
652676fbe81SDimitry Andric if (!Context.getPreferredType().isNull())
653145449b1SDimitry Andric OS << "PREFERRED-TYPE: " << Context.getPreferredType() << '\n';
654bab175ecSDimitry Andric
655676fbe81SDimitry Andric StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
656676fbe81SDimitry Andric // Print the completions.
6574c8b2481SRoman Divacky for (unsigned I = 0; I != NumResults; ++I) {
658bab175ecSDimitry Andric if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
659bab175ecSDimitry Andric continue;
6604c8b2481SRoman Divacky OS << "COMPLETION: ";
6614c8b2481SRoman Divacky switch (Results[I].Kind) {
6623d1dcd9bSDimitry Andric case CodeCompletionResult::RK_Declaration:
66336981b17SDimitry Andric OS << *Results[I].Declaration;
664676fbe81SDimitry Andric {
665676fbe81SDimitry Andric std::vector<std::string> Tags;
6664c8b2481SRoman Divacky if (Results[I].Hidden)
667676fbe81SDimitry Andric Tags.push_back("Hidden");
668676fbe81SDimitry Andric if (Results[I].InBaseClass)
669676fbe81SDimitry Andric Tags.push_back("InBase");
670676fbe81SDimitry Andric if (Results[I].Availability ==
671676fbe81SDimitry Andric CXAvailabilityKind::CXAvailability_NotAccessible)
672676fbe81SDimitry Andric Tags.push_back("Inaccessible");
673676fbe81SDimitry Andric if (!Tags.empty())
674676fbe81SDimitry Andric OS << " (" << llvm::join(Tags, ",") << ")";
675676fbe81SDimitry Andric }
676676fbe81SDimitry Andric if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(
677676fbe81SDimitry Andric SemaRef, Context, getAllocator(), CCTUInfo,
67856d91b49SDimitry Andric includeBriefComments())) {
6794c8b2481SRoman Divacky OS << " : " << CCS->getAsString();
68056d91b49SDimitry Andric if (const char *BriefComment = CCS->getBriefComment())
68156d91b49SDimitry Andric OS << " : " << BriefComment;
6824c8b2481SRoman Divacky }
683cfca06d7SDimitry Andric break;
684cfca06d7SDimitry Andric
685cfca06d7SDimitry Andric case CodeCompletionResult::RK_Keyword:
686cfca06d7SDimitry Andric OS << Results[I].Keyword;
687cfca06d7SDimitry Andric break;
688cfca06d7SDimitry Andric
689cfca06d7SDimitry Andric case CodeCompletionResult::RK_Macro:
690cfca06d7SDimitry Andric OS << Results[I].Macro->getName();
691cfca06d7SDimitry Andric if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(
692cfca06d7SDimitry Andric SemaRef, Context, getAllocator(), CCTUInfo,
693cfca06d7SDimitry Andric includeBriefComments())) {
694cfca06d7SDimitry Andric OS << " : " << CCS->getAsString();
695cfca06d7SDimitry Andric }
696cfca06d7SDimitry Andric break;
697cfca06d7SDimitry Andric
698cfca06d7SDimitry Andric case CodeCompletionResult::RK_Pattern:
699cfca06d7SDimitry Andric OS << "Pattern : " << Results[I].Pattern->getAsString();
700cfca06d7SDimitry Andric break;
701cfca06d7SDimitry Andric }
70248675466SDimitry Andric for (const FixItHint &FixIt : Results[I].FixIts) {
70348675466SDimitry Andric const SourceLocation BLoc = FixIt.RemoveRange.getBegin();
70448675466SDimitry Andric const SourceLocation ELoc = FixIt.RemoveRange.getEnd();
7054c8b2481SRoman Divacky
70648675466SDimitry Andric SourceManager &SM = SemaRef.SourceMgr;
70748675466SDimitry Andric std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
70848675466SDimitry Andric std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
70948675466SDimitry Andric // Adjust for token ranges.
71048675466SDimitry Andric if (FixIt.RemoveRange.isTokenRange())
71148675466SDimitry Andric EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts);
71248675466SDimitry Andric
71348675466SDimitry Andric OS << " (requires fix-it:"
71448675466SDimitry Andric << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
71548675466SDimitry Andric << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
71648675466SDimitry Andric << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
71748675466SDimitry Andric << SM.getColumnNumber(EInfo.first, EInfo.second) << "}"
71848675466SDimitry Andric << " to \"" << FixIt.CodeToInsert << "\")";
71948675466SDimitry Andric }
7204c8b2481SRoman Divacky OS << '\n';
7214c8b2481SRoman Divacky }
7224c8b2481SRoman Divacky }
7234c8b2481SRoman Divacky
7245e20cdd8SDimitry Andric // This function is used solely to preserve the former presentation of overloads
7255e20cdd8SDimitry Andric // by "clang -cc1 -code-completion-at", since CodeCompletionString::getAsString
7265e20cdd8SDimitry Andric // needs to be improved for printing the newer and more detailed overload
7275e20cdd8SDimitry Andric // chunks.
getOverloadAsString(const CodeCompletionString & CCS)7285e20cdd8SDimitry Andric static std::string getOverloadAsString(const CodeCompletionString &CCS) {
7295e20cdd8SDimitry Andric std::string Result;
7305e20cdd8SDimitry Andric llvm::raw_string_ostream OS(Result);
7315e20cdd8SDimitry Andric
7325e20cdd8SDimitry Andric for (auto &C : CCS) {
7335e20cdd8SDimitry Andric switch (C.Kind) {
7345e20cdd8SDimitry Andric case CodeCompletionString::CK_Informative:
7355e20cdd8SDimitry Andric case CodeCompletionString::CK_ResultType:
7365e20cdd8SDimitry Andric OS << "[#" << C.Text << "#]";
7375e20cdd8SDimitry Andric break;
7385e20cdd8SDimitry Andric
7395e20cdd8SDimitry Andric case CodeCompletionString::CK_CurrentParameter:
7405e20cdd8SDimitry Andric OS << "<#" << C.Text << "#>";
7415e20cdd8SDimitry Andric break;
7425e20cdd8SDimitry Andric
743676fbe81SDimitry Andric // FIXME: We can also print optional parameters of an overload.
744676fbe81SDimitry Andric case CodeCompletionString::CK_Optional:
745676fbe81SDimitry Andric break;
746676fbe81SDimitry Andric
747676fbe81SDimitry Andric default:
748676fbe81SDimitry Andric OS << C.Text;
749676fbe81SDimitry Andric break;
7505e20cdd8SDimitry Andric }
7515e20cdd8SDimitry Andric }
75277fc4c14SDimitry Andric return Result;
7535e20cdd8SDimitry Andric }
7545e20cdd8SDimitry Andric
ProcessOverloadCandidates(Sema & SemaRef,unsigned CurrentArg,OverloadCandidate * Candidates,unsigned NumCandidates,SourceLocation OpenParLoc,bool Braced)755676fbe81SDimitry Andric void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
756676fbe81SDimitry Andric Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates,
7576f8fc217SDimitry Andric unsigned NumCandidates, SourceLocation OpenParLoc, bool Braced) {
758676fbe81SDimitry Andric OS << "OPENING_PAREN_LOC: ";
759676fbe81SDimitry Andric OpenParLoc.print(OS, SemaRef.getSourceManager());
760676fbe81SDimitry Andric OS << "\n";
761676fbe81SDimitry Andric
7624c8b2481SRoman Divacky for (unsigned I = 0; I != NumCandidates; ++I) {
763676fbe81SDimitry Andric if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(
764676fbe81SDimitry Andric CurrentArg, SemaRef, getAllocator(), CCTUInfo,
7656f8fc217SDimitry Andric includeBriefComments(), Braced)) {
7665e20cdd8SDimitry Andric OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
7674c8b2481SRoman Divacky }
7684c8b2481SRoman Divacky }
7694c8b2481SRoman Divacky }
770b3d5a323SRoman Divacky
77148675466SDimitry Andric /// Retrieve the effective availability of the given declaration.
getDeclAvailability(const Decl * D)772809500fcSDimitry Andric static AvailabilityResult getDeclAvailability(const Decl *D) {
773dbe13110SDimitry Andric AvailabilityResult AR = D->getAvailability();
774dbe13110SDimitry Andric if (isa<EnumConstantDecl>(D))
775dbe13110SDimitry Andric AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability());
776dbe13110SDimitry Andric return AR;
777dbe13110SDimitry Andric }
778dbe13110SDimitry Andric
computeCursorKindAndAvailability(bool Accessible)77936981b17SDimitry Andric void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
7803d1dcd9bSDimitry Andric switch (Kind) {
781dbe13110SDimitry Andric case RK_Pattern:
782dbe13110SDimitry Andric if (!Declaration) {
783dbe13110SDimitry Andric // Do nothing: Patterns can come with cursor kinds!
784dbe13110SDimitry Andric break;
785dbe13110SDimitry Andric }
786e3b55780SDimitry Andric [[fallthrough]];
787dbe13110SDimitry Andric
788dbe13110SDimitry Andric case RK_Declaration: {
7893d1dcd9bSDimitry Andric // Set the availability based on attributes.
790dbe13110SDimitry Andric switch (getDeclAvailability(Declaration)) {
79101af97d3SDimitry Andric case AR_Available:
79201af97d3SDimitry Andric case AR_NotYetIntroduced:
7933d1dcd9bSDimitry Andric Availability = CXAvailability_Available;
79401af97d3SDimitry Andric break;
79501af97d3SDimitry Andric
79601af97d3SDimitry Andric case AR_Deprecated:
7973d1dcd9bSDimitry Andric Availability = CXAvailability_Deprecated;
79801af97d3SDimitry Andric break;
79901af97d3SDimitry Andric
80001af97d3SDimitry Andric case AR_Unavailable:
80101af97d3SDimitry Andric Availability = CXAvailability_NotAvailable;
80201af97d3SDimitry Andric break;
80301af97d3SDimitry Andric }
8043d1dcd9bSDimitry Andric
805676fbe81SDimitry Andric if (const auto *Function = dyn_cast<FunctionDecl>(Declaration))
8063d1dcd9bSDimitry Andric if (Function->isDeleted())
8073d1dcd9bSDimitry Andric Availability = CXAvailability_NotAvailable;
8083d1dcd9bSDimitry Andric
8093d1dcd9bSDimitry Andric CursorKind = getCursorKindForDecl(Declaration);
810dbe13110SDimitry Andric if (CursorKind == CXCursor_UnexposedDecl) {
811dbe13110SDimitry Andric // FIXME: Forward declarations of Objective-C classes and protocols
812dbe13110SDimitry Andric // are not directly exposed, but we want code completion to treat them
813dbe13110SDimitry Andric // like a definition.
814dbe13110SDimitry Andric if (isa<ObjCInterfaceDecl>(Declaration))
815dbe13110SDimitry Andric CursorKind = CXCursor_ObjCInterfaceDecl;
816dbe13110SDimitry Andric else if (isa<ObjCProtocolDecl>(Declaration))
817dbe13110SDimitry Andric CursorKind = CXCursor_ObjCProtocolDecl;
818dbe13110SDimitry Andric else
8193d1dcd9bSDimitry Andric CursorKind = CXCursor_NotImplemented;
820dbe13110SDimitry Andric }
8213d1dcd9bSDimitry Andric break;
822dbe13110SDimitry Andric }
8233d1dcd9bSDimitry Andric
8243d1dcd9bSDimitry Andric case RK_Macro:
8253d1dcd9bSDimitry Andric case RK_Keyword:
82656d91b49SDimitry Andric llvm_unreachable("Macro and keyword kinds are handled by the constructors");
8273d1dcd9bSDimitry Andric }
82836981b17SDimitry Andric
82936981b17SDimitry Andric if (!Accessible)
83036981b17SDimitry Andric Availability = CXAvailability_NotAccessible;
8313d1dcd9bSDimitry Andric }
8323d1dcd9bSDimitry Andric
83348675466SDimitry Andric /// Retrieve the name that should be used to order a result.
8343d1dcd9bSDimitry Andric ///
8353d1dcd9bSDimitry Andric /// If the name needs to be constructed as a string, that string will be
8363d1dcd9bSDimitry Andric /// saved into Saved and the returned StringRef will refer to it.
getOrderedName(std::string & Saved) const837461a67faSDimitry Andric StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const {
838461a67faSDimitry Andric switch (Kind) {
839461a67faSDimitry Andric case RK_Keyword:
840461a67faSDimitry Andric return Keyword;
841461a67faSDimitry Andric case RK_Pattern:
842461a67faSDimitry Andric return Pattern->getTypedText();
843461a67faSDimitry Andric case RK_Macro:
844461a67faSDimitry Andric return Macro->getName();
845461a67faSDimitry Andric case RK_Declaration:
8463d1dcd9bSDimitry Andric // Handle declarations below.
8473d1dcd9bSDimitry Andric break;
8483d1dcd9bSDimitry Andric }
8493d1dcd9bSDimitry Andric
850461a67faSDimitry Andric DeclarationName Name = Declaration->getDeclName();
8513d1dcd9bSDimitry Andric
8523d1dcd9bSDimitry Andric // If the name is a simple identifier (by far the common case), or a
8533d1dcd9bSDimitry Andric // zero-argument selector, just return a reference to that identifier.
8543d1dcd9bSDimitry Andric if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
8553d1dcd9bSDimitry Andric return Id->getName();
8563d1dcd9bSDimitry Andric if (Name.isObjCZeroArgSelector())
857ac9a064cSDimitry Andric if (const IdentifierInfo *Id =
858ac9a064cSDimitry Andric Name.getObjCSelector().getIdentifierInfoForSlot(0))
8593d1dcd9bSDimitry Andric return Id->getName();
8603d1dcd9bSDimitry Andric
8613d1dcd9bSDimitry Andric Saved = Name.getAsString();
8623d1dcd9bSDimitry Andric return Saved;
8633d1dcd9bSDimitry Andric }
8643d1dcd9bSDimitry Andric
operator <(const CodeCompletionResult & X,const CodeCompletionResult & Y)8653d1dcd9bSDimitry Andric bool clang::operator<(const CodeCompletionResult &X,
8663d1dcd9bSDimitry Andric const CodeCompletionResult &Y) {
8673d1dcd9bSDimitry Andric std::string XSaved, YSaved;
868461a67faSDimitry Andric StringRef XStr = X.getOrderedName(XSaved);
869461a67faSDimitry Andric StringRef YStr = Y.getOrderedName(YSaved);
870344a3780SDimitry Andric int cmp = XStr.compare_insensitive(YStr);
8713d1dcd9bSDimitry Andric if (cmp)
8723d1dcd9bSDimitry Andric return cmp < 0;
8733d1dcd9bSDimitry Andric
8743d1dcd9bSDimitry Andric // If case-insensitive comparison fails, try case-sensitive comparison.
875676fbe81SDimitry Andric return XStr.compare(YStr) < 0;
8763d1dcd9bSDimitry Andric }
877