| //===- CIndexCodeCompletion.cpp - Code Completion API hooks ---------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // This file implements the Clang-C Source Indexing library hooks for | 
 | // code completion. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "CIndexer.h" | 
 | #include "CXTranslationUnit.h" | 
 | #include "CXString.h" | 
 | #include "CXCursor.h" | 
 | #include "CXString.h" | 
 | #include "CIndexDiagnostic.h" | 
 | #include "clang/AST/Type.h" | 
 | #include "clang/AST/Decl.h" | 
 | #include "clang/AST/DeclObjC.h" | 
 | #include "clang/Basic/SourceManager.h" | 
 | #include "clang/Basic/FileManager.h" | 
 | #include "clang/Frontend/ASTUnit.h" | 
 | #include "clang/Frontend/CompilerInstance.h" | 
 | #include "clang/Frontend/FrontendDiagnostic.h" | 
 | #include "clang/Sema/CodeCompleteConsumer.h" | 
 | #include "llvm/ADT/SmallString.h" | 
 | #include "llvm/ADT/StringExtras.h" | 
 | #include "llvm/Support/Atomic.h" | 
 | #include "llvm/Support/CrashRecoveryContext.h" | 
 | #include "llvm/Support/MemoryBuffer.h" | 
 | #include "llvm/Support/Timer.h" | 
 | #include "llvm/Support/raw_ostream.h" | 
 | #include "llvm/Support/Program.h" | 
 | #include <cstdlib> | 
 | #include <cstdio> | 
 |  | 
 |  | 
 | #ifdef UDP_CODE_COMPLETION_LOGGER | 
 | #include "clang/Basic/Version.h" | 
 | #include <arpa/inet.h> | 
 | #include <sys/socket.h> | 
 | #include <sys/types.h> | 
 | #include <unistd.h> | 
 | #endif | 
 |  | 
 | using namespace clang; | 
 | using namespace clang::cxstring; | 
 |  | 
 | extern "C" { | 
 |  | 
 | enum CXCompletionChunkKind | 
 | clang_getCompletionChunkKind(CXCompletionString completion_string, | 
 |                              unsigned chunk_number) { | 
 |   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; | 
 |   if (!CCStr || chunk_number >= CCStr->size()) | 
 |     return CXCompletionChunk_Text; | 
 |  | 
 |   switch ((*CCStr)[chunk_number].Kind) { | 
 |   case CodeCompletionString::CK_TypedText: | 
 |     return CXCompletionChunk_TypedText; | 
 |   case CodeCompletionString::CK_Text: | 
 |     return CXCompletionChunk_Text; | 
 |   case CodeCompletionString::CK_Optional: | 
 |     return CXCompletionChunk_Optional; | 
 |   case CodeCompletionString::CK_Placeholder: | 
 |     return CXCompletionChunk_Placeholder; | 
 |   case CodeCompletionString::CK_Informative: | 
 |     return CXCompletionChunk_Informative; | 
 |   case CodeCompletionString::CK_ResultType: | 
 |     return CXCompletionChunk_ResultType; | 
 |   case CodeCompletionString::CK_CurrentParameter: | 
 |     return CXCompletionChunk_CurrentParameter; | 
 |   case CodeCompletionString::CK_LeftParen: | 
 |     return CXCompletionChunk_LeftParen; | 
 |   case CodeCompletionString::CK_RightParen: | 
 |     return CXCompletionChunk_RightParen; | 
 |   case CodeCompletionString::CK_LeftBracket: | 
 |     return CXCompletionChunk_LeftBracket; | 
 |   case CodeCompletionString::CK_RightBracket: | 
 |     return CXCompletionChunk_RightBracket; | 
 |   case CodeCompletionString::CK_LeftBrace: | 
 |     return CXCompletionChunk_LeftBrace; | 
 |   case CodeCompletionString::CK_RightBrace: | 
 |     return CXCompletionChunk_RightBrace; | 
 |   case CodeCompletionString::CK_LeftAngle: | 
 |     return CXCompletionChunk_LeftAngle; | 
 |   case CodeCompletionString::CK_RightAngle: | 
 |     return CXCompletionChunk_RightAngle; | 
 |   case CodeCompletionString::CK_Comma: | 
 |     return CXCompletionChunk_Comma; | 
 |   case CodeCompletionString::CK_Colon: | 
 |     return CXCompletionChunk_Colon; | 
 |   case CodeCompletionString::CK_SemiColon: | 
 |     return CXCompletionChunk_SemiColon; | 
 |   case CodeCompletionString::CK_Equal: | 
 |     return CXCompletionChunk_Equal; | 
 |   case CodeCompletionString::CK_HorizontalSpace: | 
 |     return CXCompletionChunk_HorizontalSpace; | 
 |   case CodeCompletionString::CK_VerticalSpace: | 
 |     return CXCompletionChunk_VerticalSpace; | 
 |   } | 
 |  | 
 |   // Should be unreachable, but let's be careful. | 
 |   return CXCompletionChunk_Text; | 
 | } | 
 |  | 
 | CXString clang_getCompletionChunkText(CXCompletionString completion_string, | 
 |                                       unsigned chunk_number) { | 
 |   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; | 
 |   if (!CCStr || chunk_number >= CCStr->size()) | 
 |     return createCXString((const char*)0); | 
 |  | 
 |   switch ((*CCStr)[chunk_number].Kind) { | 
 |   case CodeCompletionString::CK_TypedText: | 
 |   case CodeCompletionString::CK_Text: | 
 |   case CodeCompletionString::CK_Placeholder: | 
 |   case CodeCompletionString::CK_CurrentParameter: | 
 |   case CodeCompletionString::CK_Informative: | 
 |   case CodeCompletionString::CK_LeftParen: | 
 |   case CodeCompletionString::CK_RightParen: | 
 |   case CodeCompletionString::CK_LeftBracket: | 
 |   case CodeCompletionString::CK_RightBracket: | 
 |   case CodeCompletionString::CK_LeftBrace: | 
 |   case CodeCompletionString::CK_RightBrace: | 
 |   case CodeCompletionString::CK_LeftAngle: | 
 |   case CodeCompletionString::CK_RightAngle: | 
 |   case CodeCompletionString::CK_Comma: | 
 |   case CodeCompletionString::CK_ResultType: | 
 |   case CodeCompletionString::CK_Colon: | 
 |   case CodeCompletionString::CK_SemiColon: | 
 |   case CodeCompletionString::CK_Equal: | 
 |   case CodeCompletionString::CK_HorizontalSpace: | 
 |   case CodeCompletionString::CK_VerticalSpace: | 
 |     return createCXString((*CCStr)[chunk_number].Text, false); | 
 |        | 
 |   case CodeCompletionString::CK_Optional: | 
 |     // Note: treated as an empty text block. | 
 |     return createCXString(""); | 
 |   } | 
 |  | 
 |   // Should be unreachable, but let's be careful. | 
 |   return createCXString((const char*)0); | 
 | } | 
 |  | 
 |  | 
 | CXCompletionString | 
 | clang_getCompletionChunkCompletionString(CXCompletionString completion_string, | 
 |                                          unsigned chunk_number) { | 
 |   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; | 
 |   if (!CCStr || chunk_number >= CCStr->size()) | 
 |     return 0; | 
 |  | 
 |   switch ((*CCStr)[chunk_number].Kind) { | 
 |   case CodeCompletionString::CK_TypedText: | 
 |   case CodeCompletionString::CK_Text: | 
 |   case CodeCompletionString::CK_Placeholder: | 
 |   case CodeCompletionString::CK_CurrentParameter: | 
 |   case CodeCompletionString::CK_Informative: | 
 |   case CodeCompletionString::CK_LeftParen: | 
 |   case CodeCompletionString::CK_RightParen: | 
 |   case CodeCompletionString::CK_LeftBracket: | 
 |   case CodeCompletionString::CK_RightBracket: | 
 |   case CodeCompletionString::CK_LeftBrace: | 
 |   case CodeCompletionString::CK_RightBrace: | 
 |   case CodeCompletionString::CK_LeftAngle: | 
 |   case CodeCompletionString::CK_RightAngle: | 
 |   case CodeCompletionString::CK_Comma: | 
 |   case CodeCompletionString::CK_ResultType: | 
 |   case CodeCompletionString::CK_Colon: | 
 |   case CodeCompletionString::CK_SemiColon: | 
 |   case CodeCompletionString::CK_Equal: | 
 |   case CodeCompletionString::CK_HorizontalSpace: | 
 |   case CodeCompletionString::CK_VerticalSpace: | 
 |     return 0; | 
 |  | 
 |   case CodeCompletionString::CK_Optional: | 
 |     // Note: treated as an empty text block. | 
 |     return (*CCStr)[chunk_number].Optional; | 
 |   } | 
 |  | 
 |   // Should be unreachable, but let's be careful. | 
 |   return 0; | 
 | } | 
 |  | 
 | unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) { | 
 |   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; | 
 |   return CCStr? CCStr->size() : 0; | 
 | } | 
 |  | 
 | unsigned clang_getCompletionPriority(CXCompletionString completion_string) { | 
 |   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; | 
 |   return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely); | 
 | } | 
 |    | 
 | enum CXAvailabilityKind  | 
 | clang_getCompletionAvailability(CXCompletionString completion_string) { | 
 |   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; | 
 |   return CCStr? static_cast<CXAvailabilityKind>(CCStr->getAvailability()) | 
 |               : CXAvailability_Available; | 
 | } | 
 |  | 
 | unsigned clang_getCompletionNumAnnotations(CXCompletionString completion_string) | 
 | { | 
 |   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; | 
 |   return CCStr ? CCStr->getAnnotationCount() : 0; | 
 | } | 
 |  | 
 | CXString clang_getCompletionAnnotation(CXCompletionString completion_string, | 
 |                                        unsigned annotation_number) { | 
 |   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; | 
 |   return CCStr ? createCXString(CCStr->getAnnotation(annotation_number)) | 
 |                : createCXString((const char *) 0); | 
 | } | 
 |  | 
 |  | 
 | /// \brief The CXCodeCompleteResults structure we allocate internally; | 
 | /// the client only sees the initial CXCodeCompleteResults structure. | 
 | struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { | 
 |   AllocatedCXCodeCompleteResults(const FileSystemOptions& FileSystemOpts); | 
 |   ~AllocatedCXCodeCompleteResults(); | 
 |    | 
 |   /// \brief Diagnostics produced while performing code completion. | 
 |   SmallVector<StoredDiagnostic, 8> Diagnostics; | 
 |  | 
 |   /// \brief Diag object | 
 |   llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diag; | 
 |    | 
 |   /// \brief Language options used to adjust source locations. | 
 |   LangOptions LangOpts; | 
 |  | 
 |   FileSystemOptions FileSystemOpts; | 
 |  | 
 |   /// \brief File manager, used for diagnostics. | 
 |   llvm::IntrusiveRefCntPtr<FileManager> FileMgr; | 
 |  | 
 |   /// \brief Source manager, used for diagnostics. | 
 |   llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr; | 
 |    | 
 |   /// \brief Temporary files that should be removed once we have finished | 
 |   /// with the code-completion results. | 
 |   std::vector<llvm::sys::Path> TemporaryFiles; | 
 |  | 
 |   /// \brief Temporary buffers that will be deleted once we have finished with | 
 |   /// the code-completion results. | 
 |   SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers; | 
 |    | 
 |   /// \brief Allocator used to store globally cached code-completion results. | 
 |   llvm::IntrusiveRefCntPtr<clang::GlobalCodeCompletionAllocator>  | 
 |     CachedCompletionAllocator; | 
 |    | 
 |   /// \brief Allocator used to store code completion results. | 
 |   clang::CodeCompletionAllocator CodeCompletionAllocator; | 
 |    | 
 |   /// \brief Context under which completion occurred. | 
 |   enum clang::CodeCompletionContext::Kind ContextKind; | 
 |    | 
 |   /// \brief A bitfield representing the acceptable completions for the | 
 |   /// current context. | 
 |   unsigned long long Contexts; | 
 |    | 
 |   /// \brief The kind of the container for the current context for completions. | 
 |   enum CXCursorKind ContainerKind; | 
 |   /// \brief The USR of the container for the current context for completions. | 
 |   CXString ContainerUSR; | 
 |   /// \brief a boolean value indicating whether there is complete information | 
 |   /// about the container | 
 |   unsigned ContainerIsIncomplete; | 
 |    | 
 |   /// \brief A string containing the Objective-C selector entered thus far for a | 
 |   /// message send. | 
 |   std::string Selector; | 
 | }; | 
 |  | 
 | /// \brief Tracks the number of code-completion result objects that are  | 
 | /// currently active. | 
 | /// | 
 | /// Used for debugging purposes only. | 
 | static llvm::sys::cas_flag CodeCompletionResultObjects; | 
 |    | 
 | AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults( | 
 |                                       const FileSystemOptions& FileSystemOpts) | 
 |   : CXCodeCompleteResults(), | 
 |     Diag(new DiagnosticsEngine( | 
 |                    llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs))), | 
 |     FileSystemOpts(FileSystemOpts), | 
 |     FileMgr(new FileManager(FileSystemOpts)), | 
 |     SourceMgr(new SourceManager(*Diag, *FileMgr)), | 
 |     Contexts(CXCompletionContext_Unknown), | 
 |     ContainerKind(CXCursor_InvalidCode), | 
 |     ContainerUSR(createCXString("")), | 
 |     ContainerIsIncomplete(1) | 
 | {  | 
 |   if (getenv("LIBCLANG_OBJTRACKING")) { | 
 |     llvm::sys::AtomicIncrement(&CodeCompletionResultObjects); | 
 |     fprintf(stderr, "+++ %d completion results\n", CodeCompletionResultObjects); | 
 |   }     | 
 | } | 
 |    | 
 | AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() { | 
 |   delete [] Results; | 
 |    | 
 |   clang_disposeString(ContainerUSR); | 
 |    | 
 |   for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) | 
 |     TemporaryFiles[I].eraseFromDisk(); | 
 |   for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I) | 
 |     delete TemporaryBuffers[I]; | 
 |  | 
 |   if (getenv("LIBCLANG_OBJTRACKING")) { | 
 |     llvm::sys::AtomicDecrement(&CodeCompletionResultObjects); | 
 |     fprintf(stderr, "--- %d completion results\n", CodeCompletionResultObjects); | 
 |   }     | 
 | } | 
 |    | 
 | } // end extern "C" | 
 |  | 
 | static unsigned long long getContextsForContextKind( | 
 |                                           enum CodeCompletionContext::Kind kind,  | 
 |                                                     Sema &S) { | 
 |   unsigned long long contexts = 0; | 
 |   switch (kind) { | 
 |     case CodeCompletionContext::CCC_OtherWithMacros: { | 
 |       //We can allow macros here, but we don't know what else is permissible | 
 |       //So we'll say the only thing permissible are macros | 
 |       contexts = CXCompletionContext_MacroName; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_TopLevel: | 
 |     case CodeCompletionContext::CCC_ObjCIvarList: | 
 |     case CodeCompletionContext::CCC_ClassStructUnion: | 
 |     case CodeCompletionContext::CCC_Type: { | 
 |       contexts = CXCompletionContext_AnyType |  | 
 |                  CXCompletionContext_ObjCInterface; | 
 |       if (S.getLangOptions().CPlusPlus) { | 
 |         contexts |= CXCompletionContext_EnumTag | | 
 |                     CXCompletionContext_UnionTag | | 
 |                     CXCompletionContext_StructTag | | 
 |                     CXCompletionContext_ClassTag | | 
 |                     CXCompletionContext_NestedNameSpecifier; | 
 |       } | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_Statement: { | 
 |       contexts = CXCompletionContext_AnyType | | 
 |                  CXCompletionContext_ObjCInterface | | 
 |                  CXCompletionContext_AnyValue; | 
 |       if (S.getLangOptions().CPlusPlus) { | 
 |         contexts |= CXCompletionContext_EnumTag | | 
 |                     CXCompletionContext_UnionTag | | 
 |                     CXCompletionContext_StructTag | | 
 |                     CXCompletionContext_ClassTag | | 
 |                     CXCompletionContext_NestedNameSpecifier; | 
 |       } | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_Expression: { | 
 |       contexts = CXCompletionContext_AnyValue; | 
 |       if (S.getLangOptions().CPlusPlus) { | 
 |         contexts |= CXCompletionContext_AnyType | | 
 |                     CXCompletionContext_ObjCInterface | | 
 |                     CXCompletionContext_EnumTag | | 
 |                     CXCompletionContext_UnionTag | | 
 |                     CXCompletionContext_StructTag | | 
 |                     CXCompletionContext_ClassTag | | 
 |                     CXCompletionContext_NestedNameSpecifier; | 
 |       } | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_ObjCMessageReceiver: { | 
 |       contexts = CXCompletionContext_ObjCObjectValue | | 
 |                  CXCompletionContext_ObjCSelectorValue | | 
 |                  CXCompletionContext_ObjCInterface; | 
 |       if (S.getLangOptions().CPlusPlus) { | 
 |         contexts |= CXCompletionContext_CXXClassTypeValue | | 
 |                     CXCompletionContext_AnyType | | 
 |                     CXCompletionContext_EnumTag | | 
 |                     CXCompletionContext_UnionTag | | 
 |                     CXCompletionContext_StructTag | | 
 |                     CXCompletionContext_ClassTag | | 
 |                     CXCompletionContext_NestedNameSpecifier; | 
 |       } | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_DotMemberAccess: { | 
 |       contexts = CXCompletionContext_DotMemberAccess; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_ArrowMemberAccess: { | 
 |       contexts = CXCompletionContext_ArrowMemberAccess; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_ObjCPropertyAccess: { | 
 |       contexts = CXCompletionContext_ObjCPropertyAccess; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_EnumTag: { | 
 |       contexts = CXCompletionContext_EnumTag | | 
 |                  CXCompletionContext_NestedNameSpecifier; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_UnionTag: { | 
 |       contexts = CXCompletionContext_UnionTag | | 
 |                  CXCompletionContext_NestedNameSpecifier; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_ClassOrStructTag: { | 
 |       contexts = CXCompletionContext_StructTag | | 
 |                  CXCompletionContext_ClassTag | | 
 |                  CXCompletionContext_NestedNameSpecifier; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_ObjCProtocolName: { | 
 |       contexts = CXCompletionContext_ObjCProtocol; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_Namespace: { | 
 |       contexts = CXCompletionContext_Namespace; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_PotentiallyQualifiedName: { | 
 |       contexts = CXCompletionContext_NestedNameSpecifier; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_MacroNameUse: { | 
 |       contexts = CXCompletionContext_MacroName; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_NaturalLanguage: { | 
 |       contexts = CXCompletionContext_NaturalLanguage; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_SelectorName: { | 
 |       contexts = CXCompletionContext_ObjCSelectorName; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_ParenthesizedExpression: { | 
 |       contexts = CXCompletionContext_AnyType | | 
 |                  CXCompletionContext_ObjCInterface | | 
 |                  CXCompletionContext_AnyValue; | 
 |       if (S.getLangOptions().CPlusPlus) { | 
 |         contexts |= CXCompletionContext_EnumTag | | 
 |                     CXCompletionContext_UnionTag | | 
 |                     CXCompletionContext_StructTag | | 
 |                     CXCompletionContext_ClassTag | | 
 |                     CXCompletionContext_NestedNameSpecifier; | 
 |       } | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_ObjCInstanceMessage: { | 
 |       contexts = CXCompletionContext_ObjCInstanceMessage; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_ObjCClassMessage: { | 
 |       contexts = CXCompletionContext_ObjCClassMessage; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_ObjCInterfaceName: { | 
 |       contexts = CXCompletionContext_ObjCInterface; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_ObjCCategoryName: { | 
 |       contexts = CXCompletionContext_ObjCCategory; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_Other: | 
 |     case CodeCompletionContext::CCC_ObjCInterface: | 
 |     case CodeCompletionContext::CCC_ObjCImplementation: | 
 |     case CodeCompletionContext::CCC_Name: | 
 |     case CodeCompletionContext::CCC_MacroName: | 
 |     case CodeCompletionContext::CCC_PreprocessorExpression: | 
 |     case CodeCompletionContext::CCC_PreprocessorDirective: | 
 |     case CodeCompletionContext::CCC_TypeQualifiers: { | 
 |       //Only Clang results should be accepted, so we'll set all of the other | 
 |       //context bits to 0 (i.e. the empty set) | 
 |       contexts = CXCompletionContext_Unexposed; | 
 |       break; | 
 |     } | 
 |     case CodeCompletionContext::CCC_Recovery: { | 
 |       //We don't know what the current context is, so we'll return unknown | 
 |       //This is the equivalent of setting all of the other context bits | 
 |       contexts = CXCompletionContext_Unknown; | 
 |       break; | 
 |     } | 
 |   } | 
 |   return contexts; | 
 | } | 
 |  | 
 | namespace { | 
 |   class CaptureCompletionResults : public CodeCompleteConsumer { | 
 |     AllocatedCXCodeCompleteResults &AllocatedResults; | 
 |     SmallVector<CXCompletionResult, 16> StoredResults; | 
 |     CXTranslationUnit *TU; | 
 |   public: | 
 |     CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results, | 
 |                              CXTranslationUnit *TranslationUnit) | 
 |       : CodeCompleteConsumer(true, false, true, false),  | 
 |         AllocatedResults(Results), TU(TranslationUnit) { } | 
 |     ~CaptureCompletionResults() { Finish(); } | 
 |      | 
 |     virtual void ProcessCodeCompleteResults(Sema &S,  | 
 |                                             CodeCompletionContext Context, | 
 |                                             CodeCompletionResult *Results, | 
 |                                             unsigned NumResults) { | 
 |       StoredResults.reserve(StoredResults.size() + NumResults); | 
 |       for (unsigned I = 0; I != NumResults; ++I) { | 
 |         CodeCompletionString *StoredCompletion         | 
 |           = Results[I].CreateCodeCompletionString(S,  | 
 |                                       AllocatedResults.CodeCompletionAllocator); | 
 |          | 
 |         CXCompletionResult R; | 
 |         R.CursorKind = Results[I].CursorKind; | 
 |         R.CompletionString = StoredCompletion; | 
 |         StoredResults.push_back(R); | 
 |       } | 
 |        | 
 |       enum CodeCompletionContext::Kind contextKind = Context.getKind(); | 
 |        | 
 |       AllocatedResults.ContextKind = contextKind; | 
 |       AllocatedResults.Contexts = getContextsForContextKind(contextKind, S); | 
 |        | 
 |       AllocatedResults.Selector = ""; | 
 |       if (Context.getNumSelIdents() > 0) { | 
 |         for (unsigned i = 0; i < Context.getNumSelIdents(); i++) { | 
 |           IdentifierInfo *selIdent = Context.getSelIdents()[i]; | 
 |           if (selIdent != NULL) { | 
 |             StringRef selectorString = Context.getSelIdents()[i]->getName(); | 
 |             AllocatedResults.Selector += selectorString; | 
 |           } | 
 |           AllocatedResults.Selector += ":"; | 
 |         } | 
 |       } | 
 |        | 
 |       QualType baseType = Context.getBaseType(); | 
 |       NamedDecl *D = NULL; | 
 |        | 
 |       if (!baseType.isNull()) { | 
 |         // Get the declaration for a class/struct/union/enum type | 
 |         if (const TagType *Tag = baseType->getAs<TagType>()) | 
 |           D = Tag->getDecl(); | 
 |         // Get the @interface declaration for a (possibly-qualified) Objective-C | 
 |         // object pointer type, e.g., NSString* | 
 |         else if (const ObjCObjectPointerType *ObjPtr =  | 
 |                  baseType->getAs<ObjCObjectPointerType>()) | 
 |           D = ObjPtr->getInterfaceDecl(); | 
 |         // Get the @interface declaration for an Objective-C object type | 
 |         else if (const ObjCObjectType *Obj = baseType->getAs<ObjCObjectType>()) | 
 |           D = Obj->getInterface(); | 
 |         // Get the class for a C++ injected-class-name | 
 |         else if (const InjectedClassNameType *Injected = | 
 |                  baseType->getAs<InjectedClassNameType>()) | 
 |           D = Injected->getDecl(); | 
 |       } | 
 |        | 
 |       if (D != NULL) { | 
 |         CXCursor cursor = cxcursor::MakeCXCursor(D, *TU); | 
 |          | 
 |         CXCursorKind cursorKind = clang_getCursorKind(cursor); | 
 |         CXString cursorUSR = clang_getCursorUSR(cursor); | 
 |          | 
 |         // Normally, clients of CXString shouldn't care whether or not | 
 |         // a CXString is managed by a pool or by explicitly malloc'ed memory. | 
 |         // However, there are cases when AllocatedResults outlives the | 
 |         // CXTranslationUnit.  This is a workaround that failure mode. | 
 |         if (cxstring::isManagedByPool(cursorUSR)) { | 
 |           CXString heapStr = | 
 |             cxstring::createCXString(clang_getCString(cursorUSR), true); | 
 |           clang_disposeString(cursorUSR); | 
 |           cursorUSR = heapStr; | 
 |         } | 
 |          | 
 |         AllocatedResults.ContainerKind = cursorKind; | 
 |         AllocatedResults.ContainerUSR = cursorUSR; | 
 |          | 
 |         const Type *type = baseType.getTypePtrOrNull(); | 
 |         if (type != NULL) { | 
 |           AllocatedResults.ContainerIsIncomplete = type->isIncompleteType(); | 
 |         } | 
 |         else { | 
 |           AllocatedResults.ContainerIsIncomplete = 1; | 
 |         } | 
 |       } | 
 |       else { | 
 |         AllocatedResults.ContainerKind = CXCursor_InvalidCode; | 
 |         AllocatedResults.ContainerUSR = createCXString(""); | 
 |         AllocatedResults.ContainerIsIncomplete = 1; | 
 |       } | 
 |     } | 
 |      | 
 |     virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, | 
 |                                            OverloadCandidate *Candidates, | 
 |                                            unsigned NumCandidates) { | 
 |       StoredResults.reserve(StoredResults.size() + NumCandidates); | 
 |       for (unsigned I = 0; I != NumCandidates; ++I) { | 
 |         CodeCompletionString *StoredCompletion | 
 |           = Candidates[I].CreateSignatureString(CurrentArg, S,  | 
 |                                       AllocatedResults.CodeCompletionAllocator); | 
 |          | 
 |         CXCompletionResult R; | 
 |         R.CursorKind = CXCursor_NotImplemented; | 
 |         R.CompletionString = StoredCompletion; | 
 |         StoredResults.push_back(R); | 
 |       } | 
 |     } | 
 |      | 
 |     virtual CodeCompletionAllocator &getAllocator() {  | 
 |       return AllocatedResults.CodeCompletionAllocator; | 
 |     } | 
 |      | 
 |   private: | 
 |     void Finish() { | 
 |       AllocatedResults.Results = new CXCompletionResult [StoredResults.size()]; | 
 |       AllocatedResults.NumResults = StoredResults.size(); | 
 |       std::memcpy(AllocatedResults.Results, StoredResults.data(),  | 
 |                   StoredResults.size() * sizeof(CXCompletionResult)); | 
 |       StoredResults.clear(); | 
 |     } | 
 |   }; | 
 | } | 
 |  | 
 | extern "C" { | 
 | struct CodeCompleteAtInfo { | 
 |   CXTranslationUnit TU; | 
 |   const char *complete_filename; | 
 |   unsigned complete_line; | 
 |   unsigned complete_column; | 
 |   struct CXUnsavedFile *unsaved_files; | 
 |   unsigned num_unsaved_files; | 
 |   unsigned options; | 
 |   CXCodeCompleteResults *result; | 
 | }; | 
 | void clang_codeCompleteAt_Impl(void *UserData) { | 
 |   CodeCompleteAtInfo *CCAI = static_cast<CodeCompleteAtInfo*>(UserData); | 
 |   CXTranslationUnit TU = CCAI->TU; | 
 |   const char *complete_filename = CCAI->complete_filename; | 
 |   unsigned complete_line = CCAI->complete_line; | 
 |   unsigned complete_column = CCAI->complete_column; | 
 |   struct CXUnsavedFile *unsaved_files = CCAI->unsaved_files; | 
 |   unsigned num_unsaved_files = CCAI->num_unsaved_files; | 
 |   unsigned options = CCAI->options; | 
 |   CCAI->result = 0; | 
 |  | 
 | #ifdef UDP_CODE_COMPLETION_LOGGER | 
 | #ifdef UDP_CODE_COMPLETION_LOGGER_PORT | 
 |   const llvm::TimeRecord &StartTime =  llvm::TimeRecord::getCurrentTime(); | 
 | #endif | 
 | #endif | 
 |  | 
 |   bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != 0; | 
 |    | 
 |   ASTUnit *AST = static_cast<ASTUnit *>(TU->TUData); | 
 |   if (!AST) | 
 |     return; | 
 |  | 
 |   ASTUnit::ConcurrencyCheck Check(*AST); | 
 |  | 
 |   // Perform the remapping of source files. | 
 |   SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles; | 
 |   for (unsigned I = 0; I != num_unsaved_files; ++I) { | 
 |     StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length); | 
 |     const llvm::MemoryBuffer *Buffer | 
 |       = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename); | 
 |     RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename, | 
 |                                            Buffer)); | 
 |   } | 
 |    | 
 |   if (EnableLogging) { | 
 |     // FIXME: Add logging. | 
 |   } | 
 |  | 
 |   // Parse the resulting source file to find code-completion results. | 
 |   AllocatedCXCodeCompleteResults *Results =  | 
 |         new AllocatedCXCodeCompleteResults(AST->getFileSystemOpts()); | 
 |   Results->Results = 0; | 
 |   Results->NumResults = 0; | 
 |    | 
 |   // Create a code-completion consumer to capture the results. | 
 |   CaptureCompletionResults Capture(*Results, &TU); | 
 |  | 
 |   // Perform completion. | 
 |   AST->CodeComplete(complete_filename, complete_line, complete_column, | 
 |                     RemappedFiles.data(), RemappedFiles.size(),  | 
 |                     (options & CXCodeComplete_IncludeMacros), | 
 |                     (options & CXCodeComplete_IncludeCodePatterns), | 
 |                     Capture, | 
 |                     *Results->Diag, Results->LangOpts, *Results->SourceMgr, | 
 |                     *Results->FileMgr, Results->Diagnostics, | 
 |                     Results->TemporaryBuffers); | 
 |    | 
 |   // Keep a reference to the allocator used for cached global completions, so | 
 |   // that we can be sure that the memory used by our code completion strings | 
 |   // doesn't get freed due to subsequent reparses (while the code completion | 
 |   // results are still active). | 
 |   Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator(); | 
 |  | 
 |    | 
 |  | 
 | #ifdef UDP_CODE_COMPLETION_LOGGER | 
 | #ifdef UDP_CODE_COMPLETION_LOGGER_PORT | 
 |   const llvm::TimeRecord &EndTime =  llvm::TimeRecord::getCurrentTime(); | 
 |   llvm::SmallString<256> LogResult; | 
 |   llvm::raw_svector_ostream os(LogResult); | 
 |  | 
 |   // Figure out the language and whether or not it uses PCH. | 
 |   const char *lang = 0; | 
 |   bool usesPCH = false; | 
 |  | 
 |   for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end(); | 
 |        I != E; ++I) { | 
 |     if (*I == 0) | 
 |       continue; | 
 |     if (strcmp(*I, "-x") == 0) { | 
 |       if (I + 1 != E) { | 
 |         lang = *(++I); | 
 |         continue; | 
 |       } | 
 |     } | 
 |     else if (strcmp(*I, "-include") == 0) { | 
 |       if (I+1 != E) { | 
 |         const char *arg = *(++I); | 
 |         llvm::SmallString<512> pchName; | 
 |         { | 
 |           llvm::raw_svector_ostream os(pchName); | 
 |           os << arg << ".pth"; | 
 |         } | 
 |         pchName.push_back('\0'); | 
 |         struct stat stat_results; | 
 |         if (stat(pchName.str().c_str(), &stat_results) == 0) | 
 |           usesPCH = true; | 
 |         continue; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   os << "{ "; | 
 |   os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime()); | 
 |   os << ", \"numRes\": " << Results->NumResults; | 
 |   os << ", \"diags\": " << Results->Diagnostics.size(); | 
 |   os << ", \"pch\": " << (usesPCH ? "true" : "false"); | 
 |   os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"'; | 
 |   const char *name = getlogin(); | 
 |   os << ", \"user\": \"" << (name ? name : "unknown") << '"'; | 
 |   os << ", \"clangVer\": \"" << getClangFullVersion() << '"'; | 
 |   os << " }"; | 
 |  | 
 |   StringRef res = os.str(); | 
 |   if (res.size() > 0) { | 
 |     do { | 
 |       // Setup the UDP socket. | 
 |       struct sockaddr_in servaddr; | 
 |       bzero(&servaddr, sizeof(servaddr)); | 
 |       servaddr.sin_family = AF_INET; | 
 |       servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT); | 
 |       if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER, | 
 |                     &servaddr.sin_addr) <= 0) | 
 |         break; | 
 |  | 
 |       int sockfd = socket(AF_INET, SOCK_DGRAM, 0); | 
 |       if (sockfd < 0) | 
 |         break; | 
 |  | 
 |       sendto(sockfd, res.data(), res.size(), 0, | 
 |              (struct sockaddr *)&servaddr, sizeof(servaddr)); | 
 |       close(sockfd); | 
 |     } | 
 |     while (false); | 
 |   } | 
 | #endif | 
 | #endif | 
 |   CCAI->result = Results; | 
 | } | 
 | CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU, | 
 |                                             const char *complete_filename, | 
 |                                             unsigned complete_line, | 
 |                                             unsigned complete_column, | 
 |                                             struct CXUnsavedFile *unsaved_files, | 
 |                                             unsigned num_unsaved_files, | 
 |                                             unsigned options) { | 
 |   CodeCompleteAtInfo CCAI = { TU, complete_filename, complete_line, | 
 |                               complete_column, unsaved_files, num_unsaved_files, | 
 |                               options, 0 }; | 
 |   llvm::CrashRecoveryContext CRC; | 
 |  | 
 |   if (!RunSafely(CRC, clang_codeCompleteAt_Impl, &CCAI)) { | 
 |     fprintf(stderr, "libclang: crash detected in code completion\n"); | 
 |     static_cast<ASTUnit *>(TU->TUData)->setUnsafeToFree(true); | 
 |     return 0; | 
 |   } else if (getenv("LIBCLANG_RESOURCE_USAGE")) | 
 |     PrintLibclangResourceUsage(TU); | 
 |  | 
 |   return CCAI.result; | 
 | } | 
 |  | 
 | unsigned clang_defaultCodeCompleteOptions(void) { | 
 |   return CXCodeComplete_IncludeMacros; | 
 | } | 
 |  | 
 | void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) { | 
 |   if (!ResultsIn) | 
 |     return; | 
 |  | 
 |   AllocatedCXCodeCompleteResults *Results | 
 |     = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); | 
 |   delete Results; | 
 | } | 
 |    | 
 | unsigned  | 
 | clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) { | 
 |   AllocatedCXCodeCompleteResults *Results | 
 |     = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); | 
 |   if (!Results) | 
 |     return 0; | 
 |  | 
 |   return Results->Diagnostics.size(); | 
 | } | 
 |  | 
 | CXDiagnostic  | 
 | clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn, | 
 |                                 unsigned Index) { | 
 |   AllocatedCXCodeCompleteResults *Results | 
 |     = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); | 
 |   if (!Results || Index >= Results->Diagnostics.size()) | 
 |     return 0; | 
 |  | 
 |   return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts); | 
 | } | 
 |  | 
 | unsigned long long | 
 | clang_codeCompleteGetContexts(CXCodeCompleteResults *ResultsIn) { | 
 |   AllocatedCXCodeCompleteResults *Results | 
 |     = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); | 
 |   if (!Results) | 
 |     return 0; | 
 |    | 
 |   return Results->Contexts; | 
 | } | 
 |  | 
 | enum CXCursorKind clang_codeCompleteGetContainerKind( | 
 |                                                CXCodeCompleteResults *ResultsIn, | 
 |                                                      unsigned *IsIncomplete) { | 
 |   AllocatedCXCodeCompleteResults *Results = | 
 |     static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn); | 
 |   if (!Results) | 
 |     return CXCursor_InvalidCode; | 
 |    | 
 |   if (IsIncomplete != NULL) { | 
 |     *IsIncomplete = Results->ContainerIsIncomplete; | 
 |   } | 
 |    | 
 |   return Results->ContainerKind; | 
 | } | 
 |    | 
 | CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *ResultsIn) { | 
 |   AllocatedCXCodeCompleteResults *Results = | 
 |     static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn); | 
 |   if (!Results) | 
 |     return createCXString(""); | 
 |    | 
 |   return createCXString(clang_getCString(Results->ContainerUSR)); | 
 | } | 
 |  | 
 |    | 
 | CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *ResultsIn) { | 
 |   AllocatedCXCodeCompleteResults *Results = | 
 |     static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn); | 
 |   if (!Results) | 
 |     return createCXString(""); | 
 |    | 
 |   return createCXString(Results->Selector); | 
 | } | 
 |    | 
 | } // end extern "C" | 
 |  | 
 | /// \brief Simple utility function that appends a \p New string to the given | 
 | /// \p Old string, using the \p Buffer for storage. | 
 | /// | 
 | /// \param Old The string to which we are appending. This parameter will be | 
 | /// updated to reflect the complete string. | 
 | /// | 
 | /// | 
 | /// \param New The string to append to \p Old. | 
 | /// | 
 | /// \param Buffer A buffer that stores the actual, concatenated string. It will | 
 | /// be used if the old string is already-non-empty. | 
 | static void AppendToString(StringRef &Old, StringRef New, | 
 |                            llvm::SmallString<256> &Buffer) { | 
 |   if (Old.empty()) { | 
 |     Old = New; | 
 |     return; | 
 |   } | 
 |    | 
 |   if (Buffer.empty()) | 
 |     Buffer.append(Old.begin(), Old.end()); | 
 |   Buffer.append(New.begin(), New.end()); | 
 |   Old = Buffer.str(); | 
 | } | 
 |  | 
 | /// \brief Get the typed-text blocks from the given code-completion string | 
 | /// and return them as a single string. | 
 | /// | 
 | /// \param String The code-completion string whose typed-text blocks will be | 
 | /// concatenated. | 
 | /// | 
 | /// \param Buffer A buffer used for storage of the completed name. | 
 | static StringRef GetTypedName(CodeCompletionString *String, | 
 |                                     llvm::SmallString<256> &Buffer) { | 
 |   StringRef Result; | 
 |   for (CodeCompletionString::iterator C = String->begin(), CEnd = String->end(); | 
 |        C != CEnd; ++C) { | 
 |     if (C->Kind == CodeCompletionString::CK_TypedText) | 
 |       AppendToString(Result, C->Text, Buffer); | 
 |   } | 
 |    | 
 |   return Result; | 
 | } | 
 |  | 
 | namespace { | 
 |   struct OrderCompletionResults { | 
 |     bool operator()(const CXCompletionResult &XR,  | 
 |                     const CXCompletionResult &YR) const { | 
 |       CodeCompletionString *X | 
 |         = (CodeCompletionString *)XR.CompletionString; | 
 |       CodeCompletionString *Y | 
 |         = (CodeCompletionString *)YR.CompletionString; | 
 |        | 
 |       llvm::SmallString<256> XBuffer; | 
 |       StringRef XText = GetTypedName(X, XBuffer); | 
 |       llvm::SmallString<256> YBuffer;       | 
 |       StringRef YText = GetTypedName(Y, YBuffer); | 
 |        | 
 |       if (XText.empty() || YText.empty()) | 
 |         return !XText.empty(); | 
 |              | 
 |       int result = XText.compare_lower(YText); | 
 |       if (result < 0) | 
 |         return true; | 
 |       if (result > 0) | 
 |         return false; | 
 |        | 
 |       result = XText.compare(YText); | 
 |       return result < 0; | 
 |     } | 
 |   }; | 
 | } | 
 |  | 
 | extern "C" { | 
 |   void clang_sortCodeCompletionResults(CXCompletionResult *Results, | 
 |                                        unsigned NumResults) { | 
 |     std::stable_sort(Results, Results + NumResults, OrderCompletionResults()); | 
 |   } | 
 | } |