diff options
-rw-r--r-- | src/libs/qmljs/qmljsfindexportedcpptypes.cpp | 18 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsfindexportedcpptypes.h | 2 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsmodelmanagerinterface.cpp | 82 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsmodelmanagerinterface.h | 1 |
4 files changed, 72 insertions, 31 deletions
diff --git a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp index e03bf7d527..ff82a56cd5 100644 --- a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp +++ b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp @@ -817,16 +817,17 @@ FindExportedCppTypes::FindExportedCppTypes(const CPlusPlus::Snapshot &snapshot) { } -void FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document) +QStringList FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document) { m_contextProperties.clear(); m_exportedTypes.clear(); + QStringList fileNames; // this check only guards against some input errors, if document's source and AST has not // been guarded properly the source and AST may still become empty/null while this function is running if (document->utf8Source().isEmpty() || !document->translationUnit()->ast()) - return; + return fileNames; FindExportsVisitor finder(document); finder(); @@ -838,7 +839,7 @@ void FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document) const QList<ContextProperty> contextPropertyDescriptions = finder.contextProperties(); const QList<ExportedQmlType> exports = finder.exportedTypes(); if (exports.isEmpty() && contextPropertyDescriptions.isEmpty()) - return; + return fileNames; // context properties need lookup inside function scope, and thus require a full check CPlusPlus::Document::Ptr localDoc = document; @@ -863,14 +864,19 @@ void FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document) // convert to list of FakeMetaObject::ConstPtr m_exportedTypes.reserve(fakeMetaObjects.size() + extraFakeMetaObjects.size()); - foreach (const LanguageUtils::FakeMetaObject::Ptr &fmo, fakeMetaObjects) { - fmo->updateFingerprint(); - m_exportedTypes += fmo; + fileNames.reserve(fakeMetaObjects.size()); + for (auto it = fakeMetaObjects.constBegin(), end = fakeMetaObjects.constEnd(); it != end; + ++it) { + it.value()->updateFingerprint(); + m_exportedTypes += it.value(); + fileNames += QLatin1String(it.key()->fileName()); } foreach (const LanguageUtils::FakeMetaObject::Ptr &fmo, extraFakeMetaObjects) { fmo->updateFingerprint(); m_exportedTypes += fmo; } + + return fileNames; } QList<LanguageUtils::FakeMetaObject::ConstPtr> FindExportedCppTypes::exportedTypes() const diff --git a/src/libs/qmljs/qmljsfindexportedcpptypes.h b/src/libs/qmljs/qmljsfindexportedcpptypes.h index fbc9126880..f626130c74 100644 --- a/src/libs/qmljs/qmljsfindexportedcpptypes.h +++ b/src/libs/qmljs/qmljsfindexportedcpptypes.h @@ -41,7 +41,7 @@ public: FindExportedCppTypes(const CPlusPlus::Snapshot &snapshot); // document must have a valid source and ast for the duration of the call - void operator()(const CPlusPlus::Document::Ptr &document); + QStringList operator()(const CPlusPlus::Document::Ptr &document); QList<LanguageUtils::FakeMetaObject::ConstPtr> exportedTypes() const; QHash<QString, QString> contextProperties() const; diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index f739668f9f..a919087fea 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -1259,6 +1259,37 @@ void ModelManagerInterface::asyncReset() m_asyncResetTimer->start(); } +bool rescanExports(const QString &fileName, FindExportedCppTypes &finder, + ModelManagerInterface::CppDataHash &newData) +{ + bool hasNewInfo = false; + + QList<LanguageUtils::FakeMetaObject::ConstPtr> exported = finder.exportedTypes(); + QHash<QString, QString> contextProperties = finder.contextProperties(); + if (exported.isEmpty() && contextProperties.isEmpty()) { + hasNewInfo = hasNewInfo || newData.remove(fileName) > 0; + } else { + ModelManagerInterface::CppData &data = newData[fileName]; + if (!hasNewInfo && (data.exportedTypes.size() != exported.size() + || data.contextProperties != contextProperties)) + hasNewInfo = true; + if (!hasNewInfo) { + QHash<QString, QByteArray> newFingerprints; + foreach (LanguageUtils::FakeMetaObject::ConstPtr newType, exported) + newFingerprints[newType->className()]=newType->fingerprint(); + foreach (LanguageUtils::FakeMetaObject::ConstPtr oldType, data.exportedTypes) { + if (newFingerprints.value(oldType->className()) != oldType->fingerprint()) { + hasNewInfo = true; + break; + } + } + } + data.exportedTypes = exported; + data.contextProperties = contextProperties; + } + return hasNewInfo; +} + void ModelManagerInterface::updateCppQmlTypes(QFutureInterface<void> &interface, ModelManagerInterface *qmlModelManager, CPlusPlus::Snapshot snapshot, @@ -1266,7 +1297,14 @@ void ModelManagerInterface::updateCppQmlTypes(QFutureInterface<void> &interface, { interface.setProgressRange(0, documents.size()); interface.setProgressValue(0); - CppDataHash newData = qmlModelManager->cppData(); + + CppDataHash newData; + QHash<QString, QStringList> newDeclarations; + { + QMutexLocker locker(&qmlModelManager->m_cppDataMutex); + newData = qmlModelManager->m_cppDataHash; + newDeclarations = qmlModelManager->m_cppDeclarationFiles; + } FindExportedCppTypes finder(snapshot); @@ -1281,41 +1319,37 @@ void ModelManagerInterface::updateCppQmlTypes(QFutureInterface<void> &interface, const bool scan = pair.second; const QString fileName = doc->fileName(); if (!scan) { - hasNewInfo = hasNewInfo || newData.remove(fileName) > 0; + hasNewInfo = newData.remove(fileName) > 0 || hasNewInfo; + foreach (const QString &file, newDeclarations[fileName]) { + finder(snapshot.document(file)); + hasNewInfo = rescanExports(file, finder, newData) || hasNewInfo; + } continue; } - finder(doc); - - QList<LanguageUtils::FakeMetaObject::ConstPtr> exported = finder.exportedTypes(); - QHash<QString, QString> contextProperties = finder.contextProperties(); - if (exported.isEmpty() && contextProperties.isEmpty()) { - hasNewInfo = hasNewInfo || newData.remove(fileName) > 0; - } else { - CppData &data = newData[fileName]; - if (!hasNewInfo && (data.exportedTypes.size() != exported.size() - || data.contextProperties != contextProperties)) - hasNewInfo = true; - if (!hasNewInfo) { - QHash<QString, QByteArray> newFingerprints; - foreach (LanguageUtils::FakeMetaObject::ConstPtr newType, exported) - newFingerprints[newType->className()]=newType->fingerprint(); - foreach (LanguageUtils::FakeMetaObject::ConstPtr oldType, data.exportedTypes) { - if (newFingerprints.value(oldType->className()) != oldType->fingerprint()) { - hasNewInfo = true; - break; - } + for (auto it = newDeclarations.begin(), end = newDeclarations.end(); it != end;) { + if (it->removeOne(fileName)) { + doc->releaseSourceAndAST(); + if (it->isEmpty()) { + it = newDeclarations.erase(it); + continue; } } - data.exportedTypes = exported; - data.contextProperties = contextProperties; + ++it; + } + + foreach (const QString &declarationFile, finder(doc)) { + newDeclarations[declarationFile].append(fileName); + doc->keepSourceAndAST(); // keep for later reparsing when dependent doc changes } + hasNewInfo = rescanExports(doc->fileName(), finder, newData) || hasNewInfo; doc->releaseSourceAndAST(); } QMutexLocker locker(&qmlModelManager->m_cppDataMutex); qmlModelManager->m_cppDataHash = newData; + qmlModelManager->m_cppDeclarationFiles = newDeclarations; if (hasNewInfo) // one could get away with re-linking the cpp types... QMetaObject::invokeMethod(qmlModelManager, "asyncReset"); diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index 568fb63593..3f640c6ca7 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -275,6 +275,7 @@ private: QrcCache m_qrcCache; CppDataHash m_cppDataHash; + QHash<QString, QStringList> m_cppDeclarationFiles; mutable QMutex m_cppDataMutex; // project integration |