summaryrefslogtreecommitdiff
path: root/unittests/Format/FormatTestComments.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/Format/FormatTestComments.cpp')
-rw-r--r--unittests/Format/FormatTestComments.cpp523
1 files changed, 517 insertions, 6 deletions
diff --git a/unittests/Format/FormatTestComments.cpp b/unittests/Format/FormatTestComments.cpp
index f3c45fac34a99..ed11fbdb1fc0d 100644
--- a/unittests/Format/FormatTestComments.cpp
+++ b/unittests/Format/FormatTestComments.cpp
@@ -62,6 +62,12 @@ protected:
return Style;
}
+ FormatStyle getTextProtoStyleWithColumns(unsigned ColumnLimit) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::FormatStyle::LK_TextProto);
+ Style.ColumnLimit = ColumnLimit;
+ return Style;
+ }
+
void verifyFormat(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
@@ -680,8 +686,7 @@ TEST_F(FormatTestComments, SplitsLongCxxComments) {
EXPECT_EQ("{\n"
" //\n"
" //\\\n"
- " // long 1 2 3 4\n"
- " // 5\n"
+ " // long 1 2 3 4 5\n"
"}",
format("{\n"
" //\n"
@@ -689,6 +694,18 @@ TEST_F(FormatTestComments, SplitsLongCxxComments) {
" // long 1 2 3 4 5\n"
"}",
getLLVMStyleWithColumns(20)));
+ EXPECT_EQ("{\n"
+ " //\n"
+ " //\\\n"
+ " // long 1 2 3 4 5\n"
+ " // 6\n"
+ "}",
+ format("{\n"
+ " //\n"
+ " //\\\n"
+ " // long 1 2 3 4 5 6\n"
+ "}",
+ getLLVMStyleWithColumns(20)));
}
TEST_F(FormatTestComments, PreservesHangingIndentInCxxComments) {
@@ -836,6 +853,67 @@ TEST_F(FormatTestComments, KeepsLevelOfCommentBeforePPDirective) {
" int j;\n"
"}"));
+ EXPECT_EQ("int f(int i) {\n"
+ " if (true) {\n"
+ " ++i;\n"
+ " }\n"
+ " // comment\n"
+ "#ifdef A\n"
+ " int j;\n"
+ "#endif\n"
+ "}",
+ format("int f(int i) {\n"
+ " if (true) {\n"
+ " ++i;\n"
+ " }\n"
+ " // comment\n"
+ "#ifdef A\n"
+ "int j;\n"
+ "#endif\n"
+ "}"));
+
+ EXPECT_EQ("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ " // comment in else\n"
+ "#ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}",
+ format("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ " // comment in else\n"
+ "#ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}"));
+
+ EXPECT_EQ("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ " /* comment in else */\n"
+ "#ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}",
+ format("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ " /* comment in else */\n"
+ "#ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}"));
+
// Keep the current level if there is an empty line between the comment and
// the preprocessor directive.
EXPECT_EQ("void f() {\n"
@@ -853,8 +931,95 @@ TEST_F(FormatTestComments, KeepsLevelOfCommentBeforePPDirective) {
" int j;\n"
"}"));
+ EXPECT_EQ("void f() {\n"
+ " int i;\n"
+ " return i;\n"
+ "}\n"
+ "// comment\n"
+ "\n"
+ "#ifdef A\n"
+ "int i;\n"
+ "#endif // A",
+ format("void f() {\n"
+ " int i;\n"
+ " return i;\n"
+ "}\n"
+ "// comment\n"
+ "\n"
+ "#ifdef A\n"
+ "int i;\n"
+ "#endif // A"));
+
+ EXPECT_EQ("int f(int i) {\n"
+ " if (true) {\n"
+ " ++i;\n"
+ " }\n"
+ " // comment\n"
+ "\n"
+ "#ifdef A\n"
+ " int j;\n"
+ "#endif\n"
+ "}",
+ format("int f(int i) {\n"
+ " if (true) {\n"
+ " ++i;\n"
+ " }\n"
+ " // comment\n"
+ "\n"
+ "#ifdef A\n"
+ " int j;\n"
+ "#endif\n"
+ "}"));
+
+ EXPECT_EQ("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ " // comment in else\n"
+ "\n"
+ "#ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}",
+ format("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ "// comment in else\n"
+ "\n"
+ "#ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}"));
+
+ EXPECT_EQ("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ " /* comment in else */\n"
+ "\n"
+ "#ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}",
+ format("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ "/* comment in else */\n"
+ "\n"
+ "#ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}"));
+
// Align with the preprocessor directive if the comment was originally aligned
- // with the preprocessor directive.
+ // with the preprocessor directive and there is no newline between the comment
+ // and the preprocessor directive.
EXPECT_EQ("void f() {\n"
" int i;\n"
"/* comment */\n"
@@ -867,14 +1032,76 @@ TEST_F(FormatTestComments, KeepsLevelOfCommentBeforePPDirective) {
"#ifdef A\n"
" int j;\n"
"}"));
+
+ EXPECT_EQ("int f(int i) {\n"
+ " if (true) {\n"
+ " ++i;\n"
+ " }\n"
+ "// comment\n"
+ "#ifdef A\n"
+ " int j;\n"
+ "#endif\n"
+ "}",
+ format("int f(int i) {\n"
+ " if (true) {\n"
+ " ++i;\n"
+ " }\n"
+ "// comment\n"
+ "#ifdef A\n"
+ " int j;\n"
+ "#endif\n"
+ "}"));
+
+ EXPECT_EQ("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ "// comment in else\n"
+ "#ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}",
+ format("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ " // comment in else\n"
+ " #ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}"));
+
+ EXPECT_EQ("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ "/* comment in else */\n"
+ "#ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}",
+ format("int f(int i) {\n"
+ " if (true) {\n"
+ " i++;\n"
+ " } else {\n"
+ " /* comment in else */\n"
+ " #ifdef A\n"
+ " j++;\n"
+ "#endif\n"
+ " }\n"
+ "}"));
}
TEST_F(FormatTestComments, SplitsLongLinesInComments) {
+ // FIXME: Do we need to fix up the " */" at the end?
+ // It doesn't look like any of our current logic triggers this.
EXPECT_EQ("/* This is a long\n"
" * comment that\n"
- " * doesn't\n"
- " * fit on one line.\n"
- " */",
+ " * doesn't fit on\n"
+ " * one line. */",
format("/* "
"This is a long "
"comment that "
@@ -1852,6 +2079,22 @@ TEST_F(FormatTestComments, ReflowsComments) {
" // longsec\n",
getLLVMStyleWithColumns(20)));
+ // Simple case that correctly handles reflow in parameter lists.
+ EXPECT_EQ("a = f(/* looooooooong\n"
+ " * long long\n"
+ " */\n"
+ " a);",
+ format("a = f(/* looooooooong long\n* long\n*/ a);",
+ getLLVMStyleWithColumns(22)));
+ // Tricky case that has fewer lines if we reflow the comment, ending up with
+ // fewer lines.
+ EXPECT_EQ("a = f(/* loooooong\n"
+ " * long long\n"
+ " */\n"
+ " a);",
+ format("a = f(/* loooooong long\n* long\n*/ a);",
+ getLLVMStyleWithColumns(22)));
+
// Keep empty comment lines.
EXPECT_EQ("/**/", format(" /**/", getLLVMStyleWithColumns(20)));
EXPECT_EQ("/* */", format(" /* */", getLLVMStyleWithColumns(20)));
@@ -1860,6 +2103,85 @@ TEST_F(FormatTestComments, ReflowsComments) {
EXPECT_EQ("///", format(" /// ", getLLVMStyleWithColumns(20)));
}
+TEST_F(FormatTestComments, ReflowsCommentsPrecise) {
+ // FIXME: This assumes we do not continue compressing whitespace once we are
+ // in reflow mode. Consider compressing whitespace.
+
+ // Test that we stop reflowing precisely at the column limit.
+ // After reflowing, "// reflows into foo" does not fit the column limit,
+ // so we compress the whitespace.
+ EXPECT_EQ("// some text that\n"
+ "// reflows into foo\n",
+ format("// some text that reflows\n"
+ "// into foo\n",
+ getLLVMStyleWithColumns(20)));
+ // Given one more column, "// reflows into foo" does fit the limit, so we
+ // do not compress the whitespace.
+ EXPECT_EQ("// some text that\n"
+ "// reflows into foo\n",
+ format("// some text that reflows\n"
+ "// into foo\n",
+ getLLVMStyleWithColumns(21)));
+
+ // Make sure that we correctly account for the space added in the reflow case
+ // when making the reflowing decision.
+ // First, when the next line ends precisely one column over the limit, do not
+ // reflow.
+ EXPECT_EQ("// some text that\n"
+ "// reflows\n"
+ "// into1234567\n",
+ format("// some text that reflows\n"
+ "// into1234567\n",
+ getLLVMStyleWithColumns(21)));
+ // Secondly, when the next line ends later, but the first word in that line
+ // is precisely one column over the limit, do not reflow.
+ EXPECT_EQ("// some text that\n"
+ "// reflows\n"
+ "// into1234567 f\n",
+ format("// some text that reflows\n"
+ "// into1234567 f\n",
+ getLLVMStyleWithColumns(21)));
+}
+
+TEST_F(FormatTestComments, ReflowsCommentsWithExtraWhitespace) {
+ // Baseline.
+ EXPECT_EQ("// some text\n"
+ "// that re flows\n",
+ format("// some text that\n"
+ "// re flows\n",
+ getLLVMStyleWithColumns(16)));
+ EXPECT_EQ("// some text\n"
+ "// that re flows\n",
+ format("// some text that\n"
+ "// re flows\n",
+ getLLVMStyleWithColumns(16)));
+ EXPECT_EQ("/* some text\n"
+ " * that re flows\n"
+ " */\n",
+ format("/* some text that\n"
+ "* re flows\n"
+ "*/\n",
+ getLLVMStyleWithColumns(16)));
+ // FIXME: We do not reflow if the indent of two subsequent lines differs;
+ // given that this is different behavior from block comments, do we want
+ // to keep this?
+ EXPECT_EQ("// some text\n"
+ "// that\n"
+ "// re flows\n",
+ format("// some text that\n"
+ "// re flows\n",
+ getLLVMStyleWithColumns(16)));
+ // Space within parts of a line that fit.
+ // FIXME: Use the earliest possible split while reflowing to compress the
+ // whitespace within the line.
+ EXPECT_EQ("// some text that\n"
+ "// does re flow\n"
+ "// more here\n",
+ format("// some text that does\n"
+ "// re flow more here\n",
+ getLLVMStyleWithColumns(21)));
+}
+
TEST_F(FormatTestComments, IgnoresIf0Contents) {
EXPECT_EQ("#if 0\n"
"}{)(&*(^%%#%@! fsadj f;ldjs ,:;| <<<>>>][)(][\n"
@@ -2198,6 +2520,74 @@ TEST_F(FormatTestComments, BlockCommentsAtEndOfLine) {
getLLVMStyleWithColumns(15)));
}
+TEST_F(FormatTestComments, BreaksAfterMultilineBlockCommentsInParamLists) {
+ EXPECT_EQ("a = f(/* long\n"
+ " long */\n"
+ " a);",
+ format("a = f(/* long long */ a);", getLLVMStyleWithColumns(16)));
+ EXPECT_EQ("a = f(\n"
+ " /* long\n"
+ " long */\n"
+ " a);",
+ format("a = f(/* long long */ a);", getLLVMStyleWithColumns(15)));
+
+ EXPECT_EQ("a = f(/* long\n"
+ " long\n"
+ " */\n"
+ " a);",
+ format("a = f(/* long\n"
+ " long\n"
+ " */a);",
+ getLLVMStyleWithColumns(16)));
+
+ EXPECT_EQ("a = f(/* long\n"
+ " long\n"
+ " */\n"
+ " a);",
+ format("a = f(/* long\n"
+ " long\n"
+ " */ a);",
+ getLLVMStyleWithColumns(16)));
+
+ EXPECT_EQ("a = f(/* long\n"
+ " long\n"
+ " */\n"
+ " (1 + 1));",
+ format("a = f(/* long\n"
+ " long\n"
+ " */ (1 + 1));",
+ getLLVMStyleWithColumns(16)));
+
+ EXPECT_EQ(
+ "a = f(a,\n"
+ " /* long\n"
+ " long */\n"
+ " b);",
+ format("a = f(a, /* long long */ b);", getLLVMStyleWithColumns(16)));
+
+ EXPECT_EQ(
+ "a = f(\n"
+ " a,\n"
+ " /* long\n"
+ " long */\n"
+ " b);",
+ format("a = f(a, /* long long */ b);", getLLVMStyleWithColumns(15)));
+
+ EXPECT_EQ("a = f(a,\n"
+ " /* long\n"
+ " long */\n"
+ " (1 + 1));",
+ format("a = f(a, /* long long */ (1 + 1));",
+ getLLVMStyleWithColumns(16)));
+ EXPECT_EQ("a = f(\n"
+ " a,\n"
+ " /* long\n"
+ " long */\n"
+ " (1 + 1));",
+ format("a = f(a, /* long long */ (1 + 1));",
+ getLLVMStyleWithColumns(15)));
+}
+
TEST_F(FormatTestComments, IndentLineCommentsInStartOfBlockAtEndOfFile) {
verifyFormat("{\n"
" // a\n"
@@ -2578,6 +2968,127 @@ TEST_F(FormatTestComments, AlignsBlockCommentDecorations) {
"* long */",
getLLVMStyleWithColumns(20)));
}
+
+TEST_F(FormatTestComments, NoCrash_Bug34236) {
+ // This is a test case from a crasher reported in:
+ // https://bugs.llvm.org/show_bug.cgi?id=34236
+ // Temporarily disable formatting for readability.
+ // clang-format off
+ EXPECT_EQ(
+"/* */ /*\n"
+" * a\n"
+" * b c d*/",
+ format(
+"/* */ /*\n"
+" * a b\n"
+" * c d*/",
+ getLLVMStyleWithColumns(80)));
+ // clang-format on
+}
+
+TEST_F(FormatTestComments, NonTrailingBlockComments) {
+ verifyFormat("const /** comment comment */ A = B;",
+ getLLVMStyleWithColumns(40));
+
+ verifyFormat("const /** comment comment comment */ A =\n"
+ " B;",
+ getLLVMStyleWithColumns(40));
+
+ EXPECT_EQ("const /** comment comment comment\n"
+ " comment */\n"
+ " A = B;",
+ format("const /** comment comment comment comment */\n"
+ " A = B;",
+ getLLVMStyleWithColumns(40)));
+}
+
+TEST_F(FormatTestComments, PythonStyleComments) {
+ // Keeps a space after '#'.
+ EXPECT_EQ("# comment\n"
+ "key: value",
+ format("#comment\n"
+ "key:value",
+ getTextProtoStyleWithColumns(20)));
+ EXPECT_EQ("# comment\n"
+ "key: value",
+ format("# comment\n"
+ "key:value",
+ getTextProtoStyleWithColumns(20)));
+ // Breaks long comment.
+ EXPECT_EQ("# comment comment\n"
+ "# comment\n"
+ "key: value",
+ format("# comment comment comment\n"
+ "key:value",
+ getTextProtoStyleWithColumns(20)));
+ // Indents comments.
+ EXPECT_EQ("data {\n"
+ " # comment comment\n"
+ " # comment\n"
+ " key: value\n"
+ "}",
+ format("data {\n"
+ "# comment comment comment\n"
+ "key: value}",
+ getTextProtoStyleWithColumns(20)));
+ EXPECT_EQ("data {\n"
+ " # comment comment\n"
+ " # comment\n"
+ " key: value\n"
+ "}",
+ format("data {# comment comment comment\n"
+ "key: value}",
+ getTextProtoStyleWithColumns(20)));
+ // Reflows long comments.
+ EXPECT_EQ("# comment comment\n"
+ "# comment comment\n"
+ "key: value",
+ format("# comment comment comment\n"
+ "# comment\n"
+ "key:value",
+ getTextProtoStyleWithColumns(20)));
+ // Breaks trailing comments.
+ EXPECT_EQ("k: val # comment\n"
+ " # comment\n"
+ "a: 1",
+ format("k:val#comment comment\n"
+ "a:1",
+ getTextProtoStyleWithColumns(20)));
+ EXPECT_EQ("id {\n"
+ " k: val # comment\n"
+ " # comment\n"
+ " # line line\n"
+ " a: 1\n"
+ "}",
+ format("id {k:val#comment comment\n"
+ "# line line\n"
+ "a:1}",
+ getTextProtoStyleWithColumns(20)));
+ // Aligns trailing comments.
+ EXPECT_EQ("k: val # commen1\n"
+ " # commen2\n"
+ " # commen3\n"
+ "# commen4\n"
+ "a: 1 # commen5\n"
+ " # commen6\n"
+ " # commen7",
+ format("k:val#commen1 commen2\n"
+ " # commen3\n"
+ "# commen4\n"
+ "a:1#commen5 commen6\n"
+ " #commen7",
+ getTextProtoStyleWithColumns(20)));
+}
+
+TEST_F(FormatTestComments, BreaksBeforeTrailingUnbreakableSequence) {
+ // The end of /* trail */ is exactly at 80 columns, but the unbreakable
+ // trailing sequence ); after it exceeds the column limit. Make sure we
+ // correctly break the line in that case.
+ verifyFormat("int a =\n"
+ " foo(/* trail */);",
+ getLLVMStyleWithColumns(23));
+}
+
} // end namespace
} // end namespace format
} // end namespace clang