From 329952f5ee792484bdb53141fcfb3dba15f05a60 Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Mon, 30 Jun 2014 11:56:28 +0200 Subject: [PATCH] qmljs: fix race condition in defaultVContext defaultVContext did call defaultProjectInfo which could be called only from the ui thread (as it did check the current project) Now update the defaultProjectInfo via signals, and lock on access making defaultProjectInfo threadsafe. Task-number: QTCREATORBUG-12556 Change-Id: Ibffeb59bbcef7120f08766160bb1e2ddc9af2922 Reviewed-by: Christian Kandeler Reviewed-by: Fawzi Mohamed --- src/libs/qmljs/qmljsmodelmanagerinterface.cpp | 35 ++++++++++++++----- src/libs/qmljs/qmljsmodelmanagerinterface.h | 7 +++- src/plugins/qmljstools/qmljsmodelmanager.cpp | 10 ++++-- src/plugins/qmljstools/qmljsmodelmanager.h | 3 +- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index 6a9068807e0..167e6c29461 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -95,6 +95,7 @@ static QStringList environmentImportPaths() ModelManagerInterface::ModelManagerInterface(QObject *parent) : QObject(parent), m_shouldScanImports(false), + m_defaultProject(0), m_pluginDumper(new PluginDumper(this)) { m_synchronizer.setCancelOnWait(true); @@ -112,6 +113,11 @@ ModelManagerInterface::ModelManagerInterface(QObject *parent) qRegisterMetaType("QmlJS::Document::Ptr"); qRegisterMetaType("QmlJS::LibraryInfo"); + m_defaultProjectInfo.qtImportsPath = QLibraryInfo::location(QLibraryInfo::ImportsPath); +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + m_defaultProjectInfo.qtQmlPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); +#endif + m_defaultImportPaths << environmentImportPaths(); updateImportPaths(); @@ -253,7 +259,13 @@ void ModelManagerInterface::loadQmlTypeDescriptionsInternal(const QString &resou writeMessageInternal(warning); } - +void ModelManagerInterface::setDefaultProject(const ModelManagerInterface::ProjectInfo &pInfo, + ProjectExplorer::Project *p) +{ + QMutexLocker l(mutex()); + m_defaultProject = p; + m_defaultProjectInfo = pInfo; +} Snapshot ModelManagerInterface::snapshot() const { @@ -477,11 +489,13 @@ QList ModelManagerInterface::projectInfos() return m_projects.values(); } -ModelManagerInterface::ProjectInfo ModelManagerInterface::projectInfo(ProjectExplorer::Project *project) const +ModelManagerInterface::ProjectInfo ModelManagerInterface::projectInfo( + ProjectExplorer::Project *project, + const ModelManagerInterface::ProjectInfo &defaultValue) const { QMutexLocker locker(&m_mutex); - return m_projects.value(project, ProjectInfo()); + return m_projects.value(project, defaultValue); } void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectExplorer::Project *p) @@ -495,6 +509,8 @@ void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectE QMutexLocker locker(&m_mutex); oldInfo = m_projects.value(p); m_projects.insert(p, pinfo); + if (p == m_defaultProject) + m_defaultProjectInfo = pinfo; snapshot = m_validSnapshot; } @@ -1190,6 +1206,11 @@ void ModelManagerInterface::startCppQmlTypeUpdate() m_queuedCppDocuments.clear(); } +QMutex *ModelManagerInterface::mutex() const +{ + return &m_mutex; +} + void ModelManagerInterface::asyncReset() { m_asyncResetTimer->start(); @@ -1358,12 +1379,8 @@ ViewerContext ModelManagerInterface::defaultVContext(Language::Enum language, ModelManagerInterface::ProjectInfo ModelManagerInterface::defaultProjectInfo() const { - ProjectInfo res; - res.qtImportsPath = QLibraryInfo::location(QLibraryInfo::ImportsPath); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) - res.qtQmlPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); -#endif - return res; + QMutexLocker l(mutex()); + return m_defaultProjectInfo; } void ModelManagerInterface::setDefaultVContext(const ViewerContext &vContext) diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index 5b3f771cf9a..089b70e68e6 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -171,7 +171,8 @@ public: QrcResourceSelector resources = AllQrcResources); QList projectInfos() const; - ProjectInfo projectInfo(ProjectExplorer::Project *project) const; + ProjectInfo projectInfo(ProjectExplorer::Project *project, + const ModelManagerInterface::ProjectInfo &defaultValue = ProjectInfo()) const; void updateProjectInfo(const ProjectInfo &pinfo, ProjectExplorer::Project *p); void updateDocument(QmlJS::Document::Ptr doc); @@ -218,6 +219,7 @@ protected slots: void asyncReset(); virtual void startCppQmlTypeUpdate(); protected: + QMutex *mutex() const; virtual QHash languageForSuffix() const; virtual void writeMessageInternal(const QString &msg) const; virtual WorkingCopy workingCopyInternal() const; @@ -250,6 +252,7 @@ protected: void maybeScan(const QStringList &importPaths, Language::Enum defaultLanguage); void updateImportPaths(); void loadQmlTypeDescriptionsInternal(const QString &path); + void setDefaultProject(const ProjectInfo &pInfo, ProjectExplorer::Project *p); private: mutable QMutex m_mutex; @@ -274,6 +277,8 @@ private: // project integration QMap m_projects; + ProjectInfo m_defaultProjectInfo; + ProjectExplorer::Project *m_defaultProject; QMultiHash m_fileToProject; PluginDumper *m_pluginDumper; diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index da51a627acf..3c5a53806df 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -222,6 +222,8 @@ void ModelManager::delayedInitialization() connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectRemoved(ProjectExplorer::Project*)), this, SLOT(removeProjectInfo(ProjectExplorer::Project*))); + connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(currentProjectChanged(ProjectExplorer::Project*)), + SLOT(updateDefaultProjectInfo())); QmlJS::ViewerContext qbsVContext; qbsVContext.language = Language::QmlQbs; @@ -257,13 +259,15 @@ ModelManagerInterface::WorkingCopy ModelManager::workingCopyInternal() const return workingCopy; } -ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfo() const +void ModelManager::updateDefaultProjectInfo() { - // needs to be performed in the ui therad (change?) + // needs to be performed in the ui therad ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectExplorerPlugin::currentProject(); - return defaultProjectInfoForProject(currentProject); + ProjectInfo newDefaultProjectInfo = defaultProjectInfoForProject(currentProject); + setDefaultProject(projectInfo(currentProject,newDefaultProjectInfo), currentProject); } + // Check whether fileMimeType is the same or extends knownMimeType bool ModelManager::matchesMimeType(const MimeType &fileMimeType, const MimeType &knownMimeType) { diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h index 2b8233a66f4..efc8de8bb57 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.h +++ b/src/plugins/qmljstools/qmljsmodelmanager.h @@ -70,9 +70,10 @@ public: protected: QHash languageForSuffix() const QTC_OVERRIDE; void writeMessageInternal(const QString &msg) const QTC_OVERRIDE; - ModelManagerInterface::ProjectInfo defaultProjectInfo() const QTC_OVERRIDE; WorkingCopy workingCopyInternal() const QTC_OVERRIDE; void addTaskInternal(QFuture result, const QString &msg, const char *taskId) const QTC_OVERRIDE; +private slots: + void updateDefaultProjectInfo(); private: void loadDefaultQmlTypeDescriptions(); static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType);