File: IncludeFixer.h

package info (click to toggle)
llvm-toolchain-14 1%3A14.0.6-16
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,496,368 kB
  • sloc: cpp: 5,593,980; ansic: 986,873; asm: 585,869; python: 184,223; objc: 72,530; lisp: 31,119; f90: 27,793; javascript: 9,780; pascal: 9,762; sh: 9,482; perl: 7,468; ml: 5,432; awk: 3,523; makefile: 2,547; xml: 953; cs: 573; fortran: 567
file content (102 lines) | stat: -rw-r--r-- 4,111 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//===--- IncludeFixer.h ------------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDEFIXER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDEFIXER_H

#include "Diagnostics.h"
#include "Headers.h"
#include "index/Index.h"
#include "index/Symbol.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include <memory>

namespace clang {
namespace clangd {

/// Attempts to recover from error diagnostics by suggesting include insertion
/// fixes. For example, member access into incomplete type can be fixes by
/// include headers with the definition.
class IncludeFixer {
public:
  IncludeFixer(llvm::StringRef File, std::shared_ptr<IncludeInserter> Inserter,
               const SymbolIndex &Index, unsigned IndexRequestLimit)
      : File(File), Inserter(std::move(Inserter)), Index(Index),
        IndexRequestLimit(IndexRequestLimit) {}

  /// Returns include insertions that can potentially recover the diagnostic.
  /// If Info is a note and fixes are returned, they should *replace* the note.
  std::vector<Fix> fix(DiagnosticsEngine::Level DiagLevel,
                       const clang::Diagnostic &Info) const;

  /// Returns an ExternalSemaSource that records failed name lookups in Sema.
  /// This allows IncludeFixer to suggest inserting headers that define those
  /// names.
  llvm::IntrusiveRefCntPtr<ExternalSemaSource> unresolvedNameRecorder();

private:
  /// Attempts to recover diagnostic caused by an incomplete type \p T.
  std::vector<Fix> fixIncompleteType(const Type &T) const;

  /// Generates header insertion fixes for all symbols. Fixes are deduplicated.
  std::vector<Fix> fixesForSymbols(const SymbolSlab &Syms) const;

  llvm::Optional<Fix> insertHeader(llvm::StringRef Name,
                                   llvm::StringRef Symbol = "") const;

  struct UnresolvedName {
    std::string Name;   // E.g. "X" in foo::X.
    SourceLocation Loc; // Start location of the unresolved name.
    std::vector<std::string> Scopes; // Namespace scopes we should search in.
  };

  /// Records the last unresolved name seen by Sema.
  class UnresolvedNameRecorder;

  /// Attempts to fix the unresolved name associated with the current
  /// diagnostic. We assume a diagnostic is caused by a unresolved name when
  /// they have the same source location and the unresolved name is the last
  /// one we've seen during the Sema run.
  std::vector<Fix> fixUnresolvedName() const;

  std::string File;
  std::shared_ptr<IncludeInserter> Inserter;
  const SymbolIndex &Index;
  const unsigned IndexRequestLimit; // Make at most 5 index requests.
  mutable unsigned IndexRequestCount = 0;

  // These collect the last unresolved name so that we can associate it with the
  // diagnostic.
  llvm::Optional<UnresolvedName> LastUnresolvedName;

  // There can be multiple diagnostics that are caused by the same unresolved
  // name or incomplete type in one parse, especially when code is
  // copy-and-pasted without #includes. We cache the index results based on
  // index requests.
  mutable llvm::StringMap<SymbolSlab> FuzzyFindCache;
  mutable llvm::DenseMap<SymbolID, SymbolSlab> LookupCache;
  // Returns None if the number of index requests has reached the limit.
  llvm::Optional<const SymbolSlab *>
  fuzzyFindCached(const FuzzyFindRequest &Req) const;
  llvm::Optional<const SymbolSlab *> lookupCached(const SymbolID &ID) const;
};

} // namespace clangd
} // namespace clang

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDEFIXER_H