forked from qt-creator/qt-creator
QMLJS: Fix deadlock on session switch
Fixes: QTCREATORBUG-30016 Change-Id: I17d2b068e1bdb2fcad182209ca08a652b0957fa4 Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io> Reviewed-by: hjk <hjk@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
@@ -872,7 +872,7 @@ bool ModelManagerInterface::findNewQmlLibraryInPath(const Utils::FilePath &path,
|
|||||||
QSet<Utils::FilePath> *scannedPaths,
|
QSet<Utils::FilePath> *scannedPaths,
|
||||||
QSet<Utils::FilePath> *newLibraries,
|
QSet<Utils::FilePath> *newLibraries,
|
||||||
bool ignoreMissing,
|
bool ignoreMissing,
|
||||||
SyncedData *lockedData)
|
SynchronizedValue<SyncedData>::unique_lock *lock)
|
||||||
{
|
{
|
||||||
switch (libraryStatus(path, snapshot, newLibraries)) {
|
switch (libraryStatus(path, snapshot, newLibraries)) {
|
||||||
case LibraryStatus::Accepted: return true;
|
case LibraryStatus::Accepted: return true;
|
||||||
@@ -884,8 +884,8 @@ bool ModelManagerInterface::findNewQmlLibraryInPath(const Utils::FilePath &path,
|
|||||||
if (!qmldirFile.exists()) {
|
if (!qmldirFile.exists()) {
|
||||||
if (!ignoreMissing) {
|
if (!ignoreMissing) {
|
||||||
LibraryInfo libraryInfo(LibraryInfo::NotFound);
|
LibraryInfo libraryInfo(LibraryInfo::NotFound);
|
||||||
if (lockedData)
|
if (lock)
|
||||||
modelManager->updateLibraryInfo(path, libraryInfo, *lockedData);
|
modelManager->updateLibraryInfo(path, libraryInfo, **lock);
|
||||||
else
|
else
|
||||||
modelManager->updateLibraryInfo(path, libraryInfo);
|
modelManager->updateLibraryInfo(path, libraryInfo);
|
||||||
}
|
}
|
||||||
@@ -907,12 +907,25 @@ bool ModelManagerInterface::findNewQmlLibraryInPath(const Utils::FilePath &path,
|
|||||||
|
|
||||||
const Utils::FilePath libraryPath = qmldirFile.absolutePath();
|
const Utils::FilePath libraryPath = qmldirFile.absolutePath();
|
||||||
newLibraries->insert(libraryPath);
|
newLibraries->insert(libraryPath);
|
||||||
if (lockedData)
|
if (lock)
|
||||||
modelManager->updateLibraryInfo(libraryPath, LibraryInfo(qmldirParser), *lockedData);
|
modelManager->updateLibraryInfo(libraryPath, LibraryInfo(qmldirParser), **lock);
|
||||||
else
|
else
|
||||||
modelManager->updateLibraryInfo(libraryPath, LibraryInfo(qmldirParser));
|
modelManager->updateLibraryInfo(libraryPath, LibraryInfo(qmldirParser));
|
||||||
|
|
||||||
modelManager->loadPluginTypes(libraryPath.canonicalPath(), libraryPath, QString(), QString());
|
if (lock) {
|
||||||
|
lock->unlock();
|
||||||
|
// This will call our locking functions again, so we have to unlock first.
|
||||||
|
modelManager->loadPluginTypes(libraryPath.canonicalPath(),
|
||||||
|
libraryPath,
|
||||||
|
QString(),
|
||||||
|
QString());
|
||||||
|
lock->lock();
|
||||||
|
} else {
|
||||||
|
modelManager->loadPluginTypes(libraryPath.canonicalPath(),
|
||||||
|
libraryPath,
|
||||||
|
QString(),
|
||||||
|
QString());
|
||||||
|
}
|
||||||
|
|
||||||
// scan the qml files in the library
|
// scan the qml files in the library
|
||||||
const auto components = qmldirParser.components();
|
const auto components = qmldirParser.components();
|
||||||
@@ -945,7 +958,7 @@ void ModelManagerInterface::findNewLibraryImports(const Document::Ptr &doc,
|
|||||||
FilePaths *importedFiles,
|
FilePaths *importedFiles,
|
||||||
QSet<Utils::FilePath> *scannedPaths,
|
QSet<Utils::FilePath> *scannedPaths,
|
||||||
QSet<Utils::FilePath> *newLibraries,
|
QSet<Utils::FilePath> *newLibraries,
|
||||||
SyncedData *lockedData)
|
SynchronizedValue<SyncedData>::unique_lock *lock)
|
||||||
{
|
{
|
||||||
// scan current dir
|
// scan current dir
|
||||||
findNewQmlLibraryInPath(doc->path(),
|
findNewQmlLibraryInPath(doc->path(),
|
||||||
@@ -955,11 +968,11 @@ void ModelManagerInterface::findNewLibraryImports(const Document::Ptr &doc,
|
|||||||
scannedPaths,
|
scannedPaths,
|
||||||
newLibraries,
|
newLibraries,
|
||||||
false,
|
false,
|
||||||
lockedData);
|
lock);
|
||||||
|
|
||||||
// scan dir and lib imports
|
// scan dir and lib imports
|
||||||
const FilePaths importPaths = lockedData ? modelManager->importPathsNames(*lockedData)
|
const FilePaths importPaths = lock ? modelManager->importPathsNames(**lock)
|
||||||
: modelManager->importPathsNames();
|
: modelManager->importPathsNames();
|
||||||
const auto imports = doc->bind()->imports();
|
const auto imports = doc->bind()->imports();
|
||||||
for (const ImportInfo &import : imports) {
|
for (const ImportInfo &import : imports) {
|
||||||
switch (import.type()) {
|
switch (import.type()) {
|
||||||
@@ -971,7 +984,7 @@ void ModelManagerInterface::findNewLibraryImports(const Document::Ptr &doc,
|
|||||||
scannedPaths,
|
scannedPaths,
|
||||||
newLibraries,
|
newLibraries,
|
||||||
false,
|
false,
|
||||||
lockedData);
|
lock);
|
||||||
break;
|
break;
|
||||||
case ImportType::Library:
|
case ImportType::Library:
|
||||||
findNewQmlLibraryInPath(modulePath(import, importPaths),
|
findNewQmlLibraryInPath(modulePath(import, importPaths),
|
||||||
@@ -981,7 +994,7 @@ void ModelManagerInterface::findNewLibraryImports(const Document::Ptr &doc,
|
|||||||
scannedPaths,
|
scannedPaths,
|
||||||
newLibraries,
|
newLibraries,
|
||||||
false,
|
false,
|
||||||
lockedData);
|
lock);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1297,84 +1310,87 @@ void ModelManagerInterface::updateImportPaths()
|
|||||||
PathsAndLanguages allImportPaths;
|
PathsAndLanguages allImportPaths;
|
||||||
QList<Utils::FilePath> importedFiles;
|
QList<Utils::FilePath> importedFiles;
|
||||||
|
|
||||||
bool scan = m_syncedData.update<bool>([this, &allImportPaths, &importedFiles](SyncedData &sd) {
|
SynchronizedValue<SyncedData>::unique_lock lock = m_syncedData.writeLocked();
|
||||||
QList<Utils::FilePath> allApplicationDirectories;
|
|
||||||
QmlLanguageBundles activeBundles;
|
|
||||||
QmlLanguageBundles extendedBundles;
|
|
||||||
|
|
||||||
for (const ProjectInfo &pInfo : std::as_const(sd.m_projects)) {
|
QList<Utils::FilePath> allApplicationDirectories;
|
||||||
for (const auto &importPath : pInfo.importPaths) {
|
QmlLanguageBundles activeBundles;
|
||||||
const FilePath canonicalPath = importPath.path().canonicalPath();
|
QmlLanguageBundles extendedBundles;
|
||||||
|
|
||||||
|
for (const ProjectInfo &pInfo : std::as_const(lock->m_projects)) {
|
||||||
|
for (const auto &importPath : pInfo.importPaths) {
|
||||||
|
const FilePath canonicalPath = importPath.path().canonicalPath();
|
||||||
|
if (!canonicalPath.isEmpty())
|
||||||
|
allImportPaths.maybeInsert(canonicalPath, importPath.language());
|
||||||
|
}
|
||||||
|
allApplicationDirectories.append(pInfo.applicationDirectories);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ViewerContext &vContext : std::as_const(lock->m_defaultVContexts)) {
|
||||||
|
for (const Utils::FilePath &path : vContext.paths)
|
||||||
|
allImportPaths.maybeInsert(path, vContext.language);
|
||||||
|
allApplicationDirectories.append(vContext.applicationDirectories);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ProjectInfo &pInfo : std::as_const(lock->m_projects)) {
|
||||||
|
activeBundles.mergeLanguageBundles(pInfo.activeBundle);
|
||||||
|
const auto languages = pInfo.activeBundle.languages();
|
||||||
|
for (Dialect l : languages) {
|
||||||
|
const auto paths = pInfo.activeBundle.bundleForLanguage(l).searchPaths().stringList();
|
||||||
|
for (const QString &path : paths) {
|
||||||
|
const QString canonicalPath = QFileInfo(path).canonicalFilePath();
|
||||||
if (!canonicalPath.isEmpty())
|
if (!canonicalPath.isEmpty())
|
||||||
allImportPaths.maybeInsert(canonicalPath, importPath.language());
|
allImportPaths.maybeInsert(Utils::FilePath::fromString(canonicalPath), l);
|
||||||
}
|
|
||||||
allApplicationDirectories.append(pInfo.applicationDirectories);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const ViewerContext &vContext : std::as_const(sd.m_defaultVContexts)) {
|
|
||||||
for (const Utils::FilePath &path : vContext.paths)
|
|
||||||
allImportPaths.maybeInsert(path, vContext.language);
|
|
||||||
allApplicationDirectories.append(vContext.applicationDirectories);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const ProjectInfo &pInfo : std::as_const(sd.m_projects)) {
|
|
||||||
activeBundles.mergeLanguageBundles(pInfo.activeBundle);
|
|
||||||
const auto languages = pInfo.activeBundle.languages();
|
|
||||||
for (Dialect l : languages) {
|
|
||||||
const auto paths
|
|
||||||
= pInfo.activeBundle.bundleForLanguage(l).searchPaths().stringList();
|
|
||||||
for (const QString &path : paths) {
|
|
||||||
const QString canonicalPath = QFileInfo(path).canonicalFilePath();
|
|
||||||
if (!canonicalPath.isEmpty())
|
|
||||||
allImportPaths.maybeInsert(Utils::FilePath::fromString(canonicalPath), l);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const ProjectInfo &pInfo : std::as_const(sd.m_projects)) {
|
for (const ProjectInfo &pInfo : std::as_const(lock->m_projects)) {
|
||||||
if (!pInfo.qtQmlPath.isEmpty())
|
if (!pInfo.qtQmlPath.isEmpty())
|
||||||
allImportPaths.maybeInsert(pInfo.qtQmlPath, Dialect::QmlQtQuick2);
|
allImportPaths.maybeInsert(pInfo.qtQmlPath, Dialect::QmlQtQuick2);
|
||||||
}
|
}
|
||||||
const FilePath pathAtt = sd.m_defaultProjectInfo.qtQmlPath;
|
const FilePath pathAtt = lock->m_defaultProjectInfo.qtQmlPath;
|
||||||
if (!pathAtt.isEmpty())
|
if (!pathAtt.isEmpty())
|
||||||
allImportPaths.maybeInsert(pathAtt, Dialect::QmlQtQuick2);
|
allImportPaths.maybeInsert(pathAtt, Dialect::QmlQtQuick2);
|
||||||
for (const auto &importPath : sd.m_defaultProjectInfo.importPaths) {
|
for (const auto &importPath : lock->m_defaultProjectInfo.importPaths) {
|
||||||
allImportPaths.maybeInsert(importPath);
|
allImportPaths.maybeInsert(importPath);
|
||||||
}
|
}
|
||||||
for (const Utils::FilePath &path : std::as_const(sd.m_defaultImportPaths))
|
for (const Utils::FilePath &path : std::as_const(lock->m_defaultImportPaths))
|
||||||
allImportPaths.maybeInsert(path, Dialect::Qml);
|
allImportPaths.maybeInsert(path, Dialect::Qml);
|
||||||
allImportPaths.compact();
|
allImportPaths.compact();
|
||||||
allApplicationDirectories = Utils::filteredUnique(allApplicationDirectories);
|
allApplicationDirectories = Utils::filteredUnique(allApplicationDirectories);
|
||||||
|
|
||||||
sd.m_allImportPaths = allImportPaths;
|
lock->m_allImportPaths = allImportPaths;
|
||||||
sd.m_activeBundles = activeBundles;
|
lock->m_activeBundles = activeBundles;
|
||||||
sd.m_extendedBundles = extendedBundles;
|
lock->m_extendedBundles = extendedBundles;
|
||||||
sd.m_applicationPaths = minimalPrefixPaths(allApplicationDirectories);
|
lock->m_applicationPaths = minimalPrefixPaths(allApplicationDirectories);
|
||||||
// check if any file in the snapshot imports something new in the new paths
|
// check if any file in the snapshot imports something new in the new paths
|
||||||
Snapshot snapshot = sd.m_validSnapshot;
|
Snapshot snapshot = lock->m_validSnapshot;
|
||||||
QSet<Utils::FilePath> scannedPaths;
|
QSet<Utils::FilePath> scannedPaths;
|
||||||
QSet<Utils::FilePath> newLibraries;
|
QSet<Utils::FilePath> newLibraries;
|
||||||
for (const Document::Ptr &doc : std::as_const(snapshot))
|
|
||||||
findNewLibraryImports(doc,
|
|
||||||
snapshot,
|
|
||||||
this,
|
|
||||||
&importedFiles,
|
|
||||||
&scannedPaths,
|
|
||||||
&newLibraries,
|
|
||||||
&sd);
|
|
||||||
for (const Utils::FilePath &path : std::as_const(allApplicationDirectories)) {
|
|
||||||
allImportPaths.maybeInsert(path, Dialect::Qml);
|
|
||||||
findNewQmlApplicationInPath(path, snapshot, this, &newLibraries);
|
|
||||||
}
|
|
||||||
for (const Utils::FilePath &qrcPath : generatedQrc(sd.m_projects.values()))
|
|
||||||
updateQrcFile(qrcPath);
|
|
||||||
|
|
||||||
return sd.m_shouldScanImports;
|
for (const Document::Ptr &doc : std::as_const(snapshot))
|
||||||
});
|
findNewLibraryImports(doc,
|
||||||
|
snapshot,
|
||||||
|
this,
|
||||||
|
&importedFiles,
|
||||||
|
&scannedPaths,
|
||||||
|
&newLibraries,
|
||||||
|
&lock);
|
||||||
|
|
||||||
|
for (const Utils::FilePath &path : std::as_const(allApplicationDirectories)) {
|
||||||
|
allImportPaths.maybeInsert(path, Dialect::Qml);
|
||||||
|
findNewQmlApplicationInPath(path, snapshot, this, &newLibraries);
|
||||||
|
}
|
||||||
|
for (const Utils::FilePath &qrcPath : generatedQrc(lock->m_projects.values()))
|
||||||
|
updateQrcFile(qrcPath);
|
||||||
|
|
||||||
|
const bool shouldScan = lock->m_shouldScanImports;
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
updateSourceFiles(importedFiles, true);
|
updateSourceFiles(importedFiles, true);
|
||||||
|
|
||||||
if (!scan)
|
if (!shouldScan)
|
||||||
return;
|
return;
|
||||||
maybeScan(allImportPaths);
|
maybeScan(allImportPaths);
|
||||||
}
|
}
|
||||||
|
@@ -297,7 +297,7 @@ private:
|
|||||||
Utils::FilePaths *importedFiles,
|
Utils::FilePaths *importedFiles,
|
||||||
QSet<Utils::FilePath> *scannedPaths,
|
QSet<Utils::FilePath> *scannedPaths,
|
||||||
QSet<Utils::FilePath> *newLibraries,
|
QSet<Utils::FilePath> *newLibraries,
|
||||||
SyncedData *lockedData);
|
Utils::SynchronizedValue<SyncedData>::unique_lock *lock);
|
||||||
|
|
||||||
static bool findNewQmlLibraryInPath(const Utils::FilePath &path,
|
static bool findNewQmlLibraryInPath(const Utils::FilePath &path,
|
||||||
const Snapshot &snapshot,
|
const Snapshot &snapshot,
|
||||||
@@ -306,7 +306,7 @@ private:
|
|||||||
QSet<Utils::FilePath> *scannedPaths,
|
QSet<Utils::FilePath> *scannedPaths,
|
||||||
QSet<Utils::FilePath> *newLibraries,
|
QSet<Utils::FilePath> *newLibraries,
|
||||||
bool ignoreMissing,
|
bool ignoreMissing,
|
||||||
SyncedData *lockedData);
|
Utils::SynchronizedValue<SyncedData>::unique_lock *lock);
|
||||||
|
|
||||||
void updateLibraryInfo(const Utils::FilePath &path,
|
void updateLibraryInfo(const Utils::FilePath &path,
|
||||||
const QmlJS::LibraryInfo &info,
|
const QmlJS::LibraryInfo &info,
|
||||||
|
Reference in New Issue
Block a user