forked from qt-creator/qt-creator
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:
@@ -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()
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
2
src/tools/qml/qml.pro
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
TEMPLATE = subdirs
|
||||||
|
SUBDIRS += qmldump
|
@@ -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;
|
||||||
|
@@ -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)
|
||||||
|
@@ -1,2 +1,3 @@
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
win32:SUBDIRS = qtcdebugger
|
win32:SUBDIRS = qtcdebugger
|
||||||
|
SUBDIRS += qml
|
||||||
|
Reference in New Issue
Block a user