1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "googletest.h"
27
28 #include <clangformat/clangformatbaseindenter.h>
29 #include <utils/fileutils.h>
30
31 #include <QTextDocument>
32
33 namespace TextEditor {
34 class TabSettings
35 {};
36 } // namespace TextEditor
37
38 namespace {
39
40 class ClangFormatIndenter : public ClangFormat::ClangFormatBaseIndenter
41 {
42 public:
ClangFormatIndenter(QTextDocument * doc)43 ClangFormatIndenter(QTextDocument *doc)
44 : ClangFormat::ClangFormatBaseIndenter(doc)
45 {}
46
tabSettings() const47 Utils::optional<TextEditor::TabSettings> tabSettings() const override
48 {
49 return Utils::optional<TextEditor::TabSettings>();
50 }
51 };
52
53 class ClangFormatExtendedIndenter : public ClangFormatIndenter
54 {
55 public:
ClangFormatExtendedIndenter(QTextDocument * doc)56 ClangFormatExtendedIndenter(QTextDocument *doc)
57 : ClangFormatIndenter(doc)
58 {}
59
formatWhileTyping() const60 bool formatWhileTyping() const override { return true; }
61 };
62
63 class ClangFormat : public ::testing::Test
64 {
65 protected:
SetUp()66 void SetUp() final
67 {
68 indenter.setFileName(Utils::FilePath::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
69 extendedIndenter.setFileName(
70 Utils::FilePath::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
71 }
72
insertLines(const std::vector<QString> & lines)73 void insertLines(const std::vector<QString> &lines)
74 {
75 doc.clear();
76 cursor.setPosition(0);
77 for (size_t lineNumber = 1; lineNumber <= lines.size(); ++lineNumber) {
78 if (lineNumber > 1)
79 cursor.insertBlock();
80
81 cursor.insertText(lines[lineNumber - 1]);
82 }
83 cursor.setPosition(0);
84 cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
85 }
86
documentLines()87 std::vector<QString> documentLines()
88 {
89 std::vector<QString> result;
90 const int lines = doc.blockCount();
91 result.reserve(static_cast<size_t>(lines));
92 for (int line = 0; line < lines; ++line)
93 result.push_back(doc.findBlockByNumber(line).text());
94
95 return result;
96 }
97
98 QTextDocument doc;
99 ClangFormatIndenter indenter{&doc};
100 ClangFormatExtendedIndenter extendedIndenter{&doc};
101 QTextCursor cursor{&doc};
102 };
103
104 // clang-format off
TEST_F(ClangFormat,IndentBasicFile)105 TEST_F(ClangFormat, IndentBasicFile)
106 {
107 insertLines({"int main()",
108 "{",
109 "int a;",
110 "}"});
111
112 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
113
114 ASSERT_THAT(documentLines(), ElementsAre("int main()",
115 "{",
116 " int a;",
117 "}"));
118 }
119
TEST_F(ClangFormat,IndentEmptyLine)120 TEST_F(ClangFormat, IndentEmptyLine)
121 {
122 insertLines({"int main()",
123 "{",
124 "",
125 "}"});
126
127 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
128
129 ASSERT_THAT(documentLines(), ElementsAre("int main()",
130 "{",
131 " ",
132 "}"));
133 }
134
TEST_F(ClangFormat,IndentLambda)135 TEST_F(ClangFormat, IndentLambda)
136 {
137 insertLines({"int b = foo([](){",
138 "",
139 "});"});
140
141 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
142
143 ASSERT_THAT(documentLines(), ElementsAre("int b = foo([](){",
144 " ",
145 "});"));
146 }
147
TEST_F(ClangFormat,IndentNestedIfElse)148 TEST_F(ClangFormat, IndentNestedIfElse)
149 {
150 insertLines({"if (a)",
151 "if (b)",
152 "foo();",
153 "else",
154 "bar();",
155 "else",
156 "baz();"});
157
158 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
159
160 ASSERT_THAT(documentLines(),
161 ElementsAre("if (a)",
162 " if (b)",
163 " foo();",
164 " else",
165 " bar();",
166 "else",
167 " baz();"));
168 }
169
TEST_F(ClangFormat,IndentInitializerListInArguments)170 TEST_F(ClangFormat, IndentInitializerListInArguments)
171 {
172 insertLines({"foo(arg1,",
173 "args,",
174 "{1, 2});"});
175
176 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
177
178 ASSERT_THAT(documentLines(), ElementsAre("foo(arg1,",
179 " args,",
180 " {1, 2});"));
181 }
182
TEST_F(ClangFormat,IndentLambdaWithReturnType)183 TEST_F(ClangFormat, IndentLambdaWithReturnType)
184 {
185 insertLines({"{",
186 "auto lambda = []() -> bool {",
187 "",
188 "};",
189 "}"});
190
191 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
192
193 ASSERT_THAT(documentLines(),
194 ElementsAre("{",
195 " auto lambda = []() -> bool {",
196 " ",
197 " };",
198 "}"));
199 }
200
TEST_F(ClangFormat,ClangFormatIndentFunctionArgumentLambdaWithNextLineScope)201 TEST_F(ClangFormat, ClangFormatIndentFunctionArgumentLambdaWithNextLineScope)
202 {
203 insertLines({"foo([]()",
204 "{",
205 "",
206 "});"});
207
208 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
209
210 ASSERT_THAT(documentLines(),
211 ElementsAre("foo([]()",
212 " {",
213 " ",
214 " });"));
215 }
216
TEST_F(ClangFormat,IndentScopeAsFunctionArgument)217 TEST_F(ClangFormat, IndentScopeAsFunctionArgument)
218 {
219 insertLines({"foo(",
220 "{",
221 "",
222 "});"});
223
224 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
225
226 ASSERT_THAT(documentLines(),
227 ElementsAre("foo(",
228 " {",
229 " ",
230 " });"));
231 }
232
TEST_F(ClangFormat,IndentInsideStructuredBinding)233 TEST_F(ClangFormat, IndentInsideStructuredBinding)
234 {
235 insertLines({"auto [a,",
236 "b] = c;"});
237
238 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
239
240 ASSERT_THAT(documentLines(), ElementsAre("auto [a,",
241 " b] = c;"));
242 }
243
TEST_F(ClangFormat,IndentMacrosWithoutSemicolon)244 TEST_F(ClangFormat, IndentMacrosWithoutSemicolon)
245 {
246 insertLines({"void test()",
247 "{",
248 "ASSERT(1);",
249 "ASSERT(2)",
250 "ASSERT(3)",
251 "ASSERT(4);",
252 "ASSERT(5)",
253 "}"});
254
255 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
256
257 ASSERT_THAT(documentLines(), ElementsAre("void test()",
258 "{",
259 " ASSERT(1);",
260 " ASSERT(2)",
261 " ASSERT(3)",
262 " ASSERT(4);",
263 " ASSERT(5)",
264 "}"));
265 }
266
TEST_F(ClangFormat,IndentAfterSquareBracesInsideBraceInitialization)267 TEST_F(ClangFormat, IndentAfterSquareBracesInsideBraceInitialization)
268 {
269 insertLines({"int foo() {",
270 "char a = char{b[0]};",
271 "int c;",
272 "}"});
273
274 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
275
276 ASSERT_THAT(documentLines(), ElementsAre("int foo() {",
277 " char a = char{b[0]};",
278 " int c;",
279 "}"));
280 }
281
TEST_F(ClangFormat,IndentStringLiteralContinuation)282 TEST_F(ClangFormat, IndentStringLiteralContinuation)
283 {
284 insertLines({"foo(bar, \"foo\"",
285 "\"bar\");"});
286
287 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
288
289 ASSERT_THAT(documentLines(), ElementsAre("foo(bar, \"foo\"",
290 " \"bar\");"));
291 }
292
TEST_F(ClangFormat,IndentTemplateparameters)293 TEST_F(ClangFormat, IndentTemplateparameters)
294 {
295 insertLines({"using Alias = Template<A,",
296 "B,",
297 "C>"});
298
299 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
300
301 ASSERT_THAT(documentLines(), ElementsAre("using Alias = Template<A,",
302 " B,",
303 " C>"));
304 }
305
TEST_F(ClangFormat,NoExtraIndentAfterStatementInsideSquareBraces)306 TEST_F(ClangFormat, NoExtraIndentAfterStatementInsideSquareBraces)
307 {
308 insertLines({"{",
309 " x[y=z];",
310 " int a;",
311 "}"});
312
313 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
314
315 ASSERT_THAT(documentLines(), ElementsAre("{",
316 " x[y=z];",
317 " int a;",
318 "}"));
319 }
320
TEST_F(ClangFormat,NoExtraIndentAfterBraceInitialization)321 TEST_F(ClangFormat, NoExtraIndentAfterBraceInitialization)
322 {
323 insertLines({"int j{i?5:10};",
324 "return 0;"});
325
326 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
327
328 ASSERT_THAT(documentLines(), ElementsAre("int j{i?5:10};",
329 "return 0;"));
330 }
331
TEST_F(ClangFormat,IndentMultipleEmptyLines)332 TEST_F(ClangFormat, IndentMultipleEmptyLines)
333 {
334 insertLines({"{",
335 "",
336 "",
337 "",
338 "}"});
339
340 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
341
342 ASSERT_THAT(documentLines(), ElementsAre("{",
343 " ",
344 " ",
345 " ",
346 "}"));
347 }
348
TEST_F(ClangFormat,IndentEmptyLineAndKeepPreviousEmptyLines)349 TEST_F(ClangFormat, IndentEmptyLineAndKeepPreviousEmptyLines)
350 {
351 insertLines({"{",
352 " ",
353 " ",
354 "",
355 "}"});
356
357 indenter.indentBlock(doc.findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
358
359 ASSERT_THAT(documentLines(), ElementsAre("{",
360 " ",
361 " ",
362 " ",
363 "}"));
364 }
365
TEST_F(ClangFormat,IndentOnElectricCharacterButNotRemoveEmptyLinesBefore)366 TEST_F(ClangFormat, IndentOnElectricCharacterButNotRemoveEmptyLinesBefore)
367 {
368 insertLines({"{",
369 " ",
370 " ",
371 "if ()",
372 "}"});
373
374 indenter.indentBlock(doc.findBlockByNumber(3), '(', TextEditor::TabSettings());
375
376 ASSERT_THAT(documentLines(), ElementsAre("{",
377 " ",
378 " ",
379 " if ()",
380 "}"));
381 }
382
TEST_F(ClangFormat,IndentAfterExtraSpaceInpreviousLine)383 TEST_F(ClangFormat, IndentAfterExtraSpaceInpreviousLine)
384 {
385 insertLines({"if (a ",
386 "&& b)"});
387
388 indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
389
390 ASSERT_THAT(documentLines(), ElementsAre("if (a",
391 " && b)"));
392 }
393
TEST_F(ClangFormat,IndentEmptyLineInsideParantheses)394 TEST_F(ClangFormat, IndentEmptyLineInsideParantheses)
395 {
396 insertLines({"if (a ",
397 "",
398 " && b)"});
399
400 indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
401
402 ASSERT_THAT(documentLines(), ElementsAre("if (a",
403 " ",
404 " && b)"));
405 }
406
TEST_F(ClangFormat,IndentInsideIf)407 TEST_F(ClangFormat, IndentInsideIf)
408 {
409 insertLines({"if (a && b",
410 ")"});
411
412 indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
413
414 ASSERT_THAT(documentLines(), ElementsAre("if (a && b",
415 " )"));
416 }
417
TEST_F(ClangFormat,IndentInsideIf2)418 TEST_F(ClangFormat, IndentInsideIf2)
419 {
420 insertLines({"if (a && b &&",
421 ")"});
422
423 indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
424
425 ASSERT_THAT(documentLines(), ElementsAre("if (a && b &&",
426 " )"));
427 }
428
TEST_F(ClangFormat,IndentInsideIf3)429 TEST_F(ClangFormat, IndentInsideIf3)
430 {
431 insertLines({"if (a || b",
432 ")"});
433
434 indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
435
436 ASSERT_THAT(documentLines(), ElementsAre("if (a || b",
437 " )"));
438 }
439
TEST_F(ClangFormat,EmptyLineInInitializerList)440 TEST_F(ClangFormat, EmptyLineInInitializerList)
441 {
442 insertLines({"Bar foo{a,",
443 "",
444 "};"});
445
446 indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
447
448 ASSERT_THAT(documentLines(), ElementsAre("Bar foo{a,",
449 " ",
450 "};"));
451 }
452
TEST_F(ClangFormat,IndentClosingBraceAfterComma)453 TEST_F(ClangFormat, IndentClosingBraceAfterComma)
454 {
455 insertLines({"Bar foo{a,",
456 "}"});
457
458 indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
459
460 ASSERT_THAT(documentLines(), ElementsAre("Bar foo{a,",
461 " }"));
462 }
463
TEST_F(ClangFormat,DoNotIndentClosingBraceAfterSemicolon)464 TEST_F(ClangFormat, DoNotIndentClosingBraceAfterSemicolon)
465 {
466 insertLines({"{",
467 " a;"
468 "}"});
469
470 indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
471
472 ASSERT_THAT(documentLines(), ElementsAre("{",
473 " a;"
474 "}"));
475 }
476
TEST_F(ClangFormat,IndentAfterIf)477 TEST_F(ClangFormat, IndentAfterIf)
478 {
479 insertLines({"if (a)",
480 ""});
481
482 indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
483
484 ASSERT_THAT(documentLines(), ElementsAre("if (a)",
485 " "));
486 }
487
TEST_F(ClangFormat,IndentAfterElse)488 TEST_F(ClangFormat, IndentAfterElse)
489 {
490 insertLines({"if (a)",
491 " foo();",
492 "else",
493 ""});
494 indenter.indentBlock(doc.findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
495
496 ASSERT_THAT(documentLines(), ElementsAre("if (a)",
497 " foo();",
498 "else",
499 " "));
500 }
501
TEST_F(ClangFormat,SameIndentAfterSecondNewLineAfterIf)502 TEST_F(ClangFormat, SameIndentAfterSecondNewLineAfterIf)
503 {
504 insertLines({"if (a)",
505 " ",
506 ""});
507
508 indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
509
510 ASSERT_THAT(documentLines(), ElementsAre("if (a)",
511 " ",
512 " "));
513 }
514
TEST_F(ClangFormat,IndentAfterNewLineInsideIfWithFunctionCall)515 TEST_F(ClangFormat, IndentAfterNewLineInsideIfWithFunctionCall)
516 {
517 insertLines({"if (foo()",
518 ")"});
519
520 indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
521
522 ASSERT_THAT(documentLines(), ElementsAre("if (foo()",
523 " )"));
524 }
525
TEST_F(ClangFormat,SameIndentAfterSecondNewLineInsideIfWithFunctionCall)526 TEST_F(ClangFormat, SameIndentAfterSecondNewLineInsideIfWithFunctionCall)
527 {
528 insertLines({"if (foo()",
529 " ",
530 ")"});
531
532 indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
533
534 ASSERT_THAT(documentLines(), ElementsAre("if (foo()",
535 " ",
536 " )"));
537 }
538
TEST_F(ClangFormat,SameIndentAfterSecondNonEmptyNewLineInsideIfWithFunctionCall)539 TEST_F(ClangFormat, SameIndentAfterSecondNonEmptyNewLineInsideIfWithFunctionCall)
540 {
541 insertLines({"if (foo()",
542 " ",
543 "bar)"});
544
545 indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
546
547 ASSERT_THAT(documentLines(), ElementsAre("if (foo()",
548 " ",
549 " bar)"));
550 }
551
TEST_F(ClangFormat,SameIndentsOnNewLinesAfterComments)552 TEST_F(ClangFormat, SameIndentsOnNewLinesAfterComments)
553 {
554 insertLines({"namespace {} //comment",
555 "",
556 ""});
557
558 indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
559
560 ASSERT_THAT(documentLines(), ElementsAre("namespace {} //comment",
561 "",
562 ""));
563 }
564
TEST_F(ClangFormat,IndentAfterEmptyLineAfterAngledIncludeDirective)565 TEST_F(ClangFormat, IndentAfterEmptyLineAfterAngledIncludeDirective)
566 {
567 insertLines({"#include <string>",
568 "",
569 "using namespace std;"});
570
571 indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
572
573 ASSERT_THAT(documentLines(), ElementsAre("#include <string>",
574 "",
575 "using namespace std;"));
576 }
577
TEST_F(ClangFormat,IndentAfterEmptyLineAfterQuotedIncludeDirective)578 TEST_F(ClangFormat, IndentAfterEmptyLineAfterQuotedIncludeDirective)
579 {
580 insertLines({"#include \"foo.h\"",
581 "",
582 "using namespace std;"});
583
584 indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
585
586 ASSERT_THAT(documentLines(), ElementsAre("#include \"foo.h\"",
587 "",
588 "using namespace std;"));
589 }
590
TEST_F(ClangFormat,IndentAfterLineComment)591 TEST_F(ClangFormat, IndentAfterLineComment)
592 {
593 insertLines({"int foo()",
594 "{",
595 " // Comment",
596 " ",
597 " if (",
598 "}"});
599
600 indenter.indentBlock(doc.findBlockByNumber(4), '(', TextEditor::TabSettings());
601
602 ASSERT_THAT(documentLines(), ElementsAre("int foo()",
603 "{",
604 " // Comment",
605 " ",
606 " if (",
607 "}"));
608 }
609
TEST_F(ClangFormat,IndentAfterBlockComment)610 TEST_F(ClangFormat, IndentAfterBlockComment)
611 {
612 insertLines({"int foo()",
613 "{",
614 " bar(); /* Comment */",
615 " ",
616 " if (",
617 "}"});
618
619 indenter.indentBlock(doc.findBlockByNumber(4), '(', TextEditor::TabSettings());
620
621 ASSERT_THAT(documentLines(), ElementsAre("int foo()",
622 "{",
623 " bar(); /* Comment */",
624 " ",
625 " if (",
626 "}"));
627 }
628
TEST_F(ClangFormat,IndentAfterIfdef)629 TEST_F(ClangFormat, IndentAfterIfdef)
630 {
631 insertLines({"int foo()",
632 "{",
633 "#ifdef FOO",
634 "#endif",
635 " ",
636 " if (",
637 "}"});
638
639 indenter.indentBlock(doc.findBlockByNumber(5), '(', TextEditor::TabSettings());
640
641 ASSERT_THAT(documentLines(), ElementsAre("int foo()",
642 "{",
643 "#ifdef FOO",
644 "#endif",
645 " ",
646 " if (",
647 "}"));
648 }
649
TEST_F(ClangFormat,IndentAfterEmptyLineInTheFileBeginning)650 TEST_F(ClangFormat, IndentAfterEmptyLineInTheFileBeginning)
651 {
652 insertLines({"",
653 "void foo()"});
654
655 indenter.indentBlock(doc.findBlockByNumber(1), ')', TextEditor::TabSettings());
656
657 ASSERT_THAT(documentLines(), ElementsAre("",
658 "void foo()"));
659 }
660
TEST_F(ClangFormat,IndentFunctionBodyButNotFormatBeforeIt)661 TEST_F(ClangFormat, IndentFunctionBodyButNotFormatBeforeIt)
662 {
663 insertLines({"int foo(int a, int b,",
664 " int c, int d",
665 " ) {",
666 "",
667 "}"});
668
669 extendedIndenter.indentBlock(doc.findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
670
671 ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b,",
672 " int c, int d",
673 " ) {",
674 " ",
675 "}"));
676 }
677
TEST_F(ClangFormat,IndentAfterFunctionBodyAndNotFormatBefore)678 TEST_F(ClangFormat, IndentAfterFunctionBodyAndNotFormatBefore)
679 {
680 insertLines({"int foo(int a, int b, int c, int d)",
681 "{",
682 " ",
683 "}"});
684
685 extendedIndenter.indentBlock(doc.findBlockByNumber(3),
686 QChar::Null,
687 TextEditor::TabSettings(),
688 doc.characterCount() - 3);
689
690 ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b, int c, int d)",
691 "{",
692 " ",
693 "}"));
694 }
695
TEST_F(ClangFormat,ReformatToEmptyFunction)696 TEST_F(ClangFormat, ReformatToEmptyFunction)
697 {
698 insertLines({"int foo(int a, int b, int c, int d)",
699 "{",
700 " ",
701 "}"});
702
703 extendedIndenter.indentBlock(doc.findBlockByNumber(3), '}', TextEditor::TabSettings());
704
705 ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b, int c, int d) {}"));
706 }
707
TEST_F(ClangFormat,ReformatToNonEmptyFunction)708 TEST_F(ClangFormat, ReformatToNonEmptyFunction)
709 {
710 insertLines({"int foo(int a, int b) {",
711 "",
712 "}"});
713
714 extendedIndenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
715
716 ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b) {",
717 " ",
718 "}"));
719 }
720
TEST_F(ClangFormat,IndentClosingScopeAndFormatBeforeIt)721 TEST_F(ClangFormat, IndentClosingScopeAndFormatBeforeIt)
722 {
723 insertLines({"if(a && b",
724 " &&c && d",
725 " ) {",
726 "",
727 "}"});
728
729 extendedIndenter.indentBlock(doc.findBlockByNumber(4), '}', TextEditor::TabSettings());
730
731 ASSERT_THAT(documentLines(), ElementsAre("if (a && b && c && d) {",
732 "}"));
733 }
734
TEST_F(ClangFormat,DoNotFormatAfterTheFirstColon)735 TEST_F(ClangFormat, DoNotFormatAfterTheFirstColon)
736 {
737 insertLines({"{",
738 " Qt:",
739 "}"});
740
741 extendedIndenter.indentBlock(doc.findBlockByNumber(1), ':', TextEditor::TabSettings(), 9);
742
743 ASSERT_THAT(documentLines(), ElementsAre("{",
744 " Qt:",
745 "}"));
746 }
747
TEST_F(ClangFormat,OnlyIndentIncompleteStatementOnElectricalCharacter)748 TEST_F(ClangFormat, OnlyIndentIncompleteStatementOnElectricalCharacter)
749 {
750 insertLines({"{bar();",
751 "foo()",
752 "}"});
753
754 extendedIndenter.indentBlock(doc.findBlockByNumber(1), '(', TextEditor::TabSettings(), 12);
755
756 ASSERT_THAT(documentLines(), ElementsAre("{bar();",
757 " foo()",
758 "}"));
759 }
760
TEST_F(ClangFormat,IndentAndFormatCompleteStatementOnSemicolon)761 TEST_F(ClangFormat, IndentAndFormatCompleteStatementOnSemicolon)
762 {
763 insertLines({"{bar();",
764 "foo();",
765 "}"});
766
767 extendedIndenter.indentBlock(doc.findBlockByNumber(1), ';', TextEditor::TabSettings(), 14);
768
769 ASSERT_THAT(documentLines(), ElementsAre("{",
770 " bar();",
771 " foo();",
772 "}"));
773 }
774
TEST_F(ClangFormat,IndentAndFormatCompleteStatementOnClosingScope)775 TEST_F(ClangFormat, IndentAndFormatCompleteStatementOnClosingScope)
776 {
777 insertLines({"{bar();",
778 "foo();",
779 "}"});
780
781 extendedIndenter.indentBlock(doc.findBlockByNumber(1), '}', TextEditor::TabSettings(), 16);
782
783 ASSERT_THAT(documentLines(), ElementsAre("{",
784 " bar();",
785 " foo();",
786 "}"));
787 }
788
TEST_F(ClangFormat,OnlyIndentClosingParenthesis)789 TEST_F(ClangFormat, OnlyIndentClosingParenthesis)
790 {
791 insertLines({"foo(a,",
792 " ",
793 ")"});
794
795 extendedIndenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
796
797 ASSERT_THAT(documentLines(), ElementsAre("foo(a,",
798 " ",
799 " )"));
800 }
801
TEST_F(ClangFormat,EquallyIndentInsideParenthesis)802 TEST_F(ClangFormat, EquallyIndentInsideParenthesis)
803 {
804 insertLines({"if (a",
805 ")"});
806 extendedIndenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
807 auto linesAfterFirstLineBreak = documentLines();
808 insertLines({"if (a",
809 " ",
810 ")"});
811 extendedIndenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
812
813 ASSERT_THAT(linesAfterFirstLineBreak, ElementsAre("if (a",
814 " )"));
815 ASSERT_THAT(documentLines(), ElementsAre("if (a",
816 " ",
817 " )"));
818 }
819
TEST_F(ClangFormat,FormatBasicFile)820 TEST_F(ClangFormat, FormatBasicFile)
821 {
822 insertLines({"int main()",
823 "{",
824 "int a;",
825 "}"});
826
827 indenter.format({{1, 4}});
828
829 ASSERT_THAT(documentLines(), ElementsAre("int main()",
830 "{",
831 " int a;",
832 "}"));
833 }
834
TEST_F(ClangFormat,FormatEmptyLine)835 TEST_F(ClangFormat, FormatEmptyLine)
836 {
837 insertLines({"int main()",
838 "{",
839 "",
840 "}"});
841
842 indenter.format({{1, 4}});
843
844 ASSERT_THAT(documentLines(), ElementsAre("int main() {}"));
845 }
846
TEST_F(ClangFormat,FormatLambda)847 TEST_F(ClangFormat, FormatLambda)
848 {
849 insertLines({"int b = foo([](){",
850 "",
851 "});"});
852
853 indenter.format({{1, 3}});
854
855 ASSERT_THAT(documentLines(), ElementsAre("int b = foo([]() {",
856 "",
857 "});"));
858 }
859
TEST_F(ClangFormat,FormatInitializerListInArguments)860 TEST_F(ClangFormat, FormatInitializerListInArguments)
861 {
862 insertLines({"foo(arg1,",
863 "args,",
864 "{1, 2});"});
865
866 indenter.format({{1, 3}});
867
868 ASSERT_THAT(documentLines(), ElementsAre("foo(arg1, args, {1, 2});"));
869 }
870
TEST_F(ClangFormat,FormatFunctionArgumentLambdaWithScope)871 TEST_F(ClangFormat, FormatFunctionArgumentLambdaWithScope)
872 {
873 insertLines({"foo([]()",
874 "{",
875 "",
876 "});"});
877
878 indenter.format({{1, 4}});
879
880 ASSERT_THAT(documentLines(),
881 ElementsAre("foo([]() {",
882 "",
883 "});"));
884 }
885
TEST_F(ClangFormat,FormatScopeAsFunctionArgument)886 TEST_F(ClangFormat, FormatScopeAsFunctionArgument)
887 {
888 insertLines({"foo(",
889 "{",
890 "",
891 "});"});
892
893 indenter.format({{1, 4}});
894
895 ASSERT_THAT(documentLines(),
896 ElementsAre("foo({",
897 "",
898 "});"));
899 }
900
TEST_F(ClangFormat,FormatStructuredBinding)901 TEST_F(ClangFormat, FormatStructuredBinding)
902 {
903 insertLines({"auto [a,",
904 "b] = c;"});
905
906 indenter.format({{1, 2}});
907
908 ASSERT_THAT(documentLines(), ElementsAre("auto [a, b] = c;"));
909 }
910
TEST_F(ClangFormat,FormatStringLiteralContinuation)911 TEST_F(ClangFormat, FormatStringLiteralContinuation)
912 {
913 insertLines({"foo(bar, \"foo\"",
914 "\"bar\");"});
915
916 indenter.format({{1, 2}});
917
918 ASSERT_THAT(documentLines(), ElementsAre("foo(bar,",
919 " \"foo\"",
920 " \"bar\");"));
921 }
922
TEST_F(ClangFormat,FormatTemplateparameters)923 TEST_F(ClangFormat, FormatTemplateparameters)
924 {
925 insertLines({"using Alias = Template<A,",
926 "B,",
927 "C>"});
928
929 indenter.format({{1, 3}});
930
931 ASSERT_THAT(documentLines(), ElementsAre("using Alias = Template<A, B, C>"));
932 }
933
TEST_F(ClangFormat,SortIncludes)934 TEST_F(ClangFormat, SortIncludes)
935 {
936 insertLines({"#include \"b.h\"",
937 "#include \"a.h\"",
938 "",
939 "#include <bb.h>",
940 "#include <aa.h>"});
941
942 indenter.format({{1, 5}});
943
944 ASSERT_THAT(documentLines(), ElementsAre("#include \"a.h\"",
945 "#include \"b.h\"",
946 "",
947 "#include <aa.h>",
948 "#include <bb.h>"));
949 }
950
TEST_F(ClangFormat,ChainedMemberFunctionCalls)951 TEST_F(ClangFormat, ChainedMemberFunctionCalls)
952 {
953 insertLines({"S().func().func()",
954 ".func();"});
955 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
956 ASSERT_THAT(documentLines(), ElementsAre("S().func().func()",
957 " .func();"));
958 }
959
TEST_F(ClangFormat,CommentBlock)960 TEST_F(ClangFormat, CommentBlock)
961 {
962 insertLines({"/****************************************************************************",
963 "**",
964 "** Copyright (C) 2021 The Qt Company Ltd.",
965 "** Contact: https://www.qt.io/licensing/",
966 "**",
967 "** This file is part of Qt Creator.",
968 "**",
969 "****************************************************************************/"});
970 indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
971 ASSERT_THAT(documentLines(), ElementsAre(
972 "/****************************************************************************",
973 "**",
974 "** Copyright (C) 2021 The Qt Company Ltd.",
975 "** Contact: https://www.qt.io/licensing/",
976 "**",
977 "** This file is part of Qt Creator.",
978 "**",
979 "****************************************************************************/"));
980 }
981
982 // clang-format on
983
984 } // namespace
985