ClangFormat: Move tests into plugin

That's where they belong

Change-Id: I78e33e76a2f42f05961f6fab31da5f3dd583a2e9
Reviewed-by: Artem Sokolovskii <artem.sokolovskii@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Christian Kandeler
2022-01-14 15:08:11 +01:00
parent 70b2b2a1d5
commit ead181e385
13 changed files with 811 additions and 1025 deletions

View File

@@ -19,3 +19,12 @@ extend_qtc_plugin(ClangFormat
CONDITION UNIX AND NOT APPLE
PROPERTIES LINK_FLAGS "-Wl,--exclude-libs,ALL"
)
extend_qtc_plugin(ClangFormat
CONDITION WITH_TESTS
SOURCES
tests/clangformat-test.cpp
tests/clangformat-test.h
DEFINES
TESTDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/tests/data"
)

View File

@@ -32,3 +32,9 @@ HEADERS += \
FORMS += \
clangformatchecks.ui \
clangformatconfigwidget.ui
equals(TEST, 1) {
DEFINES += TESTDATA_DIR=\"R\\\"xxx($$PWD/tests/data)xxx\\\"\"
HEADERS += tests/clangformat-test.h
SOURCES += tests/clangformat-test.cpp
}

View File

@@ -44,4 +44,16 @@ QtcPlugin {
"clangformatutils.h",
"clangformatutils.cpp",
]
Group {
name: "Tests"
prefix: "tests/"
condition: qtc.testsEnabled
cpp.defines: outer.concat('TESTDATA_DIR="' + sourceDirectory + "/tests/data" + '"')
files: [
"clangformat-test.cpp",
"clangformat-test.h",
"data/.clang-format",
]
}
}

View File

@@ -29,6 +29,7 @@
#include "clangformatconstants.h"
#include "clangformatindenter.h"
#include "clangformatutils.h"
#include "tests/clangformat-test.h"
#include <utils/qtcassert.h>
@@ -160,4 +161,13 @@ bool ClangFormatPlugin::initialize(const QStringList &arguments, QString *errorS
return true;
}
QVector<QObject *> ClangFormatPlugin::createTestObjects() const
{
return {
#ifdef WITH_TESTS
new Internal::ClangFormatTest,
#endif
};
}
} // namespace ClangFormat

View File

@@ -35,6 +35,7 @@ class ClangFormatPlugin : public ExtensionSystem::IPlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangFormat.json")
bool initialize(const QStringList &arguments, QString *errorString) final;
QVector<QObject *> createTestObjects() const override;
};
} // namespace ClangTools

View File

@@ -0,0 +1,649 @@
/****************************************************************************
**
** 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 "clangformat-test.h"
#include "../clangformatbaseindenter.h"
#include <texteditor/tabsettings.h>
#include <utils/fileutils.h>
#include <utils/optional.h>
#include <QTextCursor>
#include <QTextDocument>
#include <QtTest>
namespace ClangFormat::Internal {
class ClangFormatTestIndenter : public ClangFormatBaseIndenter
{
public:
ClangFormatTestIndenter(QTextDocument *doc) : ClangFormatBaseIndenter(doc) {}
private:
Utils::optional<TextEditor::TabSettings> tabSettings() const override { return {}; }
};
class ClangFormatExtendedTestIndenter : public ClangFormatTestIndenter
{
public:
ClangFormatExtendedTestIndenter(QTextDocument *doc) : ClangFormatTestIndenter(doc) {}
private:
bool formatWhileTyping() const override { return true; }
};
ClangFormatTest::ClangFormatTest()
: m_doc(new QTextDocument(this)),
m_cursor(new QTextCursor(m_doc)),
m_indenter(new ClangFormatTestIndenter(m_doc)),
m_extendedIndenter(new ClangFormatExtendedTestIndenter(m_doc))
{
m_indenter->setFileName(Utils::FilePath::fromString(TESTDATA_DIR "/test.cpp"));
m_extendedIndenter->setFileName(Utils::FilePath::fromString(TESTDATA_DIR "/test.cpp"));
}
ClangFormatTest::~ClangFormatTest()
{
delete m_extendedIndenter;
delete m_indenter;
delete m_cursor;
}
void ClangFormatTest::insertLines(const std::vector<QString> &lines)
{
m_doc->clear();
m_cursor->setPosition(0);
for (std::size_t lineNumber = 1; lineNumber <= lines.size(); ++lineNumber) {
if (lineNumber > 1)
m_cursor->insertBlock();
m_cursor->insertText(lines[lineNumber - 1]);
}
m_cursor->setPosition(0);
m_cursor->movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
}
std::vector<QString> ClangFormatTest::documentLines() const
{
std::vector<QString> result;
const int lines = m_doc->blockCount();
result.reserve(static_cast<size_t>(lines));
for (int line = 0; line < lines; ++line)
result.push_back(m_doc->findBlockByNumber(line).text());
return result;
}
void ClangFormatTest::testIndentBasicFile()
{
insertLines({"int main()", "{", "int a;", "}"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"int main()", "{", " int a;", "}"}));
}
void ClangFormatTest::testIndentEmptyLine()
{
insertLines({"int main()", "{", "", "}"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"int main()", "{", " ", "}"}));
}
void ClangFormatTest::testIndentLambda()
{
insertLines({"int b = foo([](){", "", "});"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"int b = foo([](){", " ", "});"}));
}
void ClangFormatTest::testIndentNestedIfElse()
{
insertLines({"if (a)",
"if (b)",
"foo();",
"else",
"bar();",
"else",
"baz();"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{
"if (a)",
" if (b)",
" foo();",
" else",
" bar();",
"else",
" baz();"}));
}
void ClangFormatTest::testIndentInitializerListInArguments()
{
insertLines({"foo(arg1,", "args,", "{1, 2});"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"foo(arg1,", " args,", " {1, 2});"}));
}
void ClangFormatTest::testIndentLambdaWithReturnType()
{
insertLines({"{", "auto lambda = []() -> bool {", "", "};", "}"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"{", " auto lambda = []() -> bool {", " ", " };", "}"}));
}
void ClangFormatTest::testIndentFunctionArgumentLambdaWithNextLineScope()
{
insertLines({"foo([]()", "{", "", "});"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"foo([]()", " {", " ", " });"}));
}
void ClangFormatTest::testIndentScopeAsFunctionArgument()
{
insertLines({"foo(", "{", "", "});"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"foo(", " {", " ", " });"}));
}
void ClangFormatTest::testIndentInsideStructuredBinding()
{
insertLines({"auto [a,", "b] = c;"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"auto [a,", " b] = c;"}));
}
void ClangFormatTest::testIndentMacrosWithoutSemicolon()
{
insertLines({"void test()",
"{",
"ASSERT(1);",
"ASSERT(2)",
"ASSERT(3)",
"ASSERT(4);",
"ASSERT(5)",
"}"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{
"void test()",
"{",
" ASSERT(1);",
" ASSERT(2)",
" ASSERT(3)",
" ASSERT(4);",
" ASSERT(5)",
"}"}));
}
void ClangFormatTest::testIndentAfterSquareBracesInsideBraceInitialization()
{
insertLines({"int foo() {", "char a = char{b[0]};", "int c;", "}"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"int foo() {", " char a = char{b[0]};", " int c;", "}"}));
}
void ClangFormatTest::testIndentStringLiteralContinuation()
{
insertLines({"foo(bar, \"foo\"", "\"bar\");"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"foo(bar, \"foo\"", " \"bar\");"}));
}
void ClangFormatTest::testIndentTemplateparameters()
{
insertLines({"using Alias = Template<A,", "B,", "C>"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{
"using Alias = Template<A,",
" B,",
" C>"}));
}
void ClangFormatTest::testNoExtraIndentAfterStatementInsideSquareBraces()
{
insertLines({"{", " x[y=z];", " int a;", "}"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"{", " x[y=z];", " int a;", "}"}));
}
void ClangFormatTest::testNoExtraIndentAfterBraceInitialization()
{
insertLines({"int j{i?5:10};", "return 0;"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"int j{i?5:10};", "return 0;"}));
}
void ClangFormatTest::testIndentMultipleEmptyLines()
{
insertLines({"{", "", "", "", "}"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"{", " ", " ", " ", "}"}));
}
void ClangFormatTest::testIndentEmptyLineAndKeepPreviousEmptyLines()
{
insertLines({"{", " ", " ", "", "}"});
m_indenter->indentBlock(m_doc->findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"{", " ", " ", " ", "}"}));
}
void ClangFormatTest::testIndentOnElectricCharacterButNotRemoveEmptyLinesBefore()
{
insertLines({"{", " ", " ", "if ()", "}"});
m_indenter->indentBlock(m_doc->findBlockByNumber(3), '(', TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"{", " ", " ", " if ()", "}"}));
}
void ClangFormatTest::testIndentAfterExtraSpaceInpreviousLine()
{
insertLines({"if (a ", "&& b)"});
m_indenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (a", " && b)"}));
}
void ClangFormatTest::testIndentEmptyLineInsideParentheses()
{
insertLines({"if (a ", "", " && b)"});
m_indenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (a", " ", " && b)"}));
}
void ClangFormatTest::testIndentInsideIf()
{
insertLines({"if (a && b", ")"});
m_indenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (a && b", " )"}));
}
void ClangFormatTest::testIndentInsideIf2()
{
insertLines({"if (a && b &&", ")"});
m_indenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (a && b &&", " )"}));
}
void ClangFormatTest::testIndentInsideIf3()
{
insertLines({"if (a || b", ")"});
m_indenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (a || b", " )"}));
}
void ClangFormatTest::testEmptyLineInInitializerList()
{
insertLines({"Bar foo{a,", "", "};"});
m_indenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"Bar foo{a,", " ", "};"}));
}
void ClangFormatTest::testIndentClosingBraceAfterComma()
{
insertLines({"Bar foo{a,", "}"});
m_indenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"Bar foo{a,", " }"}));
}
void ClangFormatTest::testDoNotIndentClosingBraceAfterSemicolon()
{
insertLines({"{", " a;" "}"});
m_indenter->indentBlock(m_doc->findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"{", " a;" "}"}));
}
void ClangFormatTest::testIndentAfterIf()
{
insertLines({"if (a)", ""});
m_indenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (a)", " "}));
}
void ClangFormatTest::testIndentAfterElse()
{
insertLines({"if (a)", " foo();", "else", ""});
m_indenter->indentBlock(m_doc->findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (a)", " foo();", "else", " "}));
}
void ClangFormatTest::testSameIndentAfterSecondNewLineAfterIf()
{
insertLines({"if (a)", " ", ""});
m_indenter->indentBlock(m_doc->findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (a)", " ", " "}));
}
void ClangFormatTest::testIndentAfterNewLineInsideIfWithFunctionCall()
{
insertLines({"if (foo()", ")"});
m_indenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (foo()", " )"}));
}
void ClangFormatTest::testSameIndentAfterSecondNewLineInsideIfWithFunctionCall()
{
insertLines({"if (foo()", " ", ")"});
m_indenter->indentBlock(m_doc->findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (foo()", " ", " )"}));
}
void ClangFormatTest::testSameIndentAfterSecondNonEmptyNewLineInsideIfWithFunctionCall()
{
insertLines({"if (foo()", " ", "bar)"});
m_indenter->indentBlock(m_doc->findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (foo()", " ", " bar)"}));
}
void ClangFormatTest::testSameIndentsOnNewLinesAfterComments()
{
insertLines({"namespace {} //comment", "", ""});
m_indenter->indentBlock(m_doc->findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"namespace {} //comment", "", ""}));
}
void ClangFormatTest::testIndentAfterEmptyLineAfterAngledIncludeDirective()
{
insertLines({"#include <string>", "", "using namespace std;"});
m_indenter->indentBlock(m_doc->findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"#include <string>", "", "using namespace std;"}));
}
void ClangFormatTest::testIndentAfterEmptyLineAfterQuotedIncludeDirective()
{
insertLines({"#include \"foo.h\"", "", "using namespace std;"});
m_indenter->indentBlock(m_doc->findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"#include \"foo.h\"", "", "using namespace std;"}));
}
void ClangFormatTest::testIndentAfterLineComment()
{
insertLines({"int foo()",
"{",
" // Comment",
" ",
" if (",
"}"});
m_indenter->indentBlock(m_doc->findBlockByNumber(4), '(', TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{
"int foo()",
"{",
" // Comment",
" ",
" if (",
"}"}));
}
void ClangFormatTest::testIndentAfterBlockComment()
{
insertLines({"int foo()",
"{",
" bar(); /* Comment */",
" ",
" if (",
"}"});
m_indenter->indentBlock(m_doc->findBlockByNumber(4), '(', TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{
"int foo()",
"{",
" bar(); /* Comment */",
" ",
" if (",
"}"}));
}
void ClangFormatTest::testIndentAfterIfdef()
{
insertLines({"int foo()",
"{",
"#ifdef FOO",
"#endif",
" ",
" if (",
"}"});
m_indenter->indentBlock(m_doc->findBlockByNumber(5), '(', TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{
"int foo()",
"{",
"#ifdef FOO",
"#endif",
" ",
" if (",
"}"}));
}
void ClangFormatTest::testIndentAfterEmptyLineInTheFileBeginning()
{
insertLines({"", "void foo()"});
m_indenter->indentBlock(m_doc->findBlockByNumber(1), ')', TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"", "void foo()"}));
}
void ClangFormatTest::testIndentFunctionBodyButNotFormatBeforeIt()
{
insertLines({"int foo(int a, int b,",
" int c, int d",
" ) {",
"",
"}"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{
"int foo(int a, int b,",
" int c, int d",
" ) {",
" ",
"}"}));
}
void ClangFormatTest::testIndentAfterFunctionBodyAndNotFormatBefore()
{
insertLines({"int foo(int a, int b, int c, int d)",
"{",
" ",
"}"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(3),
QChar::Null,
TextEditor::TabSettings(),
m_doc->characterCount() - 3);
QCOMPARE(documentLines(), (std::vector<QString>{
"int foo(int a, int b, int c, int d)",
"{",
" ",
"}"}));
}
void ClangFormatTest::testReformatToEmptyFunction()
{
insertLines({"int foo(int a, int b, int c, int d)", "{", " ", "}"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(3), '}', TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"int foo(int a, int b, int c, int d) {}"}));
}
void ClangFormatTest::testReformatToNonEmptyFunction()
{
insertLines({"int foo(int a, int b) {", "", "}"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null,
TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"int foo(int a, int b) {", " ", "}"}));
}
void ClangFormatTest::testIndentClosingScopeAndFormatBeforeIt()
{
insertLines({"if(a && b", " &&c && d", " ) {", "", "}"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(4), '}', TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"if (a && b && c && d) {", "}"}));
}
void ClangFormatTest::testDoNotFormatAfterTheFirstColon()
{
insertLines({"{", " Qt:", "}"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(1), ':', TextEditor::TabSettings(), 9);
QCOMPARE(documentLines(), (std::vector<QString>{"{", " Qt:", "}"}));
}
void ClangFormatTest::testOnlyIndentIncompleteStatementOnElectricalCharacter()
{
insertLines({"{bar();", "foo()", "}"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(1), '(', TextEditor::TabSettings(), 12);
QCOMPARE(documentLines(), (std::vector<QString>{"{bar();", " foo()", "}"}));
}
void ClangFormatTest::testIndentAndFormatCompleteStatementOnSemicolon()
{
insertLines({"{bar();", "foo();", "}"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(1), ';', TextEditor::TabSettings(), 14);
QCOMPARE(documentLines(), (std::vector<QString>{"{", " bar();", " foo();", "}"}));
}
void ClangFormatTest::testIndentAndFormatCompleteStatementOnClosingScope()
{
insertLines({"{bar();", "foo();", "}"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(1), '}', TextEditor::TabSettings(), 16);
QCOMPARE(documentLines(), (std::vector<QString>{"{", " bar();", " foo();", "}"}));
}
void ClangFormatTest::testOnlyIndentClosingParenthesis()
{
insertLines({"foo(a,", " ", ")"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(2), QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"foo(a,", " ", " )"}));
}
void ClangFormatTest::testEquallyIndentInsideParenthesis()
{
insertLines({"if (a", ")"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(1), QChar::Null,
TextEditor::TabSettings());
auto linesAfterFirstLineBreak = documentLines();
insertLines({"if (a", " ", ")"});
m_extendedIndenter->indentBlock(m_doc->findBlockByNumber(2),
QChar::Null, TextEditor::TabSettings());
QCOMPARE(linesAfterFirstLineBreak, (std::vector<QString>{"if (a", " )"}));
QCOMPARE(documentLines(), (std::vector<QString>{"if (a", " ", " )"}));
}
void ClangFormatTest::testFormatBasicFile()
{
insertLines({"int main()", "{", "int a;", "}"});
m_indenter->format({{1, 4}});
QCOMPARE(documentLines(), (std::vector<QString>{"int main()", "{", " int a;", "}"}));
}
void ClangFormatTest::testFormatEmptyLine()
{
insertLines({"int main()", "{", "", "}"});
m_indenter->format({{1, 4}});
QCOMPARE(documentLines(), (std::vector<QString>{"int main() {}"}));
}
void ClangFormatTest::testFormatLambda()
{
insertLines({"int b = foo([](){", "", "});"});
m_indenter->format({{1, 3}});
QCOMPARE(documentLines(), (std::vector<QString>{"int b = foo([]() {", "", "});"}));
}
void ClangFormatTest::testFormatInitializerListInArguments()
{
insertLines({"foo(arg1,", "args,", "{1, 2});"});
m_indenter->format({{1, 3}});
QCOMPARE(documentLines(), (std::vector<QString>{"foo(arg1, args, {1, 2});"}));
}
void ClangFormatTest::testFormatFunctionArgumentLambdaWithScope()
{
insertLines({"foo([]()", "{", "", "});"});
m_indenter->format({{1, 4}});
QCOMPARE(documentLines(), (std::vector<QString>{"foo([]() {", "", "});"}));
}
void ClangFormatTest::testFormatScopeAsFunctionArgument()
{
insertLines({"foo(", "{", "", "});"});
m_indenter->format({{1, 4}});
QCOMPARE(documentLines(), (std::vector<QString>{"foo({", "", "});"}));
}
void ClangFormatTest::testFormatStructuredBinding()
{
insertLines({"auto [a,", "b] = c;"});
m_indenter->format({{1, 2}});
QCOMPARE(documentLines(), (std::vector<QString>{"auto [a, b] = c;"}));
}
void ClangFormatTest::testFormatStringLiteralContinuation()
{
insertLines({"foo(bar, \"foo\"", "\"bar\");"});
m_indenter->format({{1, 2}});
QCOMPARE(documentLines(), (std::vector<QString>{"foo(bar,", " \"foo\"", " \"bar\");"}));
}
void ClangFormatTest::testFormatTemplateparameters()
{
insertLines({"using Alias = Template<A,", "B,", "C>"});
m_indenter->format({{1, 3}});
QCOMPARE(documentLines(), (std::vector<QString>{"using Alias = Template<A, B, C>"}));
}
void ClangFormatTest::testSortIncludes()
{
insertLines({"#include \"b.h\"",
"#include \"a.h\"",
"",
"#include <bb.h>",
"#include <aa.h>"});
m_indenter->format({{1, 5}});
QCOMPARE(documentLines(), (std::vector<QString>{
"#include \"a.h\"",
"#include \"b.h\"",
"",
"#include <aa.h>",
"#include <bb.h>"}));
}
void ClangFormatTest::testChainedMemberFunctionCalls()
{
insertLines({"S().func().func()", ".func();"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{"S().func().func()", " .func();"}));
}
void ClangFormatTest::testCommentBlock()
{
insertLines({"/****************************************************************************",
"**",
"** Copyright (C) 2021 The Qt Company Ltd.",
"** Contact: https://www.qt.io/licensing/",
"**",
"** This file is part of Qt Creator.",
"**",
"****************************************************************************/"});
m_indenter->indent(*m_cursor, QChar::Null, TextEditor::TabSettings());
QCOMPARE(documentLines(), (std::vector<QString>{
"/****************************************************************************",
"**",
"** Copyright (C) 2021 The Qt Company Ltd.",
"** Contact: https://www.qt.io/licensing/",
"**",
"** This file is part of Qt Creator.",
"**",
"****************************************************************************/"}));
}
} // namespace ClangFormat::Internal

View File

@@ -0,0 +1,124 @@
/****************************************************************************
**
** Copyright (C) 2022 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.
**
****************************************************************************/
#pragma once
#include <QObject>
#include <vector>
QT_BEGIN_NAMESPACE
class QString;
class QTextCursor;
class QTextDocument;
QT_END_NAMESPACE
namespace ClangFormat {
class ClangFormatBaseIndenter;
namespace Internal {
class ClangFormatTest : public QObject
{
Q_OBJECT
public:
ClangFormatTest();
~ClangFormatTest();
private slots:
void testIndentBasicFile();
void testIndentEmptyLine();
void testIndentLambda();
void testIndentNestedIfElse();
void testIndentInitializerListInArguments();
void testIndentLambdaWithReturnType();
void testIndentFunctionArgumentLambdaWithNextLineScope();
void testIndentScopeAsFunctionArgument();
void testIndentInsideStructuredBinding();
void testIndentMacrosWithoutSemicolon();
void testIndentAfterSquareBracesInsideBraceInitialization();
void testIndentStringLiteralContinuation();
void testIndentTemplateparameters();
void testNoExtraIndentAfterStatementInsideSquareBraces();
void testNoExtraIndentAfterBraceInitialization();
void testIndentMultipleEmptyLines();
void testIndentEmptyLineAndKeepPreviousEmptyLines();
void testIndentOnElectricCharacterButNotRemoveEmptyLinesBefore();
void testIndentAfterExtraSpaceInpreviousLine();
void testIndentEmptyLineInsideParentheses();
void testIndentInsideIf();
void testIndentInsideIf2();
void testIndentInsideIf3();
void testEmptyLineInInitializerList();
void testIndentClosingBraceAfterComma();
void testDoNotIndentClosingBraceAfterSemicolon();
void testIndentAfterIf();
void testIndentAfterElse();
void testSameIndentAfterSecondNewLineAfterIf();
void testIndentAfterNewLineInsideIfWithFunctionCall();
void testSameIndentAfterSecondNewLineInsideIfWithFunctionCall();
void testSameIndentAfterSecondNonEmptyNewLineInsideIfWithFunctionCall();
void testSameIndentsOnNewLinesAfterComments();
void testIndentAfterEmptyLineAfterAngledIncludeDirective();
void testIndentAfterEmptyLineAfterQuotedIncludeDirective();
void testIndentAfterLineComment();
void testIndentAfterBlockComment();
void testIndentAfterIfdef();
void testIndentAfterEmptyLineInTheFileBeginning();
void testIndentFunctionBodyButNotFormatBeforeIt();
void testIndentAfterFunctionBodyAndNotFormatBefore();
void testReformatToEmptyFunction();
void testReformatToNonEmptyFunction();
void testIndentClosingScopeAndFormatBeforeIt();
void testDoNotFormatAfterTheFirstColon();
void testOnlyIndentIncompleteStatementOnElectricalCharacter();
void testIndentAndFormatCompleteStatementOnSemicolon();
void testIndentAndFormatCompleteStatementOnClosingScope();
void testOnlyIndentClosingParenthesis();
void testEquallyIndentInsideParenthesis();
void testFormatBasicFile();
void testFormatEmptyLine();
void testFormatLambda();
void testFormatInitializerListInArguments();
void testFormatFunctionArgumentLambdaWithScope();
void testFormatScopeAsFunctionArgument();
void testFormatStructuredBinding();
void testFormatStringLiteralContinuation();
void testFormatTemplateparameters();
void testSortIncludes();
void testChainedMemberFunctionCalls();
void testCommentBlock();
private:
void insertLines(const std::vector<QString> &lines);
std::vector<QString> documentLines() const;
QTextDocument * const m_doc;
QTextCursor * const m_cursor;
ClangFormatBaseIndenter * const m_indenter;
ClangFormatBaseIndenter * const m_extendedIndenter;
};
} // namespace Internal
} // namespace ClangFormat

View File

@@ -466,21 +466,6 @@ extend_qtc_test(unittest
cppprojectfile.cpp cppprojectfile.h
)
extend_qtc_test(unittest
SOURCES_PREFIX ../../../src/plugins/clangformat
CONDITION HAVE_LIBCLANG
DEPENDS ${CLANG_TOOLING_LIBS}
SOURCES
clangformatconstants.h
clangformatbaseindenter.cpp clangformatbaseindenter.h
)
extend_qtc_test(unittest
CONDITION HAVE_LIBCLANG
SOURCES
clangformat-test.cpp
)
get_filename_component(
QMLDOM_STANDALONE_CMAKELISTS
"${CMAKE_CURRENT_SOURCE_DIR}/../../../../qmldom_standalone/src/qmldom/standalone/"

View File

@@ -1,984 +0,0 @@
/****************************************************************************
**
** 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

View File

@@ -13,7 +13,6 @@ include($$PWD/../../../src/plugins/clangtools/clangtoolsunittestfiles.pri)
include($$PWD/../../../src/shared/clang/clang_defines.pri)
include($$PWD/../../../src/tools/clangbackend/source/clangbackendclangipc-source.pri)
include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri)
!isEmpty(CLANGFORMAT_LIBS): include($$PWD/../../../src/plugins/clangformat/clangformat-source.pri)
} else {
DEFINES += CLANG_VERSION=\\\"6.0.0\\\"
DEFINES += "\"CLANG_INCLUDE_DIR=\\\"/usr/include\\\"\""

View File

@@ -170,10 +170,6 @@ SOURCES += \
gtest-llvm-printing.cpp \
}
!isEmpty(CLANGFORMAT_LIBS) {
SOURCES += clangformat-test.cpp
}
!isEmpty(GOOGLEBENCHMARK_DIR):exists($$GOOGLEBENCHMARK_DIR) {
SOURCES += \
smallstring-benchmark.cpp

View File

@@ -291,14 +291,6 @@ Project {
]
}
Group {
name: "ClangFormat tests"
condition: libclang.present
&& libclang.llvmFormattingLibs.length
&& (!qbs.targetOS.contains("windows") || libclang.llvmBuildModeMatches)
files: "clangformat-test.cpp"
}
Group {
name: "benchmark test"
condition: benchmark.present
@@ -486,19 +478,6 @@ Project {
]
}
Group {
name: "sources from ClangFormat"
prefix: "../../../src/plugins/clangformat/"
condition: libclang.present
&& libclang.llvmFormattingLibs.length
&& (!qbs.targetOS.contains("windows") || libclang.llvmBuildModeMatches)
files: [
"clangformatbaseindenter.cpp",
"clangformatbaseindenter.h",
"clangformatconstants.h",
]
}
Group {
name: "sources from Debugger"
prefix: "../../../src/plugins/debugger/analyzer/"