[clang] [clang-format] Add BreakBeforeTemplateClose option (PR #118046)
Owen Pan via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 4 01:20:15 PST 2025
================
@@ -11224,6 +11224,328 @@ TEST_F(FormatTest, WrapsTemplateDeclarationsWithComments) {
Style);
}
+TEST_F(FormatTest, BreakBeforeTemplateCloser) {
+ FormatStyle Style = getLLVMStyle();
+ // Begin with tests covering the case where there is no constraint on the
+ // column limit.
+ Style.ColumnLimit = 0;
+ // When BreakBeforeTemplateCloser is turned off, the line break that it adds
+ // shall be 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.BreakBeforeTemplateCloser = true;
+ // BreakBeforeTemplateCloser should NOT force template declarations onto
+ // multiple lines.
+ verifyFormat("template <typename Foo>\n"
+ "void foo() {}",
+ Style);
+ verifyFormat("template <typename Foo, typename Bar>\n"
+ "void foo() {}",
+ Style);
+ // It should allow a line break, even when the typename is short.
+ // verifyNoChange is needed because the default behavior is one line.
+ verifyNoChange("template <\n"
+ " typename Foo\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ verifyNoChange("template <\n"
+ " typename Foo,\n"
+ " typename Bar\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ verifyNoChange("template <typename Foo,\n"
+ " typename Bar>\n"
+ "void foo() {}",
+ Style);
+ // It should add a line break before > 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 accordingly:
+ 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 https://github.com/llvm/llvm-project/issues/80049:
+ verifyFormat(
+ "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",
+ "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",
+ Style);
+
+ // Test lambda goes to next line:
+ verifyFormat("void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T\n"
+ " >(T t) {\n"
+ " };\n"
+ "}",
+ "void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T>(T t){\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"
+ "}",
+ "void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T, typename Foo>(T t){\n"
+ " };\n"
+ "}",
+ Style);
+ // Or on different lines:
+ verifyFormat("void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T,\n"
+ " typename Foo\n"
+ " >(T t) {\n"
+ " };\n"
+ "}",
+ "void foo() {\n"
+ " auto lambda = []<\n"
+ " typename T,\n"
+ " typename Foo>(T t){\n"
+ " };\n"
+ "}",
+ Style);
+
+ // Note that this is the same line (no \n):
+ verifyFormat("void foo() {\n"
+ " auto lambda = []<typename T>(T t) {};\n"
+ "}",
+ Style);
+
+ // Test template usage goes to next line too:
+ verifyFormat("void foo() {\n"
+ " myFunc<\n"
+ " T\n"
+ " >();\n"
+ "}",
+ "void foo() {\n"
+ " myFunc<\n"
+ " T>();\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. Note that these names are exactly 1
+ // character too long for the ColumnLimit.
+ verifyFormat("template <\n"
+ " typename Foo,\n"
+ " typename Barrrrrrrrrrrrrrrrrrrr\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ // Note that this "Foo" is 1 character shorter than the previous "Bar" because
+ // of the comma.
+ verifyFormat("template <\n"
+ " typename Foooooooooooooooooooo,\n"
+ " typename Bar\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ // BlockIndent style is used when the ColumnLimit allows it:
+ verifyFormat("template <typename Foo,\n"
+ " typename Barrrrrrrrrrrrrrrrrr>\n"
+ "void foo() {}",
+ Style);
+ verifyFormat("template <typename Fooooooooooooooooooo,\n"
+ " typename Bar>\n"
+ "void foo() {}",
+ Style);
+ // Same check for only one template parameter.
+ // Note how the first line is exactly 40 chars:
+ verifyFormat("template <typename Barrrrrrrrrrrrrrrrrr>\n"
+ "void foo() {}",
+ Style);
+ // And when one more "r" is added, it breaks properly:
+ verifyFormat("template <\n"
+ " typename Barrrrrrrrrrrrrrrrrrr\n"
+ ">\n"
+ "void foo() {}",
+ Style);
+ // Additionally, long names should be split in one step:
+ verifyFormat(
+ "template <\n"
+ " typename Foo,\n"
+ " typename Barrrrrrrrrrrrrrrrrrrrrrrrrr\n"
----------------
owenca wrote:
```suggestion
" typename Barrrrrrrrrrrrrrrrrrr\n"
```
https://github.com/llvm/llvm-project/pull/118046
More information about the cfe-commits
mailing list