aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/libs/qmljs/qmljsdocument.cpp1
-rw-r--r--src/libs/qmljs/qmljsdocument.h7
-rw-r--r--src/libs/qmljs/qmljsinterpreter.cpp12
-rw-r--r--src/libs/qmljs/qmljsinterpreter.h8
-rw-r--r--src/libs/qmljs/qmljsplugindumper.cpp133
-rw-r--r--src/libs/qmljs/qmljsplugindumper.h9
-rw-r--r--src/libs/qmljs/qmljstypedescriptionreader.cpp31
-rw-r--r--src/libs/qmljs/qmljstypedescriptionreader.h5
-rw-r--r--tests/auto/qml/codemodel/codemodel.pro4
-rw-r--r--tests/auto/qml/codemodel/dependencies/dependencies.pro20
-rw-r--r--tests/auto/qml/codemodel/dependencies/samples/001_ApplicationWindow.qml35
-rw-r--r--tests/auto/qml/codemodel/dependencies/samples/002_Window.qml34
-rw-r--r--tests/auto/qml/codemodel/dependencies/samples/SampleLib.qml32
-rw-r--r--tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp153
15 files changed, 458 insertions, 27 deletions
diff --git a/.gitignore b/.gitignore
index f100f3152c..92f7b6f6f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -187,6 +187,7 @@ tmp/
/tests/auto/ioutils/tst_ioutils
/tests/auto/profilewriter/tst_profilewriter
/tests/auto/qml/codemodel/check/tst_codemodel_check
+/tests/auto/qml/codemodel/dependencies/tst_dependencies
/tests/auto/qml/persistenttrie/tst_trie_check
/tests/auto/qml/qmldesigner/bauhaustests/tst_bauhaus
/tests/auto/qml/qmldesigner/coretests/tst_qmldesigner_core
diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp
index b61f44ca08..82cf503666 100644
--- a/src/libs/qmljs/qmljsdocument.cpp
+++ b/src/libs/qmljs/qmljsdocument.cpp
@@ -519,6 +519,7 @@ void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info)
foreach (const Export &e, cImport.possibleExports)
_dependencies.addExport(component.fileName, e.exportName, e.pathRequired, e.typeName);
}
+
cImport.fingerprint = info.fingerprint();
_dependencies.addCoreImport(cImport);
}
diff --git a/src/libs/qmljs/qmljsdocument.h b/src/libs/qmljs/qmljsdocument.h
index 0c39b52c02..5328fbe609 100644
--- a/src/libs/qmljs/qmljsdocument.h
+++ b/src/libs/qmljs/qmljsdocument.h
@@ -154,6 +154,7 @@ private:
typedef QList<LanguageUtils::FakeMetaObject::ConstPtr> FakeMetaObjectList;
FakeMetaObjectList _metaObjects;
QList<ModuleApiInfo> _moduleApis;
+ QStringList _dependencies;
QByteArray _fingerprint;
PluginTypeInfoStatus _dumpStatus;
@@ -190,6 +191,12 @@ public:
void setModuleApis(const QList<ModuleApiInfo> &apis)
{ _moduleApis = apis; }
+ QStringList dependencies() const
+ { return _dependencies; }
+
+ void setDependencies(const QStringList &deps)
+ { _dependencies = deps; }
+
bool isValid() const
{ return _status == Found; }
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index 078ee96ad8..b0d097beb4 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -1117,11 +1117,13 @@ const Value *ObjectValue::lookupMember(const QString &name, const Context *conte
}
}
+ const ObjectValue *prototypeObject = 0;
+
if (examinePrototypes && context) {
PrototypeIterator iter(this, context);
iter.next(); // skip this
while (iter.hasNext()) {
- const ObjectValue *prototypeObject = iter.next();
+ prototypeObject = iter.next();
if (const Value *m = prototypeObject->lookupMember(name, context, foundInObject, false))
return m;
}
@@ -1129,6 +1131,7 @@ const Value *ObjectValue::lookupMember(const QString &name, const Context *conte
if (foundInObject)
*foundInObject = 0;
+
return 0;
}
@@ -1346,6 +1349,7 @@ CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::defaultQtObjects;
CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::loadQmlTypes(const QFileInfoList &qmlTypeFiles, QStringList *errors, QStringList *warnings)
{
QHash<QString, FakeMetaObject::ConstPtr> newObjects;
+ QStringList newDependencies;
foreach (const QFileInfo &qmlTypeFile, qmlTypeFiles) {
QString error, warning;
@@ -1355,7 +1359,8 @@ CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::loadQmlTypes(const QFileInf
file.close();
- parseQmlTypeDescriptions(contents, &newObjects, 0, &error, &warning, qmlTypeFile.absoluteFilePath());
+ parseQmlTypeDescriptions(contents, &newObjects, 0, &newDependencies, &error, &warning,
+ qmlTypeFile.absoluteFilePath());
} else {
error = file.errorString();
}
@@ -1377,6 +1382,7 @@ CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::loadQmlTypes(const QFileInf
void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &contents,
BuiltinObjects *newObjects,
QList<ModuleApiInfo> *newModuleApis,
+ QStringList *newDependencies,
QString *errorMessage,
QString *warningMessage, const QString &fileName)
{
@@ -1396,7 +1402,7 @@ void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &contents,
errorMessage->clear();
warningMessage->clear();
TypeDescriptionReader reader(fileName, QString::fromUtf8(contents));
- if (!reader(newObjects, newModuleApis)) {
+ if (!reader(newObjects, newModuleApis, newDependencies)) {
if (reader.errorMessage().isEmpty())
*errorMessage = QLatin1String("unknown error");
else
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index f6a143a49e..806b858f39 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -720,8 +720,12 @@ public:
// parses the contents of a qmltypes file and fills the newObjects map
static void parseQmlTypeDescriptions(const QByteArray &contents,
- BuiltinObjects *newObjects,
- QList<ModuleApiInfo> *newModuleApis, QString *errorMessage, QString *warningMessage, const QString &fileName);
+ BuiltinObjects *newObjects,
+ QList<ModuleApiInfo> *newModuleApis,
+ QStringList *newDependencies,
+ QString *errorMessage,
+ QString *warningMessage,
+ const QString &fileName);
};
class QMLJS_EXPORT FakeMetaObjectWithOrigin
diff --git a/src/libs/qmljs/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp
index aa08ec044d..555b77671a 100644
--- a/src/libs/qmljs/qmljsplugindumper.cpp
+++ b/src/libs/qmljs/qmljsplugindumper.cpp
@@ -27,6 +27,7 @@
#include "qmljsmodelmanagerinterface.h"
#include <qmljs/qmljsinterpreter.h>
+#include <qmljs/qmljsviewercontext.h>
//#include <projectexplorer/session.h>
//#include <coreplugin/messagemanager.h>
#include <utils/filesystemwatcher.h>
@@ -309,7 +310,9 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
QString warning;
CppQmlTypesLoader::BuiltinObjects objectsList;
QList<ModuleApiInfo> moduleApis;
- CppQmlTypesLoader::parseQmlTypeDescriptions(output, &objectsList, &moduleApis, &error, &warning,
+ QStringList dependencies;
+ CppQmlTypesLoader::parseQmlTypeDescriptions(output, &objectsList, &moduleApis, &dependencies,
+ &error, &warning,
QLatin1String("<dump of ") + libraryPath + QLatin1Char('>'));
if (exitCode == 0) {
if (!error.isEmpty()) {
@@ -361,39 +364,131 @@ void PluginDumper::pluginChanged(const QString &pluginLibrary)
dump(plugin);
}
-void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
- const QString &libraryPath,
- QmlJS::LibraryInfo libraryInfo)
-{
- QStringList errors;
- QStringList warnings;
- QList<FakeMetaObject::ConstPtr> objects;
- QList<ModuleApiInfo> moduleApis;
-
- foreach (const QString &qmltypesFilePath, qmltypesFilePaths) {
+void PluginDumper::loadQmlTypeDescription(const QStringList &paths,
+ QStringList &errors,
+ QStringList &warnings,
+ QList<FakeMetaObject::ConstPtr> &objects,
+ QList<ModuleApiInfo> *moduleApi,
+ QStringList *dependencies) const {
+ for (const QString &p: paths) {
Utils::FileReader reader;
- if (!reader.fetch(qmltypesFilePath, QFile::Text)) {
+ if (!reader.fetch(p, QFile::Text)) {
errors += reader.errorString();
continue;
}
-
QString error;
QString warning;
- CppQmlTypesLoader::BuiltinObjects newObjects;
- QList<ModuleApiInfo> newModuleApis;
- CppQmlTypesLoader::parseQmlTypeDescriptions(reader.data(), &newObjects, &newModuleApis, &error, &warning, qmltypesFilePath);
+ CppQmlTypesLoader::BuiltinObjects objs;
+ QList<ModuleApiInfo> apis;
+ QStringList deps;
+ CppQmlTypesLoader::parseQmlTypeDescriptions(reader.data(), &objs, &apis, &deps,
+ &error, &warning, p);
if (!error.isEmpty()) {
- errors += tr("Failed to parse \"%1\".\nError: %2").arg(qmltypesFilePath, error);
+ errors += tr("Failed to parse \"%1\".\nError: %2").arg(p, error);
} else {
- objects += newObjects.values();
- moduleApis += newModuleApis;
+ objects += objs.values();
+ if (moduleApi)
+ *moduleApi += apis;
+ if (!deps.isEmpty())
+ *dependencies += deps;
}
if (!warning.isEmpty())
warnings += warning;
}
+}
+/*!
+ * \brief Build the path of an existing qmltypes file from a module name.
+ * \param name
+ * \return the module's qmltypes file path
+ *
+ * Look for \a name qmltypes file in model manager's import paths.
+ * For each import path the following files are searched, in this order:
+ *
+ * - <name>.<major>.<minor>/plugins.qmltypes
+ * - <name>.<major>/plugins.qmltypes
+ * - <name>/plugins.qmltypes
+ *
+ * That means that a more qualified directory name has precedence over a
+ * less qualified one. Be aware that the import paths order has a stronger
+ * precedence, so a less qualified name could shadow a more qualified one if
+ * it resides in a different import path.
+ *
+ * \sa LinkPrivate::importNonFile
+ */
+QString PluginDumper::buildQmltypesPath(const QString &name) const
+{
+ QStringList importName = name.split(QLatin1Char(' '));
+ QString qualifiedName = importName[0];
+ QString majorVersion;
+ QString minorVersion;
+ if (importName.length() == 2) {
+ QString versionString = importName[1];
+ QStringList version = versionString.split(QLatin1Char('.'));
+ if (version.length() == 2) {
+ majorVersion = version[0];
+ minorVersion = version[1];
+ }
+ }
+
+ for (const PathAndLanguage &p: m_modelManager->importPaths()) {
+ QString moduleName(qualifiedName.replace(QLatin1Char('.'), QLatin1Char('/')));
+ QString moduleNameMajor(moduleName + QLatin1Char('.') + majorVersion);
+ QString moduleNameMajorMinor(moduleNameMajor + QLatin1Char('.') + minorVersion);
+
+ for (const auto n: QStringList{moduleNameMajorMinor, moduleNameMajor, moduleName}) {
+ QString filename(p.path().toString() + QLatin1Char('/') + n
+ + QLatin1String("/plugins.qmltypes"));
+ if (QFile::exists(filename))
+ return filename;
+ }
+ }
+ return QString();
+}
+
+/*!
+ * \brief Recursively load dependencies.
+ * \param dependencies
+ * \param errors
+ * \param warnings
+ * \param objects
+ *
+ * Recursively load type descriptions of dependencies, collecting results
+ * in \a objects.
+ */
+void PluginDumper::loadDependencies(const QStringList &dependencies,
+ QStringList &errors,
+ QStringList &warnings,
+ QList<FakeMetaObject::ConstPtr> &objects) const
+{
+ QStringList dependenciesPaths;
+ QString path;
+ for (const QString &name: dependencies) {
+ path = buildQmltypesPath(name);
+ if (!path.isNull())
+ dependenciesPaths << path;
+ }
+ QStringList newDependencies;
+ loadQmlTypeDescription(dependenciesPaths, errors, warnings, objects, 0, &newDependencies);
+ if (!newDependencies.isEmpty())
+ loadDependencies(newDependencies, errors, warnings, objects);
+}
+
+void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
+ const QString &libraryPath,
+ QmlJS::LibraryInfo libraryInfo)
+{
+ QStringList errors;
+ QStringList warnings;
+ QList<FakeMetaObject::ConstPtr> objects;
+ QList<ModuleApiInfo> moduleApis;
+ QStringList dependencies;
+
+ loadQmlTypeDescription(qmltypesFilePaths, errors, warnings, objects, &moduleApis, &dependencies);
+ loadDependencies(dependencies, errors, warnings, objects);
libraryInfo.setMetaObjects(objects);
libraryInfo.setModuleApis(moduleApis);
+ libraryInfo.setDependencies(dependencies);
if (errors.isEmpty()) {
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::TypeInfoFileDone);
} else {
diff --git a/src/libs/qmljs/qmljsplugindumper.h b/src/libs/qmljs/qmljsplugindumper.h
index f0a716df9c..31c9b5e019 100644
--- a/src/libs/qmljs/qmljsplugindumper.h
+++ b/src/libs/qmljs/qmljsplugindumper.h
@@ -75,6 +75,15 @@ private:
void runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info, const QStringList &arguments, const QString &importPath);
void dump(const Plugin &plugin);
+ void loadQmlTypeDescription(const QStringList &path, QStringList &errors, QStringList &warnings,
+ QList<LanguageUtils::FakeMetaObject::ConstPtr> &objects,
+ QList<ModuleApiInfo> *moduleApi,
+ QStringList *dependencies) const;
+ QString buildQmltypesPath(const QString &name) const;
+ void loadDependencies(const QStringList &dependencies,
+ QStringList &errors,
+ QStringList &warnings,
+ QList<LanguageUtils::FakeMetaObject::ConstPtr> &objects) const;
void loadQmltypesFile(const QStringList &qmltypesFilePaths,
const QString &libraryPath,
QmlJS::LibraryInfo libraryInfo);
diff --git a/src/libs/qmljs/qmljstypedescriptionreader.cpp b/src/libs/qmljs/qmljstypedescriptionreader.cpp
index 5ada19fe12..ea660cd2ee 100644
--- a/src/libs/qmljs/qmljstypedescriptionreader.cpp
+++ b/src/libs/qmljs/qmljstypedescriptionreader.cpp
@@ -52,7 +52,8 @@ TypeDescriptionReader::~TypeDescriptionReader()
bool TypeDescriptionReader::operator()(
QHash<QString, FakeMetaObject::ConstPtr> *objects,
- QList<ModuleApiInfo> *moduleApis)
+ QList<ModuleApiInfo> *moduleApis,
+ QStringList *dependencies)
{
Engine engine;
@@ -71,6 +72,7 @@ bool TypeDescriptionReader::operator()(
_objects = objects;
_moduleApis = moduleApis;
+ _dependencies = dependencies;
readDocument(parser.ast());
return _errorMessage.isEmpty();
@@ -141,6 +143,12 @@ void TypeDescriptionReader::readModule(UiObjectDefinition *ast)
UiObjectMember *member = it->member;
UiObjectDefinition *component = dynamic_cast<UiObjectDefinition *>(member);
+ UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member);
+ if (script && (toString(script->qualifiedId) == QStringLiteral("dependencies"))) {
+ readDependencies(script);
+ continue;
+ }
+
QString typeName;
if (component)
typeName = toString(component->qualifiedTypeNameId);
@@ -174,6 +182,27 @@ void TypeDescriptionReader::addWarning(const SourceLocation &loc, const QString
message);
}
+void TypeDescriptionReader::readDependencies(UiScriptBinding *ast) {
+ ExpressionStatement *stmt = dynamic_cast<ExpressionStatement*>(ast->statement);
+ if (!stmt) {
+ addError(ast->statement->firstSourceLocation(), tr("Expected dependency definitions"));
+ return;
+ }
+ ArrayLiteral *exp = dynamic_cast<ArrayLiteral *>(stmt->expression);
+ if (!exp) {
+ addError(stmt->expression->firstSourceLocation(), tr("Expected dependency definitions"));
+ return;
+ }
+ for (ElementList *l = exp->elements; l; l = l->next) {
+ StringLiteral *str = dynamic_cast<StringLiteral *>(l->expression);
+ if (!exp) {
+ addWarning(l->expression->firstSourceLocation(),
+ tr("Cannot read dependency: skipping."));
+ }
+ *_dependencies << str->value.toString();
+ }
+}
+
void TypeDescriptionReader::readComponent(UiObjectDefinition *ast)
{
FakeMetaObject::Ptr fmo(new FakeMetaObject);
diff --git a/src/libs/qmljs/qmljstypedescriptionreader.h b/src/libs/qmljs/qmljstypedescriptionreader.h
index 85829d04ee..900ec38304 100644
--- a/src/libs/qmljs/qmljstypedescriptionreader.h
+++ b/src/libs/qmljs/qmljstypedescriptionreader.h
@@ -58,13 +58,15 @@ public:
bool operator()(
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *objects,
- QList<ModuleApiInfo> *moduleApis);
+ QList<ModuleApiInfo> *moduleApis,
+ QStringList *dependencies);
QString errorMessage() const;
QString warningMessage() const;
private:
void readDocument(AST::UiProgram *ast);
void readModule(AST::UiObjectDefinition *ast);
+ void readDependencies(AST::UiScriptBinding *ast);
void readComponent(AST::UiObjectDefinition *ast);
void readModuleApi(AST::UiObjectDefinition *ast);
void readSignalOrMethod(AST::UiObjectDefinition *ast, bool isMethod, LanguageUtils::FakeMetaObject::Ptr fmo);
@@ -90,6 +92,7 @@ private:
QString _warningMessage;
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *_objects;
QList<ModuleApiInfo> *_moduleApis;
+ QStringList *_dependencies;
};
} // namespace QmlJS
diff --git a/tests/auto/qml/codemodel/codemodel.pro b/tests/auto/qml/codemodel/codemodel.pro
index 2e42b5cb7c..61114626c1 100644
--- a/tests/auto/qml/codemodel/codemodel.pro
+++ b/tests/auto/qml/codemodel/codemodel.pro
@@ -1,4 +1,6 @@
TEMPLATE = subdirs
SUBDIRS += check \
- importscheck
+ importscheck \
+ dependencies
+
diff --git a/tests/auto/qml/codemodel/dependencies/dependencies.pro b/tests/auto/qml/codemodel/dependencies/dependencies.pro
new file mode 100644
index 0000000000..b56dfdbe6d
--- /dev/null
+++ b/tests/auto/qml/codemodel/dependencies/dependencies.pro
@@ -0,0 +1,20 @@
+QTC_LIB_DEPENDS += qmljs
+QTC_PLUGIN_DEPENDS += qmljstools
+
+include(../../../qttest.pri)
+
+DEFINES+=QTCREATORDIR=\\\"$$IDE_SOURCE_TREE\\\"
+DEFINES+=TESTSRCDIR=\\\"$$PWD\\\"
+
+QT += core
+QT -= gui
+
+CONFIG += c++11
+
+TARGET = tst_dependencies
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+SOURCES += tst_dependencies.cpp
diff --git a/tests/auto/qml/codemodel/dependencies/samples/001_ApplicationWindow.qml b/tests/auto/qml/codemodel/dependencies/samples/001_ApplicationWindow.qml
new file mode 100644
index 0000000000..6c55b2e8ab
--- /dev/null
+++ b/tests/auto/qml/codemodel/dependencies/samples/001_ApplicationWindow.qml
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtQuick.Controls 1.3
+
+ApplicationWindow {
+ title: qsTr("Hello World")
+ width: 640
+ height: 480
+ visible: true
+}
+
diff --git a/tests/auto/qml/codemodel/dependencies/samples/002_Window.qml b/tests/auto/qml/codemodel/dependencies/samples/002_Window.qml
new file mode 100644
index 0000000000..71dbbd2b7b
--- /dev/null
+++ b/tests/auto/qml/codemodel/dependencies/samples/002_Window.qml
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtQuick.Controls 1.3
+
+Window {
+ title: qsTr("Hello World")
+ width: 640
+ height: 480
+ visible: true
+}
diff --git a/tests/auto/qml/codemodel/dependencies/samples/SampleLib.qml b/tests/auto/qml/codemodel/dependencies/samples/SampleLib.qml
new file mode 100644
index 0000000000..2495247708
--- /dev/null
+++ b/tests/auto/qml/codemodel/dependencies/samples/SampleLib.qml
@@ -0,0 +1,32 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtQuick.Controls 1.4
+
+TreeView {
+ id: lib
+}
+
diff --git a/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp b/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
new file mode 100644
index 0000000000..ffa9e2f1eb
--- /dev/null
+++ b/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include <QString>
+#include <QStringList>
+#include <QFutureInterface>
+#include <QFile>
+#include <QTextStream>
+#include <QDateTime>
+#include <QLibraryInfo>
+#include <QtTest>
+
+#include <QDebug>
+
+#include <qmljs/qmljsinterpreter.h>
+#include <qmljs/qmljsdocument.h>
+#include <qmljs/qmljsbind.h>
+#include <qmljs/qmljslink.h>
+#include <qmljs/qmljscontext.h>
+#include <qmljs/qmljsviewercontext.h>
+#include <qmljs/qmljscheck.h>
+#include <qmljs/qmljsimportdependencies.h>
+#include <qmljs/parser/qmljsast_p.h>
+#include <qmljs/parser/qmljsengine_p.h>
+#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <qmljstools/qmljssemanticinfo.h>
+#include <extensionsystem/pluginmanager.h>
+
+using namespace QmlJS;
+using namespace QmlJS::AST;
+using namespace QmlJS::StaticAnalysis;
+
+static Document::MutablePtr readDocument(const QString &path)
+{
+ Document::MutablePtr doc = Document::create(path, Dialect::Qml);
+ QFile file(doc->fileName());
+ file.open(QFile::ReadOnly | QFile::Text);
+ doc->setSource(file.readAll());
+ file.close();
+ doc->parse();
+ return doc;
+}
+
+class tst_Dependencies : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void test_data();
+ void test();
+
+private:
+ QString m_path;
+ QStringList m_basePaths;
+};
+
+void tst_Dependencies::initTestCase()
+{
+ QLoggingCategory::setFilterRules(QLatin1String("qtc.*.debug=false"));
+ m_path = QCoreApplication::applicationDirPath() + QLatin1Literal("/samples");
+
+ m_basePaths.append(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath));
+
+ if (!ModelManagerInterface::instance())
+ new ModelManagerInterface;
+
+ if (!ExtensionSystem::PluginManager::instance())
+ new ExtensionSystem::PluginManager;
+}
+
+void tst_Dependencies::test_data()
+{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<int>("nSemanticMessages");
+ QTest::addColumn<int>("nStaticMessages");
+
+ QTest::newRow("ApplicationWindow")
+ << QString(m_path + QLatin1String("/001_ApplicationWindow.qml"))
+ << 0
+ << 0;
+ QTest::newRow("Window")
+ << QString(m_path + QLatin1String("/002_Window.qml"))
+ << 0
+ << 1;
+}
+
+void tst_Dependencies::test()
+{
+ QFETCH(QString, filename);
+ QFETCH(int, nSemanticMessages);
+ QFETCH(int, nStaticMessages);
+
+ ModelManagerInterface *modelManager = ModelManagerInterface::instance();
+
+ QFutureInterface<void> result;
+ PathsAndLanguages lPaths;
+ QStringList paths(m_basePaths);
+ paths << m_path;
+ for (auto p: paths)
+ lPaths.maybeInsert(Utils::FileName::fromString(p), Dialect::Qml);
+ ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), lPaths,
+ ModelManagerInterface::instance(), false);
+
+
+ Document::MutablePtr doc = readDocument(filename);
+ QVERIFY(!doc->source().isEmpty());
+
+ Snapshot snapshot = modelManager->snapshot();
+
+ QmlJSTools::SemanticInfo semanticInfo;
+ semanticInfo.document = doc;
+ semanticInfo.snapshot = snapshot;
+
+ 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);
+ semanticInfo.setRootScopeChain(QSharedPointer<const ScopeChain>(scopeChain));
+
+ Check checker(doc, semanticInfo.context);
+ semanticInfo.staticAnalysisMessages = checker();
+
+ QCOMPARE(semanticInfo.semanticMessages.length(), nSemanticMessages);
+ QCOMPARE(semanticInfo.staticAnalysisMessages.length(), nStaticMessages);
+}
+
+QTEST_MAIN(tst_Dependencies)
+
+#include "tst_dependencies.moc"