forked from qt-creator/qt-creator
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:
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
649
src/plugins/clangformat/tests/clangformat-test.cpp
Normal file
649
src/plugins/clangformat/tests/clangformat-test.cpp
Normal 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
|
||||
124
src/plugins/clangformat/tests/clangformat-test.h
Normal file
124
src/plugins/clangformat/tests/clangformat-test.h
Normal 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
|
||||
115
src/plugins/clangformat/tests/data/.clang-format
Normal file
115
src/plugins/clangformat/tests/data/.clang-format
Normal file
@@ -0,0 +1,115 @@
|
||||
# .clang-format for Qt Creator
|
||||
#
|
||||
# This is for clang-format >= 5.0.
|
||||
#
|
||||
# The configuration below follows the Qt Creator Coding Rules [1] as closely as
|
||||
# possible. For documentation of the options, see [2].
|
||||
#
|
||||
# Use ../../tests/manual/clang-format-for-qtc/test.cpp for documenting problems
|
||||
# or testing changes.
|
||||
#
|
||||
# [1] https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html
|
||||
# [2] https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
#
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: true
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- forever # avoids { wrapped to next line
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeCategories:
|
||||
- Regex: '^<Q.*'
|
||||
Priority: 200
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
# Do not add QT_BEGIN_NAMESPACE/QT_END_NAMESPACE as this will indent lines in between.
|
||||
MacroBlockBegin: ""
|
||||
MacroBlockEnd: ""
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 150
|
||||
PenaltyBreakBeforeFirstCallParameter: 300
|
||||
PenaltyBreakComment: 500
|
||||
PenaltyBreakFirstLessLess: 400
|
||||
PenaltyBreakString: 600
|
||||
PenaltyExcessCharacter: 50
|
||||
PenaltyReturnTypeOnItsOwnLine: 300
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
Reference in New Issue
Block a user