609 lines
18 KiB
C++
609 lines
18 KiB
C++
//===- unittest/Format/FormatTestSelective.cpp - Formatting unit tests ----===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "FormatTestUtils.h"
|
|
#include "clang/Format/Format.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
#define DEBUG_TYPE "format-test"
|
|
|
|
namespace clang {
|
|
namespace format {
|
|
namespace {
|
|
|
|
class FormatTestSelective : public ::testing::Test {
|
|
protected:
|
|
std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length) {
|
|
LLVM_DEBUG(llvm::errs() << "---\n");
|
|
LLVM_DEBUG(llvm::errs() << Code << "\n\n");
|
|
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
|
|
FormattingAttemptStatus Status;
|
|
tooling::Replacements Replaces =
|
|
reformat(Style, Code, Ranges, "<stdin>", &Status);
|
|
EXPECT_TRUE(Status.FormatComplete) << Code << "\n\n";
|
|
auto Result = applyAllReplacements(Code, Replaces);
|
|
EXPECT_TRUE(static_cast<bool>(Result));
|
|
LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
|
|
return *Result;
|
|
}
|
|
|
|
FormatStyle Style = getLLVMStyle();
|
|
};
|
|
|
|
TEST_F(FormatTestSelective, RemovesTrailingWhitespaceOfFormattedLine) {
|
|
EXPECT_EQ("int a;\nint b;", format("int a; \nint b;", 0, 0));
|
|
EXPECT_EQ("int a;", format("int a; ", 0, 0));
|
|
EXPECT_EQ("int a;\n", format("int a; \n \n \n ", 0, 0));
|
|
EXPECT_EQ("int a;\nint b; ", format("int a; \nint b; ", 0, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, FormatsCorrectRegionForLeadingWhitespace) {
|
|
EXPECT_EQ("{int b;\n"
|
|
" int a;\n"
|
|
"}",
|
|
format("{int b;\n int a;}", 8, 0));
|
|
EXPECT_EQ("{\n"
|
|
" int b;\n"
|
|
" int a;}",
|
|
format("{int b;\n int a;}", 7, 0));
|
|
|
|
Style.ColumnLimit = 12;
|
|
EXPECT_EQ("#define A \\\n"
|
|
" int a; \\\n"
|
|
" int b;",
|
|
format("#define A \\\n"
|
|
" int a; \\\n"
|
|
" int b;",
|
|
26, 0));
|
|
EXPECT_EQ("#define A \\\n"
|
|
" int a; \\\n"
|
|
" int b;",
|
|
format("#define A \\\n"
|
|
" int a; \\\n"
|
|
" int b;",
|
|
25, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, FormatLineWhenInvokedOnTrailingNewline) {
|
|
EXPECT_EQ("int b;\n\nint a;", format("int b;\n\nint a;", 8, 0));
|
|
EXPECT_EQ("int b;\n\nint a;", format("int b;\n\nint a;", 7, 0));
|
|
|
|
// This might not strictly be correct, but is likely good in all practical
|
|
// cases.
|
|
EXPECT_EQ("int b;\nint a;", format("int b;int a;", 7, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, RemovesWhitespaceWhenTriggeredOnEmptyLine) {
|
|
EXPECT_EQ("int a;\n\n int b;", format("int a;\n \n\n int b;", 8, 0));
|
|
EXPECT_EQ("int a;\n\n int b;", format("int a;\n \n\n int b;", 9, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, ReformatsMovedLines) {
|
|
EXPECT_EQ(
|
|
"template <typename T> T *getFETokenInfo() const {\n"
|
|
" return static_cast<T *>(FETokenInfo);\n"
|
|
"}\n"
|
|
"int a; // <- Should not be formatted",
|
|
format(
|
|
"template<typename T>\n"
|
|
"T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); }\n"
|
|
"int a; // <- Should not be formatted",
|
|
9, 5));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, FormatsIfWithoutCompoundStatement) {
|
|
Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_WithoutElse;
|
|
EXPECT_EQ("if (a) return;", format("if(a)\nreturn;", 7, 1));
|
|
EXPECT_EQ("if (a) return; // comment",
|
|
format("if(a)\nreturn; // comment", 20, 1));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, FormatsCommentsLocally) {
|
|
EXPECT_EQ("int a; // comment\n"
|
|
"int b; // comment",
|
|
format("int a; // comment\n"
|
|
"int b; // comment",
|
|
0, 0));
|
|
EXPECT_EQ("int a; // comment\n"
|
|
" // line 2\n"
|
|
"int b;",
|
|
format("int a; // comment\n"
|
|
" // line 2\n"
|
|
"int b;",
|
|
28, 0));
|
|
EXPECT_EQ("int a; // comment\n"
|
|
"// comment 2\n"
|
|
"int b;",
|
|
format("int a; // comment\n"
|
|
"// comment 2\n"
|
|
"int b;",
|
|
28, 0));
|
|
EXPECT_EQ("int aaaaaa; // comment\n"
|
|
"int b;\n"
|
|
"int c; // unrelated comment",
|
|
format("int aaaaaa; // comment\n"
|
|
"int b;\n"
|
|
"int c; // unrelated comment",
|
|
31, 0));
|
|
|
|
EXPECT_EQ("int a; // This\n"
|
|
" // is\n"
|
|
" // a",
|
|
format("int a; // This\n"
|
|
" // is\n"
|
|
" // a",
|
|
0, 0));
|
|
EXPECT_EQ("int a; // This\n"
|
|
" // is\n"
|
|
" // a\n"
|
|
"// This is b\n"
|
|
"int b;",
|
|
format("int a; // This\n"
|
|
" // is\n"
|
|
" // a\n"
|
|
"// This is b\n"
|
|
"int b;",
|
|
0, 0));
|
|
EXPECT_EQ("int a; // This\n"
|
|
" // is\n"
|
|
" // a\n"
|
|
"\n"
|
|
"//This is unrelated",
|
|
format("int a; // This\n"
|
|
" // is\n"
|
|
" // a\n"
|
|
"\n"
|
|
"//This is unrelated",
|
|
0, 0));
|
|
EXPECT_EQ("int a;\n"
|
|
"// This is\n"
|
|
"// not formatted. ",
|
|
format("int a;\n"
|
|
"// This is\n"
|
|
"// not formatted. ",
|
|
0, 0));
|
|
EXPECT_EQ("int x; // Format this line.\n"
|
|
"int xx; //\n"
|
|
"int xxxxx; //",
|
|
format("int x; // Format this line.\n"
|
|
"int xx; //\n"
|
|
"int xxxxx; //",
|
|
0, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, ContinueReindenting) {
|
|
// When we change an indent, we continue formatting as long as following
|
|
// lines are not indented correctly.
|
|
EXPECT_EQ("int i;\n"
|
|
"int b;\n"
|
|
"int c;\n"
|
|
"int d;\n"
|
|
"int e;\n"
|
|
" int f;\n",
|
|
format("int i;\n"
|
|
" int b;\n"
|
|
" int c;\n"
|
|
" int d;\n"
|
|
"int e;\n"
|
|
" int f;\n",
|
|
11, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, ReindentClosingBrace) {
|
|
EXPECT_EQ("int i;\n"
|
|
"int f() {\n"
|
|
" int a;\n"
|
|
" int b;\n"
|
|
"}\n"
|
|
" int c;\n",
|
|
format("int i;\n"
|
|
" int f(){\n"
|
|
"int a;\n"
|
|
"int b;\n"
|
|
" }\n"
|
|
" int c;\n",
|
|
11, 0));
|
|
EXPECT_EQ("void f() {\n"
|
|
" if (foo) {\n"
|
|
" b();\n"
|
|
" } else {\n"
|
|
" c();\n"
|
|
" }\n"
|
|
"int d;\n"
|
|
"}\n",
|
|
format("void f() {\n"
|
|
" if (foo) {\n"
|
|
"b();\n"
|
|
"}else{\n"
|
|
"c();\n"
|
|
"}\n"
|
|
"int d;\n"
|
|
"}\n",
|
|
13, 0));
|
|
EXPECT_EQ("int i = []() {\n"
|
|
" class C {\n"
|
|
" int a;\n"
|
|
" int b;\n"
|
|
" };\n"
|
|
" int c;\n"
|
|
"};\n",
|
|
format("int i = []() {\n"
|
|
" class C{\n"
|
|
"int a;\n"
|
|
"int b;\n"
|
|
"};\n"
|
|
"int c;\n"
|
|
" };\n",
|
|
17, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, IndividualStatementsOfNestedBlocks) {
|
|
EXPECT_EQ("DEBUG({\n"
|
|
" int i;\n"
|
|
" int j;\n"
|
|
"});",
|
|
format("DEBUG( {\n"
|
|
" int i;\n"
|
|
" int j;\n"
|
|
"} ) ;",
|
|
20, 1));
|
|
EXPECT_EQ("DEBUG( {\n"
|
|
" int i;\n"
|
|
" int j;\n"
|
|
"} ) ;",
|
|
format("DEBUG( {\n"
|
|
" int i;\n"
|
|
" int j;\n"
|
|
"} ) ;",
|
|
41, 1));
|
|
EXPECT_EQ("DEBUG( {\n"
|
|
" int i;\n"
|
|
" int j;\n"
|
|
"} ) ;",
|
|
format("DEBUG( {\n"
|
|
" int i;\n"
|
|
" int j;\n"
|
|
"} ) ;",
|
|
41, 1));
|
|
EXPECT_EQ("DEBUG({\n"
|
|
" int i;\n"
|
|
" int j;\n"
|
|
"});",
|
|
format("DEBUG( {\n"
|
|
" int i;\n"
|
|
" int j;\n"
|
|
"} ) ;",
|
|
20, 1));
|
|
|
|
EXPECT_EQ("Debug({\n"
|
|
" if (aaaaaaaaaaaaaaaaaaaaaaaa)\n"
|
|
" return;\n"
|
|
" },\n"
|
|
" a);",
|
|
format("Debug({\n"
|
|
" if (aaaaaaaaaaaaaaaaaaaaaaaa)\n"
|
|
" return;\n"
|
|
" },\n"
|
|
" a);",
|
|
50, 1));
|
|
EXPECT_EQ("DEBUG({\n"
|
|
" DEBUG({\n"
|
|
" int a;\n"
|
|
" int b;\n"
|
|
" }) ;\n"
|
|
"});",
|
|
format("DEBUG({\n"
|
|
" DEBUG({\n"
|
|
" int a;\n"
|
|
" int b;\n" // Format this line only.
|
|
" }) ;\n" // Don't touch this line.
|
|
"});",
|
|
35, 0));
|
|
EXPECT_EQ("DEBUG({\n"
|
|
" int a; //\n"
|
|
"});",
|
|
format("DEBUG({\n"
|
|
" int a; //\n"
|
|
"});",
|
|
0, 0));
|
|
EXPECT_EQ("someFunction(\n"
|
|
" [] {\n"
|
|
" // Only with this comment.\n"
|
|
" int i; // invoke formatting here.\n"
|
|
" }, // force line break\n"
|
|
" aaa);",
|
|
format("someFunction(\n"
|
|
" [] {\n"
|
|
" // Only with this comment.\n"
|
|
" int i; // invoke formatting here.\n"
|
|
" }, // force line break\n"
|
|
" aaa);",
|
|
63, 1));
|
|
|
|
EXPECT_EQ("int longlongname; // comment\n"
|
|
"int x = f({\n"
|
|
" int x; // comment\n"
|
|
" int y; // comment\n"
|
|
"});",
|
|
format("int longlongname; // comment\n"
|
|
"int x = f({\n"
|
|
" int x; // comment\n"
|
|
" int y; // comment\n"
|
|
"});",
|
|
65, 0));
|
|
EXPECT_EQ("int s = f({\n"
|
|
" class X {\n"
|
|
" public:\n"
|
|
" void f();\n"
|
|
" };\n"
|
|
"});",
|
|
format("int s = f({\n"
|
|
" class X {\n"
|
|
" public:\n"
|
|
" void f();\n"
|
|
" };\n"
|
|
"});",
|
|
0, 0));
|
|
EXPECT_EQ("SomeFunction(\n"
|
|
" [] {\n"
|
|
" int i;\n"
|
|
" return i;\n" // Format this line.
|
|
" },\n"
|
|
" [] {\n"
|
|
" return 2;\n" // Don't fix this.
|
|
" });",
|
|
format("SomeFunction(\n"
|
|
" [] {\n"
|
|
" int i;\n"
|
|
" return i;\n" // Format this line.
|
|
" },\n"
|
|
" [] {\n"
|
|
" return 2;\n" // Don't fix this.
|
|
" });",
|
|
40, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, WrongIndent) {
|
|
EXPECT_EQ("namespace {\n"
|
|
"int i;\n"
|
|
"int j;\n"
|
|
"}",
|
|
format("namespace {\n"
|
|
" int i;\n" // Format here.
|
|
" int j;\n"
|
|
"}",
|
|
15, 0));
|
|
EXPECT_EQ("namespace {\n"
|
|
" int i;\n"
|
|
" int j;\n"
|
|
"}",
|
|
format("namespace {\n"
|
|
" int i;\n"
|
|
" int j;\n" // Format here.
|
|
"}",
|
|
24, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, AlwaysFormatsEntireMacroDefinitions) {
|
|
Style.AlignEscapedNewlines = FormatStyle::ENAS_Left;
|
|
EXPECT_EQ("int i;\n"
|
|
"#define A \\\n"
|
|
" int i; \\\n"
|
|
" int j\n"
|
|
"int k;",
|
|
format("int i;\n"
|
|
"#define A \\\n"
|
|
" int i ; \\\n"
|
|
" int j\n"
|
|
"int k;",
|
|
8, 0)); // 8: position of "#define".
|
|
EXPECT_EQ("int i;\n"
|
|
"#define A \\\n"
|
|
" int i; \\\n"
|
|
" int j\n"
|
|
"int k;",
|
|
format("int i;\n"
|
|
"#define A \\\n"
|
|
" int i ; \\\n"
|
|
" int j\n"
|
|
"int k;",
|
|
45, 0)); // 45: position of "j".
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, ReformatRegionAdjustsIndent) {
|
|
EXPECT_EQ("{\n"
|
|
"{\n"
|
|
"a;\n"
|
|
"b;\n"
|
|
"}\n"
|
|
"}",
|
|
format("{\n"
|
|
"{\n"
|
|
"a;\n"
|
|
" b;\n"
|
|
"}\n"
|
|
"}",
|
|
13, 2));
|
|
EXPECT_EQ("{\n"
|
|
"{\n"
|
|
" a;\n"
|
|
" b;\n"
|
|
" c;\n"
|
|
" d;\n"
|
|
"}\n"
|
|
"}",
|
|
format("{\n"
|
|
"{\n"
|
|
" a;\n"
|
|
" b;\n"
|
|
" c;\n"
|
|
" d;\n"
|
|
"}\n"
|
|
"}",
|
|
9, 2));
|
|
EXPECT_EQ("{\n"
|
|
"{\n"
|
|
"public:\n"
|
|
" b;\n"
|
|
"}\n"
|
|
"}",
|
|
format("{\n"
|
|
"{\n"
|
|
"public:\n"
|
|
" b;\n"
|
|
"}\n"
|
|
"}",
|
|
17, 2));
|
|
EXPECT_EQ("{\n"
|
|
"{\n"
|
|
"a;\n"
|
|
"}\n"
|
|
"{\n"
|
|
" b; //\n"
|
|
"}\n"
|
|
"}",
|
|
format("{\n"
|
|
"{\n"
|
|
"a;\n"
|
|
"}\n"
|
|
"{\n"
|
|
" b; //\n"
|
|
"}\n"
|
|
"}",
|
|
22, 2));
|
|
EXPECT_EQ(" {\n"
|
|
" a; //\n"
|
|
" }",
|
|
format(" {\n"
|
|
"a; //\n"
|
|
" }",
|
|
4, 2));
|
|
EXPECT_EQ("void f() {}\n"
|
|
"void g() {}",
|
|
format("void f() {}\n"
|
|
"void g() {}",
|
|
13, 0));
|
|
EXPECT_EQ("int a; // comment\n"
|
|
" // line 2\n"
|
|
"int b;",
|
|
format("int a; // comment\n"
|
|
" // line 2\n"
|
|
" int b;",
|
|
35, 0));
|
|
|
|
EXPECT_EQ(" void f() {\n"
|
|
"#define A 1\n"
|
|
" }",
|
|
format(" void f() {\n"
|
|
" #define A 1\n" // Format this line.
|
|
" }",
|
|
20, 0));
|
|
EXPECT_EQ(" void f() {\n"
|
|
" int i;\n"
|
|
"#define A \\\n"
|
|
" int i; \\\n"
|
|
" int j;\n"
|
|
" int k;\n"
|
|
" }",
|
|
format(" void f() {\n"
|
|
" int i;\n"
|
|
"#define A \\\n"
|
|
" int i; \\\n"
|
|
" int j;\n"
|
|
" int k;\n" // Format this line.
|
|
" }",
|
|
67, 0));
|
|
|
|
Style.ColumnLimit = 11;
|
|
EXPECT_EQ(" int a;\n"
|
|
" void\n"
|
|
" ffffff() {\n"
|
|
" }",
|
|
format(" int a;\n"
|
|
"void ffffff() {}",
|
|
11, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, UnderstandsTabs) {
|
|
Style.IndentWidth = 8;
|
|
Style.UseTab = FormatStyle::UT_Always;
|
|
Style.AlignEscapedNewlines = FormatStyle::ENAS_Left;
|
|
EXPECT_EQ("void f() {\n"
|
|
"\tf();\n"
|
|
"\tg();\n"
|
|
"}",
|
|
format("void f() {\n"
|
|
"\tf();\n"
|
|
"\tg();\n"
|
|
"}",
|
|
0, 0));
|
|
EXPECT_EQ("void f() {\n"
|
|
"\tf();\n"
|
|
"\tg();\n"
|
|
"}",
|
|
format("void f() {\n"
|
|
"\tf();\n"
|
|
"\tg();\n"
|
|
"}",
|
|
16, 0));
|
|
EXPECT_EQ("void f() {\n"
|
|
" \tf();\n"
|
|
"\tg();\n"
|
|
"}",
|
|
format("void f() {\n"
|
|
" \tf();\n"
|
|
" \tg();\n"
|
|
"}",
|
|
21, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, StopFormattingWhenLeavingScope) {
|
|
EXPECT_EQ(
|
|
"void f() {\n"
|
|
" if (a) {\n"
|
|
" g();\n"
|
|
" h();\n"
|
|
" }\n"
|
|
"\n"
|
|
"void g() {\n"
|
|
"}",
|
|
format("void f() {\n"
|
|
" if (a) {\n" // Assume this was added without the closing brace.
|
|
" g();\n"
|
|
" h();\n"
|
|
"}\n"
|
|
"\n"
|
|
"void g() {\n" // Make sure not to format this.
|
|
"}",
|
|
15, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, SelectivelyRequoteJavaScript) {
|
|
Style = getGoogleStyle(FormatStyle::LK_JavaScript);
|
|
EXPECT_EQ("var x = \"a\";\n"
|
|
"var x = 'a';\n"
|
|
"var x = \"a\";",
|
|
format("var x = \"a\";\n"
|
|
"var x = \"a\";\n"
|
|
"var x = \"a\";",
|
|
20, 0));
|
|
}
|
|
|
|
TEST_F(FormatTestSelective, KeepsIndentAfterCommentSectionImport) {
|
|
std::string Code = "#include <a> // line 1\n" // 23 chars long
|
|
" // line 2\n" // 23 chars long
|
|
"\n" // this newline is char 47
|
|
"int i;"; // this line is not indented
|
|
EXPECT_EQ(Code, format(Code, 47, 1));
|
|
}
|
|
|
|
} // end namespace
|
|
} // end namespace format
|
|
} // end namespace clang
|