aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorFawzi Mohamed <[email protected]>2012-12-06 17:20:58 +0100
committerFawzi Mohamed <[email protected]>2013-02-21 17:22:16 +0100
commit942326ae9bf96fc71264e2b31b106fa8622b831a (patch)
tree387748bc658f25d29928431ea424d2e72606b9c3 /src/plugins
parent6d3c271d53200ce66f32339766d1638ad5248686 (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.cpp56
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.qbs1
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager_dependencies.pri1
-rw-r--r--src/plugins/qmljseditor/qmljscompletionassist.cpp34
-rw-r--r--src/plugins/qmljstools/qmljsbundleprovider.cpp201
-rw-r--r--src/plugins/qmljstools/qmljsbundleprovider.h80
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.cpp163
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.h10
-rw-r--r--src/plugins/qmljstools/qmljstools.pro2
-rw-r--r--src/plugins/qmljstools/qmljstools.qbs2
-rw-r--r--src/plugins/qmljstools/qmljstoolsplugin.cpp2
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp27
-rw-r--r--src/plugins/qt4projectmanager/qt4project.cpp42
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanager.qbs1
-rw-r--r--src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri1
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)