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

source code of clang-tools-extra/clangd/IncludeFixer.h