1 //===--- IncludeStyle.h - Style of C++ #include directives -------*- 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_INCLUDESTYLE_H
10 #define LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H
11
12 #include "llvm/Support/YAMLTraits.h"
13 #include <string>
14 #include <vector>
15
16 namespace clang {
17 namespace tooling {
18
19 /// Style for sorting and grouping C++ #include directives.
20 struct IncludeStyle {
21 /// Styles for sorting multiple ``#include`` blocks.
22 enum IncludeBlocksStyle {
23 /// Sort each ``#include`` block separately.
24 /// \code
25 /// #include "b.h" into #include "b.h"
26 ///
27 /// #include <lib/main.h> #include "a.h"
28 /// #include "a.h" #include <lib/main.h>
29 /// \endcode
30 IBS_Preserve,
31 /// Merge multiple ``#include`` blocks together and sort as one.
32 /// \code
33 /// #include "b.h" into #include "a.h"
34 /// #include "b.h"
35 /// #include <lib/main.h> #include <lib/main.h>
36 /// #include "a.h"
37 /// \endcode
38 IBS_Merge,
39 /// Merge multiple ``#include`` blocks together and sort as one.
40 /// Then split into groups based on category priority. See
41 /// ``IncludeCategories``.
42 /// \code
43 /// #include "b.h" into #include "a.h"
44 /// #include "b.h"
45 /// #include <lib/main.h>
46 /// #include "a.h" #include <lib/main.h>
47 /// \endcode
48 IBS_Regroup,
49 };
50
51 /// Dependent on the value, multiple ``#include`` blocks can be sorted
52 /// as one and divided based on category.
53 IncludeBlocksStyle IncludeBlocks;
54
55 /// See documentation of ``IncludeCategories``.
56 struct IncludeCategory {
57 /// The regular expression that this category matches.
58 std::string Regex;
59 /// The priority to assign to this category.
60 int Priority;
61 /// The custom priority to sort before grouping.
62 int SortPriority;
63 /// If the regular expression is case sensitive.
64 bool RegexIsCaseSensitive;
65 bool operator==(const IncludeCategory &Other) const {
66 return Regex == Other.Regex && Priority == Other.Priority &&
67 RegexIsCaseSensitive == Other.RegexIsCaseSensitive;
68 }
69 };
70
71 /// Regular expressions denoting the different ``#include`` categories
72 /// used for ordering ``#includes``.
73 ///
74 /// `POSIX extended
75 /// <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html>`_
76 /// regular expressions are supported.
77 ///
78 /// These regular expressions are matched against the filename of an include
79 /// (including the <> or "") in order. The value belonging to the first
80 /// matching regular expression is assigned and ``#includes`` are sorted first
81 /// according to increasing category number and then alphabetically within
82 /// each category.
83 ///
84 /// If none of the regular expressions match, INT_MAX is assigned as
85 /// category. The main header for a source file automatically gets category 0.
86 /// so that it is generally kept at the beginning of the ``#includes``
87 /// (https://llvm.org/docs/CodingStandards.html#include-style). However, you
88 /// can also assign negative priorities if you have certain headers that
89 /// always need to be first.
90 ///
91 /// There is a third and optional field ``SortPriority`` which can used while
92 /// ``IncludeBloks = IBS_Regroup`` to define the priority in which
93 /// ``#includes`` should be ordered, and value of ``Priority`` defines the
94 /// order of
95 /// ``#include blocks`` and also enables to group ``#includes`` of different
96 /// priority for order.``SortPriority`` is set to the value of ``Priority``
97 /// as default if it is not assigned.
98 ///
99 /// Each regular expression can be marked as case sensitive with the field
100 /// ``CaseSensitive``, per default it is not.
101 ///
102 /// To configure this in the .clang-format file, use:
103 /// \code{.yaml}
104 /// IncludeCategories:
105 /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
106 /// Priority: 2
107 /// SortPriority: 2
108 /// CaseSensitive: true
109 /// - Regex: '^(<|"(gtest|gmock|isl|json)/)'
110 /// Priority: 3
111 /// - Regex: '<[[:alnum:].]+>'
112 /// Priority: 4
113 /// - Regex: '.*'
114 /// Priority: 1
115 /// SortPriority: 0
116 /// \endcode
117 std::vector<IncludeCategory> IncludeCategories;
118
119 /// Specify a regular expression of suffixes that are allowed in the
120 /// file-to-main-include mapping.
121 ///
122 /// When guessing whether a #include is the "main" include (to assign
123 /// category 0, see above), use this regex of allowed suffixes to the header
124 /// stem. A partial match is done, so that:
125 /// - "" means "arbitrary suffix"
126 /// - "$" means "no suffix"
127 ///
128 /// For example, if configured to "(_test)?$", then a header a.h would be seen
129 /// as the "main" include in both a.cc and a_test.cc.
130 std::string IncludeIsMainRegex;
131
132 /// Specify a regular expression for files being formatted
133 /// that are allowed to be considered "main" in the
134 /// file-to-main-include mapping.
135 ///
136 /// By default, clang-format considers files as "main" only when they end
137 /// with: ``.c``, ``.cc``, ``.cpp``, ``.c++``, ``.cxx``, ``.m`` or ``.mm``
138 /// extensions.
139 /// For these files a guessing of "main" include takes place
140 /// (to assign category 0, see above). This config option allows for
141 /// additional suffixes and extensions for files to be considered as "main".
142 ///
143 /// For example, if this option is configured to ``(Impl\.hpp)$``,
144 /// then a file ``ClassImpl.hpp`` is considered "main" (in addition to
145 /// ``Class.c``, ``Class.cc``, ``Class.cpp`` and so on) and "main
146 /// include file" logic will be executed (with *IncludeIsMainRegex* setting
147 /// also being respected in later phase). Without this option set,
148 /// ``ClassImpl.hpp`` would not have the main include file put on top
149 /// before any other include.
150 std::string IncludeIsMainSourceRegex;
151 };
152
153 } // namespace tooling
154 } // namespace clang
155
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::IncludeStyle::IncludeCategory)156 LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::IncludeStyle::IncludeCategory)
157
158 namespace llvm {
159 namespace yaml {
160
161 template <>
162 struct MappingTraits<clang::tooling::IncludeStyle::IncludeCategory> {
163 static void mapping(IO &IO,
164 clang::tooling::IncludeStyle::IncludeCategory &Category);
165 };
166
167 template <>
168 struct ScalarEnumerationTraits<
169 clang::tooling::IncludeStyle::IncludeBlocksStyle> {
170 static void
171 enumeration(IO &IO, clang::tooling::IncludeStyle::IncludeBlocksStyle &Value);
172 };
173
174 } // namespace yaml
175 } // namespace llvm
176
177 #endif // LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H
178