1051 lines · cpp
1//===- CIndexCodeCompletion.cpp - Code Completion API hooks ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the Clang-C Source Indexing library hooks for10// code completion.11//12//===----------------------------------------------------------------------===//13 14#include "CIndexDiagnostic.h"15#include "CIndexer.h"16#include "CLog.h"17#include "CXCursor.h"18#include "CXSourceLocation.h"19#include "CXString.h"20#include "CXTranslationUnit.h"21#include "clang/AST/Decl.h"22#include "clang/AST/DeclObjC.h"23#include "clang/AST/Type.h"24#include "clang/Basic/FileManager.h"25#include "clang/Basic/SourceManager.h"26#include "clang/Frontend/ASTUnit.h"27#include "clang/Frontend/CompilerInstance.h"28#include "clang/Frontend/FrontendActions.h"29#include "clang/Sema/CodeCompleteConsumer.h"30#include "clang/Sema/Sema.h"31#include "llvm/ADT/SmallString.h"32#include "llvm/ADT/StringExtras.h"33#include "llvm/Support/CrashRecoveryContext.h"34#include "llvm/Support/FileSystem.h"35#include "llvm/Support/FormatVariadic.h"36#include "llvm/Support/MemoryBuffer.h"37#include "llvm/Support/Program.h"38#include "llvm/Support/Timer.h"39#include "llvm/Support/raw_ostream.h"40#include <atomic>41#include <cstdio>42#include <cstdlib>43#include <string>44 45#ifdef UDP_CODE_COMPLETION_LOGGER46#include "clang/Basic/Version.h"47#include <arpa/inet.h>48#include <sys/socket.h>49#include <sys/types.h>50#include <unistd.h>51#endif52 53using namespace clang;54using namespace clang::cxindex;55 56enum CXCompletionChunkKind57clang_getCompletionChunkKind(CXCompletionString completion_string,58 unsigned chunk_number) {59 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;60 if (!CCStr || chunk_number >= CCStr->size())61 return CXCompletionChunk_Text;62 63 switch ((*CCStr)[chunk_number].Kind) {64 case CodeCompletionString::CK_TypedText:65 return CXCompletionChunk_TypedText;66 case CodeCompletionString::CK_Text:67 return CXCompletionChunk_Text;68 case CodeCompletionString::CK_Optional:69 return CXCompletionChunk_Optional;70 case CodeCompletionString::CK_Placeholder:71 return CXCompletionChunk_Placeholder;72 case CodeCompletionString::CK_Informative:73 return CXCompletionChunk_Informative;74 case CodeCompletionString::CK_ResultType:75 return CXCompletionChunk_ResultType;76 case CodeCompletionString::CK_CurrentParameter:77 return CXCompletionChunk_CurrentParameter;78 case CodeCompletionString::CK_LeftParen:79 return CXCompletionChunk_LeftParen;80 case CodeCompletionString::CK_RightParen:81 return CXCompletionChunk_RightParen;82 case CodeCompletionString::CK_LeftBracket:83 return CXCompletionChunk_LeftBracket;84 case CodeCompletionString::CK_RightBracket:85 return CXCompletionChunk_RightBracket;86 case CodeCompletionString::CK_LeftBrace:87 return CXCompletionChunk_LeftBrace;88 case CodeCompletionString::CK_RightBrace:89 return CXCompletionChunk_RightBrace;90 case CodeCompletionString::CK_LeftAngle:91 return CXCompletionChunk_LeftAngle;92 case CodeCompletionString::CK_RightAngle:93 return CXCompletionChunk_RightAngle;94 case CodeCompletionString::CK_Comma:95 return CXCompletionChunk_Comma;96 case CodeCompletionString::CK_Colon:97 return CXCompletionChunk_Colon;98 case CodeCompletionString::CK_SemiColon:99 return CXCompletionChunk_SemiColon;100 case CodeCompletionString::CK_Equal:101 return CXCompletionChunk_Equal;102 case CodeCompletionString::CK_HorizontalSpace:103 return CXCompletionChunk_HorizontalSpace;104 case CodeCompletionString::CK_VerticalSpace:105 return CXCompletionChunk_VerticalSpace;106 }107 108 llvm_unreachable("Invalid CompletionKind!");109}110 111CXString clang_getCompletionChunkText(CXCompletionString completion_string,112 unsigned chunk_number) {113 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;114 if (!CCStr || chunk_number >= CCStr->size())115 return cxstring::createNull();116 117 switch ((*CCStr)[chunk_number].Kind) {118 case CodeCompletionString::CK_TypedText:119 case CodeCompletionString::CK_Text:120 case CodeCompletionString::CK_Placeholder:121 case CodeCompletionString::CK_CurrentParameter:122 case CodeCompletionString::CK_Informative:123 case CodeCompletionString::CK_LeftParen:124 case CodeCompletionString::CK_RightParen:125 case CodeCompletionString::CK_LeftBracket:126 case CodeCompletionString::CK_RightBracket:127 case CodeCompletionString::CK_LeftBrace:128 case CodeCompletionString::CK_RightBrace:129 case CodeCompletionString::CK_LeftAngle:130 case CodeCompletionString::CK_RightAngle:131 case CodeCompletionString::CK_Comma:132 case CodeCompletionString::CK_ResultType:133 case CodeCompletionString::CK_Colon:134 case CodeCompletionString::CK_SemiColon:135 case CodeCompletionString::CK_Equal:136 case CodeCompletionString::CK_HorizontalSpace:137 case CodeCompletionString::CK_VerticalSpace:138 return cxstring::createRef((*CCStr)[chunk_number].Text);139 140 case CodeCompletionString::CK_Optional:141 // Note: treated as an empty text block.142 return cxstring::createEmpty();143 }144 145 llvm_unreachable("Invalid CodeCompletionString Kind!");146}147 148 149CXCompletionString150clang_getCompletionChunkCompletionString(CXCompletionString completion_string,151 unsigned chunk_number) {152 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;153 if (!CCStr || chunk_number >= CCStr->size())154 return nullptr;155 156 switch ((*CCStr)[chunk_number].Kind) {157 case CodeCompletionString::CK_TypedText:158 case CodeCompletionString::CK_Text:159 case CodeCompletionString::CK_Placeholder:160 case CodeCompletionString::CK_CurrentParameter:161 case CodeCompletionString::CK_Informative:162 case CodeCompletionString::CK_LeftParen:163 case CodeCompletionString::CK_RightParen:164 case CodeCompletionString::CK_LeftBracket:165 case CodeCompletionString::CK_RightBracket:166 case CodeCompletionString::CK_LeftBrace:167 case CodeCompletionString::CK_RightBrace:168 case CodeCompletionString::CK_LeftAngle:169 case CodeCompletionString::CK_RightAngle:170 case CodeCompletionString::CK_Comma:171 case CodeCompletionString::CK_ResultType:172 case CodeCompletionString::CK_Colon:173 case CodeCompletionString::CK_SemiColon:174 case CodeCompletionString::CK_Equal:175 case CodeCompletionString::CK_HorizontalSpace:176 case CodeCompletionString::CK_VerticalSpace:177 return nullptr;178 179 case CodeCompletionString::CK_Optional:180 // Note: treated as an empty text block.181 return (*CCStr)[chunk_number].Optional;182 }183 184 llvm_unreachable("Invalid CompletionKind!");185}186 187unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {188 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;189 return CCStr? CCStr->size() : 0;190}191 192unsigned clang_getCompletionPriority(CXCompletionString completion_string) {193 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;194 return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely);195}196 197enum CXAvailabilityKind 198clang_getCompletionAvailability(CXCompletionString completion_string) {199 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;200 return CCStr? static_cast<CXAvailabilityKind>(CCStr->getAvailability())201 : CXAvailability_Available;202}203 204unsigned clang_getCompletionNumAnnotations(CXCompletionString completion_string)205{206 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;207 return CCStr ? CCStr->getAnnotationCount() : 0;208}209 210CXString clang_getCompletionAnnotation(CXCompletionString completion_string,211 unsigned annotation_number) {212 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;213 return CCStr ? cxstring::createRef(CCStr->getAnnotation(annotation_number))214 : cxstring::createNull();215}216 217CXString218clang_getCompletionParent(CXCompletionString completion_string,219 CXCursorKind *kind) {220 if (kind)221 *kind = CXCursor_NotImplemented;222 223 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;224 if (!CCStr)225 return cxstring::createNull();226 227 return cxstring::createRef(CCStr->getParentContextName());228}229 230CXString231clang_getCompletionBriefComment(CXCompletionString completion_string) {232 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;233 234 if (!CCStr)235 return cxstring::createNull();236 237 return cxstring::createRef(CCStr->getBriefComment());238}239 240namespace {241 242/// The CXCodeCompleteResults structure we allocate internally;243/// the client only sees the initial CXCodeCompleteResults structure.244///245/// Normally, clients of CXString shouldn't care whether or not a CXString is246/// managed by a pool or by explicitly malloc'ed memory. But247/// AllocatedCXCodeCompleteResults outlives the CXTranslationUnit, so we can248/// not rely on the StringPool in the TU.249struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {250 AllocatedCXCodeCompleteResults(IntrusiveRefCntPtr<FileManager> FileMgr);251 ~AllocatedCXCodeCompleteResults();252 253 /// Diagnostics produced while performing code completion.254 SmallVector<StoredDiagnostic, 8> Diagnostics;255 256 /// Allocated API-exposed wrappters for Diagnostics.257 SmallVector<std::unique_ptr<CXStoredDiagnostic>, 8> DiagnosticsWrappers;258 259 DiagnosticOptions DiagOpts;260 261 /// Diag object262 IntrusiveRefCntPtr<DiagnosticsEngine> Diag;263 264 /// Language options used to adjust source locations.265 LangOptions LangOpts;266 267 /// File manager, used for diagnostics.268 IntrusiveRefCntPtr<FileManager> FileMgr;269 270 /// Source manager, used for diagnostics.271 IntrusiveRefCntPtr<SourceManager> SourceMgr;272 273 /// Temporary buffers that will be deleted once we have finished with274 /// the code-completion results.275 SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers;276 277 /// Allocator used to store globally cached code-completion results.278 std::shared_ptr<clang::GlobalCodeCompletionAllocator>279 CachedCompletionAllocator;280 281 /// Allocator used to store code completion results.282 std::shared_ptr<clang::GlobalCodeCompletionAllocator> CodeCompletionAllocator;283 284 /// Context under which completion occurred.285 enum clang::CodeCompletionContext::Kind ContextKind;286 287 /// A bitfield representing the acceptable completions for the288 /// current context.289 unsigned long long Contexts;290 291 /// The kind of the container for the current context for completions.292 enum CXCursorKind ContainerKind;293 294 /// The USR of the container for the current context for completions.295 std::string ContainerUSR;296 297 /// a boolean value indicating whether there is complete information298 /// about the container299 unsigned ContainerIsIncomplete;300 301 /// A string containing the Objective-C selector entered thus far for a302 /// message send.303 std::string Selector;304 305 /// Vector of fix-its for each completion result that *must* be applied306 /// before that result for the corresponding completion item.307 std::vector<std::vector<FixItHint>> FixItsVector;308};309 310} // end anonymous namespace311 312unsigned clang_getCompletionNumFixIts(CXCodeCompleteResults *results,313 unsigned completion_index) {314 AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results;315 316 if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index)317 return 0;318 319 return static_cast<unsigned>(allocated_results->FixItsVector[completion_index].size());320}321 322CXString clang_getCompletionFixIt(CXCodeCompleteResults *results,323 unsigned completion_index,324 unsigned fixit_index,325 CXSourceRange *replacement_range) {326 AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results;327 328 if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index) {329 if (replacement_range)330 *replacement_range = clang_getNullRange();331 return cxstring::createNull();332 }333 334 ArrayRef<FixItHint> FixIts = allocated_results->FixItsVector[completion_index];335 if (FixIts.size() <= fixit_index) {336 if (replacement_range)337 *replacement_range = clang_getNullRange();338 return cxstring::createNull();339 }340 341 const FixItHint &FixIt = FixIts[fixit_index];342 if (replacement_range) {343 *replacement_range = cxloc::translateSourceRange(344 *allocated_results->SourceMgr, allocated_results->LangOpts,345 FixIt.RemoveRange);346 }347 348 return cxstring::createRef(FixIt.CodeToInsert.c_str());349}350 351/// Tracks the number of code-completion result objects that are 352/// currently active.353///354/// Used for debugging purposes only.355static std::atomic<unsigned> CodeCompletionResultObjects;356 357AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults(358 IntrusiveRefCntPtr<FileManager> FileMgr)359 : CXCodeCompleteResults(),360 Diag(llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(DiagnosticIDs::create(),361 DiagOpts)),362 FileMgr(std::move(FileMgr)),363 SourceMgr(364 llvm::makeIntrusiveRefCnt<SourceManager>(*Diag, *this->FileMgr)),365 CodeCompletionAllocator(366 std::make_shared<clang::GlobalCodeCompletionAllocator>()),367 Contexts(CXCompletionContext_Unknown),368 ContainerKind(CXCursor_InvalidCode), ContainerIsIncomplete(1) {369 if (getenv("LIBCLANG_OBJTRACKING"))370 fprintf(stderr, "+++ %u completion results\n",371 ++CodeCompletionResultObjects);372}373 374AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {375 delete [] Results;376 377 for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I)378 delete TemporaryBuffers[I];379 380 if (getenv("LIBCLANG_OBJTRACKING"))381 fprintf(stderr, "--- %u completion results\n",382 --CodeCompletionResultObjects);383}384 385static unsigned long long getContextsForContextKind(386 enum CodeCompletionContext::Kind kind, 387 Sema &S) {388 unsigned long long contexts = 0;389 switch (kind) {390 case CodeCompletionContext::CCC_OtherWithMacros: {391 //We can allow macros here, but we don't know what else is permissible392 //So we'll say the only thing permissible are macros393 contexts = CXCompletionContext_MacroName;394 break;395 }396 case CodeCompletionContext::CCC_TopLevel:397 case CodeCompletionContext::CCC_ObjCIvarList:398 case CodeCompletionContext::CCC_ClassStructUnion:399 case CodeCompletionContext::CCC_Type: {400 contexts = CXCompletionContext_AnyType | 401 CXCompletionContext_ObjCInterface;402 if (S.getLangOpts().CPlusPlus) {403 contexts |= CXCompletionContext_EnumTag |404 CXCompletionContext_UnionTag |405 CXCompletionContext_StructTag |406 CXCompletionContext_ClassTag |407 CXCompletionContext_NestedNameSpecifier;408 }409 break;410 }411 case CodeCompletionContext::CCC_Statement: {412 contexts = CXCompletionContext_AnyType |413 CXCompletionContext_ObjCInterface |414 CXCompletionContext_AnyValue;415 if (S.getLangOpts().CPlusPlus) {416 contexts |= CXCompletionContext_EnumTag |417 CXCompletionContext_UnionTag |418 CXCompletionContext_StructTag |419 CXCompletionContext_ClassTag |420 CXCompletionContext_NestedNameSpecifier;421 }422 break;423 }424 case CodeCompletionContext::CCC_Expression: {425 contexts = CXCompletionContext_AnyValue;426 if (S.getLangOpts().CPlusPlus) {427 contexts |= CXCompletionContext_AnyType |428 CXCompletionContext_ObjCInterface |429 CXCompletionContext_EnumTag |430 CXCompletionContext_UnionTag |431 CXCompletionContext_StructTag |432 CXCompletionContext_ClassTag |433 CXCompletionContext_NestedNameSpecifier;434 }435 break;436 }437 case CodeCompletionContext::CCC_ObjCMessageReceiver: {438 contexts = CXCompletionContext_ObjCObjectValue |439 CXCompletionContext_ObjCSelectorValue |440 CXCompletionContext_ObjCInterface;441 if (S.getLangOpts().CPlusPlus) {442 contexts |= CXCompletionContext_CXXClassTypeValue |443 CXCompletionContext_AnyType |444 CXCompletionContext_EnumTag |445 CXCompletionContext_UnionTag |446 CXCompletionContext_StructTag |447 CXCompletionContext_ClassTag |448 CXCompletionContext_NestedNameSpecifier;449 }450 break;451 }452 case CodeCompletionContext::CCC_DotMemberAccess: {453 contexts = CXCompletionContext_DotMemberAccess;454 break;455 }456 case CodeCompletionContext::CCC_ArrowMemberAccess: {457 contexts = CXCompletionContext_ArrowMemberAccess;458 break;459 }460 case CodeCompletionContext::CCC_ObjCPropertyAccess: {461 contexts = CXCompletionContext_ObjCPropertyAccess;462 break;463 }464 case CodeCompletionContext::CCC_EnumTag: {465 contexts = CXCompletionContext_EnumTag |466 CXCompletionContext_NestedNameSpecifier;467 break;468 }469 case CodeCompletionContext::CCC_UnionTag: {470 contexts = CXCompletionContext_UnionTag |471 CXCompletionContext_NestedNameSpecifier;472 break;473 }474 case CodeCompletionContext::CCC_ClassOrStructTag: {475 contexts = CXCompletionContext_StructTag |476 CXCompletionContext_ClassTag |477 CXCompletionContext_NestedNameSpecifier;478 break;479 }480 case CodeCompletionContext::CCC_ObjCProtocolName: {481 contexts = CXCompletionContext_ObjCProtocol;482 break;483 }484 case CodeCompletionContext::CCC_Namespace: {485 contexts = CXCompletionContext_Namespace;486 break;487 }488 case CodeCompletionContext::CCC_SymbolOrNewName:489 case CodeCompletionContext::CCC_Symbol: {490 contexts = CXCompletionContext_NestedNameSpecifier;491 break;492 }493 case CodeCompletionContext::CCC_MacroNameUse: {494 contexts = CXCompletionContext_MacroName;495 break;496 }497 case CodeCompletionContext::CCC_NaturalLanguage: {498 contexts = CXCompletionContext_NaturalLanguage;499 break;500 }501 case CodeCompletionContext::CCC_IncludedFile: {502 contexts = CXCompletionContext_IncludedFile;503 break;504 }505 case CodeCompletionContext::CCC_SelectorName: {506 contexts = CXCompletionContext_ObjCSelectorName;507 break;508 }509 case CodeCompletionContext::CCC_ParenthesizedExpression: {510 contexts = CXCompletionContext_AnyType |511 CXCompletionContext_ObjCInterface |512 CXCompletionContext_AnyValue;513 if (S.getLangOpts().CPlusPlus) {514 contexts |= CXCompletionContext_EnumTag |515 CXCompletionContext_UnionTag |516 CXCompletionContext_StructTag |517 CXCompletionContext_ClassTag |518 CXCompletionContext_NestedNameSpecifier;519 }520 break;521 }522 case CodeCompletionContext::CCC_ObjCInstanceMessage: {523 contexts = CXCompletionContext_ObjCInstanceMessage;524 break;525 }526 case CodeCompletionContext::CCC_ObjCClassMessage: {527 contexts = CXCompletionContext_ObjCClassMessage;528 break;529 }530 case CodeCompletionContext::CCC_ObjCInterfaceName: {531 contexts = CXCompletionContext_ObjCInterface;532 break;533 }534 case CodeCompletionContext::CCC_ObjCCategoryName: {535 contexts = CXCompletionContext_ObjCCategory;536 break;537 }538 case CodeCompletionContext::CCC_Other:539 case CodeCompletionContext::CCC_ObjCInterface:540 case CodeCompletionContext::CCC_ObjCImplementation:541 case CodeCompletionContext::CCC_ObjCClassForwardDecl:542 case CodeCompletionContext::CCC_NewName:543 case CodeCompletionContext::CCC_MacroName:544 case CodeCompletionContext::CCC_PreprocessorExpression:545 case CodeCompletionContext::CCC_PreprocessorDirective:546 case CodeCompletionContext::CCC_Attribute:547 case CodeCompletionContext::CCC_TopLevelOrExpression:548 case CodeCompletionContext::CCC_TypeQualifiers: {549 //Only Clang results should be accepted, so we'll set all of the other550 //context bits to 0 (i.e. the empty set)551 contexts = CXCompletionContext_Unexposed;552 break;553 }554 case CodeCompletionContext::CCC_Recovery: {555 //We don't know what the current context is, so we'll return unknown556 //This is the equivalent of setting all of the other context bits557 contexts = CXCompletionContext_Unknown;558 break;559 }560 }561 return contexts;562}563 564namespace {565 class CaptureCompletionResults : public CodeCompleteConsumer {566 AllocatedCXCodeCompleteResults &AllocatedResults;567 CodeCompletionTUInfo CCTUInfo;568 SmallVector<CXCompletionResult, 16> StoredResults;569 CXTranslationUnit *TU;570 public:571 CaptureCompletionResults(const CodeCompleteOptions &Opts,572 AllocatedCXCodeCompleteResults &Results,573 CXTranslationUnit *TranslationUnit)574 : CodeCompleteConsumer(Opts), AllocatedResults(Results),575 CCTUInfo(Results.CodeCompletionAllocator), TU(TranslationUnit) {}576 ~CaptureCompletionResults() override { Finish(); }577 578 void ProcessCodeCompleteResults(Sema &S, 579 CodeCompletionContext Context,580 CodeCompletionResult *Results,581 unsigned NumResults) override {582 StoredResults.reserve(StoredResults.size() + NumResults);583 if (includeFixIts())584 AllocatedResults.FixItsVector.reserve(NumResults);585 for (unsigned I = 0; I != NumResults; ++I) {586 CodeCompletionString *StoredCompletion587 = Results[I].CreateCodeCompletionString(S, Context, getAllocator(),588 getCodeCompletionTUInfo(),589 includeBriefComments());590 591 CXCompletionResult R;592 R.CursorKind = Results[I].CursorKind;593 R.CompletionString = StoredCompletion;594 StoredResults.push_back(R);595 if (includeFixIts())596 AllocatedResults.FixItsVector.emplace_back(std::move(Results[I].FixIts));597 }598 599 enum CodeCompletionContext::Kind contextKind = Context.getKind();600 601 AllocatedResults.ContextKind = contextKind;602 AllocatedResults.Contexts = getContextsForContextKind(contextKind, S);603 604 AllocatedResults.Selector = "";605 ArrayRef<const IdentifierInfo *> SelIdents = Context.getSelIdents();606 for (ArrayRef<const IdentifierInfo *>::iterator I = SelIdents.begin(),607 E = SelIdents.end();608 I != E; ++I) {609 if (const IdentifierInfo *selIdent = *I)610 AllocatedResults.Selector += selIdent->getName();611 AllocatedResults.Selector += ":";612 }613 614 QualType baseType = Context.getBaseType();615 NamedDecl *D = nullptr;616 617 if (!baseType.isNull()) {618 // Get the declaration for a class/struct/union/enum type619 if (const TagType *Tag = baseType->getAs<TagType>())620 D = Tag->getDecl();621 // Get the @interface declaration for a (possibly-qualified) Objective-C622 // object pointer type, e.g., NSString*623 else if (const ObjCObjectPointerType *ObjPtr = 624 baseType->getAs<ObjCObjectPointerType>())625 D = ObjPtr->getInterfaceDecl();626 // Get the @interface declaration for an Objective-C object type627 else if (const ObjCObjectType *Obj = baseType->getAs<ObjCObjectType>())628 D = Obj->getInterface();629 // Get the class for a C++ injected-class-name630 else if (const InjectedClassNameType *Injected =631 baseType->getAs<InjectedClassNameType>())632 D = Injected->getDecl();633 }634 635 if (D != nullptr) {636 CXCursor cursor = cxcursor::MakeCXCursor(D, *TU);637 638 AllocatedResults.ContainerKind = clang_getCursorKind(cursor);639 640 CXString CursorUSR = clang_getCursorUSR(cursor);641 AllocatedResults.ContainerUSR = clang_getCString(CursorUSR);642 clang_disposeString(CursorUSR);643 644 const Type *type = baseType.getTypePtrOrNull();645 if (type) {646 AllocatedResults.ContainerIsIncomplete = type->isIncompleteType();647 }648 else {649 AllocatedResults.ContainerIsIncomplete = 1;650 }651 }652 else {653 AllocatedResults.ContainerKind = CXCursor_InvalidCode;654 AllocatedResults.ContainerUSR.clear();655 AllocatedResults.ContainerIsIncomplete = 1;656 }657 }658 659 void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,660 OverloadCandidate *Candidates,661 unsigned NumCandidates,662 SourceLocation OpenParLoc,663 bool Braced) override {664 StoredResults.reserve(StoredResults.size() + NumCandidates);665 for (unsigned I = 0; I != NumCandidates; ++I) {666 CodeCompletionString *StoredCompletion =667 Candidates[I].CreateSignatureString(CurrentArg, S, getAllocator(),668 getCodeCompletionTUInfo(),669 includeBriefComments(), Braced);670 671 CXCompletionResult R;672 R.CursorKind = CXCursor_OverloadCandidate;673 R.CompletionString = StoredCompletion;674 StoredResults.push_back(R);675 }676 }677 678 CodeCompletionAllocator &getAllocator() override {679 return *AllocatedResults.CodeCompletionAllocator;680 }681 682 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo;}683 684 private:685 void Finish() {686 AllocatedResults.Results = new CXCompletionResult [StoredResults.size()];687 AllocatedResults.NumResults = StoredResults.size();688 std::memcpy(AllocatedResults.Results, StoredResults.data(), 689 StoredResults.size() * sizeof(CXCompletionResult));690 StoredResults.clear();691 }692 };693}694 695static CXCodeCompleteResults *696clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename,697 unsigned complete_line, unsigned complete_column,698 ArrayRef<CXUnsavedFile> unsaved_files,699 unsigned options) {700 bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments;701 bool SkipPreamble = options & CXCodeComplete_SkipPreamble;702 bool IncludeFixIts = options & CXCodeComplete_IncludeCompletionsWithFixIts;703 704#ifdef UDP_CODE_COMPLETION_LOGGER705#ifdef UDP_CODE_COMPLETION_LOGGER_PORT706 const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();707#endif708#endif709 bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr;710 711 if (cxtu::isNotUsableTU(TU)) {712 LOG_BAD_TU(TU);713 return nullptr;714 }715 716 ASTUnit *AST = cxtu::getASTUnit(TU);717 if (!AST)718 return nullptr;719 720 CIndexer *CXXIdx = TU->CIdx;721 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))722 setThreadBackgroundPriority();723 724 ASTUnit::ConcurrencyCheck Check(*AST);725 726 // Perform the remapping of source files.727 SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;728 729 for (auto &UF : unsaved_files) {730 std::unique_ptr<llvm::MemoryBuffer> MB =731 llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);732 RemappedFiles.push_back(std::make_pair(UF.Filename, MB.release()));733 }734 735 if (EnableLogging) {736 // FIXME: Add logging.737 }738 739 // Parse the resulting source file to find code-completion results.740 AllocatedCXCodeCompleteResults *Results =741 new AllocatedCXCodeCompleteResults(AST->getFileManagerPtr());742 Results->Results = nullptr;743 Results->NumResults = 0;744 745 // Create a code-completion consumer to capture the results.746 CodeCompleteOptions Opts;747 Opts.IncludeBriefComments = IncludeBriefComments;748 Opts.LoadExternal = !SkipPreamble;749 Opts.IncludeFixIts = IncludeFixIts;750 CaptureCompletionResults Capture(Opts, *Results, &TU);751 752 // Perform completion.753 std::vector<const char *> CArgs;754 for (const auto &Arg : TU->Arguments)755 CArgs.push_back(Arg.c_str());756 std::string CompletionInvocation =757 llvm::formatv("-code-completion-at={0}:{1}:{2}", complete_filename,758 complete_line, complete_column)759 .str();760 LibclangInvocationReporter InvocationReporter(761 *CXXIdx, LibclangInvocationReporter::OperationKind::CompletionOperation,762 TU->ParsingOptions, CArgs, CompletionInvocation, unsaved_files);763 AST->CodeComplete(complete_filename, complete_line, complete_column,764 RemappedFiles, (options & CXCodeComplete_IncludeMacros),765 (options & CXCodeComplete_IncludeCodePatterns),766 IncludeBriefComments, Capture,767 CXXIdx->getPCHContainerOperations(), Results->Diag,768 Results->LangOpts, Results->SourceMgr, Results->FileMgr,769 Results->Diagnostics, Results->TemporaryBuffers,770 /*SyntaxOnlyAction=*/nullptr);771 772 Results->DiagnosticsWrappers.resize(Results->Diagnostics.size());773 774 // Keep a reference to the allocator used for cached global completions, so775 // that we can be sure that the memory used by our code completion strings776 // doesn't get freed due to subsequent reparses (while the code completion777 // results are still active).778 Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator();779 780 781 782#ifdef UDP_CODE_COMPLETION_LOGGER783#ifdef UDP_CODE_COMPLETION_LOGGER_PORT784 const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();785 SmallString<256> LogResult;786 llvm::raw_svector_ostream os(LogResult);787 788 // Figure out the language and whether or not it uses PCH.789 const char *lang = 0;790 bool usesPCH = false;791 792 for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();793 I != E; ++I) {794 if (*I == 0)795 continue;796 if (strcmp(*I, "-x") == 0) {797 if (I + 1 != E) {798 lang = *(++I);799 continue;800 }801 }802 else if (strcmp(*I, "-include") == 0) {803 if (I+1 != E) {804 const char *arg = *(++I);805 SmallString<512> pchName;806 {807 llvm::raw_svector_ostream os(pchName);808 os << arg << ".pth";809 }810 pchName.push_back('\0');811 llvm::sys::fs::file_status stat_results;812 if (!llvm::sys::fs::status(pchName, stat_results))813 usesPCH = true;814 continue;815 }816 }817 }818 819 os << "{ ";820 os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());821 os << ", \"numRes\": " << Results->NumResults;822 os << ", \"diags\": " << Results->Diagnostics.size();823 os << ", \"pch\": " << (usesPCH ? "true" : "false");824 os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';825 const char *name = getlogin();826 os << ", \"user\": \"" << (name ? name : "unknown") << '"';827 os << ", \"clangVer\": \"" << getClangFullVersion() << '"';828 os << " }";829 830 StringRef res = os.str();831 if (res.size() > 0) {832 do {833 // Setup the UDP socket.834 struct sockaddr_in servaddr;835 bzero(&servaddr, sizeof(servaddr));836 servaddr.sin_family = AF_INET;837 servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);838 if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,839 &servaddr.sin_addr) <= 0)840 break;841 842 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);843 if (sockfd < 0)844 break;845 846 sendto(sockfd, res.data(), res.size(), 0,847 (struct sockaddr *)&servaddr, sizeof(servaddr));848 close(sockfd);849 }850 while (false);851 }852#endif853#endif854 return Results;855}856 857CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,858 const char *complete_filename,859 unsigned complete_line,860 unsigned complete_column,861 struct CXUnsavedFile *unsaved_files,862 unsigned num_unsaved_files,863 unsigned options) {864 LOG_FUNC_SECTION {865 *Log << TU << ' '866 << complete_filename << ':' << complete_line << ':' << complete_column;867 }868 869 if (num_unsaved_files && !unsaved_files)870 return nullptr;871 872 CXCodeCompleteResults *result;873 auto CodeCompleteAtImpl = [=, &result]() {874 result = clang_codeCompleteAt_Impl(875 TU, complete_filename, complete_line, complete_column,876 llvm::ArrayRef(unsaved_files, num_unsaved_files), options);877 };878 879 llvm::CrashRecoveryContext CRC;880 881 if (!RunSafely(CRC, CodeCompleteAtImpl)) {882 fprintf(stderr, "libclang: crash detected in code completion\n");883 cxtu::getASTUnit(TU)->setUnsafeToFree(true);884 return nullptr;885 } else if (getenv("LIBCLANG_RESOURCE_USAGE"))886 PrintLibclangResourceUsage(TU);887 888 return result;889}890 891unsigned clang_defaultCodeCompleteOptions(void) {892 return CXCodeComplete_IncludeMacros;893}894 895void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {896 if (!ResultsIn)897 return;898 899 AllocatedCXCodeCompleteResults *Results900 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);901 delete Results;902}903 904unsigned 905clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {906 AllocatedCXCodeCompleteResults *Results907 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);908 if (!Results)909 return 0;910 911 return Results->Diagnostics.size();912}913 914CXDiagnostic 915clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,916 unsigned Index) {917 AllocatedCXCodeCompleteResults *Results918 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);919 if (!Results || Index >= Results->Diagnostics.size())920 return nullptr;921 922 CXStoredDiagnostic *Diag = Results->DiagnosticsWrappers[Index].get();923 if (!Diag)924 Diag = (Results->DiagnosticsWrappers[Index] =925 std::make_unique<CXStoredDiagnostic>(926 Results->Diagnostics[Index], Results->LangOpts))927 .get();928 return Diag;929}930 931unsigned long long932clang_codeCompleteGetContexts(CXCodeCompleteResults *ResultsIn) {933 AllocatedCXCodeCompleteResults *Results934 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);935 if (!Results)936 return 0;937 938 return Results->Contexts;939}940 941enum CXCursorKind clang_codeCompleteGetContainerKind(942 CXCodeCompleteResults *ResultsIn,943 unsigned *IsIncomplete) {944 AllocatedCXCodeCompleteResults *Results =945 static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);946 if (!Results)947 return CXCursor_InvalidCode;948 949 if (IsIncomplete != nullptr) {950 *IsIncomplete = Results->ContainerIsIncomplete;951 }952 953 return Results->ContainerKind;954}955 956CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *ResultsIn) {957 AllocatedCXCodeCompleteResults *Results =958 static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);959 if (!Results)960 return cxstring::createEmpty();961 962 return cxstring::createRef(Results->ContainerUSR.c_str());963}964 965 966CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *ResultsIn) {967 AllocatedCXCodeCompleteResults *Results =968 static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);969 if (!Results)970 return cxstring::createEmpty();971 972 return cxstring::createDup(Results->Selector);973}974 975/// Simple utility function that appends a \p New string to the given976/// \p Old string, using the \p Buffer for storage.977///978/// \param Old The string to which we are appending. This parameter will be979/// updated to reflect the complete string.980///981///982/// \param New The string to append to \p Old.983///984/// \param Buffer A buffer that stores the actual, concatenated string. It will985/// be used if the old string is already-non-empty.986static void AppendToString(StringRef &Old, StringRef New,987 SmallString<256> &Buffer) {988 if (Old.empty()) {989 Old = New;990 return;991 }992 993 if (Buffer.empty())994 Buffer.append(Old.begin(), Old.end());995 Buffer.append(New.begin(), New.end());996 Old = Buffer.str();997}998 999/// Get the typed-text blocks from the given code-completion string1000/// and return them as a single string.1001///1002/// \param String The code-completion string whose typed-text blocks will be1003/// concatenated.1004///1005/// \param Buffer A buffer used for storage of the completed name.1006static StringRef GetTypedName(CodeCompletionString *String,1007 SmallString<256> &Buffer) {1008 StringRef Result;1009 for (CodeCompletionString::iterator C = String->begin(), CEnd = String->end();1010 C != CEnd; ++C) {1011 if (C->Kind == CodeCompletionString::CK_TypedText)1012 AppendToString(Result, C->Text, Buffer);1013 }1014 1015 return Result;1016}1017 1018namespace {1019 struct OrderCompletionResults {1020 bool operator()(const CXCompletionResult &XR, 1021 const CXCompletionResult &YR) const {1022 CodeCompletionString *X1023 = (CodeCompletionString *)XR.CompletionString;1024 CodeCompletionString *Y1025 = (CodeCompletionString *)YR.CompletionString;1026 1027 SmallString<256> XBuffer;1028 StringRef XText = GetTypedName(X, XBuffer);1029 SmallString<256> YBuffer;1030 StringRef YText = GetTypedName(Y, YBuffer);1031 1032 if (XText.empty() || YText.empty())1033 return !XText.empty();1034 1035 int result = XText.compare_insensitive(YText);1036 if (result < 0)1037 return true;1038 if (result > 0)1039 return false;1040 1041 result = XText.compare(YText);1042 return result < 0;1043 }1044 };1045}1046 1047void clang_sortCodeCompletionResults(CXCompletionResult *Results,1048 unsigned NumResults) {1049 std::stable_sort(Results, Results + NumResults, OrderCompletionResults());1050}1051