diff options
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 110 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor_p.h | 5 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/untitled/components/Foo.qml | 5 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/untitled/main.qml | 9 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc | 6 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/tst_qmllint.cpp | 11 |
6 files changed, 100 insertions, 46 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index ddf9a1a588..8873047697 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -2149,63 +2149,81 @@ void QQmlJSImportVisitor::addImportWithLocation(const QString &name, m_importLocations.insert(loc); } +void QQmlJSImportVisitor::importFromHost(const QString &path, const QString &prefix, + const QQmlJS::SourceLocation &location) +{ + QFileInfo fileInfo(path); + if (fileInfo.isFile()) { + const auto scope = m_importer->importFile(path); + const QString actualPrefix = prefix.isEmpty() ? scope->internalName() : prefix; + m_rootScopeImports.setType(actualPrefix, { scope, QTypeRevision() }); + addImportWithLocation(actualPrefix, location); + } else if (fileInfo.isDir()) { + const auto scopes = m_importer->importDirectory(path, prefix); + m_rootScopeImports.addTypes(scopes); + for (auto it = scopes.types().keyBegin(), end = scopes.types().keyEnd(); it != end; it++) + addImportWithLocation(*it, location); + } +} + +void QQmlJSImportVisitor::importFromQrc(const QString &path, const QString &prefix, + const QQmlJS::SourceLocation &location) +{ + if (const auto &mapper = m_importer->resourceFileMapper()) { + if (mapper->isFile(path)) { + const auto entry = m_importer->resourceFileMapper()->entry( + QQmlJSResourceFileMapper::resourceFileFilter(path)); + const auto scope = m_importer->importFile(entry.filePath); + const QString actualPrefix = + prefix.isEmpty() ? QFileInfo(entry.resourcePath).baseName() : prefix; + m_rootScopeImports.setType(actualPrefix, { scope, QTypeRevision() }); + addImportWithLocation(actualPrefix, location); + } else { + const auto scopes = m_importer->importDirectory(path, prefix); + m_rootScopeImports.addTypes(scopes); + for (auto it = scopes.types().keyBegin(), end = scopes.types().keyEnd(); it != end; it++) + addImportWithLocation(*it, location); + } + } +} + bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiImport *import) { - auto addImportLocation = [this, import](const QString &name) { - addImportWithLocation(name, import->firstSourceLocation()); - }; // construct path QString prefix = QLatin1String(""); if (import->asToken.isValid()) { prefix += import->importId; } + auto filename = import->fileName.toString(); if (!filename.isEmpty()) { - const QFileInfo file(filename); - const QString absolute = file.isRelative() - ? QDir::cleanPath(QDir(m_implicitImportDirectory).filePath(filename)) - : filename; - - if (absolute.startsWith(u':')) { - if (m_importer->resourceFileMapper()) { - if (m_importer->resourceFileMapper()->isFile(absolute.mid(1))) { - const auto entry = m_importer->resourceFileMapper()->entry( - QQmlJSResourceFileMapper::resourceFileFilter(absolute.mid(1))); - const auto scope = m_importer->importFile(entry.filePath); - const QString actualPrefix = prefix.isEmpty() - ? QFileInfo(entry.resourcePath).baseName() - : prefix; - m_rootScopeImports.setType(actualPrefix, { scope, QTypeRevision() }); - - addImportLocation(actualPrefix); - } else { - const auto scopes = m_importer->importDirectory(absolute, prefix); - m_rootScopeImports.addTypes(scopes); - for (auto it = scopes.types().keyBegin(), end = scopes.types().keyEnd(); it != end; - it++) - addImportLocation(*it); - } + const QUrl url(filename); + const QString scheme = url.scheme(); + const QQmlJS::SourceLocation importLocation = import->firstSourceLocation(); + if (scheme == ""_L1) { + QFileInfo fileInfo(url.path()); + QString absolute = fileInfo.isRelative() + ? QDir::cleanPath(QDir(m_implicitImportDirectory).filePath(filename)) + : filename; + if (absolute.startsWith(u':')) { + importFromQrc(absolute, prefix, importLocation); + } else { + importFromHost(absolute, prefix, importLocation); } - - processImportWarnings(QStringLiteral("URL \"%1\"").arg(absolute), import->firstSourceLocation()); + processImportWarnings("path \"%1\""_L1.arg(url.path()), importLocation); return true; + } else if (scheme == "file"_L1) { + importFromHost(url.path(), prefix, importLocation); + processImportWarnings("URL \"%1\""_L1.arg(url.path()), importLocation); + return true; + } else if (scheme == "qrc"_L1) { + importFromQrc(":"_L1 + url.path(), prefix, importLocation); + processImportWarnings("URL \"%1\""_L1.arg(url.path()), importLocation); + return true; + } else { + m_logger->log("Unknown import syntax. Imports can be paths, qrc urls or file urls"_L1, + qmlImport, import->firstSourceLocation()); } - - QFileInfo path(absolute); - if (path.isDir()) { - const auto scopes = m_importer->importDirectory(path.canonicalFilePath(), prefix); - m_rootScopeImports.addTypes(scopes); - for (auto it = scopes.types().keyBegin(), end = scopes.types().keyEnd(); it != end; it++) - addImportLocation(*it); - } else if (path.isFile()) { - const auto scope = m_importer->importFile(path.canonicalFilePath()); - const QString actualPrefix = prefix.isEmpty() ? scope->internalName() : prefix; - m_rootScopeImports.setType(actualPrefix, { scope, QTypeRevision() }); - addImportLocation(actualPrefix); - } - - processImportWarnings(QStringLiteral("path \"%1\"").arg(path.canonicalFilePath()), import->firstSourceLocation()); - return true; } const QString path = buildName(import->importUri); @@ -2217,7 +2235,7 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiImport *import) &staticModulesProvided); m_rootScopeImports.addTypes(imported); for (auto it = imported.types().keyBegin(), end = imported.types().keyEnd(); it != end; it++) - addImportLocation(*it); + addImportWithLocation(*it, import->firstSourceLocation()); if (prefix.isEmpty()) { for (const QString &staticModule : staticModulesProvided) { diff --git a/src/qmlcompiler/qqmljsimportvisitor_p.h b/src/qmlcompiler/qqmljsimportvisitor_p.h index 3d9f094334..0a23704e71 100644 --- a/src/qmlcompiler/qqmljsimportvisitor_p.h +++ b/src/qmlcompiler/qqmljsimportvisitor_p.h @@ -347,6 +347,11 @@ private: void enterRootScope(QQmlJSScope::ScopeType type, const QString &name, const QQmlJS::SourceLocation &location); + void importFromHost(const QString &path, const QString &prefix, + const QQmlJS::SourceLocation &location); + void importFromQrc(const QString &path, const QString &prefix, + const QQmlJS::SourceLocation &location); + public: friend class QQmlJS::Dom::QQmlDomAstCreatorWithQQmlJSScope; }; diff --git a/tests/auto/qml/qmllint/data/untitled/components/Foo.qml b/tests/auto/qml/qmllint/data/untitled/components/Foo.qml new file mode 100644 index 0000000000..10e5741900 --- /dev/null +++ b/tests/auto/qml/qmllint/data/untitled/components/Foo.qml @@ -0,0 +1,5 @@ +import QtQuick + +Text { + text: "Here I am!" +} diff --git a/tests/auto/qml/qmllint/data/untitled/main.qml b/tests/auto/qml/qmllint/data/untitled/main.qml new file mode 100644 index 0000000000..cf8980ab55 --- /dev/null +++ b/tests/auto/qml/qmllint/data/untitled/main.qml @@ -0,0 +1,9 @@ +pragma Strict + +import QtQuick +import 'qrc:/untitled/components' as C + +Window { + id: root + C.Foo {} +} diff --git a/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc b/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc new file mode 100644 index 0000000000..0ad0d57fbb --- /dev/null +++ b/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/untitled/"> + <file alias="main.qml">main.qml</file> + <file alias="components/Foo.qml">components/Foo.qml</file> + </qresource> +</RCC> diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 56705712d0..110017b371 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -79,6 +79,8 @@ private Q_SLOTS: void additionalImplicitImport(); + void qrcUrlImport(); + void attachedPropertyReuse(); void missingBuiltinsNoCrash(); @@ -1654,7 +1656,16 @@ void TestQmllint::additionalImplicitImport() const auto guard = qScopeGuard([this]() {m_linter.clearCache(); }); runTest("additionalImplicitImport.qml", Result::clean(), {}, {}, { testFile("implicitImportResource.qrc") }); +} +void TestQmllint::qrcUrlImport() +{ + const auto guard = qScopeGuard([this]() { m_linter.clearCache(); }); + + QJsonArray warnings; + callQmllint(testFile("untitled/main.qml"), true, &warnings, {}, {}, + { testFile("untitled/qrcUrlImport.qrc") }); + checkResult(warnings, Result::clean()); } void TestQmllint::attachedPropertyReuse() |