From 16b4e4e91ffc04c86cdb6afc67d6a4acc26e734d Mon Sep 17 00:00:00 2001
From: Christian Kamm <christian.d.kamm@nokia.com>
Date: Tue, 22 Jun 2010 12:54:19 +0200
Subject: [PATCH] QmlJS: Fix import path handling in the model manager.

Previously, the model manager always had exactly one import path - but
you can open more than one Qml project at once. Now, we store the union
of all import paths in the model manager.

Reviewed-by: Roberto Raggi
---
 src/libs/qmljs/qmljsmodelmanagerinterface.h   | 36 +++++++++-
 src/plugins/qmljseditor/qmljsmodelmanager.cpp | 66 ++++++++++++++-----
 src/plugins/qmljseditor/qmljsmodelmanager.h   | 12 +++-
 src/plugins/qmlprojectmanager/qmlproject.cpp  | 12 ++--
 src/plugins/qmlprojectmanager/qmlproject.h    |  1 -
 5 files changed, 98 insertions(+), 29 deletions(-)

diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h
index 58e56a6c337..bf00b137453 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.h
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h
@@ -36,6 +36,11 @@
 #include <QObject>
 #include <QStringList>
 #include <QSharedPointer>
+#include <QPointer>
+
+namespace ProjectExplorer {
+    class Project;
+}
 
 namespace QmlJS {
 
@@ -45,6 +50,32 @@ class QMLJS_EXPORT ModelManagerInterface: public QObject
 {
     Q_OBJECT
 
+public:
+    class ProjectInfo
+    {
+    public:
+        ProjectInfo()
+        { }
+
+        ProjectInfo(QPointer<ProjectExplorer::Project> project)
+            : project(project)
+        { }
+
+        operator bool() const
+        { return ! project.isNull(); }
+
+        bool isValid() const
+        { return ! project.isNull(); }
+
+        bool isNull() const
+        { return project.isNull(); }
+
+    public: // attributes
+        QPointer<ProjectExplorer::Project> project;
+        QStringList sourceFiles;
+        QStringList importPaths;
+    };
+
 public:
     ModelManagerInterface(QObject *parent = 0);
     virtual ~ModelManagerInterface();
@@ -55,7 +86,10 @@ public:
     virtual void fileChangedOnDisk(const QString &path) = 0;
     virtual void removeFiles(const QStringList &files) = 0;
 
-    virtual void setProjectImportPaths(const QStringList &importPaths) = 0;
+    virtual QList<ProjectInfo> projectInfos() const = 0;
+    virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const = 0;
+    virtual void updateProjectInfo(const ProjectInfo &pinfo) = 0;
+
     virtual QStringList importPaths() const = 0;
 
 signals:
diff --git a/src/plugins/qmljseditor/qmljsmodelmanager.cpp b/src/plugins/qmljseditor/qmljsmodelmanager.cpp
index bd5bd6a9e9b..1df8e4c8e70 100644
--- a/src/plugins/qmljseditor/qmljsmodelmanager.cpp
+++ b/src/plugins/qmljseditor/qmljsmodelmanager.cpp
@@ -39,6 +39,7 @@
 #include <qmljs/qmljsbind.h>
 #include <qmljs/parser/qmldirparser_p.h>
 #include <texteditor/itexteditor.h>
+#include <projectexplorer/project.h>
 
 #include <QDir>
 #include <QFile>
@@ -180,6 +181,33 @@ void ModelManager::removeFiles(const QStringList &files)
         _snapshot.remove(file);
 }
 
+QList<ModelManager::ProjectInfo> ModelManager::projectInfos() const
+{
+    QMutexLocker locker(&m_mutex);
+
+    return m_projects.values();
+}
+
+ModelManager::ProjectInfo ModelManager::projectInfo(ProjectExplorer::Project *project) const
+{
+    QMutexLocker locker(&m_mutex);
+
+    return m_projects.value(project, ProjectInfo(project));
+}
+
+void ModelManager::updateProjectInfo(const ProjectInfo &pinfo)
+{
+    if (! pinfo.isValid())
+        return;
+
+    {
+        QMutexLocker locker(&m_mutex);
+        m_projects.insert(pinfo.project, pinfo);
+    }
+
+    updateImportPaths();
+}
+
 void ModelManager::emitDocumentChangedOnDisk(Document::Ptr doc)
 { emit documentChangedOnDisk(doc); }
 
@@ -400,26 +428,9 @@ bool ModelManager::matchesMimeType(const Core::MimeType &fileMimeType, const Cor
     return false;
 }
 
-void ModelManager::setProjectImportPaths(const QStringList &importPaths)
-{
-    m_projectImportPaths = importPaths;
-
-    // check if any file in the snapshot imports something new in the new paths
-    Snapshot snapshot = _snapshot;
-    QStringList importedFiles;
-    QSet<QString> scannedPaths;
-    foreach (const Document::Ptr &doc, snapshot)
-        findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths);
-
-    updateSourceFiles(importedFiles, true);
-}
-
 QStringList ModelManager::importPaths() const
 {
-    QStringList paths;
-    paths << m_projectImportPaths;
-    paths << m_defaultImportPaths;
-    return paths;
+    return m_allImportPaths;
 }
 
 static QStringList environmentImportPaths()
@@ -471,6 +482,25 @@ void ModelManager::loadQmlPluginTypes(const QString &pluginPath)
     m_runningQmldumps.insert(process, pluginPath);
 }
 
+void ModelManager::updateImportPaths()
+{
+    QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
+    while (it.hasNext()) {
+        it.next();
+        m_allImportPaths += it.value().importPaths;
+    }
+    m_allImportPaths += m_defaultImportPaths;
+
+    // check if any file in the snapshot imports something new in the new paths
+    Snapshot snapshot = _snapshot;
+    QStringList importedFiles;
+    QSet<QString> scannedPaths;
+    foreach (const Document::Ptr &doc, snapshot)
+        findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths);
+
+    updateSourceFiles(importedFiles, true);
+}
+
 void ModelManager::qmlPluginTypeDumpDone(int exitCode)
 {
     QProcess *process = qobject_cast<QProcess *>(sender());
diff --git a/src/plugins/qmljseditor/qmljsmodelmanager.h b/src/plugins/qmljseditor/qmljsmodelmanager.h
index 4386c23dcd4..41d93fbf781 100644
--- a/src/plugins/qmljseditor/qmljsmodelmanager.h
+++ b/src/plugins/qmljseditor/qmljsmodelmanager.h
@@ -59,11 +59,14 @@ public:
     virtual void fileChangedOnDisk(const QString &path);
     virtual void removeFiles(const QStringList &files);
 
+    virtual QList<ProjectInfo> projectInfos() const;
+    virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const;
+    virtual void updateProjectInfo(const ProjectInfo &pinfo);
+
     void emitDocumentUpdated(QmlJS::Document::Ptr doc);
     void emitLibraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info);
     void emitDocumentChangedOnDisk(QmlJS::Document::Ptr doc);
 
-    virtual void setProjectImportPaths(const QStringList &importPaths);
     virtual QStringList importPaths() const;
 
 Q_SIGNALS:
@@ -97,17 +100,22 @@ protected:
     void loadQmlTypeDescriptions();
     void loadQmlPluginTypes(const QString &pluginPath);
 
+    void updateImportPaths();
+
 private:
     static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType);
 
     mutable QMutex m_mutex;
     Core::ICore *m_core;
     QmlJS::Snapshot _snapshot;
-    QStringList m_projectImportPaths;
+    QStringList m_allImportPaths;
     QStringList m_defaultImportPaths;
     QHash<QProcess *, QString> m_runningQmldumps;
 
     QFutureSynchronizer<void> m_synchronizer;
+
+    // project integration
+    QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
 };
 
 } // namespace Internal
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 0e65e689fdf..b8b01d4c46c 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -96,8 +96,6 @@ void QmlProject::parseProject(RefreshOptions options)
                     m_projectItem = qobject_cast<QmlProjectItem*>(component->create());
                     connect(m_projectItem.data(), SIGNAL(qmlFilesChanged(QSet<QString>, QSet<QString>)),
                             this, SLOT(refreshFiles(QSet<QString>, QSet<QString>)));
-                    connect(m_projectItem.data(), SIGNAL(importPathsChanged()), this, SLOT(refreshImportPaths()));
-                    refreshImportPaths();
                 } else {
                     Core::MessageManager *messageManager = Core::ICore::instance()->messageManager();
                     messageManager->printToOutputPane(tr("Error while loading project file!"));
@@ -126,6 +124,11 @@ void QmlProject::refresh(RefreshOptions options)
 
     if (options & Files)
         m_rootNode->refresh();
+
+    QmlJS::ModelManagerInterface::ProjectInfo pinfo(this);
+    pinfo.sourceFiles = files();
+    pinfo.importPaths = importPaths();
+    m_modelManager->updateProjectInfo(pinfo);
 }
 
 QStringList QmlProject::convertToAbsoluteFiles(const QStringList &paths) const
@@ -186,11 +189,6 @@ void QmlProject::refreshFiles(const QSet<QString> &/*added*/, const QSet<QString
         m_modelManager->removeFiles(removed.toList());
 }
 
-void QmlProject::refreshImportPaths()
-{
-    m_modelManager->setProjectImportPaths(importPaths());
-}
-
 QString QmlProject::displayName() const
 {
     return m_projectName;
diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h
index 8a510a66652..e9de0617115 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.h
+++ b/src/plugins/qmlprojectmanager/qmlproject.h
@@ -104,7 +104,6 @@ public:
 private slots:
     void refreshProjectFile();
     void refreshFiles(const QSet<QString> &added, const QSet<QString> &removed);
-    void refreshImportPaths();
 
 protected:
     bool fromMap(const QVariantMap &map);
-- 
GitLab