diff options
author | Fawzi Mohamed <[email protected]> | 2012-12-06 17:20:58 +0100 |
---|---|---|
committer | Fawzi Mohamed <[email protected]> | 2013-02-21 17:22:16 +0100 |
commit | 942326ae9bf96fc71264e2b31b106fa8622b831a (patch) | |
tree | 387748bc658f25d29928431ea424d2e72606b9c3 /src/plugins | |
parent | 6d3c271d53200ce66f32339766d1638ad5248686 (diff) |
qmljs: add infrastructure handling qml dialects better
QmlBundles enables us to treat the different qml
dialects differently.
Add imports completion.
Change-log: [Qml/JS Support] Corrected handling of QtQuick2 only features.
Change-log: [Qml/JS Support] Added import completion in editor.
Task-number: QTCREATORBUG-8750
Task-number: QTCREATORBUG-8624
Task-number: QTCREATORBUG-8584
Task-number: QTCREATORBUG-8583
Task-number: QTCREATORBUG-8429
Change-Id: I1384b1b23136a85b4d077895ea86f92960da9e71
Reviewed-by: Kai Koehne <[email protected]>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/qbsprojectmanager/qbsproject.cpp | 56 | ||||
-rw-r--r-- | src/plugins/qbsprojectmanager/qbsprojectmanager.qbs | 1 | ||||
-rw-r--r-- | src/plugins/qbsprojectmanager/qbsprojectmanager_dependencies.pri | 1 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmljscompletionassist.cpp | 34 | ||||
-rw-r--r-- | src/plugins/qmljstools/qmljsbundleprovider.cpp | 201 | ||||
-rw-r--r-- | src/plugins/qmljstools/qmljsbundleprovider.h | 80 | ||||
-rw-r--r-- | src/plugins/qmljstools/qmljsmodelmanager.cpp | 163 | ||||
-rw-r--r-- | src/plugins/qmljstools/qmljsmodelmanager.h | 10 | ||||
-rw-r--r-- | src/plugins/qmljstools/qmljstools.pro | 2 | ||||
-rw-r--r-- | src/plugins/qmljstools/qmljstools.qbs | 2 | ||||
-rw-r--r-- | src/plugins/qmljstools/qmljstoolsplugin.cpp | 2 | ||||
-rw-r--r-- | src/plugins/qmlprojectmanager/qmlproject.cpp | 27 | ||||
-rw-r--r-- | src/plugins/qt4projectmanager/qt4project.cpp | 42 | ||||
-rw-r--r-- | src/plugins/qt4projectmanager/qt4projectmanager.qbs | 1 | ||||
-rw-r--r-- | src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri | 1 |
15 files changed, 507 insertions, 116 deletions
diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index a4951882c07..5f85dd9669a 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -54,6 +54,7 @@ #include <projectexplorer/target.h> #include <projectexplorer/taskhub.h> #include <qtsupport/qtkitinformation.h> +#include <qmljstools/qmljsmodelmanager.h> #include <qmljs/qmljsmodelmanagerinterface.h> @@ -603,61 +604,10 @@ void QbsProject::updateCppCodeModel(const qbs::ProjectData *prj) void QbsProject::updateQmlJsCodeModel(const qbs::ProjectData *prj) { - // FIXME: No information about import directories, so ignore this for now. -#if 1 Q_UNUSED(prj); -#else - QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); - if (!modelManager) - return; - - QmlJS::ModelManagerInterface::ProjectInfo projectInfo = modelManager->projectInfo(this); - projectInfo.sourceFiles = m_projectFiles->files[QMLType]; - - FindQt4ProFiles findQt4ProFiles; - QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode()); - - projectInfo.importPaths.clear(); - foreach (Qt4ProFileNode *node, proFiles) { - projectInfo.importPaths.append(node->variableValue(QmlImportPathVar)); - } - - bool preferDebugDump = false; - projectInfo.tryQmlDump = false; - - ProjectExplorer::Target *t = activeTarget(); - ProjectExplorer::Kit *k = t ? t->kit() : ProjectExplorer::KitManager::instance()->defaultKit(); - QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k); - - if (t) { - if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(t->activeBuildConfiguration())) - preferDebugDump = bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild; - } else { - if (qtVersion) - preferDebugDump = qtVersion->defaultBuildConfig() & QtSupport::BaseQtVersion::DebugBuild; - } - if (qtVersion && qtVersion->isValid()) { - projectInfo.tryQmlDump = qtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT) - || qtVersion->type() == QLatin1String(QtSupport::Constants::SIMULATORQT); - projectInfo.qtImportsPath = qtVersion->qmakeProperty("QT_INSTALL_IMPORTS"); - if (!projectInfo.qtImportsPath.isEmpty()) - projectInfo.importPaths += projectInfo.qtImportsPath; - projectInfo.qtVersionString = qtVersion->qtVersionString(); - } - projectInfo.importPaths.removeDuplicates(); - - if (projectInfo.tryQmlDump) { - QtSupport::QmlDumpTool::pathAndEnvironment(this, qtVersion, - ToolChainKitInformation::toolChain(k), - preferDebugDump, &projectInfo.qmlDumpPath, - &projectInfo.qmlDumpEnvironment); - } else { - projectInfo.qmlDumpPath.clear(); - projectInfo.qmlDumpEnvironment.clear(); - } - + QmlJS::ModelManagerInterface::ProjectInfo projectInfo = + QmlJSTools::defaultProjectInfoForProject(this); modelManager->updateProjectInfo(projectInfo); -#endif } } // namespace Internal diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs index 7b0c2559d20..17ddb68285a 100644 --- a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs +++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs @@ -17,6 +17,7 @@ QtcPlugin { Depends { name: "TextEditor" } Depends { name: "QtSupport" } Depends { name: "QmlJS" } + Depends { name: "QmlJSTools" } Depends { name: "cpp" } diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager_dependencies.pri b/src/plugins/qbsprojectmanager/qbsprojectmanager_dependencies.pri index 03f29efcdb1..35151814588 100644 --- a/src/plugins/qbsprojectmanager/qbsprojectmanager_dependencies.pri +++ b/src/plugins/qbsprojectmanager/qbsprojectmanager_dependencies.pri @@ -2,3 +2,4 @@ include(../../plugins/projectexplorer/projectexplorer.pri) include(../../plugins/cpptools/cpptools.pri) include(../../plugins/texteditor/texteditor.pri) include(../../plugins/qtsupport/qtsupport.pri) +include(../../plugins/qmljstools/qmljstools.pri) diff --git a/src/plugins/qmljseditor/qmljscompletionassist.cpp b/src/plugins/qmljseditor/qmljscompletionassist.cpp index 0eacbcbe706..d1c559988b7 100644 --- a/src/plugins/qmljseditor/qmljscompletionassist.cpp +++ b/src/plugins/qmljseditor/qmljscompletionassist.cpp @@ -51,7 +51,9 @@ #include <qmljs/qmljsscanner.h> #include <qmljs/qmljsbind.h> #include <qmljs/qmljscompletioncontextfinder.h> +#include <qmljs/qmljsbundle.h> #include <qmljs/qmljsscopebuilder.h> +#include <projectexplorer/projectexplorer.h> #include <QFile> #include <QFileInfo> @@ -61,6 +63,7 @@ #include <QDirIterator> #include <QStringList> #include <QIcon> +#include <QTextDocumentFragment> using namespace QmlJS; using namespace QmlJSEditor; @@ -645,8 +648,37 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface } // currently path-in-stringliteral is the only completion available in imports - if (contextFinder.isInImport()) + if (contextFinder.isInImport()) { + QmlJS::ModelManagerInterface::ProjectInfo pInfo = QmlJS::ModelManagerInterface::instance() + ->projectInfo(ProjectExplorer::ProjectExplorerPlugin::currentProject()); + QmlBundle platform = pInfo.extendedBundle.bundleForLanguage(document->language()); + if (!platform.supportedImports().isEmpty()) { + QTextCursor tc(qmlInterface->textDocument()); + tc.setPosition(qmlInterface->position()); + QmlExpressionUnderCursor expressionUnderCursor; + expressionUnderCursor(tc); + QString libVersion = contextFinder.libVersionImport(); + if (!libVersion.isNull()) { + QStringList completions=platform.supportedImports().complete(libVersion, QString(), QmlJS::PersistentTrie::LookupFlags(QmlJS::PersistentTrie::CaseInsensitive|QmlJS::PersistentTrie::SkipChars|QmlJS::PersistentTrie::SkipSpaces)); + completions = QmlJS::PersistentTrie::matchStrengthSort(libVersion, completions); + + int toSkip = qMax(libVersion.lastIndexOf(QLatin1Char(' ')) + , libVersion.lastIndexOf(QLatin1Char('.'))); + if (++toSkip > 0) { + QStringList nCompletions; + QString prefix(libVersion.left(toSkip)); + nCompletions.reserve(completions.size()); + foreach (QString completion, completions) + if (completion.startsWith(prefix)) + nCompletions.append(completion.right(completion.size()-toSkip)); + completions = nCompletions; + } + addCompletions(&m_completions, completions, m_interface->fileNameIcon(), KeywordOrder); + return createContentProposal(); + } + } return 0; + } // member "a.bc<complete>" or function "foo(<complete>" completion if (completionOperator == QLatin1Char('.') diff --git a/src/plugins/qmljstools/qmljsbundleprovider.cpp b/src/plugins/qmljstools/qmljsbundleprovider.cpp new file mode 100644 index 00000000000..fa3933a0c43 --- /dev/null +++ b/src/plugins/qmljstools/qmljsbundleprovider.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmljsbundleprovider.h" + +#include <coreplugin/icore.h> +#include <extensionsystem/pluginmanager.h> +#include <projectexplorer/kit.h> +#include <projectexplorer/kit.h> +#include <projectexplorer/kitmanager.h> +#include <projectexplorer/project.h> +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/target.h> +#include <qmljs/qmljsbundle.h> +#include <qmljs/qmljsdocument.h> +#include <qtsupport/qtkitinformation.h> +#include <qtsupport/qtsupportconstants.h> + +#include <QDir> +#include <QFile> +#include <QHash> +#include <QHashIterator> +#include <QList> +#include <QMutex> +#include <QMutexLocker> +#include <QtAlgorithms> + +namespace QmlJSTools { + +namespace { +typedef QmlJS::Document::Language Language; +typedef QmlJS::QmlBundle QmlBundle; +typedef QmlJS::QmlLanguageBundles QmlLanguageBundles; +} + +/*! + \class QmlJSEditor::BasicBundleProvider + + \brief a class that sets up the default bundles for qt and various qml states. + */ +BasicBundleProvider::BasicBundleProvider(QObject *parent) : + IBundleProvider(parent) +{ } + +QmlBundle BasicBundleProvider::defaultBundle(const QString &bundleInfoName) +{ + static bool wroteErrors = false; + QmlBundle res; + QString defaultBundlePath = Core::ICore::resourcePath() + + QLatin1String("/qml-type-descriptions/") + + bundleInfoName; + if (!QFileInfo(defaultBundlePath).exists()) { + qWarning() << "BasicBundleProvider: ERROR " << defaultBundlePath + << " not found"; + return res; + } + QStringList errors; + if (!res.readFrom(defaultBundlePath, &errors) && ! wroteErrors) { + qWarning() << "BasicBundleProvider: ERROR reading " << defaultBundlePath + << " : " << errors; + wroteErrors = true; + } + return res; +} + +QmlBundle BasicBundleProvider::defaultQt4QtQuick1Bundle() +{ + return defaultBundle(QLatin1String("qt4QtQuick1-bundle.json")); +} + +QmlBundle BasicBundleProvider::defaultQt5QtQuick1Bundle() +{ + return defaultBundle(QLatin1String("qt5QtQuick1-bundle.json")); +} + +QmlBundle BasicBundleProvider::defaultQt5QtQuick2Bundle() +{ + return defaultBundle(QLatin1String("qt5QtQuick2-bundle.json")); +} + +QmlBundle BasicBundleProvider::defaultQbsBundle() +{ + return defaultBundle(QLatin1String("qbs-bundle.json")); +} + +QmlBundle BasicBundleProvider::defaultQmltypesBundle() +{ + return defaultBundle(QLatin1String("qmltypes-bundle.json")); +} + +QmlBundle BasicBundleProvider::defaultQmlprojectBundle() +{ + return defaultBundle(QLatin1String("qmlproject-bundle.json")); +} + +void BasicBundleProvider::mergeBundlesForKit(ProjectExplorer::Kit *kit + , QmlJS::QmlLanguageBundles &bundles + , const QHash<QString,QString> &replacements) +{ + typedef QmlJS::Document Doc; + QHash<QString,QString> myReplacements = replacements; + + bundles.mergeBundleForLanguage(Doc::QmlQbsLanguage, defaultQbsBundle()); + bundles.mergeBundleForLanguage(Doc::QmlTypeInfoLanguage, defaultQmltypesBundle()); + bundles.mergeBundleForLanguage(Doc::QmlProjectLanguage, defaultQmlprojectBundle()); + + QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(kit); + if (!qtVersion) { + QmlBundle b1(defaultQt4QtQuick1Bundle()); + bundles.mergeBundleForLanguage(Doc::QmlLanguage, b1); + bundles.mergeBundleForLanguage(Doc::QmlQtQuick1Language, b1); + QmlBundle b11(defaultQt5QtQuick1Bundle()); + bundles.mergeBundleForLanguage(Doc::QmlLanguage, b11); + bundles.mergeBundleForLanguage(Doc::QmlQtQuick1Language, b11); + QmlBundle b2(defaultQt5QtQuick2Bundle()); + bundles.mergeBundleForLanguage(Doc::QmlLanguage, b2); + bundles.mergeBundleForLanguage(Doc::QmlQtQuick2Language, b2); + return; + } + QString qtImportsPath = qtVersion->qmakeProperty("QT_INSTALL_IMPORTS"); + QString qtQmlPath = qtVersion->qmakeProperty("QT_INSTALL_QML"); + + Core::FeatureSet features = qtVersion->availableFeatures(); + if (features.contains(Core::Feature(QtSupport::Constants::FEATURE_QT_QUICK)) + || features.contains(Core::Feature(QtSupport::Constants::FEATURE_QT_QUICK_1)) + || features.contains(Core::Feature(QtSupport::Constants::FEATURE_QT_QUICK_1_1))) { + myReplacements.insert(QLatin1String("$(CURRENT_DIRECTORY)"), qtImportsPath); + QDir qtQuick1Bundles(qtImportsPath); + qtQuick1Bundles.setNameFilters(QStringList(QLatin1String("*-bundle.json"))); + QmlBundle qtQuick1Bundle; + QFileInfoList list = qtQuick1Bundles.entryInfoList(); + for (int i = 0; i < list.size(); ++i) { + QmlBundle bAtt; + QStringList errors; + if (!bAtt.readFrom(list.value(i).filePath(), &errors)) + qWarning() << "BasicBundleProvider: ERROR reading " << list[i].filePath() << " : " + << errors; + qtQuick1Bundle.merge(bAtt); + } + if (!qtQuick1Bundle.supportedImports().contains(QLatin1String("QtQuick 1."), + QmlJS::PersistentTrie::Partial)) { + if (qtVersion->qtVersion().majorVersion == 4) + qtQuick1Bundle.merge(defaultQt4QtQuick1Bundle()); + else if (qtVersion->qtVersion().majorVersion > 4) + qtQuick1Bundle.merge(defaultQt5QtQuick1Bundle()); + } + qtQuick1Bundle.replaceVars(myReplacements); + bundles.mergeBundleForLanguage(Doc::QmlLanguage, qtQuick1Bundle); + bundles.mergeBundleForLanguage(Doc::QmlQtQuick1Language, qtQuick1Bundle); + } + if (features.contains(Core::Feature(QtSupport::Constants::FEATURE_QT_QUICK_2))) { + myReplacements.insert(QLatin1String("$(CURRENT_DIRECTORY)"), qtQmlPath); + QDir qtQuick2Bundles(qtQmlPath); + qtQuick2Bundles.setNameFilters(QStringList(QLatin1String("*-bundle.json"))); + QmlBundle qtQuick2Bundle; + QFileInfoList list = qtQuick2Bundles.entryInfoList(); + for (int i = 0; i < list.size(); ++i) { + QmlBundle bAtt; + QStringList errors; + if (!bAtt.readFrom(list.value(i).filePath(), &errors)) + qWarning() << "BasicBundleProvider: ERROR reading " << list[i].filePath() << " : " + << errors; + qtQuick2Bundle.merge(bAtt); + } + if (!qtQuick2Bundle.supportedImports().contains(QLatin1String("QtQuick 2."), + QmlJS::PersistentTrie::Partial)) { + qtQuick2Bundle.merge(defaultQt5QtQuick2Bundle()); + } + qtQuick2Bundle.replaceVars(myReplacements); + bundles.mergeBundleForLanguage(Doc::QmlLanguage, qtQuick2Bundle); + bundles.mergeBundleForLanguage(Doc::QmlQtQuick2Language, qtQuick2Bundle); + } +} + +} // end namespace QmlJSTools diff --git a/src/plugins/qmljstools/qmljsbundleprovider.h b/src/plugins/qmljstools/qmljsbundleprovider.h new file mode 100644 index 00000000000..f02a6e3fe7e --- /dev/null +++ b/src/plugins/qmljstools/qmljsbundleprovider.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLJSBUNDLEPROVIDER_H +#define QMLJSBUNDLEPROVIDER_H + +#include <QObject> + +#include <qmljs/qmljsbundle.h> +#include <qmljs/qmljsdocument.h> + +#include "qmljstools_global.h" + +namespace ProjectExplorer { +class Kit; +class Project; +class Target; +} + +namespace QmlJSTools { + +class QMLJSTOOLS_EXPORT IBundleProvider : public QObject +{ + Q_OBJECT +public: + explicit IBundleProvider(QObject *parent = 0) + : QObject(parent) + { } + + virtual void mergeBundlesForKit(ProjectExplorer::Kit *kit, QmlJS::QmlLanguageBundles &bundles + , const QHash<QString,QString> &replacements) = 0; +}; + +class QMLJSTOOLS_EXPORT BasicBundleProvider : public IBundleProvider +{ + Q_OBJECT +public: + explicit BasicBundleProvider(QObject *parent = 0); + + virtual void mergeBundlesForKit(ProjectExplorer::Kit *kit, QmlJS::QmlLanguageBundles &bundles + , const QHash<QString,QString> &replacements); + + static QmlJS::QmlBundle defaultBundle(const QString &bundleInfoName); + static QmlJS::QmlBundle defaultQt4QtQuick1Bundle(); + static QmlJS::QmlBundle defaultQt5QtQuick1Bundle(); + static QmlJS::QmlBundle defaultQt5QtQuick2Bundle(); + static QmlJS::QmlBundle defaultQbsBundle(); + static QmlJS::QmlBundle defaultQmltypesBundle(); + static QmlJS::QmlBundle defaultQmlprojectBundle(); +}; + +} // end QmlJSTools namespace + +#endif // QMLJSBUNDLEPROVIDER_H diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index 6020dd9e551..36cac68fdac 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -32,6 +32,7 @@ #include "qmljsplugindumper.h" #include "qmljsfindexportedcpptypes.h" #include "qmljssemanticinfo.h" +#include "qmljsbundleprovider.h" #include <coreplugin/icore.h> #include <coreplugin/editormanager/editormanager.h> @@ -42,15 +43,25 @@ #include <cplusplus/CppDocument.h> #include <qmljs/qmljscontext.h> #include <qmljs/qmljsbind.h> +#include <qmljs/qmljsbundle.h> #include <qmljs/parser/qmldirparser_p.h> #include <texteditor/itexteditor.h> #include <texteditor/basetexteditor.h> +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/kit.h> +#include <projectexplorer/kitinformation.h> #include <projectexplorer/project.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/session.h> +#include <projectexplorer/target.h> +#include <projectexplorer/toolchain.h> #include <qtsupport/baseqtversion.h> +#include <qtsupport/qtkitinformation.h> +#include <qtsupport/qmldumptool.h> +#include <qtsupport/qtsupportconstants.h> #include <utils/hostosinfo.h> +#include <extensionsystem/pluginmanager.h> #include <QDir> #include <QFile> @@ -61,6 +72,7 @@ #include <QTextStream> #include <QCoreApplication> #include <QTimer> +#include <QRegExp> #include <QDebug> @@ -68,6 +80,104 @@ using namespace QmlJS; using namespace QmlJSTools; using namespace QmlJSTools::Internal; + +ModelManagerInterface::ProjectInfo QmlJSTools::defaultProjectInfoForProject( + ProjectExplorer::Project *project) +{ + ModelManagerInterface::ProjectInfo projectInfo(project); + ProjectExplorer::Target *activeTarget = 0; + if (project) { + Core::MimeDatabase *db = Core::ICore::mimeDatabase(); + QList<Core::MimeGlobPattern> globs; + QList<Core::MimeType> mimeTypes = db->mimeTypes(); + foreach (const Core::MimeType &mimeType, mimeTypes) + if (mimeType.type() == QLatin1String(Constants::QML_MIMETYPE) + || mimeType.subClassesOf().contains(QLatin1String(Constants::QML_MIMETYPE))) + globs << mimeType.globPatterns(); + if (globs.isEmpty()) + globs << Core::MimeGlobPattern(QRegExp(QLatin1String(".*\\.(?:qbs|qml|qmltypes|qmlproject)$"))); + foreach (const QString &filePath + , project->files(ProjectExplorer::Project::ExcludeGeneratedFiles)) + foreach (const Core::MimeGlobPattern &glob, globs) + if (glob.regExp().exactMatch(filePath)) + projectInfo.sourceFiles << filePath; + activeTarget = project->activeTarget(); + } + ProjectExplorer::Kit *activeKit = activeTarget ? activeTarget->kit() : + ProjectExplorer::KitManager::instance()->defaultKit(); + QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(activeKit); + + bool preferDebugDump = false; + bool setPreferDump = false; + projectInfo.tryQmlDump = false; + + if (activeTarget) { + if (ProjectExplorer::BuildConfiguration *bc = activeTarget->activeBuildConfiguration()) { + preferDebugDump = bc->buildType() == ProjectExplorer::BuildConfiguration::Debug; + setPreferDump = true; + } + } + if (!setPreferDump && qtVersion) + preferDebugDump = (qtVersion->defaultBuildConfig() & QtSupport::BaseQtVersion::DebugBuild); + if (qtVersion && qtVersion->isValid()) { + projectInfo.tryQmlDump = project && ( + qtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT) + || qtVersion->type() == QLatin1String(QtSupport::Constants::SIMULATORQT)); + projectInfo.qtQmlPath = qtVersion->qmakeProperty("QT_INSTALL_QML"); + projectInfo.qtImportsPath = qtVersion->qmakeProperty("QT_INSTALL_IMPORTS"); + projectInfo.qtVersionString = qtVersion->qtVersionString(); + } + + if (projectInfo.tryQmlDump) { + ProjectExplorer::ToolChain *toolChain = + ProjectExplorer::ToolChainKitInformation::toolChain(activeKit); + QtSupport::QmlDumpTool::pathAndEnvironment(project, qtVersion, + toolChain, + preferDebugDump, &projectInfo.qmlDumpPath, + &projectInfo.qmlDumpEnvironment); + } else { + projectInfo.qmlDumpPath.clear(); + projectInfo.qmlDumpEnvironment.clear(); + } + setupProjectInfoQmlBundles(projectInfo); + return projectInfo; +} + +void QmlJSTools::setupProjectInfoQmlBundles(ModelManagerInterface::ProjectInfo &projectInfo) +{ + ProjectExplorer::Target *activeTarget = 0; + if (projectInfo.project) { + activeTarget = projectInfo.project->activeTarget(); + } + ProjectExplorer::Kit *activeKit = activeTarget + ? activeTarget->kit() : ProjectExplorer::KitManager::instance()->defaultKit(); + QHash<QString, QString> replacements; + replacements.insert(QLatin1String("$(QT_INSTALL_IMPORTS)"), projectInfo.qtImportsPath); + replacements.insert(QLatin1String("$(QT_INSTALL_QML)"), projectInfo.qtQmlPath); + + QList<IBundleProvider *> bundleProviders = + ExtensionSystem::PluginManager::getObjects<IBundleProvider>(); + + foreach (IBundleProvider *bp, bundleProviders) { + if (bp) + bp->mergeBundlesForKit(activeKit, projectInfo.activeBundle, replacements); + } + projectInfo.extendedBundle = projectInfo.activeBundle; + + if (projectInfo.project) { + QSet<ProjectExplorer::Kit *> currentKits; + foreach (const ProjectExplorer::Target *t, projectInfo.project->targets()) + if (t->kit()) + currentKits.insert(t->kit()); + currentKits.remove(activeKit); + foreach (ProjectExplorer::Kit *kit, currentKits) { + foreach (IBundleProvider *bp, bundleProviders) + if (bp) + bp->mergeBundlesForKit(kit, projectInfo.extendedBundle, replacements); + } + } +} + static QStringList environmentImportPaths(); static void mergeSuffixes(QStringList &l1, const QStringList &l2) @@ -373,6 +483,7 @@ void ModelManager::updateProjectInfo(const ProjectInfo &pinfo) void ModelManager::removeProjectInfo(ProjectExplorer::Project *project) { ProjectInfo info(project); + info.sourceFiles.clear(); // update with an empty project info to clear data updateProjectInfo(info); @@ -382,6 +493,16 @@ void ModelManager::removeProjectInfo(ProjectExplorer::Project *project) } } +ModelManagerInterface::ProjectInfo ModelManager::projectInfoForPath(QString path) +{ + QMutexLocker locker(&m_mutex); + + foreach (const ProjectInfo &p, m_projects) + if (p.sourceFiles.contains(path)) + return p; + return ProjectInfo(); +} + void ModelManager::emitDocumentChangedOnDisk(Document::Ptr doc) { emit documentChangedOnDisk(doc); } @@ -660,6 +781,18 @@ QStringList ModelManager::importPaths() const return m_allImportPaths; } +QmlLanguageBundles ModelManager::activeBundles() const +{ + QMutexLocker l(&m_mutex); + return m_activeBundles; +} + +QmlLanguageBundles ModelManager::extendedBundles() const +{ + QMutexLocker l(&m_mutex); + return m_extendedBundles; +} + static QStringList environmentImportPaths() { QStringList paths; @@ -679,6 +812,8 @@ static QStringList environmentImportPaths() void ModelManager::updateImportPaths() { QStringList allImportPaths; + QmlLanguageBundles activeBundles; + QmlLanguageBundles extendedBundles; QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects); while (it.hasNext()) { it.next(); @@ -688,12 +823,40 @@ void ModelManager::updateImportPaths() allImportPaths += canonicalPath; } } + it.toFront(); + while (it.hasNext()) { + it.next(); + activeBundles.mergeLanguageBundles(it.value().activeBundle); + foreach (Document::Language l, it.value().activeBundle.languages()) { + foreach (const QString &path, it.value().activeBundle.bundleForLanguage(l) + .searchPaths().stringList()) { + const QString canonicalPath = QFileInfo(path).canonicalFilePath(); + if (!canonicalPath.isEmpty()) + allImportPaths += canonicalPath; + } + } + } + it.toFront(); + while (it.hasNext()) { + it.next(); + extendedBundles.mergeLanguageBundles(it.value().extendedBundle); + foreach (Document::Language 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; + } + } + } allImportPaths += m_defaultImportPaths; allImportPaths.removeDuplicates(); { QMutexLocker l(&m_mutex); m_allImportPaths = allImportPaths; + m_activeBundles = activeBundles; + m_extendedBundles = extendedBundles; } diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h index 571ea8b0550..3b0763f904a 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.h +++ b/src/plugins/qmljstools/qmljsmodelmanager.h @@ -82,12 +82,15 @@ public: virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const; virtual void updateProjectInfo(const ProjectInfo &pinfo); Q_SLOT virtual void removeProjectInfo(ProjectExplorer::Project *project); + virtual ProjectInfo projectInfoForPath(QString path); void updateDocument(QmlJS::Document::Ptr doc); void updateLibraryInfo(const QString &path, const QmlJS::LibraryInfo &info); void emitDocumentChangedOnDisk(QmlJS::Document::Ptr doc); virtual QStringList importPaths() const; + virtual QmlJS::QmlLanguageBundles activeBundles() const; + virtual QmlJS::QmlLanguageBundles extendedBundles() const; virtual void loadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri, const QString &importVersion); @@ -136,6 +139,8 @@ private: QmlJS::Snapshot _newestSnapshot; QStringList m_allImportPaths; QStringList m_defaultImportPaths; + QmlJS::QmlLanguageBundles m_activeBundles; + QmlJS::QmlLanguageBundles m_extendedBundles; QFutureSynchronizer<void> m_synchronizer; @@ -153,6 +158,11 @@ private: }; } // namespace Internal + +QMLJSTOOLS_EXPORT QmlJS::ModelManagerInterface::ProjectInfo defaultProjectInfoForProject( + ProjectExplorer::Project *project); +QMLJSTOOLS_EXPORT void setupProjectInfoQmlBundles(QmlJS::ModelManagerInterface::ProjectInfo &projectInfo); + } // namespace QmlJSTools #endif // QMLJSMODELMANAGER_H diff --git a/src/plugins/qmljstools/qmljstools.pro b/src/plugins/qmljstools/qmljstools.pro index b653f9b0843..575d486be1b 100644 --- a/src/plugins/qmljstools/qmljstools.pro +++ b/src/plugins/qmljstools/qmljstools.pro @@ -10,6 +10,7 @@ DEFINES += QMLJSTOOLS_LIBRARY } HEADERS += \ + $$PWD/qmljsbundleprovider.h \ $$PWD/qmljstoolsplugin.h \ $$PWD/qmljstoolsconstants.h \ $$PWD/qmljstoolssettings.h \ @@ -36,6 +37,7 @@ HEADERS += \ $$PWD/qmlconsoleproxymodel.h SOURCES += \ + $$PWD/qmljsbundleprovider.cpp \ $$PWD/qmljstoolsplugin.cpp \ $$PWD/qmljstoolssettings.cpp \ $$PWD/qmljscodestylepreferencesfactory.cpp \ diff --git a/src/plugins/qmljstools/qmljstools.qbs b/src/plugins/qmljstools/qmljstools.qbs index 9f62253750f..d787c842b1c 100644 --- a/src/plugins/qmljstools/qmljstools.qbs +++ b/src/plugins/qmljstools/qmljstools.qbs @@ -21,6 +21,8 @@ QtcPlugin { cpp.includePaths: base.concat("../../libs/3rdparty") files: [ + "qmljsbundleprovider.cpp", + "qmljsbundleprovider.h", "qmljscodestylepreferencesfactory.cpp", "qmljscodestylepreferencesfactory.h", "qmljscodestylesettingspage.cpp", diff --git a/src/plugins/qmljstools/qmljstoolsplugin.cpp b/src/plugins/qmljstools/qmljstoolsplugin.cpp index 22d6717294d..dc9ba4ec1bf 100644 --- a/src/plugins/qmljstools/qmljstoolsplugin.cpp +++ b/src/plugins/qmljstools/qmljstoolsplugin.cpp @@ -35,6 +35,7 @@ #include "qmljstoolsconstants.h" #include "qmljstoolssettings.h" #include "qmlconsolemanager.h" +#include "qmljsbundleprovider.h" #include <extensionsystem/pluginmanager.h> @@ -94,6 +95,7 @@ bool QmlJSToolsPlugin::initialize(const QStringList &arguments, QString *error) addAutoReleasedObject(locatorData); addAutoReleasedObject(new FunctionFilter(locatorData)); addAutoReleasedObject(new QmlJSCodeStyleSettingsPage); + addAutoReleasedObject(new BasicBundleProvider); // Menus Core::ActionContainer *mtools = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS); diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 7b0377d21af..abae2fc9d51 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -45,6 +45,7 @@ #include <qtsupport/qtversionmanager.h> #include <qtsupport/qtkitinformation.h> #include <qmljs/qmljsmodelmanagerinterface.h> +#include <qmljstools/qmljsmodelmanager.h> #include <utils/fileutils.h> #include <projectexplorer/kitinformation.h> #include <projectexplorer/kitmanager.h> @@ -184,32 +185,10 @@ void QmlProject::refresh(RefreshOptions options) if (options & Files) m_rootNode->refresh(); - QmlJS::ModelManagerInterface::ProjectInfo projectInfo(this); - projectInfo.sourceFiles = files(); + QmlJS::ModelManagerInterface::ProjectInfo projectInfo = + QmlJSTools::defaultProjectInfoForProject(this); projectInfo.importPaths = customImportPaths(); - QtSupport::BaseQtVersion *qtVersion = 0; - { - ProjectExplorer::Target *target = activeTarget(); - ProjectExplorer::Kit *kit = target ? target->kit() : ProjectExplorer::KitManager::instance()->defaultKit(); - ProjectExplorer::ToolChain *toolChain = ProjectExplorer::ToolChainKitInformation::toolChain(kit); - qtVersion = QtSupport::QtKitInformation::qtVersion(kit); - QtSupport::QmlDumpTool::pathAndEnvironment(this, qtVersion, toolChain, false, - &projectInfo.qmlDumpPath, &projectInfo.qmlDumpEnvironment); - } - - if (qtVersion) { - projectInfo.tryQmlDump = true; - projectInfo.qtImportsPath = qtVersion->qmakeProperty("QT_INSTALL_IMPORTS"); - projectInfo.qtQmlPath = qtVersion->qmakeProperty("QT_INSTALL_QML"); - projectInfo.qtVersionString = qtVersion->qtVersionString(); - - if (!projectInfo.qtQmlPath.isEmpty()) - projectInfo.importPaths += projectInfo.qtQmlPath; - if (!projectInfo.qtImportsPath.isEmpty()) - projectInfo.importPaths += projectInfo.qtImportsPath; - - } m_modelManager->updateProjectInfo(projectInfo); } diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index 2a630f96769..6dac1e54633 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -51,6 +51,7 @@ #include <extensionsystem/pluginmanager.h> #include <cpptools/ModelManagerInterface.h> #include <qmljs/qmljsmodelmanagerinterface.h> +#include <qmljstools/qmljsmodelmanager.h> #include <projectexplorer/buildtargetinfo.h> #include <projectexplorer/deploymentdata.h> #include <projectexplorer/toolchain.h> @@ -592,8 +593,8 @@ void Qt4Project::updateQmlJSCodeModel() if (!modelManager) return; - QmlJS::ModelManagerInterface::ProjectInfo projectInfo = modelManager->projectInfo(this); - projectInfo.sourceFiles = m_projectFiles->files[QMLType]; + QmlJS::ModelManagerInterface::ProjectInfo projectInfo = + QmlJSTools::defaultProjectInfoForProject(this); FindQt4ProFiles findQt4ProFiles; QList<Qt4ProFileNode *> proFiles = findQt4ProFiles(rootProjectNode()); @@ -616,47 +617,12 @@ void Qt4Project::updateQmlJSCodeModel() // This assumption fails when there are no QDeclarativeEngine/QDeclarativeView (QtQuick 1) // or QQmlEngine/QQuickView (QtQuick 2) instances. Core::Context pl(ProjectExplorer::Constants::LANG_CXX); - if (projectInfo.sourceFiles.count() && hasQmlLib) + if (m_projectFiles->files[QMLType].count() && hasQmlLib) pl.add(ProjectExplorer::Constants::LANG_QMLJS); setProjectLanguages(pl); - bool preferDebugDump = false; - projectInfo.tryQmlDump = false; - - ProjectExplorer::Target *t = activeTarget(); - ProjectExplorer::Kit *k = t ? t->kit() : ProjectExplorer::KitManager::instance()->defaultKit(); - QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k); - - if (t) { - if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(t->activeBuildConfiguration())) - preferDebugDump = bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild; - } else { - if (qtVersion) - preferDebugDump = qtVersion->defaultBuildConfig() & QtSupport::BaseQtVersion::DebugBuild; - } - if (qtVersion && qtVersion->isValid()) { - projectInfo.tryQmlDump = qtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT) - || qtVersion->type() == QLatin1String(QtSupport::Constants::SIMULATORQT); - projectInfo.qtQmlPath = qtVersion->qmakeProperty("QT_INSTALL_QML"); - if (!projectInfo.qtQmlPath.isEmpty()) - projectInfo.importPaths += projectInfo.qtQmlPath; - projectInfo.qtImportsPath = qtVersion->qmakeProperty("QT_INSTALL_IMPORTS"); - if (!projectInfo.qtImportsPath.isEmpty()) - projectInfo.importPaths += projectInfo.qtImportsPath; - projectInfo.qtVersionString = qtVersion->qtVersionString(); - } projectInfo.importPaths.removeDuplicates(); - if (projectInfo.tryQmlDump) { - QtSupport::QmlDumpTool::pathAndEnvironment(this, qtVersion, - ToolChainKitInformation::toolChain(k), - preferDebugDump, &projectInfo.qmlDumpPath, - &projectInfo.qmlDumpEnvironment); - } else { - projectInfo.qmlDumpPath.clear(); - projectInfo.qmlDumpEnvironment.clear(); - } - modelManager->updateProjectInfo(projectInfo); } diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.qbs b/src/plugins/qt4projectmanager/qt4projectmanager.qbs index 57502c1d0e7..1aee5b998bd 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.qbs +++ b/src/plugins/qt4projectmanager/qt4projectmanager.qbs @@ -14,6 +14,7 @@ QtcPlugin { Depends { name: "QmlJS" } Depends { name: "CPlusPlus" } Depends { name: "TextEditor" } + Depends { name: "QmlJSTools" } Depends { name: "cpp" } cpp.defines: base.concat([ diff --git a/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri b/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri index 2f469a603d1..35c58553abe 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri +++ b/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri @@ -3,3 +3,4 @@ include(../../plugins/qtsupport/qtsupport.pri) include(../../plugins/cpptools/cpptools.pri) include(../../plugins/debugger/debugger.pri) include(../../libs/qmljs/qmljs.pri) +include(../../plugins/qmljstools/qmljstools.pri) |