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