diff options
author | Fawzi Mohamed <fawzi.mohamed@digia.com> | 2014-04-11 23:07:52 +0200 |
---|---|---|
committer | Fawzi Mohamed <fawzi.mohamed@digia.com> | 2014-05-06 14:28:40 +0200 |
commit | 08163f3b9ae4692cc7f2b4b6fe6e7aa3b9f6c626 (patch) | |
tree | 4b1f52abdeec99b5ca3e43f6929df06c523371a8 | |
parent | 0ee870493003b8f7ee12799049a9a0f8d7a4e094 (diff) | |
download | qt-creator-08163f3b9ae4692cc7f2b4b6fe6e7aa3b9f6c626.tar.gz |
qmljs: better defaults, more uniform handling of paths
Uniform handling of the different qml dialects.
Now paths for a given document prefer the project of that document.
For Qt the following sequence is used:
- Qt of the project of the document
- Qt of the active target
- Qt used to run creator
Currently all paths of the open projects are still merged, but that
can be changed.
Change-Id: Iacf28d63184c05e2bcdfe0210ec472d2bf140d66
Reviewed-by: Thomas Hartmann <Thomas.Hartmann@digia.com>
-rw-r--r-- | src/libs/qmljs/qmljsmodelmanagerinterface.cpp | 250 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsmodelmanagerinterface.h | 19 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsviewercontext.cpp | 6 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsviewercontext.h | 5 | ||||
-rw-r--r-- | src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp | 2 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmljsfindreferences.cpp | 2 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp | 2 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmltaskmanager.cpp | 2 | ||||
-rw-r--r-- | src/plugins/qmljstools/qmljsmodelmanager.cpp | 19 |
9 files changed, 223 insertions, 84 deletions
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index 84ad6ad0ce..09195018d9 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -38,6 +38,7 @@ #include <cplusplus/cppmodelmanagerbase.h> #include <utils/function.h> #include <utils/hostosinfo.h> +#include <utils/runextensions.h> #include <QDebug> #include <QDir> @@ -49,7 +50,7 @@ #include <QTextStream> #include <QTimer> #include <QtAlgorithms> -#include <utils/runextensions.h> +#include <QLibraryInfo> #include <stdio.h> @@ -362,6 +363,32 @@ bool pInfoLessThanAll(const ModelManagerInterface::ProjectInfo &p1, const ModelM } return false; } + +bool pInfoLessThanImports(const ModelManagerInterface::ProjectInfo &p1, const ModelManagerInterface::ProjectInfo &p2) +{ + if (p1.qtQmlPath < p2.qtQmlPath) + return true; + if (p1.qtQmlPath > p2.qtQmlPath) + return false; + if (p1.qtImportsPath < p2.qtImportsPath) + return true; + if (p1.qtImportsPath > p2.qtImportsPath) + return false; + QStringList s1 = p1.importPaths; + QStringList s2 = p2.importPaths; + if (s1.size() < s2.size()) + return true; + if (s1.size() > s2.size()) + return false; + for (int i = 0; i < s1.size(); ++i) { + if (s1.at(i) < s2.at(i)) + return true; + else if (s1.at(i) > s2.at(i)) + return false; + } + return false; +} + } QStringList ModelManagerInterface::filesAtQrcPath(const QString &path, const QLocale *locale, @@ -531,14 +558,32 @@ void ModelManagerInterface::removeProjectInfo(ProjectExplorer::Project *project) } } -ModelManagerInterface::ProjectInfo ModelManagerInterface::projectInfoForPath(QString path) +ModelManagerInterface::ProjectInfo ModelManagerInterface::projectInfoForPath(QString path) const { - QMutexLocker locker(&m_mutex); - - foreach (const ProjectInfo &p, m_projects) - if (p.sourceFiles.contains(path)) - return p; - return ProjectInfo(); + QList<ProjectExplorer::Project *> projects; + { + QMutexLocker locker(&m_mutex); + projects = m_fileToProject.values(path); + } + QList<ProjectInfo> infos; + foreach (ProjectExplorer::Project *project, projects) { + ProjectInfo info = projectInfo(project); + if (info.isValid()) + infos.append(info); + } + std::sort(infos.begin(), infos.end(), &pInfoLessThanImports); + + ProjectInfo res; + foreach (const ProjectInfo &pInfo, infos) { + if (res.qtImportsPath.isEmpty()) + res.qtImportsPath = pInfo.qtImportsPath; + if (res.qtQmlPath.isEmpty()) + res.qtQmlPath = pInfo.qtQmlPath; + foreach (const QString &path, pInfo.importPaths) + if (res.importPaths.contains(path)) + res.importPaths.append(path); + } + return res; } void ModelManagerInterface::emitDocumentChangedOnDisk(Document::Ptr doc) @@ -1003,21 +1048,26 @@ void ModelManagerInterface::updateImportPaths() QStringList allImportPaths; QmlLanguageBundles activeBundles; QmlLanguageBundles extendedBundles; - QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects); - while (it.hasNext()) { - it.next(); - foreach (const QString &path, it.value().importPaths) { + QMapIterator<ProjectExplorer::Project *, ProjectInfo> pInfoIter(m_projects); + QHashIterator<Language::Enum, QmlJS::ViewerContext> vCtxsIter = m_defaultVContexts; + while (pInfoIter.hasNext()) { + pInfoIter.next(); + foreach (const QString &path, pInfoIter.value().importPaths) { const QString canonicalPath = QFileInfo(path).canonicalFilePath(); if (!canonicalPath.isEmpty()) allImportPaths += canonicalPath; } } - it.toFront(); - while (it.hasNext()) { - it.next(); - activeBundles.mergeLanguageBundles(it.value().activeBundle); - foreach (Language::Enum l, it.value().activeBundle.languages()) { - foreach (const QString &path, it.value().activeBundle.bundleForLanguage(l) + while (vCtxsIter.hasNext()) { + vCtxsIter.next(); + allImportPaths << vCtxsIter.value().paths; + } + pInfoIter.toFront(); + while (pInfoIter.hasNext()) { + pInfoIter.next(); + activeBundles.mergeLanguageBundles(pInfoIter.value().activeBundle); + foreach (Language::Enum l, pInfoIter.value().activeBundle.languages()) { + foreach (const QString &path, pInfoIter.value().activeBundle.bundleForLanguage(l) .searchPaths().stringList()) { const QString canonicalPath = QFileInfo(path).canonicalFilePath(); if (!canonicalPath.isEmpty()) @@ -1025,18 +1075,33 @@ void ModelManagerInterface::updateImportPaths() } } } - it.toFront(); - while (it.hasNext()) { - it.next(); - extendedBundles.mergeLanguageBundles(it.value().extendedBundle); - foreach (Language::Enum l, it.value().extendedBundle.languages()) { - foreach (const QString &path, it.value().extendedBundle.bundleForLanguage(l) - .searchPaths().stringList()) { - const QString canonicalPath = QFileInfo(path).canonicalFilePath(); - if (!canonicalPath.isEmpty()) - allImportPaths += canonicalPath; - } - } + pInfoIter.toFront(); + while (pInfoIter.hasNext()) { + pInfoIter.next(); + QString pathAtt = pInfoIter.value().qtQmlPath; + if (!pathAtt.isEmpty() && allImportPaths.size() > 0 + && allImportPaths.value(allImportPaths.size()) != pathAtt) + allImportPaths.append(pathAtt); + } + { + QString pathAtt = defaultProjectInfo().qtQmlPath; + if (!pathAtt.isEmpty() && allImportPaths.size() > 0 + && allImportPaths.value(allImportPaths.size()) != pathAtt) + allImportPaths.append(pathAtt); + } + pInfoIter.toFront(); + while (pInfoIter.hasNext()) { + pInfoIter.next(); + QString pathAtt = pInfoIter.value().qtImportsPath; + if (!pathAtt.isEmpty() && allImportPaths.size() > 0 + && allImportPaths.value(allImportPaths.size()) != pathAtt) + allImportPaths.append(pathAtt); + } + { + QString pathAtt = defaultProjectInfo().qtImportsPath; + if (!pathAtt.isEmpty() && allImportPaths.size() > 0 + && allImportPaths.value(allImportPaths.size()) != pathAtt) + allImportPaths.append(pathAtt); } allImportPaths += m_defaultImportPaths; allImportPaths.removeDuplicates(); @@ -1064,13 +1129,6 @@ void ModelManagerInterface::updateImportPaths() maybeScan(allImportPaths, Language::Qml); } -ModelManagerInterface::ProjectInfo ModelManagerInterface::defaultProjectInfo() const -{ - if (m_projects.isEmpty()) - return ProjectInfo(); - return m_projects.begin().value(); -} - void ModelManagerInterface::loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri, const QString &importVersion) { @@ -1185,54 +1243,124 @@ ModelManagerInterface::CppDataHash ModelManagerInterface::cppData() const LibraryInfo ModelManagerInterface::builtins(const Document::Ptr &doc) const { - QList<ProjectExplorer::Project *> projects = m_fileToProject.values(doc->fileName()); - - ProjectExplorer::Project *project = 0; - foreach (ProjectExplorer::Project *p, projects) { - if (p) { - project = p; - break; - } - } - - if (!project) - return LibraryInfo(); - - QMutexLocker locker(&m_mutex); - ProjectInfo info = m_projects.value(project); + ProjectInfo info = projectInfoForPath(doc->path()); if (!info.isValid()) return LibraryInfo(); - return m_validSnapshot.libraryInfo(info.qtImportsPath); } ViewerContext ModelManagerInterface::completeVContext(const ViewerContext &vCtx, - const Document::Ptr &doc) const + const Document::Ptr &doc) const { - Q_UNUSED(doc); ViewerContext res = vCtx; + + if (vCtx.language == Language::Qml && !doc.isNull() && + (doc->language() == Language::QmlQtQuick1 || doc->language() == Language::QmlQtQuick2)) + res.language = doc->language(); + ProjectInfo info; + if (!doc.isNull()) + info = projectInfoForPath(doc->path()); + ViewerContext defaultVCtx = defaultVContext(res.language, Document::Ptr(0), false); + ProjectInfo defaultInfo = defaultProjectInfo(); + if (info.qtImportsPath.isEmpty()) + info.qtImportsPath = defaultInfo.qtImportsPath; + if (info.qtQmlPath.isEmpty()) + info.qtQmlPath = defaultInfo.qtQmlPath; switch (res.flags) { case ViewerContext::Complete: break; - case ViewerContext::AddQtPath: + case ViewerContext::AddAllPathsAndDefaultSelectors: + res.selectors.append(defaultVCtx.selectors); + // fallthrough case ViewerContext::AddAllPaths: - res.paths << importPaths(); + { + foreach (const QString &path, defaultVCtx.paths) + res.maybeAddPath(path); + switch (res.language) { + case Language::Unknown: + case Language::Qml: + res.maybeAddPath(info.qtQmlPath); + // fallthrough + case Language::QmlQtQuick1: + res.maybeAddPath(info.qtImportsPath); + // fallthrough + case Language::QmlQtQuick2: + { + if (res.language == Language::QmlQtQuick2) + res.maybeAddPath(info.qtQmlPath); + QList<ProjectInfo> allProjects; + { + QMutexLocker locker(&m_mutex); + allProjects = m_projects.values(); + } + std::sort(allProjects.begin(), allProjects.end(), &pInfoLessThanImports); + foreach (const ProjectInfo &pInfo, allProjects) { + foreach (const QString &path, pInfo.importPaths) + res.maybeAddPath(path); + } + break; + } + case Language::JavaScript: + case Language::QmlTypeInfo: + case Language::Json: + case Language::QmlQbs: + case Language::QmlProject: + break; + } + break; + } + case ViewerContext::AddDefaultPathsAndSelectors: + res.selectors.append(defaultVCtx.selectors); + // fallthrough + case ViewerContext::AddDefaultPaths: + foreach (const QString &path, defaultVCtx.paths) + res.maybeAddPath(path); + if (res.language == Language::Unknown || res.language == Language::Qml + || res.language == Language::QmlQtQuick2) + res.maybeAddPath(info.qtImportsPath); + if (res.language == Language::Unknown || res.language == Language::Qml + || res.language == Language::QmlQtQuick1) + res.maybeAddPath(info.qtQmlPath); + break; } res.flags = ViewerContext::Complete; return res; } -ViewerContext ModelManagerInterface::defaultVContext(bool autoComplete, const Document::Ptr &doc) const +ViewerContext ModelManagerInterface::defaultVContext(Language::Enum language, + const Document::Ptr &doc, + bool autoComplete) const { + if (!doc.isNull()) { + if (language == Language::Unknown) + language = doc->language(); + else if (language == Language::Qml && + (doc->language() == Language::QmlQtQuick1 || doc->language() == Language::QmlQtQuick2)) + language = doc->language(); + } + ViewerContext defaultCtx; + { + QMutexLocker locker(&m_mutex); + defaultCtx = m_defaultVContexts.value(language); + } if (autoComplete) - return completeVContext(m_vContext, doc); + return completeVContext(defaultCtx, doc); else - return m_vContext; + return defaultCtx; +} + +ModelManagerInterface::ProjectInfo ModelManagerInterface::defaultProjectInfo() const +{ + ProjectInfo res; + res.qtImportsPath = QLibraryInfo::location(QLibraryInfo::ImportsPath); + res.qtQmlPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); + return res; } void ModelManagerInterface::setDefaultVContext(const ViewerContext &vContext) { - m_vContext = vContext; + QMutexLocker locker(&m_mutex); + m_defaultVContexts[vContext.language] = vContext; } void ModelManagerInterface::joinAllThreads() diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index 0dc2cb7142..e8b4748932 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -177,7 +177,7 @@ public: void updateLibraryInfo(const QString &path, const QmlJS::LibraryInfo &info); void emitDocumentChangedOnDisk(QmlJS::Document::Ptr doc); void updateQrcFile(const QString &path); - ProjectInfo projectInfoForPath(QString path); + ProjectInfo projectInfoForPath(QString path) const; QStringList importPaths() const; QmlJS::QmlLanguageBundles activeBundles() const; @@ -188,17 +188,16 @@ public: CppDataHash cppData() const; LibraryInfo builtins(const Document::Ptr &doc) const; - virtual ViewerContext completeVContext(const ViewerContext &vCtx, - const Document::Ptr &doc = Document::Ptr(0)) const; - virtual ViewerContext defaultVContext(bool autoComplete = true, - const Document::Ptr &doc = Document::Ptr(0)) const; - virtual void setDefaultVContext(const ViewerContext &vContext); + ViewerContext completeVContext(const ViewerContext &vCtx, + const Document::Ptr &doc = Document::Ptr(0)) const; + ViewerContext defaultVContext(Language::Enum language = Language::Qml, + const Document::Ptr &doc = Document::Ptr(0), + bool autoComplete = true) const; + void setDefaultVContext(const ViewerContext &vContext); + virtual ProjectInfo defaultProjectInfo() const; // Blocks until all parsing threads are done. Used for testing. void joinAllThreads(); - - virtual ModelManagerInterface::ProjectInfo defaultProjectInfo() const; - public slots: virtual void resetCodeModel(); void removeProjectInfo(ProjectExplorer::Project *project); @@ -256,7 +255,7 @@ private: QStringList m_defaultImportPaths; QmlJS::QmlLanguageBundles m_activeBundles; QmlJS::QmlLanguageBundles m_extendedBundles; - QmlJS::ViewerContext m_vContext; + QHash<Language::Enum, QmlJS::ViewerContext> m_defaultVContexts; bool m_shouldScanImports; QSet<QString> m_scannedPaths; diff --git a/src/libs/qmljs/qmljsviewercontext.cpp b/src/libs/qmljs/qmljsviewercontext.cpp index 3a7e7c945e..4750c23f53 100644 --- a/src/libs/qmljs/qmljsviewercontext.cpp +++ b/src/libs/qmljs/qmljsviewercontext.cpp @@ -76,4 +76,10 @@ bool ViewerContext::languageIsCompatible(Language::Enum l) const return true; } +void ViewerContext::maybeAddPath(const QString &path) +{ + if (!path.isEmpty() && !paths.contains(path)) + paths.append(path); +} + } // namespace QmlJS diff --git a/src/libs/qmljs/qmljsviewercontext.h b/src/libs/qmljs/qmljsviewercontext.h index 32a93e9c95..f4b3639226 100644 --- a/src/libs/qmljs/qmljsviewercontext.h +++ b/src/libs/qmljs/qmljsviewercontext.h @@ -42,8 +42,10 @@ class QMLJS_EXPORT ViewerContext public: enum Flags { Complete, + AddAllPathsAndDefaultSelectors, AddAllPaths, - AddQtPath + AddDefaultPaths, + AddDefaultPathsAndSelectors }; ViewerContext(); @@ -52,6 +54,7 @@ public: Flags flags = AddAllPaths); bool languageIsCompatible(Language::Enum l) const; + void maybeAddPath(const QString &path); QStringList selectors; QStringList paths; diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp index 2b1723f164..3fd8985324 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp @@ -103,7 +103,7 @@ static inline bool checkIfDerivedFromItem(const QString &fileName) snapshot.insert(document); - QmlJS::Link link(snapshot, modelManager->defaultVContext(), QmlJS::ModelManagerInterface::instance()->builtins(document)); + QmlJS::Link link(snapshot, modelManager->defaultVContext(document->language(), document), QmlJS::ModelManagerInterface::instance()->builtins(document)); QList<QmlJS::DiagnosticMessage> diagnosticLinkMessages; QmlJS::ContextPtr context = link(document, &diagnosticLinkMessages); diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp index b92341637d..4258a14719 100644 --- a/src/plugins/qmljseditor/qmljsfindreferences.cpp +++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp @@ -831,7 +831,7 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future, QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); - Link link(snapshot, modelManager->defaultVContext(), modelManager->builtins(doc)); + Link link(snapshot, modelManager->defaultVContext(doc->language(), doc), modelManager->builtins(doc)); ContextPtr context = link(); ScopeChain scopeChain(doc, context); diff --git a/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp b/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp index 64b44e4978..84d280aa24 100644 --- a/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp +++ b/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp @@ -122,7 +122,7 @@ QmlJSTools::SemanticInfo SemanticInfoUpdater::makeNewSemanticInfo(const QmlJS::D ModelManagerInterface *modelManager = ModelManagerInterface::instance(); - Link link(semanticInfo.snapshot, modelManager->defaultVContext(), modelManager->builtins(doc)); + Link link(semanticInfo.snapshot, modelManager->defaultVContext(doc->language(), doc), modelManager->builtins(doc)); semanticInfo.context = link(doc, &semanticInfo.semanticMessages); ScopeChain *scopeChain = new ScopeChain(doc, semanticInfo.context); diff --git a/src/plugins/qmljseditor/qmltaskmanager.cpp b/src/plugins/qmljseditor/qmltaskmanager.cpp index 496720e15a..0b54640fdc 100644 --- a/src/plugins/qmljseditor/qmltaskmanager.cpp +++ b/src/plugins/qmljseditor/qmltaskmanager.cpp @@ -161,7 +161,7 @@ void QmlTaskManager::updateMessagesNow(bool updateSemantic) QFuture<FileErrorMessages> future = QtConcurrent::run<FileErrorMessages>( &collectMessages, modelManager->newestSnapshot(), modelManager->projectInfos(), - modelManager->defaultVContext(), updateSemantic); + modelManager->defaultVContext(Language::Unknown), updateSemantic); m_messageCollector.setFuture(future); } diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index 51144b8dbc..d0abc0beac 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -61,6 +61,8 @@ #include <QTimer> #include <QRegExp> #include <QtAlgorithms> +#include <QLibraryInfo> +#include <qglobal.h> #include <QDebug> @@ -87,8 +89,8 @@ ModelManagerInterface::ProjectInfo QmlJSTools::defaultProjectInfoForProject( globs.append(MimeGlobPattern(QLatin1String("*.qmltypes"))); globs.append(MimeGlobPattern(QLatin1String("*.qmlproject"))); } - foreach (const QString &filePath - , project->files(ProjectExplorer::Project::ExcludeGeneratedFiles)) + foreach (const QString &filePath, + project->files(ProjectExplorer::Project::ExcludeGeneratedFiles)) foreach (const MimeGlobPattern &glob, globs) if (glob.matches(filePath)) projectInfo.sourceFiles << filePath; @@ -117,6 +119,10 @@ ModelManagerInterface::ProjectInfo QmlJSTools::defaultProjectInfoForProject( projectInfo.qtQmlPath = qtVersion->qmakeProperty("QT_INSTALL_QML"); projectInfo.qtImportsPath = qtVersion->qmakeProperty("QT_INSTALL_IMPORTS"); projectInfo.qtVersionString = qtVersion->qtVersionString(); + } else { + projectInfo.qtQmlPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); + projectInfo.qtImportsPath = QLibraryInfo::location(QLibraryInfo::ImportsPath); + projectInfo.qtVersionString = QLatin1String(qVersion()); } if (projectInfo.tryQmlDump) { @@ -251,11 +257,9 @@ ModelManagerInterface::WorkingCopy ModelManager::workingCopyInternal() const ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfo() const { - ProjectExplorer::Project *activeProject = ProjectExplorer::SessionManager::startupProject(); - if (!activeProject) - return ModelManagerInterface::ProjectInfo(); - - return projectInfo(activeProject); + // needs to be performed in the ui therad (change?) + ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectExplorerPlugin::currentProject(); + return defaultProjectInfoForProject(currentProject); } // Check whether fileMimeType is the same or extends knownMimeType @@ -279,4 +283,3 @@ void ModelManager::addTaskInternal(QFuture<void> result, const QString &msg, con { ProgressManager::addTask(result, msg, taskId); } - |