summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs/qmljs/qmljsfindexportedcpptypes.cpp18
-rw-r--r--src/libs/qmljs/qmljsfindexportedcpptypes.h2
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.cpp82
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.h1
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