1 //===--- IncludeFixer.cpp ----------------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "IncludeFixer.h"
10 #include "AST.h"
11 #include "Diagnostics.h"
12 #include "SourceCode.h"
13 #include "index/Index.h"
14 #include "index/Symbol.h"
15 #include "support/Logger.h"
16 #include "support/Trace.h"
17 #include "clang/AST/Decl.h"
18 #include "clang/AST/DeclBase.h"
19 #include "clang/AST/DeclarationName.h"
20 #include "clang/AST/NestedNameSpecifier.h"
21 #include "clang/AST/Type.h"
22 #include "clang/Basic/Diagnostic.h"
23 #include "clang/Basic/DiagnosticParse.h"
24 #include "clang/Basic/DiagnosticSema.h"
25 #include "clang/Basic/LangOptions.h"
26 #include "clang/Basic/SourceLocation.h"
27 #include "clang/Basic/SourceManager.h"
28 #include "clang/Basic/TokenKinds.h"
29 #include "clang/Lex/Lexer.h"
30 #include "clang/Sema/DeclSpec.h"
31 #include "clang/Sema/Lookup.h"
32 #include "clang/Sema/Scope.h"
33 #include "clang/Sema/Sema.h"
34 #include "clang/Sema/TypoCorrection.h"
35 #include "llvm/ADT/DenseMap.h"
36 #include "llvm/ADT/None.h"
37 #include "llvm/ADT/Optional.h"
38 #include "llvm/ADT/STLExtras.h"
39 #include "llvm/ADT/StringExtras.h"
40 #include "llvm/ADT/StringRef.h"
41 #include "llvm/ADT/StringSet.h"
42 #include "llvm/Support/Error.h"
43 #include "llvm/Support/FormatVariadic.h"
44 #include <algorithm>
45 #include <set>
46 #include <string>
47 #include <vector>
48 
49 namespace clang {
50 namespace clangd {
51 namespace {
52 
getArgStr(const clang::Diagnostic & Info,unsigned Index)53 llvm::Optional<llvm::StringRef> getArgStr(const clang::Diagnostic &Info,
54                                           unsigned Index) {
55   switch (Info.getArgKind(Index)) {
56   case DiagnosticsEngine::ak_c_string:
57     return llvm::StringRef(Info.getArgCStr(Index));
58   case DiagnosticsEngine::ak_std_string:
59     return llvm::StringRef(Info.getArgStdStr(Index));
60   default:
61     return llvm::None;
62   }
63 }
64 
only(llvm::Optional<Fix> F)65 std::vector<Fix> only(llvm::Optional<Fix> F) {
66   if (F)
67     return {std::move(*F)};
68   return {};
69 }
70 
71 } // namespace
72 
fix(DiagnosticsEngine::Level DiagLevel,const clang::Diagnostic & Info) const73 std::vector<Fix> IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel,
74                                    const clang::Diagnostic &Info) const {
75   switch (Info.getID()) {
76   /*
77    There are many "incomplete type" diagnostics!
78    They are almost all Sema diagnostics with "incomplete" in the name.
79 
80    sed -n '/CLASS_NOTE/! s/DIAG(\\([^,]*\\).*)/  case diag::\\1:/p' \
81      tools/clang/include/clang/Basic/DiagnosticSemaKinds.inc | grep incomplete
82   */
83   // clang-format off
84   //case diag::err_alignof_member_of_incomplete_type:
85   case diag::err_array_incomplete_or_sizeless_type:
86   case diag::err_array_size_incomplete_type:
87   case diag::err_asm_incomplete_type:
88   case diag::err_assoc_type_incomplete:
89   case diag::err_bad_cast_incomplete:
90   case diag::err_call_function_incomplete_return:
91   case diag::err_call_incomplete_argument:
92   case diag::err_call_incomplete_return:
93   case diag::err_capture_of_incomplete_or_sizeless_type:
94   case diag::err_catch_incomplete:
95   case diag::err_catch_incomplete_ptr:
96   case diag::err_catch_incomplete_ref:
97   case diag::err_cconv_incomplete_param_type:
98   case diag::err_coroutine_promise_type_incomplete:
99   case diag::err_covariant_return_incomplete:
100   //case diag::err_deduced_class_template_incomplete:
101   case diag::err_delete_incomplete_class_type:
102   case diag::err_dereference_incomplete_type:
103   case diag::err_exception_spec_incomplete_type:
104   case diag::err_field_incomplete_or_sizeless:
105   case diag::err_for_range_incomplete_type:
106   case diag::err_func_def_incomplete_result:
107   case diag::err_ice_incomplete_type:
108   case diag::err_illegal_message_expr_incomplete_type:
109   case diag::err_incomplete_base_class:
110   case diag::err_incomplete_enum:
111   case diag::err_incomplete_in_exception_spec:
112   case diag::err_incomplete_member_access:
113   case diag::err_incomplete_nested_name_spec:
114   case diag::err_incomplete_object_call:
115   case diag::err_incomplete_receiver_type:
116   case diag::err_incomplete_synthesized_property:
117   case diag::err_incomplete_type:
118   case diag::err_incomplete_type_objc_at_encode:
119   case diag::err_incomplete_type_used_in_type_trait_expr:
120   case diag::err_incomplete_typeid:
121   case diag::err_init_incomplete_type:
122   case diag::err_invalid_incomplete_type_use:
123   case diag::err_lambda_incomplete_result:
124   //case diag::err_matrix_incomplete_index:
125   //case diag::err_matrix_separate_incomplete_index:
126   case diag::err_memptr_incomplete:
127   case diag::err_new_incomplete_or_sizeless_type:
128   case diag::err_objc_incomplete_boxed_expression_type:
129   case diag::err_objc_index_incomplete_class_type:
130   case diag::err_offsetof_incomplete_type:
131   case diag::err_omp_firstprivate_incomplete_type:
132   case diag::err_omp_incomplete_type:
133   case diag::err_omp_lastprivate_incomplete_type:
134   case diag::err_omp_linear_incomplete_type:
135   case diag::err_omp_private_incomplete_type:
136   case diag::err_omp_reduction_incomplete_type:
137   case diag::err_omp_section_incomplete_type:
138   case diag::err_omp_threadprivate_incomplete_type:
139   case diag::err_second_parameter_to_va_arg_incomplete:
140   case diag::err_sizeof_alignof_incomplete_or_sizeless_type:
141   case diag::err_subscript_incomplete_or_sizeless_type:
142   case diag::err_switch_incomplete_class_type:
143   case diag::err_temp_copy_incomplete:
144   //case diag::err_template_arg_deduced_incomplete_pack:
145   case diag::err_template_nontype_parm_incomplete:
146   //case diag::err_tentative_def_incomplete_type:
147   case diag::err_throw_incomplete:
148   case diag::err_throw_incomplete_ptr:
149   case diag::err_typecheck_arithmetic_incomplete_or_sizeless_type:
150   case diag::err_typecheck_cast_to_incomplete:
151   case diag::err_typecheck_decl_incomplete_type:
152   //case diag::err_typecheck_incomplete_array_needs_initializer:
153   case diag::err_typecheck_incomplete_tag:
154   case diag::err_typecheck_incomplete_type_not_modifiable_lvalue:
155   case diag::err_typecheck_nonviable_condition_incomplete:
156   case diag::err_underlying_type_of_incomplete_enum:
157   case diag::ext_incomplete_in_exception_spec:
158   //case diag::ext_typecheck_compare_complete_incomplete_pointers:
159   case diag::ext_typecheck_decl_incomplete_type:
160   case diag::warn_delete_incomplete:
161   case diag::warn_incomplete_encoded_type:
162   //case diag::warn_printf_incomplete_specifier:
163   case diag::warn_return_value_udt_incomplete:
164   //case diag::warn_scanf_scanlist_incomplete:
165   //case diag::warn_tentative_incomplete_array:
166     //  clang-format on
167     // Incomplete type diagnostics should have a QualType argument for the
168     // incomplete type.
169     for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) {
170       if (Info.getArgKind(Idx) == DiagnosticsEngine::ak_qualtype) {
171         auto QT = QualType::getFromOpaquePtr((void *)Info.getRawArg(Idx));
172         if (const Type *T = QT.getTypePtrOrNull()) {
173           if (T->isIncompleteType())
174             return fixIncompleteType(*T);
175           // `enum x : int;' is not formally an incomplete type.
176           // We may need a full definition anyway.
177           if (auto * ET = llvm::dyn_cast<EnumType>(T))
178             if (!ET->getDecl()->getDefinition())
179               return fixIncompleteType(*T);
180         }
181       }
182     }
183     break;
184 
185   case diag::err_unknown_typename:
186   case diag::err_unknown_typename_suggest:
187   case diag::err_unknown_type_or_class_name_suggest:
188   case diag::err_expected_class_name:
189   case diag::err_typename_nested_not_found:
190   case diag::err_no_template:
191   case diag::err_no_template_suggest:
192   case diag::err_undeclared_use:
193   case diag::err_undeclared_use_suggest:
194   case diag::err_undeclared_var_use:
195   case diag::err_undeclared_var_use_suggest:
196   case diag::err_no_member: // Could be no member in namespace.
197   case diag::err_no_member_suggest:
198   case diag::err_no_member_template:
199   case diag::err_no_member_template_suggest:
200   case diag::warn_implicit_function_decl:
201   case diag::ext_implicit_function_decl_c99:
202     dlog("Unresolved name at {0}, last typo was {1}",
203          Info.getLocation().printToString(Info.getSourceManager()),
204          LastUnresolvedName
205              ? LastUnresolvedName->Loc.printToString(Info.getSourceManager())
206              : "none");
207     if (LastUnresolvedName) {
208       // Try to fix unresolved name caused by missing declaration.
209       // E.g.
210       //   clang::SourceManager SM;
211       //          ~~~~~~~~~~~~~
212       //          UnresolvedName
213       //   or
214       //   namespace clang {  SourceManager SM; }
215       //                      ~~~~~~~~~~~~~
216       //                      UnresolvedName
217       // We only attempt to recover a diagnostic if it has the same location as
218       // the last seen unresolved name.
219       if (LastUnresolvedName->Loc == Info.getLocation())
220         return fixUnresolvedName();
221     }
222     break;
223 
224   // Cases where clang explicitly knows which header to include.
225   // (There's no fix provided for boring formatting reasons).
226   case diag::err_implied_std_initializer_list_not_found:
227     return only(insertHeader("<initializer_list>"));
228   case diag::err_need_header_before_typeid:
229     return only(insertHeader("<typeid>"));
230   case diag::err_need_header_before_placement_new:
231   case diag::err_implicit_coroutine_std_nothrow_type_not_found:
232     return only(insertHeader("<new>"));
233   case diag::err_omp_implied_type_not_found:
234   case diag::err_omp_interop_type_not_found:
235     return only(insertHeader("<omp.h>"));
236   case diag::err_implied_coroutine_type_not_found:
237     return only(insertHeader("<coroutine>"));
238   case diag::err_implied_comparison_category_type_not_found:
239     return only(insertHeader("<compare>"));
240   case diag::note_include_header_or_declare:
241     if (Info.getNumArgs() > 0)
242       if (auto Header = getArgStr(Info, 0))
243         return only(insertHeader(("<" + *Header + ">").str(),
244                                  getArgStr(Info, 1).value_or("")));
245     break;
246   }
247 
248   return {};
249 }
250 
insertHeader(llvm::StringRef Spelled,llvm::StringRef Symbol) const251 llvm::Optional<Fix> IncludeFixer::insertHeader(llvm::StringRef Spelled,
252                                                llvm::StringRef Symbol) const {
253   Fix F;
254 
255   if (auto Edit = Inserter->insert(Spelled))
256     F.Edits.push_back(std::move(*Edit));
257   else
258     return llvm::None;
259 
260   if (Symbol.empty())
261     F.Message = llvm::formatv("Include {0}", Spelled);
262   else
263     F.Message = llvm::formatv("Include {0} for symbol {1}", Spelled, Symbol);
264 
265   return F;
266 }
267 
fixIncompleteType(const Type & T) const268 std::vector<Fix> IncludeFixer::fixIncompleteType(const Type &T) const {
269   // Only handle incomplete TagDecl type.
270   const TagDecl *TD = T.getAsTagDecl();
271   if (!TD)
272     return {};
273   std::string TypeName = printQualifiedName(*TD);
274   trace::Span Tracer("Fix include for incomplete type");
275   SPAN_ATTACH(Tracer, "type", TypeName);
276   vlog("Trying to fix include for incomplete type {0}", TypeName);
277 
278   auto ID = getSymbolID(TD);
279   if (!ID)
280     return {};
281   llvm::Optional<const SymbolSlab *> Symbols = lookupCached(ID);
282   if (!Symbols)
283     return {};
284   const SymbolSlab &Syms = **Symbols;
285   std::vector<Fix> Fixes;
286   if (!Syms.empty()) {
287     auto &Matched = *Syms.begin();
288     if (!Matched.IncludeHeaders.empty() && Matched.Definition &&
289         Matched.CanonicalDeclaration.FileURI == Matched.Definition.FileURI)
290       Fixes = fixesForSymbols(Syms);
291   }
292   return Fixes;
293 }
294 
fixesForSymbols(const SymbolSlab & Syms) const295 std::vector<Fix> IncludeFixer::fixesForSymbols(const SymbolSlab &Syms) const {
296   auto Inserted = [&](const Symbol &Sym, llvm::StringRef Header)
297       -> llvm::Expected<std::pair<std::string, bool>> {
298     auto ResolvedDeclaring =
299         URI::resolve(Sym.CanonicalDeclaration.FileURI, File);
300     if (!ResolvedDeclaring)
301       return ResolvedDeclaring.takeError();
302     auto ResolvedInserted = toHeaderFile(Header, File);
303     if (!ResolvedInserted)
304       return ResolvedInserted.takeError();
305     auto Spelled = Inserter->calculateIncludePath(*ResolvedInserted, File);
306     if (!Spelled)
307       return error("Header not on include path");
308     return std::make_pair(
309         std::move(*Spelled),
310         Inserter->shouldInsertInclude(*ResolvedDeclaring, *ResolvedInserted));
311   };
312 
313   std::vector<Fix> Fixes;
314   // Deduplicate fixes by include headers. This doesn't distinguish symbols in
315   // different scopes from the same header, but this case should be rare and is
316   // thus ignored.
317   llvm::StringSet<> InsertedHeaders;
318   for (const auto &Sym : Syms) {
319     for (const auto &Inc : getRankedIncludes(Sym)) {
320       if (auto ToInclude = Inserted(Sym, Inc)) {
321         if (ToInclude->second) {
322           if (!InsertedHeaders.try_emplace(ToInclude->first).second)
323             continue;
324           if (auto Fix =
325                   insertHeader(ToInclude->first, (Sym.Scope + Sym.Name).str()))
326             Fixes.push_back(std::move(*Fix));
327         }
328       } else {
329         vlog("Failed to calculate include insertion for {0} into {1}: {2}", Inc,
330              File, ToInclude.takeError());
331       }
332     }
333   }
334   return Fixes;
335 }
336 
337 // Returns the identifiers qualified by an unresolved name. \p Loc is the
338 // start location of the unresolved name. For the example below, this returns
339 // "::X::Y" that is qualified by unresolved name "clangd":
340 //     clang::clangd::X::Y
341 //            ~
qualifiedByUnresolved(const SourceManager & SM,SourceLocation Loc,const LangOptions & LangOpts)342 llvm::Optional<std::string> qualifiedByUnresolved(const SourceManager &SM,
343                                                   SourceLocation Loc,
344                                                   const LangOptions &LangOpts) {
345   std::string Result;
346   // Accept qualifier written within macro arguments, but not macro bodies.
347   SourceLocation NextLoc = SM.getTopMacroCallerLoc(Loc);
348   while (auto CCTok = Lexer::findNextToken(NextLoc, SM, LangOpts)) {
349     if (!CCTok->is(tok::coloncolon))
350       break;
351     auto IDTok = Lexer::findNextToken(CCTok->getLocation(), SM, LangOpts);
352     if (!IDTok || !IDTok->is(tok::raw_identifier))
353       break;
354     Result.append(("::" + IDTok->getRawIdentifier()).str());
355     NextLoc = IDTok->getLocation();
356   }
357   if (Result.empty())
358     return llvm::None;
359   return Result;
360 }
361 
362 // An unresolved name and its scope information that can be extracted cheaply.
363 struct CheapUnresolvedName {
364   std::string Name;
365   // This is the part of what was typed that was resolved, and it's in its
366   // resolved form not its typed form (think `namespace clang { clangd::x }` -->
367   // `clang::clangd::`).
368   llvm::Optional<std::string> ResolvedScope;
369 
370   // Unresolved part of the scope. When the unresolved name is a specifier, we
371   // use the name that comes after it as the alternative name to resolve and use
372   // the specifier as the extra scope in the accessible scopes.
373   llvm::Optional<std::string> UnresolvedScope;
374 };
375 
getSpelledSpecifier(const CXXScopeSpec & SS,const SourceManager & SM)376 llvm::Optional<std::string> getSpelledSpecifier(const CXXScopeSpec &SS,
377     const SourceManager &SM) {
378   // Support specifiers written within a single macro argument.
379   if (!SM.isWrittenInSameFile(SS.getBeginLoc(), SS.getEndLoc()))
380     return llvm::None;
381   SourceRange Range(SM.getTopMacroCallerLoc(SS.getBeginLoc()), SM.getTopMacroCallerLoc(SS.getEndLoc()));
382   if (Range.getBegin().isMacroID() || Range.getEnd().isMacroID())
383     return llvm::None;
384 
385   return (toSourceCode(SM, Range) + "::").str();
386 }
387 
388 // Extracts unresolved name and scope information around \p Unresolved.
389 // FIXME: try to merge this with the scope-wrangling code in CodeComplete.
extractUnresolvedNameCheaply(const SourceManager & SM,const DeclarationNameInfo & Unresolved,CXXScopeSpec * SS,const LangOptions & LangOpts,bool UnresolvedIsSpecifier)390 llvm::Optional<CheapUnresolvedName> extractUnresolvedNameCheaply(
391     const SourceManager &SM, const DeclarationNameInfo &Unresolved,
392     CXXScopeSpec *SS, const LangOptions &LangOpts, bool UnresolvedIsSpecifier) {
393   CheapUnresolvedName Result;
394   Result.Name = Unresolved.getAsString();
395   if (SS && SS->isNotEmpty()) { // "::" or "ns::"
396     if (auto *Nested = SS->getScopeRep()) {
397       if (Nested->getKind() == NestedNameSpecifier::Global) {
398         Result.ResolvedScope = "";
399       } else if (const auto *NS = Nested->getAsNamespace()) {
400         std::string SpecifiedNS = printNamespaceScope(*NS);
401         llvm::Optional<std::string> Spelling = getSpelledSpecifier(*SS, SM);
402 
403         // Check the specifier spelled in the source.
404         // If the resolved scope doesn't end with the spelled scope, the
405         // resolved scope may come from a sema typo correction. For example,
406         // sema assumes that "clangd::" is a typo of "clang::" and uses
407         // "clang::" as the specified scope in:
408         //     namespace clang { clangd::X; }
409         // In this case, we use the "typo" specifier as extra scope instead
410         // of using the scope assumed by sema.
411         if (!Spelling || llvm::StringRef(SpecifiedNS).endswith(*Spelling)) {
412           Result.ResolvedScope = std::move(SpecifiedNS);
413         } else {
414           Result.UnresolvedScope = std::move(*Spelling);
415         }
416       } else if (const auto *ANS = Nested->getAsNamespaceAlias()) {
417         Result.ResolvedScope = printNamespaceScope(*ANS->getNamespace());
418       } else {
419         // We don't fix symbols in scopes that are not top-level e.g. class
420         // members, as we don't collect includes for them.
421         return llvm::None;
422       }
423     }
424   }
425 
426   if (UnresolvedIsSpecifier) {
427     // If the unresolved name is a specifier e.g.
428     //      clang::clangd::X
429     //             ~~~~~~
430     // We try to resolve clang::clangd::X instead of clang::clangd.
431     // FIXME: We won't be able to fix include if the specifier is what we
432     // should resolve (e.g. it's a class scope specifier). Collecting include
433     // headers for nested types could make this work.
434 
435     // Not using the end location as it doesn't always point to the end of
436     // identifier.
437     if (auto QualifiedByUnresolved =
438             qualifiedByUnresolved(SM, Unresolved.getBeginLoc(), LangOpts)) {
439       auto Split = splitQualifiedName(*QualifiedByUnresolved);
440       if (!Result.UnresolvedScope)
441         Result.UnresolvedScope.emplace();
442       // If UnresolvedSpecifiedScope is already set, we simply append the
443       // extra scope. Suppose the unresolved name is "index" in the following
444       // example:
445       //   namespace clang {  clangd::index::X; }
446       //                      ~~~~~~  ~~~~~
447       // "clangd::" is assumed to be clang:: by Sema, and we would have used
448       // it as extra scope. With "index" being a specifier, we append "index::"
449       // to the extra scope.
450       Result.UnresolvedScope->append((Result.Name + Split.first).str());
451       Result.Name = std::string(Split.second);
452     }
453   }
454   return Result;
455 }
456 
457 /// Returns all namespace scopes that the unqualified lookup would visit.
458 std::vector<std::string>
collectAccessibleScopes(Sema & Sem,const DeclarationNameInfo & Typo,Scope * S,Sema::LookupNameKind LookupKind)459 collectAccessibleScopes(Sema &Sem, const DeclarationNameInfo &Typo, Scope *S,
460                         Sema::LookupNameKind LookupKind) {
461   // Collects contexts visited during a Sema name lookup.
462   struct VisitedContextCollector : public VisibleDeclConsumer {
463     VisitedContextCollector(std::vector<std::string> &Out) : Out(Out) {}
464     void EnteredContext(DeclContext *Ctx) override {
465       if (llvm::isa<NamespaceDecl>(Ctx))
466         Out.push_back(printNamespaceScope(*Ctx));
467     }
468     void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
469                    bool InBaseClass) override {}
470     std::vector<std::string> &Out;
471   };
472 
473   std::vector<std::string> Scopes;
474   Scopes.push_back("");
475   VisitedContextCollector Collector(Scopes);
476   Sem.LookupVisibleDecls(S, LookupKind, Collector,
477                          /*IncludeGlobalScope=*/false,
478                          /*LoadExternal=*/false);
479   llvm::sort(Scopes);
480   Scopes.erase(std::unique(Scopes.begin(), Scopes.end()), Scopes.end());
481   return Scopes;
482 }
483 
484 class IncludeFixer::UnresolvedNameRecorder : public ExternalSemaSource {
485 public:
UnresolvedNameRecorder(llvm::Optional<UnresolvedName> & LastUnresolvedName)486   UnresolvedNameRecorder(llvm::Optional<UnresolvedName> &LastUnresolvedName)
487       : LastUnresolvedName(LastUnresolvedName) {}
488 
InitializeSema(Sema & S)489   void InitializeSema(Sema &S) override { this->SemaPtr = &S; }
490 
491   // Captures the latest typo and treat it as an unresolved name that can
492   // potentially be fixed by adding #includes.
CorrectTypo(const DeclarationNameInfo & Typo,int LookupKind,Scope * S,CXXScopeSpec * SS,CorrectionCandidateCallback & CCC,DeclContext * MemberContext,bool EnteringContext,const ObjCObjectPointerType * OPT)493   TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, int LookupKind,
494                              Scope *S, CXXScopeSpec *SS,
495                              CorrectionCandidateCallback &CCC,
496                              DeclContext *MemberContext, bool EnteringContext,
497                              const ObjCObjectPointerType *OPT) override {
498     dlog("CorrectTypo: {0}", Typo.getAsString());
499     assert(SemaPtr && "Sema must have been set.");
500     if (SemaPtr->isSFINAEContext())
501       return TypoCorrection();
502     if (!isInsideMainFile(Typo.getLoc(), SemaPtr->SourceMgr))
503       return clang::TypoCorrection();
504 
505     auto Extracted = extractUnresolvedNameCheaply(
506         SemaPtr->SourceMgr, Typo, SS, SemaPtr->LangOpts,
507         static_cast<Sema::LookupNameKind>(LookupKind) ==
508             Sema::LookupNameKind::LookupNestedNameSpecifierName);
509     if (!Extracted)
510       return TypoCorrection();
511 
512     UnresolvedName Unresolved;
513     Unresolved.Name = Extracted->Name;
514     Unresolved.Loc = Typo.getBeginLoc();
515     if (!Extracted->ResolvedScope && !S) // Give up if no scope available.
516       return TypoCorrection();
517 
518     if (Extracted->ResolvedScope)
519       Unresolved.Scopes.push_back(*Extracted->ResolvedScope);
520     else // no qualifier or qualifier is unresolved.
521       Unresolved.Scopes = collectAccessibleScopes(
522           *SemaPtr, Typo, S, static_cast<Sema::LookupNameKind>(LookupKind));
523 
524     if (Extracted->UnresolvedScope) {
525       for (std::string &Scope : Unresolved.Scopes)
526         Scope += *Extracted->UnresolvedScope;
527     }
528 
529     LastUnresolvedName = std::move(Unresolved);
530 
531     // Never return a valid correction to try to recover. Our suggested fixes
532     // always require a rebuild.
533     return TypoCorrection();
534   }
535 
536 private:
537   Sema *SemaPtr = nullptr;
538 
539   llvm::Optional<UnresolvedName> &LastUnresolvedName;
540 };
541 
542 llvm::IntrusiveRefCntPtr<ExternalSemaSource>
unresolvedNameRecorder()543 IncludeFixer::unresolvedNameRecorder() {
544   return new UnresolvedNameRecorder(LastUnresolvedName);
545 }
546 
fixUnresolvedName() const547 std::vector<Fix> IncludeFixer::fixUnresolvedName() const {
548   assert(LastUnresolvedName);
549   auto &Unresolved = *LastUnresolvedName;
550   vlog("Trying to fix unresolved name \"{0}\" in scopes: [{1}]",
551        Unresolved.Name, llvm::join(Unresolved.Scopes, ", "));
552 
553   FuzzyFindRequest Req;
554   Req.AnyScope = false;
555   Req.Query = Unresolved.Name;
556   Req.Scopes = Unresolved.Scopes;
557   Req.RestrictForCodeCompletion = true;
558   Req.Limit = 100;
559 
560   if (llvm::Optional<const SymbolSlab *> Syms = fuzzyFindCached(Req))
561     return fixesForSymbols(**Syms);
562 
563   return {};
564 }
565 
566 llvm::Optional<const SymbolSlab *>
fuzzyFindCached(const FuzzyFindRequest & Req) const567 IncludeFixer::fuzzyFindCached(const FuzzyFindRequest &Req) const {
568   auto ReqStr = llvm::formatv("{0}", toJSON(Req)).str();
569   auto I = FuzzyFindCache.find(ReqStr);
570   if (I != FuzzyFindCache.end())
571     return &I->second;
572 
573   if (IndexRequestCount >= IndexRequestLimit)
574     return llvm::None;
575   IndexRequestCount++;
576 
577   SymbolSlab::Builder Matches;
578   Index.fuzzyFind(Req, [&](const Symbol &Sym) {
579     if (Sym.Name != Req.Query)
580       return;
581     if (!Sym.IncludeHeaders.empty())
582       Matches.insert(Sym);
583   });
584   auto Syms = std::move(Matches).build();
585   auto E = FuzzyFindCache.try_emplace(ReqStr, std::move(Syms));
586   return &E.first->second;
587 }
588 
589 llvm::Optional<const SymbolSlab *>
lookupCached(const SymbolID & ID) const590 IncludeFixer::lookupCached(const SymbolID &ID) const {
591   LookupRequest Req;
592   Req.IDs.insert(ID);
593 
594   auto I = LookupCache.find(ID);
595   if (I != LookupCache.end())
596     return &I->second;
597 
598   if (IndexRequestCount >= IndexRequestLimit)
599     return llvm::None;
600   IndexRequestCount++;
601 
602   // FIXME: consider batching the requests for all diagnostics.
603   SymbolSlab::Builder Matches;
604   Index.lookup(Req, [&](const Symbol &Sym) { Matches.insert(Sym); });
605   auto Syms = std::move(Matches).build();
606 
607   std::vector<Fix> Fixes;
608   if (!Syms.empty()) {
609     auto &Matched = *Syms.begin();
610     if (!Matched.IncludeHeaders.empty() && Matched.Definition &&
611         Matched.CanonicalDeclaration.FileURI == Matched.Definition.FileURI)
612       Fixes = fixesForSymbols(Syms);
613   }
614   auto E = LookupCache.try_emplace(ID, std::move(Syms));
615   return &E.first->second;
616 }
617 
618 } // namespace clangd
619 } // namespace clang
620