diff --git a/src/libs/cplusplus/ModelManagerInterface.h b/src/libs/cplusplus/ModelManagerInterface.h index 943d32000bee36aeb8bbc194908c886b986f79e8..17724f55e94caf0630b56225f4f1a4975744aafc 100644 --- a/src/libs/cplusplus/ModelManagerInterface.h +++ b/src/libs/cplusplus/ModelManagerInterface.h @@ -147,7 +147,7 @@ public: virtual void findMacroUsages(const CPlusPlus::Macro ¯o) = 0; - virtual QList<LanguageUtils::FakeMetaObject::ConstPtr> exportedQmlObjects() const = 0; + virtual QList<LanguageUtils::FakeMetaObject::ConstPtr> exportedQmlObjects(const CPlusPlus::Document::Ptr &doc) const = 0; Q_SIGNALS: void documentUpdated(CPlusPlus::Document::Ptr doc); diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index fb2fe5a589e13fded44ecd26078484ea8a8a0e3d..910b2f543984e6f54f2eb1b3179b158b6dcf142f 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -1944,7 +1944,6 @@ const Value *Function::invoke(const Activation *activation) const //////////////////////////////////////////////////////////////////////////////// QList<FakeMetaObject::ConstPtr> CppQmlTypesLoader::builtinObjects; -QList<FakeMetaObject::ConstPtr> CppQmlTypesLoader::cppObjects; QStringList CppQmlTypesLoader::load(const QFileInfoList &xmlFiles) { @@ -2438,7 +2437,6 @@ Engine::Engine() initializePrototypes(); _cppQmlTypes.load(this, CppQmlTypesLoader::builtinObjects); - _cppQmlTypes.load(this, CppQmlTypesLoader::cppObjects); // the 'Qt' object is dumped even though it is not exported // it contains useful information, in particular on enums - add the diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index f4f10b0fb41fcace228f29ce2d0ae225ddaac7bf..f1e30c4bd1d18e49436e646e4dbfceb6c5187589 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -587,7 +587,6 @@ public: /** \return an empty list when successful, error messages otherwise. */ static QStringList load(const QFileInfoList &xmlFiles); static QList<LanguageUtils::FakeMetaObject::ConstPtr> builtinObjects; - static QList<LanguageUtils::FakeMetaObject::ConstPtr> cppObjects; // parses the xml string and fills the newObjects map static QString parseQmlTypeXml(const QByteArray &xml, diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp index 0c4f85a1747303271d89400cd15f5d09e50f41ca..06a6e3438ec76a53119e8c57f1dd13bfd4a58830 100644 --- a/src/libs/qmljs/qmljslink.cpp +++ b/src/libs/qmljs/qmljslink.cpp @@ -120,6 +120,14 @@ Link::Link(Context *context, const Document::Ptr &doc, const Snapshot &snapshot, d->snapshot = snapshot; d->importPaths = importPaths; + // populate engine with types from C++ + ModelManagerInterface *modelManager = ModelManagerInterface::instance(); + if (modelManager) { + foreach (const QList<FakeMetaObject::ConstPtr> &cppTypes, modelManager->cppQmlTypes()) { + engine()->cppQmlTypes().load(engine(), cppTypes); + } + } + linkImports(); } diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index 7b579f52fe0ca7b91d42d471ec9233264b749db2..56a3022e6c01bf1f43b166affc268c6d9fe0cb24 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -110,6 +110,8 @@ public: Table _elements; }; + typedef QHash<QString, QList<LanguageUtils::FakeMetaObject::ConstPtr> > CppQmlTypeHash; + public: ModelManagerInterface(QObject *parent = 0); virtual ~ModelManagerInterface(); @@ -132,6 +134,8 @@ public: virtual void loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri) = 0; + virtual CppQmlTypeHash cppQmlTypes() const = 0; + signals: void documentUpdated(QmlJS::Document::Ptr doc); void documentChangedOnDisk(QmlJS::Document::Ptr doc); diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 263e0c1a81a466afece45f641d160241518267fb..4860027f693c45eddce317a421aeecb956e7dbbd 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -291,8 +291,7 @@ public: void operator()() { _doc->check(_mode); - // temporarily disabled because it's too expensive - //_doc->findExposedQmlTypes(); + _doc->findExposedQmlTypes(); _doc->releaseSource(); _doc->releaseTranslationUnit(); @@ -1548,32 +1547,34 @@ static void populate(LanguageUtils::FakeMetaObject::Ptr fmo, Class *klass, } } -QList<LanguageUtils::FakeMetaObject::ConstPtr> CppModelManager::exportedQmlObjects() const +QList<LanguageUtils::FakeMetaObject::ConstPtr> CppModelManager::exportedQmlObjects(const Document::Ptr &doc) const { using namespace LanguageUtils; QList<FakeMetaObject::ConstPtr> exportedObjects; QHash<Class *, FakeMetaObject::Ptr> classes; + const QList<CPlusPlus::Document::ExportedQmlType> exported = doc->exportedQmlTypes(); + if (exported.isEmpty()) + return exportedObjects; + + TypeOfExpression typeOf; const Snapshot currentSnapshot = snapshot(); - foreach (Document::Ptr doc, currentSnapshot) { - TypeOfExpression typeOf; - typeOf.init(doc, currentSnapshot); - foreach (const Document::ExportedQmlType &exportedType, doc->exportedQmlTypes()) { - FakeMetaObject::Ptr fmo(new FakeMetaObject); - fmo->addExport(exportedType.typeName, exportedType.packageName, - ComponentVersion(exportedType.majorVersion, exportedType.minorVersion)); - exportedObjects += fmo; - - Class *klass = lookupClass(exportedType.typeExpression, exportedType.scope, typeOf); - if (!klass) - continue; + typeOf.init(doc, currentSnapshot); + foreach (const Document::ExportedQmlType &exportedType, exported) { + FakeMetaObject::Ptr fmo(new FakeMetaObject); + fmo->addExport(exportedType.typeName, exportedType.packageName, + ComponentVersion(exportedType.majorVersion, exportedType.minorVersion)); + exportedObjects += fmo; + + Class *klass = lookupClass(exportedType.typeExpression, exportedType.scope, typeOf); + if (!klass) + continue; - // add the no-package export, so the cpp name can be used in properties - Overview overview; - fmo->addExport(overview(klass->name()), QString(), ComponentVersion()); + // add the no-package export, so the cpp name can be used in properties + Overview overview; + fmo->addExport(overview(klass->name()), QString(), ComponentVersion()); - populate(fmo, klass, &classes, typeOf); - } + populate(fmo, klass, &classes, typeOf); } return exportedObjects; diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 262a30d99f76175597dc769541ce3538c8b73c6d..1b79e67bb8775f9cff3b859f1e6f5130e5efafd1 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -131,7 +131,7 @@ public: virtual void findMacroUsages(const CPlusPlus::Macro ¯o); - virtual QList<LanguageUtils::FakeMetaObject::ConstPtr> exportedQmlObjects() const; + virtual QList<LanguageUtils::FakeMetaObject::ConstPtr> exportedQmlObjects(const CPlusPlus::Document::Ptr &doc) const; void setHeaderSuffixes(const QStringList &suffixes) { m_headerSuffixes = suffixes; } diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index 377d2540e5e67d4c47eb576c27e46e23ea6fe11e..6f0463470d41687b524a655db07467957e067e86 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -40,6 +40,9 @@ #include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/mimedatabase.h> #include <cplusplus/ModelManagerInterface.h> +#include <cplusplus/CppDocument.h> +#include <cplusplus/TypeOfExpression.h> +#include <cplusplus/Overview.h> #include <qmljs/qmljsinterpreter.h> #include <qmljs/qmljsbind.h> #include <qmljs/parser/qmldirparser_p.h> @@ -77,7 +80,7 @@ ModelManager::ModelManager(QObject *parent): m_updateCppQmlTypesTimer = new QTimer(this); m_updateCppQmlTypesTimer->setInterval(1000); m_updateCppQmlTypesTimer->setSingleShot(true); - connect(m_updateCppQmlTypesTimer, SIGNAL(timeout()), SLOT(updateCppQmlTypes())); + connect(m_updateCppQmlTypesTimer, SIGNAL(timeout()), SLOT(startCppQmlTypeUpdate())); qRegisterMetaType<QmlJS::Document::Ptr>("QmlJS::Document::Ptr"); qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo"); @@ -94,7 +97,7 @@ void ModelManager::delayedInitialization() CPlusPlus::CppModelManagerInterface::instance(); if (cppModelManager) { connect(cppModelManager, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)), - m_updateCppQmlTypesTimer, SLOT(start())); + this, SLOT(queueCppQmlTypeUpdate(CPlusPlus::Document::Ptr))); } } @@ -555,12 +558,46 @@ void ModelManager::loadPluginTypes(const QString &libraryPath, const QString &im m_pluginDumper->loadPluginTypes(libraryPath, importPath, importUri); } -void ModelManager::updateCppQmlTypes() +void ModelManager::queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc) +{ + m_queuedCppDocuments.insert(doc->fileName()); + m_updateCppQmlTypesTimer->start(); +} + +void ModelManager::startCppQmlTypeUpdate() { CPlusPlus::CppModelManagerInterface *cppModelManager = CPlusPlus::CppModelManagerInterface::instance(); if (!cppModelManager) return; - Interpreter::CppQmlTypesLoader::cppObjects = cppModelManager->exportedQmlObjects(); + QtConcurrent::run(&ModelManager::updateCppQmlTypes, + this, cppModelManager, m_queuedCppDocuments); + m_queuedCppDocuments.clear(); +} + +void ModelManager::updateCppQmlTypes(ModelManager *qmlModelManager, CPlusPlus::CppModelManagerInterface *cppModelManager, QSet<QString> files) +{ + CppQmlTypeHash newCppTypes = qmlModelManager->cppQmlTypes(); + CPlusPlus::Snapshot snapshot = cppModelManager->snapshot(); + + foreach (const QString &fileName, files) { + CPlusPlus::Document::Ptr doc = snapshot.document(fileName); + QList<LanguageUtils::FakeMetaObject::ConstPtr> exported; + if (doc) + exported = cppModelManager->exportedQmlObjects(doc); + if (!exported.isEmpty()) + newCppTypes[fileName] = exported; + else + newCppTypes.remove(fileName); + } + + QMutexLocker locker(&qmlModelManager->m_cppTypesMutex); + qmlModelManager->m_cppTypes = newCppTypes; +} + +ModelManagerInterface::CppQmlTypeHash ModelManager::cppQmlTypes() const +{ + QMutexLocker locker(&m_cppTypesMutex); + return m_cppTypes; } diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h index 1a0b4c2833d6b3ead3cc7cc7b180ceb2f5cb6f8d..b4a98cabceab89f153cd3e2fae3ce739f4e34e0b 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.h +++ b/src/plugins/qmljstools/qmljsmodelmanager.h @@ -38,6 +38,8 @@ #include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/qmljsdocument.h> +#include <cplusplus/CppDocument.h> +#include <cplusplus/ModelManagerInterface.h> #include <QFuture> #include <QFutureSynchronizer> @@ -85,6 +87,8 @@ public: virtual void loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri); + virtual CppQmlTypeHash cppQmlTypes() const; + Q_SIGNALS: void projectPathChanged(const QString &projectPath); @@ -104,10 +108,12 @@ protected: void updateImportPaths(); private slots: - void updateCppQmlTypes(); + void queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc); + void startCppQmlTypeUpdate(); private: static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType); + static void updateCppQmlTypes(ModelManager *qmlModelManager, CPlusPlus::CppModelManagerInterface *cppModelManager, QSet<QString> files); mutable QMutex m_mutex; Core::ICore *m_core; @@ -116,7 +122,11 @@ private: QStringList m_defaultImportPaths; QFutureSynchronizer<void> m_synchronizer; + QTimer *m_updateCppQmlTypesTimer; + QSet<QString> m_queuedCppDocuments; + CppQmlTypeHash m_cppTypes; + mutable QMutex m_cppTypesMutex; // project integration QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;