aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorFawzi Mohamed <fawzi.mohamed@digia.com>2014-04-09 15:42:06 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-04-18 07:39:38 +0200
commit007683512faa65c0d575bf12b9b1a3251c03d857 (patch)
treec9ed210bb558c168a7cda7a4724c5bf213378fbe /tools
parent5772da7e911832e71634322345948b0c98d397bf (diff)
qmlplugindump: correctly merge composite types
When hiding part of the hierarchy during the merging of composite types properties/methods/signals that are hidden should not be dumped twice. Task-number: QTBUG-38354 Change-Id: I328cf25dd5a70e1c0fce017e8ae572e8a9e56245 Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com> Reviewed-by: Alan Alpert <aalpert@blackberry.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/qmlplugindump/main.cpp125
1 files changed, 77 insertions, 48 deletions
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index 8babaecc8b..bc55c40434 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -317,6 +317,29 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
return metas;
}
+class KnownAttributes {
+ QHash<QByteArray, int> m_properties;
+ QHash<QByteArray, QHash<int, int> > m_methods;
+public:
+ bool knownMethod(const QByteArray &name, int nArgs, int revision)
+ {
+ if (m_methods.contains(name)) {
+ QHash<int, int> overloads = m_methods.value(name);
+ if (overloads.contains(nArgs) && overloads.value(nArgs) <= revision)
+ return true;
+ }
+ m_methods[name][nArgs] = revision;
+ return false;
+ }
+
+ bool knownProperty(const QByteArray &name, int revision)
+ {
+ if (m_properties.contains(name) && m_properties.value(name) <= revision)
+ return true;
+ m_properties[name] = revision;
+ return false;
+ }
+};
class Dumper
{
@@ -350,12 +373,15 @@ public:
return exportString;
}
- void writeMetaContent(const QMetaObject *meta)
+ void writeMetaContent(const QMetaObject *meta, KnownAttributes *knownAttributes = 0)
{
QSet<QString> implicitSignals;
for (int index = meta->propertyOffset(); index < meta->propertyCount(); ++index) {
const QMetaProperty &property = meta->property(index);
- dump(property);
+ dump(property, knownAttributes);
+ if (knownAttributes)
+ knownAttributes->knownMethod(QByteArray(property.name()).append("Changed"),
+ 0, property.revision());
implicitSignals.insert(QString("%1Changed").arg(QString::fromUtf8(property.name())));
}
@@ -368,38 +394,52 @@ public:
|| signature == QByteArrayLiteral("destroyed()")
|| signature == QByteArrayLiteral("deleteLater()"))
continue;
- dump(method, implicitSignals);
+ dump(method, implicitSignals, knownAttributes);
}
// and add toString(), destroy() and destroy(int)
- qml->writeStartObject(QLatin1String("Method"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("toString")));
- qml->writeEndObject();
- qml->writeStartObject(QLatin1String("Method"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy")));
- qml->writeEndObject();
- qml->writeStartObject(QLatin1String("Method"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy")));
- qml->writeStartObject(QLatin1String("Parameter"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("delay")));
- qml->writeScriptBinding(QLatin1String("type"), enquote(QLatin1String("int")));
- qml->writeEndObject();
- qml->writeEndObject();
+ if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("toString"), 0, 0)) {
+ qml->writeStartObject(QLatin1String("Method"));
+ qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("toString")));
+ qml->writeEndObject();
+ }
+ if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("destroy"), 0, 0)) {
+ qml->writeStartObject(QLatin1String("Method"));
+ qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy")));
+ qml->writeEndObject();
+ }
+ if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("destroy"), 1, 0)) {
+ qml->writeStartObject(QLatin1String("Method"));
+ qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy")));
+ qml->writeStartObject(QLatin1String("Parameter"));
+ qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("delay")));
+ qml->writeScriptBinding(QLatin1String("type"), enquote(QLatin1String("int")));
+ qml->writeEndObject();
+ qml->writeEndObject();
+ }
} else {
for (int index = meta->methodOffset(); index < meta->methodCount(); ++index)
- dump(meta->method(index), implicitSignals);
+ dump(meta->method(index), implicitSignals, knownAttributes);
}
}
- QString getPrototypeNameForCompositeType(const QMetaObject *metaObject, QSet<QByteArray> &defaultReachableNames)
+ QString getPrototypeNameForCompositeType(const QMetaObject *metaObject, QSet<QByteArray> &defaultReachableNames,
+ QList<const QMetaObject *> *objectsToMerge)
{
QString prototypeName;
if (!defaultReachableNames.contains(metaObject->className())) {
+ // dynamic meta objects can break things badly
+ // but extended types are usually fine
+ const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate *>(metaObject->d.data);
+ if (!(mop->flags & DynamicMetaObject) && objectsToMerge
+ && !objectsToMerge->contains(metaObject))
+ objectsToMerge->append(metaObject);
const QMetaObject *superMetaObject = metaObject->superClass();
if (!superMetaObject)
prototypeName = "QObject";
else
- prototypeName = getPrototypeNameForCompositeType(superMetaObject, defaultReachableNames);
+ prototypeName = getPrototypeNameForCompositeType(
+ superMetaObject, defaultReachableNames, objectsToMerge);
} else {
prototypeName = convertToId(metaObject->className());
}
@@ -418,8 +458,11 @@ public:
const QMetaObject *mainMeta = object->metaObject();
+ QList<const QMetaObject *> objectsToMerge;
+ KnownAttributes knownAttributes;
// Get C++ base class name for the composite type
- QString prototypeName = getPrototypeNameForCompositeType(mainMeta, defaultReachableNames);
+ QString prototypeName = getPrototypeNameForCompositeType(mainMeta, defaultReachableNames,
+ &objectsToMerge);
qml->writeScriptBinding(QLatin1String("prototype"), enquote(prototypeName));
QString qmlTyName = compositeType->qmlTypeName();
@@ -443,25 +486,8 @@ public:
}
}
- QSet<const QMetaObject *> metas;
- QSet<const QMetaObject *> candidatesComposite;
- collectReachableMetaObjects(mainMeta, &candidatesComposite);
-
- // Also eliminate meta objects with the same classname.
- // This is required because extended objects seem not to share
- // a single meta object instance.
- foreach (const QMetaObject *mo, candidatesComposite) {
- if (!defaultReachableNames.contains(mo->className()))
- metas.insert(mo);
- }
-
- // put the metaobjects into a map so they are always dumped in the same order
- QMap<QString, const QMetaObject *> nameToMeta;
- foreach (const QMetaObject *meta, metas)
- nameToMeta.insert(convertToId(meta), meta);
-
- foreach (const QMetaObject *meta, nameToMeta)
- writeMetaContent(meta);
+ foreach (const QMetaObject *meta, objectsToMerge)
+ writeMetaContent(meta, &knownAttributes);
qml->writeEndObject();
}
@@ -579,21 +605,23 @@ private:
qml->writeScriptBinding(QLatin1String("isPointer"), QLatin1String("true"));
}
- void dump(const QMetaProperty &prop)
+ void dump(const QMetaProperty &prop, KnownAttributes *knownAttributes = 0)
{
+ int revision = prop.revision();
+ QByteArray propName = prop.name();
+ if (knownAttributes && knownAttributes->knownProperty(propName, revision))
+ return;
qml->writeStartObject("Property");
-
qml->writeScriptBinding(QLatin1String("name"), enquote(QString::fromUtf8(prop.name())));
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 4))
- if (int revision = prop.revision())
+ if (revision)
qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision));
-#endif
writeTypeProperties(prop.typeName(), prop.isWritable());
qml->writeEndObject();
}
- void dump(const QMetaMethod &meth, const QSet<QString> &implicitSignals)
+ void dump(const QMetaMethod &meth, const QSet<QString> &implicitSignals,
+ KnownAttributes *knownAttributes = 0)
{
if (meth.methodType() == QMetaMethod::Signal) {
if (meth.access() != QMetaMethod::Public)
@@ -614,6 +642,9 @@ private:
return;
}
+ int revision = meth.revision();
+ if (knownAttributes && knownAttributes->knownMethod(name, meth.parameterNames().size(), revision))
+ return;
if (meth.methodType() == QMetaMethod::Signal)
qml->writeStartObject(QLatin1String("Signal"));
else
@@ -621,10 +652,8 @@ private:
qml->writeScriptBinding(QLatin1String("name"), enquote(name));
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 4))
- if (int revision = meth.revision())
+ if (revision)
qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision));
-#endif
if (typeName != QLatin1String("void"))
qml->writeScriptBinding(QLatin1String("type"), enquote(typeName));