1336815Sdim//===--- IncludeStyle.h - Style of C++ #include directives -------*- C++-*-===//
2336815Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6336815Sdim//
7336815Sdim//===----------------------------------------------------------------------===//
8336815Sdim
9336815Sdim#ifndef LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H
10336815Sdim#define LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H
11336815Sdim
12336815Sdim#include "llvm/Support/YAMLTraits.h"
13336815Sdim#include <string>
14336815Sdim#include <vector>
15336815Sdim
16336815Sdimnamespace clang {
17336815Sdimnamespace tooling {
18336815Sdim
19336815Sdim/// Style for sorting and grouping C++ #include directives.
20336815Sdimstruct IncludeStyle {
21336815Sdim  /// Styles for sorting multiple ``#include`` blocks.
22336815Sdim  enum IncludeBlocksStyle {
23336815Sdim    /// Sort each ``#include`` block separately.
24336815Sdim    /// \code
25336815Sdim    ///    #include "b.h"               into      #include "b.h"
26336815Sdim    ///
27336815Sdim    ///    #include <lib/main.h>                  #include "a.h"
28336815Sdim    ///    #include "a.h"                         #include <lib/main.h>
29336815Sdim    /// \endcode
30336815Sdim    IBS_Preserve,
31336815Sdim    /// Merge multiple ``#include`` blocks together and sort as one.
32336815Sdim    /// \code
33336815Sdim    ///    #include "b.h"               into      #include "a.h"
34336815Sdim    ///                                           #include "b.h"
35336815Sdim    ///    #include <lib/main.h>                  #include <lib/main.h>
36336815Sdim    ///    #include "a.h"
37336815Sdim    /// \endcode
38336815Sdim    IBS_Merge,
39336815Sdim    /// Merge multiple ``#include`` blocks together and sort as one.
40336815Sdim    /// Then split into groups based on category priority. See
41336815Sdim    /// ``IncludeCategories``.
42336815Sdim    /// \code
43336815Sdim    ///    #include "b.h"               into      #include "a.h"
44336815Sdim    ///                                           #include "b.h"
45336815Sdim    ///    #include <lib/main.h>
46336815Sdim    ///    #include "a.h"                         #include <lib/main.h>
47336815Sdim    /// \endcode
48336815Sdim    IBS_Regroup,
49336815Sdim  };
50336815Sdim
51336815Sdim  /// Dependent on the value, multiple ``#include`` blocks can be sorted
52336815Sdim  /// as one and divided based on category.
53336815Sdim  IncludeBlocksStyle IncludeBlocks;
54336815Sdim
55336815Sdim  /// See documentation of ``IncludeCategories``.
56336815Sdim  struct IncludeCategory {
57336815Sdim    /// The regular expression that this category matches.
58336815Sdim    std::string Regex;
59336815Sdim    /// The priority to assign to this category.
60336815Sdim    int Priority;
61360784Sdim    /// The custom priority to sort before grouping.
62360784Sdim    int SortPriority;
63336815Sdim    bool operator==(const IncludeCategory &Other) const {
64336815Sdim      return Regex == Other.Regex && Priority == Other.Priority;
65336815Sdim    }
66336815Sdim  };
67336815Sdim
68336815Sdim  /// Regular expressions denoting the different ``#include`` categories
69336815Sdim  /// used for ordering ``#includes``.
70336815Sdim  ///
71336815Sdim  /// `POSIX extended
72353358Sdim  /// <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html>`_
73336815Sdim  /// regular expressions are supported.
74336815Sdim  ///
75336815Sdim  /// These regular expressions are matched against the filename of an include
76336815Sdim  /// (including the <> or "") in order. The value belonging to the first
77336815Sdim  /// matching regular expression is assigned and ``#includes`` are sorted first
78336815Sdim  /// according to increasing category number and then alphabetically within
79336815Sdim  /// each category.
80336815Sdim  ///
81336815Sdim  /// If none of the regular expressions match, INT_MAX is assigned as
82336815Sdim  /// category. The main header for a source file automatically gets category 0.
83336815Sdim  /// so that it is generally kept at the beginning of the ``#includes``
84353358Sdim  /// (https://llvm.org/docs/CodingStandards.html#include-style). However, you
85336815Sdim  /// can also assign negative priorities if you have certain headers that
86336815Sdim  /// always need to be first.
87360784Sdim  ///
88360784Sdim  /// There is a third and optional field ``SortPriority`` which can used while
89360784Sdim  /// ``IncludeBloks = IBS_Regroup`` to define the priority in which ``#includes``
90360784Sdim  /// should be ordered, and value of ``Priority`` defines the order of
91360784Sdim  /// ``#include blocks`` and also enables to group ``#includes`` of different
92360784Sdim  /// priority for order.``SortPriority`` is set to the value of ``Priority``
93360784Sdim  /// as default if it is not assigned.
94336815Sdim  ///
95336815Sdim  /// To configure this in the .clang-format file, use:
96336815Sdim  /// \code{.yaml}
97336815Sdim  ///   IncludeCategories:
98336815Sdim  ///     - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
99336815Sdim  ///       Priority:        2
100360784Sdim  ///       SortPriority:    2
101336815Sdim  ///     - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
102336815Sdim  ///       Priority:        3
103336815Sdim  ///     - Regex:           '<[[:alnum:].]+>'
104336815Sdim  ///       Priority:        4
105336815Sdim  ///     - Regex:           '.*'
106336815Sdim  ///       Priority:        1
107360784Sdim  ///       SortPriority:    0
108336815Sdim  /// \endcode
109336815Sdim  std::vector<IncludeCategory> IncludeCategories;
110336815Sdim
111336815Sdim  /// Specify a regular expression of suffixes that are allowed in the
112336815Sdim  /// file-to-main-include mapping.
113336815Sdim  ///
114336815Sdim  /// When guessing whether a #include is the "main" include (to assign
115336815Sdim  /// category 0, see above), use this regex of allowed suffixes to the header
116336815Sdim  /// stem. A partial match is done, so that:
117336815Sdim  /// - "" means "arbitrary suffix"
118336815Sdim  /// - "$" means "no suffix"
119336815Sdim  ///
120336815Sdim  /// For example, if configured to "(_test)?$", then a header a.h would be seen
121336815Sdim  /// as the "main" include in both a.cc and a_test.cc.
122336815Sdim  std::string IncludeIsMainRegex;
123360784Sdim
124360784Sdim  /// Specify a regular expression for files being formatted
125360784Sdim  /// that are allowed to be considered "main" in the
126360784Sdim  /// file-to-main-include mapping.
127360784Sdim  ///
128360784Sdim  /// By default, clang-format considers files as "main" only when they end
129360784Sdim  /// with: ``.c``, ``.cc``, ``.cpp``, ``.c++``, ``.cxx``, ``.m`` or ``.mm``
130360784Sdim  /// extensions.
131360784Sdim  /// For these files a guessing of "main" include takes place
132360784Sdim  /// (to assign category 0, see above). This config option allows for
133360784Sdim  /// additional suffixes and extensions for files to be considered as "main".
134360784Sdim  ///
135360784Sdim  /// For example, if this option is configured to ``(Impl\.hpp)$``,
136360784Sdim  /// then a file ``ClassImpl.hpp`` is considered "main" (in addition to
137360784Sdim  /// ``Class.c``, ``Class.cc``, ``Class.cpp`` and so on) and "main
138360784Sdim  /// include file" logic will be executed (with *IncludeIsMainRegex* setting
139360784Sdim  /// also being respected in later phase). Without this option set,
140360784Sdim  /// ``ClassImpl.hpp`` would not have the main include file put on top
141360784Sdim  /// before any other include.
142360784Sdim  std::string IncludeIsMainSourceRegex;
143336815Sdim};
144336815Sdim
145336815Sdim} // namespace tooling
146336815Sdim} // namespace clang
147336815Sdim
148336815SdimLLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::IncludeStyle::IncludeCategory)
149336815Sdim
150336815Sdimnamespace llvm {
151336815Sdimnamespace yaml {
152336815Sdim
153336815Sdimtemplate <>
154336815Sdimstruct MappingTraits<clang::tooling::IncludeStyle::IncludeCategory> {
155336815Sdim  static void mapping(IO &IO,
156336815Sdim                      clang::tooling::IncludeStyle::IncludeCategory &Category);
157336815Sdim};
158336815Sdim
159336815Sdimtemplate <>
160336815Sdimstruct ScalarEnumerationTraits<
161336815Sdim    clang::tooling::IncludeStyle::IncludeBlocksStyle> {
162336815Sdim  static void
163336815Sdim  enumeration(IO &IO, clang::tooling::IncludeStyle::IncludeBlocksStyle &Value);
164336815Sdim};
165336815Sdim
166336815Sdim} // namespace yaml
167336815Sdim} // namespace llvm
168336815Sdim
169336815Sdim#endif // LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H
170