1711964ddSEugene Zelenko //===- CodeCompleteConsumer.cpp - Code Completion Interface ---------------===//
22436e711SDouglas Gregor //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62436e711SDouglas Gregor //
72436e711SDouglas Gregor //===----------------------------------------------------------------------===//
82436e711SDouglas Gregor //
92436e711SDouglas Gregor // This file implements the CodeCompleteConsumer class.
102436e711SDouglas Gregor //
112436e711SDouglas Gregor //===----------------------------------------------------------------------===//
12711964ddSEugene Zelenko
132436e711SDouglas Gregor #include "clang/Sema/CodeCompleteConsumer.h"
143a02247dSChandler Carruth #include "clang-c/Index.h"
15711964ddSEugene Zelenko #include "clang/AST/Decl.h"
16711964ddSEugene Zelenko #include "clang/AST/DeclBase.h"
17de6836a3SJohn McCall #include "clang/AST/DeclObjC.h"
1819c1bfd1SJohn McCall #include "clang/AST/DeclTemplate.h"
19711964ddSEugene Zelenko #include "clang/AST/DeclarationName.h"
20711964ddSEugene Zelenko #include "clang/AST/Type.h"
21711964ddSEugene Zelenko #include "clang/Basic/IdentifierTable.h"
22644ea61dSVassil Vassilev #include "clang/Lex/Preprocessor.h"
232fab2353SIlya Biryukov #include "clang/Sema/Sema.h"
243a02247dSChandler Carruth #include "llvm/ADT/SmallString.h"
25711964ddSEugene Zelenko #include "llvm/ADT/SmallVector.h"
2676221c73SReid Kleckner #include "llvm/ADT/StringExtras.h"
27711964ddSEugene Zelenko #include "llvm/ADT/StringRef.h"
28669a25aeSDouglas Gregor #include "llvm/ADT/Twine.h"
29711964ddSEugene Zelenko #include "llvm/Support/Casting.h"
30711964ddSEugene Zelenko #include "llvm/Support/Compiler.h"
31711964ddSEugene Zelenko #include "llvm/Support/ErrorHandling.h"
322fab2353SIlya Biryukov #include "llvm/Support/FormatVariadic.h"
332436e711SDouglas Gregor #include "llvm/Support/raw_ostream.h"
342436e711SDouglas Gregor #include <algorithm>
35711964ddSEugene Zelenko #include <cassert>
36711964ddSEugene Zelenko #include <cstdint>
37711964ddSEugene Zelenko #include <string>
38ab6ccb5fSDouglas Gregor
392436e711SDouglas Gregor using namespace clang;
402436e711SDouglas Gregor
41fedc328aSDouglas Gregor //===----------------------------------------------------------------------===//
420212fd71SDouglas Gregor // Code completion context implementation
430212fd71SDouglas Gregor //===----------------------------------------------------------------------===//
440212fd71SDouglas Gregor
wantConstructorResults() const450212fd71SDouglas Gregor bool CodeCompletionContext::wantConstructorResults() const {
463289ab20SIlya Biryukov switch (CCKind) {
470ac41389SDouglas Gregor case CCC_Recovery:
480212fd71SDouglas Gregor case CCC_Statement:
490212fd71SDouglas Gregor case CCC_Expression:
500212fd71SDouglas Gregor case CCC_ObjCMessageReceiver:
510212fd71SDouglas Gregor case CCC_ParenthesizedExpression:
52b006e099SKadir Cetinkaya case CCC_Symbol:
53b006e099SKadir Cetinkaya case CCC_SymbolOrNewName:
540212fd71SDouglas Gregor return true;
550212fd71SDouglas Gregor
560212fd71SDouglas Gregor case CCC_TopLevel:
570212fd71SDouglas Gregor case CCC_ObjCInterface:
580212fd71SDouglas Gregor case CCC_ObjCImplementation:
590212fd71SDouglas Gregor case CCC_ObjCIvarList:
600212fd71SDouglas Gregor case CCC_ClassStructUnion:
612132584dSDouglas Gregor case CCC_DotMemberAccess:
622132584dSDouglas Gregor case CCC_ArrowMemberAccess:
632132584dSDouglas Gregor case CCC_ObjCPropertyAccess:
640212fd71SDouglas Gregor case CCC_EnumTag:
650212fd71SDouglas Gregor case CCC_UnionTag:
660212fd71SDouglas Gregor case CCC_ClassOrStructTag:
670212fd71SDouglas Gregor case CCC_ObjCProtocolName:
680212fd71SDouglas Gregor case CCC_Namespace:
690212fd71SDouglas Gregor case CCC_Type:
70b006e099SKadir Cetinkaya case CCC_NewName:
710212fd71SDouglas Gregor case CCC_MacroName:
720212fd71SDouglas Gregor case CCC_MacroNameUse:
730212fd71SDouglas Gregor case CCC_PreprocessorExpression:
740212fd71SDouglas Gregor case CCC_PreprocessorDirective:
750212fd71SDouglas Gregor case CCC_NaturalLanguage:
760212fd71SDouglas Gregor case CCC_SelectorName:
770212fd71SDouglas Gregor case CCC_TypeQualifiers:
780ac41389SDouglas Gregor case CCC_Other:
793a69eafaSDouglas Gregor case CCC_OtherWithMacros:
802132584dSDouglas Gregor case CCC_ObjCInstanceMessage:
812132584dSDouglas Gregor case CCC_ObjCClassMessage:
822c595adfSDouglas Gregor case CCC_ObjCInterfaceName:
832132584dSDouglas Gregor case CCC_ObjCCategoryName:
843d8051abSSam McCall case CCC_IncludedFile:
85ece4e920SSam McCall case CCC_Attribute:
860212fd71SDouglas Gregor return false;
870212fd71SDouglas Gregor }
880212fd71SDouglas Gregor
898a40f700SDavid Blaikie llvm_unreachable("Invalid CodeCompletionContext::Kind!");
900212fd71SDouglas Gregor }
910212fd71SDouglas Gregor
getCompletionKindString(CodeCompletionContext::Kind Kind)923289ab20SIlya Biryukov StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) {
933289ab20SIlya Biryukov using CCKind = CodeCompletionContext::Kind;
9427d82585SIlya Biryukov switch (Kind) {
9527d82585SIlya Biryukov case CCKind::CCC_Other:
9627d82585SIlya Biryukov return "Other";
9727d82585SIlya Biryukov case CCKind::CCC_OtherWithMacros:
9827d82585SIlya Biryukov return "OtherWithMacros";
9927d82585SIlya Biryukov case CCKind::CCC_TopLevel:
10027d82585SIlya Biryukov return "TopLevel";
10127d82585SIlya Biryukov case CCKind::CCC_ObjCInterface:
10227d82585SIlya Biryukov return "ObjCInterface";
10327d82585SIlya Biryukov case CCKind::CCC_ObjCImplementation:
10427d82585SIlya Biryukov return "ObjCImplementation";
10527d82585SIlya Biryukov case CCKind::CCC_ObjCIvarList:
10627d82585SIlya Biryukov return "ObjCIvarList";
10727d82585SIlya Biryukov case CCKind::CCC_ClassStructUnion:
10827d82585SIlya Biryukov return "ClassStructUnion";
10927d82585SIlya Biryukov case CCKind::CCC_Statement:
11027d82585SIlya Biryukov return "Statement";
11127d82585SIlya Biryukov case CCKind::CCC_Expression:
11227d82585SIlya Biryukov return "Expression";
11327d82585SIlya Biryukov case CCKind::CCC_ObjCMessageReceiver:
11427d82585SIlya Biryukov return "ObjCMessageReceiver";
11527d82585SIlya Biryukov case CCKind::CCC_DotMemberAccess:
11627d82585SIlya Biryukov return "DotMemberAccess";
11727d82585SIlya Biryukov case CCKind::CCC_ArrowMemberAccess:
11827d82585SIlya Biryukov return "ArrowMemberAccess";
11927d82585SIlya Biryukov case CCKind::CCC_ObjCPropertyAccess:
12027d82585SIlya Biryukov return "ObjCPropertyAccess";
12127d82585SIlya Biryukov case CCKind::CCC_EnumTag:
12227d82585SIlya Biryukov return "EnumTag";
12327d82585SIlya Biryukov case CCKind::CCC_UnionTag:
12427d82585SIlya Biryukov return "UnionTag";
12527d82585SIlya Biryukov case CCKind::CCC_ClassOrStructTag:
12627d82585SIlya Biryukov return "ClassOrStructTag";
12727d82585SIlya Biryukov case CCKind::CCC_ObjCProtocolName:
12827d82585SIlya Biryukov return "ObjCProtocolName";
12927d82585SIlya Biryukov case CCKind::CCC_Namespace:
13027d82585SIlya Biryukov return "Namespace";
13127d82585SIlya Biryukov case CCKind::CCC_Type:
13227d82585SIlya Biryukov return "Type";
133b006e099SKadir Cetinkaya case CCKind::CCC_NewName:
134b006e099SKadir Cetinkaya return "NewName";
135b006e099SKadir Cetinkaya case CCKind::CCC_Symbol:
136b006e099SKadir Cetinkaya return "Symbol";
137b006e099SKadir Cetinkaya case CCKind::CCC_SymbolOrNewName:
138b006e099SKadir Cetinkaya return "SymbolOrNewName";
13927d82585SIlya Biryukov case CCKind::CCC_MacroName:
14027d82585SIlya Biryukov return "MacroName";
14127d82585SIlya Biryukov case CCKind::CCC_MacroNameUse:
14227d82585SIlya Biryukov return "MacroNameUse";
14327d82585SIlya Biryukov case CCKind::CCC_PreprocessorExpression:
14427d82585SIlya Biryukov return "PreprocessorExpression";
14527d82585SIlya Biryukov case CCKind::CCC_PreprocessorDirective:
14627d82585SIlya Biryukov return "PreprocessorDirective";
14727d82585SIlya Biryukov case CCKind::CCC_NaturalLanguage:
14827d82585SIlya Biryukov return "NaturalLanguage";
14927d82585SIlya Biryukov case CCKind::CCC_SelectorName:
15027d82585SIlya Biryukov return "SelectorName";
15127d82585SIlya Biryukov case CCKind::CCC_TypeQualifiers:
15227d82585SIlya Biryukov return "TypeQualifiers";
15327d82585SIlya Biryukov case CCKind::CCC_ParenthesizedExpression:
15427d82585SIlya Biryukov return "ParenthesizedExpression";
15527d82585SIlya Biryukov case CCKind::CCC_ObjCInstanceMessage:
15627d82585SIlya Biryukov return "ObjCInstanceMessage";
15727d82585SIlya Biryukov case CCKind::CCC_ObjCClassMessage:
15827d82585SIlya Biryukov return "ObjCClassMessage";
15927d82585SIlya Biryukov case CCKind::CCC_ObjCInterfaceName:
16027d82585SIlya Biryukov return "ObjCInterfaceName";
16127d82585SIlya Biryukov case CCKind::CCC_ObjCCategoryName:
16227d82585SIlya Biryukov return "ObjCCategoryName";
1633d8051abSSam McCall case CCKind::CCC_IncludedFile:
1643d8051abSSam McCall return "IncludedFile";
165ece4e920SSam McCall case CCKind::CCC_Attribute:
166ece4e920SSam McCall return "Attribute";
16727d82585SIlya Biryukov case CCKind::CCC_Recovery:
16827d82585SIlya Biryukov return "Recovery";
16927d82585SIlya Biryukov }
17027d82585SIlya Biryukov llvm_unreachable("Invalid CodeCompletionContext::Kind!");
17127d82585SIlya Biryukov }
17227d82585SIlya Biryukov
1730212fd71SDouglas Gregor //===----------------------------------------------------------------------===//
174fedc328aSDouglas Gregor // Code completion string implementation
175fedc328aSDouglas Gregor //===----------------------------------------------------------------------===//
176711964ddSEugene Zelenko
Chunk(ChunkKind Kind,const char * Text)177b278aafbSDouglas Gregor CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
178711964ddSEugene Zelenko : Kind(Kind), Text("") {
1799eb7701dSDouglas Gregor switch (Kind) {
1809eb7701dSDouglas Gregor case CK_TypedText:
1819eb7701dSDouglas Gregor case CK_Text:
1829eb7701dSDouglas Gregor case CK_Placeholder:
1839eb7701dSDouglas Gregor case CK_Informative:
184b3fa919cSDouglas Gregor case CK_ResultType:
185b278aafbSDouglas Gregor case CK_CurrentParameter:
186b278aafbSDouglas Gregor this->Text = Text;
1879eb7701dSDouglas Gregor break;
1889eb7701dSDouglas Gregor
1899eb7701dSDouglas Gregor case CK_Optional:
1901615d45dSJeffrey Yasskin llvm_unreachable("Optional strings cannot be created from text");
1919eb7701dSDouglas Gregor
1929eb7701dSDouglas Gregor case CK_LeftParen:
1939eb7701dSDouglas Gregor this->Text = "(";
1949eb7701dSDouglas Gregor break;
1959eb7701dSDouglas Gregor
1969eb7701dSDouglas Gregor case CK_RightParen:
1979eb7701dSDouglas Gregor this->Text = ")";
1989eb7701dSDouglas Gregor break;
1999eb7701dSDouglas Gregor
2009eb7701dSDouglas Gregor case CK_LeftBracket:
2019eb7701dSDouglas Gregor this->Text = "[";
2029eb7701dSDouglas Gregor break;
2039eb7701dSDouglas Gregor
2049eb7701dSDouglas Gregor case CK_RightBracket:
2059eb7701dSDouglas Gregor this->Text = "]";
2069eb7701dSDouglas Gregor break;
2079eb7701dSDouglas Gregor
2089eb7701dSDouglas Gregor case CK_LeftBrace:
2099eb7701dSDouglas Gregor this->Text = "{";
2109eb7701dSDouglas Gregor break;
2119eb7701dSDouglas Gregor
2129eb7701dSDouglas Gregor case CK_RightBrace:
2139eb7701dSDouglas Gregor this->Text = "}";
2149eb7701dSDouglas Gregor break;
2159eb7701dSDouglas Gregor
2169eb7701dSDouglas Gregor case CK_LeftAngle:
2179eb7701dSDouglas Gregor this->Text = "<";
2189eb7701dSDouglas Gregor break;
2199eb7701dSDouglas Gregor
2209eb7701dSDouglas Gregor case CK_RightAngle:
2219eb7701dSDouglas Gregor this->Text = ">";
2229eb7701dSDouglas Gregor break;
2239eb7701dSDouglas Gregor
2249eb7701dSDouglas Gregor case CK_Comma:
2259eb7701dSDouglas Gregor this->Text = ", ";
2269eb7701dSDouglas Gregor break;
227504a6ae8SDouglas Gregor
228504a6ae8SDouglas Gregor case CK_Colon:
229504a6ae8SDouglas Gregor this->Text = ":";
230504a6ae8SDouglas Gregor break;
231504a6ae8SDouglas Gregor
232504a6ae8SDouglas Gregor case CK_SemiColon:
233504a6ae8SDouglas Gregor this->Text = ";";
234504a6ae8SDouglas Gregor break;
235504a6ae8SDouglas Gregor
236504a6ae8SDouglas Gregor case CK_Equal:
237504a6ae8SDouglas Gregor this->Text = " = ";
238504a6ae8SDouglas Gregor break;
239504a6ae8SDouglas Gregor
240504a6ae8SDouglas Gregor case CK_HorizontalSpace:
241504a6ae8SDouglas Gregor this->Text = " ";
242504a6ae8SDouglas Gregor break;
243504a6ae8SDouglas Gregor
244504a6ae8SDouglas Gregor case CK_VerticalSpace:
245504a6ae8SDouglas Gregor this->Text = "\n";
246504a6ae8SDouglas Gregor break;
2479eb7701dSDouglas Gregor }
2485bf52697SDouglas Gregor }
2495bf52697SDouglas Gregor
2505bf52697SDouglas Gregor CodeCompletionString::Chunk
CreateText(const char * Text)251b278aafbSDouglas Gregor CodeCompletionString::Chunk::CreateText(const char *Text) {
2525bf52697SDouglas Gregor return Chunk(CK_Text, Text);
253fedc328aSDouglas Gregor }
254fedc328aSDouglas Gregor
255fedc328aSDouglas Gregor CodeCompletionString::Chunk
CreateOptional(CodeCompletionString * Optional)256b278aafbSDouglas Gregor CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) {
257fedc328aSDouglas Gregor Chunk Result;
258fedc328aSDouglas Gregor Result.Kind = CK_Optional;
259b278aafbSDouglas Gregor Result.Optional = Optional;
260fedc328aSDouglas Gregor return Result;
261fedc328aSDouglas Gregor }
262fedc328aSDouglas Gregor
263fedc328aSDouglas Gregor CodeCompletionString::Chunk
CreatePlaceholder(const char * Placeholder)264b278aafbSDouglas Gregor CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
2655bf52697SDouglas Gregor return Chunk(CK_Placeholder, Placeholder);
2665bf52697SDouglas Gregor }
2675bf52697SDouglas Gregor
2685bf52697SDouglas Gregor CodeCompletionString::Chunk
CreateInformative(const char * Informative)269b278aafbSDouglas Gregor CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
2705bf52697SDouglas Gregor return Chunk(CK_Informative, Informative);
271fedc328aSDouglas Gregor }
272fedc328aSDouglas Gregor
2739eb7701dSDouglas Gregor CodeCompletionString::Chunk
CreateResultType(const char * ResultType)274b278aafbSDouglas Gregor CodeCompletionString::Chunk::CreateResultType(const char *ResultType) {
275b3fa919cSDouglas Gregor return Chunk(CK_ResultType, ResultType);
276b3fa919cSDouglas Gregor }
277b3fa919cSDouglas Gregor
CreateCurrentParameter(const char * CurrentParameter)278de314b39SFangrui Song CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateCurrentParameter(
279b278aafbSDouglas Gregor const char *CurrentParameter) {
2809eb7701dSDouglas Gregor return Chunk(CK_CurrentParameter, CurrentParameter);
2819eb7701dSDouglas Gregor }
2829eb7701dSDouglas Gregor
CodeCompletionString(const Chunk * Chunks,unsigned NumChunks,unsigned Priority,CXAvailabilityKind Availability,const char ** Annotations,unsigned NumAnnotations,StringRef ParentName,const char * BriefComment)283de314b39SFangrui Song CodeCompletionString::CodeCompletionString(
284de314b39SFangrui Song const Chunk *Chunks, unsigned NumChunks, unsigned Priority,
285de314b39SFangrui Song CXAvailabilityKind Availability, const char **Annotations,
286de314b39SFangrui Song unsigned NumAnnotations, StringRef ParentName, const char *BriefComment)
287de314b39SFangrui Song : NumChunks(NumChunks), NumAnnotations(NumAnnotations), Priority(Priority),
288de314b39SFangrui Song Availability(Availability), ParentName(ParentName),
289de314b39SFangrui Song BriefComment(BriefComment) {
29098ea7f67SErik Verbruggen assert(NumChunks <= 0xffff);
29198ea7f67SErik Verbruggen assert(NumAnnotations <= 0xffff);
29298ea7f67SErik Verbruggen
2931e95bc0fSEugene Zelenko Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1);
294b278aafbSDouglas Gregor for (unsigned I = 0; I != NumChunks; ++I)
295b278aafbSDouglas Gregor StoredChunks[I] = Chunks[I];
29698ea7f67SErik Verbruggen
297de314b39SFangrui Song const char **StoredAnnotations =
298de314b39SFangrui Song reinterpret_cast<const char **>(StoredChunks + NumChunks);
29998ea7f67SErik Verbruggen for (unsigned I = 0; I != NumAnnotations; ++I)
30098ea7f67SErik Verbruggen StoredAnnotations[I] = Annotations[I];
301fedc328aSDouglas Gregor }
302fedc328aSDouglas Gregor
getAnnotationCount() const30398ea7f67SErik Verbruggen unsigned CodeCompletionString::getAnnotationCount() const {
30498ea7f67SErik Verbruggen return NumAnnotations;
30598ea7f67SErik Verbruggen }
30698ea7f67SErik Verbruggen
getAnnotation(unsigned AnnotationNr) const30798ea7f67SErik Verbruggen const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const {
30898ea7f67SErik Verbruggen if (AnnotationNr < NumAnnotations)
30998ea7f67SErik Verbruggen return reinterpret_cast<const char *const *>(end())[AnnotationNr];
31098ea7f67SErik Verbruggen else
311c3ec149bSCraig Topper return nullptr;
31298ea7f67SErik Verbruggen }
31398ea7f67SErik Verbruggen
getAsString() const314fedc328aSDouglas Gregor std::string CodeCompletionString::getAsString() const {
315fedc328aSDouglas Gregor std::string Result;
316fedc328aSDouglas Gregor llvm::raw_string_ostream OS(Result);
317fedc328aSDouglas Gregor
318de314b39SFangrui Song for (const Chunk &C : *this) {
319de314b39SFangrui Song switch (C.Kind) {
320de314b39SFangrui Song case CK_Optional:
321de314b39SFangrui Song OS << "{#" << C.Optional->getAsString() << "#}";
322de314b39SFangrui Song break;
323de314b39SFangrui Song case CK_Placeholder:
324de314b39SFangrui Song OS << "<#" << C.Text << "#>";
325de314b39SFangrui Song break;
326b3fa919cSDouglas Gregor case CK_Informative:
327b3fa919cSDouglas Gregor case CK_ResultType:
328de314b39SFangrui Song OS << "[#" << C.Text << "#]";
329b3fa919cSDouglas Gregor break;
330de314b39SFangrui Song case CK_CurrentParameter:
331de314b39SFangrui Song OS << "<#" << C.Text << "#>";
332de314b39SFangrui Song break;
333de314b39SFangrui Song default:
334de314b39SFangrui Song OS << C.Text;
335de314b39SFangrui Song break;
336fedc328aSDouglas Gregor }
337fedc328aSDouglas Gregor }
3385276002aSLogan Smith return Result;
339fedc328aSDouglas Gregor }
340fedc328aSDouglas Gregor
getTypedText() const34145f83ee8SDouglas Gregor const char *CodeCompletionString::getTypedText() const {
342de314b39SFangrui Song for (const Chunk &C : *this)
343de314b39SFangrui Song if (C.Kind == CK_TypedText)
344de314b39SFangrui Song return C.Text;
34545f83ee8SDouglas Gregor
346c3ec149bSCraig Topper return nullptr;
34745f83ee8SDouglas Gregor }
34845f83ee8SDouglas Gregor
getAllTypedText() const349322e2a3bSDavid Goldman std::string CodeCompletionString::getAllTypedText() const {
350322e2a3bSDavid Goldman std::string Res;
351322e2a3bSDavid Goldman for (const Chunk &C : *this)
352322e2a3bSDavid Goldman if (C.Kind == CK_TypedText)
353322e2a3bSDavid Goldman Res += C.Text;
354322e2a3bSDavid Goldman
355322e2a3bSDavid Goldman return Res;
356322e2a3bSDavid Goldman }
357322e2a3bSDavid Goldman
CopyString(const Twine & String)3581ee89fc4SYaron Keren const char *CodeCompletionAllocator::CopyString(const Twine &String) {
3591ee89fc4SYaron Keren SmallString<128> Data;
3601ee89fc4SYaron Keren StringRef Ref = String.toStringRef(Data);
361669a25aeSDouglas Gregor // FIXME: It would be more efficient to teach Twine to tell us its size and
362669a25aeSDouglas Gregor // then add a routine there to fill in an allocated char* with the contents
363669a25aeSDouglas Gregor // of the string.
3641e95bc0fSEugene Zelenko char *Mem = (char *)Allocate(Ref.size() + 1, 1);
3651ee89fc4SYaron Keren std::copy(Ref.begin(), Ref.end(), Mem);
3661ee89fc4SYaron Keren Mem[Ref.size()] = 0;
3671ee89fc4SYaron Keren return Mem;
368669a25aeSDouglas Gregor }
369669a25aeSDouglas Gregor
getParentName(const DeclContext * DC)370fe0483dbSDmitri Gribenko StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
3715e373b2eSSimon Pilgrim if (!isa<NamedDecl>(DC))
372711964ddSEugene Zelenko return {};
3739d7c0fefSArgyrios Kyrtzidis
3749d7c0fefSArgyrios Kyrtzidis // Check whether we've already cached the parent name.
3759d7c0fefSArgyrios Kyrtzidis StringRef &CachedParentName = ParentNames[DC];
3769d7c0fefSArgyrios Kyrtzidis if (!CachedParentName.empty())
3779d7c0fefSArgyrios Kyrtzidis return CachedParentName;
3789d7c0fefSArgyrios Kyrtzidis
3799d7c0fefSArgyrios Kyrtzidis // If we already processed this DeclContext and assigned empty to it, the
3809d7c0fefSArgyrios Kyrtzidis // data pointer will be non-null.
381c3ec149bSCraig Topper if (CachedParentName.data() != nullptr)
382711964ddSEugene Zelenko return {};
3839d7c0fefSArgyrios Kyrtzidis
3849d7c0fefSArgyrios Kyrtzidis // Find the interesting names.
385fe0483dbSDmitri Gribenko SmallVector<const DeclContext *, 2> Contexts;
3869d7c0fefSArgyrios Kyrtzidis while (DC && !DC->isFunctionOrMethod()) {
387de314b39SFangrui Song if (const auto *ND = dyn_cast<NamedDecl>(DC)) {
3889d7c0fefSArgyrios Kyrtzidis if (ND->getIdentifier())
3899d7c0fefSArgyrios Kyrtzidis Contexts.push_back(DC);
3909d7c0fefSArgyrios Kyrtzidis }
3919d7c0fefSArgyrios Kyrtzidis
3929d7c0fefSArgyrios Kyrtzidis DC = DC->getParent();
3939d7c0fefSArgyrios Kyrtzidis }
3949d7c0fefSArgyrios Kyrtzidis
3959d7c0fefSArgyrios Kyrtzidis {
396f857950dSDmitri Gribenko SmallString<128> S;
3979d7c0fefSArgyrios Kyrtzidis llvm::raw_svector_ostream OS(S);
3989d7c0fefSArgyrios Kyrtzidis bool First = true;
3998adb6d6dSBenjamin Kramer for (const DeclContext *CurDC : llvm::reverse(Contexts)) {
4009d7c0fefSArgyrios Kyrtzidis if (First)
4019d7c0fefSArgyrios Kyrtzidis First = false;
4029d7c0fefSArgyrios Kyrtzidis else {
4039d7c0fefSArgyrios Kyrtzidis OS << "::";
4049d7c0fefSArgyrios Kyrtzidis }
4059d7c0fefSArgyrios Kyrtzidis
406de314b39SFangrui Song if (const auto *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
4079d7c0fefSArgyrios Kyrtzidis CurDC = CatImpl->getCategoryDecl();
4089d7c0fefSArgyrios Kyrtzidis
409de314b39SFangrui Song if (const auto *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
410fe0483dbSDmitri Gribenko const ObjCInterfaceDecl *Interface = Cat->getClassInterface();
4119d7c0fefSArgyrios Kyrtzidis if (!Interface) {
4129d7c0fefSArgyrios Kyrtzidis // Assign an empty StringRef but with non-null data to distinguish
4139d7c0fefSArgyrios Kyrtzidis // between empty because we didn't process the DeclContext yet.
414d16cebefSReid Kleckner CachedParentName = StringRef((const char *)(uintptr_t)~0U, 0);
415711964ddSEugene Zelenko return {};
4169d7c0fefSArgyrios Kyrtzidis }
4179d7c0fefSArgyrios Kyrtzidis
4189d7c0fefSArgyrios Kyrtzidis OS << Interface->getName() << '(' << Cat->getName() << ')';
4199d7c0fefSArgyrios Kyrtzidis } else {
4209d7c0fefSArgyrios Kyrtzidis OS << cast<NamedDecl>(CurDC)->getName();
4219d7c0fefSArgyrios Kyrtzidis }
4229d7c0fefSArgyrios Kyrtzidis }
4239d7c0fefSArgyrios Kyrtzidis
4249d7c0fefSArgyrios Kyrtzidis CachedParentName = AllocatorRef->CopyString(OS.str());
4259d7c0fefSArgyrios Kyrtzidis }
4269d7c0fefSArgyrios Kyrtzidis
4279d7c0fefSArgyrios Kyrtzidis return CachedParentName;
4289d7c0fefSArgyrios Kyrtzidis }
4299d7c0fefSArgyrios Kyrtzidis
TakeString()430b278aafbSDouglas Gregor CodeCompletionString *CodeCompletionBuilder::TakeString() {
4319d7c0fefSArgyrios Kyrtzidis void *Mem = getAllocator().Allocate(
432c3f89253SBenjamin Kramer sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() +
433c3f89253SBenjamin Kramer sizeof(const char *) * Annotations.size(),
434c3f89253SBenjamin Kramer alignof(CodeCompletionString));
435de314b39SFangrui Song CodeCompletionString *Result = new (Mem) CodeCompletionString(
436de314b39SFangrui Song Chunks.data(), Chunks.size(), Priority, Availability, Annotations.data(),
437de314b39SFangrui Song Annotations.size(), ParentName, BriefComment);
438b278aafbSDouglas Gregor Chunks.clear();
43945f83ee8SDouglas Gregor return Result;
44045f83ee8SDouglas Gregor }
4419eb7701dSDouglas Gregor
AddTypedTextChunk(const char * Text)442db534a4eSBenjamin Kramer void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) {
443db534a4eSBenjamin Kramer Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text));
444db534a4eSBenjamin Kramer }
445db534a4eSBenjamin Kramer
AddTextChunk(const char * Text)446db534a4eSBenjamin Kramer void CodeCompletionBuilder::AddTextChunk(const char *Text) {
447db534a4eSBenjamin Kramer Chunks.push_back(Chunk::CreateText(Text));
448db534a4eSBenjamin Kramer }
449db534a4eSBenjamin Kramer
AddOptionalChunk(CodeCompletionString * Optional)450db534a4eSBenjamin Kramer void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) {
451db534a4eSBenjamin Kramer Chunks.push_back(Chunk::CreateOptional(Optional));
452db534a4eSBenjamin Kramer }
453db534a4eSBenjamin Kramer
AddPlaceholderChunk(const char * Placeholder)454db534a4eSBenjamin Kramer void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) {
455db534a4eSBenjamin Kramer Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
456db534a4eSBenjamin Kramer }
457db534a4eSBenjamin Kramer
AddInformativeChunk(const char * Text)458db534a4eSBenjamin Kramer void CodeCompletionBuilder::AddInformativeChunk(const char *Text) {
459db534a4eSBenjamin Kramer Chunks.push_back(Chunk::CreateInformative(Text));
460db534a4eSBenjamin Kramer }
461db534a4eSBenjamin Kramer
AddResultTypeChunk(const char * ResultType)462db534a4eSBenjamin Kramer void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) {
463db534a4eSBenjamin Kramer Chunks.push_back(Chunk::CreateResultType(ResultType));
464db534a4eSBenjamin Kramer }
465db534a4eSBenjamin Kramer
AddCurrentParameterChunk(const char * CurrentParameter)466de314b39SFangrui Song void CodeCompletionBuilder::AddCurrentParameterChunk(
467de314b39SFangrui Song const char *CurrentParameter) {
468db534a4eSBenjamin Kramer Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter));
469db534a4eSBenjamin Kramer }
470db534a4eSBenjamin Kramer
AddChunk(CodeCompletionString::ChunkKind CK,const char * Text)471db534a4eSBenjamin Kramer void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK,
472db534a4eSBenjamin Kramer const char *Text) {
473db534a4eSBenjamin Kramer Chunks.push_back(Chunk(CK, Text));
474db534a4eSBenjamin Kramer }
475db534a4eSBenjamin Kramer
addParentContext(const DeclContext * DC)476fe0483dbSDmitri Gribenko void CodeCompletionBuilder::addParentContext(const DeclContext *DC) {
477711964ddSEugene Zelenko if (DC->isTranslationUnit())
47878254c88SDouglas Gregor return;
47978254c88SDouglas Gregor
48078254c88SDouglas Gregor if (DC->isFunctionOrMethod())
48178254c88SDouglas Gregor return;
48278254c88SDouglas Gregor
4835e373b2eSSimon Pilgrim if (!isa<NamedDecl>(DC))
48478254c88SDouglas Gregor return;
48578254c88SDouglas Gregor
4869d7c0fefSArgyrios Kyrtzidis ParentName = getCodeCompletionTUInfo().getParentName(DC);
48778254c88SDouglas Gregor }
48878254c88SDouglas Gregor
addBriefComment(StringRef Comment)4893292d06aSDmitri Gribenko void CodeCompletionBuilder::addBriefComment(StringRef Comment) {
4903292d06aSDmitri Gribenko BriefComment = Allocator.CopyString(Comment);
4913292d06aSDmitri Gribenko }
4923292d06aSDmitri Gribenko
493fedc328aSDouglas Gregor //===----------------------------------------------------------------------===//
49405f477c1SDouglas Gregor // Code completion overload candidate implementation
49505f477c1SDouglas Gregor //===----------------------------------------------------------------------===//
getFunction() const496de314b39SFangrui Song FunctionDecl *CodeCompleteConsumer::OverloadCandidate::getFunction() const {
49705f477c1SDouglas Gregor if (getKind() == CK_Function)
49805f477c1SDouglas Gregor return Function;
49905f477c1SDouglas Gregor else if (getKind() == CK_FunctionTemplate)
50005f477c1SDouglas Gregor return FunctionTemplate->getTemplatedDecl();
50105f477c1SDouglas Gregor else
502c3ec149bSCraig Topper return nullptr;
50305f477c1SDouglas Gregor }
50405f477c1SDouglas Gregor
50505f477c1SDouglas Gregor const FunctionType *
getFunctionType() const50605f477c1SDouglas Gregor CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
50705f477c1SDouglas Gregor switch (Kind) {
50805f477c1SDouglas Gregor case CK_Function:
50905f477c1SDouglas Gregor return Function->getType()->getAs<FunctionType>();
51005f477c1SDouglas Gregor
51105f477c1SDouglas Gregor case CK_FunctionTemplate:
512de314b39SFangrui Song return FunctionTemplate->getTemplatedDecl()
513de314b39SFangrui Song ->getType()
51405f477c1SDouglas Gregor ->getAs<FunctionType>();
51505f477c1SDouglas Gregor
51605f477c1SDouglas Gregor case CK_FunctionType:
51705f477c1SDouglas Gregor return Type;
518*3f73c579SQwinci case CK_FunctionProtoTypeLoc:
519*3f73c579SQwinci return ProtoTypeLoc.getTypePtr();
520cd45e8c7SSam McCall case CK_Template:
521229c95abSSam McCall case CK_Aggregate:
522cd45e8c7SSam McCall return nullptr;
52305f477c1SDouglas Gregor }
52405f477c1SDouglas Gregor
5258a40f700SDavid Blaikie llvm_unreachable("Invalid CandidateKind!");
52605f477c1SDouglas Gregor }
52705f477c1SDouglas Gregor
528*3f73c579SQwinci const FunctionProtoTypeLoc
getFunctionProtoTypeLoc() const529*3f73c579SQwinci CodeCompleteConsumer::OverloadCandidate::getFunctionProtoTypeLoc() const {
530*3f73c579SQwinci if (Kind == CK_FunctionProtoTypeLoc)
531*3f73c579SQwinci return ProtoTypeLoc;
532*3f73c579SQwinci return FunctionProtoTypeLoc();
533*3f73c579SQwinci }
534*3f73c579SQwinci
getNumParams() const535cd45e8c7SSam McCall unsigned CodeCompleteConsumer::OverloadCandidate::getNumParams() const {
536cd45e8c7SSam McCall if (Kind == CK_Template)
537cd45e8c7SSam McCall return Template->getTemplateParameters()->size();
538229c95abSSam McCall
539229c95abSSam McCall if (Kind == CK_Aggregate) {
540229c95abSSam McCall unsigned Count =
541229c95abSSam McCall std::distance(AggregateType->field_begin(), AggregateType->field_end());
542229c95abSSam McCall if (const auto *CRD = dyn_cast<CXXRecordDecl>(AggregateType))
543229c95abSSam McCall Count += CRD->getNumBases();
544229c95abSSam McCall return Count;
545229c95abSSam McCall }
546229c95abSSam McCall
547229c95abSSam McCall if (const auto *FT = getFunctionType())
548229c95abSSam McCall if (const auto *FPT = dyn_cast<FunctionProtoType>(FT))
549cd45e8c7SSam McCall return FPT->getNumParams();
550229c95abSSam McCall
551cd45e8c7SSam McCall return 0;
552cd45e8c7SSam McCall }
553cd45e8c7SSam McCall
554229c95abSSam McCall QualType
getParamType(unsigned N) const555229c95abSSam McCall CodeCompleteConsumer::OverloadCandidate::getParamType(unsigned N) const {
556229c95abSSam McCall if (Kind == CK_Aggregate) {
557229c95abSSam McCall if (const auto *CRD = dyn_cast<CXXRecordDecl>(AggregateType)) {
558229c95abSSam McCall if (N < CRD->getNumBases())
559229c95abSSam McCall return std::next(CRD->bases_begin(), N)->getType();
560229c95abSSam McCall N -= CRD->getNumBases();
561229c95abSSam McCall }
562229c95abSSam McCall for (const auto *Field : AggregateType->fields())
563229c95abSSam McCall if (N-- == 0)
564229c95abSSam McCall return Field->getType();
565229c95abSSam McCall return QualType();
566229c95abSSam McCall }
567229c95abSSam McCall
568229c95abSSam McCall if (Kind == CK_Template) {
569229c95abSSam McCall TemplateParameterList *TPL = getTemplate()->getTemplateParameters();
570229c95abSSam McCall if (N < TPL->size())
571229c95abSSam McCall if (const auto *D = dyn_cast<NonTypeTemplateParmDecl>(TPL->getParam(N)))
572229c95abSSam McCall return D->getType();
573229c95abSSam McCall return QualType();
574229c95abSSam McCall }
575229c95abSSam McCall
576229c95abSSam McCall if (const auto *FT = getFunctionType())
577229c95abSSam McCall if (const auto *FPT = dyn_cast<FunctionProtoType>(FT))
578229c95abSSam McCall if (N < FPT->getNumParams())
579229c95abSSam McCall return FPT->getParamType(N);
580229c95abSSam McCall return QualType();
581229c95abSSam McCall }
582229c95abSSam McCall
583229c95abSSam McCall const NamedDecl *
getParamDecl(unsigned N) const584229c95abSSam McCall CodeCompleteConsumer::OverloadCandidate::getParamDecl(unsigned N) const {
585229c95abSSam McCall if (Kind == CK_Aggregate) {
586229c95abSSam McCall if (const auto *CRD = dyn_cast<CXXRecordDecl>(AggregateType)) {
587229c95abSSam McCall if (N < CRD->getNumBases())
588229c95abSSam McCall return std::next(CRD->bases_begin(), N)->getType()->getAsTagDecl();
589229c95abSSam McCall N -= CRD->getNumBases();
590229c95abSSam McCall }
591229c95abSSam McCall for (const auto *Field : AggregateType->fields())
592229c95abSSam McCall if (N-- == 0)
593229c95abSSam McCall return Field;
594229c95abSSam McCall return nullptr;
595229c95abSSam McCall }
596229c95abSSam McCall
597229c95abSSam McCall if (Kind == CK_Template) {
598229c95abSSam McCall TemplateParameterList *TPL = getTemplate()->getTemplateParameters();
599229c95abSSam McCall if (N < TPL->size())
600229c95abSSam McCall return TPL->getParam(N);
601229c95abSSam McCall return nullptr;
602229c95abSSam McCall }
603229c95abSSam McCall
604229c95abSSam McCall // Note that if we only have a FunctionProtoType, we don't have param decls.
605229c95abSSam McCall if (const auto *FD = getFunction()) {
606229c95abSSam McCall if (N < FD->param_size())
607229c95abSSam McCall return FD->getParamDecl(N);
608*3f73c579SQwinci } else if (Kind == CK_FunctionProtoTypeLoc) {
609*3f73c579SQwinci if (N < ProtoTypeLoc.getNumParams()) {
610*3f73c579SQwinci return ProtoTypeLoc.getParam(N);
611229c95abSSam McCall }
612*3f73c579SQwinci }
613*3f73c579SQwinci
614229c95abSSam McCall return nullptr;
615229c95abSSam McCall }
616229c95abSSam McCall
61705f477c1SDouglas Gregor //===----------------------------------------------------------------------===//
618fedc328aSDouglas Gregor // Code completion consumer implementation
619fedc328aSDouglas Gregor //===----------------------------------------------------------------------===//
620fedc328aSDouglas Gregor
621711964ddSEugene Zelenko CodeCompleteConsumer::~CodeCompleteConsumer() = default;
622fedc328aSDouglas Gregor
isResultFilteredOut(StringRef Filter,CodeCompletionResult Result)623de314b39SFangrui Song bool PrintingCodeCompleteConsumer::isResultFilteredOut(
624de314b39SFangrui Song StringRef Filter, CodeCompletionResult Result) {
625644ea61dSVassil Vassilev switch (Result.Kind) {
626711964ddSEugene Zelenko case CodeCompletionResult::RK_Declaration:
627644ea61dSVassil Vassilev return !(Result.Declaration->getIdentifier() &&
628644ea61dSVassil Vassilev Result.Declaration->getIdentifier()->getName().startswith(Filter));
629711964ddSEugene Zelenko case CodeCompletionResult::RK_Keyword:
630644ea61dSVassil Vassilev return !StringRef(Result.Keyword).startswith(Filter);
631711964ddSEugene Zelenko case CodeCompletionResult::RK_Macro:
632644ea61dSVassil Vassilev return !Result.Macro->getName().startswith(Filter);
633711964ddSEugene Zelenko case CodeCompletionResult::RK_Pattern:
6343d8051abSSam McCall return !(Result.Pattern->getTypedText() &&
6353d8051abSSam McCall StringRef(Result.Pattern->getTypedText()).startswith(Filter));
636644ea61dSVassil Vassilev }
637e71a1f90SSimon Pilgrim llvm_unreachable("Unknown code completion result Kind.");
638644ea61dSVassil Vassilev }
639644ea61dSVassil Vassilev
ProcessCodeCompleteResults(Sema & SemaRef,CodeCompletionContext Context,CodeCompletionResult * Results,unsigned NumResults)640de314b39SFangrui Song void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(
641de314b39SFangrui Song Sema &SemaRef, CodeCompletionContext Context, CodeCompletionResult *Results,
6422436e711SDouglas Gregor unsigned NumResults) {
64349f67ce4SDouglas Gregor std::stable_sort(Results, Results + NumResults);
64449f67ce4SDouglas Gregor
6454110967cSIlya Biryukov if (!Context.getPreferredType().isNull())
646cfb81690SNathan James OS << "PREFERRED-TYPE: " << Context.getPreferredType() << '\n';
647644ea61dSVassil Vassilev
6484110967cSIlya Biryukov StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
6494110967cSIlya Biryukov // Print the completions.
6502436e711SDouglas Gregor for (unsigned I = 0; I != NumResults; ++I) {
651644ea61dSVassil Vassilev if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
652644ea61dSVassil Vassilev continue;
65358acf32aSDouglas Gregor OS << "COMPLETION: ";
6542436e711SDouglas Gregor switch (Results[I].Kind) {
655276321a9SJohn McCall case CodeCompletionResult::RK_Declaration:
656b89514a9SBenjamin Kramer OS << *Results[I].Declaration;
6574a7cd637SEric Liu {
6584a7cd637SEric Liu std::vector<std::string> Tags;
6592436e711SDouglas Gregor if (Results[I].Hidden)
6604a7cd637SEric Liu Tags.push_back("Hidden");
6614a7cd637SEric Liu if (Results[I].InBaseClass)
6624a7cd637SEric Liu Tags.push_back("InBase");
663f1822ec4SIlya Biryukov if (Results[I].Availability ==
664f1822ec4SIlya Biryukov CXAvailabilityKind::CXAvailability_NotAccessible)
665f1822ec4SIlya Biryukov Tags.push_back("Inaccessible");
6664a7cd637SEric Liu if (!Tags.empty())
6674a7cd637SEric Liu OS << " (" << llvm::join(Tags, ",") << ")";
6684a7cd637SEric Liu }
6694a7cd637SEric Liu if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(
6704a7cd637SEric Liu SemaRef, Context, getAllocator(), CCTUInfo,
6713292d06aSDmitri Gribenko includeBriefComments())) {
672fedc328aSDouglas Gregor OS << " : " << CCS->getAsString();
6733292d06aSDmitri Gribenko if (const char *BriefComment = CCS->getBriefComment())
6743292d06aSDmitri Gribenko OS << " : " << BriefComment;
675fedc328aSDouglas Gregor }
676a76e68c9SSam McCall break;
677a76e68c9SSam McCall
678a76e68c9SSam McCall case CodeCompletionResult::RK_Keyword:
679a76e68c9SSam McCall OS << Results[I].Keyword;
680a76e68c9SSam McCall break;
681a76e68c9SSam McCall
682a76e68c9SSam McCall case CodeCompletionResult::RK_Macro:
683a76e68c9SSam McCall OS << Results[I].Macro->getName();
684a76e68c9SSam McCall if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(
685a76e68c9SSam McCall SemaRef, Context, getAllocator(), CCTUInfo,
686a76e68c9SSam McCall includeBriefComments())) {
687a76e68c9SSam McCall OS << " : " << CCS->getAsString();
688a76e68c9SSam McCall }
689a76e68c9SSam McCall break;
690a76e68c9SSam McCall
691a76e68c9SSam McCall case CodeCompletionResult::RK_Pattern:
692a76e68c9SSam McCall OS << "Pattern : " << Results[I].Pattern->getAsString();
693a76e68c9SSam McCall break;
694a76e68c9SSam McCall }
695b4670fc7SIvan Donchevskii for (const FixItHint &FixIt : Results[I].FixIts) {
696b4670fc7SIvan Donchevskii const SourceLocation BLoc = FixIt.RemoveRange.getBegin();
697b4670fc7SIvan Donchevskii const SourceLocation ELoc = FixIt.RemoveRange.getEnd();
698b4670fc7SIvan Donchevskii
699b4670fc7SIvan Donchevskii SourceManager &SM = SemaRef.SourceMgr;
700b4670fc7SIvan Donchevskii std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
701b4670fc7SIvan Donchevskii std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
702b4670fc7SIvan Donchevskii // Adjust for token ranges.
703b4670fc7SIvan Donchevskii if (FixIt.RemoveRange.isTokenRange())
704b4670fc7SIvan Donchevskii EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts);
705b4670fc7SIvan Donchevskii
706b4670fc7SIvan Donchevskii OS << " (requires fix-it:"
707b4670fc7SIvan Donchevskii << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
708b4670fc7SIvan Donchevskii << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
709b4670fc7SIvan Donchevskii << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
710b4670fc7SIvan Donchevskii << SM.getColumnNumber(EInfo.first, EInfo.second) << "}"
711b4670fc7SIvan Donchevskii << " to \"" << FixIt.CodeToInsert << "\")";
712b4670fc7SIvan Donchevskii }
7132436e711SDouglas Gregor OS << '\n';
7142436e711SDouglas Gregor }
7152436e711SDouglas Gregor }
71605f477c1SDouglas Gregor
7170c010cddSFrancisco Lopes da Silva // This function is used solely to preserve the former presentation of overloads
7180c010cddSFrancisco Lopes da Silva // by "clang -cc1 -code-completion-at", since CodeCompletionString::getAsString
7190c010cddSFrancisco Lopes da Silva // needs to be improved for printing the newer and more detailed overload
7200c010cddSFrancisco Lopes da Silva // chunks.
getOverloadAsString(const CodeCompletionString & CCS)7210c010cddSFrancisco Lopes da Silva static std::string getOverloadAsString(const CodeCompletionString &CCS) {
7220c010cddSFrancisco Lopes da Silva std::string Result;
7230c010cddSFrancisco Lopes da Silva llvm::raw_string_ostream OS(Result);
7240c010cddSFrancisco Lopes da Silva
7250c010cddSFrancisco Lopes da Silva for (auto &C : CCS) {
7260c010cddSFrancisco Lopes da Silva switch (C.Kind) {
7270c010cddSFrancisco Lopes da Silva case CodeCompletionString::CK_Informative:
7280c010cddSFrancisco Lopes da Silva case CodeCompletionString::CK_ResultType:
7290c010cddSFrancisco Lopes da Silva OS << "[#" << C.Text << "#]";
7300c010cddSFrancisco Lopes da Silva break;
7310c010cddSFrancisco Lopes da Silva
7320c010cddSFrancisco Lopes da Silva case CodeCompletionString::CK_CurrentParameter:
7330c010cddSFrancisco Lopes da Silva OS << "<#" << C.Text << "#>";
7340c010cddSFrancisco Lopes da Silva break;
7350c010cddSFrancisco Lopes da Silva
736a32d253fSKadir Cetinkaya // FIXME: We can also print optional parameters of an overload.
737a32d253fSKadir Cetinkaya case CodeCompletionString::CK_Optional:
738a32d253fSKadir Cetinkaya break;
739a32d253fSKadir Cetinkaya
740de314b39SFangrui Song default:
741de314b39SFangrui Song OS << C.Text;
742de314b39SFangrui Song break;
7430c010cddSFrancisco Lopes da Silva }
7440c010cddSFrancisco Lopes da Silva }
7455276002aSLogan Smith return Result;
7460c010cddSFrancisco Lopes da Silva }
7470c010cddSFrancisco Lopes da Silva
ProcessOverloadCandidates(Sema & SemaRef,unsigned CurrentArg,OverloadCandidate * Candidates,unsigned NumCandidates,SourceLocation OpenParLoc,bool Braced)7482fab2353SIlya Biryukov void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
7492fab2353SIlya Biryukov Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates,
75092417eafSSam McCall unsigned NumCandidates, SourceLocation OpenParLoc, bool Braced) {
7512fab2353SIlya Biryukov OS << "OPENING_PAREN_LOC: ";
7522fab2353SIlya Biryukov OpenParLoc.print(OS, SemaRef.getSourceManager());
7532fab2353SIlya Biryukov OS << "\n";
7542fab2353SIlya Biryukov
75505f477c1SDouglas Gregor for (unsigned I = 0; I != NumCandidates; ++I) {
7562fab2353SIlya Biryukov if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(
7572fab2353SIlya Biryukov CurrentArg, SemaRef, getAllocator(), CCTUInfo,
75892417eafSSam McCall includeBriefComments(), Braced)) {
7590c010cddSFrancisco Lopes da Silva OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
76005f477c1SDouglas Gregor }
76105f477c1SDouglas Gregor }
76205f477c1SDouglas Gregor }
7639eb7701dSDouglas Gregor
7649fc8faf9SAdrian Prantl /// Retrieve the effective availability of the given declaration.
getDeclAvailability(const Decl * D)765fe0483dbSDmitri Gribenko static AvailabilityResult getDeclAvailability(const Decl *D) {
7667b316825SDouglas Gregor AvailabilityResult AR = D->getAvailability();
7677b316825SDouglas Gregor if (isa<EnumConstantDecl>(D))
7687b316825SDouglas Gregor AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability());
7697b316825SDouglas Gregor return AR;
7707b316825SDouglas Gregor }
7717b316825SDouglas Gregor
computeCursorKindAndAvailability(bool Accessible)7722e657ffdSErik Verbruggen void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
773b14904c4SDouglas Gregor switch (Kind) {
77478254c88SDouglas Gregor case RK_Pattern:
77578254c88SDouglas Gregor if (!Declaration) {
77678254c88SDouglas Gregor // Do nothing: Patterns can come with cursor kinds!
77778254c88SDouglas Gregor break;
77878254c88SDouglas Gregor }
779f3b3ccdaSAdrian Prantl LLVM_FALLTHROUGH;
78078254c88SDouglas Gregor
7817b316825SDouglas Gregor case RK_Declaration: {
782f757a12dSDouglas Gregor // Set the availability based on attributes.
7837b316825SDouglas Gregor switch (getDeclAvailability(Declaration)) {
78420b2ebd7SDouglas Gregor case AR_Available:
78520b2ebd7SDouglas Gregor case AR_NotYetIntroduced:
786f757a12dSDouglas Gregor Availability = CXAvailability_Available;
78720b2ebd7SDouglas Gregor break;
78820b2ebd7SDouglas Gregor
78920b2ebd7SDouglas Gregor case AR_Deprecated:
790f757a12dSDouglas Gregor Availability = CXAvailability_Deprecated;
79120b2ebd7SDouglas Gregor break;
79220b2ebd7SDouglas Gregor
79320b2ebd7SDouglas Gregor case AR_Unavailable:
79420b2ebd7SDouglas Gregor Availability = CXAvailability_NotAvailable;
79520b2ebd7SDouglas Gregor break;
79620b2ebd7SDouglas Gregor }
797f757a12dSDouglas Gregor
798de314b39SFangrui Song if (const auto *Function = dyn_cast<FunctionDecl>(Declaration))
79909c0eb15SDouglas Gregor if (Function->isDeleted())
800f757a12dSDouglas Gregor Availability = CXAvailability_NotAvailable;
801f09935f1SDouglas Gregor
80209c0eb15SDouglas Gregor CursorKind = getCursorKindForDecl(Declaration);
803deafd0b2SDouglas Gregor if (CursorKind == CXCursor_UnexposedDecl) {
804f6102675SDouglas Gregor // FIXME: Forward declarations of Objective-C classes and protocols
805f6102675SDouglas Gregor // are not directly exposed, but we want code completion to treat them
806f6102675SDouglas Gregor // like a definition.
807deafd0b2SDouglas Gregor if (isa<ObjCInterfaceDecl>(Declaration))
808deafd0b2SDouglas Gregor CursorKind = CXCursor_ObjCInterfaceDecl;
809f6102675SDouglas Gregor else if (isa<ObjCProtocolDecl>(Declaration))
810f6102675SDouglas Gregor CursorKind = CXCursor_ObjCProtocolDecl;
811deafd0b2SDouglas Gregor else
812b14904c4SDouglas Gregor CursorKind = CXCursor_NotImplemented;
813deafd0b2SDouglas Gregor }
814f09935f1SDouglas Gregor break;
8157b316825SDouglas Gregor }
8169eb7701dSDouglas Gregor
817276321a9SJohn McCall case RK_Macro:
818276321a9SJohn McCall case RK_Keyword:
819c25c0b9dSBenjamin Kramer llvm_unreachable("Macro and keyword kinds are handled by the constructors");
8208e984da8SDouglas Gregor }
8212e657ffdSErik Verbruggen
8222e657ffdSErik Verbruggen if (!Accessible)
8232e657ffdSErik Verbruggen Availability = CXAvailability_NotAccessible;
824f09935f1SDouglas Gregor }
8259eb7701dSDouglas Gregor
8269fc8faf9SAdrian Prantl /// Retrieve the name that should be used to order a result.
8270de55cecSDouglas Gregor ///
8280de55cecSDouglas Gregor /// If the name needs to be constructed as a string, that string will be
8290de55cecSDouglas Gregor /// saved into Saved and the returned StringRef will refer to it.
getOrderedName(std::string & Saved) const8301102a861SSam McCall StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const {
8311102a861SSam McCall switch (Kind) {
8321102a861SSam McCall case RK_Keyword:
8331102a861SSam McCall return Keyword;
8341102a861SSam McCall case RK_Pattern:
8351102a861SSam McCall return Pattern->getTypedText();
8361102a861SSam McCall case RK_Macro:
8371102a861SSam McCall return Macro->getName();
8381102a861SSam McCall case RK_Declaration:
8390de55cecSDouglas Gregor // Handle declarations below.
8400de55cecSDouglas Gregor break;
8410de55cecSDouglas Gregor }
8420de55cecSDouglas Gregor
8431102a861SSam McCall DeclarationName Name = Declaration->getDeclName();
8440de55cecSDouglas Gregor
8450de55cecSDouglas Gregor // If the name is a simple identifier (by far the common case), or a
8460de55cecSDouglas Gregor // zero-argument selector, just return a reference to that identifier.
8470de55cecSDouglas Gregor if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
8480de55cecSDouglas Gregor return Id->getName();
8490de55cecSDouglas Gregor if (Name.isObjCZeroArgSelector())
850de314b39SFangrui Song if (IdentifierInfo *Id = Name.getObjCSelector().getIdentifierInfoForSlot(0))
8510de55cecSDouglas Gregor return Id->getName();
8520de55cecSDouglas Gregor
8530de55cecSDouglas Gregor Saved = Name.getAsString();
8540de55cecSDouglas Gregor return Saved;
8550de55cecSDouglas Gregor }
8560de55cecSDouglas Gregor
operator <(const CodeCompletionResult & X,const CodeCompletionResult & Y)8570de55cecSDouglas Gregor bool clang::operator<(const CodeCompletionResult &X,
8580de55cecSDouglas Gregor const CodeCompletionResult &Y) {
8590de55cecSDouglas Gregor std::string XSaved, YSaved;
8601102a861SSam McCall StringRef XStr = X.getOrderedName(XSaved);
8611102a861SSam McCall StringRef YStr = Y.getOrderedName(YSaved);
862e5c7c171SMartin Storsjö int cmp = XStr.compare_insensitive(YStr);
8630de55cecSDouglas Gregor if (cmp)
8640de55cecSDouglas Gregor return cmp < 0;
8650de55cecSDouglas Gregor
86649f67ce4SDouglas Gregor // If case-insensitive comparison fails, try case-sensitive comparison.
867de314b39SFangrui Song return XStr.compare(YStr) < 0;
8680de55cecSDouglas Gregor }
869