================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits