1 //===--- IncludeFixer.h ------------------------------------------*- 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 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H 11 12 #include "Diagnostics.h" 13 #include "Headers.h" 14 #include "index/Index.h" 15 #include "index/Symbol.h" 16 #include "clang/AST/Type.h" 17 #include "clang/Basic/Diagnostic.h" 18 #include "clang/Basic/SourceLocation.h" 19 #include "clang/Sema/ExternalSemaSource.h" 20 #include "clang/Sema/Sema.h" 21 #include "llvm/ADT/ArrayRef.h" 22 #include "llvm/ADT/DenseMap.h" 23 #include "llvm/ADT/IntrusiveRefCntPtr.h" 24 #include "llvm/ADT/Optional.h" 25 #include "llvm/ADT/StringMap.h" 26 #include "llvm/ADT/StringRef.h" 27 #include <memory> 28 29 namespace clang { 30 namespace clangd { 31 32 /// Attempts to recover from error diagnostics by suggesting include insertion 33 /// fixes. For example, member access into incomplete type can be fixes by 34 /// include headers with the definition. 35 class IncludeFixer { 36 public: IncludeFixer(llvm::StringRef File,std::shared_ptr<IncludeInserter> Inserter,const SymbolIndex & Index,unsigned IndexRequestLimit)37 IncludeFixer(llvm::StringRef File, std::shared_ptr<IncludeInserter> Inserter, 38 const SymbolIndex &Index, unsigned IndexRequestLimit) 39 : File(File), Inserter(std::move(Inserter)), Index(Index), 40 IndexRequestLimit(IndexRequestLimit) {} 41 42 /// Returns include insertions that can potentially recover the diagnostic. 43 std::vector<Fix> fix(DiagnosticsEngine::Level DiagLevel, 44 const clang::Diagnostic &Info) const; 45 46 /// Returns an ExternalSemaSource that records failed name lookups in Sema. 47 /// This allows IncludeFixer to suggest inserting headers that define those 48 /// names. 49 llvm::IntrusiveRefCntPtr<ExternalSemaSource> unresolvedNameRecorder(); 50 51 private: 52 /// Attempts to recover diagnostic caused by an incomplete type \p T. 53 std::vector<Fix> fixIncompleteType(const Type &T) const; 54 55 /// Generates header insertion fixes for all symbols. Fixes are deduplicated. 56 std::vector<Fix> fixesForSymbols(const SymbolSlab &Syms) const; 57 58 struct UnresolvedName { 59 std::string Name; // E.g. "X" in foo::X. 60 SourceLocation Loc; // Start location of the unresolved name. 61 std::vector<std::string> Scopes; // Namespace scopes we should search in. 62 }; 63 64 /// Records the last unresolved name seen by Sema. 65 class UnresolvedNameRecorder; 66 67 /// Attempts to fix the unresolved name associated with the current 68 /// diagnostic. We assume a diagnostic is caused by a unresolved name when 69 /// they have the same source location and the unresolved name is the last 70 /// one we've seen during the Sema run. 71 std::vector<Fix> fixUnresolvedName() const; 72 73 std::string File; 74 std::shared_ptr<IncludeInserter> Inserter; 75 const SymbolIndex &Index; 76 const unsigned IndexRequestLimit; // Make at most 5 index requests. 77 mutable unsigned IndexRequestCount = 0; 78 79 // These collect the last unresolved name so that we can associate it with the 80 // diagnostic. 81 llvm::Optional<UnresolvedName> LastUnresolvedName; 82 83 // There can be multiple diagnostics that are caused by the same unresolved 84 // name or incomplete type in one parse, especially when code is 85 // copy-and-pasted without #includes. We cache the index results based on 86 // index requests. 87 mutable llvm::StringMap<SymbolSlab> FuzzyFindCache; 88 mutable llvm::DenseMap<SymbolID, SymbolSlab> LookupCache; 89 // Returns None if the number of index requests has reached the limit. 90 llvm::Optional<const SymbolSlab *> 91 fuzzyFindCached(const FuzzyFindRequest &Req) const; 92 llvm::Optional<const SymbolSlab *> lookupCached(const SymbolID &ID) const; 93 }; 94 95 } // namespace clangd 96 } // namespace clang 97 98 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H 99