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