forked from qt-creator/qt-creator
		
	Apparently, we can prevent clang-format from removing line breaks by adding an empty comment at the end of the line. Change-Id: Ia78ecb9e7351d059c544cbda11d33af5734e2218 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
		
			
				
	
	
		
			963 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			963 lines
		
	
	
		
			29 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();"));
 | 
						|
}
 | 
						|
 | 
						|
// clang-format on
 | 
						|
 | 
						|
} // namespace
 |