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 "cpptoolssettings.h"
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <utils/fileutils.h>
#include <QDebug>
@@ -60,7 +62,8 @@ QList<TestDocumentPtr> singleDocument(const QByteArray &original,
}
BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDocuments,
const ProjectExplorer::HeaderPaths &headerPaths)
const ProjectExplorer::HeaderPaths &headerPaths,
const QByteArray &clangFormatSettings)
: m_testDocuments(testDocuments)
, m_cppCodeStylePreferences(0)
, m_restoreHeaderPaths(false)
@@ -85,6 +88,10 @@ BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<TestDocumentPtr> &testDoc
document->writeToDisk();
}
// Create .clang-format file
if (!clangFormatSettings.isEmpty())
m_temporaryDirectory->createFile(".clang-format", clangFormatSettings);
// Set appropriate include paths
if (!headerPaths.isEmpty()) {
m_restoreHeaderPaths = true;
@@ -182,8 +189,9 @@ QuickFixOperationTest::QuickFixOperationTest(const QList<TestDocumentPtr> &testD
CppQuickFixFactory *factory,
const ProjectExplorer::HeaderPaths &headerPaths,
int operationIndex,
const QByteArray &expectedFailMessage)
: BaseQuickFixTestCase(testDocuments, headerPaths)
const QByteArray &expectedFailMessage,
const QByteArray &clangFormatSettings)
: BaseQuickFixTestCase(testDocuments, headerPaths, clangFormatSettings)
{
QVERIFY(succeededSoFar());
@@ -5336,6 +5344,57 @@ void QuickfixTest::testInsertDefsFromDecls()
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
void insertToSectionDeclFromDef(const QByteArray &section, int sectionIndex)
{

View File

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

View File

@@ -3478,6 +3478,15 @@ private:
settings = dlg.settings();
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: {
int defPos = DefPosImplementationFile;
const auto incDefPos = [&defPos] {

View File

@@ -402,6 +402,7 @@ public:
enum class Mode {
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
User // Normal interactive mode
};

View File

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