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 /// ``IncludeBlocks = IBS_Regroup`` to define the priority in which 93 /// ``#includes`` should be ordered. The value of ``Priority`` defines the 94 /// order of ``#include blocks`` and also allows the grouping of ``#includes`` 95 /// of different priority. ``SortPriority`` is set to the value of 96 /// ``Priority`` as default if it is not assigned. 97 /// 98 /// Each regular expression can be marked as case sensitive with the field 99 /// ``CaseSensitive``, per default it is not. 100 /// 101 /// To configure this in the .clang-format file, use: 102 /// \code{.yaml} 103 /// IncludeCategories: 104 /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 105 /// Priority: 2 106 /// SortPriority: 2 107 /// CaseSensitive: true 108 /// - Regex: '^(<|"(gtest|gmock|isl|json)/)' 109 /// Priority: 3 110 /// - Regex: '<[[:alnum:].]+>' 111 /// Priority: 4 112 /// - Regex: '.*' 113 /// Priority: 1 114 /// SortPriority: 0 115 /// \endcode 116 std::vector<IncludeCategory> IncludeCategories; 117 118 /// Specify a regular expression of suffixes that are allowed in the 119 /// file-to-main-include mapping. 120 /// 121 /// When guessing whether a #include is the "main" include (to assign 122 /// category 0, see above), use this regex of allowed suffixes to the header 123 /// stem. A partial match is done, so that: 124 /// - "" means "arbitrary suffix" 125 /// - "$" means "no suffix" 126 /// 127 /// For example, if configured to "(_test)?$", then a header a.h would be seen 128 /// as the "main" include in both a.cc and a_test.cc. 129 std::string IncludeIsMainRegex; 130 131 /// Specify a regular expression for files being formatted 132 /// that are allowed to be considered "main" in the 133 /// file-to-main-include mapping. 134 /// 135 /// By default, clang-format considers files as "main" only when they end 136 /// with: ``.c``, ``.cc``, ``.cpp``, ``.c++``, ``.cxx``, ``.m`` or ``.mm`` 137 /// extensions. 138 /// For these files a guessing of "main" include takes place 139 /// (to assign category 0, see above). This config option allows for 140 /// additional suffixes and extensions for files to be considered as "main". 141 /// 142 /// For example, if this option is configured to ``(Impl\.hpp)$``, 143 /// then a file ``ClassImpl.hpp`` is considered "main" (in addition to 144 /// ``Class.c``, ``Class.cc``, ``Class.cpp`` and so on) and "main 145 /// include file" logic will be executed (with *IncludeIsMainRegex* setting 146 /// also being respected in later phase). Without this option set, 147 /// ``ClassImpl.hpp`` would not have the main include file put on top 148 /// before any other include. 149 std::string IncludeIsMainSourceRegex; 150 }; 151 152 } // namespace tooling 153 } // namespace clang 154 155 LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::IncludeStyle::IncludeCategory) 156 157 namespace llvm { 158 namespace yaml { 159 160 template <> 161 struct MappingTraits<clang::tooling::IncludeStyle::IncludeCategory> { 162 static void mapping(IO &IO, 163 clang::tooling::IncludeStyle::IncludeCategory &Category); 164 }; 165 166 template <> 167 struct ScalarEnumerationTraits< 168 clang::tooling::IncludeStyle::IncludeBlocksStyle> { 169 static void 170 enumeration(IO &IO, clang::tooling::IncludeStyle::IncludeBlocksStyle &Value); 171 }; 172 173 } // namespace yaml 174 } // namespace llvm 175 176 #endif // LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H 177