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);
CppDataHash newData;
QHash<QString, QStringList> newDeclarations;
QHash<QString, QList<CPlusPlus::Document::Ptr> > newDeclarations;
{
QMutexLocker locker(&qmlModelManager->m_cppDataMutex);
newData = qmlModelManager->m_cppDataHash;
@@ -1321,33 +1321,36 @@ void ModelManagerInterface::updateCppQmlTypes(QFutureInterface<void> &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();
}

View File

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