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