1 //===--- IncludeFixer.h ------------------------------------------*- C++-*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDEFIXER_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDEFIXER_H
12 #include "Diagnostics.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"
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.
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
) {}
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;
47 /// Returns an ExternalSemaSource that records failed name lookups in Sema.
48 /// This allows IncludeFixer to suggest inserting headers that define those
50 llvm::IntrusiveRefCntPtr
<ExternalSemaSource
> unresolvedNameRecorder();
53 /// Attempts to recover diagnostic caused by an incomplete type \p T.
54 std::vector
<Fix
> fixIncompleteType(const Type
&T
) const;
56 /// Generates header insertion fixes for all symbols. Fixes are deduplicated.
57 std::vector
<Fix
> fixesForSymbols(const SymbolSlab
&Syms
) const;
59 std::optional
<Fix
> insertHeader(llvm::StringRef Name
,
60 llvm::StringRef Symbol
= "",
61 tooling::IncludeDirective Directive
=
62 tooling::IncludeDirective::Include
) const;
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.
70 /// Records the last unresolved name seen by Sema.
71 class UnresolvedNameRecorder
;
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;
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
;
86 // These collect the last unresolved name so that we can associate it with the
88 std::optional
<UnresolvedName
> LastUnresolvedName
;
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
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;
102 } // namespace clangd
105 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDEFIXER_H