Suggest candidates when non-existent method passed to invokeMethod().

QMetaObject::invokeMethod: No such method Object::someMethod(SomeType)

becomes:

QMetaObject::invokeMethod: No such method Object::someMethod(SomeType)
Candidates are:
    someMethod(SomeOtherType)
    someMethod(YetAnotherType)

Change-Id: I3566bca64423e2f8150d0d544fb4e35a5262b19e
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
Mitch Curtis 2014-06-11 11:15:59 +02:00
parent f3e86a8cc8
commit daa56f1b4e
2 changed files with 32 additions and 6 deletions

View File

@ -1338,6 +1338,27 @@ QByteArray QMetaObject::normalizedSignature(const char *method)
enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
/*!
Returns the signatures of all methods whose name matches \a nonExistentMember,
or an empty QByteArray if there are no matches.
*/
static inline QByteArray findMethodCandidates(const QMetaObject *metaObject, const char *nonExistentMember)
{
QByteArray candidateMessage;
// Prevent full string comparison in every iteration.
const QByteArray memberByteArray = nonExistentMember;
for (int i = 0; i < metaObject->methodCount(); ++i) {
const QMetaMethod method = metaObject->method(i);
if (method.name() == memberByteArray)
candidateMessage.append(" " + method.methodSignature() + '\n');
}
if (!candidateMessage.isEmpty()) {
candidateMessage.prepend("\nCandidates are:\n");
candidateMessage.chop(1);
}
return candidateMessage;
}
/*!
Invokes the \a member (a signal or a slot name) on the object \a
obj. Returns \c true if the member could be invoked. Returns \c false
@ -1455,8 +1476,9 @@ bool QMetaObject::invokeMethod(QObject *obj,
}
if (idx < 0 || idx >= meta->methodCount()) {
qWarning("QMetaObject::invokeMethod: No such method %s::%s",
meta->className(), sig.constData());
// This method doesn't belong to us; print out a nice warning with candidates.
qWarning("QMetaObject::invokeMethod: No such method %s::%s%s",
meta->className(), sig.constData(), findMethodCandidates(meta, member).constData());
return false;
}
QMetaMethod method = meta->method(idx);

View File

@ -561,9 +561,11 @@ void tst_QMetaObject::invokeMetaMember()
QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist"));
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)");
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Q_ARG(QString, "arg")));
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)");
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n"
"Candidates are:\n sl3(QString,QString,QString)");
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Q_ARG(QString, "arg")));
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)");
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)\n"
"Candidates are:\n sl1(QString)");
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(QString, "arg"), Q_ARG(QString, "arg"), Q_ARG(QString, "arg")));
//should not have changed since last test.
@ -747,9 +749,11 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember()
QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist", Qt::BlockingQueuedConnection));
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)");
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg")));
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)");
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n"
"Candidates are:\n sl3(QString,QString,QString)");
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg")));
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)");
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)\n"
"Candidates are:\n sl1(QString)");
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"), Q_ARG(QString, "arg"), Q_ARG(QString, "arg")));
//should not have changed since last test.