From 424005c91183edb72000ed795522c1256d68de13 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 28 Oct 2016 12:53:24 +0200 Subject: [PATCH] QmlJS: Release the same documents we keep before When rescanning imports we generally get a new version of the parent document. When replacing the cached documents we want to release the old ones, not the new ones. Failing to do so leads to types disappearing from the QML code model and to leaking memory. Task-number: QTCREATORBUG-17175 Change-Id: I3994444ac0a6cd87f9d9d0b47ab3d6015660e416 Reviewed-by: Thomas Hartmann --- src/libs/qmljs/qmljsmodelmanagerinterface.cpp | 33 ++++++++++--------- src/libs/qmljs/qmljsmodelmanagerinterface.h | 2 +- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index e0983433916..34d1cd24959 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -1300,7 +1300,7 @@ void ModelManagerInterface::updateCppQmlTypes(QFutureInterface &interface, interface.setProgressValue(0); CppDataHash newData; - QHash newDeclarations; + QHash > newDeclarations; { QMutexLocker locker(&qmlModelManager->m_cppDataMutex); newData = qmlModelManager->m_cppDataHash; @@ -1321,33 +1321,36 @@ void ModelManagerInterface::updateCppQmlTypes(QFutureInterface &interface, const QString fileName = doc->fileName(); if (!scan) { hasNewInfo = newData.remove(fileName) > 0 || hasNewInfo; - foreach (const QString &file, newDeclarations[fileName]) { - CPlusPlus::Document::Ptr doc = snapshot.document(file); - if (doc.isNull()) - continue; - finder(doc); - hasNewInfo = rescanExports(file, finder, newData) || hasNewInfo; + foreach (const CPlusPlus::Document::Ptr &savedDoc, newDeclarations.value(fileName)) { + finder(savedDoc); + hasNewInfo = rescanExports(savedDoc->fileName(), finder, newData) || hasNewInfo; } continue; } for (auto it = newDeclarations.begin(), end = newDeclarations.end(); it != end;) { - if (it->removeOne(fileName)) { - doc->releaseSourceAndAST(); - if (it->isEmpty()) { - it = newDeclarations.erase(it); - continue; + for (auto docIt = it->begin(), endDocIt = it->end(); docIt != endDocIt;) { + CPlusPlus::Document::Ptr &savedDoc = *docIt; + if (savedDoc->fileName() == fileName) { + savedDoc->releaseSourceAndAST(); + it->erase(docIt); + break; + } else { + ++docIt; } } - ++it; + if (it->isEmpty()) + it = newDeclarations.erase(it); + else + ++it; } foreach (const QString &declarationFile, finder(doc)) { - newDeclarations[declarationFile].append(fileName); + newDeclarations[declarationFile].append(doc); doc->keepSourceAndAST(); // keep for later reparsing when dependent doc changes } - hasNewInfo = rescanExports(doc->fileName(), finder, newData) || hasNewInfo; + hasNewInfo = rescanExports(fileName, finder, newData) || hasNewInfo; doc->releaseSourceAndAST(); } diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index 3f640c6ca78..2cb02083f6e 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -275,7 +275,7 @@ private: QrcCache m_qrcCache; CppDataHash m_cppDataHash; - QHash m_cppDeclarationFiles; + QHash > m_cppDeclarationFiles; mutable QMutex m_cppDataMutex; // project integration