QmlJS: Get at types defined in plugins by running qmldump on them.

Task-number: QTCREATORBUG-1021
Reviewed-by: Roberto Raggi
This commit is contained in:
Christian Kamm
2010-06-01 15:10:20 +02:00
parent ea5ca79900
commit 822520c304
8 changed files with 114 additions and 43 deletions

View File

@@ -34,12 +34,14 @@
#include "parser/qmljsast_p.h" #include "parser/qmljsast_p.h"
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QString> #include <QtCore/QString>
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include <QtCore/QMetaObject> #include <QtCore/QMetaObject>
#include <QtCore/QMetaProperty> #include <QtCore/QMetaProperty>
#include <QtCore/QXmlStreamReader> #include <QtCore/QXmlStreamReader>
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtCore/QDebug> #include <QtCore/QDebug>
using namespace QmlJS::Interpreter; using namespace QmlJS::Interpreter;
@@ -334,6 +336,10 @@ public:
, _objects(0) , _objects(0)
{} {}
QmlXmlReader(const QByteArray &data)
: _xml(data)
{}
bool operator()(QMap<QString, FakeMetaObject *> *objects) { bool operator()(QMap<QString, FakeMetaObject *> *objects) {
Q_ASSERT(objects); Q_ASSERT(objects);
_objects = objects; _objects = objects;
@@ -774,7 +780,7 @@ const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const
const QString typeName = prop.typeName(); const QString typeName = prop.typeName();
// ### Verify type resolving. // ### Verify type resolving.
QmlObjectValue *objectValue = engine()->metaTypeSystem().staticTypeForImport(typeName); QmlObjectValue *objectValue = engine()->cppQmlTypes().typeForImport(typeName);
if (objectValue) if (objectValue)
return objectValue; return objectValue;
@@ -917,7 +923,10 @@ bool QmlObjectValue::hasChildInPackage() const
{ {
if (!packageName().isEmpty()) if (!packageName().isEmpty())
return true; return true;
foreach (const FakeMetaObject *other, MetaTypeSystem::_metaObjects) { QHashIterator<QString, FakeMetaObject *> it(CppQmlTypesLoader::instance()->objects);
while (it.hasNext()) {
it.next();
const FakeMetaObject *other = it.value();
if (other->packageName().isEmpty()) if (other->packageName().isEmpty())
continue; continue;
for (const FakeMetaObject *iter = other; iter; iter = iter->superClass()) { for (const FakeMetaObject *iter = other; iter; iter = iter->superClass()) {
@@ -1931,19 +1940,22 @@ const Value *Function::invoke(const Activation *activation) const
// typing environment // typing environment
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
QList<const FakeMetaObject *> MetaTypeSystem::_metaObjects; CppQmlTypesLoader *CppQmlTypesLoader::instance()
QStringList MetaTypeSystem::load(const QFileInfoList &xmlFiles)
{ {
QMap<QString, FakeMetaObject *> objects; static CppQmlTypesLoader _instance;
return &_instance;
}
QStringList CppQmlTypesLoader::load(const QFileInfoList &xmlFiles)
{
QMap<QString, FakeMetaObject *> newObjects;
QStringList errorMsgs; QStringList errorMsgs;
foreach (const QFileInfo &xmlFile, xmlFiles) { foreach (const QFileInfo &xmlFile, xmlFiles) {
QFile file(xmlFile.absoluteFilePath()); QFile file(xmlFile.absoluteFilePath());
if (file.open(QIODevice::ReadOnly)) { if (file.open(QIODevice::ReadOnly)) {
QmlXmlReader read(&file); QmlXmlReader read(&file);
if (!read(&objects)) { if (!read(&newObjects)) {
errorMsgs.append(read.errorMessage()); errorMsgs.append(read.errorMessage());
} }
file.close(); file.close();
@@ -1953,34 +1965,70 @@ QStringList MetaTypeSystem::load(const QFileInfoList &xmlFiles)
} }
} }
if (errorMsgs.isEmpty()) { if (errorMsgs.isEmpty())
qDeleteAll(_metaObjects); addObjects(newObjects);
_metaObjects.clear();
foreach (FakeMetaObject *obj, objects.values()) {
const QString superName = obj->superclassName();
if (! superName.isEmpty()) {
obj->setSuperclass(objects.value(superName, 0));
}
_metaObjects.append(obj);
}
}
return errorMsgs; return errorMsgs;
} }
void MetaTypeSystem::reload(Engine *interpreter) void CppQmlTypesLoader::loadPluginTypes(const QString &pluginPath)
{
QProcess *process = new QProcess(this);
connect(process, SIGNAL(finished(int)), SLOT(processDone(int)));
QDir qmldumpExecutable(QCoreApplication::applicationDirPath());
process->start(qmldumpExecutable.filePath("qmldump"), QStringList(pluginPath));
}
void CppQmlTypesLoader::processDone(int exitCode)
{
QMap<QString, FakeMetaObject *> newObjects;
QProcess *process = qobject_cast<QProcess *>(sender());
if (process && exitCode == 0) {
const QByteArray output = process->readAllStandardOutput();
QmlXmlReader read(output);
if (read(&newObjects))
addObjects(newObjects);
}
process->deleteLater();
}
void CppQmlTypesLoader::addObjects(QMap<QString, FakeMetaObject *> &newObjects)
{
QMapIterator<QString, FakeMetaObject *> it(newObjects);
while (it.hasNext()) {
it.next();
FakeMetaObject *obj = it.value();
//if (objects.contains(it.key()))
// qWarning() << "QmlJS::Interpreter::MetaTypeSystem: Found duplicate type" << it.key();
const QString superName = obj->superclassName();
if (! superName.isEmpty()) {
FakeMetaObject *superClass = objects.value(superName);
if (!superClass)
superClass = newObjects.value(superName);
if (superClass)
obj->setSuperclass(superClass);
//else
// qWarning() << "QmlJS::Interpreter::MetaTypeSystem: Can't find superclass" << superName << "for" << it.key();
}
objects.insert(it.key(), obj);
}
}
void CppQmlTypes::reload(Engine *interpreter)
{ {
QHash<const FakeMetaObject *, QmlObjectValue *> qmlObjects; QHash<const FakeMetaObject *, QmlObjectValue *> qmlObjects;
_importedTypes.clear(); _importedTypes.clear();
foreach (const FakeMetaObject *metaObject, _metaObjects) { foreach (const FakeMetaObject *metaObject, CppQmlTypesLoader::instance()->objects) {
QmlObjectValue *objectValue = new QmlObjectValue(metaObject, interpreter); QmlObjectValue *objectValue = new QmlObjectValue(metaObject, interpreter);
qmlObjects.insert(metaObject, objectValue); qmlObjects.insert(metaObject, objectValue);
_importedTypes[metaObject->packageName()].append(objectValue); _importedTypes[metaObject->packageName()].append(objectValue);
} }
foreach (const FakeMetaObject *metaObject, _metaObjects) { foreach (const FakeMetaObject *metaObject, CppQmlTypesLoader::instance()->objects) {
QmlObjectValue *objectValue = qmlObjects.value(metaObject); QmlObjectValue *objectValue = qmlObjects.value(metaObject);
if (!objectValue) if (!objectValue)
continue; continue;
@@ -1988,7 +2036,7 @@ void MetaTypeSystem::reload(Engine *interpreter)
} }
} }
QList<QmlObjectValue *> MetaTypeSystem::staticTypesForImport(const QString &packageName, int majorVersion, int minorVersion) const QList<QmlObjectValue *> CppQmlTypes::typesForImport(const QString &packageName, int majorVersion, int minorVersion) const
{ {
QMap<QString, QmlObjectValue *> objectValuesByName; QMap<QString, QmlObjectValue *> objectValuesByName;
@@ -2014,7 +2062,7 @@ QList<QmlObjectValue *> MetaTypeSystem::staticTypesForImport(const QString &pack
return objectValuesByName.values(); return objectValuesByName.values();
} }
QmlObjectValue *MetaTypeSystem::staticTypeForImport(const QString &qualifiedName) const QmlObjectValue *CppQmlTypes::typeForImport(const QString &qualifiedName) const
{ {
QString name = qualifiedName; QString name = qualifiedName;
QString packageName; QString packageName;
@@ -2045,7 +2093,7 @@ QmlObjectValue *MetaTypeSystem::staticTypeForImport(const QString &qualifiedName
return previousCandidate; return previousCandidate;
} }
bool MetaTypeSystem::hasPackage(const QString &package) const bool CppQmlTypes::hasPackage(const QString &package) const
{ {
return _importedTypes.contains(package); return _importedTypes.contains(package);
} }
@@ -2323,7 +2371,7 @@ Engine::Engine()
{ {
initializePrototypes(); initializePrototypes();
_metaTypeSystem.reload(this); _cppQmlTypes.reload(this);
} }
Engine::~Engine() Engine::~Engine()

View File

@@ -515,25 +515,38 @@ private:
// typing environment // typing environment
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class QMLJS_EXPORT MetaTypeSystem class QMLJS_EXPORT CppQmlTypesLoader : public QObject
{ {
static QList<const FakeMetaObject *> _metaObjects; Q_OBJECT
public: public:
/** \return an empty list when successful, error messages otherwise. */ static CppQmlTypesLoader *instance();
static QStringList load(const QFileInfoList &xmlFiles);
QHash<QString, FakeMetaObject *> objects;
/** \return an empty list when successful, error messages otherwise. */
QStringList load(const QFileInfoList &xmlFiles);
void loadPluginTypes(const QString &pluginPath);
private slots:
void processDone(int exitCode);
private:
void addObjects(QMap<QString, FakeMetaObject *> &newObjects);
};
class QMLJS_EXPORT CppQmlTypes
{
public:
void reload(Interpreter::Engine *interpreter); void reload(Interpreter::Engine *interpreter);
QList<Interpreter::QmlObjectValue *> staticTypesForImport(const QString &prefix, int majorVersion, int minorVersion) const; QList<Interpreter::QmlObjectValue *> typesForImport(const QString &prefix, int majorVersion, int minorVersion) const;
Interpreter::QmlObjectValue *staticTypeForImport(const QString &qualifiedName) const; Interpreter::QmlObjectValue *typeForImport(const QString &qualifiedName) const;
bool hasPackage(const QString &package) const; bool hasPackage(const QString &package) const;
private: private:
QHash<QString, QList<QmlObjectValue *> > _importedTypes; QHash<QString, QList<QmlObjectValue *> > _importedTypes;
friend class QmlObjectValue;
}; };
class ConvertToNumber: protected ValueVisitor // ECMAScript ToInt() class ConvertToNumber: protected ValueVisitor // ECMAScript ToInt()
@@ -683,8 +696,8 @@ public:
QString typeId(const Value *value); QString typeId(const Value *value);
// typing: // typing:
const MetaTypeSystem &metaTypeSystem() const const CppQmlTypes &cppQmlTypes() const
{ return _metaTypeSystem; } { return _cppQmlTypes; }
void registerValue(Value *value); // internal void registerValue(Value *value); // internal
@@ -732,7 +745,7 @@ private:
ConvertToObject _convertToObject; ConvertToObject _convertToObject;
TypeId _typeId; TypeId _typeId;
MetaTypeSystem _metaTypeSystem; CppQmlTypes _cppQmlTypes;
}; };

View File

@@ -136,7 +136,7 @@ void Link::populateImportedTypes(Interpreter::ObjectValue *typeEnv, Document::Pt
return; return;
// Add the implicitly available Script type // Add the implicitly available Script type
const ObjectValue *scriptValue = engine()->metaTypeSystem().staticTypeForImport("Script"); const ObjectValue *scriptValue = engine()->cppQmlTypes().typeForImport("Script");
if (scriptValue) if (scriptValue)
typeEnv->setProperty("Script", scriptValue); typeEnv->setProperty("Script", scriptValue);
@@ -270,8 +270,8 @@ void Link::importNonFile(Interpreter::ObjectValue *typeEnv, Document::Ptr doc, A
} }
// if the package is in the meta type system, use it // if the package is in the meta type system, use it
if (engine()->metaTypeSystem().hasPackage(packageName)) { if (engine()->cppQmlTypes().hasPackage(packageName)) {
foreach (QmlObjectValue *object, engine()->metaTypeSystem().staticTypesForImport(packageName, majorVersion, minorVersion)) { foreach (QmlObjectValue *object, engine()->cppQmlTypes().typesForImport(packageName, majorVersion, minorVersion)) {
namespaceObject->setProperty(object->className(), object); namespaceObject->setProperty(object->className(), object);
} }
return; return;

View File

@@ -85,7 +85,7 @@ void ModelManager::loadQmlTypeDescriptions()
QDir::Files, QDir::Files,
QDir::Name); QDir::Name);
const QStringList errors = Interpreter::MetaTypeSystem::load(xmlFiles); const QStringList errors = Interpreter::CppQmlTypesLoader::instance()->load(xmlFiles);
foreach (const QString &error, errors) foreach (const QString &error, errors)
qWarning() << qPrintable(error); qWarning() << qPrintable(error);
} }
@@ -194,6 +194,9 @@ void ModelManager::onLibraryInfoUpdated(const QString &path, const LibraryInfo &
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
if (!_snapshot.libraryInfo(path).isValid())
QmlJS::Interpreter::CppQmlTypesLoader::instance()->loadPluginTypes(path);
_snapshot.insertLibraryInfo(path, info); _snapshot.insertLibraryInfo(path, info);
} }

2
src/tools/qml/qml.pro Normal file
View File

@@ -0,0 +1,2 @@
TEMPLATE = subdirs
SUBDIRS += qmldump

View File

@@ -267,7 +267,7 @@ int main(int argc, char *argv[])
importCode += "import Qt.labs.folderlistmodel 4.7;\n"; importCode += "import Qt.labs.folderlistmodel 4.7;\n";
importCode += "import org.webkit 1.0;\n"; importCode += "import org.webkit 1.0;\n";
if (!pluginImportName.isEmpty()) if (!pluginImportName.isEmpty())
importCode += QString("import %0 1.0;\n").arg(pluginImportName); importCode += QString("import %0 1.0;\n").arg(pluginImportName).toAscii();
{ {
QByteArray code = importCode; QByteArray code = importCode;

View File

@@ -12,3 +12,7 @@ CONFIG -= app_bundle
TEMPLATE = app TEMPLATE = app
SOURCES += main.cpp SOURCES += main.cpp
include(../../../../qtcreator.pri)
DESTDIR = $$IDE_APP_PATH
include(../../../rpath.pri)

View File

@@ -1,2 +1,3 @@
TEMPLATE = subdirs TEMPLATE = subdirs
win32:SUBDIRS = qtcdebugger win32:SUBDIRS = qtcdebugger
SUBDIRS += qml