qmlplugindump: Take care of 'void' types
[profile/ivi/qtdeclarative.git] / tools / qmlplugindump / main.cpp
index 169c0d7..b2e503c 100644 (file)
@@ -1,7 +1,6 @@
 /****************************************************************************
 **
 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
 ** Contact: http://www.qt-project.org/
 **
 ** This file is part of the tools applications of the Qt Toolkit.
 **
 **
 **
+**
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
 
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/private/qdeclarativemetatype_p.h>
-#include <QtDeclarative/private/qdeclarativeopenmetaobject_p.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/private/qqmlmetatype_p.h>
+#include <QtQml/private/qqmlopenmetaobject_p.h>
 #include <QtQuick/private/qquickevents_p_p.h>
 #include <QtQuick/private/qquickpincharea_p.h>
 
-#ifdef QT_WIDGETS_LIB
-#include <QtWidgets/QApplication>
-#endif
-
 #include <QtGui/QGuiApplication>
 #include <QtCore/QDir>
 #include <QtCore/QFileInfo>
@@ -84,8 +80,8 @@ void collectReachableMetaObjects(const QMetaObject *meta, QSet<const QMetaObject
     if (! meta || metas->contains(meta))
         return;
 
-    // dynamic meta objects can break things badly (like QDeclarative1VisualDataModelParts)
-    // but extended types are usually fine (like QDeclarative1GraphicsWidget)
+    // dynamic meta objects can break things badly
+    // but extended types are usually fine
     const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate *>(meta->d.data);
     if (extended || !(mop->flags & DynamicMetaObject))
         metas->insert(meta);
@@ -105,14 +101,14 @@ void collectReachableMetaObjects(QObject *object, QSet<const QMetaObject *> *met
 
     for (int index = 0; index < meta->propertyCount(); ++index) {
         QMetaProperty prop = meta->property(index);
-        if (QDeclarativeMetaType::isQObject(prop.userType())) {
+        if (QQmlMetaType::isQObject(prop.userType())) {
             if (verbose)
                 qDebug() << "  Processing property" << prop.name();
             currentProperty = QString("%1::%2").arg(meta->className(), prop.name());
 
             // if the property was not initialized during construction,
             // accessing a member of oo is going to cause a segmentation fault
-            QObject *oo = QDeclarativeMetaType::toQObject(prop.read(object));
+            QObject *oo = QQmlMetaType::toQObject(prop.read(object));
             if (oo && !metas->contains(oo->metaObject()))
                 collectReachableMetaObjects(oo, metas);
             currentProperty.clear();
@@ -120,7 +116,7 @@ void collectReachableMetaObjects(QObject *object, QSet<const QMetaObject *> *met
     }
 }
 
-void collectReachableMetaObjects(const QDeclarativeType *ty, QSet<const QMetaObject *> *metas)
+void collectReachableMetaObjects(const QQmlType *ty, QSet<const QMetaObject *> *metas)
 {
     collectReachableMetaObjects(ty->metaObject(), metas, ty->isExtendedType());
     if (ty->attachedPropertiesType())
@@ -137,10 +133,10 @@ public:
 };
 
 /* When we dump a QMetaObject, we want to list all the types it is exported as.
-   To do this, we need to find the QDeclarativeTypes associated with this
+   To do this, we need to find the QQmlTypes associated with this
    QMetaObject.
 */
-static QHash<QByteArray, QSet<const QDeclarativeType *> > qmlTypesByCppName;
+static QHash<QByteArray, QSet<const QQmlType *> > qmlTypesByCppName;
 
 static QHash<QByteArray, QByteArray> cppToId;
 
@@ -181,23 +177,13 @@ QByteArray convertToId(const QMetaObject *mo)
     return className;
 }
 
-/* All exported module APIs are collected into this list */
-class ModuleApi {
-public:
-    QString uri;
-    int majorVersion;
-    int minorVersion;
-    QByteArray objectId;
-};
-QList<ModuleApi> moduleApis;
-
-QSet<const QMetaObject *> collectReachableMetaObjects(QDeclarativeEngine *engine, const QList<QDeclarativeType *> &skip = QList<QDeclarativeType *>())
+QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const QList<QQmlType *> &skip = QList<QQmlType *>())
 {
     QSet<const QMetaObject *> metas;
     metas.insert(FriendlyQObject::qtMeta());
 
     QHash<QByteArray, QSet<QByteArray> > extensions;
-    foreach (const QDeclarativeType *ty, QDeclarativeMetaType::qmlTypes()) {
+    foreach (const QQmlType *ty, QQmlMetaType::qmlTypes()) {
         qmlTypesByCppName[ty->metaObject()->className()].insert(ty);
         if (ty->isExtendedType()) {
             extensions[ty->typeName()].insert(ty->metaObject()->className());
@@ -210,18 +196,18 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QDeclarativeEngine *engine
     // Example: QDeclarativeGraphicsWidget overrides the QtQuick/QGraphicsWidget export
     //          of QGraphicsWidget.
     foreach (const QByteArray &baseCpp, extensions.keys()) {
-        QSet<const QDeclarativeType *> baseExports = qmlTypesByCppName.value(baseCpp);
+        QSet<const QQmlType *> baseExports = qmlTypesByCppName.value(baseCpp);
 
         const QSet<QByteArray> extensionCppNames = extensions.value(baseCpp);
         foreach (const QByteArray &extensionCppName, extensionCppNames) {
-            const QSet<const QDeclarativeType *> extensionExports = qmlTypesByCppName.value(extensionCppName);
+            const QSet<const QQmlType *> extensionExports = qmlTypesByCppName.value(extensionCppName);
 
             // remove extension exports from base imports
-            // unfortunately the QDeclarativeType pointers don't match, so can't use QSet::substract
-            QSet<const QDeclarativeType *> newBaseExports;
-            foreach (const QDeclarativeType *baseExport, baseExports) {
+            // unfortunately the QQmlType pointers don't match, so can't use QSet::substract
+            QSet<const QQmlType *> newBaseExports;
+            foreach (const QQmlType *baseExport, baseExports) {
                 bool match = false;
-                foreach (const QDeclarativeType *extensionExport, extensionExports) {
+                foreach (const QQmlType *extensionExport, extensionExports) {
                     if (baseExport->qmlTypeName() == extensionExport->qmlTypeName()
                             && baseExport->majorVersion() == extensionExport->majorVersion()
                             && baseExport->minorVersion() == extensionExport->minorVersion()) {
@@ -239,14 +225,14 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QDeclarativeEngine *engine
 
     // find even more QMetaObjects by instantiating QML types and running
     // over the instances
-    foreach (QDeclarativeType *ty, QDeclarativeMetaType::qmlTypes()) {
+    foreach (QQmlType *ty, QQmlMetaType::qmlTypes()) {
         if (skip.contains(ty))
             continue;
         if (ty->isExtendedType())
             continue;
         if (!ty->isCreatable())
             continue;
-        if (ty->typeName() == "QDeclarativeComponent")
+        if (ty->typeName() == "QQmlComponent")
             continue;
 
         QString tyName = ty->qmlTypeName();
@@ -255,7 +241,22 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QDeclarativeEngine *engine
             continue;
 
         inObjectInstantiation = tyName;
-        QObject *object = ty->create();
+        QObject *object = 0;
+
+        if (ty->isSingleton()) {
+            QQmlType::SingletonInstanceInfo *siinfo = ty->singletonInstanceInfo();
+            if (siinfo->qobjectCallback) {
+                siinfo->init(engine);
+                collectReachableMetaObjects(object, &metas);
+                object = siinfo->qobjectApi(engine);
+            } else {
+                inObjectInstantiation.clear();
+                continue; // we don't handle QJSValue singleton types.
+            }
+        } else {
+            ty->create();
+        }
+
         inObjectInstantiation.clear();
 
         if (object)
@@ -264,33 +265,6 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QDeclarativeEngine *engine
             qWarning() << "Could not create" << tyName;
     }
 
-    // extract exported module api
-    QHashIterator<QString, QList<QDeclarativeMetaType::ModuleApi> > moduleApiIt(QDeclarativeMetaType::moduleApis());
-    while (moduleApiIt.hasNext()) {
-        moduleApiIt.next();
-        foreach (const QDeclarativeMetaType::ModuleApi &api, moduleApiIt.value()) {
-            ModuleApi moduleApi;
-            moduleApi.uri = moduleApiIt.key();
-            moduleApi.majorVersion = api.major;
-            moduleApi.minorVersion = api.minor;
-
-            if (api.qobject) {
-                if (QObject *object = (*api.qobject)(engine, engine)) {
-                    collectReachableMetaObjects(object, &metas);
-                    moduleApi.objectId = convertToId(object->metaObject()->className());
-                    delete object;
-                }
-            } else if (api.script) {
-                qWarning() << "Can't dump the module api in " << moduleApi.uri << ". QJSValue based module API is not supported.";
-//                QJSValue value = (*api.script)(engine, engine);
-//                IdToObjectHash jsObjects;
-//                collectReachableJSObjects(value, &jsObjects, &metas);
-            }
-
-            moduleApis += moduleApi;
-        }
-    }
-
     return metas;
 }
 
@@ -326,11 +300,11 @@ public:
         if (meta->superClass())
             qml->writeScriptBinding(QLatin1String("prototype"), enquote(convertToId(meta->superClass())));
 
-        QSet<const QDeclarativeType *> qmlTypes = qmlTypesByCppName.value(meta->className());
+        QSet<const QQmlType *> qmlTypes = qmlTypesByCppName.value(meta->className());
         if (!qmlTypes.isEmpty()) {
-            QHash<QString, const QDeclarativeType *> exports;
+            QHash<QString, const QQmlType *> exports;
 
-            foreach (const QDeclarativeType *qmlTy, qmlTypes) {
+            foreach (const QQmlType *qmlTy, qmlTypes) {
                 QString qmlTyName = qmlTy->qmlTypeName();
                 if (qmlTyName.startsWith(relocatableModuleUri + QLatin1Char('/'))) {
                     qmlTyName.remove(0, relocatableModuleUri.size() + 1);
@@ -390,10 +364,10 @@ public:
             // for QObject, hide deleteLater() and onDestroyed
             for (int index = meta->methodOffset(); index < meta->methodCount(); ++index) {
                 QMetaMethod method = meta->method(index);
-                const char *signature(method.signature());
-                if (signature == QLatin1String("destroyed(QObject*)")
-                        || signature == QLatin1String("destroyed()")
-                        || signature == QLatin1String("deleteLater()"))
+                QByteArray signature = method.methodSignature();
+                if (signature == QByteArrayLiteral("destroyed(QObject*)")
+                        || signature == QByteArrayLiteral("destroyed()")
+                        || signature == QByteArrayLiteral("deleteLater()"))
                     continue;
                 dump(method, implicitSignals);
             }
@@ -420,23 +394,11 @@ public:
         qml->writeEndObject();
     }
 
-    void dump(const ModuleApi &api)
-    {
-        qml->writeStartObject(QLatin1String("ModuleApi"));
-        if (api.uri != relocatableModuleUri)
-            qml->writeScriptBinding(QLatin1String("uri"), enquote(api.uri));
-        qml->writeScriptBinding(QLatin1String("version"), QString("%1.%2").arg(
-                                    QString::number(api.majorVersion),
-                                    QString::number(api.minorVersion)));
-        qml->writeScriptBinding(QLatin1String("name"), enquote(api.objectId));
-        qml->writeEndObject();
-    }
-
     void writeEasingCurve()
     {
         qml->writeStartObject(QLatin1String("Component"));
         qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("QEasingCurve")));
-        qml->writeScriptBinding(QLatin1String("prototype"), enquote(QLatin1String("QDeclarativeEasingValueType")));
+        qml->writeScriptBinding(QLatin1String("prototype"), enquote(QLatin1String("QQmlEasingValueType")));
         qml->writeEndObject();
     }
 
@@ -451,7 +413,7 @@ private:
     */
     static void removePointerAndList(QByteArray *typeName, bool *isList, bool *isPointer)
     {
-        static QByteArray declListPrefix = "QDeclarativeListProperty<";
+        static QByteArray declListPrefix = "QQmlListProperty<";
 
         if (typeName->endsWith('*')) {
             *isPointer = true;
@@ -504,19 +466,14 @@ private:
             return; // nothing to do.
         }
 
-        QByteArray name = meth.signature();
-        int lparenIndex = name.indexOf('(');
-        if (lparenIndex == -1) {
-            return; // invalid signature
-        }
-        name = name.left(lparenIndex);
+        QByteArray name = meth.name();
         const QString typeName = convertToId(meth.typeName());
 
         if (implicitSignals.contains(name)
                 && !meth.revision()
                 && meth.methodType() == QMetaMethod::Signal
                 && meth.parameterNames().isEmpty()
-                && typeName.isEmpty()) {
+                && typeName != QLatin1String("void")) {
             // don't mention implicit signals
             return;
         }
@@ -533,7 +490,7 @@ private:
             qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision));
 #endif
 
-        if (! typeName.isEmpty())
+        if (typeName != QLatin1String("void"))
             qml->writeScriptBinding(QLatin1String("type"), enquote(typeName));
 
         for (int i = 0; i < meth.parameterTypes().size(); ++i) {
@@ -611,11 +568,7 @@ int main(int argc, char *argv[])
     QtSimulatorPrivate::SimulatorConnection::createStubInstance();
 #endif
 
-#ifdef QT_WIDGETS_LIB
-    QApplication app(argc, argv);
-#else
     QGuiApplication app(argc, argv);
-#endif
     const QStringList args = app.arguments();
     const QString appName = QFileInfo(app.applicationFilePath()).baseName();
     if (args.size() < 2) {
@@ -678,7 +631,7 @@ int main(int argc, char *argv[])
         }
     }
 
-    QDeclarativeEngine engine;
+    QQmlEngine engine;
     if (!pluginImportPath.isEmpty()) {
         QDir cur = QDir::current();
         cur.cd(pluginImportPath);
@@ -687,29 +640,14 @@ int main(int argc, char *argv[])
         engine.addImportPath(pluginImportPath);
     }
 
-#ifdef QT_WIDGETS_LIB
-    // load the QtQuick 1 plugin
-    {
-        QByteArray code("import QtQuick 1.0\nQtObject {}");
-        QDeclarativeComponent c(&engine);
-        c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/loadqtquick1.qml"));
-        c.create();
-        if (!c.errors().isEmpty()) {
-            foreach (const QDeclarativeError &error, c.errors())
-                qWarning() << error.toString();
-            return EXIT_IMPORTERROR;
-        }
-    }
-#endif
-
     // load the QtQuick 2 plugin
     {
         QByteArray code("import QtQuick 2.0\nQtObject {}");
-        QDeclarativeComponent c(&engine);
+        QQmlComponent c(&engine);
         c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/loadqtquick2.qml"));
         c.create();
         if (!c.errors().isEmpty()) {
-            foreach (const QDeclarativeError &error, c.errors())
+            foreach (const QQmlError &error, c.errors())
                 qWarning() << error.toString();
             return EXIT_IMPORTERROR;
         }
@@ -717,7 +655,7 @@ int main(int argc, char *argv[])
 
     // find all QMetaObjects reachable from the builtin module
     QSet<const QMetaObject *> defaultReachable = collectReachableMetaObjects(&engine);
-    QList<QDeclarativeType *> defaultTypes = QDeclarativeMetaType::qmlTypes();
+    QList<QQmlType *> defaultTypes = QQmlMetaType::qmlTypes();
 
     // add some otherwise unreachable QMetaObjects
     defaultReachable.insert(&QQuickMouseEvent::staticMetaObject);
@@ -731,7 +669,7 @@ int main(int argc, char *argv[])
     } else {
         // find a valid QtQuick import
         QByteArray importCode;
-        QDeclarativeType *qtObjectType = QDeclarativeMetaType::qmlType(&QObject::staticMetaObject);
+        QQmlType *qtObjectType = QQmlMetaType::qmlType(&QObject::staticMetaObject);
         if (!qtObjectType) {
             qWarning() << "Could not find QtObject type";
             importCode = QByteArray("import QtQuick 2.0\n");
@@ -745,10 +683,10 @@ int main(int argc, char *argv[])
 
         // find all QMetaObjects reachable when the specified module is imported
         if (action != Path) {
-            importCode += QString("import %0 %1\n").arg(pluginImportUri, pluginImportVersion).toAscii();
+            importCode += QString("import %0 %1\n").arg(pluginImportUri, pluginImportVersion).toLatin1();
         } else {
             // pluginImportVersion can be empty
-            importCode += QString("import \".\" %2\n").arg(pluginImportVersion).toAscii();
+            importCode += QString("import \".\" %2\n").arg(pluginImportVersion).toLatin1();
         }
 
         // create a component with these imports to make sure the imports are valid
@@ -756,12 +694,12 @@ int main(int argc, char *argv[])
         {
             QByteArray code = importCode;
             code += "QtObject {}";
-            QDeclarativeComponent c(&engine);
+            QQmlComponent c(&engine);
 
             c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/typelist.qml"));
             c.create();
             if (!c.errors().isEmpty()) {
-                foreach (const QDeclarativeError &error, c.errors())
+                foreach (const QQmlError &error, c.errors())
                     qWarning() << error.toString();
                 return EXIT_IMPORTERROR;
             }
@@ -784,7 +722,7 @@ int main(int argc, char *argv[])
 
     // setup static rewrites of type names
     cppToId.insert("QString", "string");
-    cppToId.insert("QDeclarativeEasingValueType::Type", "Type");
+    cppToId.insert("QQmlEasingValueType::Type", "Type");
 
     // start dumping data
     QByteArray bytes;
@@ -792,10 +730,12 @@ int main(int argc, char *argv[])
 
     qml.writeStartDocument();
     qml.writeLibraryImport(QLatin1String("QtQuick.tooling"), 1, 1);
-    qml.write("\n"
+    qml.write(QString("\n"
               "// This file describes the plugin-supplied types contained in the library.\n"
               "// It is used for QML tooling purposes only.\n"
-              "\n");
+              "//\n"
+              "// This file was auto-generated with the command '%1'.\n"
+              "\n").arg(args.join(QLatin1String(" "))));
     qml.writeStartObject("Module");
 
     // put the metaobjects into a map so they are always dumped in the same order
@@ -810,16 +750,11 @@ int main(int argc, char *argv[])
         dumper.dump(meta);
     }
 
-    // define QEasingCurve as an extension of QDeclarativeEasingValueType, this way
+    // define QEasingCurve as an extension of QQmlEasingValueType, this way
     // properties using the QEasingCurve type get useful type information.
     if (pluginImportUri.isEmpty())
         dumper.writeEasingCurve();
 
-    // write out module api elements
-    foreach (const ModuleApi &api, moduleApis) {
-        dumper.dump(api);
-    }
-
     qml.writeEndObject();
     qml.writeEndDocument();