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 "clang/Format/Format.h"
13#include "clang/Tooling/Core/Replacement.h"
14#include "llvm/Support/Error.h"
15#include "gmock/gmock.h"
16#include "gtest/gtest.h"
17
18namespace clang {
19namespace clangd {
20namespace {
21
22std::string afterTyped(llvm::StringRef CodeWithCursor, llvm::StringRef Typed,
23 clang::format::FormatStyle Style) {
24 Annotations Code(CodeWithCursor);
25 unsigned Cursor = llvm::cantFail(ValOrErr: positionToOffset(Code: Code.code(), P: Code.point()));
26 auto Changes = formatIncremental(Code: Code.code(), Cursor, InsertedText: Typed, Style);
27 tooling::Replacements Merged;
28 for (const auto& R : Changes)
29 if (llvm::Error E = Merged.add(R))
30 ADD_FAILURE() << llvm::toString(E: std::move(E));
31 auto NewCode = tooling::applyAllReplacements(Code: Code.code(), Replaces: Merged);
32 EXPECT_TRUE(bool(NewCode))
33 << "Bad replacements: " << llvm::toString(E: NewCode.takeError());
34 NewCode->insert(pos: transformCursorPosition(Offset: Cursor, Replacements: Changes), s: "^");
35 return *NewCode;
36}
37
38// We can't pass raw strings directly to EXPECT_EQ because of gcc bugs.
39void expectAfterNewline(const char *Before, const char *After,
40 format::FormatStyle Style = format::getGoogleStyle(
41 Language: format::FormatStyle::LK_Cpp)) {
42 EXPECT_EQ(After, afterTyped(Before, "\n", Style)) << Before;
43}
44void expectAfter(const char *Typed, const char *Before, const char *After,
45 format::FormatStyle Style =
46 format::getGoogleStyle(Language: format::FormatStyle::LK_Cpp)) {
47 EXPECT_EQ(After, afterTyped(Before, Typed, Style)) << Before;
48}
49
50TEST(FormatIncremental, SplitComment) {
51 expectAfterNewline(Before: R"cpp(
52// this comment was
53^split
54)cpp",
55 After: R"cpp(
56// this comment was
57// ^split
58)cpp");
59
60 expectAfterNewline(Before: R"cpp(
61// trailing whitespace is not a split
62^
63)cpp",
64 After: R"cpp(
65// trailing whitespace is not a split
66^
67)cpp");
68
69 expectAfterNewline(Before: R"cpp(
70// splitting a
71^
72// multiline comment
73)cpp",
74 After: R"cpp(
75// splitting a
76// ^
77// multiline comment
78)cpp");
79
80 expectAfterNewline(Before: R"cpp(
81// extra
82 ^ whitespace
83)cpp",
84 After: R"cpp(
85// extra
86// ^whitespace
87)cpp");
88
89 expectAfterNewline(Before: R"cpp(
90/// triple
91^slash
92)cpp",
93 After: R"cpp(
94/// triple
95/// ^slash
96)cpp");
97
98 expectAfterNewline(Before: R"cpp(
99/// editor continuation
100//^
101)cpp",
102 After: R"cpp(
103/// editor continuation
104/// ^
105)cpp");
106
107 expectAfterNewline(Before: R"cpp(
108// break before
109^ // slashes
110)cpp",
111 After: R"cpp(
112// break before
113^// slashes
114)cpp");
115
116
117 expectAfterNewline(Before: R"cpp(
118int x; // aligned
119^comment
120)cpp",
121 After: R"cpp(
122int x; // aligned
123 // ^comment
124)cpp");
125
126 // Fixed bug: the second line of the aligned comment shouldn't be "attached"
127 // to the cursor and outdented.
128 expectAfterNewline(Before: R"cpp(
129void foo() {
130 if (x)
131 return; // All spelled tokens are accounted for.
132 // that takes two lines
133 ^
134}
135)cpp",
136 After: R"cpp(
137void foo() {
138 if (x)
139 return; // All spelled tokens are accounted for.
140 // that takes two lines
141 ^
142}
143)cpp");
144
145 // Handle tab character in leading indentation
146 format::FormatStyle TabStyle =
147 format::getGoogleStyle(Language: format::FormatStyle::LK_Cpp);
148 TabStyle.UseTab = format::FormatStyle::UT_Always;
149 TabStyle.TabWidth = 4;
150 TabStyle.IndentWidth = 4;
151 // Do not use raw strings, otherwise '\t' will be interpreted literally.
152 expectAfterNewline(Before: "void foo() {\n\t// this comment was\n^split\n}\n",
153 After: "void foo() {\n\t// this comment was\n\t// ^split\n}\n",
154 Style: TabStyle);
155}
156
157TEST(FormatIncremental, Indentation) {
158 expectAfterNewline(Before: R"cpp(
159void foo() {
160 if (bar)
161^
162)cpp",
163 After: R"cpp(
164void foo() {
165 if (bar)
166 ^
167)cpp");
168
169 expectAfterNewline(Before: R"cpp(
170void foo() {
171 bar(baz(
172^
173)cpp",
174 After: R"cpp(
175void foo() {
176 bar(baz(
177 ^
178)cpp");
179
180 expectAfterNewline(Before: R"cpp(
181void foo() {
182^}
183)cpp",
184 After: R"cpp(
185void foo() {
186 ^
187}
188)cpp");
189
190 expectAfterNewline(Before: R"cpp(
191class X {
192protected:
193^
194)cpp",
195 After: R"cpp(
196class X {
197 protected:
198 ^
199)cpp");
200
201// Mismatched brackets (1)
202 expectAfterNewline(Before: R"cpp(
203void foo() {
204 foo{bar(
205^}
206}
207)cpp",
208 After: R"cpp(
209void foo() {
210 foo {
211 bar(
212 ^}
213}
214)cpp");
215// Mismatched brackets (2)
216 expectAfterNewline(Before: R"cpp(
217void foo() {
218 foo{bar(
219^text}
220}
221)cpp",
222 After: R"cpp(
223void foo() {
224 foo {
225 bar(
226 ^text}
227}
228)cpp");
229// Matched brackets
230 expectAfterNewline(Before: R"cpp(
231void foo() {
232 foo{bar(
233^)
234}
235)cpp",
236 After: R"cpp(
237void foo() {
238 foo {
239 bar(
240 ^)
241}
242)cpp");
243}
244
245TEST(FormatIncremental, FormatPreviousLine) {
246 expectAfterNewline(Before: R"cpp(
247void foo() {
248 untouched( );
249int x=2;
250^
251)cpp",
252 After: R"cpp(
253void foo() {
254 untouched( );
255 int x = 2;
256 ^
257)cpp");
258
259 expectAfterNewline(Before: R"cpp(
260int x=untouched( );
261auto L = []{return;return;};
262^
263)cpp",
264 After: R"cpp(
265int x=untouched( );
266auto L = [] {
267 return;
268 return;
269};
270^
271)cpp");
272}
273
274TEST(FormatIncremental, Annoyances) {
275 // Don't remove newlines the user typed!
276 expectAfterNewline(Before: R"cpp(
277int x(){
278
279
280^
281}
282)cpp",
283 After: R"cpp(
284int x(){
285
286
287 ^
288}
289)cpp");
290 // FIXME: we should not remove newlines here, either.
291 expectAfterNewline(Before: R"cpp(
292class x{
293 public:
294
295^
296}
297)cpp",
298 After: R"cpp(
299class x{
300 public:
301 ^
302}
303)cpp");
304}
305
306TEST(FormatIncremental, FormatBrace) {
307 expectAfter(Typed: "}", Before: R"cpp(
308vector<int> x= {
309 1,
310 2,
311 3}^
312)cpp",
313 After: R"cpp(
314vector<int> x = {1, 2, 3}^
315)cpp");
316}
317
318} // namespace
319} // namespace clangd
320} // namespace clang
321

source code of clang-tools-extra/clangd/unittests/FormatTests.cpp