1*d5a2a073SDaniel Dunbar //===- CIndexCodeCompletion.cpp - Code Completion API hooks ---------------===// 2*d5a2a073SDaniel Dunbar // 3*d5a2a073SDaniel Dunbar // The LLVM Compiler Infrastructure 4*d5a2a073SDaniel Dunbar // 5*d5a2a073SDaniel Dunbar // This file is distributed under the University of Illinois Open Source 6*d5a2a073SDaniel Dunbar // License. See LICENSE.TXT for details. 7*d5a2a073SDaniel Dunbar // 8*d5a2a073SDaniel Dunbar //===----------------------------------------------------------------------===// 9*d5a2a073SDaniel Dunbar // 10*d5a2a073SDaniel Dunbar // This file implements the Clang-C Source Indexing library hooks for 11*d5a2a073SDaniel Dunbar // code completion. 12*d5a2a073SDaniel Dunbar // 13*d5a2a073SDaniel Dunbar //===----------------------------------------------------------------------===// 14*d5a2a073SDaniel Dunbar 15*d5a2a073SDaniel Dunbar #include "CIndexer.h" 16*d5a2a073SDaniel Dunbar #include "CIndexDiagnostic.h" 17*d5a2a073SDaniel Dunbar #include "clang/Basic/SourceManager.h" 18*d5a2a073SDaniel Dunbar #include "clang/Basic/FileManager.h" 19*d5a2a073SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h" 20*d5a2a073SDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h" 21*d5a2a073SDaniel Dunbar #include "clang/Sema/CodeCompleteConsumer.h" 22*d5a2a073SDaniel Dunbar #include "llvm/ADT/StringExtras.h" 23*d5a2a073SDaniel Dunbar #include "llvm/Support/MemoryBuffer.h" 24*d5a2a073SDaniel Dunbar #include "llvm/System/Program.h" 25*d5a2a073SDaniel Dunbar 26*d5a2a073SDaniel Dunbar #ifdef UDP_CODE_COMPLETION_LOGGER 27*d5a2a073SDaniel Dunbar #include "clang/Basic/Version.h" 28*d5a2a073SDaniel Dunbar #include "llvm/ADT/SmallString.h" 29*d5a2a073SDaniel Dunbar #include "llvm/Support/Timer.h" 30*d5a2a073SDaniel Dunbar #include "llvm/Support/raw_ostream.h" 31*d5a2a073SDaniel Dunbar #include <arpa/inet.h> 32*d5a2a073SDaniel Dunbar #include <sys/socket.h> 33*d5a2a073SDaniel Dunbar #include <sys/types.h> 34*d5a2a073SDaniel Dunbar #include <unistd.h> 35*d5a2a073SDaniel Dunbar #endif 36*d5a2a073SDaniel Dunbar 37*d5a2a073SDaniel Dunbar using namespace clang; 38*d5a2a073SDaniel Dunbar using namespace clang::cxstring; 39*d5a2a073SDaniel Dunbar 40*d5a2a073SDaniel Dunbar extern "C" { 41*d5a2a073SDaniel Dunbar 42*d5a2a073SDaniel Dunbar enum CXCompletionChunkKind 43*d5a2a073SDaniel Dunbar clang_getCompletionChunkKind(CXCompletionString completion_string, 44*d5a2a073SDaniel Dunbar unsigned chunk_number) { 45*d5a2a073SDaniel Dunbar CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; 46*d5a2a073SDaniel Dunbar if (!CCStr || chunk_number >= CCStr->size()) 47*d5a2a073SDaniel Dunbar return CXCompletionChunk_Text; 48*d5a2a073SDaniel Dunbar 49*d5a2a073SDaniel Dunbar switch ((*CCStr)[chunk_number].Kind) { 50*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_TypedText: 51*d5a2a073SDaniel Dunbar return CXCompletionChunk_TypedText; 52*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Text: 53*d5a2a073SDaniel Dunbar return CXCompletionChunk_Text; 54*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Optional: 55*d5a2a073SDaniel Dunbar return CXCompletionChunk_Optional; 56*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Placeholder: 57*d5a2a073SDaniel Dunbar return CXCompletionChunk_Placeholder; 58*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Informative: 59*d5a2a073SDaniel Dunbar return CXCompletionChunk_Informative; 60*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_ResultType: 61*d5a2a073SDaniel Dunbar return CXCompletionChunk_ResultType; 62*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_CurrentParameter: 63*d5a2a073SDaniel Dunbar return CXCompletionChunk_CurrentParameter; 64*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftParen: 65*d5a2a073SDaniel Dunbar return CXCompletionChunk_LeftParen; 66*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightParen: 67*d5a2a073SDaniel Dunbar return CXCompletionChunk_RightParen; 68*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftBracket: 69*d5a2a073SDaniel Dunbar return CXCompletionChunk_LeftBracket; 70*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightBracket: 71*d5a2a073SDaniel Dunbar return CXCompletionChunk_RightBracket; 72*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftBrace: 73*d5a2a073SDaniel Dunbar return CXCompletionChunk_LeftBrace; 74*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightBrace: 75*d5a2a073SDaniel Dunbar return CXCompletionChunk_RightBrace; 76*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftAngle: 77*d5a2a073SDaniel Dunbar return CXCompletionChunk_LeftAngle; 78*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightAngle: 79*d5a2a073SDaniel Dunbar return CXCompletionChunk_RightAngle; 80*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Comma: 81*d5a2a073SDaniel Dunbar return CXCompletionChunk_Comma; 82*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Colon: 83*d5a2a073SDaniel Dunbar return CXCompletionChunk_Colon; 84*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_SemiColon: 85*d5a2a073SDaniel Dunbar return CXCompletionChunk_SemiColon; 86*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Equal: 87*d5a2a073SDaniel Dunbar return CXCompletionChunk_Equal; 88*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_HorizontalSpace: 89*d5a2a073SDaniel Dunbar return CXCompletionChunk_HorizontalSpace; 90*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_VerticalSpace: 91*d5a2a073SDaniel Dunbar return CXCompletionChunk_VerticalSpace; 92*d5a2a073SDaniel Dunbar } 93*d5a2a073SDaniel Dunbar 94*d5a2a073SDaniel Dunbar // Should be unreachable, but let's be careful. 95*d5a2a073SDaniel Dunbar return CXCompletionChunk_Text; 96*d5a2a073SDaniel Dunbar } 97*d5a2a073SDaniel Dunbar 98*d5a2a073SDaniel Dunbar CXString clang_getCompletionChunkText(CXCompletionString completion_string, 99*d5a2a073SDaniel Dunbar unsigned chunk_number) { 100*d5a2a073SDaniel Dunbar CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; 101*d5a2a073SDaniel Dunbar if (!CCStr || chunk_number >= CCStr->size()) 102*d5a2a073SDaniel Dunbar return createCXString(0); 103*d5a2a073SDaniel Dunbar 104*d5a2a073SDaniel Dunbar switch ((*CCStr)[chunk_number].Kind) { 105*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_TypedText: 106*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Text: 107*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Placeholder: 108*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_CurrentParameter: 109*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Informative: 110*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftParen: 111*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightParen: 112*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftBracket: 113*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightBracket: 114*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftBrace: 115*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightBrace: 116*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftAngle: 117*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightAngle: 118*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Comma: 119*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_ResultType: 120*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Colon: 121*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_SemiColon: 122*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Equal: 123*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_HorizontalSpace: 124*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_VerticalSpace: 125*d5a2a073SDaniel Dunbar return createCXString((*CCStr)[chunk_number].Text, false); 126*d5a2a073SDaniel Dunbar 127*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Optional: 128*d5a2a073SDaniel Dunbar // Note: treated as an empty text block. 129*d5a2a073SDaniel Dunbar return createCXString(""); 130*d5a2a073SDaniel Dunbar } 131*d5a2a073SDaniel Dunbar 132*d5a2a073SDaniel Dunbar // Should be unreachable, but let's be careful. 133*d5a2a073SDaniel Dunbar return createCXString(0); 134*d5a2a073SDaniel Dunbar } 135*d5a2a073SDaniel Dunbar 136*d5a2a073SDaniel Dunbar 137*d5a2a073SDaniel Dunbar CXCompletionString 138*d5a2a073SDaniel Dunbar clang_getCompletionChunkCompletionString(CXCompletionString completion_string, 139*d5a2a073SDaniel Dunbar unsigned chunk_number) { 140*d5a2a073SDaniel Dunbar CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; 141*d5a2a073SDaniel Dunbar if (!CCStr || chunk_number >= CCStr->size()) 142*d5a2a073SDaniel Dunbar return 0; 143*d5a2a073SDaniel Dunbar 144*d5a2a073SDaniel Dunbar switch ((*CCStr)[chunk_number].Kind) { 145*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_TypedText: 146*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Text: 147*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Placeholder: 148*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_CurrentParameter: 149*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Informative: 150*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftParen: 151*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightParen: 152*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftBracket: 153*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightBracket: 154*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftBrace: 155*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightBrace: 156*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_LeftAngle: 157*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_RightAngle: 158*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Comma: 159*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_ResultType: 160*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Colon: 161*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_SemiColon: 162*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Equal: 163*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_HorizontalSpace: 164*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_VerticalSpace: 165*d5a2a073SDaniel Dunbar return 0; 166*d5a2a073SDaniel Dunbar 167*d5a2a073SDaniel Dunbar case CodeCompletionString::CK_Optional: 168*d5a2a073SDaniel Dunbar // Note: treated as an empty text block. 169*d5a2a073SDaniel Dunbar return (*CCStr)[chunk_number].Optional; 170*d5a2a073SDaniel Dunbar } 171*d5a2a073SDaniel Dunbar 172*d5a2a073SDaniel Dunbar // Should be unreachable, but let's be careful. 173*d5a2a073SDaniel Dunbar return 0; 174*d5a2a073SDaniel Dunbar } 175*d5a2a073SDaniel Dunbar 176*d5a2a073SDaniel Dunbar unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) { 177*d5a2a073SDaniel Dunbar CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; 178*d5a2a073SDaniel Dunbar return CCStr? CCStr->size() : 0; 179*d5a2a073SDaniel Dunbar } 180*d5a2a073SDaniel Dunbar 181*d5a2a073SDaniel Dunbar static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd, 182*d5a2a073SDaniel Dunbar unsigned &Value) { 183*d5a2a073SDaniel Dunbar if (Memory + sizeof(unsigned) > MemoryEnd) 184*d5a2a073SDaniel Dunbar return true; 185*d5a2a073SDaniel Dunbar 186*d5a2a073SDaniel Dunbar memmove(&Value, Memory, sizeof(unsigned)); 187*d5a2a073SDaniel Dunbar Memory += sizeof(unsigned); 188*d5a2a073SDaniel Dunbar return false; 189*d5a2a073SDaniel Dunbar } 190*d5a2a073SDaniel Dunbar 191*d5a2a073SDaniel Dunbar /// \brief The CXCodeCompleteResults structure we allocate internally; 192*d5a2a073SDaniel Dunbar /// the client only sees the initial CXCodeCompleteResults structure. 193*d5a2a073SDaniel Dunbar struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { 194*d5a2a073SDaniel Dunbar AllocatedCXCodeCompleteResults(); 195*d5a2a073SDaniel Dunbar ~AllocatedCXCodeCompleteResults(); 196*d5a2a073SDaniel Dunbar 197*d5a2a073SDaniel Dunbar /// \brief The memory buffer from which we parsed the results. We 198*d5a2a073SDaniel Dunbar /// retain this buffer because the completion strings point into it. 199*d5a2a073SDaniel Dunbar llvm::MemoryBuffer *Buffer; 200*d5a2a073SDaniel Dunbar 201*d5a2a073SDaniel Dunbar /// \brief Diagnostics produced while performing code completion. 202*d5a2a073SDaniel Dunbar llvm::SmallVector<StoredDiagnostic, 8> Diagnostics; 203*d5a2a073SDaniel Dunbar 204*d5a2a073SDaniel Dunbar /// \brief Diag object 205*d5a2a073SDaniel Dunbar Diagnostic Diag; 206*d5a2a073SDaniel Dunbar 207*d5a2a073SDaniel Dunbar /// \brief Language options used to adjust source locations. 208*d5a2a073SDaniel Dunbar LangOptions LangOpts; 209*d5a2a073SDaniel Dunbar 210*d5a2a073SDaniel Dunbar /// \brief Source manager, used for diagnostics. 211*d5a2a073SDaniel Dunbar SourceManager SourceMgr; 212*d5a2a073SDaniel Dunbar 213*d5a2a073SDaniel Dunbar /// \brief File manager, used for diagnostics. 214*d5a2a073SDaniel Dunbar FileManager FileMgr; 215*d5a2a073SDaniel Dunbar 216*d5a2a073SDaniel Dunbar /// \brief Temporary files that should be removed once we have finished 217*d5a2a073SDaniel Dunbar /// with the code-completion results. 218*d5a2a073SDaniel Dunbar std::vector<llvm::sys::Path> TemporaryFiles; 219*d5a2a073SDaniel Dunbar }; 220*d5a2a073SDaniel Dunbar 221*d5a2a073SDaniel Dunbar AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults() 222*d5a2a073SDaniel Dunbar : CXCodeCompleteResults(), Buffer(0), SourceMgr(Diag) { } 223*d5a2a073SDaniel Dunbar 224*d5a2a073SDaniel Dunbar AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() { 225*d5a2a073SDaniel Dunbar for (unsigned I = 0, N = NumResults; I != N; ++I) 226*d5a2a073SDaniel Dunbar delete (CodeCompletionString *)Results[I].CompletionString; 227*d5a2a073SDaniel Dunbar delete [] Results; 228*d5a2a073SDaniel Dunbar delete Buffer; 229*d5a2a073SDaniel Dunbar 230*d5a2a073SDaniel Dunbar for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) 231*d5a2a073SDaniel Dunbar TemporaryFiles[I].eraseFromDisk(); 232*d5a2a073SDaniel Dunbar } 233*d5a2a073SDaniel Dunbar 234*d5a2a073SDaniel Dunbar CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, 235*d5a2a073SDaniel Dunbar const char *source_filename, 236*d5a2a073SDaniel Dunbar int num_command_line_args, 237*d5a2a073SDaniel Dunbar const char **command_line_args, 238*d5a2a073SDaniel Dunbar unsigned num_unsaved_files, 239*d5a2a073SDaniel Dunbar struct CXUnsavedFile *unsaved_files, 240*d5a2a073SDaniel Dunbar const char *complete_filename, 241*d5a2a073SDaniel Dunbar unsigned complete_line, 242*d5a2a073SDaniel Dunbar unsigned complete_column) { 243*d5a2a073SDaniel Dunbar #ifdef UDP_CODE_COMPLETION_LOGGER 244*d5a2a073SDaniel Dunbar #ifdef UDP_CODE_COMPLETION_LOGGER_PORT 245*d5a2a073SDaniel Dunbar const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime(); 246*d5a2a073SDaniel Dunbar #endif 247*d5a2a073SDaniel Dunbar #endif 248*d5a2a073SDaniel Dunbar 249*d5a2a073SDaniel Dunbar // The indexer, which is mainly used to determine where diagnostics go. 250*d5a2a073SDaniel Dunbar CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); 251*d5a2a073SDaniel Dunbar 252*d5a2a073SDaniel Dunbar // Configure the diagnostics. 253*d5a2a073SDaniel Dunbar DiagnosticOptions DiagOpts; 254*d5a2a073SDaniel Dunbar llvm::IntrusiveRefCntPtr<Diagnostic> Diags; 255*d5a2a073SDaniel Dunbar Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0); 256*d5a2a073SDaniel Dunbar 257*d5a2a073SDaniel Dunbar // The set of temporary files that we've built. 258*d5a2a073SDaniel Dunbar std::vector<llvm::sys::Path> TemporaryFiles; 259*d5a2a073SDaniel Dunbar 260*d5a2a073SDaniel Dunbar // Build up the arguments for invoking 'clang'. 261*d5a2a073SDaniel Dunbar std::vector<const char *> argv; 262*d5a2a073SDaniel Dunbar 263*d5a2a073SDaniel Dunbar // First add the complete path to the 'clang' executable. 264*d5a2a073SDaniel Dunbar llvm::sys::Path ClangPath = CXXIdx->getClangPath(); 265*d5a2a073SDaniel Dunbar argv.push_back(ClangPath.c_str()); 266*d5a2a073SDaniel Dunbar 267*d5a2a073SDaniel Dunbar // Add the '-fsyntax-only' argument so that we only perform a basic 268*d5a2a073SDaniel Dunbar // syntax check of the code. 269*d5a2a073SDaniel Dunbar argv.push_back("-fsyntax-only"); 270*d5a2a073SDaniel Dunbar 271*d5a2a073SDaniel Dunbar // Add the appropriate '-code-completion-at=file:line:column' argument 272*d5a2a073SDaniel Dunbar // to perform code completion, with an "-Xclang" preceding it. 273*d5a2a073SDaniel Dunbar std::string code_complete_at; 274*d5a2a073SDaniel Dunbar code_complete_at += complete_filename; 275*d5a2a073SDaniel Dunbar code_complete_at += ":"; 276*d5a2a073SDaniel Dunbar code_complete_at += llvm::utostr(complete_line); 277*d5a2a073SDaniel Dunbar code_complete_at += ":"; 278*d5a2a073SDaniel Dunbar code_complete_at += llvm::utostr(complete_column); 279*d5a2a073SDaniel Dunbar argv.push_back("-Xclang"); 280*d5a2a073SDaniel Dunbar argv.push_back("-code-completion-at"); 281*d5a2a073SDaniel Dunbar argv.push_back("-Xclang"); 282*d5a2a073SDaniel Dunbar argv.push_back(code_complete_at.c_str()); 283*d5a2a073SDaniel Dunbar argv.push_back("-Xclang"); 284*d5a2a073SDaniel Dunbar argv.push_back("-no-code-completion-debug-printer"); 285*d5a2a073SDaniel Dunbar argv.push_back("-Xclang"); 286*d5a2a073SDaniel Dunbar argv.push_back("-code-completion-macros"); 287*d5a2a073SDaniel Dunbar argv.push_back("-fdiagnostics-binary"); 288*d5a2a073SDaniel Dunbar 289*d5a2a073SDaniel Dunbar // Remap any unsaved files to temporary files. 290*d5a2a073SDaniel Dunbar std::vector<std::string> RemapArgs; 291*d5a2a073SDaniel Dunbar if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles)) 292*d5a2a073SDaniel Dunbar return 0; 293*d5a2a073SDaniel Dunbar 294*d5a2a073SDaniel Dunbar // The pointers into the elements of RemapArgs are stable because we 295*d5a2a073SDaniel Dunbar // won't be adding anything to RemapArgs after this point. 296*d5a2a073SDaniel Dunbar for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i) 297*d5a2a073SDaniel Dunbar argv.push_back(RemapArgs[i].c_str()); 298*d5a2a073SDaniel Dunbar 299*d5a2a073SDaniel Dunbar // Add the source file name (FIXME: later, we'll want to build temporary 300*d5a2a073SDaniel Dunbar // file from the buffer, or just feed the source text via standard input). 301*d5a2a073SDaniel Dunbar if (source_filename) 302*d5a2a073SDaniel Dunbar argv.push_back(source_filename); 303*d5a2a073SDaniel Dunbar 304*d5a2a073SDaniel Dunbar // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'. 305*d5a2a073SDaniel Dunbar for (int i = 0; i < num_command_line_args; ++i) 306*d5a2a073SDaniel Dunbar if (const char *arg = command_line_args[i]) { 307*d5a2a073SDaniel Dunbar if (strcmp(arg, "-o") == 0) { 308*d5a2a073SDaniel Dunbar ++i; // Also skip the matching argument. 309*d5a2a073SDaniel Dunbar continue; 310*d5a2a073SDaniel Dunbar } 311*d5a2a073SDaniel Dunbar if (strcmp(arg, "-emit-ast") == 0 || 312*d5a2a073SDaniel Dunbar strcmp(arg, "-c") == 0 || 313*d5a2a073SDaniel Dunbar strcmp(arg, "-fsyntax-only") == 0) { 314*d5a2a073SDaniel Dunbar continue; 315*d5a2a073SDaniel Dunbar } 316*d5a2a073SDaniel Dunbar 317*d5a2a073SDaniel Dunbar // Keep the argument. 318*d5a2a073SDaniel Dunbar argv.push_back(arg); 319*d5a2a073SDaniel Dunbar } 320*d5a2a073SDaniel Dunbar 321*d5a2a073SDaniel Dunbar // Add the null terminator. 322*d5a2a073SDaniel Dunbar argv.push_back(NULL); 323*d5a2a073SDaniel Dunbar 324*d5a2a073SDaniel Dunbar // Generate a temporary name for the code-completion results file. 325*d5a2a073SDaniel Dunbar char tmpFile[L_tmpnam]; 326*d5a2a073SDaniel Dunbar char *tmpFileName = tmpnam(tmpFile); 327*d5a2a073SDaniel Dunbar llvm::sys::Path ResultsFile(tmpFileName); 328*d5a2a073SDaniel Dunbar TemporaryFiles.push_back(ResultsFile); 329*d5a2a073SDaniel Dunbar 330*d5a2a073SDaniel Dunbar // Generate a temporary name for the diagnostics file. 331*d5a2a073SDaniel Dunbar char tmpFileResults[L_tmpnam]; 332*d5a2a073SDaniel Dunbar char *tmpResultsFileName = tmpnam(tmpFileResults); 333*d5a2a073SDaniel Dunbar llvm::sys::Path DiagnosticsFile(tmpResultsFileName); 334*d5a2a073SDaniel Dunbar TemporaryFiles.push_back(DiagnosticsFile); 335*d5a2a073SDaniel Dunbar 336*d5a2a073SDaniel Dunbar // Invoke 'clang'. 337*d5a2a073SDaniel Dunbar llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null 338*d5a2a073SDaniel Dunbar // on Unix or NUL (Windows). 339*d5a2a073SDaniel Dunbar std::string ErrMsg; 340*d5a2a073SDaniel Dunbar const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile, 341*d5a2a073SDaniel Dunbar &DiagnosticsFile, 0 }; 342*d5a2a073SDaniel Dunbar llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL, 343*d5a2a073SDaniel Dunbar /* redirects */ &Redirects[0], 344*d5a2a073SDaniel Dunbar /* secondsToWait */ 0, 345*d5a2a073SDaniel Dunbar /* memoryLimits */ 0, &ErrMsg); 346*d5a2a073SDaniel Dunbar 347*d5a2a073SDaniel Dunbar if (!ErrMsg.empty()) { 348*d5a2a073SDaniel Dunbar std::string AllArgs; 349*d5a2a073SDaniel Dunbar for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end(); 350*d5a2a073SDaniel Dunbar I != E; ++I) { 351*d5a2a073SDaniel Dunbar AllArgs += ' '; 352*d5a2a073SDaniel Dunbar if (*I) 353*d5a2a073SDaniel Dunbar AllArgs += *I; 354*d5a2a073SDaniel Dunbar } 355*d5a2a073SDaniel Dunbar 356*d5a2a073SDaniel Dunbar Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg; 357*d5a2a073SDaniel Dunbar } 358*d5a2a073SDaniel Dunbar 359*d5a2a073SDaniel Dunbar // Parse the resulting source file to find code-completion results. 360*d5a2a073SDaniel Dunbar using llvm::MemoryBuffer; 361*d5a2a073SDaniel Dunbar using llvm::StringRef; 362*d5a2a073SDaniel Dunbar AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults; 363*d5a2a073SDaniel Dunbar Results->Results = 0; 364*d5a2a073SDaniel Dunbar Results->NumResults = 0; 365*d5a2a073SDaniel Dunbar Results->Buffer = 0; 366*d5a2a073SDaniel Dunbar // FIXME: Set Results->LangOpts! 367*d5a2a073SDaniel Dunbar if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) { 368*d5a2a073SDaniel Dunbar llvm::SmallVector<CXCompletionResult, 4> CompletionResults; 369*d5a2a073SDaniel Dunbar StringRef Buffer = F->getBuffer(); 370*d5a2a073SDaniel Dunbar for (const char *Str = Buffer.data(), *StrEnd = Str + Buffer.size(); 371*d5a2a073SDaniel Dunbar Str < StrEnd;) { 372*d5a2a073SDaniel Dunbar unsigned KindValue; 373*d5a2a073SDaniel Dunbar if (ReadUnsigned(Str, StrEnd, KindValue)) 374*d5a2a073SDaniel Dunbar break; 375*d5a2a073SDaniel Dunbar 376*d5a2a073SDaniel Dunbar CodeCompletionString *CCStr 377*d5a2a073SDaniel Dunbar = CodeCompletionString::Deserialize(Str, StrEnd); 378*d5a2a073SDaniel Dunbar if (!CCStr) 379*d5a2a073SDaniel Dunbar continue; 380*d5a2a073SDaniel Dunbar 381*d5a2a073SDaniel Dunbar if (!CCStr->empty()) { 382*d5a2a073SDaniel Dunbar // Vend the code-completion result to the caller. 383*d5a2a073SDaniel Dunbar CXCompletionResult Result; 384*d5a2a073SDaniel Dunbar Result.CursorKind = (CXCursorKind)KindValue; 385*d5a2a073SDaniel Dunbar Result.CompletionString = CCStr; 386*d5a2a073SDaniel Dunbar CompletionResults.push_back(Result); 387*d5a2a073SDaniel Dunbar } 388*d5a2a073SDaniel Dunbar }; 389*d5a2a073SDaniel Dunbar 390*d5a2a073SDaniel Dunbar // Allocate the results. 391*d5a2a073SDaniel Dunbar Results->Results = new CXCompletionResult [CompletionResults.size()]; 392*d5a2a073SDaniel Dunbar Results->NumResults = CompletionResults.size(); 393*d5a2a073SDaniel Dunbar memcpy(Results->Results, CompletionResults.data(), 394*d5a2a073SDaniel Dunbar CompletionResults.size() * sizeof(CXCompletionResult)); 395*d5a2a073SDaniel Dunbar Results->Buffer = F; 396*d5a2a073SDaniel Dunbar } 397*d5a2a073SDaniel Dunbar 398*d5a2a073SDaniel Dunbar LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files, 399*d5a2a073SDaniel Dunbar Results->FileMgr, Results->SourceMgr, 400*d5a2a073SDaniel Dunbar Results->Diagnostics); 401*d5a2a073SDaniel Dunbar 402*d5a2a073SDaniel Dunbar // Make sure we delete temporary files when the code-completion results are 403*d5a2a073SDaniel Dunbar // destroyed. 404*d5a2a073SDaniel Dunbar Results->TemporaryFiles.swap(TemporaryFiles); 405*d5a2a073SDaniel Dunbar 406*d5a2a073SDaniel Dunbar #ifdef UDP_CODE_COMPLETION_LOGGER 407*d5a2a073SDaniel Dunbar #ifdef UDP_CODE_COMPLETION_LOGGER_PORT 408*d5a2a073SDaniel Dunbar const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime(); 409*d5a2a073SDaniel Dunbar llvm::SmallString<256> LogResult; 410*d5a2a073SDaniel Dunbar llvm::raw_svector_ostream os(LogResult); 411*d5a2a073SDaniel Dunbar 412*d5a2a073SDaniel Dunbar // Figure out the language and whether or not it uses PCH. 413*d5a2a073SDaniel Dunbar const char *lang = 0; 414*d5a2a073SDaniel Dunbar bool usesPCH = false; 415*d5a2a073SDaniel Dunbar 416*d5a2a073SDaniel Dunbar for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end(); 417*d5a2a073SDaniel Dunbar I != E; ++I) { 418*d5a2a073SDaniel Dunbar if (*I == 0) 419*d5a2a073SDaniel Dunbar continue; 420*d5a2a073SDaniel Dunbar if (strcmp(*I, "-x") == 0) { 421*d5a2a073SDaniel Dunbar if (I + 1 != E) { 422*d5a2a073SDaniel Dunbar lang = *(++I); 423*d5a2a073SDaniel Dunbar continue; 424*d5a2a073SDaniel Dunbar } 425*d5a2a073SDaniel Dunbar } 426*d5a2a073SDaniel Dunbar else if (strcmp(*I, "-include") == 0) { 427*d5a2a073SDaniel Dunbar if (I+1 != E) { 428*d5a2a073SDaniel Dunbar const char *arg = *(++I); 429*d5a2a073SDaniel Dunbar llvm::SmallString<512> pchName; 430*d5a2a073SDaniel Dunbar { 431*d5a2a073SDaniel Dunbar llvm::raw_svector_ostream os(pchName); 432*d5a2a073SDaniel Dunbar os << arg << ".pth"; 433*d5a2a073SDaniel Dunbar } 434*d5a2a073SDaniel Dunbar pchName.push_back('\0'); 435*d5a2a073SDaniel Dunbar struct stat stat_results; 436*d5a2a073SDaniel Dunbar if (stat(pchName.data(), &stat_results) == 0) 437*d5a2a073SDaniel Dunbar usesPCH = true; 438*d5a2a073SDaniel Dunbar continue; 439*d5a2a073SDaniel Dunbar } 440*d5a2a073SDaniel Dunbar } 441*d5a2a073SDaniel Dunbar } 442*d5a2a073SDaniel Dunbar 443*d5a2a073SDaniel Dunbar os << "{ "; 444*d5a2a073SDaniel Dunbar os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime()); 445*d5a2a073SDaniel Dunbar os << ", \"numRes\": " << Results->NumResults; 446*d5a2a073SDaniel Dunbar os << ", \"diags\": " << Results->Diagnostics.size(); 447*d5a2a073SDaniel Dunbar os << ", \"pch\": " << (usesPCH ? "true" : "false"); 448*d5a2a073SDaniel Dunbar os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"'; 449*d5a2a073SDaniel Dunbar const char *name = getlogin(); 450*d5a2a073SDaniel Dunbar os << ", \"user\": \"" << (name ? name : "unknown") << '"'; 451*d5a2a073SDaniel Dunbar os << ", \"clangVer\": \"" << getClangFullVersion() << '"'; 452*d5a2a073SDaniel Dunbar os << " }"; 453*d5a2a073SDaniel Dunbar 454*d5a2a073SDaniel Dunbar llvm::StringRef res = os.str(); 455*d5a2a073SDaniel Dunbar if (res.size() > 0) { 456*d5a2a073SDaniel Dunbar do { 457*d5a2a073SDaniel Dunbar // Setup the UDP socket. 458*d5a2a073SDaniel Dunbar struct sockaddr_in servaddr; 459*d5a2a073SDaniel Dunbar bzero(&servaddr, sizeof(servaddr)); 460*d5a2a073SDaniel Dunbar servaddr.sin_family = AF_INET; 461*d5a2a073SDaniel Dunbar servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT); 462*d5a2a073SDaniel Dunbar if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER, 463*d5a2a073SDaniel Dunbar &servaddr.sin_addr) <= 0) 464*d5a2a073SDaniel Dunbar break; 465*d5a2a073SDaniel Dunbar 466*d5a2a073SDaniel Dunbar int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 467*d5a2a073SDaniel Dunbar if (sockfd < 0) 468*d5a2a073SDaniel Dunbar break; 469*d5a2a073SDaniel Dunbar 470*d5a2a073SDaniel Dunbar sendto(sockfd, res.data(), res.size(), 0, 471*d5a2a073SDaniel Dunbar (struct sockaddr *)&servaddr, sizeof(servaddr)); 472*d5a2a073SDaniel Dunbar close(sockfd); 473*d5a2a073SDaniel Dunbar } 474*d5a2a073SDaniel Dunbar while (false); 475*d5a2a073SDaniel Dunbar } 476*d5a2a073SDaniel Dunbar #endif 477*d5a2a073SDaniel Dunbar #endif 478*d5a2a073SDaniel Dunbar return Results; 479*d5a2a073SDaniel Dunbar } 480*d5a2a073SDaniel Dunbar 481*d5a2a073SDaniel Dunbar void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) { 482*d5a2a073SDaniel Dunbar if (!ResultsIn) 483*d5a2a073SDaniel Dunbar return; 484*d5a2a073SDaniel Dunbar 485*d5a2a073SDaniel Dunbar AllocatedCXCodeCompleteResults *Results 486*d5a2a073SDaniel Dunbar = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); 487*d5a2a073SDaniel Dunbar delete Results; 488*d5a2a073SDaniel Dunbar } 489*d5a2a073SDaniel Dunbar 490*d5a2a073SDaniel Dunbar unsigned 491*d5a2a073SDaniel Dunbar clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) { 492*d5a2a073SDaniel Dunbar AllocatedCXCodeCompleteResults *Results 493*d5a2a073SDaniel Dunbar = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); 494*d5a2a073SDaniel Dunbar if (!Results) 495*d5a2a073SDaniel Dunbar return 0; 496*d5a2a073SDaniel Dunbar 497*d5a2a073SDaniel Dunbar return Results->Diagnostics.size(); 498*d5a2a073SDaniel Dunbar } 499*d5a2a073SDaniel Dunbar 500*d5a2a073SDaniel Dunbar CXDiagnostic 501*d5a2a073SDaniel Dunbar clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn, 502*d5a2a073SDaniel Dunbar unsigned Index) { 503*d5a2a073SDaniel Dunbar AllocatedCXCodeCompleteResults *Results 504*d5a2a073SDaniel Dunbar = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); 505*d5a2a073SDaniel Dunbar if (!Results || Index >= Results->Diagnostics.size()) 506*d5a2a073SDaniel Dunbar return 0; 507*d5a2a073SDaniel Dunbar 508*d5a2a073SDaniel Dunbar return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts); 509*d5a2a073SDaniel Dunbar } 510*d5a2a073SDaniel Dunbar 511*d5a2a073SDaniel Dunbar 512*d5a2a073SDaniel Dunbar } // end extern "C" 513