From fe013bdbaecd9605ebf715215cef3cd82c1a712f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 6 Oct 2020 11:35:30 +0200 Subject: qmllint: Read deprecated dependency specifications from qmltypes files And produce a warning when doing so. Task-number: QTBUG-87164 Change-Id: I75eab97a37af1268a310e88e3ac6a625127a7f62 Reviewed-by: Fabian Kosmale --- src/qmlcompiler/qqmljsimporter.cpp | 47 ++++++++++++++++++---- src/qmlcompiler/qqmljsimporter_p.h | 3 +- .../qml/qmllint/data/OldQmltypes/plugins.qmltypes | 2 + tests/auto/qml/qmllint/data/oldQmltypes.qml | 1 + tests/auto/qml/qmllint/tst_qmllint.cpp | 2 + 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/qmlcompiler/qqmljsimporter.cpp b/src/qmlcompiler/qqmljsimporter.cpp index a83f344523..94fcdc460c 100644 --- a/src/qmlcompiler/qqmljsimporter.cpp +++ b/src/qmlcompiler/qqmljsimporter.cpp @@ -56,7 +56,8 @@ static QQmlDirParser createQmldirParserForFile(const QString &filename) } void QQmlJSImporter::readQmltypes( - const QString &filename, QHash *objects) + const QString &filename, QHash *objects, + QList *dependencies) { const QFileInfo fileInfo(filename); if (!fileInfo.exists()) { @@ -72,10 +73,42 @@ void QQmlJSImporter::readQmltypes( QFile file(filename); file.open(QFile::ReadOnly); QQmlJSTypeDescriptionReader reader { filename, QString::fromUtf8(file.readAll()) }; - QStringList dependencies; - auto succ = reader(objects, &dependencies); + QStringList dependencyStrings; + auto succ = reader(objects, &dependencyStrings); if (!succ) m_warnings.append(reader.errorMessage()); + + if (dependencyStrings.isEmpty()) + return; + + m_warnings.append(QStringLiteral("Found deprecated dependency specifications in %1." + "Specify dependencies in qmldir and use qmltyperegistrar to " + "generate qmltypes files without dependencies.") + .arg(filename)); + + for (const QString &dependency : qAsConst(dependencyStrings)) { + const auto blank = dependency.indexOf(u' '); + if (blank < 0) { + dependencies->append(QQmlDirParser::Import(dependency, {}, false)); + continue; + } + + const QString module = dependency.left(blank); + const QString versionString = dependency.mid(blank + 1).trimmed(); + if (versionString == QStringLiteral("auto")) { + dependencies->append(QQmlDirParser::Import(module, {}, true)); + continue; + } + + const auto dot = versionString.indexOf(u'.'); + + const QTypeRevision version = dot < 0 + ? QTypeRevision::fromMajorVersion(versionString.toUShort()) + : QTypeRevision::fromVersion(versionString.left(dot).toUShort(), + versionString.mid(dot + 1).toUShort()); + + dependencies->append(QQmlDirParser::Import(module, version, false)); + } } QQmlJSImporter::Import QQmlJSImporter::readQmldir(const QString &path) @@ -109,7 +142,7 @@ QQmlJSImporter::Import QQmlJSImporter::readQmldir(const QString &path) for (const auto &typeInfo : typeInfos) { const QString typeInfoPath = QFileInfo(typeInfo).isRelative() ? path + u'/' + typeInfo : typeInfo; - readQmltypes(typeInfoPath, &result.objects); + readQmltypes(typeInfoPath, &result.objects, &result.dependencies); } if (typeInfos.isEmpty() && !reader.plugins().isEmpty()) { @@ -117,7 +150,7 @@ QQmlJSImporter::Import QQmlJSImporter::readQmldir(const QString &path) if (QFile::exists(defaultTypeInfoPath)) { m_warnings.append(QStringLiteral("typeinfo not declared in qmldir file: ") + defaultTypeInfoPath); - readQmltypes(defaultTypeInfoPath, &result.objects); + readQmltypes(defaultTypeInfoPath, &result.objects, &result.dependencies); } } @@ -182,7 +215,7 @@ QQmlJSImporter::ImportedTypes QQmlJSImporter::importBuiltins() QDirIterator it { dir, QStringList() << QLatin1String("builtins.qmltypes"), QDir::NoFilter, QDirIterator::Subdirectories }; while (it.hasNext()) - readQmltypes(it.next(), &result.objects); + readQmltypes(it.next(), &result.objects, &result.dependencies); importDependencies(result, &types); processImport(result, &types); } @@ -199,7 +232,7 @@ QQmlJSImporter::ImportedTypes QQmlJSImporter::importQmltypes(const QStringList & Import result; for (const auto &qmltypeFile : qmltypesFiles) - readQmltypes(qmltypeFile, &result.objects); + readQmltypes(qmltypeFile, &result.objects, &result.dependencies); importDependencies(result, &types); processImport(result, &types); diff --git a/src/qmlcompiler/qqmljsimporter_p.h b/src/qmlcompiler/qqmljsimporter_p.h index 245964a339..2f4d51a33c 100644 --- a/src/qmlcompiler/qqmljsimporter_p.h +++ b/src/qmlcompiler/qqmljsimporter_p.h @@ -94,7 +94,8 @@ private: AvailableTypes *types, const QString &prefix = QString(), QTypeRevision version = QTypeRevision()); - void readQmltypes(const QString &filename, QHash *objects); + void readQmltypes(const QString &filename, QHash *objects, + QList *dependencies); Import readQmldir(const QString &dirname); QQmlJSScope::Ptr localFile2ScopeTree(const QString &filePath); diff --git a/tests/auto/qml/qmllint/data/OldQmltypes/plugins.qmltypes b/tests/auto/qml/qmllint/data/OldQmltypes/plugins.qmltypes index eab91f6723..71a515d8c5 100644 --- a/tests/auto/qml/qmllint/data/OldQmltypes/plugins.qmltypes +++ b/tests/auto/qml/qmllint/data/OldQmltypes/plugins.qmltypes @@ -1,7 +1,9 @@ import QtQuick.tooling 1.2 Module { + dependencies: [ "QtQuick 2.15" ] Component { name: "Frame" + prototype: "QQuickItem" exports: ["OldQmltypes/Frame 1.0"] exportMetaObjectRevisions: [0] } diff --git a/tests/auto/qml/qmllint/data/oldQmltypes.qml b/tests/auto/qml/qmllint/data/oldQmltypes.qml index f33d4d90fe..80980be451 100644 --- a/tests/auto/qml/qmllint/data/oldQmltypes.qml +++ b/tests/auto/qml/qmllint/data/oldQmltypes.qml @@ -1,4 +1,5 @@ import OldQmltypes 1.0 Frame { + x: 15 } diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 1b77e941ab..0b78285c23 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -138,6 +138,8 @@ void TestQmllint::oldQmltypes() { const QString errors = runQmllint("oldQmltypes.qml", true); QVERIFY(errors.contains(QStringLiteral("Warning: typeinfo not declared in qmldir file"))); + QVERIFY(!errors.contains(QStringLiteral("Warning: QQuickItem was not found. Did you add all import paths?"))); + QVERIFY(errors.contains(QStringLiteral("Warning: Found deprecated dependency specifications"))); } void TestQmllint::dirtyQmlCode_data() -- cgit v1.2.3