CppEditor: Convert ConvertToMetaMethodCallTest to out-of-line approach

Change-Id: If540f851c424df57793551bcfef3f565c4b07682
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Christian Kandeler
2025-03-05 16:27:36 +01:00
parent cdca663ede
commit 7dca8434ef
21 changed files with 216 additions and 108 deletions

View File

@@ -302,5 +302,24 @@
<file>testcases/ConvertToCamelCaseTest/upper-case/original_file.cpp</file> <file>testcases/ConvertToCamelCaseTest/upper-case/original_file.cpp</file>
<file>testcases/ConvertToCamelCaseTest/wild-mix/expected_file.cpp</file> <file>testcases/ConvertToCamelCaseTest/wild-mix/expected_file.cpp</file>
<file>testcases/ConvertToCamelCaseTest/wild-mix/original_file.cpp</file> <file>testcases/ConvertToCamelCaseTest/wild-mix/original_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/emit/expected_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/emit/original_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/expression/expected_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/expression/original_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/not-invokable/original_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/object-value/expected_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/object-value/original_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/pointer-to-object/expected_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/pointer-to-object/original_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/Q_EMIT/expected_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/Q_EMIT/original_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/Q_INVOKABLE/expected_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/Q_INVOKABLE/original_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/Q_SIGNAL/expected_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/Q_SIGNAL/original_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/Q_SLOT/expected_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/Q_SLOT/original_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/slot/expected_file.cpp</file>
<file>testcases/ConvertToMetaMethodCallTest/slot/original_file.cpp</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -110,11 +110,6 @@ private:
//! marked as invokable. //! marked as invokable.
class ConvertToMetaMethodCall : public CppQuickFixFactory class ConvertToMetaMethodCall : public CppQuickFixFactory
{ {
#ifdef WITH_TESTS
public:
static QObject *createTest();
#endif
private:
void doMatch(const CppQuickFixInterface &interface, QuickFixOperations &result) override void doMatch(const CppQuickFixInterface &interface, QuickFixOperations &result) override
{ {
const Document::Ptr &cppDoc = interface.currentFile()->cppDocument(); const Document::Ptr &cppDoc = interface.currentFile()->cppDocument();
@@ -161,113 +156,12 @@ private:
} }
}; };
#ifdef WITH_TESTS
using namespace Tests;
class ConvertToMetaMethodCallTest : public QObject
{
Q_OBJECT
private slots:
void test_data()
{
QTest::addColumn<QByteArray>("input");
QTest::addColumn<QByteArray>("expected");
// ^ marks the cursor locations.
// $ marks the replacement regions.
// The quoted string in the comment is the data tag.
// The rest of the comment is the replacement string.
const QByteArray allCases = R"(
class C {
public:
C() {
$this->^aSignal()$; // "signal from region on pointer to object" QMetaObject::invokeMethod(this, "aSignal")
C c;
$c.^aSignal()$; // "signal from region on object value" QMetaObject::invokeMethod(&c, "aSignal")
$(new C)->^aSignal()$; // "signal from region on expression" QMetaObject::invokeMethod((new C), "aSignal")
$emit this->^aSignal()$; // "signal from region, with emit" QMetaObject::invokeMethod(this, "aSignal")
$Q_EMIT this->^aSignal()$; // "signal from region, with Q_EMIT" QMetaObject::invokeMethod(this, "aSignal")
$this->^aSlot()$; // "slot from region" QMetaObject::invokeMethod(this, "aSlot")
$this->^noArgs()$; // "Q_SIGNAL, no arguments" QMetaObject::invokeMethod(this, "noArgs")
$this->^oneArg(0)$; // "Q_SLOT, one argument" QMetaObject::invokeMethod(this, "oneArg", Q_ARG(int, 0))
$this->^twoArgs(0, c)$; // "Q_INVOKABLE, two arguments" QMetaObject::invokeMethod(this, "twoArgs", Q_ARG(int, 0), Q_ARG(C, c))
this->^notInvokable(); // "not invokable"
}
signals:
void aSignal();
private slots:
void aSlot();
private:
Q_SIGNAL void noArgs();
Q_SLOT void oneArg(int index);
Q_INVOKABLE void twoArgs(int index, const C &value);
void notInvokable();
};
)";
qsizetype nextCursor = allCases.indexOf('^');
while (nextCursor != -1) {
const int commentStart = allCases.indexOf("//", nextCursor);
QVERIFY(commentStart != -1);
const int tagStart = allCases.indexOf('"', commentStart + 2);
QVERIFY(tagStart != -1);
const int tagEnd = allCases.indexOf('"', tagStart + 1);
QVERIFY(tagEnd != -1);
QByteArray input = allCases;
QByteArray output = allCases;
input.replace(nextCursor, 1, "@");
const QByteArray tag = allCases.mid(tagStart + 1, tagEnd - tagStart - 1);
const int prevNewline = allCases.lastIndexOf('\n', nextCursor);
const int regionStart = allCases.lastIndexOf('$', nextCursor);
bool hasReplacement = false;
if (regionStart != -1 && regionStart > prevNewline) {
const int regionEnd = allCases.indexOf('$', regionStart + 1);
QVERIFY(regionEnd != -1);
const int nextNewline = allCases.indexOf('\n', tagEnd);
QVERIFY(nextNewline != -1);
const QByteArray replacement
= allCases.mid(tagEnd + 1, nextNewline - tagEnd - 1).trimmed();
output.replace(regionStart, regionEnd - regionStart, replacement);
hasReplacement = true;
}
static const auto matcher = [](char c) { return c == '^' || c == '$'; };
input.removeIf(matcher);
if (hasReplacement) {
output.removeIf(matcher);
output.prepend("#include <QMetaObject>\n\n");
} else {
output.clear();
}
QTest::newRow(tag.data()) << input << output;
nextCursor = allCases.indexOf('^', nextCursor + 1);
}
}
void test()
{
QFETCH(QByteArray, input);
QFETCH(QByteArray, expected);
ConvertToMetaMethodCall factory;
QuickFixOperationTest({CppTestDocument::create("file.cpp", input, expected)}, &factory);
}
};
QObject *ConvertToMetaMethodCall::createTest() { return new ConvertToMetaMethodCallTest; }
#endif // WITH_TESTS
} // namespace } // namespace
void registerConvertToMetaMethodCallQuickfix() void registerConvertToMetaMethodCallQuickfix()
{ {
CppQuickFixFactory::registerFactory<ConvertToMetaMethodCall>(); CppQuickFixFactory::registerFactoryWithStandardTest<ConvertToMetaMethodCall>(
"ConvertToMetaMethodCallTest");
} }
} // namespace CppEditor::Internal } // namespace CppEditor::Internal
#ifdef WITH_TESTS
#include <converttometamethodcall.moc>
#endif

View File

@@ -0,0 +1,11 @@
#include <QMetaObject>
class C {
public:
C() {
QMetaObject::invokeMethod(this, "aSignal");
}
signals:
void aSignal();
};

View File

@@ -0,0 +1,9 @@
class C {
public:
C() {
Q_EMIT this->@aSignal();
}
signals:
void aSignal();
};

View File

@@ -0,0 +1,12 @@
#include <QMetaObject>
class C {
public:
C() {
C c;
QMetaObject::invokeMethod(this, "twoArgs", Q_ARG(int, 0), Q_ARG(C, c));
}
private:
Q_INVOKABLE void twoArgs(int index, const C &value);
};

View File

@@ -0,0 +1,10 @@
class C {
public:
C() {
C c;
this->@twoArgs(0, c);
}
private:
Q_INVOKABLE void twoArgs(int index, const C &value);
};

View File

@@ -0,0 +1,12 @@
#include <QMetaObject>
class C {
public:
C() {
C c;
QMetaObject::invokeMethod(this, "noArgs");
}
private:
Q_SIGNAL void noArgs();
};

View File

@@ -0,0 +1,10 @@
class C {
public:
C() {
C c;
this->@noArgs();
}
private:
Q_SIGNAL void noArgs();
};

View File

@@ -0,0 +1,11 @@
#include <QMetaObject>
class C {
public:
C() {
QMetaObject::invokeMethod(this, "oneArg", Q_ARG(int, 0));
}
private:
Q_SLOT void oneArg(int index);
};

View File

@@ -0,0 +1,9 @@
class C {
public:
C() {
this->@oneArg(0);
}
private:
Q_SLOT void oneArg(int index);
};

View File

@@ -0,0 +1,11 @@
#include <QMetaObject>
class C {
public:
C() {
QMetaObject::invokeMethod(this, "aSignal");
}
signals:
void aSignal();
};

View File

@@ -0,0 +1,9 @@
class C {
public:
C() {
emit this->@aSignal();
}
signals:
void aSignal();
};

View File

@@ -0,0 +1,11 @@
#include <QMetaObject>
class C {
public:
C() {
QMetaObject::invokeMethod((new C), "aSignal");
}
signals:
void aSignal();
};

View File

@@ -0,0 +1,9 @@
class C {
public:
C() {
(new C)->@aSignal();
}
signals:
void aSignal();
};

View File

@@ -0,0 +1,9 @@
class C {
public:
C() {
this->@notInvokable();
}
private:
void notInvokable();
};

View File

@@ -0,0 +1,12 @@
#include <QMetaObject>
class C {
public:
C() {
C c;
QMetaObject::invokeMethod(&c, "aSignal");
}
signals:
void aSignal();
};

View File

@@ -0,0 +1,10 @@
class C {
public:
C() {
C c;
c.@aSignal();
}
signals:
void aSignal();
};

View File

@@ -0,0 +1,11 @@
#include <QMetaObject>
class C {
public:
C() {
QMetaObject::invokeMethod(this, "aSignal");
}
signals:
void aSignal();
};

View File

@@ -0,0 +1,9 @@
class C {
public:
C() {
this->@aSignal();
}
signals:
void aSignal();
};

View File

@@ -0,0 +1,11 @@
#include <QMetaObject>
class C {
public:
C() {
QMetaObject::invokeMethod(this, "aSlot");
}
private slots:
void aSlot();
};

View File

@@ -0,0 +1,9 @@
class C {
public:
C() {
this->@aSlot();
}
private slots:
void aSlot();
};