aboutsummaryrefslogtreecommitdiffstats
path: root/include/clang/Tooling/Inclusions/IncludeStyle.h
blob: 266763a5b1bd0aa2932ccf07f538d0fc48e2296a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//===--- IncludeStyle.h - Style of C++ #include directives -------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H
#define LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H

#include "llvm/Support/YAMLTraits.h"
#include <string>
#include <vector>

namespace clang {
namespace tooling {

/// Style for sorting and grouping C++ #include directives.
struct IncludeStyle {
  /// Styles for sorting multiple ``#include`` blocks.
  enum IncludeBlocksStyle {
    /// Sort each ``#include`` block separately.
    /// \code
    ///    #include "b.h"               into      #include "b.h"
    ///
    ///    #include <lib/main.h>                  #include "a.h"
    ///    #include "a.h"                         #include <lib/main.h>
    /// \endcode
    IBS_Preserve,
    /// Merge multiple ``#include`` blocks together and sort as one.
    /// \code
    ///    #include "b.h"               into      #include "a.h"
    ///                                           #include "b.h"
    ///    #include <lib/main.h>                  #include <lib/main.h>
    ///    #include "a.h"
    /// \endcode
    IBS_Merge,
    /// Merge multiple ``#include`` blocks together and sort as one.
    /// Then split into groups based on category priority. See
    /// ``IncludeCategories``.
    /// \code
    ///    #include "b.h"               into      #include "a.h"
    ///                                           #include "b.h"
    ///    #include <lib/main.h>
    ///    #include "a.h"                         #include <lib/main.h>
    /// \endcode
    IBS_Regroup,
  };

  /// Dependent on the value, multiple ``#include`` blocks can be sorted
  /// as one and divided based on category.
  IncludeBlocksStyle IncludeBlocks;

  /// See documentation of ``IncludeCategories``.
  struct IncludeCategory {
    /// The regular expression that this category matches.
    std::string Regex;
    /// The priority to assign to this category.
    int Priority;
    /// The custom priority to sort before grouping.
    int SortPriority;
    bool operator==(const IncludeCategory &Other) const {
      return Regex == Other.Regex && Priority == Other.Priority;
    }
  };

  /// Regular expressions denoting the different ``#include`` categories
  /// used for ordering ``#includes``.
  ///
  /// `POSIX extended
  /// <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html>`_
  /// regular expressions are supported.
  ///
  /// These regular expressions are matched against the filename of an include
  /// (including the <> or "") in order. The value belonging to the first
  /// matching regular expression is assigned and ``#includes`` are sorted first
  /// according to increasing category number and then alphabetically within
  /// each category.
  ///
  /// If none of the regular expressions match, INT_MAX is assigned as
  /// category. The main header for a source file automatically gets category 0.
  /// so that it is generally kept at the beginning of the ``#includes``
  /// (https://llvm.org/docs/CodingStandards.html#include-style). However, you
  /// can also assign negative priorities if you have certain headers that
  /// always need to be first.
  ///
  /// To configure this in the .clang-format file, use:
  /// \code{.yaml}
  ///   IncludeCategories:
  ///     - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
  ///       Priority:        2
  ///     - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
  ///       Priority:        3
  ///     - Regex:           '<[[:alnum:].]+>'
  ///       Priority:        4
  ///     - Regex:           '.*'
  ///       Priority:        1
  /// \endcode
  std::vector<IncludeCategory> IncludeCategories;

  /// Specify a regular expression of suffixes that are allowed in the
  /// file-to-main-include mapping.
  ///
  /// When guessing whether a #include is the "main" include (to assign
  /// category 0, see above), use this regex of allowed suffixes to the header
  /// stem. A partial match is done, so that:
  /// - "" means "arbitrary suffix"
  /// - "$" means "no suffix"
  ///
  /// For example, if configured to "(_test)?$", then a header a.h would be seen
  /// as the "main" include in both a.cc and a_test.cc.
  std::string IncludeIsMainRegex;
};

} // namespace tooling
} // namespace clang

LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::IncludeStyle::IncludeCategory)

namespace llvm {
namespace yaml {

template <>
struct MappingTraits<clang::tooling::IncludeStyle::IncludeCategory> {
  static void mapping(IO &IO,
                      clang::tooling::IncludeStyle::IncludeCategory &Category);
};

template <>
struct ScalarEnumerationTraits<
    clang::tooling::IncludeStyle::IncludeBlocksStyle> {
  static void
  enumeration(IO &IO, clang::tooling::IncludeStyle::IncludeBlocksStyle &Value);
};

} // namespace yaml
} // namespace llvm

#endif // LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H