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