================
@@ -11220,6 +11220,333 @@ TEST_F(FormatTest,
WrapsTemplateDeclarationsWithComments) {
Style);
}
+TEST_F(FormatTest, BreakBeforeTemplateCloser) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_Cpp);
+ // 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 = FormatStyle::BBTCS_BlockIndent;
+ // 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 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"
+ "}",
+ "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"
+ "}",
+ 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 "
+ "Looooooooooooooooooooooooooooong>("
+ "Looooooooooooooooooooooooooooong 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);
----------------
owenca wrote:
> Let me clarify my earlier comment.
>
> For this PR, I don't feel as though it's on me to ensure clang-format
> consistently / aesthetically picks between these:
>
> ```c++
> // good:
> template <typename Foo, typename Bar>
>
> template <typename Foo,
> typename Bar>
>
> template <
> typename Foo,
> typename Bar
> >
> ```
>
> The only thing that I need to do in this PR is prevent these cases, which
> should not be allowed when my feature is turned on (per your most recent
> suggestion, which I'm willing to accept):
>
> ```c++
> // bad:
> template <typename Foo, typename Bar
> >
>
> template <typename Foo,
> typename Bar
> >
>
> template <
> typename Foo,
> typename Bar>
> ```
>
> As long as the formatter is picking between one those first three, and never
> one of the latter three, I think we're in the clear.
>
> The issue arose last night when I was updating the lambda tests. It was
> picking between one of the first three, but, not consistently. It depended on
> whether "template Loooong" or "template T" was first or second. That's silly
> behavior that I don't agree with. So I intentionally did not test it. All I'm
> testing is that it picks between one of the allowable three variants, within
> reason. I do not intend or desire to lock in exactly which lambda scenarios
> cause which to be picked, because that isn't what I'm intending to change in
> this PR. So if it's inconsistent between two options, both of which are
> reasonable, I just decided to remove that from my tests.
If I understand you correctly, you just want to add a boolean option to break
after the template closer when there is a break after the matching template
opener? I'm fine with that! It seems though making it a struct doesn't make
sense anymore. Can we change it back to a boolean?
https://github.com/llvm/llvm-project/pull/118046
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits