blob: 01a90a306c9b0d36b50ea3af97bd651b8188b7f9 [file] [log] [blame]
Eric Liu4cfb88a2016-04-25 15:09:22 +00001//===- unittest/Format/CleanupTest.cpp - Code cleanup unit tests ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "clang/Format/Format.h"
11
12#include "clang/Tooling/Core/Replacement.h"
13
14#include "gtest/gtest.h"
15
16namespace clang {
17namespace format {
18namespace {
19
20class CleanupTest : public ::testing::Test {
21protected:
22 std::string cleanup(llvm::StringRef Code,
23 const std::vector<tooling::Range> &Ranges,
24 const FormatStyle &Style = getLLVMStyle()) {
25 tooling::Replacements Replaces = format::cleanup(Style, Code, Ranges);
26
27 std::string Result = applyAllReplacements(Code, Replaces);
28 EXPECT_NE("", Result);
29 return Result;
30 }
31};
32
33TEST_F(CleanupTest, DeleteEmptyNamespaces) {
34 std::string Code = "namespace A {\n"
35 "namespace B {\n"
36 "} // namespace B\n"
37 "} // namespace A\n\n"
38 "namespace C {\n"
39 "namespace D { int i; }\n"
40 "inline namespace E { namespace { } }\n"
41 "}";
42 std::string Expected = "\n\n\n\n\nnamespace C {\n"
43 "namespace D { int i; }\n \n"
44 "}";
45 std::vector<tooling::Range> Ranges;
46 Ranges.push_back(tooling::Range(28, 0));
47 Ranges.push_back(tooling::Range(91, 6));
48 Ranges.push_back(tooling::Range(132, 0));
49 std::string Result = cleanup(Code, Ranges);
50 EXPECT_EQ(Expected, Result);
51}
52
53TEST_F(CleanupTest, NamespaceWithSyntaxError) {
54 std::string Code = "namespace A {\n"
55 "namespace B {\n" // missing r_brace
56 "} // namespace A\n\n"
57 "namespace C {\n"
58 "namespace D int i; }\n"
59 "inline namespace E { namespace { } }\n"
60 "}";
61 std::string Expected = "namespace A {\n"
62 "\n\n\nnamespace C {\n"
63 "namespace D int i; }\n \n"
64 "}";
65 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
66 std::string Result = cleanup(Code, Ranges);
67 EXPECT_EQ(Expected, Result);
68}
69
70TEST_F(CleanupTest, EmptyNamespaceNotAffected) {
71 std::string Code = "namespace A {\n\n"
72 "namespace {\n\n}}";
73 // Even though the namespaces are empty, but the inner most empty namespace
74 // block is not affected by the changed ranges.
75 std::string Expected = "namespace A {\n\n"
76 "namespace {\n\n}}";
77 // Set the changed range to be the second "\n".
78 std::vector<tooling::Range> Ranges(1, tooling::Range(14, 0));
79 std::string Result = cleanup(Code, Ranges);
80 EXPECT_EQ(Expected, Result);
81}
82
83TEST_F(CleanupTest, EmptyNamespaceWithCommentsNoBreakBeforeBrace) {
84 std::string Code = "namespace A {\n"
85 "namespace B {\n"
86 "// Yo\n"
87 "} // namespace B\n"
88 "} // namespace A\n"
89 "namespace C { // Yo\n"
90 "}";
91 std::string Expected = "\n\n\n\n\n\n";
92 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
93 std::string Result = cleanup(Code, Ranges);
94 EXPECT_EQ(Expected, Result);
95}
96
97TEST_F(CleanupTest, EmptyNamespaceWithCommentsBreakBeforeBrace) {
98 std::string Code = "namespace A\n"
99 "/* Yo */ {\n"
100 "namespace B\n"
101 "{\n"
102 "// Yo\n"
103 "} // namespace B\n"
104 "} // namespace A\n"
105 "namespace C\n"
106 "{ // Yo\n"
107 "}\n";
108 std::string Expected = "\n\n\n\n\n\n\n\n\n\n";
109 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
110 FormatStyle Style = getLLVMStyle();
111 Style.BraceWrapping.AfterNamespace = true;
112 std::string Result = cleanup(Code, Ranges, Style);
113 EXPECT_EQ(Expected, Result);
114}
115
Eric Liuce5e4bc2016-05-18 08:02:56 +0000116TEST_F(CleanupTest, CtorInitializationSimpleRedundantComma) {
117 std::string Code = "class A {\nA() : , {} };";
118 std::string Expected = "class A {\nA() {} };";
119 std::vector<tooling::Range> Ranges;
120 Ranges.push_back(tooling::Range(17, 0));
121 Ranges.push_back(tooling::Range(19, 0));
122 std::string Result = cleanup(Code, Ranges);
123 EXPECT_EQ(Expected, Result);
124
125 Code = "class A {\nA() : x(1), {} };";
126 Expected = "class A {\nA() : x(1) {} };";
127 Ranges.clear();
128 Ranges.push_back(tooling::Range(23, 0));
129 Result = cleanup(Code, Ranges);
130 EXPECT_EQ(Expected, Result);
131
132 Code = "class A {\nA() :,,,,{} };";
133 Expected = "class A {\nA() {} };";
134 Ranges.clear();
135 Ranges.push_back(tooling::Range(15, 0));
136 Result = cleanup(Code, Ranges);
137 EXPECT_EQ(Expected, Result);
138}
139
140TEST_F(CleanupTest, ListSimpleRedundantComma) {
141 std::string Code = "void f() { std::vector<int> v = {1,2,,,3,{4,5}}; }";
142 std::string Expected = "void f() { std::vector<int> v = {1,2,3,{4,5}}; }";
143 std::vector<tooling::Range> Ranges;
144 Ranges.push_back(tooling::Range(40, 0));
145 std::string Result = cleanup(Code, Ranges);
146 EXPECT_EQ(Expected, Result);
147
148 Code = "int main() { f(1,,2,3,,4);}";
149 Expected = "int main() { f(1,2,3,4);}";
150 Ranges.clear();
151 Ranges.push_back(tooling::Range(17, 0));
152 Ranges.push_back(tooling::Range(22, 0));
153 Result = cleanup(Code, Ranges);
154 EXPECT_EQ(Expected, Result);
155}
156
157TEST_F(CleanupTest, CtorInitializationBracesInParens) {
158 std::string Code = "class A {\nA() : x({1}),, {} };";
159 std::string Expected = "class A {\nA() : x({1}) {} };";
160 std::vector<tooling::Range> Ranges;
161 Ranges.push_back(tooling::Range(24, 0));
162 Ranges.push_back(tooling::Range(26, 0));
163 std::string Result = cleanup(Code, Ranges);
164 EXPECT_EQ(Expected, Result);
165}
166
167TEST_F(CleanupTest, RedundantCommaNotInAffectedRanges) {
168 std::string Code =
169 "class A {\nA() : x({1}), /* comment */, { int x = 0; } };";
170 std::string Expected =
171 "class A {\nA() : x({1}), /* comment */, { int x = 0; } };";
172 // Set the affected range to be "int x = 0", which does not intercept the
173 // constructor initialization list.
174 std::vector<tooling::Range> Ranges(1, tooling::Range(42, 9));
175 std::string Result = cleanup(Code, Ranges);
176 EXPECT_EQ(Expected, Result);
177
178 Code = "class A {\nA() : x(1), {} };";
179 Expected = "class A {\nA() : x(1), {} };";
180 // No range. Fixer should do nothing.
181 Ranges.clear();
182 Result = cleanup(Code, Ranges);
183 EXPECT_EQ(Expected, Result);
184}
185
186// FIXME: delete comments too.
187TEST_F(CleanupTest, CtorInitializationCommentAroundCommas) {
188 // Remove redundant commas around comment.
189 std::string Code = "class A {\nA() : x({1}), /* comment */, {} };";
190 std::string Expected = "class A {\nA() : x({1}) /* comment */ {} };";
191 std::vector<tooling::Range> Ranges;
192 Ranges.push_back(tooling::Range(25, 0));
193 Ranges.push_back(tooling::Range(40, 0));
194 std::string Result = cleanup(Code, Ranges);
195 EXPECT_EQ(Expected, Result);
196
197 // Remove trailing comma and ignore comment.
198 Code = "class A {\nA() : x({1}), // comment\n{} };";
199 Expected = "class A {\nA() : x({1}) // comment\n{} };";
200 Ranges = std::vector<tooling::Range>(1, tooling::Range(25, 0));
201 Result = cleanup(Code, Ranges);
202 EXPECT_EQ(Expected, Result);
203
204 // Remove trailing comma and ignore comment.
205 Code = "class A {\nA() : x({1}), // comment\n , y(1),{} };";
206 Expected = "class A {\nA() : x({1}), // comment\n y(1){} };";
207 Ranges = std::vector<tooling::Range>(1, tooling::Range(38, 0));
208 Result = cleanup(Code, Ranges);
209 EXPECT_EQ(Expected, Result);
210
211 // Remove trailing comma and ignore comment.
212 Code = "class A {\nA() : x({1}), \n/* comment */, y(1),{} };";
213 Expected = "class A {\nA() : x({1}), \n/* comment */ y(1){} };";
214 Ranges = std::vector<tooling::Range>(1, tooling::Range(40, 0));
215 Result = cleanup(Code, Ranges);
216 EXPECT_EQ(Expected, Result);
217
218 // Remove trailing comma and ignore comment.
219 Code = "class A {\nA() : , // comment\n y(1),{} };";
220 Expected = "class A {\nA() : // comment\n y(1){} };";
221 Ranges = std::vector<tooling::Range>(1, tooling::Range(17, 0));
222 Result = cleanup(Code, Ranges);
223 EXPECT_EQ(Expected, Result);
224}
225
226TEST_F(CleanupTest, CtorInitializerInNamespace) {
227 std::string Code = "namespace A {\n"
228 "namespace B {\n" // missing r_brace
229 "} // namespace A\n\n"
230 "namespace C {\n"
231 "class A { A() : x(0),, {} };\n"
232 "inline namespace E { namespace { } }\n"
233 "}";
234 std::string Expected = "namespace A {\n"
235 "\n\n\nnamespace C {\n"
236 "class A { A() : x(0) {} };\n \n"
237 "}";
238 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
239 std::string Result = cleanup(Code, Ranges);
240 EXPECT_EQ(Expected, Result);
241}
242
Eric Liu4cfb88a2016-04-25 15:09:22 +0000243} // end namespace
244} // end namespace format
245} // end namespace clang