[clang] [clang-format] Add BreakBeforeTemplateClose option (PR #118046)
Björn Schäpers via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 25 07:43:35 PST 2024
================
@@ -11077,6 +11077,281 @@ TEST_F(FormatTest, WrapsTemplateDeclarationsWithComments) {
Style);
}
+TEST_F(FormatTest, BreakBeforeTemplateClose) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp);
+ Style.ColumnLimit = 0;
+ verifyNoChange("template <typename Foo>\n"
+ "void foo() {}",
+ Style);
+ verifyNoChange("template <\n"
+ " typename Foo,\n"
+ " typename Bar>\n"
+ "void foo() {}",
+ Style);
+ // when BreakBeforeTemplateClose is off, this line break is removed:
+ verifyFormat("template <\n"
+ " typename Foo,\n"
+ " typename Bar>\n"
+ "void foo() {}",
+ "template <\n"
+ " typename Foo,\n"
+ " typename Bar\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ Style.BreakBeforeTemplateClose = true;
+ // BreakBeforeTemplateClose should NOT force multiline templates
+ verifyNoChange("template <typename Foo>\n"
+ "void foo() {}",
+ Style);
+ verifyNoChange("template <typename Foo, typename Bar>\n"
+ "void foo() {}",
+ Style);
+ // it should allow a line break:
+ verifyNoChange("template <\n"
+ " typename Foo\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ verifyNoChange("template <\n"
+ " typename Foo,\n"
+ " typename Bar\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ // it should add a line break if not already present:
+ verifyFormat("template <\n"
+ " typename Foo\n"
+ ">\n"
+ "void foo() {}",
+ "template <\n"
+ " typename Foo>\n"
+ "void foo() {}",
+ Style);
+ verifyFormat("template <\n"
+ " typename Foo,\n"
+ " typename Bar\n"
+ ">\n"
+ "void foo() {}",
+ "template <\n"
+ " typename Foo,\n"
+ " typename Bar>\n"
+ "void foo() {}",
+ Style);
+ // when within an indent scope, the > should be placed appropriately:
+ verifyFormat("struct Baz {\n"
+ " template <\n"
+ " typename Foo,\n"
+ " typename Bar\n"
+ " >\n"
+ " void foo() {}\n"
+ "};",
+ "struct Baz {\n"
+ " template <\n"
+ " typename Foo,\n"
+ " typename Bar>\n"
+ " void foo() {}\n"
+ "};",
+ Style);
+
+ // test from issue #80049
+ verifyFormat(
+ "void foo() {\n"
+ " using type = std::remove_cv_t<\n"
+ " add_common_cv_reference<\n"
+ " std::common_type_t<std::decay_t<T0>, std::decay_t<T1>>,\n"
+ " T0,\n"
+ " T1\n"
+ " >\n"
+ " >;\n"
+ "}\n",
+ "void foo() {\n"
+ " using type = std::remove_cv_t<\n"
+ " add_common_cv_reference<\n"
+ " std::common_type_t<std::decay_t<T0>, std::decay_t<T1>>,\n"
+ " T0,\n"
+ " T1>>;\n"
+ "}\n",
+ Style);
+
+ // test lambda goes to next line:
+ verifyFormat("void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T\n"
+ " >(T t) {\n"
+ " };\n"
+ "}\n",
+ "void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T>(T t){\n"
+ " };\n"
+ "}\n",
+ Style);
+ // with no column limit, two parameters can go on the same line:
+ verifyFormat("void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T, typename Foo\n"
+ " >(T t) {\n"
+ " };\n"
+ "}\n",
+ "void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T, typename Foo>(T t){\n"
+ " };\n"
+ "}\n",
+ Style);
+ // or on different lines:
+ verifyFormat("void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T,\n"
+ " typename Foo\n"
+ " >(T t) {\n"
+ " };\n"
+ "}\n",
+ "void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T,\n"
+ " typename Foo>(T t){\n"
+ " };\n"
+ "}\n",
+ Style);
+
+ // same line with no column limit
+ verifyFormat("void foo() {\n"
+ " auto lambda = []<typename "
+ "Looooooooooooooooooooooooooooong>("
+ "Looooooooooooooooooooooooooooong t) {};\n"
+ "}\n",
+ Style);
+
+ // test template usage goes to next line:
+ verifyFormat("void foo() {\n"
+ " myFunc<\n"
+ " T\n"
+ " >();\n"
+ "}\n",
+ "void foo() {\n"
+ " myFunc<\n"
+ " T>();\n"
+ "}\n",
+ Style);
+
+ // now test that it handles the cases when the column limit forces wrapping
+ Style.ColumnLimit = 40;
+ // when the column limit allows it, the template should be combined back into
+ // one line:
+ verifyFormat("template <typename Foo, typename Bar>\n"
+ "void foo() {}",
+ "template <\n"
+ " typename Foo,\n"
+ " typename Bar\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ // but not when the name is looong
+ verifyFormat("template <\n"
+ " typename Foo,\n"
+ " typename Barrrrrrrrrrrrrrrrrrrrrrrrrr\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ verifyFormat("template <\n"
+ " typename Fooooooooooooooooooooooooooo,\n"
+ " typename Bar\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ // additionally, long names should be split in one step:
+ verifyFormat(
+ "template <\n"
+ " typename Foo,\n"
+ " typename Barrrrrrrrrrrrrrrrrrrrrrrrrr\n"
+ ">\n"
+ "void foo() {}",
+ "template <typename Foo, typename Barrrrrrrrrrrrrrrrrrrrrrrrrr>\n"
+ "void foo() {}",
+ Style);
+ verifyFormat(
+ "template <\n"
+ " typename Fooooooooooooooooooooooooooo,\n"
+ " typename Bar\n"
+ ">\n"
+ "void foo() {}",
+ "template <typename Fooooooooooooooooooooooooooo, typename Bar>\n"
+ "void foo() {}",
+ Style);
+ // even when there is only one long name:
+ verifyFormat("template <\n"
+ " typename Fooooooooooooooooooooooooooo\n"
+ ">\n"
+ "void foo() {}",
+ "template <typename Fooooooooooooooooooooooooooo>\n"
+ "void foo() {}",
+ Style);
+ // test lambda goes to next line if the type is looong:
+ verifyFormat(
+ "void foo() {\n"
+ // in this case, breaking "typename Looong" onto the next line would
+ // actually exceed the column limit by even more. same goes for "auto
+ // lambda = []<\n" because then the continuation indent would be all the
+ // way to the "[". therefore, this is correct for the column limited case:
+ " auto lambda =\n"
+ " []<typename Loooooooooooooooooooooooooooooooooong\n"
+ " >(T t) {};\n"
+ // for completeness, let's also make sure it's willing to break if and
+ // when doing so is helpful. if we put something long into the square
+ // brackets, now it's worth it:
+ " auto lambda =\n"
+ " [looooooooooooooong]<\n"
+ " typename Loooooooooooooooooooooooooooooooooong\n"
+ " >(T t) {};\n"
+ " auto lambda =\n"
+ " []<typename T,\n"
+ " typename Loooooooooooooooooooooooooooooooooong\n"
+ " >(T t) {};\n"
+ // nested:
+ " auto lambda =\n"
+ " []<template <typename, typename>\n"
+ " typename Looooooooooooooooooong\n"
+ " >(T t) {};\n"
+ // nested with long capture:
+ " auto lambda =\n"
+ " [loooooooooooooooooooong]<\n"
+ " template <typename, typename>\n"
----------------
HazardyKnusperkeks wrote:
Now the question is, shouldn't this also break?
```suggestion
" template <typename, typename\n"
" >\n"
```
https://github.com/llvm/llvm-project/pull/118046
More information about the cfe-commits
mailing list