xref: /freebsd/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/IncludeStyle.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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   /// \version 6
54   IncludeBlocksStyle IncludeBlocks;
55 
56   /// See documentation of ``IncludeCategories``.
57   struct IncludeCategory {
58     /// The regular expression that this category matches.
59     std::string Regex;
60     /// The priority to assign to this category.
61     int Priority;
62     /// The custom priority to sort before grouping.
63     int SortPriority;
64     /// If the regular expression is case sensitive.
65     bool RegexIsCaseSensitive;
66     bool operator==(const IncludeCategory &Other) const {
67       return Regex == Other.Regex && Priority == Other.Priority &&
68              RegexIsCaseSensitive == Other.RegexIsCaseSensitive;
69     }
70   };
71 
72   /// Regular expressions denoting the different ``#include`` categories
73   /// used for ordering ``#includes``.
74   ///
75   /// `POSIX extended
76   /// <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html>`_
77   /// regular expressions are supported.
78   ///
79   /// These regular expressions are matched against the filename of an include
80   /// (including the <> or "") in order. The value belonging to the first
81   /// matching regular expression is assigned and ``#includes`` are sorted first
82   /// according to increasing category number and then alphabetically within
83   /// each category.
84   ///
85   /// If none of the regular expressions match, INT_MAX is assigned as
86   /// category. The main header for a source file automatically gets category 0.
87   /// so that it is generally kept at the beginning of the ``#includes``
88   /// (https://llvm.org/docs/CodingStandards.html#include-style). However, you
89   /// can also assign negative priorities if you have certain headers that
90   /// always need to be first.
91   ///
92   /// There is a third and optional field ``SortPriority`` which can used while
93   /// ``IncludeBlocks = IBS_Regroup`` to define the priority in which
94   /// ``#includes`` should be ordered. The value of ``Priority`` defines the
95   /// order of ``#include blocks`` and also allows the grouping of ``#includes``
96   /// of different priority. ``SortPriority`` is set to the value of
97   /// ``Priority`` 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   /// \version 3.8
118   std::vector<IncludeCategory> IncludeCategories;
119 
120   /// Specify a regular expression of suffixes that are allowed in the
121   /// file-to-main-include mapping.
122   ///
123   /// When guessing whether a #include is the "main" include (to assign
124   /// category 0, see above), use this regex of allowed suffixes to the header
125   /// stem. A partial match is done, so that:
126   /// - "" means "arbitrary suffix"
127   /// - "$" means "no suffix"
128   ///
129   /// For example, if configured to "(_test)?$", then a header a.h would be seen
130   /// as the "main" include in both a.cc and a_test.cc.
131   /// \version 3.9
132   std::string IncludeIsMainRegex;
133 
134   /// Specify a regular expression for files being formatted
135   /// that are allowed to be considered "main" in the
136   /// file-to-main-include mapping.
137   ///
138   /// By default, clang-format considers files as "main" only when they end
139   /// with: ``.c``, ``.cc``, ``.cpp``, ``.c++``, ``.cxx``, ``.m`` or ``.mm``
140   /// extensions.
141   /// For these files a guessing of "main" include takes place
142   /// (to assign category 0, see above). This config option allows for
143   /// additional suffixes and extensions for files to be considered as "main".
144   ///
145   /// For example, if this option is configured to ``(Impl\.hpp)$``,
146   /// then a file ``ClassImpl.hpp`` is considered "main" (in addition to
147   /// ``Class.c``, ``Class.cc``, ``Class.cpp`` and so on) and "main
148   /// include file" logic will be executed (with *IncludeIsMainRegex* setting
149   /// also being respected in later phase). Without this option set,
150   /// ``ClassImpl.hpp`` would not have the main include file put on top
151   /// before any other include.
152   /// \version 10
153   std::string IncludeIsMainSourceRegex;
154 
155   /// Character to consider in the include directives for the main header.
156   enum MainIncludeCharDiscriminator : int8_t {
157     /// Main include uses quotes: ``#include "foo.hpp"`` (the default).
158     MICD_Quote,
159     /// Main include uses angle brackets: ``#include <foo.hpp>``.
160     MICD_AngleBracket,
161     /// Main include uses either quotes or angle brackets.
162     MICD_Any
163   };
164 
165   /// When guessing whether a #include is the "main" include, only the include
166   /// directives that use the specified character are considered.
167   /// \version 19
168   MainIncludeCharDiscriminator MainIncludeChar;
169 };
170 
171 } // namespace tooling
172 } // namespace clang
173 
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::IncludeStyle::IncludeCategory)174 LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::IncludeStyle::IncludeCategory)
175 
176 namespace llvm {
177 namespace yaml {
178 
179 template <>
180 struct MappingTraits<clang::tooling::IncludeStyle::IncludeCategory> {
181   static void mapping(IO &IO,
182                       clang::tooling::IncludeStyle::IncludeCategory &Category);
183 };
184 
185 template <>
186 struct ScalarEnumerationTraits<
187     clang::tooling::IncludeStyle::IncludeBlocksStyle> {
188   static void
189   enumeration(IO &IO, clang::tooling::IncludeStyle::IncludeBlocksStyle &Value);
190 };
191 
192 template <>
193 struct ScalarEnumerationTraits<
194     clang::tooling::IncludeStyle::MainIncludeCharDiscriminator> {
195   static void enumeration(
196       IO &IO,
197       clang::tooling::IncludeStyle::MainIncludeCharDiscriminator &Value);
198 };
199 
200 } // namespace yaml
201 } // namespace llvm
202 
203 #endif // LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H
204