forked from qt-creator/qt-creator
Qml code model: handle modules dependencies.
Fix the broken hierarchies between qml objects. Change-Id: Id36c735cab0129af382fab7b9dd90c228304168c Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com> Reviewed-by: Alessandro Portale <alessandro.portale@theqtcompany.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -187,6 +187,7 @@ tmp/
|
|||||||
/tests/auto/ioutils/tst_ioutils
|
/tests/auto/ioutils/tst_ioutils
|
||||||
/tests/auto/profilewriter/tst_profilewriter
|
/tests/auto/profilewriter/tst_profilewriter
|
||||||
/tests/auto/qml/codemodel/check/tst_codemodel_check
|
/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/persistenttrie/tst_trie_check
|
||||||
/tests/auto/qml/qmldesigner/bauhaustests/tst_bauhaus
|
/tests/auto/qml/qmldesigner/bauhaustests/tst_bauhaus
|
||||||
/tests/auto/qml/qmldesigner/coretests/tst_qmldesigner_core
|
/tests/auto/qml/qmldesigner/coretests/tst_qmldesigner_core
|
||||||
|
|||||||
@@ -519,6 +519,7 @@ void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info)
|
|||||||
foreach (const Export &e, cImport.possibleExports)
|
foreach (const Export &e, cImport.possibleExports)
|
||||||
_dependencies.addExport(component.fileName, e.exportName, e.pathRequired, e.typeName);
|
_dependencies.addExport(component.fileName, e.exportName, e.pathRequired, e.typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
cImport.fingerprint = info.fingerprint();
|
cImport.fingerprint = info.fingerprint();
|
||||||
_dependencies.addCoreImport(cImport);
|
_dependencies.addCoreImport(cImport);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ private:
|
|||||||
typedef QList<LanguageUtils::FakeMetaObject::ConstPtr> FakeMetaObjectList;
|
typedef QList<LanguageUtils::FakeMetaObject::ConstPtr> FakeMetaObjectList;
|
||||||
FakeMetaObjectList _metaObjects;
|
FakeMetaObjectList _metaObjects;
|
||||||
QList<ModuleApiInfo> _moduleApis;
|
QList<ModuleApiInfo> _moduleApis;
|
||||||
|
QStringList _dependencies;
|
||||||
QByteArray _fingerprint;
|
QByteArray _fingerprint;
|
||||||
|
|
||||||
PluginTypeInfoStatus _dumpStatus;
|
PluginTypeInfoStatus _dumpStatus;
|
||||||
@@ -190,6 +191,12 @@ public:
|
|||||||
void setModuleApis(const QList<ModuleApiInfo> &apis)
|
void setModuleApis(const QList<ModuleApiInfo> &apis)
|
||||||
{ _moduleApis = apis; }
|
{ _moduleApis = apis; }
|
||||||
|
|
||||||
|
QStringList dependencies() const
|
||||||
|
{ return _dependencies; }
|
||||||
|
|
||||||
|
void setDependencies(const QStringList &deps)
|
||||||
|
{ _dependencies = deps; }
|
||||||
|
|
||||||
bool isValid() const
|
bool isValid() const
|
||||||
{ return _status == Found; }
|
{ return _status == Found; }
|
||||||
|
|
||||||
|
|||||||
@@ -1117,11 +1117,13 @@ const Value *ObjectValue::lookupMember(const QString &name, const Context *conte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ObjectValue *prototypeObject = 0;
|
||||||
|
|
||||||
if (examinePrototypes && context) {
|
if (examinePrototypes && context) {
|
||||||
PrototypeIterator iter(this, context);
|
PrototypeIterator iter(this, context);
|
||||||
iter.next(); // skip this
|
iter.next(); // skip this
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
const ObjectValue *prototypeObject = iter.next();
|
prototypeObject = iter.next();
|
||||||
if (const Value *m = prototypeObject->lookupMember(name, context, foundInObject, false))
|
if (const Value *m = prototypeObject->lookupMember(name, context, foundInObject, false))
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
@@ -1129,6 +1131,7 @@ const Value *ObjectValue::lookupMember(const QString &name, const Context *conte
|
|||||||
|
|
||||||
if (foundInObject)
|
if (foundInObject)
|
||||||
*foundInObject = 0;
|
*foundInObject = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1346,6 +1349,7 @@ CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::defaultQtObjects;
|
|||||||
CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::loadQmlTypes(const QFileInfoList &qmlTypeFiles, QStringList *errors, QStringList *warnings)
|
CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::loadQmlTypes(const QFileInfoList &qmlTypeFiles, QStringList *errors, QStringList *warnings)
|
||||||
{
|
{
|
||||||
QHash<QString, FakeMetaObject::ConstPtr> newObjects;
|
QHash<QString, FakeMetaObject::ConstPtr> newObjects;
|
||||||
|
QStringList newDependencies;
|
||||||
|
|
||||||
foreach (const QFileInfo &qmlTypeFile, qmlTypeFiles) {
|
foreach (const QFileInfo &qmlTypeFile, qmlTypeFiles) {
|
||||||
QString error, warning;
|
QString error, warning;
|
||||||
@@ -1355,7 +1359,8 @@ CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::loadQmlTypes(const QFileInf
|
|||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
|
|
||||||
parseQmlTypeDescriptions(contents, &newObjects, 0, &error, &warning, qmlTypeFile.absoluteFilePath());
|
parseQmlTypeDescriptions(contents, &newObjects, 0, &newDependencies, &error, &warning,
|
||||||
|
qmlTypeFile.absoluteFilePath());
|
||||||
} else {
|
} else {
|
||||||
error = file.errorString();
|
error = file.errorString();
|
||||||
}
|
}
|
||||||
@@ -1377,6 +1382,7 @@ CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::loadQmlTypes(const QFileInf
|
|||||||
void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &contents,
|
void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &contents,
|
||||||
BuiltinObjects *newObjects,
|
BuiltinObjects *newObjects,
|
||||||
QList<ModuleApiInfo> *newModuleApis,
|
QList<ModuleApiInfo> *newModuleApis,
|
||||||
|
QStringList *newDependencies,
|
||||||
QString *errorMessage,
|
QString *errorMessage,
|
||||||
QString *warningMessage, const QString &fileName)
|
QString *warningMessage, const QString &fileName)
|
||||||
{
|
{
|
||||||
@@ -1396,7 +1402,7 @@ void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &contents,
|
|||||||
errorMessage->clear();
|
errorMessage->clear();
|
||||||
warningMessage->clear();
|
warningMessage->clear();
|
||||||
TypeDescriptionReader reader(fileName, QString::fromUtf8(contents));
|
TypeDescriptionReader reader(fileName, QString::fromUtf8(contents));
|
||||||
if (!reader(newObjects, newModuleApis)) {
|
if (!reader(newObjects, newModuleApis, newDependencies)) {
|
||||||
if (reader.errorMessage().isEmpty())
|
if (reader.errorMessage().isEmpty())
|
||||||
*errorMessage = QLatin1String("unknown error");
|
*errorMessage = QLatin1String("unknown error");
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -720,8 +720,12 @@ public:
|
|||||||
|
|
||||||
// parses the contents of a qmltypes file and fills the newObjects map
|
// parses the contents of a qmltypes file and fills the newObjects map
|
||||||
static void parseQmlTypeDescriptions(const QByteArray &contents,
|
static void parseQmlTypeDescriptions(const QByteArray &contents,
|
||||||
BuiltinObjects *newObjects,
|
BuiltinObjects *newObjects,
|
||||||
QList<ModuleApiInfo> *newModuleApis, QString *errorMessage, QString *warningMessage, const QString &fileName);
|
QList<ModuleApiInfo> *newModuleApis,
|
||||||
|
QStringList *newDependencies,
|
||||||
|
QString *errorMessage,
|
||||||
|
QString *warningMessage,
|
||||||
|
const QString &fileName);
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMLJS_EXPORT FakeMetaObjectWithOrigin
|
class QMLJS_EXPORT FakeMetaObjectWithOrigin
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "qmljsmodelmanagerinterface.h"
|
#include "qmljsmodelmanagerinterface.h"
|
||||||
|
|
||||||
#include <qmljs/qmljsinterpreter.h>
|
#include <qmljs/qmljsinterpreter.h>
|
||||||
|
#include <qmljs/qmljsviewercontext.h>
|
||||||
//#include <projectexplorer/session.h>
|
//#include <projectexplorer/session.h>
|
||||||
//#include <coreplugin/messagemanager.h>
|
//#include <coreplugin/messagemanager.h>
|
||||||
#include <utils/filesystemwatcher.h>
|
#include <utils/filesystemwatcher.h>
|
||||||
@@ -309,7 +310,9 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
|
|||||||
QString warning;
|
QString warning;
|
||||||
CppQmlTypesLoader::BuiltinObjects objectsList;
|
CppQmlTypesLoader::BuiltinObjects objectsList;
|
||||||
QList<ModuleApiInfo> moduleApis;
|
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('>'));
|
QLatin1String("<dump of ") + libraryPath + QLatin1Char('>'));
|
||||||
if (exitCode == 0) {
|
if (exitCode == 0) {
|
||||||
if (!error.isEmpty()) {
|
if (!error.isEmpty()) {
|
||||||
@@ -361,6 +364,115 @@ void PluginDumper::pluginChanged(const QString &pluginLibrary)
|
|||||||
dump(plugin);
|
dump(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(p, QFile::Text)) {
|
||||||
|
errors += reader.errorString();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString error;
|
||||||
|
QString warning;
|
||||||
|
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(p, error);
|
||||||
|
} else {
|
||||||
|
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,
|
void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
|
||||||
const QString &libraryPath,
|
const QString &libraryPath,
|
||||||
QmlJS::LibraryInfo libraryInfo)
|
QmlJS::LibraryInfo libraryInfo)
|
||||||
@@ -369,31 +481,14 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
|
|||||||
QStringList warnings;
|
QStringList warnings;
|
||||||
QList<FakeMetaObject::ConstPtr> objects;
|
QList<FakeMetaObject::ConstPtr> objects;
|
||||||
QList<ModuleApiInfo> moduleApis;
|
QList<ModuleApiInfo> moduleApis;
|
||||||
|
QStringList dependencies;
|
||||||
|
|
||||||
foreach (const QString &qmltypesFilePath, qmltypesFilePaths) {
|
loadQmlTypeDescription(qmltypesFilePaths, errors, warnings, objects, &moduleApis, &dependencies);
|
||||||
Utils::FileReader reader;
|
loadDependencies(dependencies, errors, warnings, objects);
|
||||||
if (!reader.fetch(qmltypesFilePath, 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);
|
|
||||||
if (!error.isEmpty()) {
|
|
||||||
errors += tr("Failed to parse \"%1\".\nError: %2").arg(qmltypesFilePath, error);
|
|
||||||
} else {
|
|
||||||
objects += newObjects.values();
|
|
||||||
moduleApis += newModuleApis;
|
|
||||||
}
|
|
||||||
if (!warning.isEmpty())
|
|
||||||
warnings += warning;
|
|
||||||
}
|
|
||||||
|
|
||||||
libraryInfo.setMetaObjects(objects);
|
libraryInfo.setMetaObjects(objects);
|
||||||
libraryInfo.setModuleApis(moduleApis);
|
libraryInfo.setModuleApis(moduleApis);
|
||||||
|
libraryInfo.setDependencies(dependencies);
|
||||||
if (errors.isEmpty()) {
|
if (errors.isEmpty()) {
|
||||||
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::TypeInfoFileDone);
|
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::TypeInfoFileDone);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -75,6 +75,15 @@ private:
|
|||||||
|
|
||||||
void runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info, const QStringList &arguments, const QString &importPath);
|
void runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info, const QStringList &arguments, const QString &importPath);
|
||||||
void dump(const Plugin &plugin);
|
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,
|
void loadQmltypesFile(const QStringList &qmltypesFilePaths,
|
||||||
const QString &libraryPath,
|
const QString &libraryPath,
|
||||||
QmlJS::LibraryInfo libraryInfo);
|
QmlJS::LibraryInfo libraryInfo);
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ TypeDescriptionReader::~TypeDescriptionReader()
|
|||||||
|
|
||||||
bool TypeDescriptionReader::operator()(
|
bool TypeDescriptionReader::operator()(
|
||||||
QHash<QString, FakeMetaObject::ConstPtr> *objects,
|
QHash<QString, FakeMetaObject::ConstPtr> *objects,
|
||||||
QList<ModuleApiInfo> *moduleApis)
|
QList<ModuleApiInfo> *moduleApis,
|
||||||
|
QStringList *dependencies)
|
||||||
{
|
{
|
||||||
Engine engine;
|
Engine engine;
|
||||||
|
|
||||||
@@ -71,6 +72,7 @@ bool TypeDescriptionReader::operator()(
|
|||||||
|
|
||||||
_objects = objects;
|
_objects = objects;
|
||||||
_moduleApis = moduleApis;
|
_moduleApis = moduleApis;
|
||||||
|
_dependencies = dependencies;
|
||||||
readDocument(parser.ast());
|
readDocument(parser.ast());
|
||||||
|
|
||||||
return _errorMessage.isEmpty();
|
return _errorMessage.isEmpty();
|
||||||
@@ -141,6 +143,12 @@ void TypeDescriptionReader::readModule(UiObjectDefinition *ast)
|
|||||||
UiObjectMember *member = it->member;
|
UiObjectMember *member = it->member;
|
||||||
UiObjectDefinition *component = dynamic_cast<UiObjectDefinition *>(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;
|
QString typeName;
|
||||||
if (component)
|
if (component)
|
||||||
typeName = toString(component->qualifiedTypeNameId);
|
typeName = toString(component->qualifiedTypeNameId);
|
||||||
@@ -174,6 +182,27 @@ void TypeDescriptionReader::addWarning(const SourceLocation &loc, const QString
|
|||||||
message);
|
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)
|
void TypeDescriptionReader::readComponent(UiObjectDefinition *ast)
|
||||||
{
|
{
|
||||||
FakeMetaObject::Ptr fmo(new FakeMetaObject);
|
FakeMetaObject::Ptr fmo(new FakeMetaObject);
|
||||||
|
|||||||
@@ -58,13 +58,15 @@ public:
|
|||||||
|
|
||||||
bool operator()(
|
bool operator()(
|
||||||
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *objects,
|
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *objects,
|
||||||
QList<ModuleApiInfo> *moduleApis);
|
QList<ModuleApiInfo> *moduleApis,
|
||||||
|
QStringList *dependencies);
|
||||||
QString errorMessage() const;
|
QString errorMessage() const;
|
||||||
QString warningMessage() const;
|
QString warningMessage() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void readDocument(AST::UiProgram *ast);
|
void readDocument(AST::UiProgram *ast);
|
||||||
void readModule(AST::UiObjectDefinition *ast);
|
void readModule(AST::UiObjectDefinition *ast);
|
||||||
|
void readDependencies(AST::UiScriptBinding *ast);
|
||||||
void readComponent(AST::UiObjectDefinition *ast);
|
void readComponent(AST::UiObjectDefinition *ast);
|
||||||
void readModuleApi(AST::UiObjectDefinition *ast);
|
void readModuleApi(AST::UiObjectDefinition *ast);
|
||||||
void readSignalOrMethod(AST::UiObjectDefinition *ast, bool isMethod, LanguageUtils::FakeMetaObject::Ptr fmo);
|
void readSignalOrMethod(AST::UiObjectDefinition *ast, bool isMethod, LanguageUtils::FakeMetaObject::Ptr fmo);
|
||||||
@@ -90,6 +92,7 @@ private:
|
|||||||
QString _warningMessage;
|
QString _warningMessage;
|
||||||
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *_objects;
|
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *_objects;
|
||||||
QList<ModuleApiInfo> *_moduleApis;
|
QList<ModuleApiInfo> *_moduleApis;
|
||||||
|
QStringList *_dependencies;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlJS
|
} // namespace QmlJS
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
SUBDIRS += check \
|
SUBDIRS += check \
|
||||||
importscheck
|
importscheck \
|
||||||
|
dependencies
|
||||||
|
|
||||||
|
|||||||
20
tests/auto/qml/codemodel/dependencies/dependencies.pro
Normal file
20
tests/auto/qml/codemodel/dependencies/dependencies.pro
Normal file
@@ -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
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
34
tests/auto/qml/codemodel/dependencies/samples/002_Window.qml
Normal file
34
tests/auto/qml/codemodel/dependencies/samples/002_Window.qml
Normal file
@@ -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
|
||||||
|
}
|
||||||
32
tests/auto/qml/codemodel/dependencies/samples/SampleLib.qml
Normal file
32
tests/auto/qml/codemodel/dependencies/samples/SampleLib.qml
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
153
tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
Normal file
153
tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
Normal file
@@ -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"
|
||||||
Reference in New Issue
Block a user