forked from qt-creator/qt-creator
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:
@@ -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 §ion, int sectionIndex)
|
void insertToSectionDeclFromDef(const QByteArray §ion, int sectionIndex)
|
||||||
{
|
{
|
||||||
|
@@ -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();
|
||||||
|
@@ -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] {
|
||||||
|
@@ -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
|
||||||
};
|
};
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user