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 "CXTranslationUnit.h" 17 #include "CXString.h" 18 #include "CIndexDiagnostic.h" 19 #include "clang/Basic/SourceManager.h" 20 #include "clang/Basic/FileManager.h" 21 #include "clang/Frontend/ASTUnit.h" 22 #include "clang/Frontend/CompilerInstance.h" 23 #include "clang/Frontend/FrontendDiagnostic.h" 24 #include "clang/Sema/CodeCompleteConsumer.h" 25 #include "llvm/ADT/SmallString.h" 26 #include "llvm/ADT/StringExtras.h" 27 #include "llvm/Support/Atomic.h" 28 #include "llvm/Support/CrashRecoveryContext.h" 29 #include "llvm/Support/MemoryBuffer.h" 30 #include "llvm/Support/Timer.h" 31 #include "llvm/Support/raw_ostream.h" 32 #include "llvm/Support/Program.h" 33 #include <cstdlib> 34 #include <cstdio> 35 36 37 #ifdef UDP_CODE_COMPLETION_LOGGER 38 #include "clang/Basic/Version.h" 39 #include <arpa/inet.h> 40 #include <sys/socket.h> 41 #include <sys/types.h> 42 #include <unistd.h> 43 #endif 44 45 using namespace clang; 46 using namespace clang::cxstring; 47 48 extern "C" { 49 50 enum CXCompletionChunkKind 51 clang_getCompletionChunkKind(CXCompletionString completion_string, 52 unsigned chunk_number) { 53 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; 54 if (!CCStr || chunk_number >= CCStr->size()) 55 return CXCompletionChunk_Text; 56 57 switch ((*CCStr)[chunk_number].Kind) { 58 case CodeCompletionString::CK_TypedText: 59 return CXCompletionChunk_TypedText; 60 case CodeCompletionString::CK_Text: 61 return CXCompletionChunk_Text; 62 case CodeCompletionString::CK_Optional: 63 return CXCompletionChunk_Optional; 64 case CodeCompletionString::CK_Placeholder: 65 return CXCompletionChunk_Placeholder; 66 case CodeCompletionString::CK_Informative: 67 return CXCompletionChunk_Informative; 68 case CodeCompletionString::CK_ResultType: 69 return CXCompletionChunk_ResultType; 70 case CodeCompletionString::CK_CurrentParameter: 71 return CXCompletionChunk_CurrentParameter; 72 case CodeCompletionString::CK_LeftParen: 73 return CXCompletionChunk_LeftParen; 74 case CodeCompletionString::CK_RightParen: 75 return CXCompletionChunk_RightParen; 76 case CodeCompletionString::CK_LeftBracket: 77 return CXCompletionChunk_LeftBracket; 78 case CodeCompletionString::CK_RightBracket: 79 return CXCompletionChunk_RightBracket; 80 case CodeCompletionString::CK_LeftBrace: 81 return CXCompletionChunk_LeftBrace; 82 case CodeCompletionString::CK_RightBrace: 83 return CXCompletionChunk_RightBrace; 84 case CodeCompletionString::CK_LeftAngle: 85 return CXCompletionChunk_LeftAngle; 86 case CodeCompletionString::CK_RightAngle: 87 return CXCompletionChunk_RightAngle; 88 case CodeCompletionString::CK_Comma: 89 return CXCompletionChunk_Comma; 90 case CodeCompletionString::CK_Colon: 91 return CXCompletionChunk_Colon; 92 case CodeCompletionString::CK_SemiColon: 93 return CXCompletionChunk_SemiColon; 94 case CodeCompletionString::CK_Equal: 95 return CXCompletionChunk_Equal; 96 case CodeCompletionString::CK_HorizontalSpace: 97 return CXCompletionChunk_HorizontalSpace; 98 case CodeCompletionString::CK_VerticalSpace: 99 return CXCompletionChunk_VerticalSpace; 100 } 101 102 // Should be unreachable, but let's be careful. 103 return CXCompletionChunk_Text; 104 } 105 106 CXString clang_getCompletionChunkText(CXCompletionString completion_string, 107 unsigned chunk_number) { 108 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; 109 if (!CCStr || chunk_number >= CCStr->size()) 110 return createCXString((const char*)0); 111 112 switch ((*CCStr)[chunk_number].Kind) { 113 case CodeCompletionString::CK_TypedText: 114 case CodeCompletionString::CK_Text: 115 case CodeCompletionString::CK_Placeholder: 116 case CodeCompletionString::CK_CurrentParameter: 117 case CodeCompletionString::CK_Informative: 118 case CodeCompletionString::CK_LeftParen: 119 case CodeCompletionString::CK_RightParen: 120 case CodeCompletionString::CK_LeftBracket: 121 case CodeCompletionString::CK_RightBracket: 122 case CodeCompletionString::CK_LeftBrace: 123 case CodeCompletionString::CK_RightBrace: 124 case CodeCompletionString::CK_LeftAngle: 125 case CodeCompletionString::CK_RightAngle: 126 case CodeCompletionString::CK_Comma: 127 case CodeCompletionString::CK_ResultType: 128 case CodeCompletionString::CK_Colon: 129 case CodeCompletionString::CK_SemiColon: 130 case CodeCompletionString::CK_Equal: 131 case CodeCompletionString::CK_HorizontalSpace: 132 case CodeCompletionString::CK_VerticalSpace: 133 return createCXString((*CCStr)[chunk_number].Text, false); 134 135 case CodeCompletionString::CK_Optional: 136 // Note: treated as an empty text block. 137 return createCXString(""); 138 } 139 140 // Should be unreachable, but let's be careful. 141 return createCXString((const char*)0); 142 } 143 144 145 CXCompletionString 146 clang_getCompletionChunkCompletionString(CXCompletionString completion_string, 147 unsigned chunk_number) { 148 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; 149 if (!CCStr || chunk_number >= CCStr->size()) 150 return 0; 151 152 switch ((*CCStr)[chunk_number].Kind) { 153 case CodeCompletionString::CK_TypedText: 154 case CodeCompletionString::CK_Text: 155 case CodeCompletionString::CK_Placeholder: 156 case CodeCompletionString::CK_CurrentParameter: 157 case CodeCompletionString::CK_Informative: 158 case CodeCompletionString::CK_LeftParen: 159 case CodeCompletionString::CK_RightParen: 160 case CodeCompletionString::CK_LeftBracket: 161 case CodeCompletionString::CK_RightBracket: 162 case CodeCompletionString::CK_LeftBrace: 163 case CodeCompletionString::CK_RightBrace: 164 case CodeCompletionString::CK_LeftAngle: 165 case CodeCompletionString::CK_RightAngle: 166 case CodeCompletionString::CK_Comma: 167 case CodeCompletionString::CK_ResultType: 168 case CodeCompletionString::CK_Colon: 169 case CodeCompletionString::CK_SemiColon: 170 case CodeCompletionString::CK_Equal: 171 case CodeCompletionString::CK_HorizontalSpace: 172 case CodeCompletionString::CK_VerticalSpace: 173 return 0; 174 175 case CodeCompletionString::CK_Optional: 176 // Note: treated as an empty text block. 177 return (*CCStr)[chunk_number].Optional; 178 } 179 180 // Should be unreachable, but let's be careful. 181 return 0; 182 } 183 184 unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) { 185 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; 186 return CCStr? CCStr->size() : 0; 187 } 188 189 unsigned clang_getCompletionPriority(CXCompletionString completion_string) { 190 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; 191 return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely); 192 } 193 194 enum CXAvailabilityKind 195 clang_getCompletionAvailability(CXCompletionString completion_string) { 196 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string; 197 return CCStr? static_cast<CXAvailabilityKind>(CCStr->getAvailability()) 198 : CXAvailability_Available; 199 } 200 201 /// \brief The CXCodeCompleteResults structure we allocate internally; 202 /// the client only sees the initial CXCodeCompleteResults structure. 203 struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { 204 AllocatedCXCodeCompleteResults(const FileSystemOptions& FileSystemOpts); 205 ~AllocatedCXCodeCompleteResults(); 206 207 /// \brief Diagnostics produced while performing code completion. 208 llvm::SmallVector<StoredDiagnostic, 8> Diagnostics; 209 210 /// \brief Diag object 211 llvm::IntrusiveRefCntPtr<Diagnostic> Diag; 212 213 /// \brief Language options used to adjust source locations. 214 LangOptions LangOpts; 215 216 FileSystemOptions FileSystemOpts; 217 218 /// \brief File manager, used for diagnostics. 219 llvm::IntrusiveRefCntPtr<FileManager> FileMgr; 220 221 /// \brief Source manager, used for diagnostics. 222 llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr; 223 224 /// \brief Temporary files that should be removed once we have finished 225 /// with the code-completion results. 226 std::vector<llvm::sys::Path> TemporaryFiles; 227 228 /// \brief Temporary buffers that will be deleted once we have finished with 229 /// the code-completion results. 230 llvm::SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers; 231 232 /// \brief Allocator used to store globally cached code-completion results. 233 llvm::IntrusiveRefCntPtr<clang::GlobalCodeCompletionAllocator> 234 CachedCompletionAllocator; 235 236 /// \brief Allocator used to store code completion results. 237 clang::CodeCompletionAllocator CodeCompletionAllocator; 238 239 /// \brief Context under which completion occurred. 240 enum clang::CodeCompletionContext::Kind ContextKind; 241 242 /// \brief A bitfield representing the acceptable completions for the 243 /// current context. 244 unsigned long long Contexts; 245 }; 246 247 /// \brief Tracks the number of code-completion result objects that are 248 /// currently active. 249 /// 250 /// Used for debugging purposes only. 251 static llvm::sys::cas_flag CodeCompletionResultObjects; 252 253 AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults( 254 const FileSystemOptions& FileSystemOpts) 255 : CXCodeCompleteResults(), 256 Diag(new Diagnostic( 257 llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs))), 258 FileSystemOpts(FileSystemOpts), 259 FileMgr(new FileManager(FileSystemOpts)), 260 SourceMgr(new SourceManager(*Diag, *FileMgr)) { 261 if (getenv("LIBCLANG_OBJTRACKING")) { 262 llvm::sys::AtomicIncrement(&CodeCompletionResultObjects); 263 fprintf(stderr, "+++ %d completion results\n", CodeCompletionResultObjects); 264 } 265 } 266 267 AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() { 268 delete [] Results; 269 270 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) 271 TemporaryFiles[I].eraseFromDisk(); 272 for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I) 273 delete TemporaryBuffers[I]; 274 275 if (getenv("LIBCLANG_OBJTRACKING")) { 276 llvm::sys::AtomicDecrement(&CodeCompletionResultObjects); 277 fprintf(stderr, "--- %d completion results\n", CodeCompletionResultObjects); 278 } 279 } 280 281 } // end extern "C" 282 283 static unsigned long long getContextsForContextKind( 284 enum CodeCompletionContext::Kind kind, 285 Sema &S) { 286 unsigned long long contexts = 0; 287 switch (kind) { 288 case CodeCompletionContext::CCC_OtherWithMacros: { 289 //We can allow macros here, but we don't know what else is permissible 290 //So we'll say the only thing permissible are macros 291 contexts = CXCompletionContext_MacroName; 292 break; 293 } 294 case CodeCompletionContext::CCC_TopLevel: 295 case CodeCompletionContext::CCC_ObjCIvarList: 296 case CodeCompletionContext::CCC_ClassStructUnion: 297 case CodeCompletionContext::CCC_Type: { 298 contexts = CXCompletionContext_AnyType | 299 CXCompletionContext_ObjCInterface; 300 if (S.getLangOptions().CPlusPlus) { 301 contexts |= CXCompletionContext_EnumTag | 302 CXCompletionContext_UnionTag | 303 CXCompletionContext_StructTag | 304 CXCompletionContext_ClassTag | 305 CXCompletionContext_NestedNameSpecifier; 306 } 307 break; 308 } 309 case CodeCompletionContext::CCC_Statement: { 310 contexts = CXCompletionContext_AnyType | 311 CXCompletionContext_ObjCInterface | 312 CXCompletionContext_AnyValue; 313 if (S.getLangOptions().CPlusPlus) { 314 contexts |= CXCompletionContext_EnumTag | 315 CXCompletionContext_UnionTag | 316 CXCompletionContext_StructTag | 317 CXCompletionContext_ClassTag | 318 CXCompletionContext_NestedNameSpecifier; 319 } 320 break; 321 } 322 case CodeCompletionContext::CCC_Expression: { 323 contexts = CXCompletionContext_AnyValue; 324 if (S.getLangOptions().CPlusPlus) { 325 contexts |= CXCompletionContext_AnyType | 326 CXCompletionContext_ObjCInterface | 327 CXCompletionContext_EnumTag | 328 CXCompletionContext_UnionTag | 329 CXCompletionContext_StructTag | 330 CXCompletionContext_ClassTag | 331 CXCompletionContext_NestedNameSpecifier; 332 } 333 break; 334 } 335 case CodeCompletionContext::CCC_ObjCMessageReceiver: { 336 contexts = CXCompletionContext_ObjCObjectValue | 337 CXCompletionContext_ObjCSelectorValue | 338 CXCompletionContext_ObjCInterface; 339 if (S.getLangOptions().CPlusPlus) { 340 contexts |= CXCompletionContext_CXXClassTypeValue | 341 CXCompletionContext_AnyType | 342 CXCompletionContext_EnumTag | 343 CXCompletionContext_UnionTag | 344 CXCompletionContext_StructTag | 345 CXCompletionContext_ClassTag | 346 CXCompletionContext_NestedNameSpecifier; 347 } 348 break; 349 } 350 case CodeCompletionContext::CCC_DotMemberAccess: { 351 contexts = CXCompletionContext_DotMemberAccess; 352 break; 353 } 354 case CodeCompletionContext::CCC_ArrowMemberAccess: { 355 contexts = CXCompletionContext_ArrowMemberAccess; 356 break; 357 } 358 case CodeCompletionContext::CCC_ObjCPropertyAccess: { 359 contexts = CXCompletionContext_ObjCPropertyAccess; 360 break; 361 } 362 case CodeCompletionContext::CCC_EnumTag: { 363 contexts = CXCompletionContext_EnumTag | 364 CXCompletionContext_NestedNameSpecifier; 365 break; 366 } 367 case CodeCompletionContext::CCC_UnionTag: { 368 contexts = CXCompletionContext_UnionTag | 369 CXCompletionContext_NestedNameSpecifier; 370 break; 371 } 372 case CodeCompletionContext::CCC_ClassOrStructTag: { 373 contexts = CXCompletionContext_StructTag | 374 CXCompletionContext_ClassTag | 375 CXCompletionContext_NestedNameSpecifier; 376 break; 377 } 378 case CodeCompletionContext::CCC_ObjCProtocolName: { 379 contexts = CXCompletionContext_ObjCProtocol; 380 break; 381 } 382 case CodeCompletionContext::CCC_Namespace: { 383 contexts = CXCompletionContext_Namespace; 384 break; 385 } 386 case CodeCompletionContext::CCC_PotentiallyQualifiedName: { 387 contexts = CXCompletionContext_NestedNameSpecifier; 388 break; 389 } 390 case CodeCompletionContext::CCC_MacroNameUse: { 391 contexts = CXCompletionContext_MacroName; 392 break; 393 } 394 case CodeCompletionContext::CCC_NaturalLanguage: { 395 contexts = CXCompletionContext_NaturalLanguage; 396 break; 397 } 398 case CodeCompletionContext::CCC_SelectorName: { 399 contexts = CXCompletionContext_ObjCSelectorName; 400 break; 401 } 402 case CodeCompletionContext::CCC_ParenthesizedExpression: { 403 contexts = CXCompletionContext_AnyType | 404 CXCompletionContext_ObjCInterface | 405 CXCompletionContext_AnyValue; 406 if (S.getLangOptions().CPlusPlus) { 407 contexts |= CXCompletionContext_EnumTag | 408 CXCompletionContext_UnionTag | 409 CXCompletionContext_StructTag | 410 CXCompletionContext_ClassTag | 411 CXCompletionContext_NestedNameSpecifier; 412 } 413 break; 414 } 415 case CodeCompletionContext::CCC_ObjCInstanceMessage: { 416 contexts = CXCompletionContext_ObjCInstanceMessage; 417 break; 418 } 419 case CodeCompletionContext::CCC_ObjCClassMessage: { 420 contexts = CXCompletionContext_ObjCClassMessage; 421 break; 422 } 423 case CodeCompletionContext::CCC_ObjCSuperclass: { 424 contexts = CXCompletionContext_ObjCInterface; 425 break; 426 } 427 case CodeCompletionContext::CCC_ObjCCategoryName: { 428 contexts = CXCompletionContext_ObjCCategory; 429 break; 430 } 431 case CodeCompletionContext::CCC_Other: 432 case CodeCompletionContext::CCC_ObjCInterface: 433 case CodeCompletionContext::CCC_ObjCImplementation: 434 case CodeCompletionContext::CCC_Name: 435 case CodeCompletionContext::CCC_MacroName: 436 case CodeCompletionContext::CCC_PreprocessorExpression: 437 case CodeCompletionContext::CCC_PreprocessorDirective: 438 case CodeCompletionContext::CCC_TypeQualifiers: { 439 //Only Clang results should be accepted, so we'll set all of the other 440 //context bits to 0 (i.e. the empty set) 441 contexts = CXCompletionContext_Unexposed; 442 break; 443 } 444 case CodeCompletionContext::CCC_Recovery: { 445 //We don't know what the current context is, so we'll return unknown 446 //This is the equivalent of setting all of the other context bits 447 contexts = CXCompletionContext_Unknown; 448 break; 449 } 450 } 451 return contexts; 452 } 453 454 namespace { 455 class CaptureCompletionResults : public CodeCompleteConsumer { 456 AllocatedCXCodeCompleteResults &AllocatedResults; 457 llvm::SmallVector<CXCompletionResult, 16> StoredResults; 458 public: 459 CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results) 460 : CodeCompleteConsumer(true, false, true, false), 461 AllocatedResults(Results) { } 462 ~CaptureCompletionResults() { Finish(); } 463 464 virtual void ProcessCodeCompleteResults(Sema &S, 465 CodeCompletionContext Context, 466 CodeCompletionResult *Results, 467 unsigned NumResults) { 468 StoredResults.reserve(StoredResults.size() + NumResults); 469 for (unsigned I = 0; I != NumResults; ++I) { 470 CodeCompletionString *StoredCompletion 471 = Results[I].CreateCodeCompletionString(S, 472 AllocatedResults.CodeCompletionAllocator); 473 474 CXCompletionResult R; 475 R.CursorKind = Results[I].CursorKind; 476 R.CompletionString = StoredCompletion; 477 StoredResults.push_back(R); 478 } 479 480 enum CodeCompletionContext::Kind kind = Context.getKind(); 481 482 AllocatedResults.ContextKind = kind; 483 AllocatedResults.Contexts = getContextsForContextKind(kind, S); 484 } 485 486 virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, 487 OverloadCandidate *Candidates, 488 unsigned NumCandidates) { 489 StoredResults.reserve(StoredResults.size() + NumCandidates); 490 for (unsigned I = 0; I != NumCandidates; ++I) { 491 CodeCompletionString *StoredCompletion 492 = Candidates[I].CreateSignatureString(CurrentArg, S, 493 AllocatedResults.CodeCompletionAllocator); 494 495 CXCompletionResult R; 496 R.CursorKind = CXCursor_NotImplemented; 497 R.CompletionString = StoredCompletion; 498 StoredResults.push_back(R); 499 } 500 } 501 502 virtual CodeCompletionAllocator &getAllocator() { 503 return AllocatedResults.CodeCompletionAllocator; 504 } 505 506 private: 507 void Finish() { 508 AllocatedResults.Results = new CXCompletionResult [StoredResults.size()]; 509 AllocatedResults.NumResults = StoredResults.size(); 510 std::memcpy(AllocatedResults.Results, StoredResults.data(), 511 StoredResults.size() * sizeof(CXCompletionResult)); 512 StoredResults.clear(); 513 } 514 }; 515 } 516 517 extern "C" { 518 struct CodeCompleteAtInfo { 519 CXTranslationUnit TU; 520 const char *complete_filename; 521 unsigned complete_line; 522 unsigned complete_column; 523 struct CXUnsavedFile *unsaved_files; 524 unsigned num_unsaved_files; 525 unsigned options; 526 CXCodeCompleteResults *result; 527 }; 528 void clang_codeCompleteAt_Impl(void *UserData) { 529 CodeCompleteAtInfo *CCAI = static_cast<CodeCompleteAtInfo*>(UserData); 530 CXTranslationUnit TU = CCAI->TU; 531 const char *complete_filename = CCAI->complete_filename; 532 unsigned complete_line = CCAI->complete_line; 533 unsigned complete_column = CCAI->complete_column; 534 struct CXUnsavedFile *unsaved_files = CCAI->unsaved_files; 535 unsigned num_unsaved_files = CCAI->num_unsaved_files; 536 unsigned options = CCAI->options; 537 CCAI->result = 0; 538 539 #ifdef UDP_CODE_COMPLETION_LOGGER 540 #ifdef UDP_CODE_COMPLETION_LOGGER_PORT 541 const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime(); 542 #endif 543 #endif 544 545 bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != 0; 546 547 ASTUnit *AST = static_cast<ASTUnit *>(TU->TUData); 548 if (!AST) 549 return; 550 551 ASTUnit::ConcurrencyCheck Check(*AST); 552 553 // Perform the remapping of source files. 554 llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles; 555 for (unsigned I = 0; I != num_unsaved_files; ++I) { 556 llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length); 557 const llvm::MemoryBuffer *Buffer 558 = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename); 559 RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename, 560 Buffer)); 561 } 562 563 if (EnableLogging) { 564 // FIXME: Add logging. 565 } 566 567 // Parse the resulting source file to find code-completion results. 568 AllocatedCXCodeCompleteResults *Results = 569 new AllocatedCXCodeCompleteResults(AST->getFileSystemOpts()); 570 Results->Results = 0; 571 Results->NumResults = 0; 572 573 // Create a code-completion consumer to capture the results. 574 CaptureCompletionResults Capture(*Results); 575 576 // Perform completion. 577 AST->CodeComplete(complete_filename, complete_line, complete_column, 578 RemappedFiles.data(), RemappedFiles.size(), 579 (options & CXCodeComplete_IncludeMacros), 580 (options & CXCodeComplete_IncludeCodePatterns), 581 Capture, 582 *Results->Diag, Results->LangOpts, *Results->SourceMgr, 583 *Results->FileMgr, Results->Diagnostics, 584 Results->TemporaryBuffers); 585 586 // Keep a reference to the allocator used for cached global completions, so 587 // that we can be sure that the memory used by our code completion strings 588 // doesn't get freed due to subsequent reparses (while the code completion 589 // results are still active). 590 Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator(); 591 592 593 594 #ifdef UDP_CODE_COMPLETION_LOGGER 595 #ifdef UDP_CODE_COMPLETION_LOGGER_PORT 596 const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime(); 597 llvm::SmallString<256> LogResult; 598 llvm::raw_svector_ostream os(LogResult); 599 600 // Figure out the language and whether or not it uses PCH. 601 const char *lang = 0; 602 bool usesPCH = false; 603 604 for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end(); 605 I != E; ++I) { 606 if (*I == 0) 607 continue; 608 if (strcmp(*I, "-x") == 0) { 609 if (I + 1 != E) { 610 lang = *(++I); 611 continue; 612 } 613 } 614 else if (strcmp(*I, "-include") == 0) { 615 if (I+1 != E) { 616 const char *arg = *(++I); 617 llvm::SmallString<512> pchName; 618 { 619 llvm::raw_svector_ostream os(pchName); 620 os << arg << ".pth"; 621 } 622 pchName.push_back('\0'); 623 struct stat stat_results; 624 if (stat(pchName.data(), &stat_results) == 0) 625 usesPCH = true; 626 continue; 627 } 628 } 629 } 630 631 os << "{ "; 632 os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime()); 633 os << ", \"numRes\": " << Results->NumResults; 634 os << ", \"diags\": " << Results->Diagnostics.size(); 635 os << ", \"pch\": " << (usesPCH ? "true" : "false"); 636 os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"'; 637 const char *name = getlogin(); 638 os << ", \"user\": \"" << (name ? name : "unknown") << '"'; 639 os << ", \"clangVer\": \"" << getClangFullVersion() << '"'; 640 os << " }"; 641 642 llvm::StringRef res = os.str(); 643 if (res.size() > 0) { 644 do { 645 // Setup the UDP socket. 646 struct sockaddr_in servaddr; 647 bzero(&servaddr, sizeof(servaddr)); 648 servaddr.sin_family = AF_INET; 649 servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT); 650 if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER, 651 &servaddr.sin_addr) <= 0) 652 break; 653 654 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 655 if (sockfd < 0) 656 break; 657 658 sendto(sockfd, res.data(), res.size(), 0, 659 (struct sockaddr *)&servaddr, sizeof(servaddr)); 660 close(sockfd); 661 } 662 while (false); 663 } 664 #endif 665 #endif 666 CCAI->result = Results; 667 } 668 CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU, 669 const char *complete_filename, 670 unsigned complete_line, 671 unsigned complete_column, 672 struct CXUnsavedFile *unsaved_files, 673 unsigned num_unsaved_files, 674 unsigned options) { 675 CodeCompleteAtInfo CCAI = { TU, complete_filename, complete_line, 676 complete_column, unsaved_files, num_unsaved_files, 677 options, 0 }; 678 llvm::CrashRecoveryContext CRC; 679 680 if (!RunSafely(CRC, clang_codeCompleteAt_Impl, &CCAI)) { 681 fprintf(stderr, "libclang: crash detected in code completion\n"); 682 static_cast<ASTUnit *>(TU->TUData)->setUnsafeToFree(true); 683 return 0; 684 } else if (getenv("LIBCLANG_RESOURCE_USAGE")) 685 PrintLibclangResourceUsage(TU); 686 687 return CCAI.result; 688 } 689 690 unsigned clang_defaultCodeCompleteOptions(void) { 691 return CXCodeComplete_IncludeMacros; 692 } 693 694 void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) { 695 if (!ResultsIn) 696 return; 697 698 AllocatedCXCodeCompleteResults *Results 699 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); 700 delete Results; 701 } 702 703 unsigned 704 clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) { 705 AllocatedCXCodeCompleteResults *Results 706 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); 707 if (!Results) 708 return 0; 709 710 return Results->Diagnostics.size(); 711 } 712 713 CXDiagnostic 714 clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn, 715 unsigned Index) { 716 AllocatedCXCodeCompleteResults *Results 717 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); 718 if (!Results || Index >= Results->Diagnostics.size()) 719 return 0; 720 721 return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts); 722 } 723 724 unsigned long long 725 clang_codeCompleteGetContexts(CXCodeCompleteResults *ResultsIn) { 726 AllocatedCXCodeCompleteResults *Results 727 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); 728 if (!Results) 729 return 0; 730 731 return Results->Contexts; 732 } 733 734 } // end extern "C" 735 736 /// \brief Simple utility function that appends a \p New string to the given 737 /// \p Old string, using the \p Buffer for storage. 738 /// 739 /// \param Old The string to which we are appending. This parameter will be 740 /// updated to reflect the complete string. 741 /// 742 /// 743 /// \param New The string to append to \p Old. 744 /// 745 /// \param Buffer A buffer that stores the actual, concatenated string. It will 746 /// be used if the old string is already-non-empty. 747 static void AppendToString(llvm::StringRef &Old, llvm::StringRef New, 748 llvm::SmallString<256> &Buffer) { 749 if (Old.empty()) { 750 Old = New; 751 return; 752 } 753 754 if (Buffer.empty()) 755 Buffer.append(Old.begin(), Old.end()); 756 Buffer.append(New.begin(), New.end()); 757 Old = Buffer.str(); 758 } 759 760 /// \brief Get the typed-text blocks from the given code-completion string 761 /// and return them as a single string. 762 /// 763 /// \param String The code-completion string whose typed-text blocks will be 764 /// concatenated. 765 /// 766 /// \param Buffer A buffer used for storage of the completed name. 767 static llvm::StringRef GetTypedName(CodeCompletionString *String, 768 llvm::SmallString<256> &Buffer) { 769 llvm::StringRef Result; 770 for (CodeCompletionString::iterator C = String->begin(), CEnd = String->end(); 771 C != CEnd; ++C) { 772 if (C->Kind == CodeCompletionString::CK_TypedText) 773 AppendToString(Result, C->Text, Buffer); 774 } 775 776 return Result; 777 } 778 779 namespace { 780 struct OrderCompletionResults { 781 bool operator()(const CXCompletionResult &XR, 782 const CXCompletionResult &YR) const { 783 CodeCompletionString *X 784 = (CodeCompletionString *)XR.CompletionString; 785 CodeCompletionString *Y 786 = (CodeCompletionString *)YR.CompletionString; 787 788 llvm::SmallString<256> XBuffer; 789 llvm::StringRef XText = GetTypedName(X, XBuffer); 790 llvm::SmallString<256> YBuffer; 791 llvm::StringRef YText = GetTypedName(Y, YBuffer); 792 793 if (XText.empty() || YText.empty()) 794 return !XText.empty(); 795 796 int result = XText.compare_lower(YText); 797 if (result < 0) 798 return true; 799 if (result > 0) 800 return false; 801 802 result = XText.compare(YText); 803 return result < 0; 804 } 805 }; 806 } 807 808 extern "C" { 809 void clang_sortCodeCompletionResults(CXCompletionResult *Results, 810 unsigned NumResults) { 811 std::stable_sort(Results, Results + NumResults, OrderCompletionResults()); 812 } 813 } 814