QMetaObjectPrivate: Add firstMethod

QMetaObject::indexfOfMethod returns the method corresponding to a
specific signature. In QML, we however only want any of the methods with
a given name (and do overload resolution at a later point).
For this usecase this patch introduces the internal
QMetaObject::firstMethod function.

Change-Id: Ie3820354edffb273c4cbe1399201a955ebe79344
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Fabian Kosmale 2020-11-30 14:53:38 +01:00
parent 405244fe30
commit 5082b84b38
3 changed files with 58 additions and 0 deletions

View File

@ -590,6 +590,24 @@ bool QMetaObjectPrivate::methodMatch(const QMetaObject *m, const QMetaMethod &me
return true;
}
/*!
\internal
Returns the first method with name \a name found in \a baseObject
*/
QMetaMethod QMetaObjectPrivate::firstMethod(const QMetaObject *baseObject, QByteArrayView name)
{
for (const QMetaObject *currentObject = baseObject; currentObject; currentObject = currentObject->superClass()) {
const int start = priv(currentObject->d.data)->methodCount - 1;
const int end = 0;
for (int i = start; i >= end; --i) {
auto candidate = QMetaMethod::fromRelativeMethodIndex(currentObject, i);
if (name == candidate.name())
return candidate;
}
}
return QMetaMethod{};
}
/**
* \internal
* helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within

View File

@ -253,6 +253,7 @@ struct QMetaObjectPrivate
static bool methodMatch(const QMetaObject *m, const QMetaMethod &method,
const QByteArray &name, int argc,
const QArgumentType *types);
Q_CORE_EXPORT static QMetaMethod firstMethod(const QMetaObject *baseObject, QByteArrayView name);
};

View File

@ -321,6 +321,9 @@ private slots:
void indexOfMethod_data();
void indexOfMethod();
void firstMethod_data();
void firstMethod();
void indexOfMethodPMF();
void signalOffset_data();
@ -1700,6 +1703,42 @@ void tst_QMetaObject::indexOfMethod()
QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx);
}
class Base : public QObject {
Q_OBJECT
public slots:
int test() {return 0;}
int baseOnly() {return 0;}
};
class Derived : public Base {
Q_OBJECT
public slots:
int test() {return 1;}
};
void tst_QMetaObject::firstMethod_data()
{
QTest::addColumn<QByteArray>("name");
QTest::addColumn<QMetaMethod>("method");
const QMetaObject &derived = Derived::staticMetaObject;
const QMetaObject &base = Base::staticMetaObject;
QTest::newRow("own method") << QByteArray("test") << derived.method(derived.indexOfMethod("test()"));
QTest::newRow("parent method") << QByteArray("baseOnly") << derived.method(base.indexOfMethod("baseOnly()"));
QTest::newRow("invalid") << QByteArray("invalid") << QMetaMethod();
}
void tst_QMetaObject::firstMethod()
{
QFETCH(QByteArray, name);
QFETCH(QMetaMethod, method);
QMetaMethod firstMethod = QMetaObjectPrivate::firstMethod(&Derived::staticMetaObject, name);
QCOMPARE(firstMethod, method);
}
void tst_QMetaObject::indexOfMethodPMF()
{
#define INDEXOFMETHODPMF_HELPER(ObjectType, Name, Arguments) { \