Coverage Report

Created: 2020-02-18 08:44

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
Line
Count
Source
1
//===--- HeaderIncludes.h - Insert/Delete #includes for C++ code--*- 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_TOOLING_INCLUSIONS_HEADERINCLUDES_H
10
#define LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H
11
12
#include "clang/Basic/SourceManager.h"
13
#include "clang/Tooling/Core/Replacement.h"
14
#include "clang/Tooling/Inclusions/IncludeStyle.h"
15
#include "llvm/Support/Path.h"
16
#include "llvm/Support/Regex.h"
17
#include <unordered_map>
18
19
namespace clang {
20
namespace tooling {
21
22
/// This class manages priorities of C++ #include categories and calculates
23
/// priorities for headers.
24
/// FIXME(ioeric): move this class into implementation file when clang-format's
25
/// include sorting functions are also moved here.
26
class IncludeCategoryManager {
27
public:
28
  IncludeCategoryManager(const IncludeStyle &Style, StringRef FileName);
29
30
  /// Returns the priority of the category which \p IncludeName belongs to.
31
  /// If \p CheckMainHeader is true and \p IncludeName is a main header, returns
32
  /// 0. Otherwise, returns the priority of the matching category or INT_MAX.
33
  /// NOTE: this API is not thread-safe!
34
  int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
35
  int getSortIncludePriority(StringRef IncludeName, bool CheckMainHeader) const;
36
37
private:
38
  bool isMainHeader(StringRef IncludeName) const;
39
40
  const IncludeStyle Style;
41
  bool IsMainFile;
42
  std::string FileName;
43
  // This refers to a substring in FileName.
44
  StringRef FileStem;
45
  SmallVector<llvm::Regex, 4> CategoryRegexs;
46
};
47
48
/// Generates replacements for inserting or deleting #include directives in a
49
/// file.
50
class HeaderIncludes {
51
public:
52
  HeaderIncludes(llvm::StringRef FileName, llvm::StringRef Code,
53
                 const IncludeStyle &Style);
54
55
  /// Inserts an #include directive of \p Header into the code. If \p IsAngled
56
  /// is true, \p Header will be quoted with <> in the directive; otherwise, it
57
  /// will be quoted with "".
58
  ///
59
  /// When searching for points to insert new header, this ignores #include's
60
  /// after the #include block(s) in the beginning of a file to avoid inserting
61
  /// headers into code sections where new #include's should not be added by
62
  /// default. These code sections include:
63
  ///   - raw string literals (containing #include).
64
  ///   - #if blocks.
65
  ///   - Special #include's among declarations (e.g. functions).
66
  ///
67
  /// Returns a replacement that inserts the new header into a suitable #include
68
  /// block of the same category. This respects the order of the existing
69
  /// #includes in the block; if the existing #includes are not already sorted,
70
  /// this will simply insert the #include in front of the first #include of the
71
  /// same category in the code that should be sorted after \p IncludeName. If
72
  /// \p IncludeName already exists (with exactly the same spelling), this
73
  /// returns None.
74
  llvm::Optional<tooling::Replacement> insert(llvm::StringRef Header,
75
                                              bool IsAngled) const;
76
77
  /// Removes all existing #includes of \p Header quoted with <> if \p IsAngled
78
  /// is true or "" if \p IsAngled is false.
79
  /// This doesn't resolve the header file path; it only deletes #includes with
80
  /// exactly the same spelling.
81
  tooling::Replacements remove(llvm::StringRef Header, bool IsAngled) const;
82
83
private:
84
  struct Include {
85
89
    Include(StringRef Name, tooling::Range R) : Name(Name), R(R) {}
86
87
    // An include header quoted with either <> or "".
88
    std::string Name;
89
    // The range of the whole line of include directive including any eading
90
    // whitespaces and trailing comment.
91
    tooling::Range R;
92
  };
93
94
  void addExistingInclude(Include IncludeToAdd, unsigned NextLineOffset);
95
96
  std::string FileName;
97
  std::string Code;
98
99
  // Map from include name (quotation trimmed) to a list of existing includes
100
  // (in case there are more than one) with the name in the current file. <x>
101
  // and "x" will be treated as the same header when deleting #includes.
102
  llvm::StringMap<llvm::SmallVector<Include, 1>> ExistingIncludes;
103
104
  /// Map from priorities of #include categories to all #includes in the same
105
  /// category. This is used to find #includes of the same category when
106
  /// inserting new #includes. #includes in the same categories are sorted in
107
  /// in the order they appear in the source file.
108
  /// See comment for "FormatStyle::IncludeCategories" for details about include
109
  /// priorities.
110
  std::unordered_map<int, llvm::SmallVector<const Include *, 8>>
111
      IncludesByPriority;
112
113
  int FirstIncludeOffset;
114
  // All new headers should be inserted after this offset (e.g. after header
115
  // guards, file comment).
116
  unsigned MinInsertOffset;
117
  // Max insertion offset in the original code. For example, we want to avoid
118
  // inserting new #includes into the actual code section (e.g. after a
119
  // declaration).
120
  unsigned MaxInsertOffset;
121
  IncludeCategoryManager Categories;
122
  // Record the offset of the end of the last include in each category.
123
  std::unordered_map<int, int> CategoryEndOffsets;
124
125
  // All possible priorities.
126
  std::set<int> Priorities;
127
128
  // Matches a whole #include directive.
129
  llvm::Regex IncludeRegex;
130
};
131
132
133
} // namespace tooling
134
} // namespace clang
135
136
#endif // LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H