Commit 329952f5 authored by Fawzi Mohamed's avatar Fawzi Mohamed
Browse files

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: default avatarChristian Kandeler <christian.kandeler@digia.com>
Reviewed-by: default avatarFawzi Mohamed <fawzi.mohamed@digia.com>
parent b013637f
......@@ -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>("QmlJS::Document::Ptr");
qRegisterMetaType<QmlJS::LibraryInfo>("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::ProjectInfo> 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)
......
......@@ -171,7 +171,8 @@ public:
QrcResourceSelector resources = AllQrcResources);
QList<ProjectInfo> 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<QString,Language::Enum> 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<ProjectExplorer::Project *, ProjectInfo> m_projects;
ProjectInfo m_defaultProjectInfo;
ProjectExplorer::Project *m_defaultProject;
QMultiHash<QString, ProjectExplorer::Project *> m_fileToProject;
PluginDumper *m_pluginDumper;
......
......@@ -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)
{
......
......@@ -70,9 +70,10 @@ public:
protected:
QHash<QString, QmlJS::Language::Enum> 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<void> 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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment