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 <Thomas.Hartmann@theqtcompany.com>
This commit is contained in:
Ulf Hermann
2016-10-28 12:53:24 +02:00
parent ff21689487
commit 424005c911
2 changed files with 19 additions and 16 deletions

View File

@@ -1300,7 +1300,7 @@ void ModelManagerInterface::updateCppQmlTypes(QFutureInterface<void> &interface,
interface.setProgressValue(0); interface.setProgressValue(0);
CppDataHash newData; CppDataHash newData;
QHash<QString, QStringList> newDeclarations; QHash<QString, QList<CPlusPlus::Document::Ptr> > newDeclarations;
{ {
QMutexLocker locker(&qmlModelManager->m_cppDataMutex); QMutexLocker locker(&qmlModelManager->m_cppDataMutex);
newData = qmlModelManager->m_cppDataHash; newData = qmlModelManager->m_cppDataHash;
@@ -1321,33 +1321,36 @@ void ModelManagerInterface::updateCppQmlTypes(QFutureInterface<void> &interface,
const QString fileName = doc->fileName(); const QString fileName = doc->fileName();
if (!scan) { if (!scan) {
hasNewInfo = newData.remove(fileName) > 0 || hasNewInfo; hasNewInfo = newData.remove(fileName) > 0 || hasNewInfo;
foreach (const QString &file, newDeclarations[fileName]) { foreach (const CPlusPlus::Document::Ptr &savedDoc, newDeclarations.value(fileName)) {
CPlusPlus::Document::Ptr doc = snapshot.document(file); finder(savedDoc);
if (doc.isNull()) hasNewInfo = rescanExports(savedDoc->fileName(), finder, newData) || hasNewInfo;
continue;
finder(doc);
hasNewInfo = rescanExports(file, finder, newData) || hasNewInfo;
} }
continue; continue;
} }
for (auto it = newDeclarations.begin(), end = newDeclarations.end(); it != end;) { for (auto it = newDeclarations.begin(), end = newDeclarations.end(); it != end;) {
if (it->removeOne(fileName)) { for (auto docIt = it->begin(), endDocIt = it->end(); docIt != endDocIt;) {
doc->releaseSourceAndAST(); CPlusPlus::Document::Ptr &savedDoc = *docIt;
if (it->isEmpty()) { if (savedDoc->fileName() == fileName) {
savedDoc->releaseSourceAndAST();
it->erase(docIt);
break;
} else {
++docIt;
}
}
if (it->isEmpty())
it = newDeclarations.erase(it); it = newDeclarations.erase(it);
continue; else
}
}
++it; ++it;
} }
foreach (const QString &declarationFile, finder(doc)) { foreach (const QString &declarationFile, finder(doc)) {
newDeclarations[declarationFile].append(fileName); newDeclarations[declarationFile].append(doc);
doc->keepSourceAndAST(); // keep for later reparsing when dependent doc changes 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(); doc->releaseSourceAndAST();
} }

View File

@@ -275,7 +275,7 @@ private:
QrcCache m_qrcCache; QrcCache m_qrcCache;
CppDataHash m_cppDataHash; CppDataHash m_cppDataHash;
QHash<QString, QStringList> m_cppDeclarationFiles; QHash<QString, QList<CPlusPlus::Document::Ptr> > m_cppDeclarationFiles;
mutable QMutex m_cppDataMutex; mutable QMutex m_cppDataMutex;
// project integration // project integration