clang-tools  14.0.0git
FormatTests.cpp
Go to the documentation of this file.
1 //===-- FormatTests.cpp - Automatic code formatting tests -----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Format.h"
10 #include "Annotations.h"
11 #include "SourceCode.h"
12 #include "TestFS.h"
13 #include "clang/Format/Format.h"
14 #include "clang/Tooling/Core/Replacement.h"
15 #include "llvm/Support/Error.h"
16 #include "gmock/gmock.h"
17 #include "gtest/gtest.h"
18 
19 namespace clang {
20 namespace clangd {
21 namespace {
22 
23 std::string afterTyped(llvm::StringRef CodeWithCursor,
24  llvm::StringRef Typed) {
25  Annotations Code(CodeWithCursor);
26  unsigned Cursor = llvm::cantFail(positionToOffset(Code.code(), Code.point()));
27  auto Changes =
28  formatIncremental(Code.code(), Cursor, Typed,
29  format::getGoogleStyle(format::FormatStyle::LK_Cpp));
30  tooling::Replacements Merged;
31  for (const auto& R : Changes)
32  if (llvm::Error E = Merged.add(R))
33  ADD_FAILURE() << llvm::toString(std::move(E));
34  auto NewCode = tooling::applyAllReplacements(Code.code(), Merged);
35  EXPECT_TRUE(bool(NewCode))
36  << "Bad replacements: " << llvm::toString(NewCode.takeError());
37  NewCode->insert(transformCursorPosition(Cursor, Changes), "^");
38  return *NewCode;
39 }
40 
41 // We can't pass raw strings directly to EXPECT_EQ because of gcc bugs.
42 void expectAfterNewline(const char *Before, const char *After) {
43  EXPECT_EQ(After, afterTyped(Before, "\n")) << Before;
44 }
45 void expectAfter(const char *Typed, const char *Before, const char *After) {
46  EXPECT_EQ(After, afterTyped(Before, Typed)) << Before;
47 }
48 
49 TEST(FormatIncremental, SplitComment) {
50  expectAfterNewline(R"cpp(
51 // this comment was
52 ^split
53 )cpp",
54  R"cpp(
55 // this comment was
56 // ^split
57 )cpp");
58 
59  expectAfterNewline(R"cpp(
60 // trailing whitespace is not a split
61 ^
62 )cpp",
63  R"cpp(
64 // trailing whitespace is not a split
65 ^
66 )cpp");
67 
68  expectAfterNewline(R"cpp(
69 // splitting a
70 ^
71 // multiline comment
72 )cpp",
73  R"cpp(
74 // splitting a
75 // ^
76 // multiline comment
77 )cpp");
78 
79  expectAfterNewline(R"cpp(
80 // extra
81  ^ whitespace
82 )cpp",
83  R"cpp(
84 // extra
85 // ^whitespace
86 )cpp");
87 
88  expectAfterNewline(R"cpp(
89 /// triple
90 ^slash
91 )cpp",
92  R"cpp(
93 /// triple
94 /// ^slash
95 )cpp");
96 
97  expectAfterNewline(R"cpp(
98 /// editor continuation
99 //^
100 )cpp",
101  R"cpp(
102 /// editor continuation
103 /// ^
104 )cpp");
105 
106  expectAfterNewline(R"cpp(
107 // break before
108 ^ // slashes
109 )cpp",
110  R"cpp(
111 // break before
112 ^// slashes
113 )cpp");
114 
115 
116  expectAfterNewline(R"cpp(
117 int x; // aligned
118 ^comment
119 )cpp",
120  R"cpp(
121 int x; // aligned
122  // ^comment
123 )cpp");
124 
125  // Fixed bug: the second line of the aligned comment shouldn't be "attached"
126  // to the cursor and outdented.
127  expectAfterNewline(R"cpp(
128 void foo() {
129  if (x)
130  return; // All spelled tokens are accounted for.
131  // that takes two lines
132  ^
133 }
134 )cpp",
135  R"cpp(
136 void foo() {
137  if (x)
138  return; // All spelled tokens are accounted for.
139  // that takes two lines
140  ^
141 }
142 )cpp");
143 }
144 
145 TEST(FormatIncremental, Indentation) {
146  expectAfterNewline(R"cpp(
147 void foo() {
148  if (bar)
149 ^
150 )cpp",
151  R"cpp(
152 void foo() {
153  if (bar)
154  ^
155 )cpp");
156 
157  expectAfterNewline(R"cpp(
158 void foo() {
159  bar(baz(
160 ^
161 )cpp",
162  R"cpp(
163 void foo() {
164  bar(baz(
165  ^
166 )cpp");
167 
168  expectAfterNewline(R"cpp(
169 void foo() {
170 ^}
171 )cpp",
172  R"cpp(
173 void foo() {
174  ^
175 }
176 )cpp");
177 
178  expectAfterNewline(R"cpp(
179 class X {
180 protected:
181 ^
182 )cpp",
183  R"cpp(
184 class X {
185  protected:
186  ^
187 )cpp");
188 
189 // Mismatched brackets (1)
190  expectAfterNewline(R"cpp(
191 void foo() {
192  foo{bar(
193 ^}
194 }
195 )cpp",
196  R"cpp(
197 void foo() {
198  foo {
199  bar(
200  ^}
201 }
202 )cpp");
203 // Mismatched brackets (2)
204  expectAfterNewline(R"cpp(
205 void foo() {
206  foo{bar(
207 ^text}
208 }
209 )cpp",
210  R"cpp(
211 void foo() {
212  foo {
213  bar(
214  ^text}
215 }
216 )cpp");
217 // Matched brackets
218  expectAfterNewline(R"cpp(
219 void foo() {
220  foo{bar(
221 ^)
222 }
223 )cpp",
224  R"cpp(
225 void foo() {
226  foo {
227  bar(
228  ^)
229 }
230 )cpp");
231 }
232 
233 TEST(FormatIncremental, FormatPreviousLine) {
234  expectAfterNewline(R"cpp(
235 void foo() {
236  untouched( );
237 int x=2;
238 ^
239 )cpp",
240  R"cpp(
241 void foo() {
242  untouched( );
243  int x = 2;
244  ^
245 )cpp");
246 
247  expectAfterNewline(R"cpp(
248 int x=untouched( );
249 auto L = []{return;return;};
250 ^
251 )cpp",
252  R"cpp(
253 int x=untouched( );
254 auto L = [] {
255  return;
256  return;
257 };
258 ^
259 )cpp");
260 }
261 
262 TEST(FormatIncremental, Annoyances) {
263  // Don't remove newlines the user typed!
264  expectAfterNewline(R"cpp(
265 int x(){
266 
267 
268 ^
269 }
270 )cpp",
271  R"cpp(
272 int x(){
273 
274 
275  ^
276 }
277 )cpp");
278  // FIXME: we should not remove newlines here, either.
279  expectAfterNewline(R"cpp(
280 class x{
281  public:
282 
283 ^
284 }
285 )cpp",
286  R"cpp(
287 class x{
288  public:
289  ^
290 }
291 )cpp");
292 }
293 
294 TEST(FormatIncremental, FormatBrace) {
295  expectAfter("}", R"cpp(
296 vector<int> x= {
297  1,
298  2,
299  3}^
300 )cpp",
301  R"cpp(
302 vector<int> x = {1, 2, 3}^
303 )cpp");
304 }
305 
306 } // namespace
307 } // namespace clangd
308 } // namespace clang
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:751
E
const Expr * E
Definition: AvoidBindCheck.cpp:88
Format.h
Changes
tooling::Replacements Changes
Definition: Format.cpp:110
Code
std::string Code
Definition: FindTargetTests.cpp:67
TestFS.h
clang::clangd::positionToOffset
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
Definition: SourceCode.cpp:175
Annotations.h
SourceCode.h
clang::clangd::transformCursorPosition
unsigned transformCursorPosition(unsigned Offset, const std::vector< tooling::Replacement > &Replacements)
Determine the new cursor position after applying Replacements.
Definition: Format.cpp:354
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::formatIncremental
std::vector< tooling::Replacement > formatIncremental(llvm::StringRef OriginalCode, unsigned OriginalCursor, llvm::StringRef InsertedText, format::FormatStyle Style)
Applies limited formatting around new InsertedText.
Definition: Format.cpp:248
clang::tidy::cppcoreguidelines::toString
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
Definition: SpecialMemberFunctionsCheck.cpp:55