forked from OSchip/llvm-project
clang-format: Make include sorting's main include detection configurable.
This patch adds a regular expression to configure suffixes of an included file to check whether it is the "main" include of the current file. Previously, clang-format has allowed arbitrary suffixes on the formatted file, which is still the case when no IncludeMainRegex is specified. llvm-svn: 263943
This commit is contained in:
parent
4aeab5fbf2
commit
9c8ff3551a
|
@ -519,6 +519,19 @@ the configuration (without a prefix: ``Auto``).
|
|||
- Regex: '.\*'
|
||||
Priority: 1
|
||||
|
||||
**IncludeIsMainRegex** (``std::string``)
|
||||
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.
|
||||
|
||||
**IndentCaseLabels** (``bool``)
|
||||
Indent case labels one level from the switch statement.
|
||||
|
||||
|
@ -532,6 +545,22 @@ the configuration (without a prefix: ``Auto``).
|
|||
Indent if a function definition or declaration is wrapped after the
|
||||
type.
|
||||
|
||||
**JavaScriptQuotes** (``JavaScriptQuoteStyle``)
|
||||
The JavaScriptQuoteStyle to use for JavaScript strings.
|
||||
|
||||
Possible values:
|
||||
|
||||
* ``JSQS_Leave`` (in configuration: ``Leave``)
|
||||
Leave string quotes as they are.
|
||||
|
||||
* ``JSQS_Single`` (in configuration: ``Single``)
|
||||
Always use single quotes.
|
||||
|
||||
* ``JSQS_Double`` (in configuration: ``Double``)
|
||||
Always use double quotes.
|
||||
|
||||
|
||||
|
||||
**KeepEmptyLinesAtTheStartOfBlocks** (``bool``)
|
||||
If true, empty lines at the start of blocks are kept.
|
||||
|
||||
|
|
|
@ -401,6 +401,19 @@ struct FormatStyle {
|
|||
/// \endcode
|
||||
std::vector<IncludeCategory> IncludeCategories;
|
||||
|
||||
/// \brief 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;
|
||||
|
||||
/// \brief Indent case labels one level from the switch statement.
|
||||
///
|
||||
/// When ``false``, use the same indentation level as for the switch statement.
|
||||
|
|
|
@ -300,6 +300,7 @@ template <> struct MappingTraits<FormatStyle> {
|
|||
Style.ExperimentalAutoDetectBinPacking);
|
||||
IO.mapOptional("ForEachMacros", Style.ForEachMacros);
|
||||
IO.mapOptional("IncludeCategories", Style.IncludeCategories);
|
||||
IO.mapOptional("IncludeIsMainRegex", Style.IncludeIsMainRegex);
|
||||
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
|
||||
IO.mapOptional("IndentWidth", Style.IndentWidth);
|
||||
IO.mapOptional("IndentWrappedFunctionNames",
|
||||
|
@ -517,6 +518,7 @@ FormatStyle getLLVMStyle() {
|
|||
LLVMStyle.IncludeCategories = {{"^\"(llvm|llvm-c|clang|clang-c)/", 2},
|
||||
{"^(<|\"(gtest|isl|json)/)", 3},
|
||||
{".*", 1}};
|
||||
LLVMStyle.IncludeIsMainRegex = "$";
|
||||
LLVMStyle.IndentCaseLabels = false;
|
||||
LLVMStyle.IndentWrappedFunctionNames = false;
|
||||
LLVMStyle.IndentWidth = 2;
|
||||
|
@ -569,6 +571,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
|
|||
GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
|
||||
GoogleStyle.DerivePointerAlignment = true;
|
||||
GoogleStyle.IncludeCategories = {{"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
|
||||
GoogleStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
|
||||
GoogleStyle.IndentCaseLabels = true;
|
||||
GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
|
||||
GoogleStyle.ObjCSpaceAfterProperty = false;
|
||||
|
@ -1961,8 +1964,12 @@ tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
|
|||
StringRef HeaderStem =
|
||||
llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
|
||||
if (FileStem.startswith(HeaderStem)) {
|
||||
Category = 0;
|
||||
MainIncludeFound = true;
|
||||
llvm::Regex MainIncludeRegex(
|
||||
(HeaderStem + Style.IncludeIsMainRegex).str());
|
||||
if (MainIncludeRegex.match(FileStem)) {
|
||||
Category = 0;
|
||||
MainIncludeFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
IncludesInBlock.push_back({IncludeName, Line, Prev, Category});
|
||||
|
|
|
@ -9941,6 +9941,7 @@ TEST_F(FormatTest, ParsesConfiguration) {
|
|||
SpacesBeforeTrailingComments, 1234u);
|
||||
CHECK_PARSE("IndentWidth: 32", IndentWidth, 32u);
|
||||
CHECK_PARSE("ContinuationIndentWidth: 11", ContinuationIndentWidth, 11u);
|
||||
CHECK_PARSE("CommentPragmas: '// abc$'", CommentPragmas, "// abc$");
|
||||
|
||||
Style.PointerAlignment = FormatStyle::PAS_Middle;
|
||||
CHECK_PARSE("PointerAlignment: Left", PointerAlignment,
|
||||
|
@ -10099,6 +10100,7 @@ TEST_F(FormatTest, ParsesConfiguration) {
|
|||
" - Regex: .*\n"
|
||||
" Priority: 1",
|
||||
IncludeCategories, ExpectedCategories);
|
||||
CHECK_PARSE("IncludeIsMainRegex: 'abc$'", IncludeIsMainRegex, "abc$");
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, ParsesConfigurationWithLanguages) {
|
||||
|
|
|
@ -175,6 +175,7 @@ TEST_F(SortIncludesTest, HandlesMultilineIncludes) {
|
|||
}
|
||||
|
||||
TEST_F(SortIncludesTest, LeavesMainHeaderFirst) {
|
||||
Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
|
||||
EXPECT_EQ("#include \"llvm/a.h\"\n"
|
||||
"#include \"b.h\"\n"
|
||||
"#include \"c.h\"\n",
|
||||
|
@ -188,7 +189,7 @@ TEST_F(SortIncludesTest, LeavesMainHeaderFirst) {
|
|||
sort("#include \"llvm/a.h\"\n"
|
||||
"#include \"c.h\"\n"
|
||||
"#include \"b.h\"\n",
|
||||
"a_main.cc"));
|
||||
"a_test.cc"));
|
||||
EXPECT_EQ("#include \"llvm/input.h\"\n"
|
||||
"#include \"b.h\"\n"
|
||||
"#include \"c.h\"\n",
|
||||
|
@ -197,6 +198,24 @@ TEST_F(SortIncludesTest, LeavesMainHeaderFirst) {
|
|||
"#include \"b.h\"\n",
|
||||
"input.mm"));
|
||||
|
||||
// Don't allow prefixes.
|
||||
EXPECT_EQ("#include \"b.h\"\n"
|
||||
"#include \"c.h\"\n"
|
||||
"#include \"llvm/not_a.h\"\n",
|
||||
sort("#include \"llvm/not_a.h\"\n"
|
||||
"#include \"c.h\"\n"
|
||||
"#include \"b.h\"\n",
|
||||
"a.cc"));
|
||||
|
||||
// Don't do this for _main and other suffixes.
|
||||
EXPECT_EQ("#include \"b.h\"\n"
|
||||
"#include \"c.h\"\n"
|
||||
"#include \"llvm/a.h\"\n",
|
||||
sort("#include \"llvm/a.h\"\n"
|
||||
"#include \"c.h\"\n"
|
||||
"#include \"b.h\"\n",
|
||||
"a_main.cc"));
|
||||
|
||||
// Don't do this in headers.
|
||||
EXPECT_EQ("#include \"b.h\"\n"
|
||||
"#include \"c.h\"\n"
|
||||
|
|
Loading…
Reference in New Issue