clang  10.0.0svn
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 <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.
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  // Regex is not thread-safe.
46  mutable SmallVector<llvm::Regex, 4> CategoryRegexs;
47 };
48 
49 /// Generates replacements for inserting or deleting #include directives in a
50 /// file.
52 public:
53  HeaderIncludes(llvm::StringRef FileName, llvm::StringRef Code,
54  const IncludeStyle &Style);
55 
56  /// Inserts an #include directive of \p Header into the code. If \p IsAngled
57  /// is true, \p Header will be quoted with <> in the directive; otherwise, it
58  /// will be quoted with "".
59  ///
60  /// When searching for points to insert new header, this ignores #include's
61  /// after the #include block(s) in the beginning of a file to avoid inserting
62  /// headers into code sections where new #include's should not be added by
63  /// default. These code sections include:
64  /// - raw string literals (containing #include).
65  /// - #if blocks.
66  /// - Special #include's among declarations (e.g. functions).
67  ///
68  /// Returns a replacement that inserts the new header into a suitable #include
69  /// block of the same category. This respects the order of the existing
70  /// #includes in the block; if the existing #includes are not already sorted,
71  /// this will simply insert the #include in front of the first #include of the
72  /// same category in the code that should be sorted after \p IncludeName. If
73  /// \p IncludeName already exists (with exactly the same spelling), this
74  /// returns None.
75  llvm::Optional<tooling::Replacement> insert(llvm::StringRef Header,
76  bool IsAngled) const;
77 
78  /// Removes all existing #includes of \p Header quoted with <> if \p IsAngled
79  /// is true or "" if \p IsAngled is false.
80  /// This doesn't resolve the header file path; it only deletes #includes with
81  /// exactly the same spelling.
82  tooling::Replacements remove(llvm::StringRef Header, bool IsAngled) const;
83 
84 private:
85  struct Include {
86  Include(StringRef Name, tooling::Range R) : Name(Name), R(R) {}
87 
88  // An include header quoted with either <> or "".
89  std::string Name;
90  // The range of the whole line of include directive including any eading
91  // whitespaces and trailing comment.
93  };
94 
95  void addExistingInclude(Include IncludeToAdd, unsigned NextLineOffset);
96 
97  std::string FileName;
98  std::string Code;
99 
100  // Map from include name (quotation trimmed) to a list of existing includes
101  // (in case there are more than one) with the name in the current file. <x>
102  // and "x" will be treated as the same header when deleting #includes.
103  llvm::StringMap<llvm::SmallVector<Include, 1>> ExistingIncludes;
104 
105  /// Map from priorities of #include categories to all #includes in the same
106  /// category. This is used to find #includes of the same category when
107  /// inserting new #includes. #includes in the same categories are sorted in
108  /// in the order they appear in the source file.
109  /// See comment for "FormatStyle::IncludeCategories" for details about include
110  /// priorities.
111  std::unordered_map<int, llvm::SmallVector<const Include *, 8>>
112  IncludesByPriority;
113 
114  int FirstIncludeOffset;
115  // All new headers should be inserted after this offset (e.g. after header
116  // guards, file comment).
117  unsigned MinInsertOffset;
118  // Max insertion offset in the original code. For example, we want to avoid
119  // inserting new #includes into the actual code section (e.g. after a
120  // declaration).
121  unsigned MaxInsertOffset;
122  IncludeCategoryManager Categories;
123  // Record the offset of the end of the last include in each category.
124  std::unordered_map<int, int> CategoryEndOffsets;
125 
126  // All possible priorities.
127  std::set<int> Priorities;
128 
129  // Matches a whole #include directive.
130  llvm::Regex IncludeRegex;
131 };
132 
133 
134 } // namespace tooling
135 } // namespace clang
136 
137 #endif // LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H
Defines the SourceManager interface.
Maintains a set of replacements that are conflict-free.
Definition: Replacement.h:209
Generates replacements for inserting or deleting #include directives in a file.
A source range independent of the SourceManager.
Definition: Replacement.h:44
int getSortIncludePriority(StringRef IncludeName, bool CheckMainHeader) const
This class manages priorities of C++ #include categories and calculates priorities for headers...
Style for sorting and grouping C++ #include directives.
Definition: IncludeStyle.h:20
Dataflow Directional Tag Classes.
IncludeCategoryManager(const IncludeStyle &Style, StringRef FileName)
int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const
Returns the priority of the category which IncludeName belongs to.