CppEditor: Add test case for quickfix formatting

Also fixes an off-by-one error in the formatting code that was uncovered
by the test.

Change-Id: I013194e21cf37f318bb806bb60ea659b91b99fbf
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Christian Kandeler
2023-06-28 12:47:38 +02:00
parent 379e7f906e
commit bcd49bafdd
5 changed files with 78 additions and 7 deletions

View File

@@ -13,6 +13,8 @@
#include "cppsourceprocessertesthelper.h" #include "cppsourceprocessertesthelper.h"
#include "cpptoolssettings.h" #include "cpptoolssettings.h"
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <QDebug> #include <QDebug>
@@ -60,7 +62,8 @@ QList<TestDocumentPtr> singleDocument(const QByteArray &original,
} }
BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDocuments, BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDocuments,
const ProjectExplorer::HeaderPaths &headerPaths) const ProjectExplorer::HeaderPaths &headerPaths,
const QByteArray &clangFormatSettings)
: m_testDocuments(testDocuments) : m_testDocuments(testDocuments)
, m_cppCodeStylePreferences(0) , m_cppCodeStylePreferences(0)
, m_restoreHeaderPaths(false) , m_restoreHeaderPaths(false)
@@ -85,6 +88,10 @@ BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDoc
document->writeToDisk(); document->writeToDisk();
} }
// Create .clang-format file
if (!clangFormatSettings.isEmpty())
m_temporaryDirectory->createFile(".clang-format", clangFormatSettings);
// Set appropriate include paths // Set appropriate include paths
if (!headerPaths.isEmpty()) { if (!headerPaths.isEmpty()) {
m_restoreHeaderPaths = true; m_restoreHeaderPaths = true;
@@ -182,8 +189,9 @@ QuickFixOperationTest::QuickFixOperationTest(const QList<TestDocumentPtr> &testD
CppQuickFixFactory *factory, CppQuickFixFactory *factory,
const ProjectExplorer::HeaderPaths &headerPaths, const ProjectExplorer::HeaderPaths &headerPaths,
int operationIndex, int operationIndex,
const QByteArray &expectedFailMessage) const QByteArray &expectedFailMessage,
: BaseQuickFixTestCase(testDocuments, headerPaths) const QByteArray &clangFormatSettings)
: BaseQuickFixTestCase(testDocuments, headerPaths, clangFormatSettings)
{ {
QVERIFY(succeededSoFar()); QVERIFY(succeededSoFar());
@@ -5336,6 +5344,57 @@ void QuickfixTest::testInsertDefsFromDecls()
QuickFixOperationTest(testDocuments, &factory); QuickFixOperationTest(testDocuments, &factory);
} }
void QuickfixTest::testInsertAndFormatDefsFromDecls()
{
static const auto isClangFormatPresent = [] {
using namespace ExtensionSystem;
return Utils::contains(PluginManager::plugins(), [](const PluginSpec *plugin) {
return plugin->name() == "ClangFormat" && plugin->isEffectivelyEnabled();
});
};
if (!isClangFormatPresent())
QSKIP("This test reqires ClangFormat");
const QByteArray origHeader = R"(
class @C
{
public:
void func1 (int const &i);
void func2 (double const d);
};
)";
const QByteArray origSource = R"(
#include "file.h"
)";
const QByteArray expectedSource = R"(
#include "file.h"
void C::func1 (int const &i)
{
}
void C::func2 (double const d)
{
}
)";
const QByteArray clangFormatSettings = R"(
BreakBeforeBraces: Allman
QualifierAlignment: Right
SpaceBeforeParens: Always
)";
const QList<TestDocumentPtr> testDocuments({
CppTestDocument::create("file.h", origHeader, origHeader),
CppTestDocument::create("file.cpp", origSource, expectedSource)});
InsertDefsFromDecls factory;
factory.setMode(InsertDefsFromDecls::Mode::Impl);
QuickFixOperationTest(testDocuments, &factory, {}, {}, {}, clangFormatSettings);
}
// Function for one of InsertDeclDef section cases // Function for one of InsertDeclDef section cases
void insertToSectionDeclFromDef(const QByteArray &section, int sectionIndex) void insertToSectionDeclFromDef(const QByteArray &section, int sectionIndex)
{ {

View File

@@ -26,8 +26,8 @@ public:
/// Exactly one QuickFixTestDocument must contain the cursor position marker '@' /// Exactly one QuickFixTestDocument must contain the cursor position marker '@'
/// or "@{start}" and "@{end}" /// or "@{start}" and "@{end}"
BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDocuments, BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDocuments,
const ProjectExplorer::HeaderPaths &headerPaths const ProjectExplorer::HeaderPaths &headerPaths,
= ProjectExplorer::HeaderPaths()); const QByteArray &clangFormatSettings = {});
~BaseQuickFixTestCase(); ~BaseQuickFixTestCase();
@@ -54,7 +54,8 @@ public:
const ProjectExplorer::HeaderPaths &headerPaths const ProjectExplorer::HeaderPaths &headerPaths
= ProjectExplorer::HeaderPaths(), = ProjectExplorer::HeaderPaths(),
int operationIndex = 0, int operationIndex = 0,
const QByteArray &expectedFailMessage = QByteArray()); const QByteArray &expectedFailMessage = {},
const QByteArray &clangFormatSettings = {});
static void run(const QList<TestDocumentPtr> &testDocuments, static void run(const QList<TestDocumentPtr> &testDocuments,
CppQuickFixFactory *factory, CppQuickFixFactory *factory,
@@ -139,6 +140,7 @@ private slots:
void testInsertDefFromDeclAliasTemplateAsReturnType(); void testInsertDefFromDeclAliasTemplateAsReturnType();
void testInsertDefsFromDecls_data(); void testInsertDefsFromDecls_data();
void testInsertDefsFromDecls(); void testInsertDefsFromDecls();
void testInsertAndFormatDefsFromDecls();
void testInsertDeclFromDef(); void testInsertDeclFromDef();
void testInsertDeclFromDefTemplateFuncTypename(); void testInsertDeclFromDefTemplateFuncTypename();

View File

@@ -3478,6 +3478,15 @@ private:
settings = dlg.settings(); settings = dlg.settings();
break; break;
} }
case InsertDefsFromDecls::Mode::Impl: {
for (Symbol * const func : std::as_const(unimplemented)) {
MemberFunctionImplSetting setting;
setting.func = func;
setting.defPos = DefPosImplementationFile;
settings << setting;
}
break;
}
case InsertDefsFromDecls::Mode::Alternating: { case InsertDefsFromDecls::Mode::Alternating: {
int defPos = DefPosImplementationFile; int defPos = DefPosImplementationFile;
const auto incDefPos = [&defPos] { const auto incDefPos = [&defPos] {

View File

@@ -402,6 +402,7 @@ public:
enum class Mode { enum class Mode {
Off, // Testing: simulates user canceling the dialog Off, // Testing: simulates user canceling the dialog
Impl, // Testing: simulates user choosing cpp file for every function
Alternating, // Testing: simulates user choosing a different DefPos for every function Alternating, // Testing: simulates user choosing a different DefPos for every function
User // Normal interactive mode User // Normal interactive mode
}; };

View File

@@ -468,7 +468,7 @@ void RefactoringFile::doFormatting()
QTC_ASSERT(b.isValid(), break); QTC_ASSERT(b.isValid(), break);
if (b.text().simplified().isEmpty()) if (b.text().simplified().isEmpty())
QTextCursor(b).insertText(clangFormatLineRemovalBlocker); QTextCursor(b).insertText(clangFormatLineRemovalBlocker);
if (b.blockNumber() == r.endLine) if (b.blockNumber() == r.endLine - 1)
break; break;
b = b.next(); b = b.next();
} }