forked from qt-creator/qt-creator
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 <christian.kandeler@digia.com> Reviewed-by: Fawzi Mohamed <fawzi.mohamed@digia.com>
This commit is contained in:
@@ -95,6 +95,7 @@ static QStringList environmentImportPaths()
|
|||||||
ModelManagerInterface::ModelManagerInterface(QObject *parent)
|
ModelManagerInterface::ModelManagerInterface(QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
m_shouldScanImports(false),
|
m_shouldScanImports(false),
|
||||||
|
m_defaultProject(0),
|
||||||
m_pluginDumper(new PluginDumper(this))
|
m_pluginDumper(new PluginDumper(this))
|
||||||
{
|
{
|
||||||
m_synchronizer.setCancelOnWait(true);
|
m_synchronizer.setCancelOnWait(true);
|
||||||
@@ -112,6 +113,11 @@ ModelManagerInterface::ModelManagerInterface(QObject *parent)
|
|||||||
qRegisterMetaType<QmlJS::Document::Ptr>("QmlJS::Document::Ptr");
|
qRegisterMetaType<QmlJS::Document::Ptr>("QmlJS::Document::Ptr");
|
||||||
qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo");
|
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();
|
m_defaultImportPaths << environmentImportPaths();
|
||||||
updateImportPaths();
|
updateImportPaths();
|
||||||
|
|
||||||
@@ -253,7 +259,13 @@ void ModelManagerInterface::loadQmlTypeDescriptionsInternal(const QString &resou
|
|||||||
writeMessageInternal(warning);
|
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
|
Snapshot ModelManagerInterface::snapshot() const
|
||||||
{
|
{
|
||||||
@@ -477,11 +489,13 @@ QList<ModelManagerInterface::ProjectInfo> ModelManagerInterface::projectInfos()
|
|||||||
return m_projects.values();
|
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);
|
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)
|
void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectExplorer::Project *p)
|
||||||
@@ -495,6 +509,8 @@ void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectE
|
|||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
oldInfo = m_projects.value(p);
|
oldInfo = m_projects.value(p);
|
||||||
m_projects.insert(p, pinfo);
|
m_projects.insert(p, pinfo);
|
||||||
|
if (p == m_defaultProject)
|
||||||
|
m_defaultProjectInfo = pinfo;
|
||||||
snapshot = m_validSnapshot;
|
snapshot = m_validSnapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1190,6 +1206,11 @@ void ModelManagerInterface::startCppQmlTypeUpdate()
|
|||||||
m_queuedCppDocuments.clear();
|
m_queuedCppDocuments.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMutex *ModelManagerInterface::mutex() const
|
||||||
|
{
|
||||||
|
return &m_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
void ModelManagerInterface::asyncReset()
|
void ModelManagerInterface::asyncReset()
|
||||||
{
|
{
|
||||||
m_asyncResetTimer->start();
|
m_asyncResetTimer->start();
|
||||||
@@ -1358,12 +1379,8 @@ ViewerContext ModelManagerInterface::defaultVContext(Language::Enum language,
|
|||||||
|
|
||||||
ModelManagerInterface::ProjectInfo ModelManagerInterface::defaultProjectInfo() const
|
ModelManagerInterface::ProjectInfo ModelManagerInterface::defaultProjectInfo() const
|
||||||
{
|
{
|
||||||
ProjectInfo res;
|
QMutexLocker l(mutex());
|
||||||
res.qtImportsPath = QLibraryInfo::location(QLibraryInfo::ImportsPath);
|
return m_defaultProjectInfo;
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
|
||||||
res.qtQmlPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
|
|
||||||
#endif
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelManagerInterface::setDefaultVContext(const ViewerContext &vContext)
|
void ModelManagerInterface::setDefaultVContext(const ViewerContext &vContext)
|
||||||
|
@@ -171,7 +171,8 @@ public:
|
|||||||
QrcResourceSelector resources = AllQrcResources);
|
QrcResourceSelector resources = AllQrcResources);
|
||||||
|
|
||||||
QList<ProjectInfo> projectInfos() const;
|
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 updateProjectInfo(const ProjectInfo &pinfo, ProjectExplorer::Project *p);
|
||||||
|
|
||||||
void updateDocument(QmlJS::Document::Ptr doc);
|
void updateDocument(QmlJS::Document::Ptr doc);
|
||||||
@@ -218,6 +219,7 @@ protected slots:
|
|||||||
void asyncReset();
|
void asyncReset();
|
||||||
virtual void startCppQmlTypeUpdate();
|
virtual void startCppQmlTypeUpdate();
|
||||||
protected:
|
protected:
|
||||||
|
QMutex *mutex() const;
|
||||||
virtual QHash<QString,Language::Enum> languageForSuffix() const;
|
virtual QHash<QString,Language::Enum> languageForSuffix() const;
|
||||||
virtual void writeMessageInternal(const QString &msg) const;
|
virtual void writeMessageInternal(const QString &msg) const;
|
||||||
virtual WorkingCopy workingCopyInternal() const;
|
virtual WorkingCopy workingCopyInternal() const;
|
||||||
@@ -250,6 +252,7 @@ protected:
|
|||||||
void maybeScan(const QStringList &importPaths, Language::Enum defaultLanguage);
|
void maybeScan(const QStringList &importPaths, Language::Enum defaultLanguage);
|
||||||
void updateImportPaths();
|
void updateImportPaths();
|
||||||
void loadQmlTypeDescriptionsInternal(const QString &path);
|
void loadQmlTypeDescriptionsInternal(const QString &path);
|
||||||
|
void setDefaultProject(const ProjectInfo &pInfo, ProjectExplorer::Project *p);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable QMutex m_mutex;
|
mutable QMutex m_mutex;
|
||||||
@@ -274,6 +277,8 @@ private:
|
|||||||
|
|
||||||
// project integration
|
// project integration
|
||||||
QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
|
QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
|
||||||
|
ProjectInfo m_defaultProjectInfo;
|
||||||
|
ProjectExplorer::Project *m_defaultProject;
|
||||||
QMultiHash<QString, ProjectExplorer::Project *> m_fileToProject;
|
QMultiHash<QString, ProjectExplorer::Project *> m_fileToProject;
|
||||||
|
|
||||||
PluginDumper *m_pluginDumper;
|
PluginDumper *m_pluginDumper;
|
||||||
|
@@ -222,6 +222,8 @@ void ModelManager::delayedInitialization()
|
|||||||
|
|
||||||
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectRemoved(ProjectExplorer::Project*)),
|
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectRemoved(ProjectExplorer::Project*)),
|
||||||
this, SLOT(removeProjectInfo(ProjectExplorer::Project*)));
|
this, SLOT(removeProjectInfo(ProjectExplorer::Project*)));
|
||||||
|
connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(currentProjectChanged(ProjectExplorer::Project*)),
|
||||||
|
SLOT(updateDefaultProjectInfo()));
|
||||||
|
|
||||||
QmlJS::ViewerContext qbsVContext;
|
QmlJS::ViewerContext qbsVContext;
|
||||||
qbsVContext.language = Language::QmlQbs;
|
qbsVContext.language = Language::QmlQbs;
|
||||||
@@ -257,13 +259,15 @@ ModelManagerInterface::WorkingCopy ModelManager::workingCopyInternal() const
|
|||||||
return workingCopy;
|
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();
|
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
|
// Check whether fileMimeType is the same or extends knownMimeType
|
||||||
bool ModelManager::matchesMimeType(const MimeType &fileMimeType, const MimeType &knownMimeType)
|
bool ModelManager::matchesMimeType(const MimeType &fileMimeType, const MimeType &knownMimeType)
|
||||||
{
|
{
|
||||||
|
@@ -70,9 +70,10 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
QHash<QString, QmlJS::Language::Enum> languageForSuffix() const QTC_OVERRIDE;
|
QHash<QString, QmlJS::Language::Enum> languageForSuffix() const QTC_OVERRIDE;
|
||||||
void writeMessageInternal(const QString &msg) const QTC_OVERRIDE;
|
void writeMessageInternal(const QString &msg) const QTC_OVERRIDE;
|
||||||
ModelManagerInterface::ProjectInfo defaultProjectInfo() const QTC_OVERRIDE;
|
|
||||||
WorkingCopy workingCopyInternal() const QTC_OVERRIDE;
|
WorkingCopy workingCopyInternal() const QTC_OVERRIDE;
|
||||||
void addTaskInternal(QFuture<void> result, const QString &msg, const char *taskId) const QTC_OVERRIDE;
|
void addTaskInternal(QFuture<void> result, const QString &msg, const char *taskId) const QTC_OVERRIDE;
|
||||||
|
private slots:
|
||||||
|
void updateDefaultProjectInfo();
|
||||||
private:
|
private:
|
||||||
void loadDefaultQmlTypeDescriptions();
|
void loadDefaultQmlTypeDescriptions();
|
||||||
static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType);
|
static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType);
|
||||||
|
Reference in New Issue
Block a user