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