17330f729Sjoerg //===- CIndexCodeCompletion.cpp - Code Completion API hooks ---------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file implements the Clang-C Source Indexing library hooks for
107330f729Sjoerg // code completion.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg
147330f729Sjoerg #include "CIndexer.h"
157330f729Sjoerg #include "CIndexDiagnostic.h"
167330f729Sjoerg #include "CLog.h"
177330f729Sjoerg #include "CXCursor.h"
187330f729Sjoerg #include "CXSourceLocation.h"
197330f729Sjoerg #include "CXString.h"
207330f729Sjoerg #include "CXTranslationUnit.h"
217330f729Sjoerg #include "clang/AST/Decl.h"
227330f729Sjoerg #include "clang/AST/DeclObjC.h"
237330f729Sjoerg #include "clang/AST/Type.h"
247330f729Sjoerg #include "clang/Basic/FileManager.h"
257330f729Sjoerg #include "clang/Basic/SourceManager.h"
267330f729Sjoerg #include "clang/Frontend/ASTUnit.h"
277330f729Sjoerg #include "clang/Frontend/CompilerInstance.h"
287330f729Sjoerg #include "clang/Sema/CodeCompleteConsumer.h"
297330f729Sjoerg #include "clang/Sema/Sema.h"
307330f729Sjoerg #include "llvm/ADT/SmallString.h"
317330f729Sjoerg #include "llvm/ADT/StringExtras.h"
327330f729Sjoerg #include "llvm/Support/CrashRecoveryContext.h"
337330f729Sjoerg #include "llvm/Support/FileSystem.h"
347330f729Sjoerg #include "llvm/Support/FormatVariadic.h"
357330f729Sjoerg #include "llvm/Support/MemoryBuffer.h"
367330f729Sjoerg #include "llvm/Support/Program.h"
377330f729Sjoerg #include "llvm/Support/Timer.h"
387330f729Sjoerg #include "llvm/Support/raw_ostream.h"
397330f729Sjoerg #include <atomic>
407330f729Sjoerg #include <cstdio>
417330f729Sjoerg #include <cstdlib>
427330f729Sjoerg #include <string>
437330f729Sjoerg
447330f729Sjoerg
457330f729Sjoerg #ifdef UDP_CODE_COMPLETION_LOGGER
467330f729Sjoerg #include "clang/Basic/Version.h"
477330f729Sjoerg #include <arpa/inet.h>
487330f729Sjoerg #include <sys/socket.h>
497330f729Sjoerg #include <sys/types.h>
507330f729Sjoerg #include <unistd.h>
517330f729Sjoerg #endif
527330f729Sjoerg
537330f729Sjoerg using namespace clang;
547330f729Sjoerg using namespace clang::cxindex;
557330f729Sjoerg
567330f729Sjoerg enum CXCompletionChunkKind
clang_getCompletionChunkKind(CXCompletionString completion_string,unsigned chunk_number)577330f729Sjoerg clang_getCompletionChunkKind(CXCompletionString completion_string,
587330f729Sjoerg unsigned chunk_number) {
597330f729Sjoerg CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
607330f729Sjoerg if (!CCStr || chunk_number >= CCStr->size())
617330f729Sjoerg return CXCompletionChunk_Text;
627330f729Sjoerg
637330f729Sjoerg switch ((*CCStr)[chunk_number].Kind) {
647330f729Sjoerg case CodeCompletionString::CK_TypedText:
657330f729Sjoerg return CXCompletionChunk_TypedText;
667330f729Sjoerg case CodeCompletionString::CK_Text:
677330f729Sjoerg return CXCompletionChunk_Text;
687330f729Sjoerg case CodeCompletionString::CK_Optional:
697330f729Sjoerg return CXCompletionChunk_Optional;
707330f729Sjoerg case CodeCompletionString::CK_Placeholder:
717330f729Sjoerg return CXCompletionChunk_Placeholder;
727330f729Sjoerg case CodeCompletionString::CK_Informative:
737330f729Sjoerg return CXCompletionChunk_Informative;
747330f729Sjoerg case CodeCompletionString::CK_ResultType:
757330f729Sjoerg return CXCompletionChunk_ResultType;
767330f729Sjoerg case CodeCompletionString::CK_CurrentParameter:
777330f729Sjoerg return CXCompletionChunk_CurrentParameter;
787330f729Sjoerg case CodeCompletionString::CK_LeftParen:
797330f729Sjoerg return CXCompletionChunk_LeftParen;
807330f729Sjoerg case CodeCompletionString::CK_RightParen:
817330f729Sjoerg return CXCompletionChunk_RightParen;
827330f729Sjoerg case CodeCompletionString::CK_LeftBracket:
837330f729Sjoerg return CXCompletionChunk_LeftBracket;
847330f729Sjoerg case CodeCompletionString::CK_RightBracket:
857330f729Sjoerg return CXCompletionChunk_RightBracket;
867330f729Sjoerg case CodeCompletionString::CK_LeftBrace:
877330f729Sjoerg return CXCompletionChunk_LeftBrace;
887330f729Sjoerg case CodeCompletionString::CK_RightBrace:
897330f729Sjoerg return CXCompletionChunk_RightBrace;
907330f729Sjoerg case CodeCompletionString::CK_LeftAngle:
917330f729Sjoerg return CXCompletionChunk_LeftAngle;
927330f729Sjoerg case CodeCompletionString::CK_RightAngle:
937330f729Sjoerg return CXCompletionChunk_RightAngle;
947330f729Sjoerg case CodeCompletionString::CK_Comma:
957330f729Sjoerg return CXCompletionChunk_Comma;
967330f729Sjoerg case CodeCompletionString::CK_Colon:
977330f729Sjoerg return CXCompletionChunk_Colon;
987330f729Sjoerg case CodeCompletionString::CK_SemiColon:
997330f729Sjoerg return CXCompletionChunk_SemiColon;
1007330f729Sjoerg case CodeCompletionString::CK_Equal:
1017330f729Sjoerg return CXCompletionChunk_Equal;
1027330f729Sjoerg case CodeCompletionString::CK_HorizontalSpace:
1037330f729Sjoerg return CXCompletionChunk_HorizontalSpace;
1047330f729Sjoerg case CodeCompletionString::CK_VerticalSpace:
1057330f729Sjoerg return CXCompletionChunk_VerticalSpace;
1067330f729Sjoerg }
1077330f729Sjoerg
1087330f729Sjoerg llvm_unreachable("Invalid CompletionKind!");
1097330f729Sjoerg }
1107330f729Sjoerg
clang_getCompletionChunkText(CXCompletionString completion_string,unsigned chunk_number)1117330f729Sjoerg CXString clang_getCompletionChunkText(CXCompletionString completion_string,
1127330f729Sjoerg unsigned chunk_number) {
1137330f729Sjoerg CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
1147330f729Sjoerg if (!CCStr || chunk_number >= CCStr->size())
1157330f729Sjoerg return cxstring::createNull();
1167330f729Sjoerg
1177330f729Sjoerg switch ((*CCStr)[chunk_number].Kind) {
1187330f729Sjoerg case CodeCompletionString::CK_TypedText:
1197330f729Sjoerg case CodeCompletionString::CK_Text:
1207330f729Sjoerg case CodeCompletionString::CK_Placeholder:
1217330f729Sjoerg case CodeCompletionString::CK_CurrentParameter:
1227330f729Sjoerg case CodeCompletionString::CK_Informative:
1237330f729Sjoerg case CodeCompletionString::CK_LeftParen:
1247330f729Sjoerg case CodeCompletionString::CK_RightParen:
1257330f729Sjoerg case CodeCompletionString::CK_LeftBracket:
1267330f729Sjoerg case CodeCompletionString::CK_RightBracket:
1277330f729Sjoerg case CodeCompletionString::CK_LeftBrace:
1287330f729Sjoerg case CodeCompletionString::CK_RightBrace:
1297330f729Sjoerg case CodeCompletionString::CK_LeftAngle:
1307330f729Sjoerg case CodeCompletionString::CK_RightAngle:
1317330f729Sjoerg case CodeCompletionString::CK_Comma:
1327330f729Sjoerg case CodeCompletionString::CK_ResultType:
1337330f729Sjoerg case CodeCompletionString::CK_Colon:
1347330f729Sjoerg case CodeCompletionString::CK_SemiColon:
1357330f729Sjoerg case CodeCompletionString::CK_Equal:
1367330f729Sjoerg case CodeCompletionString::CK_HorizontalSpace:
1377330f729Sjoerg case CodeCompletionString::CK_VerticalSpace:
1387330f729Sjoerg return cxstring::createRef((*CCStr)[chunk_number].Text);
1397330f729Sjoerg
1407330f729Sjoerg case CodeCompletionString::CK_Optional:
1417330f729Sjoerg // Note: treated as an empty text block.
1427330f729Sjoerg return cxstring::createEmpty();
1437330f729Sjoerg }
1447330f729Sjoerg
1457330f729Sjoerg llvm_unreachable("Invalid CodeCompletionString Kind!");
1467330f729Sjoerg }
1477330f729Sjoerg
1487330f729Sjoerg
1497330f729Sjoerg CXCompletionString
clang_getCompletionChunkCompletionString(CXCompletionString completion_string,unsigned chunk_number)1507330f729Sjoerg clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
1517330f729Sjoerg unsigned chunk_number) {
1527330f729Sjoerg CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
1537330f729Sjoerg if (!CCStr || chunk_number >= CCStr->size())
1547330f729Sjoerg return nullptr;
1557330f729Sjoerg
1567330f729Sjoerg switch ((*CCStr)[chunk_number].Kind) {
1577330f729Sjoerg case CodeCompletionString::CK_TypedText:
1587330f729Sjoerg case CodeCompletionString::CK_Text:
1597330f729Sjoerg case CodeCompletionString::CK_Placeholder:
1607330f729Sjoerg case CodeCompletionString::CK_CurrentParameter:
1617330f729Sjoerg case CodeCompletionString::CK_Informative:
1627330f729Sjoerg case CodeCompletionString::CK_LeftParen:
1637330f729Sjoerg case CodeCompletionString::CK_RightParen:
1647330f729Sjoerg case CodeCompletionString::CK_LeftBracket:
1657330f729Sjoerg case CodeCompletionString::CK_RightBracket:
1667330f729Sjoerg case CodeCompletionString::CK_LeftBrace:
1677330f729Sjoerg case CodeCompletionString::CK_RightBrace:
1687330f729Sjoerg case CodeCompletionString::CK_LeftAngle:
1697330f729Sjoerg case CodeCompletionString::CK_RightAngle:
1707330f729Sjoerg case CodeCompletionString::CK_Comma:
1717330f729Sjoerg case CodeCompletionString::CK_ResultType:
1727330f729Sjoerg case CodeCompletionString::CK_Colon:
1737330f729Sjoerg case CodeCompletionString::CK_SemiColon:
1747330f729Sjoerg case CodeCompletionString::CK_Equal:
1757330f729Sjoerg case CodeCompletionString::CK_HorizontalSpace:
1767330f729Sjoerg case CodeCompletionString::CK_VerticalSpace:
1777330f729Sjoerg return nullptr;
1787330f729Sjoerg
1797330f729Sjoerg case CodeCompletionString::CK_Optional:
1807330f729Sjoerg // Note: treated as an empty text block.
1817330f729Sjoerg return (*CCStr)[chunk_number].Optional;
1827330f729Sjoerg }
1837330f729Sjoerg
1847330f729Sjoerg llvm_unreachable("Invalid CompletionKind!");
1857330f729Sjoerg }
1867330f729Sjoerg
clang_getNumCompletionChunks(CXCompletionString completion_string)1877330f729Sjoerg unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
1887330f729Sjoerg CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
1897330f729Sjoerg return CCStr? CCStr->size() : 0;
1907330f729Sjoerg }
1917330f729Sjoerg
clang_getCompletionPriority(CXCompletionString completion_string)1927330f729Sjoerg unsigned clang_getCompletionPriority(CXCompletionString completion_string) {
1937330f729Sjoerg CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
1947330f729Sjoerg return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely);
1957330f729Sjoerg }
1967330f729Sjoerg
1977330f729Sjoerg enum CXAvailabilityKind
clang_getCompletionAvailability(CXCompletionString completion_string)1987330f729Sjoerg clang_getCompletionAvailability(CXCompletionString completion_string) {
1997330f729Sjoerg CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
2007330f729Sjoerg return CCStr? static_cast<CXAvailabilityKind>(CCStr->getAvailability())
2017330f729Sjoerg : CXAvailability_Available;
2027330f729Sjoerg }
2037330f729Sjoerg
clang_getCompletionNumAnnotations(CXCompletionString completion_string)2047330f729Sjoerg unsigned clang_getCompletionNumAnnotations(CXCompletionString completion_string)
2057330f729Sjoerg {
2067330f729Sjoerg CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
2077330f729Sjoerg return CCStr ? CCStr->getAnnotationCount() : 0;
2087330f729Sjoerg }
2097330f729Sjoerg
clang_getCompletionAnnotation(CXCompletionString completion_string,unsigned annotation_number)2107330f729Sjoerg CXString clang_getCompletionAnnotation(CXCompletionString completion_string,
2117330f729Sjoerg unsigned annotation_number) {
2127330f729Sjoerg CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
2137330f729Sjoerg return CCStr ? cxstring::createRef(CCStr->getAnnotation(annotation_number))
2147330f729Sjoerg : cxstring::createNull();
2157330f729Sjoerg }
2167330f729Sjoerg
2177330f729Sjoerg CXString
clang_getCompletionParent(CXCompletionString completion_string,CXCursorKind * kind)2187330f729Sjoerg clang_getCompletionParent(CXCompletionString completion_string,
2197330f729Sjoerg CXCursorKind *kind) {
2207330f729Sjoerg if (kind)
2217330f729Sjoerg *kind = CXCursor_NotImplemented;
2227330f729Sjoerg
2237330f729Sjoerg CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
2247330f729Sjoerg if (!CCStr)
2257330f729Sjoerg return cxstring::createNull();
2267330f729Sjoerg
2277330f729Sjoerg return cxstring::createRef(CCStr->getParentContextName());
2287330f729Sjoerg }
2297330f729Sjoerg
2307330f729Sjoerg CXString
clang_getCompletionBriefComment(CXCompletionString completion_string)2317330f729Sjoerg clang_getCompletionBriefComment(CXCompletionString completion_string) {
2327330f729Sjoerg CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
2337330f729Sjoerg
2347330f729Sjoerg if (!CCStr)
2357330f729Sjoerg return cxstring::createNull();
2367330f729Sjoerg
2377330f729Sjoerg return cxstring::createRef(CCStr->getBriefComment());
2387330f729Sjoerg }
2397330f729Sjoerg
2407330f729Sjoerg namespace {
2417330f729Sjoerg
2427330f729Sjoerg /// The CXCodeCompleteResults structure we allocate internally;
2437330f729Sjoerg /// the client only sees the initial CXCodeCompleteResults structure.
2447330f729Sjoerg ///
2457330f729Sjoerg /// Normally, clients of CXString shouldn't care whether or not a CXString is
2467330f729Sjoerg /// managed by a pool or by explicitly malloc'ed memory. But
2477330f729Sjoerg /// AllocatedCXCodeCompleteResults outlives the CXTranslationUnit, so we can
2487330f729Sjoerg /// not rely on the StringPool in the TU.
2497330f729Sjoerg struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
2507330f729Sjoerg AllocatedCXCodeCompleteResults(IntrusiveRefCntPtr<FileManager> FileMgr);
2517330f729Sjoerg ~AllocatedCXCodeCompleteResults();
2527330f729Sjoerg
2537330f729Sjoerg /// Diagnostics produced while performing code completion.
2547330f729Sjoerg SmallVector<StoredDiagnostic, 8> Diagnostics;
2557330f729Sjoerg
2567330f729Sjoerg /// Allocated API-exposed wrappters for Diagnostics.
257*e038c9c4Sjoerg SmallVector<std::unique_ptr<CXStoredDiagnostic>, 8> DiagnosticsWrappers;
2587330f729Sjoerg
2597330f729Sjoerg IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
2607330f729Sjoerg
2617330f729Sjoerg /// Diag object
2627330f729Sjoerg IntrusiveRefCntPtr<DiagnosticsEngine> Diag;
2637330f729Sjoerg
2647330f729Sjoerg /// Language options used to adjust source locations.
2657330f729Sjoerg LangOptions LangOpts;
2667330f729Sjoerg
2677330f729Sjoerg /// File manager, used for diagnostics.
2687330f729Sjoerg IntrusiveRefCntPtr<FileManager> FileMgr;
2697330f729Sjoerg
2707330f729Sjoerg /// Source manager, used for diagnostics.
2717330f729Sjoerg IntrusiveRefCntPtr<SourceManager> SourceMgr;
2727330f729Sjoerg
2737330f729Sjoerg /// Temporary buffers that will be deleted once we have finished with
2747330f729Sjoerg /// the code-completion results.
2757330f729Sjoerg SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers;
2767330f729Sjoerg
2777330f729Sjoerg /// Allocator used to store globally cached code-completion results.
2787330f729Sjoerg std::shared_ptr<clang::GlobalCodeCompletionAllocator>
2797330f729Sjoerg CachedCompletionAllocator;
2807330f729Sjoerg
2817330f729Sjoerg /// Allocator used to store code completion results.
2827330f729Sjoerg std::shared_ptr<clang::GlobalCodeCompletionAllocator> CodeCompletionAllocator;
2837330f729Sjoerg
2847330f729Sjoerg /// Context under which completion occurred.
2857330f729Sjoerg enum clang::CodeCompletionContext::Kind ContextKind;
2867330f729Sjoerg
2877330f729Sjoerg /// A bitfield representing the acceptable completions for the
2887330f729Sjoerg /// current context.
2897330f729Sjoerg unsigned long long Contexts;
2907330f729Sjoerg
2917330f729Sjoerg /// The kind of the container for the current context for completions.
2927330f729Sjoerg enum CXCursorKind ContainerKind;
2937330f729Sjoerg
2947330f729Sjoerg /// The USR of the container for the current context for completions.
2957330f729Sjoerg std::string ContainerUSR;
2967330f729Sjoerg
2977330f729Sjoerg /// a boolean value indicating whether there is complete information
2987330f729Sjoerg /// about the container
2997330f729Sjoerg unsigned ContainerIsIncomplete;
3007330f729Sjoerg
3017330f729Sjoerg /// A string containing the Objective-C selector entered thus far for a
3027330f729Sjoerg /// message send.
3037330f729Sjoerg std::string Selector;
3047330f729Sjoerg
3057330f729Sjoerg /// Vector of fix-its for each completion result that *must* be applied
3067330f729Sjoerg /// before that result for the corresponding completion item.
3077330f729Sjoerg std::vector<std::vector<FixItHint>> FixItsVector;
3087330f729Sjoerg };
3097330f729Sjoerg
3107330f729Sjoerg } // end anonymous namespace
3117330f729Sjoerg
clang_getCompletionNumFixIts(CXCodeCompleteResults * results,unsigned completion_index)3127330f729Sjoerg unsigned clang_getCompletionNumFixIts(CXCodeCompleteResults *results,
3137330f729Sjoerg unsigned completion_index) {
3147330f729Sjoerg AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results;
3157330f729Sjoerg
3167330f729Sjoerg if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index)
3177330f729Sjoerg return 0;
3187330f729Sjoerg
3197330f729Sjoerg return static_cast<unsigned>(allocated_results->FixItsVector[completion_index].size());
3207330f729Sjoerg }
3217330f729Sjoerg
clang_getCompletionFixIt(CXCodeCompleteResults * results,unsigned completion_index,unsigned fixit_index,CXSourceRange * replacement_range)3227330f729Sjoerg CXString clang_getCompletionFixIt(CXCodeCompleteResults *results,
3237330f729Sjoerg unsigned completion_index,
3247330f729Sjoerg unsigned fixit_index,
3257330f729Sjoerg CXSourceRange *replacement_range) {
3267330f729Sjoerg AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results;
3277330f729Sjoerg
3287330f729Sjoerg if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index) {
3297330f729Sjoerg if (replacement_range)
3307330f729Sjoerg *replacement_range = clang_getNullRange();
3317330f729Sjoerg return cxstring::createNull();
3327330f729Sjoerg }
3337330f729Sjoerg
3347330f729Sjoerg ArrayRef<FixItHint> FixIts = allocated_results->FixItsVector[completion_index];
3357330f729Sjoerg if (FixIts.size() <= fixit_index) {
3367330f729Sjoerg if (replacement_range)
3377330f729Sjoerg *replacement_range = clang_getNullRange();
3387330f729Sjoerg return cxstring::createNull();
3397330f729Sjoerg }
3407330f729Sjoerg
3417330f729Sjoerg const FixItHint &FixIt = FixIts[fixit_index];
3427330f729Sjoerg if (replacement_range) {
3437330f729Sjoerg *replacement_range = cxloc::translateSourceRange(
3447330f729Sjoerg *allocated_results->SourceMgr, allocated_results->LangOpts,
3457330f729Sjoerg FixIt.RemoveRange);
3467330f729Sjoerg }
3477330f729Sjoerg
3487330f729Sjoerg return cxstring::createRef(FixIt.CodeToInsert.c_str());
3497330f729Sjoerg }
3507330f729Sjoerg
3517330f729Sjoerg /// Tracks the number of code-completion result objects that are
3527330f729Sjoerg /// currently active.
3537330f729Sjoerg ///
3547330f729Sjoerg /// Used for debugging purposes only.
3557330f729Sjoerg static std::atomic<unsigned> CodeCompletionResultObjects;
3567330f729Sjoerg
AllocatedCXCodeCompleteResults(IntrusiveRefCntPtr<FileManager> FileMgr)3577330f729Sjoerg AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults(
3587330f729Sjoerg IntrusiveRefCntPtr<FileManager> FileMgr)
3597330f729Sjoerg : CXCodeCompleteResults(), DiagOpts(new DiagnosticOptions),
3607330f729Sjoerg Diag(new DiagnosticsEngine(
3617330f729Sjoerg IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts)),
3627330f729Sjoerg FileMgr(std::move(FileMgr)),
3637330f729Sjoerg SourceMgr(new SourceManager(*Diag, *this->FileMgr)),
3647330f729Sjoerg CodeCompletionAllocator(
3657330f729Sjoerg std::make_shared<clang::GlobalCodeCompletionAllocator>()),
3667330f729Sjoerg Contexts(CXCompletionContext_Unknown),
3677330f729Sjoerg ContainerKind(CXCursor_InvalidCode), ContainerIsIncomplete(1) {
3687330f729Sjoerg if (getenv("LIBCLANG_OBJTRACKING"))
3697330f729Sjoerg fprintf(stderr, "+++ %u completion results\n",
3707330f729Sjoerg ++CodeCompletionResultObjects);
3717330f729Sjoerg }
3727330f729Sjoerg
~AllocatedCXCodeCompleteResults()3737330f729Sjoerg AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
3747330f729Sjoerg delete [] Results;
3757330f729Sjoerg
3767330f729Sjoerg for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I)
3777330f729Sjoerg delete TemporaryBuffers[I];
3787330f729Sjoerg
3797330f729Sjoerg if (getenv("LIBCLANG_OBJTRACKING"))
3807330f729Sjoerg fprintf(stderr, "--- %u completion results\n",
3817330f729Sjoerg --CodeCompletionResultObjects);
3827330f729Sjoerg }
3837330f729Sjoerg
getContextsForContextKind(enum CodeCompletionContext::Kind kind,Sema & S)3847330f729Sjoerg static unsigned long long getContextsForContextKind(
3857330f729Sjoerg enum CodeCompletionContext::Kind kind,
3867330f729Sjoerg Sema &S) {
3877330f729Sjoerg unsigned long long contexts = 0;
3887330f729Sjoerg switch (kind) {
3897330f729Sjoerg case CodeCompletionContext::CCC_OtherWithMacros: {
3907330f729Sjoerg //We can allow macros here, but we don't know what else is permissible
3917330f729Sjoerg //So we'll say the only thing permissible are macros
3927330f729Sjoerg contexts = CXCompletionContext_MacroName;
3937330f729Sjoerg break;
3947330f729Sjoerg }
3957330f729Sjoerg case CodeCompletionContext::CCC_TopLevel:
3967330f729Sjoerg case CodeCompletionContext::CCC_ObjCIvarList:
3977330f729Sjoerg case CodeCompletionContext::CCC_ClassStructUnion:
3987330f729Sjoerg case CodeCompletionContext::CCC_Type: {
3997330f729Sjoerg contexts = CXCompletionContext_AnyType |
4007330f729Sjoerg CXCompletionContext_ObjCInterface;
4017330f729Sjoerg if (S.getLangOpts().CPlusPlus) {
4027330f729Sjoerg contexts |= CXCompletionContext_EnumTag |
4037330f729Sjoerg CXCompletionContext_UnionTag |
4047330f729Sjoerg CXCompletionContext_StructTag |
4057330f729Sjoerg CXCompletionContext_ClassTag |
4067330f729Sjoerg CXCompletionContext_NestedNameSpecifier;
4077330f729Sjoerg }
4087330f729Sjoerg break;
4097330f729Sjoerg }
4107330f729Sjoerg case CodeCompletionContext::CCC_Statement: {
4117330f729Sjoerg contexts = CXCompletionContext_AnyType |
4127330f729Sjoerg CXCompletionContext_ObjCInterface |
4137330f729Sjoerg CXCompletionContext_AnyValue;
4147330f729Sjoerg if (S.getLangOpts().CPlusPlus) {
4157330f729Sjoerg contexts |= CXCompletionContext_EnumTag |
4167330f729Sjoerg CXCompletionContext_UnionTag |
4177330f729Sjoerg CXCompletionContext_StructTag |
4187330f729Sjoerg CXCompletionContext_ClassTag |
4197330f729Sjoerg CXCompletionContext_NestedNameSpecifier;
4207330f729Sjoerg }
4217330f729Sjoerg break;
4227330f729Sjoerg }
4237330f729Sjoerg case CodeCompletionContext::CCC_Expression: {
4247330f729Sjoerg contexts = CXCompletionContext_AnyValue;
4257330f729Sjoerg if (S.getLangOpts().CPlusPlus) {
4267330f729Sjoerg contexts |= CXCompletionContext_AnyType |
4277330f729Sjoerg CXCompletionContext_ObjCInterface |
4287330f729Sjoerg CXCompletionContext_EnumTag |
4297330f729Sjoerg CXCompletionContext_UnionTag |
4307330f729Sjoerg CXCompletionContext_StructTag |
4317330f729Sjoerg CXCompletionContext_ClassTag |
4327330f729Sjoerg CXCompletionContext_NestedNameSpecifier;
4337330f729Sjoerg }
4347330f729Sjoerg break;
4357330f729Sjoerg }
4367330f729Sjoerg case CodeCompletionContext::CCC_ObjCMessageReceiver: {
4377330f729Sjoerg contexts = CXCompletionContext_ObjCObjectValue |
4387330f729Sjoerg CXCompletionContext_ObjCSelectorValue |
4397330f729Sjoerg CXCompletionContext_ObjCInterface;
4407330f729Sjoerg if (S.getLangOpts().CPlusPlus) {
4417330f729Sjoerg contexts |= CXCompletionContext_CXXClassTypeValue |
4427330f729Sjoerg CXCompletionContext_AnyType |
4437330f729Sjoerg CXCompletionContext_EnumTag |
4447330f729Sjoerg CXCompletionContext_UnionTag |
4457330f729Sjoerg CXCompletionContext_StructTag |
4467330f729Sjoerg CXCompletionContext_ClassTag |
4477330f729Sjoerg CXCompletionContext_NestedNameSpecifier;
4487330f729Sjoerg }
4497330f729Sjoerg break;
4507330f729Sjoerg }
4517330f729Sjoerg case CodeCompletionContext::CCC_DotMemberAccess: {
4527330f729Sjoerg contexts = CXCompletionContext_DotMemberAccess;
4537330f729Sjoerg break;
4547330f729Sjoerg }
4557330f729Sjoerg case CodeCompletionContext::CCC_ArrowMemberAccess: {
4567330f729Sjoerg contexts = CXCompletionContext_ArrowMemberAccess;
4577330f729Sjoerg break;
4587330f729Sjoerg }
4597330f729Sjoerg case CodeCompletionContext::CCC_ObjCPropertyAccess: {
4607330f729Sjoerg contexts = CXCompletionContext_ObjCPropertyAccess;
4617330f729Sjoerg break;
4627330f729Sjoerg }
4637330f729Sjoerg case CodeCompletionContext::CCC_EnumTag: {
4647330f729Sjoerg contexts = CXCompletionContext_EnumTag |
4657330f729Sjoerg CXCompletionContext_NestedNameSpecifier;
4667330f729Sjoerg break;
4677330f729Sjoerg }
4687330f729Sjoerg case CodeCompletionContext::CCC_UnionTag: {
4697330f729Sjoerg contexts = CXCompletionContext_UnionTag |
4707330f729Sjoerg CXCompletionContext_NestedNameSpecifier;
4717330f729Sjoerg break;
4727330f729Sjoerg }
4737330f729Sjoerg case CodeCompletionContext::CCC_ClassOrStructTag: {
4747330f729Sjoerg contexts = CXCompletionContext_StructTag |
4757330f729Sjoerg CXCompletionContext_ClassTag |
4767330f729Sjoerg CXCompletionContext_NestedNameSpecifier;
4777330f729Sjoerg break;
4787330f729Sjoerg }
4797330f729Sjoerg case CodeCompletionContext::CCC_ObjCProtocolName: {
4807330f729Sjoerg contexts = CXCompletionContext_ObjCProtocol;
4817330f729Sjoerg break;
4827330f729Sjoerg }
4837330f729Sjoerg case CodeCompletionContext::CCC_Namespace: {
4847330f729Sjoerg contexts = CXCompletionContext_Namespace;
4857330f729Sjoerg break;
4867330f729Sjoerg }
4877330f729Sjoerg case CodeCompletionContext::CCC_SymbolOrNewName:
4887330f729Sjoerg case CodeCompletionContext::CCC_Symbol: {
4897330f729Sjoerg contexts = CXCompletionContext_NestedNameSpecifier;
4907330f729Sjoerg break;
4917330f729Sjoerg }
4927330f729Sjoerg case CodeCompletionContext::CCC_MacroNameUse: {
4937330f729Sjoerg contexts = CXCompletionContext_MacroName;
4947330f729Sjoerg break;
4957330f729Sjoerg }
4967330f729Sjoerg case CodeCompletionContext::CCC_NaturalLanguage: {
4977330f729Sjoerg contexts = CXCompletionContext_NaturalLanguage;
4987330f729Sjoerg break;
4997330f729Sjoerg }
5007330f729Sjoerg case CodeCompletionContext::CCC_IncludedFile: {
5017330f729Sjoerg contexts = CXCompletionContext_IncludedFile;
5027330f729Sjoerg break;
5037330f729Sjoerg }
5047330f729Sjoerg case CodeCompletionContext::CCC_SelectorName: {
5057330f729Sjoerg contexts = CXCompletionContext_ObjCSelectorName;
5067330f729Sjoerg break;
5077330f729Sjoerg }
5087330f729Sjoerg case CodeCompletionContext::CCC_ParenthesizedExpression: {
5097330f729Sjoerg contexts = CXCompletionContext_AnyType |
5107330f729Sjoerg CXCompletionContext_ObjCInterface |
5117330f729Sjoerg CXCompletionContext_AnyValue;
5127330f729Sjoerg if (S.getLangOpts().CPlusPlus) {
5137330f729Sjoerg contexts |= CXCompletionContext_EnumTag |
5147330f729Sjoerg CXCompletionContext_UnionTag |
5157330f729Sjoerg CXCompletionContext_StructTag |
5167330f729Sjoerg CXCompletionContext_ClassTag |
5177330f729Sjoerg CXCompletionContext_NestedNameSpecifier;
5187330f729Sjoerg }
5197330f729Sjoerg break;
5207330f729Sjoerg }
5217330f729Sjoerg case CodeCompletionContext::CCC_ObjCInstanceMessage: {
5227330f729Sjoerg contexts = CXCompletionContext_ObjCInstanceMessage;
5237330f729Sjoerg break;
5247330f729Sjoerg }
5257330f729Sjoerg case CodeCompletionContext::CCC_ObjCClassMessage: {
5267330f729Sjoerg contexts = CXCompletionContext_ObjCClassMessage;
5277330f729Sjoerg break;
5287330f729Sjoerg }
5297330f729Sjoerg case CodeCompletionContext::CCC_ObjCInterfaceName: {
5307330f729Sjoerg contexts = CXCompletionContext_ObjCInterface;
5317330f729Sjoerg break;
5327330f729Sjoerg }
5337330f729Sjoerg case CodeCompletionContext::CCC_ObjCCategoryName: {
5347330f729Sjoerg contexts = CXCompletionContext_ObjCCategory;
5357330f729Sjoerg break;
5367330f729Sjoerg }
5377330f729Sjoerg case CodeCompletionContext::CCC_Other:
5387330f729Sjoerg case CodeCompletionContext::CCC_ObjCInterface:
5397330f729Sjoerg case CodeCompletionContext::CCC_ObjCImplementation:
5407330f729Sjoerg case CodeCompletionContext::CCC_NewName:
5417330f729Sjoerg case CodeCompletionContext::CCC_MacroName:
5427330f729Sjoerg case CodeCompletionContext::CCC_PreprocessorExpression:
5437330f729Sjoerg case CodeCompletionContext::CCC_PreprocessorDirective:
5447330f729Sjoerg case CodeCompletionContext::CCC_TypeQualifiers: {
5457330f729Sjoerg //Only Clang results should be accepted, so we'll set all of the other
5467330f729Sjoerg //context bits to 0 (i.e. the empty set)
5477330f729Sjoerg contexts = CXCompletionContext_Unexposed;
5487330f729Sjoerg break;
5497330f729Sjoerg }
5507330f729Sjoerg case CodeCompletionContext::CCC_Recovery: {
5517330f729Sjoerg //We don't know what the current context is, so we'll return unknown
5527330f729Sjoerg //This is the equivalent of setting all of the other context bits
5537330f729Sjoerg contexts = CXCompletionContext_Unknown;
5547330f729Sjoerg break;
5557330f729Sjoerg }
5567330f729Sjoerg }
5577330f729Sjoerg return contexts;
5587330f729Sjoerg }
5597330f729Sjoerg
5607330f729Sjoerg namespace {
5617330f729Sjoerg class CaptureCompletionResults : public CodeCompleteConsumer {
5627330f729Sjoerg AllocatedCXCodeCompleteResults &AllocatedResults;
5637330f729Sjoerg CodeCompletionTUInfo CCTUInfo;
5647330f729Sjoerg SmallVector<CXCompletionResult, 16> StoredResults;
5657330f729Sjoerg CXTranslationUnit *TU;
5667330f729Sjoerg public:
CaptureCompletionResults(const CodeCompleteOptions & Opts,AllocatedCXCodeCompleteResults & Results,CXTranslationUnit * TranslationUnit)5677330f729Sjoerg CaptureCompletionResults(const CodeCompleteOptions &Opts,
5687330f729Sjoerg AllocatedCXCodeCompleteResults &Results,
5697330f729Sjoerg CXTranslationUnit *TranslationUnit)
5707330f729Sjoerg : CodeCompleteConsumer(Opts), AllocatedResults(Results),
5717330f729Sjoerg CCTUInfo(Results.CodeCompletionAllocator), TU(TranslationUnit) {}
~CaptureCompletionResults()5727330f729Sjoerg ~CaptureCompletionResults() override { Finish(); }
5737330f729Sjoerg
ProcessCodeCompleteResults(Sema & S,CodeCompletionContext Context,CodeCompletionResult * Results,unsigned NumResults)5747330f729Sjoerg void ProcessCodeCompleteResults(Sema &S,
5757330f729Sjoerg CodeCompletionContext Context,
5767330f729Sjoerg CodeCompletionResult *Results,
5777330f729Sjoerg unsigned NumResults) override {
5787330f729Sjoerg StoredResults.reserve(StoredResults.size() + NumResults);
5797330f729Sjoerg if (includeFixIts())
5807330f729Sjoerg AllocatedResults.FixItsVector.reserve(NumResults);
5817330f729Sjoerg for (unsigned I = 0; I != NumResults; ++I) {
5827330f729Sjoerg CodeCompletionString *StoredCompletion
5837330f729Sjoerg = Results[I].CreateCodeCompletionString(S, Context, getAllocator(),
5847330f729Sjoerg getCodeCompletionTUInfo(),
5857330f729Sjoerg includeBriefComments());
5867330f729Sjoerg
5877330f729Sjoerg CXCompletionResult R;
5887330f729Sjoerg R.CursorKind = Results[I].CursorKind;
5897330f729Sjoerg R.CompletionString = StoredCompletion;
5907330f729Sjoerg StoredResults.push_back(R);
5917330f729Sjoerg if (includeFixIts())
5927330f729Sjoerg AllocatedResults.FixItsVector.emplace_back(std::move(Results[I].FixIts));
5937330f729Sjoerg }
5947330f729Sjoerg
5957330f729Sjoerg enum CodeCompletionContext::Kind contextKind = Context.getKind();
5967330f729Sjoerg
5977330f729Sjoerg AllocatedResults.ContextKind = contextKind;
5987330f729Sjoerg AllocatedResults.Contexts = getContextsForContextKind(contextKind, S);
5997330f729Sjoerg
6007330f729Sjoerg AllocatedResults.Selector = "";
6017330f729Sjoerg ArrayRef<IdentifierInfo *> SelIdents = Context.getSelIdents();
6027330f729Sjoerg for (ArrayRef<IdentifierInfo *>::iterator I = SelIdents.begin(),
6037330f729Sjoerg E = SelIdents.end();
6047330f729Sjoerg I != E; ++I) {
6057330f729Sjoerg if (IdentifierInfo *selIdent = *I)
6067330f729Sjoerg AllocatedResults.Selector += selIdent->getName();
6077330f729Sjoerg AllocatedResults.Selector += ":";
6087330f729Sjoerg }
6097330f729Sjoerg
6107330f729Sjoerg QualType baseType = Context.getBaseType();
6117330f729Sjoerg NamedDecl *D = nullptr;
6127330f729Sjoerg
6137330f729Sjoerg if (!baseType.isNull()) {
6147330f729Sjoerg // Get the declaration for a class/struct/union/enum type
6157330f729Sjoerg if (const TagType *Tag = baseType->getAs<TagType>())
6167330f729Sjoerg D = Tag->getDecl();
6177330f729Sjoerg // Get the @interface declaration for a (possibly-qualified) Objective-C
6187330f729Sjoerg // object pointer type, e.g., NSString*
6197330f729Sjoerg else if (const ObjCObjectPointerType *ObjPtr =
6207330f729Sjoerg baseType->getAs<ObjCObjectPointerType>())
6217330f729Sjoerg D = ObjPtr->getInterfaceDecl();
6227330f729Sjoerg // Get the @interface declaration for an Objective-C object type
6237330f729Sjoerg else if (const ObjCObjectType *Obj = baseType->getAs<ObjCObjectType>())
6247330f729Sjoerg D = Obj->getInterface();
6257330f729Sjoerg // Get the class for a C++ injected-class-name
6267330f729Sjoerg else if (const InjectedClassNameType *Injected =
6277330f729Sjoerg baseType->getAs<InjectedClassNameType>())
6287330f729Sjoerg D = Injected->getDecl();
6297330f729Sjoerg }
6307330f729Sjoerg
6317330f729Sjoerg if (D != nullptr) {
6327330f729Sjoerg CXCursor cursor = cxcursor::MakeCXCursor(D, *TU);
6337330f729Sjoerg
6347330f729Sjoerg AllocatedResults.ContainerKind = clang_getCursorKind(cursor);
6357330f729Sjoerg
6367330f729Sjoerg CXString CursorUSR = clang_getCursorUSR(cursor);
6377330f729Sjoerg AllocatedResults.ContainerUSR = clang_getCString(CursorUSR);
6387330f729Sjoerg clang_disposeString(CursorUSR);
6397330f729Sjoerg
6407330f729Sjoerg const Type *type = baseType.getTypePtrOrNull();
6417330f729Sjoerg if (type) {
6427330f729Sjoerg AllocatedResults.ContainerIsIncomplete = type->isIncompleteType();
6437330f729Sjoerg }
6447330f729Sjoerg else {
6457330f729Sjoerg AllocatedResults.ContainerIsIncomplete = 1;
6467330f729Sjoerg }
6477330f729Sjoerg }
6487330f729Sjoerg else {
6497330f729Sjoerg AllocatedResults.ContainerKind = CXCursor_InvalidCode;
6507330f729Sjoerg AllocatedResults.ContainerUSR.clear();
6517330f729Sjoerg AllocatedResults.ContainerIsIncomplete = 1;
6527330f729Sjoerg }
6537330f729Sjoerg }
6547330f729Sjoerg
ProcessOverloadCandidates(Sema & S,unsigned CurrentArg,OverloadCandidate * Candidates,unsigned NumCandidates,SourceLocation OpenParLoc)6557330f729Sjoerg void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
6567330f729Sjoerg OverloadCandidate *Candidates,
6577330f729Sjoerg unsigned NumCandidates,
6587330f729Sjoerg SourceLocation OpenParLoc) override {
6597330f729Sjoerg StoredResults.reserve(StoredResults.size() + NumCandidates);
6607330f729Sjoerg for (unsigned I = 0; I != NumCandidates; ++I) {
6617330f729Sjoerg CodeCompletionString *StoredCompletion
6627330f729Sjoerg = Candidates[I].CreateSignatureString(CurrentArg, S, getAllocator(),
6637330f729Sjoerg getCodeCompletionTUInfo(),
6647330f729Sjoerg includeBriefComments());
6657330f729Sjoerg
6667330f729Sjoerg CXCompletionResult R;
6677330f729Sjoerg R.CursorKind = CXCursor_OverloadCandidate;
6687330f729Sjoerg R.CompletionString = StoredCompletion;
6697330f729Sjoerg StoredResults.push_back(R);
6707330f729Sjoerg }
6717330f729Sjoerg }
6727330f729Sjoerg
getAllocator()6737330f729Sjoerg CodeCompletionAllocator &getAllocator() override {
6747330f729Sjoerg return *AllocatedResults.CodeCompletionAllocator;
6757330f729Sjoerg }
6767330f729Sjoerg
getCodeCompletionTUInfo()6777330f729Sjoerg CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo;}
6787330f729Sjoerg
6797330f729Sjoerg private:
Finish()6807330f729Sjoerg void Finish() {
6817330f729Sjoerg AllocatedResults.Results = new CXCompletionResult [StoredResults.size()];
6827330f729Sjoerg AllocatedResults.NumResults = StoredResults.size();
6837330f729Sjoerg std::memcpy(AllocatedResults.Results, StoredResults.data(),
6847330f729Sjoerg StoredResults.size() * sizeof(CXCompletionResult));
6857330f729Sjoerg StoredResults.clear();
6867330f729Sjoerg }
6877330f729Sjoerg };
6887330f729Sjoerg }
6897330f729Sjoerg
6907330f729Sjoerg static CXCodeCompleteResults *
clang_codeCompleteAt_Impl(CXTranslationUnit TU,const char * complete_filename,unsigned complete_line,unsigned complete_column,ArrayRef<CXUnsavedFile> unsaved_files,unsigned options)6917330f729Sjoerg clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename,
6927330f729Sjoerg unsigned complete_line, unsigned complete_column,
6937330f729Sjoerg ArrayRef<CXUnsavedFile> unsaved_files,
6947330f729Sjoerg unsigned options) {
6957330f729Sjoerg bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments;
6967330f729Sjoerg bool SkipPreamble = options & CXCodeComplete_SkipPreamble;
6977330f729Sjoerg bool IncludeFixIts = options & CXCodeComplete_IncludeCompletionsWithFixIts;
6987330f729Sjoerg
6997330f729Sjoerg #ifdef UDP_CODE_COMPLETION_LOGGER
7007330f729Sjoerg #ifdef UDP_CODE_COMPLETION_LOGGER_PORT
7017330f729Sjoerg const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
7027330f729Sjoerg #endif
7037330f729Sjoerg #endif
7047330f729Sjoerg bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr;
7057330f729Sjoerg
7067330f729Sjoerg if (cxtu::isNotUsableTU(TU)) {
7077330f729Sjoerg LOG_BAD_TU(TU);
7087330f729Sjoerg return nullptr;
7097330f729Sjoerg }
7107330f729Sjoerg
7117330f729Sjoerg ASTUnit *AST = cxtu::getASTUnit(TU);
7127330f729Sjoerg if (!AST)
7137330f729Sjoerg return nullptr;
7147330f729Sjoerg
7157330f729Sjoerg CIndexer *CXXIdx = TU->CIdx;
7167330f729Sjoerg if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
7177330f729Sjoerg setThreadBackgroundPriority();
7187330f729Sjoerg
7197330f729Sjoerg ASTUnit::ConcurrencyCheck Check(*AST);
7207330f729Sjoerg
7217330f729Sjoerg // Perform the remapping of source files.
7227330f729Sjoerg SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
7237330f729Sjoerg
7247330f729Sjoerg for (auto &UF : unsaved_files) {
7257330f729Sjoerg std::unique_ptr<llvm::MemoryBuffer> MB =
7267330f729Sjoerg llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
7277330f729Sjoerg RemappedFiles.push_back(std::make_pair(UF.Filename, MB.release()));
7287330f729Sjoerg }
7297330f729Sjoerg
7307330f729Sjoerg if (EnableLogging) {
7317330f729Sjoerg // FIXME: Add logging.
7327330f729Sjoerg }
7337330f729Sjoerg
7347330f729Sjoerg // Parse the resulting source file to find code-completion results.
7357330f729Sjoerg AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults(
7367330f729Sjoerg &AST->getFileManager());
7377330f729Sjoerg Results->Results = nullptr;
7387330f729Sjoerg Results->NumResults = 0;
7397330f729Sjoerg
7407330f729Sjoerg // Create a code-completion consumer to capture the results.
7417330f729Sjoerg CodeCompleteOptions Opts;
7427330f729Sjoerg Opts.IncludeBriefComments = IncludeBriefComments;
7437330f729Sjoerg Opts.LoadExternal = !SkipPreamble;
7447330f729Sjoerg Opts.IncludeFixIts = IncludeFixIts;
7457330f729Sjoerg CaptureCompletionResults Capture(Opts, *Results, &TU);
7467330f729Sjoerg
7477330f729Sjoerg // Perform completion.
7487330f729Sjoerg std::vector<const char *> CArgs;
7497330f729Sjoerg for (const auto &Arg : TU->Arguments)
7507330f729Sjoerg CArgs.push_back(Arg.c_str());
7517330f729Sjoerg std::string CompletionInvocation =
7527330f729Sjoerg llvm::formatv("-code-completion-at={0}:{1}:{2}", complete_filename,
7537330f729Sjoerg complete_line, complete_column)
7547330f729Sjoerg .str();
7557330f729Sjoerg LibclangInvocationReporter InvocationReporter(
7567330f729Sjoerg *CXXIdx, LibclangInvocationReporter::OperationKind::CompletionOperation,
7577330f729Sjoerg TU->ParsingOptions, CArgs, CompletionInvocation, unsaved_files);
7587330f729Sjoerg AST->CodeComplete(complete_filename, complete_line, complete_column,
7597330f729Sjoerg RemappedFiles, (options & CXCodeComplete_IncludeMacros),
7607330f729Sjoerg (options & CXCodeComplete_IncludeCodePatterns),
7617330f729Sjoerg IncludeBriefComments, Capture,
7627330f729Sjoerg CXXIdx->getPCHContainerOperations(), *Results->Diag,
7637330f729Sjoerg Results->LangOpts, *Results->SourceMgr, *Results->FileMgr,
7647330f729Sjoerg Results->Diagnostics, Results->TemporaryBuffers);
7657330f729Sjoerg
7667330f729Sjoerg Results->DiagnosticsWrappers.resize(Results->Diagnostics.size());
7677330f729Sjoerg
7687330f729Sjoerg // Keep a reference to the allocator used for cached global completions, so
7697330f729Sjoerg // that we can be sure that the memory used by our code completion strings
7707330f729Sjoerg // doesn't get freed due to subsequent reparses (while the code completion
7717330f729Sjoerg // results are still active).
7727330f729Sjoerg Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator();
7737330f729Sjoerg
7747330f729Sjoerg
7757330f729Sjoerg
7767330f729Sjoerg #ifdef UDP_CODE_COMPLETION_LOGGER
7777330f729Sjoerg #ifdef UDP_CODE_COMPLETION_LOGGER_PORT
7787330f729Sjoerg const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
7797330f729Sjoerg SmallString<256> LogResult;
7807330f729Sjoerg llvm::raw_svector_ostream os(LogResult);
7817330f729Sjoerg
7827330f729Sjoerg // Figure out the language and whether or not it uses PCH.
7837330f729Sjoerg const char *lang = 0;
7847330f729Sjoerg bool usesPCH = false;
7857330f729Sjoerg
7867330f729Sjoerg for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
7877330f729Sjoerg I != E; ++I) {
7887330f729Sjoerg if (*I == 0)
7897330f729Sjoerg continue;
7907330f729Sjoerg if (strcmp(*I, "-x") == 0) {
7917330f729Sjoerg if (I + 1 != E) {
7927330f729Sjoerg lang = *(++I);
7937330f729Sjoerg continue;
7947330f729Sjoerg }
7957330f729Sjoerg }
7967330f729Sjoerg else if (strcmp(*I, "-include") == 0) {
7977330f729Sjoerg if (I+1 != E) {
7987330f729Sjoerg const char *arg = *(++I);
7997330f729Sjoerg SmallString<512> pchName;
8007330f729Sjoerg {
8017330f729Sjoerg llvm::raw_svector_ostream os(pchName);
8027330f729Sjoerg os << arg << ".pth";
8037330f729Sjoerg }
8047330f729Sjoerg pchName.push_back('\0');
8057330f729Sjoerg llvm::sys::fs::file_status stat_results;
8067330f729Sjoerg if (!llvm::sys::fs::status(pchName, stat_results))
8077330f729Sjoerg usesPCH = true;
8087330f729Sjoerg continue;
8097330f729Sjoerg }
8107330f729Sjoerg }
8117330f729Sjoerg }
8127330f729Sjoerg
8137330f729Sjoerg os << "{ ";
8147330f729Sjoerg os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
8157330f729Sjoerg os << ", \"numRes\": " << Results->NumResults;
8167330f729Sjoerg os << ", \"diags\": " << Results->Diagnostics.size();
8177330f729Sjoerg os << ", \"pch\": " << (usesPCH ? "true" : "false");
8187330f729Sjoerg os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
8197330f729Sjoerg const char *name = getlogin();
8207330f729Sjoerg os << ", \"user\": \"" << (name ? name : "unknown") << '"';
8217330f729Sjoerg os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
8227330f729Sjoerg os << " }";
8237330f729Sjoerg
8247330f729Sjoerg StringRef res = os.str();
8257330f729Sjoerg if (res.size() > 0) {
8267330f729Sjoerg do {
8277330f729Sjoerg // Setup the UDP socket.
8287330f729Sjoerg struct sockaddr_in servaddr;
8297330f729Sjoerg bzero(&servaddr, sizeof(servaddr));
8307330f729Sjoerg servaddr.sin_family = AF_INET;
8317330f729Sjoerg servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
8327330f729Sjoerg if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
8337330f729Sjoerg &servaddr.sin_addr) <= 0)
8347330f729Sjoerg break;
8357330f729Sjoerg
8367330f729Sjoerg int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
8377330f729Sjoerg if (sockfd < 0)
8387330f729Sjoerg break;
8397330f729Sjoerg
8407330f729Sjoerg sendto(sockfd, res.data(), res.size(), 0,
8417330f729Sjoerg (struct sockaddr *)&servaddr, sizeof(servaddr));
8427330f729Sjoerg close(sockfd);
8437330f729Sjoerg }
8447330f729Sjoerg while (false);
8457330f729Sjoerg }
8467330f729Sjoerg #endif
8477330f729Sjoerg #endif
8487330f729Sjoerg return Results;
8497330f729Sjoerg }
8507330f729Sjoerg
clang_codeCompleteAt(CXTranslationUnit TU,const char * complete_filename,unsigned complete_line,unsigned complete_column,struct CXUnsavedFile * unsaved_files,unsigned num_unsaved_files,unsigned options)8517330f729Sjoerg CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
8527330f729Sjoerg const char *complete_filename,
8537330f729Sjoerg unsigned complete_line,
8547330f729Sjoerg unsigned complete_column,
8557330f729Sjoerg struct CXUnsavedFile *unsaved_files,
8567330f729Sjoerg unsigned num_unsaved_files,
8577330f729Sjoerg unsigned options) {
8587330f729Sjoerg LOG_FUNC_SECTION {
8597330f729Sjoerg *Log << TU << ' '
8607330f729Sjoerg << complete_filename << ':' << complete_line << ':' << complete_column;
8617330f729Sjoerg }
8627330f729Sjoerg
8637330f729Sjoerg if (num_unsaved_files && !unsaved_files)
8647330f729Sjoerg return nullptr;
8657330f729Sjoerg
8667330f729Sjoerg CXCodeCompleteResults *result;
8677330f729Sjoerg auto CodeCompleteAtImpl = [=, &result]() {
8687330f729Sjoerg result = clang_codeCompleteAt_Impl(
8697330f729Sjoerg TU, complete_filename, complete_line, complete_column,
8707330f729Sjoerg llvm::makeArrayRef(unsaved_files, num_unsaved_files), options);
8717330f729Sjoerg };
8727330f729Sjoerg
8737330f729Sjoerg llvm::CrashRecoveryContext CRC;
8747330f729Sjoerg
8757330f729Sjoerg if (!RunSafely(CRC, CodeCompleteAtImpl)) {
8767330f729Sjoerg fprintf(stderr, "libclang: crash detected in code completion\n");
8777330f729Sjoerg cxtu::getASTUnit(TU)->setUnsafeToFree(true);
8787330f729Sjoerg return nullptr;
8797330f729Sjoerg } else if (getenv("LIBCLANG_RESOURCE_USAGE"))
8807330f729Sjoerg PrintLibclangResourceUsage(TU);
8817330f729Sjoerg
8827330f729Sjoerg return result;
8837330f729Sjoerg }
8847330f729Sjoerg
clang_defaultCodeCompleteOptions(void)8857330f729Sjoerg unsigned clang_defaultCodeCompleteOptions(void) {
8867330f729Sjoerg return CXCodeComplete_IncludeMacros;
8877330f729Sjoerg }
8887330f729Sjoerg
clang_disposeCodeCompleteResults(CXCodeCompleteResults * ResultsIn)8897330f729Sjoerg void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
8907330f729Sjoerg if (!ResultsIn)
8917330f729Sjoerg return;
8927330f729Sjoerg
8937330f729Sjoerg AllocatedCXCodeCompleteResults *Results
8947330f729Sjoerg = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
8957330f729Sjoerg delete Results;
8967330f729Sjoerg }
8977330f729Sjoerg
8987330f729Sjoerg unsigned
clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults * ResultsIn)8997330f729Sjoerg clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
9007330f729Sjoerg AllocatedCXCodeCompleteResults *Results
9017330f729Sjoerg = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
9027330f729Sjoerg if (!Results)
9037330f729Sjoerg return 0;
9047330f729Sjoerg
9057330f729Sjoerg return Results->Diagnostics.size();
9067330f729Sjoerg }
9077330f729Sjoerg
9087330f729Sjoerg CXDiagnostic
clang_codeCompleteGetDiagnostic(CXCodeCompleteResults * ResultsIn,unsigned Index)9097330f729Sjoerg clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
9107330f729Sjoerg unsigned Index) {
9117330f729Sjoerg AllocatedCXCodeCompleteResults *Results
9127330f729Sjoerg = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
9137330f729Sjoerg if (!Results || Index >= Results->Diagnostics.size())
9147330f729Sjoerg return nullptr;
9157330f729Sjoerg
916*e038c9c4Sjoerg CXStoredDiagnostic *Diag = Results->DiagnosticsWrappers[Index].get();
9177330f729Sjoerg if (!Diag)
918*e038c9c4Sjoerg Diag = (Results->DiagnosticsWrappers[Index] =
919*e038c9c4Sjoerg std::make_unique<CXStoredDiagnostic>(
920*e038c9c4Sjoerg Results->Diagnostics[Index], Results->LangOpts))
921*e038c9c4Sjoerg .get();
9227330f729Sjoerg return Diag;
9237330f729Sjoerg }
9247330f729Sjoerg
9257330f729Sjoerg unsigned long long
clang_codeCompleteGetContexts(CXCodeCompleteResults * ResultsIn)9267330f729Sjoerg clang_codeCompleteGetContexts(CXCodeCompleteResults *ResultsIn) {
9277330f729Sjoerg AllocatedCXCodeCompleteResults *Results
9287330f729Sjoerg = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
9297330f729Sjoerg if (!Results)
9307330f729Sjoerg return 0;
9317330f729Sjoerg
9327330f729Sjoerg return Results->Contexts;
9337330f729Sjoerg }
9347330f729Sjoerg
clang_codeCompleteGetContainerKind(CXCodeCompleteResults * ResultsIn,unsigned * IsIncomplete)9357330f729Sjoerg enum CXCursorKind clang_codeCompleteGetContainerKind(
9367330f729Sjoerg CXCodeCompleteResults *ResultsIn,
9377330f729Sjoerg unsigned *IsIncomplete) {
9387330f729Sjoerg AllocatedCXCodeCompleteResults *Results =
9397330f729Sjoerg static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
9407330f729Sjoerg if (!Results)
9417330f729Sjoerg return CXCursor_InvalidCode;
9427330f729Sjoerg
9437330f729Sjoerg if (IsIncomplete != nullptr) {
9447330f729Sjoerg *IsIncomplete = Results->ContainerIsIncomplete;
9457330f729Sjoerg }
9467330f729Sjoerg
9477330f729Sjoerg return Results->ContainerKind;
9487330f729Sjoerg }
9497330f729Sjoerg
clang_codeCompleteGetContainerUSR(CXCodeCompleteResults * ResultsIn)9507330f729Sjoerg CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *ResultsIn) {
9517330f729Sjoerg AllocatedCXCodeCompleteResults *Results =
9527330f729Sjoerg static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
9537330f729Sjoerg if (!Results)
9547330f729Sjoerg return cxstring::createEmpty();
9557330f729Sjoerg
9567330f729Sjoerg return cxstring::createRef(Results->ContainerUSR.c_str());
9577330f729Sjoerg }
9587330f729Sjoerg
9597330f729Sjoerg
clang_codeCompleteGetObjCSelector(CXCodeCompleteResults * ResultsIn)9607330f729Sjoerg CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *ResultsIn) {
9617330f729Sjoerg AllocatedCXCodeCompleteResults *Results =
9627330f729Sjoerg static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
9637330f729Sjoerg if (!Results)
9647330f729Sjoerg return cxstring::createEmpty();
9657330f729Sjoerg
9667330f729Sjoerg return cxstring::createDup(Results->Selector);
9677330f729Sjoerg }
9687330f729Sjoerg
9697330f729Sjoerg /// Simple utility function that appends a \p New string to the given
9707330f729Sjoerg /// \p Old string, using the \p Buffer for storage.
9717330f729Sjoerg ///
9727330f729Sjoerg /// \param Old The string to which we are appending. This parameter will be
9737330f729Sjoerg /// updated to reflect the complete string.
9747330f729Sjoerg ///
9757330f729Sjoerg ///
9767330f729Sjoerg /// \param New The string to append to \p Old.
9777330f729Sjoerg ///
9787330f729Sjoerg /// \param Buffer A buffer that stores the actual, concatenated string. It will
9797330f729Sjoerg /// be used if the old string is already-non-empty.
AppendToString(StringRef & Old,StringRef New,SmallString<256> & Buffer)9807330f729Sjoerg static void AppendToString(StringRef &Old, StringRef New,
9817330f729Sjoerg SmallString<256> &Buffer) {
9827330f729Sjoerg if (Old.empty()) {
9837330f729Sjoerg Old = New;
9847330f729Sjoerg return;
9857330f729Sjoerg }
9867330f729Sjoerg
9877330f729Sjoerg if (Buffer.empty())
9887330f729Sjoerg Buffer.append(Old.begin(), Old.end());
9897330f729Sjoerg Buffer.append(New.begin(), New.end());
9907330f729Sjoerg Old = Buffer.str();
9917330f729Sjoerg }
9927330f729Sjoerg
9937330f729Sjoerg /// Get the typed-text blocks from the given code-completion string
9947330f729Sjoerg /// and return them as a single string.
9957330f729Sjoerg ///
9967330f729Sjoerg /// \param String The code-completion string whose typed-text blocks will be
9977330f729Sjoerg /// concatenated.
9987330f729Sjoerg ///
9997330f729Sjoerg /// \param Buffer A buffer used for storage of the completed name.
GetTypedName(CodeCompletionString * String,SmallString<256> & Buffer)10007330f729Sjoerg static StringRef GetTypedName(CodeCompletionString *String,
10017330f729Sjoerg SmallString<256> &Buffer) {
10027330f729Sjoerg StringRef Result;
10037330f729Sjoerg for (CodeCompletionString::iterator C = String->begin(), CEnd = String->end();
10047330f729Sjoerg C != CEnd; ++C) {
10057330f729Sjoerg if (C->Kind == CodeCompletionString::CK_TypedText)
10067330f729Sjoerg AppendToString(Result, C->Text, Buffer);
10077330f729Sjoerg }
10087330f729Sjoerg
10097330f729Sjoerg return Result;
10107330f729Sjoerg }
10117330f729Sjoerg
10127330f729Sjoerg namespace {
10137330f729Sjoerg struct OrderCompletionResults {
operator ()__anone15a3c3a0411::OrderCompletionResults10147330f729Sjoerg bool operator()(const CXCompletionResult &XR,
10157330f729Sjoerg const CXCompletionResult &YR) const {
10167330f729Sjoerg CodeCompletionString *X
10177330f729Sjoerg = (CodeCompletionString *)XR.CompletionString;
10187330f729Sjoerg CodeCompletionString *Y
10197330f729Sjoerg = (CodeCompletionString *)YR.CompletionString;
10207330f729Sjoerg
10217330f729Sjoerg SmallString<256> XBuffer;
10227330f729Sjoerg StringRef XText = GetTypedName(X, XBuffer);
10237330f729Sjoerg SmallString<256> YBuffer;
10247330f729Sjoerg StringRef YText = GetTypedName(Y, YBuffer);
10257330f729Sjoerg
10267330f729Sjoerg if (XText.empty() || YText.empty())
10277330f729Sjoerg return !XText.empty();
10287330f729Sjoerg
10297330f729Sjoerg int result = XText.compare_lower(YText);
10307330f729Sjoerg if (result < 0)
10317330f729Sjoerg return true;
10327330f729Sjoerg if (result > 0)
10337330f729Sjoerg return false;
10347330f729Sjoerg
10357330f729Sjoerg result = XText.compare(YText);
10367330f729Sjoerg return result < 0;
10377330f729Sjoerg }
10387330f729Sjoerg };
10397330f729Sjoerg }
10407330f729Sjoerg
clang_sortCodeCompletionResults(CXCompletionResult * Results,unsigned NumResults)10417330f729Sjoerg void clang_sortCodeCompletionResults(CXCompletionResult *Results,
10427330f729Sjoerg unsigned NumResults) {
10437330f729Sjoerg std::stable_sort(Results, Results + NumResults, OrderCompletionResults());
10447330f729Sjoerg }
1045