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 "CodeCompletionStrings.h"
19 #include "Compiler.h"
20 #include "FuzzyMatch.h"
21 #include "Logger.h"
22 #include "index/Index.h"
23 #include "clang/Frontend/CompilerInstance.h"
24 #include "clang/Frontend/FrontendActions.h"
25 #include "clang/Sema/CodeCompleteConsumer.h"
26 #include "clang/Sema/Sema.h"
27 #include "llvm/Support/Format.h"
28 #include <queue>
29 
30 namespace clang {
31 namespace clangd {
32 namespace {
33 
34 CompletionItemKind toCompletionItemKind(CXCursorKind CursorKind) {
35   switch (CursorKind) {
36   case CXCursor_MacroInstantiation:
37   case CXCursor_MacroDefinition:
38     return CompletionItemKind::Text;
39   case CXCursor_CXXMethod:
40   case CXCursor_Destructor:
41     return CompletionItemKind::Method;
42   case CXCursor_FunctionDecl:
43   case CXCursor_FunctionTemplate:
44     return CompletionItemKind::Function;
45   case CXCursor_Constructor:
46     return CompletionItemKind::Constructor;
47   case CXCursor_FieldDecl:
48     return CompletionItemKind::Field;
49   case CXCursor_VarDecl:
50   case CXCursor_ParmDecl:
51     return CompletionItemKind::Variable;
52   // FIXME(ioeric): use LSP struct instead of class when it is suppoted in the
53   // protocol.
54   case CXCursor_StructDecl:
55   case CXCursor_ClassDecl:
56   case CXCursor_UnionDecl:
57   case CXCursor_ClassTemplate:
58   case CXCursor_ClassTemplatePartialSpecialization:
59     return CompletionItemKind::Class;
60   case CXCursor_Namespace:
61   case CXCursor_NamespaceAlias:
62   case CXCursor_NamespaceRef:
63     return CompletionItemKind::Module;
64   case CXCursor_EnumConstantDecl:
65     return CompletionItemKind::Value;
66   case CXCursor_EnumDecl:
67     return CompletionItemKind::Enum;
68   // FIXME(ioeric): figure out whether reference is the right type for aliases.
69   case CXCursor_TypeAliasDecl:
70   case CXCursor_TypeAliasTemplateDecl:
71   case CXCursor_TypedefDecl:
72   case CXCursor_MemberRef:
73   case CXCursor_TypeRef:
74     return CompletionItemKind::Reference;
75   default:
76     return CompletionItemKind::Missing;
77   }
78 }
79 
80 CompletionItemKind
81 toCompletionItemKind(CodeCompletionResult::ResultKind ResKind,
82                      CXCursorKind CursorKind) {
83   switch (ResKind) {
84   case CodeCompletionResult::RK_Declaration:
85     return toCompletionItemKind(CursorKind);
86   case CodeCompletionResult::RK_Keyword:
87     return CompletionItemKind::Keyword;
88   case CodeCompletionResult::RK_Macro:
89     return CompletionItemKind::Text; // unfortunately, there's no 'Macro'
90                                      // completion items in LSP.
91   case CodeCompletionResult::RK_Pattern:
92     return CompletionItemKind::Snippet;
93   }
94   llvm_unreachable("Unhandled CodeCompletionResult::ResultKind.");
95 }
96 
97 CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) {
98   using SK = index::SymbolKind;
99   switch (Kind) {
100   case SK::Unknown:
101     return CompletionItemKind::Missing;
102   case SK::Module:
103   case SK::Namespace:
104   case SK::NamespaceAlias:
105     return CompletionItemKind::Module;
106   case SK::Macro:
107     return CompletionItemKind::Text;
108   case SK::Enum:
109     return CompletionItemKind::Enum;
110   // FIXME(ioeric): use LSP struct instead of class when it is suppoted in the
111   // protocol.
112   case SK::Struct:
113   case SK::Class:
114   case SK::Protocol:
115   case SK::Extension:
116   case SK::Union:
117     return CompletionItemKind::Class;
118   // FIXME(ioeric): figure out whether reference is the right type for aliases.
119   case SK::TypeAlias:
120   case SK::Using:
121     return CompletionItemKind::Reference;
122   case SK::Function:
123   // FIXME(ioeric): this should probably be an operator. This should be fixed
124   // when `Operator` is support type in the protocol.
125   case SK::ConversionFunction:
126     return CompletionItemKind::Function;
127   case SK::Variable:
128   case SK::Parameter:
129     return CompletionItemKind::Variable;
130   case SK::Field:
131     return CompletionItemKind::Field;
132   // FIXME(ioeric): use LSP enum constant when it is supported in the protocol.
133   case SK::EnumConstant:
134     return CompletionItemKind::Value;
135   case SK::InstanceMethod:
136   case SK::ClassMethod:
137   case SK::StaticMethod:
138   case SK::Destructor:
139     return CompletionItemKind::Method;
140   case SK::InstanceProperty:
141   case SK::ClassProperty:
142   case SK::StaticProperty:
143     return CompletionItemKind::Property;
144   case SK::Constructor:
145     return CompletionItemKind::Constructor;
146   }
147   llvm_unreachable("Unhandled clang::index::SymbolKind.");
148 }
149 
150 /// Get the optional chunk as a string. This function is possibly recursive.
151 ///
152 /// The parameter info for each parameter is appended to the Parameters.
153 std::string
154 getOptionalParameters(const CodeCompletionString &CCS,
155                       std::vector<ParameterInformation> &Parameters) {
156   std::string Result;
157   for (const auto &Chunk : CCS) {
158     switch (Chunk.Kind) {
159     case CodeCompletionString::CK_Optional:
160       assert(Chunk.Optional &&
161              "Expected the optional code completion string to be non-null.");
162       Result += getOptionalParameters(*Chunk.Optional, Parameters);
163       break;
164     case CodeCompletionString::CK_VerticalSpace:
165       break;
166     case CodeCompletionString::CK_Placeholder:
167       // A string that acts as a placeholder for, e.g., a function call
168       // argument.
169       // Intentional fallthrough here.
170     case CodeCompletionString::CK_CurrentParameter: {
171       // A piece of text that describes the parameter that corresponds to
172       // the code-completion location within a function call, message send,
173       // macro invocation, etc.
174       Result += Chunk.Text;
175       ParameterInformation Info;
176       Info.label = Chunk.Text;
177       Parameters.push_back(std::move(Info));
178       break;
179     }
180     default:
181       Result += Chunk.Text;
182       break;
183     }
184   }
185   return Result;
186 }
187 
188 /// A scored code completion result.
189 /// It may be promoted to a CompletionItem if it's among the top-ranked results.
190 ///
191 /// We score candidates by multiplying the symbolScore ("quality" of the result)
192 /// with the filterScore (how well it matched the query).
193 /// This is sensitive to the distribution of both component scores!
194 struct CompletionCandidate {
195   CompletionCandidate(CodeCompletionResult &Result, float FilterScore)
196       : Result(&Result) {
197     Scores.symbolScore = score(Result);  // Higher is better.
198     Scores.filterScore = FilterScore;    // 0-1, higher is better.
199     Scores.finalScore = Scores.symbolScore * Scores.filterScore;
200   }
201 
202   CodeCompletionResult *Result;
203   CompletionItemScores Scores;
204 
205   // Comparison reflects rank: better candidates are smaller.
206   bool operator<(const CompletionCandidate &C) const {
207     if (Scores.finalScore != C.Scores.finalScore)
208       return Scores.finalScore > C.Scores.finalScore;
209     return *Result < *C.Result;
210   }
211 
212   // Returns a string that sorts in the same order as operator<, for LSP.
213   // Conceptually, this is [-Score, Name]. We convert -Score to an integer, and
214   // hex-encode it for readability. Example: [0.5, "foo"] -> "41000000foo"
215   std::string sortText() const {
216     std::string S, NameStorage;
217     llvm::raw_string_ostream OS(S);
218     write_hex(OS, encodeFloat(-Scores.finalScore), llvm::HexPrintStyle::Lower,
219               /*Width=*/2 * sizeof(Scores.finalScore));
220     OS << Result->getOrderedName(NameStorage);
221     return OS.str();
222   }
223 
224 private:
225   static float score(const CodeCompletionResult &Result) {
226     // Priority 80 is a really bad score.
227     float Score = 1 - std::min<float>(80, Result.Priority) / 80;
228 
229     switch (static_cast<CXAvailabilityKind>(Result.Availability)) {
230     case CXAvailability_Available:
231       // No penalty.
232       break;
233     case CXAvailability_Deprecated:
234       Score *= 0.1f;
235       break;
236     case CXAvailability_NotAccessible:
237     case CXAvailability_NotAvailable:
238       Score = 0;
239       break;
240     }
241     return Score;
242   }
243 
244   // Produces an integer that sorts in the same order as F.
245   // That is: a < b <==> encodeFloat(a) < encodeFloat(b).
246   static uint32_t encodeFloat(float F) {
247     static_assert(std::numeric_limits<float>::is_iec559, "");
248     static_assert(sizeof(float) == sizeof(uint32_t), "");
249     constexpr uint32_t TopBit = ~(~uint32_t{0} >> 1);
250 
251     // Get the bits of the float. Endianness is the same as for integers.
252     uint32_t U;
253     memcpy(&U, &F, sizeof(float));
254     // IEEE 754 floats compare like sign-magnitude integers.
255     if (U & TopBit)    // Negative float.
256       return 0 - U;    // Map onto the low half of integers, order reversed.
257     return U + TopBit; // Positive floats map onto the high half of integers.
258   }
259 };
260 
261 /// \brief Information about the scope specifier in the qualified-id code
262 /// completion (e.g. "ns::ab?").
263 struct SpecifiedScope {
264   /// The scope specifier as written. For example, for completion "ns::ab?", the
265   /// written scope specifier is "ns".
266   std::string Written;
267   // If this scope specifier is recognized in Sema (e.g. as a namespace
268   // context), this will be set to the fully qualfied name of the corresponding
269   // context.
270   std::string Resolved;
271 };
272 
273 /// \brief Information from sema about (parital) symbol names to be completed.
274 /// For example, for completion "ns::ab^", this stores the scope specifier
275 /// "ns::" and the completion filter text "ab".
276 struct NameToComplete {
277   // The partial identifier being completed, without qualifier.
278   std::string Filter;
279 
280   /// This is set if the completion is for qualified IDs, e.g. "abc::x^".
281   llvm::Optional<SpecifiedScope> SSInfo;
282 };
283 
284 SpecifiedScope extraCompletionScope(Sema &S, const CXXScopeSpec &SS);
285 
286 class CompletionItemsCollector : public CodeCompleteConsumer {
287 public:
288   CompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
289                            CompletionList &Items, NameToComplete &CompletedName)
290       : CodeCompleteConsumer(CodeCompleteOpts.getClangCompleteOpts(),
291                              /*OutputIsBinary=*/false),
292         ClangdOpts(CodeCompleteOpts), Items(Items),
293         Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
294         CCTUInfo(Allocator), CompletedName(CompletedName),
295         EnableSnippets(CodeCompleteOpts.EnableSnippets) {}
296 
297   void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
298                                   CodeCompletionResult *Results,
299                                   unsigned NumResults) override final {
300     FuzzyMatcher Filter(S.getPreprocessor().getCodeCompletionFilter());
301     if (auto SS = Context.getCXXScopeSpecifier())
302       CompletedName.SSInfo = extraCompletionScope(S, **SS);
303 
304     CompletedName.Filter = S.getPreprocessor().getCodeCompletionFilter();
305     std::priority_queue<CompletionCandidate> Candidates;
306     for (unsigned I = 0; I < NumResults; ++I) {
307       auto &Result = Results[I];
308       // We drop hidden items, as they cannot be found by the lookup after
309       // inserting the corresponding completion item and only produce noise and
310       // duplicates in the completion list. However, there is one exception. If
311       // Result has a Qualifier which is non-informative, we can refer to an
312       // item by adding that qualifier, so we don't filter out this item.
313       if (Result.Hidden && (!Result.Qualifier || Result.QualifierIsInformative))
314         continue;
315       if (!ClangdOpts.IncludeIneligibleResults &&
316           (Result.Availability == CXAvailability_NotAvailable ||
317            Result.Availability == CXAvailability_NotAccessible))
318         continue;
319       auto FilterScore = fuzzyMatch(S, Context, Filter, Result);
320       if (!FilterScore)
321         continue;
322       Candidates.emplace(Result, *FilterScore);
323       if (ClangdOpts.Limit && Candidates.size() > ClangdOpts.Limit) {
324         Candidates.pop();
325         Items.isIncomplete = true;
326       }
327     }
328     while (!Candidates.empty()) {
329       auto &Candidate = Candidates.top();
330       const auto *CCS = Candidate.Result->CreateCodeCompletionString(
331           S, Context, *Allocator, CCTUInfo,
332           CodeCompleteOpts.IncludeBriefComments);
333       assert(CCS && "Expected the CodeCompletionString to be non-null");
334       Items.items.push_back(ProcessCodeCompleteResult(Candidate, *CCS));
335       Candidates.pop();
336     }
337     std::reverse(Items.items.begin(), Items.items.end());
338   }
339 
340   GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
341 
342   CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
343 
344 private:
345   llvm::Optional<float> fuzzyMatch(Sema &S, const CodeCompletionContext &CCCtx,
346                                    FuzzyMatcher &Filter,
347                                    CodeCompletionResult Result) {
348     switch (Result.Kind) {
349     case CodeCompletionResult::RK_Declaration:
350       if (auto *ID = Result.Declaration->getIdentifier())
351         return Filter.match(ID->getName());
352       break;
353     case CodeCompletionResult::RK_Keyword:
354       return Filter.match(Result.Keyword);
355     case CodeCompletionResult::RK_Macro:
356       return Filter.match(Result.Macro->getName());
357     case CodeCompletionResult::RK_Pattern:
358       return Filter.match(Result.Pattern->getTypedText());
359     }
360     auto *CCS = Result.CreateCodeCompletionString(
361         S, CCCtx, *Allocator, CCTUInfo, /*IncludeBriefComments=*/false);
362     return Filter.match(CCS->getTypedText());
363   }
364 
365   CompletionItem
366   ProcessCodeCompleteResult(const CompletionCandidate &Candidate,
367                             const CodeCompletionString &CCS) const {
368 
369     // Adjust this to InsertTextFormat::Snippet iff we encounter a
370     // CK_Placeholder chunk in SnippetCompletionItemsCollector.
371     CompletionItem Item;
372 
373     Item.documentation = getDocumentation(CCS);
374     Item.sortText = Candidate.sortText();
375     Item.scoreInfo = Candidate.Scores;
376 
377     Item.detail = getDetail(CCS);
378     Item.filterText = getFilterText(CCS);
379     getLabelAndInsertText(CCS, &Item.label, &Item.insertText, EnableSnippets);
380 
381     Item.insertTextFormat = EnableSnippets ? InsertTextFormat::Snippet
382                                            : InsertTextFormat::PlainText;
383 
384     // Fill in the kind field of the CompletionItem.
385     Item.kind = toCompletionItemKind(Candidate.Result->Kind,
386                                      Candidate.Result->CursorKind);
387 
388     return Item;
389   }
390 
391   CodeCompleteOptions ClangdOpts;
392   CompletionList &Items;
393   std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
394   CodeCompletionTUInfo CCTUInfo;
395   NameToComplete &CompletedName;
396   bool EnableSnippets;
397 }; // CompletionItemsCollector
398 
399 class SignatureHelpCollector final : public CodeCompleteConsumer {
400 
401 public:
402   SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
403                          SignatureHelp &SigHelp)
404       : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
405         SigHelp(SigHelp),
406         Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
407         CCTUInfo(Allocator) {}
408 
409   void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
410                                  OverloadCandidate *Candidates,
411                                  unsigned NumCandidates) override {
412     SigHelp.signatures.reserve(NumCandidates);
413     // FIXME(rwols): How can we determine the "active overload candidate"?
414     // Right now the overloaded candidates seem to be provided in a "best fit"
415     // order, so I'm not too worried about this.
416     SigHelp.activeSignature = 0;
417     assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&
418            "too many arguments");
419     SigHelp.activeParameter = static_cast<int>(CurrentArg);
420     for (unsigned I = 0; I < NumCandidates; ++I) {
421       const auto &Candidate = Candidates[I];
422       const auto *CCS = Candidate.CreateSignatureString(
423           CurrentArg, S, *Allocator, CCTUInfo, true);
424       assert(CCS && "Expected the CodeCompletionString to be non-null");
425       SigHelp.signatures.push_back(ProcessOverloadCandidate(Candidate, *CCS));
426     }
427   }
428 
429   GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
430 
431   CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
432 
433 private:
434   // FIXME(ioeric): consider moving CodeCompletionString logic here to
435   // CompletionString.h.
436   SignatureInformation
437   ProcessOverloadCandidate(const OverloadCandidate &Candidate,
438                            const CodeCompletionString &CCS) const {
439     SignatureInformation Result;
440     const char *ReturnType = nullptr;
441 
442     Result.documentation = getDocumentation(CCS);
443 
444     for (const auto &Chunk : CCS) {
445       switch (Chunk.Kind) {
446       case CodeCompletionString::CK_ResultType:
447         // A piece of text that describes the type of an entity or,
448         // for functions and methods, the return type.
449         assert(!ReturnType && "Unexpected CK_ResultType");
450         ReturnType = Chunk.Text;
451         break;
452       case CodeCompletionString::CK_Placeholder:
453         // A string that acts as a placeholder for, e.g., a function call
454         // argument.
455         // Intentional fallthrough here.
456       case CodeCompletionString::CK_CurrentParameter: {
457         // A piece of text that describes the parameter that corresponds to
458         // the code-completion location within a function call, message send,
459         // macro invocation, etc.
460         Result.label += Chunk.Text;
461         ParameterInformation Info;
462         Info.label = Chunk.Text;
463         Result.parameters.push_back(std::move(Info));
464         break;
465       }
466       case CodeCompletionString::CK_Optional: {
467         // The rest of the parameters are defaulted/optional.
468         assert(Chunk.Optional &&
469                "Expected the optional code completion string to be non-null.");
470         Result.label +=
471             getOptionalParameters(*Chunk.Optional, Result.parameters);
472         break;
473       }
474       case CodeCompletionString::CK_VerticalSpace:
475         break;
476       default:
477         Result.label += Chunk.Text;
478         break;
479       }
480     }
481     if (ReturnType) {
482       Result.label += " -> ";
483       Result.label += ReturnType;
484     }
485     return Result;
486   }
487 
488   SignatureHelp &SigHelp;
489   std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
490   CodeCompletionTUInfo CCTUInfo;
491 
492 }; // SignatureHelpCollector
493 
494 bool invokeCodeComplete(const Context &Ctx,
495                         std::unique_ptr<CodeCompleteConsumer> Consumer,
496                         const clang::CodeCompleteOptions &Options,
497                         PathRef FileName,
498                         const tooling::CompileCommand &Command,
499                         PrecompiledPreamble const *Preamble, StringRef Contents,
500                         Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
501                         std::shared_ptr<PCHContainerOperations> PCHs) {
502   std::vector<const char *> ArgStrs;
503   for (const auto &S : Command.CommandLine)
504     ArgStrs.push_back(S.c_str());
505 
506   VFS->setCurrentWorkingDirectory(Command.Directory);
507 
508   IgnoreDiagnostics DummyDiagsConsumer;
509   auto CI = createInvocationFromCommandLine(
510       ArgStrs,
511       CompilerInstance::createDiagnostics(new DiagnosticOptions,
512                                           &DummyDiagsConsumer, false),
513       VFS);
514   assert(CI && "Couldn't create CompilerInvocation");
515   CI->getFrontendOpts().DisableFree = false;
516 
517   std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
518       llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName);
519 
520   // Attempt to reuse the PCH from precompiled preamble, if it was built.
521   if (Preamble) {
522     auto Bounds =
523         ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0);
524     if (!Preamble->CanReuse(*CI, ContentsBuffer.get(), Bounds, VFS.get()))
525       Preamble = nullptr;
526   }
527 
528   auto Clang = prepareCompilerInstance(
529       std::move(CI), Preamble, std::move(ContentsBuffer), std::move(PCHs),
530       std::move(VFS), DummyDiagsConsumer);
531   auto &DiagOpts = Clang->getDiagnosticOpts();
532   DiagOpts.IgnoreWarnings = true;
533 
534   auto &FrontendOpts = Clang->getFrontendOpts();
535   FrontendOpts.SkipFunctionBodies = true;
536   FrontendOpts.CodeCompleteOpts = Options;
537   FrontendOpts.CodeCompletionAt.FileName = FileName;
538   FrontendOpts.CodeCompletionAt.Line = Pos.line + 1;
539   FrontendOpts.CodeCompletionAt.Column = Pos.character + 1;
540 
541   Clang->setCodeCompletionConsumer(Consumer.release());
542 
543   SyntaxOnlyAction Action;
544   if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
545     log(Ctx,
546         "BeginSourceFile() failed when running codeComplete for " + FileName);
547     return false;
548   }
549   if (!Action.Execute()) {
550     log(Ctx, "Execute() failed when running codeComplete for " + FileName);
551     return false;
552   }
553 
554   Action.EndSourceFile();
555 
556   return true;
557 }
558 
559 CompletionItem indexCompletionItem(const Symbol &Sym, llvm::StringRef Filter,
560                                    const SpecifiedScope &SSInfo,
561                                    llvm::StringRef DebuggingLabel = "") {
562   CompletionItem Item;
563   Item.kind = toCompletionItemKind(Sym.SymInfo.Kind);
564   // Add DebuggingLabel to the completion results if DebuggingLabel is not
565   // empty.
566   //
567   // For symbols from static index, there are prefix "[G]" in the
568   // results (which is used for debugging purpose).
569   // So completion list will be like:
570   //   clang::symbol_from_dynamic_index
571   //   [G]clang::symbol_from_static_index
572   //
573   // FIXME: Find out a better way to show the index source.
574   if (!DebuggingLabel.empty()) {
575     llvm::raw_string_ostream Label(Item.label);
576     Label << llvm::format("[%s]%s", DebuggingLabel.str().c_str(),
577                           Sym.Name.str().c_str());
578   } else {
579     Item.label = Sym.Name;
580   }
581   // FIXME(ioeric): support inserting/replacing scope qualifiers.
582 
583   // FIXME(ioeric): support snippets.
584   Item.insertText = Sym.CompletionPlainInsertText;
585   Item.insertTextFormat = InsertTextFormat::PlainText;
586   Item.filterText = Sym.Name;
587 
588   // FIXME(ioeric): sort symbols appropriately.
589   Item.sortText = "";
590 
591   if (Sym.Detail) {
592     Item.documentation = Sym.Detail->Documentation;
593     Item.detail = Sym.Detail->CompletionDetail;
594   }
595 
596   return Item;
597 }
598 
599 void completeWithIndex(const Context &Ctx, const SymbolIndex &Index,
600                        llvm::StringRef Code, const SpecifiedScope &SSInfo,
601                        llvm::StringRef Filter, CompletionList *Items,
602                        llvm::StringRef DebuggingLabel = "") {
603   FuzzyFindRequest Req;
604   Req.Query = Filter;
605   // FIXME(ioeric): add more possible scopes based on using namespaces and
606   // containing namespaces.
607   StringRef Scope = SSInfo.Resolved.empty() ? SSInfo.Written : SSInfo.Resolved;
608   Req.Scopes = {Scope.trim(':').str()};
609 
610   Items->isIncomplete |= !Index.fuzzyFind(Ctx, Req, [&](const Symbol &Sym) {
611     Items->items.push_back(
612         indexCompletionItem(Sym, Filter, SSInfo, DebuggingLabel));
613   });
614 }
615 
616 SpecifiedScope extraCompletionScope(Sema &S, const CXXScopeSpec &SS) {
617   SpecifiedScope Info;
618   auto &SM = S.getSourceManager();
619   auto SpecifierRange = SS.getRange();
620   Info.Written = Lexer::getSourceText(
621       CharSourceRange::getCharRange(SpecifierRange), SM, clang::LangOptions());
622   if (SS.isValid()) {
623     DeclContext *DC = S.computeDeclContext(SS);
624     if (auto *NS = llvm::dyn_cast<NamespaceDecl>(DC)) {
625       Info.Resolved = NS->getQualifiedNameAsString();
626     } else if (llvm::dyn_cast<TranslationUnitDecl>(DC) != nullptr) {
627       Info.Resolved = "::";
628       // Sema does not include the suffix "::" in the range of SS, so we add
629       // it back here.
630       Info.Written = "::";
631     }
632   }
633   return Info;
634 }
635 
636 } // namespace
637 
638 clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
639   clang::CodeCompleteOptions Result;
640   Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns;
641   Result.IncludeMacros = IncludeMacros;
642   Result.IncludeGlobals = IncludeGlobals;
643   Result.IncludeBriefComments = IncludeBriefComments;
644 
645   // When an is used, Sema is responsible for completing the main file,
646   // the index can provide results from the preamble.
647   // Tell Sema not to deserialize the preamble to look for results.
648   Result.LoadExternal = !Index;
649 
650   return Result;
651 }
652 
653 CompletionList codeComplete(const Context &Ctx, PathRef FileName,
654                             const tooling::CompileCommand &Command,
655                             PrecompiledPreamble const *Preamble,
656                             StringRef Contents, Position Pos,
657                             IntrusiveRefCntPtr<vfs::FileSystem> VFS,
658                             std::shared_ptr<PCHContainerOperations> PCHs,
659                             CodeCompleteOptions Opts) {
660   CompletionList Results;
661   NameToComplete CompletedName;
662   auto Consumer =
663       llvm::make_unique<CompletionItemsCollector>(Opts, Results, CompletedName);
664   invokeCodeComplete(Ctx, std::move(Consumer), Opts.getClangCompleteOpts(),
665                      FileName, Command, Preamble, Contents, Pos, std::move(VFS),
666                      std::move(PCHs));
667 
668   // Got scope specifier (ns::f^) for code completion from sema, try to query
669   // global symbols from indexes.
670   // FIXME: merge with Sema results, and respect limits.
671   if (CompletedName.SSInfo && Opts.Index)
672     completeWithIndex(Ctx, *Opts.Index, Contents, *CompletedName.SSInfo,
673                       CompletedName.Filter, &Results, /*DebuggingLabel=*/"I");
674   return Results;
675 }
676 
677 SignatureHelp signatureHelp(const Context &Ctx, PathRef FileName,
678                             const tooling::CompileCommand &Command,
679                             PrecompiledPreamble const *Preamble,
680                             StringRef Contents, Position Pos,
681                             IntrusiveRefCntPtr<vfs::FileSystem> VFS,
682                             std::shared_ptr<PCHContainerOperations> PCHs) {
683   SignatureHelp Result;
684   clang::CodeCompleteOptions Options;
685   Options.IncludeGlobals = false;
686   Options.IncludeMacros = false;
687   Options.IncludeCodePatterns = false;
688   Options.IncludeBriefComments = true;
689   invokeCodeComplete(Ctx,
690                      llvm::make_unique<SignatureHelpCollector>(Options, Result),
691                      Options, FileName, Command, Preamble, Contents, Pos,
692                      std::move(VFS), std::move(PCHs));
693   return Result;
694 }
695 
696 } // namespace clangd
697 } // namespace clang
698