================ @@ -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); ---------------- leijurv 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. https://github.com/llvm/llvm-project/pull/118046 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits