forked from qt-creator/qt-creator
		
	Otherwise, we could introduce unwanted syntactical constructs, for instance if the previous character is an asterisk. Fixes: QTCREATORBUG-25966 Change-Id: Ic0b535861bc1cb4f5f93d06bb11d0f3c7c583893 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
		
			
				
	
	
		
			985 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			985 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /****************************************************************************
 | |
| **
 | |
| ** Copyright (C) 2019 The Qt Company Ltd.
 | |
| ** Contact: https://www.qt.io/licensing/
 | |
| **
 | |
| ** This file is part of Qt Creator.
 | |
| **
 | |
| ** Commercial License Usage
 | |
| ** Licensees holding valid commercial Qt licenses may use this file in
 | |
| ** accordance with the commercial license agreement provided with the
 | |
| ** Software or, alternatively, in accordance with the terms contained in
 | |
| ** a written agreement between you and The Qt Company. For licensing terms
 | |
| ** and conditions see https://www.qt.io/terms-conditions. For further
 | |
| ** information use the contact form at https://www.qt.io/contact-us.
 | |
| **
 | |
| ** GNU General Public License Usage
 | |
| ** Alternatively, this file may be used under the terms of the GNU
 | |
| ** General Public License version 3 as published by the Free Software
 | |
| ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
 | |
| ** included in the packaging of this file. Please review the following
 | |
| ** information to ensure the GNU General Public License requirements will
 | |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
 | |
| **
 | |
| ****************************************************************************/
 | |
| 
 | |
| #include "googletest.h"
 | |
| 
 | |
| #include <clangformat/clangformatbaseindenter.h>
 | |
| #include <utils/fileutils.h>
 | |
| 
 | |
| #include <QTextDocument>
 | |
| 
 | |
| namespace TextEditor {
 | |
| class TabSettings
 | |
| {};
 | |
| } // namespace TextEditor
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| class ClangFormatIndenter : public ClangFormat::ClangFormatBaseIndenter
 | |
| {
 | |
| public:
 | |
|     ClangFormatIndenter(QTextDocument *doc)
 | |
|         : ClangFormat::ClangFormatBaseIndenter(doc)
 | |
|     {}
 | |
| 
 | |
|     Utils::optional<TextEditor::TabSettings> tabSettings() const override
 | |
|     {
 | |
|         return Utils::optional<TextEditor::TabSettings>();
 | |
|     }
 | |
| };
 | |
| 
 | |
| class ClangFormatExtendedIndenter : public ClangFormatIndenter
 | |
| {
 | |
| public:
 | |
|     ClangFormatExtendedIndenter(QTextDocument *doc)
 | |
|         : ClangFormatIndenter(doc)
 | |
|     {}
 | |
| 
 | |
|     bool formatWhileTyping() const override { return true; }
 | |
| };
 | |
| 
 | |
| class ClangFormat : public ::testing::Test
 | |
| {
 | |
| protected:
 | |
|     void SetUp() final
 | |
|     {
 | |
|         indenter.setFileName(Utils::FilePath::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
 | |
|         extendedIndenter.setFileName(
 | |
|             Utils::FilePath::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
 | |
|     }
 | |
| 
 | |
|     void insertLines(const std::vector<QString> &lines)
 | |
|     {
 | |
|         doc.clear();
 | |
|         cursor.setPosition(0);
 | |
|         for (size_t lineNumber = 1; lineNumber <= lines.size(); ++lineNumber) {
 | |
|             if (lineNumber > 1)
 | |
|                 cursor.insertBlock();
 | |
| 
 | |
|             cursor.insertText(lines[lineNumber - 1]);
 | |
|         }
 | |
|         cursor.setPosition(0);
 | |
|         cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
 | |
|     }
 | |
| 
 | |
|     std::vector<QString> documentLines()
 | |
|     {
 | |
|         std::vector<QString> result;
 | |
|         const int lines = doc.blockCount();
 | |
|         result.reserve(static_cast<size_t>(lines));
 | |
|         for (int line = 0; line < lines; ++line)
 | |
|             result.push_back(doc.findBlockByNumber(line).text());
 | |
| 
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     QTextDocument doc;
 | |
|     ClangFormatIndenter indenter{&doc};
 | |
|     ClangFormatExtendedIndenter extendedIndenter{&doc};
 | |
|     QTextCursor cursor{&doc};
 | |
| };
 | |
| 
 | |
| // clang-format off
 | |
| TEST_F(ClangFormat, IndentBasicFile)
 | |
| {
 | |
|     insertLines({"int main()",
 | |
|                  "{",
 | |
|                  "int a;",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int main()",
 | |
|                                              "{",
 | |
|                                              "    int a;",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentEmptyLine)
 | |
| {
 | |
|     insertLines({"int main()",
 | |
|                  "{",
 | |
|                  "",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int main()",
 | |
|                                              "{",
 | |
|                                              "    ",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentLambda)
 | |
| {
 | |
|     insertLines({"int b = foo([](){",
 | |
|                  "",
 | |
|                  "});"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int b = foo([](){",
 | |
|                                              "    ",
 | |
|                                              "});"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentNestedIfElse)
 | |
| {
 | |
|     insertLines({"if (a)",
 | |
|                  "if (b)",
 | |
|                  "foo();",
 | |
|                  "else",
 | |
|                  "bar();",
 | |
|                  "else",
 | |
|                  "baz();"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(),
 | |
|                 ElementsAre("if (a)",
 | |
|                             "    if (b)",
 | |
|                             "        foo();",
 | |
|                             "    else",
 | |
|                             "        bar();",
 | |
|                             "else",
 | |
|                             "    baz();"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentInitializerListInArguments)
 | |
| {
 | |
|     insertLines({"foo(arg1,",
 | |
|                  "args,",
 | |
|                  "{1, 2});"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("foo(arg1,",
 | |
|                                              "    args,",
 | |
|                                              "    {1, 2});"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentLambdaWithReturnType)
 | |
| {
 | |
|     insertLines({"{",
 | |
|                  "auto lambda = []() -> bool {",
 | |
|                  "",
 | |
|                  "};",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(),
 | |
|                 ElementsAre("{",
 | |
|                             "    auto lambda = []() -> bool {",
 | |
|                             "        ",
 | |
|                             "    };",
 | |
|                             "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, ClangFormatIndentFunctionArgumentLambdaWithNextLineScope)
 | |
| {
 | |
|     insertLines({"foo([]()",
 | |
|                  "{",
 | |
|                  "",
 | |
|                  "});"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(),
 | |
|                 ElementsAre("foo([]()",
 | |
|                             "    {",
 | |
|                             "        ",
 | |
|                             "    });"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentScopeAsFunctionArgument)
 | |
| {
 | |
|     insertLines({"foo(",
 | |
|                  "{",
 | |
|                  "",
 | |
|                  "});"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(),
 | |
|                 ElementsAre("foo(",
 | |
|                             "    {",
 | |
|                             "        ",
 | |
|                             "    });"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentInsideStructuredBinding)
 | |
| {
 | |
|     insertLines({"auto [a,",
 | |
|                  "b] = c;"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("auto [a,",
 | |
|                                              "      b] = c;"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentMacrosWithoutSemicolon)
 | |
| {
 | |
|     insertLines({"void test()",
 | |
|                  "{",
 | |
|                  "ASSERT(1);",
 | |
|                  "ASSERT(2)",
 | |
|                  "ASSERT(3)",
 | |
|                  "ASSERT(4);",
 | |
|                  "ASSERT(5)",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("void test()",
 | |
|                                              "{",
 | |
|                                              "    ASSERT(1);",
 | |
|                                              "    ASSERT(2)",
 | |
|                                              "    ASSERT(3)",
 | |
|                                              "    ASSERT(4);",
 | |
|                                              "    ASSERT(5)",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterSquareBracesInsideBraceInitialization)
 | |
| {
 | |
|     insertLines({"int foo() {",
 | |
|                  "char a = char{b[0]};",
 | |
|                  "int c;",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int foo() {",
 | |
|                                              "    char a = char{b[0]};",
 | |
|                                              "    int c;",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentStringLiteralContinuation)
 | |
| {
 | |
|     insertLines({"foo(bar, \"foo\"",
 | |
|                  "\"bar\");"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("foo(bar, \"foo\"",
 | |
|                                              "         \"bar\");"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentTemplateparameters)
 | |
| {
 | |
|     insertLines({"using Alias = Template<A,",
 | |
|                  "B,",
 | |
|                  "C>"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("using Alias = Template<A,",
 | |
|                                              "                       B,",
 | |
|                                              "                       C>"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, NoExtraIndentAfterStatementInsideSquareBraces)
 | |
| {
 | |
|     insertLines({"{",
 | |
|                  "    x[y=z];",
 | |
|                  "    int a;",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("{",
 | |
|                                              "    x[y=z];",
 | |
|                                              "    int a;",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, NoExtraIndentAfterBraceInitialization)
 | |
| {
 | |
|     insertLines({"int j{i?5:10};",
 | |
|                  "return 0;"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int j{i?5:10};",
 | |
|                                              "return 0;"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentMultipleEmptyLines)
 | |
| {
 | |
|     insertLines({"{",
 | |
|                  "",
 | |
|                  "",
 | |
|                  "",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("{",
 | |
|                                              "    ",
 | |
|                                              "    ",
 | |
|                                              "    ",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentEmptyLineAndKeepPreviousEmptyLines)
 | |
| {
 | |
|     insertLines({"{",
 | |
|                  "    ",
 | |
|                  "    ",
 | |
|                  "",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("{",
 | |
|                                              "    ",
 | |
|                                              "    ",
 | |
|                                              "    ",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentOnElectricCharacterButNotRemoveEmptyLinesBefore)
 | |
| {
 | |
|     insertLines({"{",
 | |
|                  "    ",
 | |
|                  "    ",
 | |
|                  "if ()",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(3), '(', TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("{",
 | |
|                                              "    ",
 | |
|                                              "    ",
 | |
|                                              "    if ()",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterExtraSpaceInpreviousLine)
 | |
| {
 | |
|     insertLines({"if (a ",
 | |
|                  "&& b)"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (a",
 | |
|                                              "    && b)"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentEmptyLineInsideParantheses)
 | |
| {
 | |
|     insertLines({"if (a ",
 | |
|                  "",
 | |
|                  "    && b)"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (a",
 | |
|                                              "    ",
 | |
|                                              "    && b)"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentInsideIf)
 | |
| {
 | |
|     insertLines({"if (a && b",
 | |
|                  ")"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (a && b",
 | |
|                                              "    )"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentInsideIf2)
 | |
| {
 | |
|     insertLines({"if (a && b &&",
 | |
|                  ")"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (a && b &&",
 | |
|                                              "    )"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentInsideIf3)
 | |
| {
 | |
|     insertLines({"if (a || b",
 | |
|                  ")"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (a || b",
 | |
|                                              "    )"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, EmptyLineInInitializerList)
 | |
| {
 | |
|     insertLines({"Bar foo{a,",
 | |
|                  "",
 | |
|                  "};"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("Bar foo{a,",
 | |
|                                              "        ",
 | |
|                                              "};"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentClosingBraceAfterComma)
 | |
| {
 | |
|     insertLines({"Bar foo{a,",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("Bar foo{a,",
 | |
|                                              "        }"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, DoNotIndentClosingBraceAfterSemicolon)
 | |
| {
 | |
|     insertLines({"{",
 | |
|                  "    a;"
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("{",
 | |
|                                              "    a;"
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterIf)
 | |
| {
 | |
|     insertLines({"if (a)",
 | |
|                  ""});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (a)",
 | |
|                                              "    "));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterElse)
 | |
| {
 | |
|     insertLines({"if (a)",
 | |
|                  "    foo();",
 | |
|                  "else",
 | |
|                  ""});
 | |
|     indenter.indentBlock(doc.findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (a)",
 | |
|                                              "    foo();",
 | |
|                                              "else",
 | |
|                                              "    "));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, SameIndentAfterSecondNewLineAfterIf)
 | |
| {
 | |
|     insertLines({"if (a)",
 | |
|                  "    ",
 | |
|                  ""});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (a)",
 | |
|                                              "    ",
 | |
|                                              "    "));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterNewLineInsideIfWithFunctionCall)
 | |
| {
 | |
|     insertLines({"if (foo()",
 | |
|                  ")"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (foo()",
 | |
|                                              "    )"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, SameIndentAfterSecondNewLineInsideIfWithFunctionCall)
 | |
| {
 | |
|     insertLines({"if (foo()",
 | |
|                  "    ",
 | |
|                  ")"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (foo()",
 | |
|                                              "    ",
 | |
|                                              "    )"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, SameIndentAfterSecondNonEmptyNewLineInsideIfWithFunctionCall)
 | |
| {
 | |
|     insertLines({"if (foo()",
 | |
|                  "    ",
 | |
|                  "bar)"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (foo()",
 | |
|                                              "    ",
 | |
|                                              "    bar)"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, SameIndentsOnNewLinesAfterComments)
 | |
| {
 | |
|     insertLines({"namespace {} //comment",
 | |
|                  "",
 | |
|                  ""});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("namespace {} //comment",
 | |
|                                              "",
 | |
|                                              ""));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterEmptyLineAfterAngledIncludeDirective)
 | |
| {
 | |
|     insertLines({"#include <string>",
 | |
|                  "",
 | |
|                  "using namespace std;"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("#include <string>",
 | |
|                                              "",
 | |
|                                              "using namespace std;"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterEmptyLineAfterQuotedIncludeDirective)
 | |
| {
 | |
|     insertLines({"#include \"foo.h\"",
 | |
|                  "",
 | |
|                  "using namespace std;"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("#include \"foo.h\"",
 | |
|                                              "",
 | |
|                                              "using namespace std;"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterLineComment)
 | |
| {
 | |
|     insertLines({"int foo()",
 | |
|                  "{",
 | |
|                  "    // Comment",
 | |
|                  "    ",
 | |
|                  "    if (",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(4), '(', TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int foo()",
 | |
|                                              "{",
 | |
|                                              "    // Comment",
 | |
|                                              "    ",
 | |
|                                              "    if (",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterBlockComment)
 | |
| {
 | |
|     insertLines({"int foo()",
 | |
|                  "{",
 | |
|                  "    bar(); /* Comment */",
 | |
|                  "    ",
 | |
|                  "    if (",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(4), '(', TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int foo()",
 | |
|                                              "{",
 | |
|                                              "    bar(); /* Comment */",
 | |
|                                              "    ",
 | |
|                                              "    if (",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterIfdef)
 | |
| {
 | |
|     insertLines({"int foo()",
 | |
|                  "{",
 | |
|                  "#ifdef FOO",
 | |
|                  "#endif",
 | |
|                  "    ",
 | |
|                  "    if (",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(5), '(', TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int foo()",
 | |
|                                              "{",
 | |
|                                              "#ifdef FOO",
 | |
|                                              "#endif",
 | |
|                                              "    ",
 | |
|                                              "    if (",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterEmptyLineInTheFileBeginning)
 | |
| {
 | |
|     insertLines({"",
 | |
|                  "void foo()"});
 | |
| 
 | |
|     indenter.indentBlock(doc.findBlockByNumber(1), ')', TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("",
 | |
|                                              "void foo()"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentFunctionBodyButNotFormatBeforeIt)
 | |
| {
 | |
|     insertLines({"int foo(int a, int b,",
 | |
|                  "        int c, int d",
 | |
|                  "        ) {",
 | |
|                  "",
 | |
|                  "}"});
 | |
| 
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b,",
 | |
|                                              "        int c, int d",
 | |
|                                              "        ) {",
 | |
|                                              "    ",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAfterFunctionBodyAndNotFormatBefore)
 | |
| {
 | |
|     insertLines({"int foo(int a, int b, int c, int d)",
 | |
|                  "{",
 | |
|                  "    ",
 | |
|                  "}"});
 | |
| 
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(3),
 | |
|                                  QChar::Null,
 | |
|                                  TextEditor::TabSettings(),
 | |
|                                  doc.characterCount() - 3);
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b, int c, int d)",
 | |
|                                              "{",
 | |
|                                              "    ",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, ReformatToEmptyFunction)
 | |
| {
 | |
|     insertLines({"int foo(int a, int b, int c, int d)",
 | |
|                  "{",
 | |
|                  "    ",
 | |
|                  "}"});
 | |
| 
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(3), '}', TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b, int c, int d) {}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, ReformatToNonEmptyFunction)
 | |
| {
 | |
|     insertLines({"int foo(int a, int b) {",
 | |
|                  "",
 | |
|                  "}"});
 | |
| 
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b) {",
 | |
|                                              "    ",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentClosingScopeAndFormatBeforeIt)
 | |
| {
 | |
|     insertLines({"if(a && b",
 | |
|                  "   &&c && d",
 | |
|                  "   ) {",
 | |
|                  "",
 | |
|                  "}"});
 | |
| 
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(4), '}', TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (a && b && c && d) {",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, DoNotFormatAfterTheFirstColon)
 | |
| {
 | |
|     insertLines({"{",
 | |
|                  "    Qt:",
 | |
|                  "}"});
 | |
| 
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(1), ':', TextEditor::TabSettings(), 9);
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("{",
 | |
|                                              "    Qt:",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, OnlyIndentIncompleteStatementOnElectricalCharacter)
 | |
| {
 | |
|     insertLines({"{bar();",
 | |
|                  "foo()",
 | |
|                  "}"});
 | |
| 
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(1), '(', TextEditor::TabSettings(), 12);
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("{bar();",
 | |
|                                              "    foo()",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAndFormatCompleteStatementOnSemicolon)
 | |
| {
 | |
|     insertLines({"{bar();",
 | |
|                  "foo();",
 | |
|                  "}"});
 | |
| 
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(1), ';', TextEditor::TabSettings(), 14);
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("{",
 | |
|                                              "    bar();",
 | |
|                                              "    foo();",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, IndentAndFormatCompleteStatementOnClosingScope)
 | |
| {
 | |
|     insertLines({"{bar();",
 | |
|                  "foo();",
 | |
|                  "}"});
 | |
| 
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(1), '}', TextEditor::TabSettings(), 16);
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("{",
 | |
|                                              "    bar();",
 | |
|                                              "    foo();",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, OnlyIndentClosingParenthesis)
 | |
| {
 | |
|     insertLines({"foo(a,",
 | |
|                  "    ",
 | |
|                  ")"});
 | |
| 
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("foo(a,",
 | |
|                                              "    ",
 | |
|                                              "    )"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, EquallyIndentInsideParenthesis)
 | |
| {
 | |
|     insertLines({"if (a",
 | |
|                  ")"});
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
 | |
|     auto linesAfterFirstLineBreak = documentLines();
 | |
|     insertLines({"if (a",
 | |
|                  "    ",
 | |
|                  ")"});
 | |
|     extendedIndenter.indentBlock(doc.findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
 | |
| 
 | |
|     ASSERT_THAT(linesAfterFirstLineBreak, ElementsAre("if (a",
 | |
|                                                       "    )"));
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("if (a",
 | |
|                                              "    ",
 | |
|                                              "    )"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, FormatBasicFile)
 | |
| {
 | |
|     insertLines({"int main()",
 | |
|                  "{",
 | |
|                  "int a;",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.format({{1, 4}});
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int main()",
 | |
|                                              "{",
 | |
|                                              "    int a;",
 | |
|                                              "}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, FormatEmptyLine)
 | |
| {
 | |
|     insertLines({"int main()",
 | |
|                  "{",
 | |
|                  "",
 | |
|                  "}"});
 | |
| 
 | |
|     indenter.format({{1, 4}});
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int main() {}"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, FormatLambda)
 | |
| {
 | |
|     insertLines({"int b = foo([](){",
 | |
|                  "",
 | |
|                  "});"});
 | |
| 
 | |
|     indenter.format({{1, 3}});
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("int b = foo([]() {",
 | |
|                                              "",
 | |
|                                              "});"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, FormatInitializerListInArguments)
 | |
| {
 | |
|     insertLines({"foo(arg1,",
 | |
|                  "args,",
 | |
|                  "{1, 2});"});
 | |
| 
 | |
|     indenter.format({{1, 3}});
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("foo(arg1, args, {1, 2});"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, FormatFunctionArgumentLambdaWithScope)
 | |
| {
 | |
|     insertLines({"foo([]()",
 | |
|                  "{",
 | |
|                  "",
 | |
|                  "});"});
 | |
| 
 | |
|     indenter.format({{1, 4}});
 | |
| 
 | |
|     ASSERT_THAT(documentLines(),
 | |
|                 ElementsAre("foo([]() {",
 | |
|                             "",
 | |
|                             "});"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, FormatScopeAsFunctionArgument)
 | |
| {
 | |
|     insertLines({"foo(",
 | |
|                  "{",
 | |
|                  "",
 | |
|                  "});"});
 | |
| 
 | |
|     indenter.format({{1, 4}});
 | |
| 
 | |
|     ASSERT_THAT(documentLines(),
 | |
|                 ElementsAre("foo({",
 | |
|                             "",
 | |
|                             "});"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, FormatStructuredBinding)
 | |
| {
 | |
|     insertLines({"auto [a,",
 | |
|                  "b] = c;"});
 | |
| 
 | |
|     indenter.format({{1, 2}});
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("auto [a, b] = c;"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, FormatStringLiteralContinuation)
 | |
| {
 | |
|     insertLines({"foo(bar, \"foo\"",
 | |
|                  "\"bar\");"});
 | |
| 
 | |
|     indenter.format({{1, 2}});
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("foo(bar,",
 | |
|                                              "    \"foo\"",
 | |
|                                              "    \"bar\");"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, FormatTemplateparameters)
 | |
| {
 | |
|     insertLines({"using Alias = Template<A,",
 | |
|                  "B,",
 | |
|                  "C>"});
 | |
| 
 | |
|     indenter.format({{1, 3}});
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("using Alias = Template<A, B, C>"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, SortIncludes)
 | |
| {
 | |
|     insertLines({"#include \"b.h\"",
 | |
|                  "#include \"a.h\"",
 | |
|                  "",
 | |
|                  "#include <bb.h>",
 | |
|                  "#include <aa.h>"});
 | |
| 
 | |
|     indenter.format({{1, 5}});
 | |
| 
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("#include \"a.h\"",
 | |
|                                              "#include \"b.h\"",
 | |
|                                              "",
 | |
|                                              "#include <aa.h>",
 | |
|                                              "#include <bb.h>"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, ChainedMemberFunctionCalls)
 | |
| {
 | |
|     insertLines({"S().func().func()",
 | |
|                  ".func();"});
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
|     ASSERT_THAT(documentLines(), ElementsAre("S().func().func()",
 | |
|                                              "    .func();"));
 | |
| }
 | |
| 
 | |
| TEST_F(ClangFormat, CommentBlock)
 | |
| {
 | |
|     insertLines({"/****************************************************************************",
 | |
|                  "**",
 | |
|                  "** Copyright (C) 2021 The Qt Company Ltd.",
 | |
|                  "** Contact: https://www.qt.io/licensing/",
 | |
|                  "**",
 | |
|                  "** This file is part of Qt Creator.",
 | |
|                  "**",
 | |
|                  "****************************************************************************/"});
 | |
|     indenter.indent(cursor, QChar::Null, TextEditor::TabSettings());
 | |
|     ASSERT_THAT(documentLines(), ElementsAre(
 | |
|                  "/****************************************************************************",
 | |
|                  "**",
 | |
|                  "** Copyright (C) 2021 The Qt Company Ltd.",
 | |
|                  "** Contact: https://www.qt.io/licensing/",
 | |
|                  "**",
 | |
|                  "** This file is part of Qt Creator.",
 | |
|                  "**",
 | |
|                  "****************************************************************************/"));
 | |
| }
 | |
| 
 | |
| // clang-format on
 | |
| 
 | |
| } // namespace
 |