1 //===--- CodeComplete.cpp ---------------------------------------*- C++-*-===// 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 // AST-based completions are provided using the completion hooks in Sema. 11 // 12 // Signature help works in a similar way as code completion, but it is simpler 13 // as there are typically fewer candidates. 14 // 15 //===---------------------------------------------------------------------===// 16 17 #include "CodeComplete.h" 18 #include "Compiler.h" 19 #include "clang/Frontend/CompilerInstance.h" 20 #include "clang/Frontend/FrontendActions.h" 21 #include "clang/Sema/CodeCompleteConsumer.h" 22 #include "clang/Sema/Sema.h" 23 #include <queue> 24 25 namespace clang { 26 namespace clangd { 27 namespace { 28 29 CompletionItemKind getKindOfDecl(CXCursorKind CursorKind) { 30 switch (CursorKind) { 31 case CXCursor_MacroInstantiation: 32 case CXCursor_MacroDefinition: 33 return CompletionItemKind::Text; 34 case CXCursor_CXXMethod: 35 return CompletionItemKind::Method; 36 case CXCursor_FunctionDecl: 37 case CXCursor_FunctionTemplate: 38 return CompletionItemKind::Function; 39 case CXCursor_Constructor: 40 case CXCursor_Destructor: 41 return CompletionItemKind::Constructor; 42 case CXCursor_FieldDecl: 43 return CompletionItemKind::Field; 44 case CXCursor_VarDecl: 45 case CXCursor_ParmDecl: 46 return CompletionItemKind::Variable; 47 case CXCursor_ClassDecl: 48 case CXCursor_StructDecl: 49 case CXCursor_UnionDecl: 50 case CXCursor_ClassTemplate: 51 case CXCursor_ClassTemplatePartialSpecialization: 52 return CompletionItemKind::Class; 53 case CXCursor_Namespace: 54 case CXCursor_NamespaceAlias: 55 case CXCursor_NamespaceRef: 56 return CompletionItemKind::Module; 57 case CXCursor_EnumConstantDecl: 58 return CompletionItemKind::Value; 59 case CXCursor_EnumDecl: 60 return CompletionItemKind::Enum; 61 case CXCursor_TypeAliasDecl: 62 case CXCursor_TypeAliasTemplateDecl: 63 case CXCursor_TypedefDecl: 64 case CXCursor_MemberRef: 65 case CXCursor_TypeRef: 66 return CompletionItemKind::Reference; 67 default: 68 return CompletionItemKind::Missing; 69 } 70 } 71 72 CompletionItemKind getKind(CodeCompletionResult::ResultKind ResKind, 73 CXCursorKind CursorKind) { 74 switch (ResKind) { 75 case CodeCompletionResult::RK_Declaration: 76 return getKindOfDecl(CursorKind); 77 case CodeCompletionResult::RK_Keyword: 78 return CompletionItemKind::Keyword; 79 case CodeCompletionResult::RK_Macro: 80 return CompletionItemKind::Text; // unfortunately, there's no 'Macro' 81 // completion items in LSP. 82 case CodeCompletionResult::RK_Pattern: 83 return CompletionItemKind::Snippet; 84 } 85 llvm_unreachable("Unhandled CodeCompletionResult::ResultKind."); 86 } 87 88 std::string escapeSnippet(const llvm::StringRef Text) { 89 std::string Result; 90 Result.reserve(Text.size()); // Assume '$', '}' and '\\' are rare. 91 for (const auto Character : Text) { 92 if (Character == '$' || Character == '}' || Character == '\\') 93 Result.push_back('\\'); 94 Result.push_back(Character); 95 } 96 return Result; 97 } 98 99 std::string getDocumentation(const CodeCompletionString &CCS) { 100 // Things like __attribute__((nonnull(1,3))) and [[noreturn]]. Present this 101 // information in the documentation field. 102 std::string Result; 103 const unsigned AnnotationCount = CCS.getAnnotationCount(); 104 if (AnnotationCount > 0) { 105 Result += "Annotation"; 106 if (AnnotationCount == 1) { 107 Result += ": "; 108 } else /* AnnotationCount > 1 */ { 109 Result += "s: "; 110 } 111 for (unsigned I = 0; I < AnnotationCount; ++I) { 112 Result += CCS.getAnnotation(I); 113 Result.push_back(I == AnnotationCount - 1 ? '\n' : ' '); 114 } 115 } 116 // Add brief documentation (if there is any). 117 if (CCS.getBriefComment() != nullptr) { 118 if (!Result.empty()) { 119 // This means we previously added annotations. Add an extra newline 120 // character to make the annotations stand out. 121 Result.push_back('\n'); 122 } 123 Result += CCS.getBriefComment(); 124 } 125 return Result; 126 } 127 128 /// Get the optional chunk as a string. This function is possibly recursive. 129 /// 130 /// The parameter info for each parameter is appended to the Parameters. 131 std::string 132 getOptionalParameters(const CodeCompletionString &CCS, 133 std::vector<ParameterInformation> &Parameters) { 134 std::string Result; 135 for (const auto &Chunk : CCS) { 136 switch (Chunk.Kind) { 137 case CodeCompletionString::CK_Optional: 138 assert(Chunk.Optional && 139 "Expected the optional code completion string to be non-null."); 140 Result += getOptionalParameters(*Chunk.Optional, Parameters); 141 break; 142 case CodeCompletionString::CK_VerticalSpace: 143 break; 144 case CodeCompletionString::CK_Placeholder: 145 // A string that acts as a placeholder for, e.g., a function call 146 // argument. 147 // Intentional fallthrough here. 148 case CodeCompletionString::CK_CurrentParameter: { 149 // A piece of text that describes the parameter that corresponds to 150 // the code-completion location within a function call, message send, 151 // macro invocation, etc. 152 Result += Chunk.Text; 153 ParameterInformation Info; 154 Info.label = Chunk.Text; 155 Parameters.push_back(std::move(Info)); 156 break; 157 } 158 default: 159 Result += Chunk.Text; 160 break; 161 } 162 } 163 return Result; 164 } 165 166 /// A scored code completion result. 167 /// It may be promoted to a CompletionItem if it's among the top-ranked results. 168 struct CompletionCandidate { 169 CompletionCandidate(CodeCompletionResult &Result) 170 : Result(&Result), Score(score(Result)) {} 171 172 CodeCompletionResult *Result; 173 float Score; // 0 to 1, higher is better. 174 175 // Comparison reflects rank: better candidates are smaller. 176 bool operator<(const CompletionCandidate &C) const { 177 if (Score != C.Score) 178 return Score > C.Score; 179 return *Result < *C.Result; 180 } 181 182 // Returns a string that sorts in the same order as operator<, for LSP. 183 // Conceptually, this is [-Score, Name]. We convert -Score to an integer, and 184 // hex-encode it for readability. Example: [0.5, "foo"] -> "41000000foo" 185 std::string sortText() const { 186 std::string S, NameStorage; 187 llvm::raw_string_ostream OS(S); 188 write_hex(OS, encodeFloat(-Score), llvm::HexPrintStyle::Lower, 189 /*Width=*/2 * sizeof(Score)); 190 OS << Result->getOrderedName(NameStorage); 191 return OS.str(); 192 } 193 194 private: 195 static float score(const CodeCompletionResult &Result) { 196 // Priority 80 is a really bad score. 197 float Score = 1 - std::min<float>(80, Result.Priority) / 80; 198 199 switch (static_cast<CXAvailabilityKind>(Result.Availability)) { 200 case CXAvailability_Available: 201 // No penalty. 202 break; 203 case CXAvailability_Deprecated: 204 Score *= 0.1f; 205 break; 206 case CXAvailability_NotAccessible: 207 case CXAvailability_NotAvailable: 208 Score = 0; 209 break; 210 } 211 return Score; 212 } 213 214 // Produces an integer that sorts in the same order as F. 215 // That is: a < b <==> encodeFloat(a) < encodeFloat(b). 216 static uint32_t encodeFloat(float F) { 217 static_assert(std::numeric_limits<float>::is_iec559, ""); 218 static_assert(sizeof(float) == sizeof(uint32_t), ""); 219 constexpr uint32_t TopBit = ~(~uint32_t{0} >> 1); 220 221 // Get the bits of the float. Endianness is the same as for integers. 222 uint32_t U; 223 memcpy(&U, &F, sizeof(float)); 224 // IEEE 754 floats compare like sign-magnitude integers. 225 if (U & TopBit) // Negative float. 226 return 0 - U; // Map onto the low half of integers, order reversed. 227 return U + TopBit; // Positive floats map onto the high half of integers. 228 } 229 }; 230 231 class CompletionItemsCollector : public CodeCompleteConsumer { 232 public: 233 CompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts, 234 CompletionList &Items) 235 : CodeCompleteConsumer(CodeCompleteOpts.getClangCompleteOpts(), 236 /*OutputIsBinary=*/false), 237 ClangdOpts(CodeCompleteOpts), Items(Items), 238 Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()), 239 CCTUInfo(Allocator) {} 240 241 void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, 242 CodeCompletionResult *Results, 243 unsigned NumResults) override final { 244 StringRef Filter = S.getPreprocessor().getCodeCompletionFilter(); 245 std::priority_queue<CompletionCandidate> Candidates; 246 for (unsigned I = 0; I < NumResults; ++I) { 247 auto &Result = Results[I]; 248 if (!ClangdOpts.IncludeIneligibleResults && 249 (Result.Availability == CXAvailability_NotAvailable || 250 Result.Availability == CXAvailability_NotAccessible)) 251 continue; 252 if (!Filter.empty() && !fuzzyMatch(S, Context, Filter, Result)) 253 continue; 254 Candidates.emplace(Result); 255 if (ClangdOpts.Limit && Candidates.size() > ClangdOpts.Limit) { 256 Candidates.pop(); 257 Items.isIncomplete = true; 258 } 259 } 260 while (!Candidates.empty()) { 261 auto &Candidate = Candidates.top(); 262 const auto *CCS = Candidate.Result->CreateCodeCompletionString( 263 S, Context, *Allocator, CCTUInfo, 264 CodeCompleteOpts.IncludeBriefComments); 265 assert(CCS && "Expected the CodeCompletionString to be non-null"); 266 Items.items.push_back(ProcessCodeCompleteResult(Candidate, *CCS)); 267 Candidates.pop(); 268 } 269 std::reverse(Items.items.begin(), Items.items.end()); 270 } 271 272 GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; } 273 274 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } 275 276 private: 277 bool fuzzyMatch(Sema &S, const CodeCompletionContext &CCCtx, StringRef Filter, 278 CodeCompletionResult Result) { 279 switch (Result.Kind) { 280 case CodeCompletionResult::RK_Declaration: 281 if (auto *ID = Result.Declaration->getIdentifier()) 282 return fuzzyMatch(Filter, ID->getName()); 283 break; 284 case CodeCompletionResult::RK_Keyword: 285 return fuzzyMatch(Filter, Result.Keyword); 286 case CodeCompletionResult::RK_Macro: 287 return fuzzyMatch(Filter, Result.Macro->getName()); 288 case CodeCompletionResult::RK_Pattern: 289 return fuzzyMatch(Filter, Result.Pattern->getTypedText()); 290 } 291 auto *CCS = Result.CreateCodeCompletionString( 292 S, CCCtx, *Allocator, CCTUInfo, /*IncludeBriefComments=*/false); 293 return fuzzyMatch(Filter, CCS->getTypedText()); 294 } 295 296 // Checks whether Target matches the Filter. 297 // Currently just requires a case-insensitive subsequence match. 298 // FIXME: make stricter and word-based: 'unique_ptr' should not match 'que'. 299 // FIXME: return a score to be incorporated into ranking. 300 static bool fuzzyMatch(StringRef Filter, StringRef Target) { 301 size_t TPos = 0; 302 for (char C : Filter) { 303 TPos = Target.find_lower(C, TPos); 304 if (TPos == StringRef::npos) 305 return false; 306 } 307 return true; 308 } 309 310 CompletionItem 311 ProcessCodeCompleteResult(const CompletionCandidate &Candidate, 312 const CodeCompletionString &CCS) const { 313 314 // Adjust this to InsertTextFormat::Snippet iff we encounter a 315 // CK_Placeholder chunk in SnippetCompletionItemsCollector. 316 CompletionItem Item; 317 Item.insertTextFormat = InsertTextFormat::PlainText; 318 319 Item.documentation = getDocumentation(CCS); 320 Item.sortText = Candidate.sortText(); 321 322 // Fill in the label, detail, insertText and filterText fields of the 323 // CompletionItem. 324 ProcessChunks(CCS, Item); 325 326 // Fill in the kind field of the CompletionItem. 327 Item.kind = getKind(Candidate.Result->Kind, Candidate.Result->CursorKind); 328 329 return Item; 330 } 331 332 virtual void ProcessChunks(const CodeCompletionString &CCS, 333 CompletionItem &Item) const = 0; 334 335 CodeCompleteOptions ClangdOpts; 336 CompletionList &Items; 337 std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator; 338 CodeCompletionTUInfo CCTUInfo; 339 340 }; // CompletionItemsCollector 341 342 bool isInformativeQualifierChunk(CodeCompletionString::Chunk const &Chunk) { 343 return Chunk.Kind == CodeCompletionString::CK_Informative && 344 StringRef(Chunk.Text).endswith("::"); 345 } 346 347 class PlainTextCompletionItemsCollector final 348 : public CompletionItemsCollector { 349 350 public: 351 PlainTextCompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts, 352 CompletionList &Items) 353 : CompletionItemsCollector(CodeCompleteOpts, Items) {} 354 355 private: 356 void ProcessChunks(const CodeCompletionString &CCS, 357 CompletionItem &Item) const override { 358 for (const auto &Chunk : CCS) { 359 // Informative qualifier chunks only clutter completion results, skip 360 // them. 361 if (isInformativeQualifierChunk(Chunk)) 362 continue; 363 364 switch (Chunk.Kind) { 365 case CodeCompletionString::CK_TypedText: 366 // There's always exactly one CK_TypedText chunk. 367 Item.insertText = Item.filterText = Chunk.Text; 368 Item.label += Chunk.Text; 369 break; 370 case CodeCompletionString::CK_ResultType: 371 assert(Item.detail.empty() && "Unexpected extraneous CK_ResultType"); 372 Item.detail = Chunk.Text; 373 break; 374 case CodeCompletionString::CK_Optional: 375 break; 376 default: 377 Item.label += Chunk.Text; 378 break; 379 } 380 } 381 } 382 }; // PlainTextCompletionItemsCollector 383 384 class SnippetCompletionItemsCollector final : public CompletionItemsCollector { 385 386 public: 387 SnippetCompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts, 388 CompletionList &Items) 389 : CompletionItemsCollector(CodeCompleteOpts, Items) {} 390 391 private: 392 void ProcessChunks(const CodeCompletionString &CCS, 393 CompletionItem &Item) const override { 394 unsigned ArgCount = 0; 395 for (const auto &Chunk : CCS) { 396 // Informative qualifier chunks only clutter completion results, skip 397 // them. 398 if (isInformativeQualifierChunk(Chunk)) 399 continue; 400 401 switch (Chunk.Kind) { 402 case CodeCompletionString::CK_TypedText: 403 // The piece of text that the user is expected to type to match 404 // the code-completion string, typically a keyword or the name of 405 // a declarator or macro. 406 Item.filterText = Chunk.Text; 407 LLVM_FALLTHROUGH; 408 case CodeCompletionString::CK_Text: 409 // A piece of text that should be placed in the buffer, 410 // e.g., parentheses or a comma in a function call. 411 Item.label += Chunk.Text; 412 Item.insertText += Chunk.Text; 413 break; 414 case CodeCompletionString::CK_Optional: 415 // A code completion string that is entirely optional. 416 // For example, an optional code completion string that 417 // describes the default arguments in a function call. 418 419 // FIXME: Maybe add an option to allow presenting the optional chunks? 420 break; 421 case CodeCompletionString::CK_Placeholder: 422 // A string that acts as a placeholder for, e.g., a function call 423 // argument. 424 ++ArgCount; 425 Item.insertText += "${" + std::to_string(ArgCount) + ':' + 426 escapeSnippet(Chunk.Text) + '}'; 427 Item.label += Chunk.Text; 428 Item.insertTextFormat = InsertTextFormat::Snippet; 429 break; 430 case CodeCompletionString::CK_Informative: 431 // A piece of text that describes something about the result 432 // but should not be inserted into the buffer. 433 // For example, the word "const" for a const method, or the name of 434 // the base class for methods that are part of the base class. 435 Item.label += Chunk.Text; 436 // Don't put the informative chunks in the insertText. 437 break; 438 case CodeCompletionString::CK_ResultType: 439 // A piece of text that describes the type of an entity or, 440 // for functions and methods, the return type. 441 assert(Item.detail.empty() && "Unexpected extraneous CK_ResultType"); 442 Item.detail = Chunk.Text; 443 break; 444 case CodeCompletionString::CK_CurrentParameter: 445 // A piece of text that describes the parameter that corresponds to 446 // the code-completion location within a function call, message send, 447 // macro invocation, etc. 448 // 449 // This should never be present while collecting completion items, 450 // only while collecting overload candidates. 451 llvm_unreachable("Unexpected CK_CurrentParameter while collecting " 452 "CompletionItems"); 453 break; 454 case CodeCompletionString::CK_LeftParen: 455 // A left parenthesis ('('). 456 case CodeCompletionString::CK_RightParen: 457 // A right parenthesis (')'). 458 case CodeCompletionString::CK_LeftBracket: 459 // A left bracket ('['). 460 case CodeCompletionString::CK_RightBracket: 461 // A right bracket (']'). 462 case CodeCompletionString::CK_LeftBrace: 463 // A left brace ('{'). 464 case CodeCompletionString::CK_RightBrace: 465 // A right brace ('}'). 466 case CodeCompletionString::CK_LeftAngle: 467 // A left angle bracket ('<'). 468 case CodeCompletionString::CK_RightAngle: 469 // A right angle bracket ('>'). 470 case CodeCompletionString::CK_Comma: 471 // A comma separator (','). 472 case CodeCompletionString::CK_Colon: 473 // A colon (':'). 474 case CodeCompletionString::CK_SemiColon: 475 // A semicolon (';'). 476 case CodeCompletionString::CK_Equal: 477 // An '=' sign. 478 case CodeCompletionString::CK_HorizontalSpace: 479 // Horizontal whitespace (' '). 480 Item.insertText += Chunk.Text; 481 Item.label += Chunk.Text; 482 break; 483 case CodeCompletionString::CK_VerticalSpace: 484 // Vertical whitespace ('\n' or '\r\n', depending on the 485 // platform). 486 Item.insertText += Chunk.Text; 487 // Don't even add a space to the label. 488 break; 489 } 490 } 491 } 492 }; // SnippetCompletionItemsCollector 493 494 class SignatureHelpCollector final : public CodeCompleteConsumer { 495 496 public: 497 SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts, 498 SignatureHelp &SigHelp) 499 : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false), 500 SigHelp(SigHelp), 501 Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()), 502 CCTUInfo(Allocator) {} 503 504 void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, 505 OverloadCandidate *Candidates, 506 unsigned NumCandidates) override { 507 SigHelp.signatures.reserve(NumCandidates); 508 // FIXME(rwols): How can we determine the "active overload candidate"? 509 // Right now the overloaded candidates seem to be provided in a "best fit" 510 // order, so I'm not too worried about this. 511 SigHelp.activeSignature = 0; 512 assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() && 513 "too many arguments"); 514 SigHelp.activeParameter = static_cast<int>(CurrentArg); 515 for (unsigned I = 0; I < NumCandidates; ++I) { 516 const auto &Candidate = Candidates[I]; 517 const auto *CCS = Candidate.CreateSignatureString( 518 CurrentArg, S, *Allocator, CCTUInfo, true); 519 assert(CCS && "Expected the CodeCompletionString to be non-null"); 520 SigHelp.signatures.push_back(ProcessOverloadCandidate(Candidate, *CCS)); 521 } 522 } 523 524 GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; } 525 526 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } 527 528 private: 529 SignatureInformation 530 ProcessOverloadCandidate(const OverloadCandidate &Candidate, 531 const CodeCompletionString &CCS) const { 532 SignatureInformation Result; 533 const char *ReturnType = nullptr; 534 535 Result.documentation = getDocumentation(CCS); 536 537 for (const auto &Chunk : CCS) { 538 switch (Chunk.Kind) { 539 case CodeCompletionString::CK_ResultType: 540 // A piece of text that describes the type of an entity or, 541 // for functions and methods, the return type. 542 assert(!ReturnType && "Unexpected CK_ResultType"); 543 ReturnType = Chunk.Text; 544 break; 545 case CodeCompletionString::CK_Placeholder: 546 // A string that acts as a placeholder for, e.g., a function call 547 // argument. 548 // Intentional fallthrough here. 549 case CodeCompletionString::CK_CurrentParameter: { 550 // A piece of text that describes the parameter that corresponds to 551 // the code-completion location within a function call, message send, 552 // macro invocation, etc. 553 Result.label += Chunk.Text; 554 ParameterInformation Info; 555 Info.label = Chunk.Text; 556 Result.parameters.push_back(std::move(Info)); 557 break; 558 } 559 case CodeCompletionString::CK_Optional: { 560 // The rest of the parameters are defaulted/optional. 561 assert(Chunk.Optional && 562 "Expected the optional code completion string to be non-null."); 563 Result.label += 564 getOptionalParameters(*Chunk.Optional, Result.parameters); 565 break; 566 } 567 case CodeCompletionString::CK_VerticalSpace: 568 break; 569 default: 570 Result.label += Chunk.Text; 571 break; 572 } 573 } 574 if (ReturnType) { 575 Result.label += " -> "; 576 Result.label += ReturnType; 577 } 578 return Result; 579 } 580 581 SignatureHelp &SigHelp; 582 std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator; 583 CodeCompletionTUInfo CCTUInfo; 584 585 }; // SignatureHelpCollector 586 587 bool invokeCodeComplete(const Context &Ctx, 588 std::unique_ptr<CodeCompleteConsumer> Consumer, 589 const clang::CodeCompleteOptions &Options, 590 PathRef FileName, 591 const tooling::CompileCommand &Command, 592 PrecompiledPreamble const *Preamble, StringRef Contents, 593 Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS, 594 std::shared_ptr<PCHContainerOperations> PCHs) { 595 std::vector<const char *> ArgStrs; 596 for (const auto &S : Command.CommandLine) 597 ArgStrs.push_back(S.c_str()); 598 599 VFS->setCurrentWorkingDirectory(Command.Directory); 600 601 IgnoreDiagnostics DummyDiagsConsumer; 602 auto CI = createInvocationFromCommandLine( 603 ArgStrs, 604 CompilerInstance::createDiagnostics(new DiagnosticOptions, 605 &DummyDiagsConsumer, false), 606 VFS); 607 assert(CI && "Couldn't create CompilerInvocation"); 608 609 std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer = 610 llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName); 611 612 // Attempt to reuse the PCH from precompiled preamble, if it was built. 613 if (Preamble) { 614 auto Bounds = 615 ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0); 616 if (!Preamble->CanReuse(*CI, ContentsBuffer.get(), Bounds, VFS.get())) 617 Preamble = nullptr; 618 } 619 620 auto Clang = prepareCompilerInstance( 621 std::move(CI), Preamble, std::move(ContentsBuffer), std::move(PCHs), 622 std::move(VFS), DummyDiagsConsumer); 623 auto &DiagOpts = Clang->getDiagnosticOpts(); 624 DiagOpts.IgnoreWarnings = true; 625 626 auto &FrontendOpts = Clang->getFrontendOpts(); 627 FrontendOpts.SkipFunctionBodies = true; 628 FrontendOpts.CodeCompleteOpts = Options; 629 FrontendOpts.CodeCompletionAt.FileName = FileName; 630 FrontendOpts.CodeCompletionAt.Line = Pos.line + 1; 631 FrontendOpts.CodeCompletionAt.Column = Pos.character + 1; 632 633 Clang->setCodeCompletionConsumer(Consumer.release()); 634 635 SyntaxOnlyAction Action; 636 if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) { 637 log(Ctx, 638 "BeginSourceFile() failed when running codeComplete for " + FileName); 639 return false; 640 } 641 if (!Action.Execute()) { 642 log(Ctx, "Execute() failed when running codeComplete for " + FileName); 643 return false; 644 } 645 646 Action.EndSourceFile(); 647 648 return true; 649 } 650 651 } // namespace 652 653 clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const { 654 clang::CodeCompleteOptions Result; 655 Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns; 656 Result.IncludeMacros = IncludeMacros; 657 Result.IncludeGlobals = IncludeGlobals; 658 Result.IncludeBriefComments = IncludeBriefComments; 659 660 return Result; 661 } 662 663 CompletionList codeComplete(const Context &Ctx, PathRef FileName, 664 const tooling::CompileCommand &Command, 665 PrecompiledPreamble const *Preamble, 666 StringRef Contents, Position Pos, 667 IntrusiveRefCntPtr<vfs::FileSystem> VFS, 668 std::shared_ptr<PCHContainerOperations> PCHs, 669 CodeCompleteOptions Opts) { 670 CompletionList Results; 671 std::unique_ptr<CodeCompleteConsumer> Consumer; 672 if (Opts.EnableSnippets) { 673 Consumer = 674 llvm::make_unique<SnippetCompletionItemsCollector>(Opts, Results); 675 } else { 676 Consumer = 677 llvm::make_unique<PlainTextCompletionItemsCollector>(Opts, Results); 678 } 679 invokeCodeComplete(Ctx, std::move(Consumer), Opts.getClangCompleteOpts(), 680 FileName, Command, Preamble, Contents, Pos, std::move(VFS), 681 std::move(PCHs)); 682 return Results; 683 } 684 685 SignatureHelp signatureHelp(const Context &Ctx, PathRef FileName, 686 const tooling::CompileCommand &Command, 687 PrecompiledPreamble const *Preamble, 688 StringRef Contents, Position Pos, 689 IntrusiveRefCntPtr<vfs::FileSystem> VFS, 690 std::shared_ptr<PCHContainerOperations> PCHs) { 691 SignatureHelp Result; 692 clang::CodeCompleteOptions Options; 693 Options.IncludeGlobals = false; 694 Options.IncludeMacros = false; 695 Options.IncludeCodePatterns = false; 696 Options.IncludeBriefComments = true; 697 invokeCodeComplete(Ctx, 698 llvm::make_unique<SignatureHelpCollector>(Options, Result), 699 Options, FileName, Command, Preamble, Contents, Pos, 700 std::move(VFS), std::move(PCHs)); 701 return Result; 702 } 703 704 } // namespace clangd 705 } // namespace clang 706