aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qmlcompiler/qqmljsimporter_p.h3
-rw-r--r--tests/auto/qml/qmltc/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmltc/data/localImport_explicit.qml23
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.cpp21
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.h1
-rw-r--r--tools/qmltc/prototype/qml2cppdefaultpasses.cpp22
-rw-r--r--tools/qmltc/prototype/typeresolver.cpp77
-rw-r--r--tools/qmltc/prototype/typeresolver.h11
-rw-r--r--tools/qmltc/prototype/visitor.cpp22
-rw-r--r--tools/qmltc/prototype/visitor.h8
10 files changed, 70 insertions, 119 deletions
diff --git a/src/qmlcompiler/qqmljsimporter_p.h b/src/qmlcompiler/qqmljsimporter_p.h
index 4cc22f4cfe..953f8d720e 100644
--- a/src/qmlcompiler/qqmljsimporter_p.h
+++ b/src/qmlcompiler/qqmljsimporter_p.h
@@ -65,6 +65,9 @@ public:
QQmlJSScope::Ptr importFile(const QString &file);
ImportedTypes importDirectory(const QString &directory, const QString &prefix = QString());
+ // ### qmltc needs this. once re-written, we no longer need to expose this
+ QHash<QString, QQmlJSScope::Ptr> importedFiles() const { return m_importedFiles; }
+
ImportedTypes importModule(const QString &module, const QString &prefix = QString(),
QTypeRevision version = QTypeRevision(),
QStringList *staticModuleList = nullptr);
diff --git a/tests/auto/qml/qmltc/CMakeLists.txt b/tests/auto/qml/qmltc/CMakeLists.txt
index 90731f2e02..fc1d88e56a 100644
--- a/tests/auto/qml/qmltc/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/CMakeLists.txt
@@ -41,6 +41,7 @@ set(qml_sources
data/groupedProperty.qml
data/groupedProperty_qquicktext.qml
data/localImport.qml
+ data/localImport_explicit.qml
data/newPropertyBoundToOld.qml
data/oldPropertyBoundToNew.qml
data/nonLocalQmlPropertyBoundToAny.qml
diff --git a/tests/auto/qml/qmltc/data/localImport_explicit.qml b/tests/auto/qml/qmltc/data/localImport_explicit.qml
new file mode 100644
index 0000000000..a5455cb5a9
--- /dev/null
+++ b/tests/auto/qml/qmltc/data/localImport_explicit.qml
@@ -0,0 +1,23 @@
+import QtQuick
+import QmltcTests 1.0
+
+LocallyImported {
+ property string derivedMessage: "derived"
+ message: "derived.message"
+
+ baseObject: Text {
+ text: "derived.baseObject"
+ }
+
+ Text {
+ text: "derived.child[0]"
+ }
+
+ Rectangle {
+ property string text: "derived.child[1]"
+ }
+
+ HelloWorld {
+ property string text: "derived.child[2]"
+ }
+}
diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp
index d16b1157c1..e93fd3bf24 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.cpp
+++ b/tests/auto/qml/qmltc/tst_qmltc.cpp
@@ -57,6 +57,7 @@
#include "groupedproperty.h"
#include "groupedproperty_qquicktext.h"
#include "localimport.h"
+#include "localimport_explicit.h"
#include "newpropertyboundtoold.h"
#include "oldpropertyboundtonew.h"
#include "nonlocalqmlpropertyboundtoany.h"
@@ -1169,11 +1170,9 @@ void tst_qmltc::groupedProperty_qquicktext()
QCOMPARE(childAnchors->bottomMargin(), qreal(11));
}
-void tst_qmltc::localImport()
+template<typename T>
+void localImport_impl(T &created)
{
- QQmlEngine e;
- PREPEND_NAMESPACE(localImport) created(&e);
-
QCOMPARE(created.baseMessage(), QStringLiteral(u"base"));
QCOMPARE(created.count(), 1);
QCOMPARE(created.derivedMessage(), QStringLiteral(u"derived"));
@@ -1201,6 +1200,20 @@ void tst_qmltc::localImport()
QCOMPARE(children.at(2)->property("hello").toString(), QStringLiteral("Hello, World"));
}
+void tst_qmltc::localImport()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(localImport) created(&e);
+ localImport_impl(created);
+}
+
+void tst_qmltc::explicitLocalImport()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(localImport_explicit) created(&e);
+ localImport_impl(created);
+}
+
void tst_qmltc::newPropertyBoundToOld()
{
QQmlEngine e;
diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h
index d6c4d3aec3..78a66cf8e5 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.h
+++ b/tests/auto/qml/qmltc/tst_qmltc.h
@@ -72,6 +72,7 @@ private slots:
void groupedProperty();
void groupedProperty_qquicktext();
void localImport();
+ void explicitLocalImport();
void newPropertyBoundToOld();
void oldPropertyBoundToNew();
void nonLocalQmlPropertyBoundToAny();
diff --git a/tools/qmltc/prototype/qml2cppdefaultpasses.cpp b/tools/qmltc/prototype/qml2cppdefaultpasses.cpp
index 22767eee45..b4be78de7e 100644
--- a/tools/qmltc/prototype/qml2cppdefaultpasses.cpp
+++ b/tools/qmltc/prototype/qml2cppdefaultpasses.cpp
@@ -539,8 +539,7 @@ static void setupQmlCppType(const Qml2CppContext &context, const QQmlJSScope::Pt
return;
}
- // TODO: in reality, the file path could be something else instead of
- // "<qml_file_name>_qmltc.h", but this is not supported right now
+ // TODO: this does not cover QT_QMLTC_FILE_BASENAME renaming
filePath = QFileInfo(filePath).baseName().toLower() + u".h"_qs;
type->setFileName(filePath); // this file name will be discovered during findCppIncludes
@@ -566,17 +565,26 @@ static void setupQmlCppType(const Qml2CppContext &context, const QQmlJSScope::Pt
QSet<QString> setupQmlCppTypes(const Qml2CppContext &context, QList<Qml2CppObject> &objects)
{
+ // TODO: in general, the whole logic here is incomplete. it will suffice as
+ // long as we only import QML types from our own module and C++ types from
+ // any module. importing QML types (that are presumably compiled) from
+ // external modules is not supported, so we can get away with it
+
QSet<QString> qmlBaseTypes;
- QHash<QString, std::pair<QString, QQmlJSScope::Ptr>> qmlTypes =
- context.typeResolver->gatherCompiledQmlTypes();
for (const auto &object : objects) {
// 1. set up object itself
setupQmlCppType(context, object.type, context.documentUrl);
// 2. set up the base type if it is also QML originated
- auto [url, potentialQmlType] = qmlTypes.value(object.type->baseTypeName());
- if (potentialQmlType) { // it is an actual QML type
- setupQmlCppType(context, potentialQmlType, url);
+ if (auto base = object.type->baseType(); base->isComposite()) {
+ auto pair = context.typeResolver->importedType(base);
+ if (pair.first.isEmpty()) {
+ context.recordError(object.type->sourceLocation(),
+ u"QML base type has unknown origin. Do you miss an import?"_qs);
+ continue;
+ }
+
+ setupQmlCppType(context, pair.second, pair.first);
qmlBaseTypes.insert(object.type->baseTypeName());
}
}
diff --git a/tools/qmltc/prototype/typeresolver.cpp b/tools/qmltc/prototype/typeresolver.cpp
index 5bfff44928..377787830e 100644
--- a/tools/qmltc/prototype/typeresolver.cpp
+++ b/tools/qmltc/prototype/typeresolver.cpp
@@ -39,44 +39,6 @@
Q_LOGGING_CATEGORY(lcTypeResolver2, "qml.compiler.typeresolver", QtInfoMsg);
-static QString prefixedName(const QString &prefix, const QString &name)
-{
- Q_ASSERT(!prefix.endsWith(u'.'));
- return prefix.isEmpty() ? name : (prefix + QLatin1Char('.') + name);
-}
-
-// TODO: this method is a (almost identical) copy-paste of QQmlJSImporter::importDirectory().
-static void customImportDirectory(QHash<QString, std::pair<QString, QQmlJSScope::Ptr>> &qmlTypes,
- QQmlJSImporter *importer, const QString &directory,
- const QString &prefix = QString())
-{
- if (directory.startsWith(u':')) {
- if (QQmlJSResourceFileMapper *mapper = importer->resourceFileMapper()) {
- const auto resources = mapper->filter(
- QQmlJSResourceFileMapper::resourceQmlDirectoryFilter(directory.mid(1)));
- for (const auto &entry : resources) {
- const QString name = QFileInfo(entry.resourcePath).baseName();
- if (name.front().isUpper()) {
- qmlTypes.insert(
- prefixedName(prefix, name),
- std::make_pair(entry.filePath, importer->importFile(entry.filePath)));
- }
- }
- }
- return;
- }
-
- QDirIterator it { directory, QStringList() << QLatin1String("*.qml"), QDir::NoFilter };
- while (it.hasNext()) {
- it.next();
- if (!it.fileName().front().isUpper())
- continue; // Non-uppercase names cannot be imported anyway.
-
- qmlTypes.insert(prefixedName(prefix, QFileInfo(it.filePath()).baseName()),
- std::make_pair(it.filePath(), importer->importFile(it.filePath())));
- }
-}
-
namespace Qmltc {
TypeResolver::TypeResolver(QQmlJSImporter *importer)
@@ -103,10 +65,6 @@ void TypeResolver::init(Visitor &visitor, QQmlJS::AST::Node *program)
for (const auto &childScope : childScopes)
objects.enqueue(childScope);
}
-
- m_implicitImportDir = visitor.getImplicitImportDirectory();
- m_importedDirs = visitor.getImportedDirectories();
- m_importedFiles = visitor.getImportedQmlFiles();
}
QQmlJSScope::Ptr TypeResolver::scopeForLocation(const QV4::CompiledData::Location &location) const
@@ -116,33 +74,14 @@ QQmlJSScope::Ptr TypeResolver::scopeForLocation(const QV4::CompiledData::Locatio
return m_objectsByLocationNonConst.value(location);
}
-QHash<QString, std::pair<QString, QQmlJSScope::Ptr>> TypeResolver::gatherCompiledQmlTypes() const
+QPair<QString, QQmlJSScope::Ptr> TypeResolver::importedType(const QQmlJSScope::ConstPtr &type) const
{
- QHash<QString, std::pair<QString, QQmlJSScope::Ptr>> qmlTypes;
- // implicit directory first
- customImportDirectory(qmlTypes, m_importer, m_implicitImportDir);
- // followed by subdirectories and absolute directories
- for (const QString &dir : m_importedDirs) {
- QString dirPath = dir;
- const QFileInfo dirInfo(dir);
- if (dirInfo.isRelative()) {
- dirPath = QDir(m_implicitImportDir).filePath(dirPath);
- }
- customImportDirectory(qmlTypes, m_importer, dirPath);
- }
- // followed by individual files
- for (const QString &file : m_importedFiles) {
- QString filePath = file;
- const QFileInfo fileInfo(file);
- if (fileInfo.isRelative()) {
- filePath = QDir(m_implicitImportDir).filePath(filePath);
- }
- // TODO: file importing is untested
- const QString baseName = QFileInfo(filePath).baseName();
- if (baseName.front().isUpper())
- qmlTypes.insert(baseName, std::make_pair(filePath, m_importer->importFile(filePath)));
- }
- return qmlTypes;
+ const auto files = m_importer->importedFiles();
+ auto it = std::find_if(files.cbegin(), files.cend(), [&](const QQmlJSScope::Ptr &importedType) {
+ return importedType.data() == type.data();
+ });
+ if (it == files.cend())
+ return {};
+ return { it.key(), it.value() };
}
-
}
diff --git a/tools/qmltc/prototype/typeresolver.h b/tools/qmltc/prototype/typeresolver.h
index dc747fd042..ff5fd19ef5 100644
--- a/tools/qmltc/prototype/typeresolver.h
+++ b/tools/qmltc/prototype/typeresolver.h
@@ -74,21 +74,14 @@ public:
QQmlJSScope::Ptr scopeForLocation(const QV4::CompiledData::Location &location) const;
- // returns a mapping from "QML name" (typically QML file name without
- // extension) to {file path, QML scope/type pointer} pair. the mapping
- // contains only native, non-C++ originated, QML types that would be
- // compiled into C++.
- QHash<QString, std::pair<QString, QQmlJSScope::Ptr>> gatherCompiledQmlTypes() const;
+ // returns an import pair {url, modifiable type} for a given \a type
+ QPair<QString, QQmlJSScope::Ptr> importedType(const QQmlJSScope::ConstPtr &type) const;
private:
QQmlJSImporter *m_importer = nullptr;
QHash<QV4::CompiledData::Location, QQmlJSScope::Ptr> m_objectsByLocationNonConst;
- QString m_implicitImportDir; // implicit QML import directory
QQmlJSScope::Ptr m_root;
-
- QList<QString> m_importedDirs;
- QList<QString> m_importedFiles;
};
}
diff --git a/tools/qmltc/prototype/visitor.cpp b/tools/qmltc/prototype/visitor.cpp
index 07e5e41214..307cb992ea 100644
--- a/tools/qmltc/prototype/visitor.cpp
+++ b/tools/qmltc/prototype/visitor.cpp
@@ -38,28 +38,6 @@ Visitor::Visitor(QQmlJSImporter *importer, QQmlJSLogger *logger,
{
}
-bool Visitor::visit(QQmlJS::AST::UiImport *import)
-{
- if (!QQmlJSImportVisitor::visit(import))
- return false;
-
- auto filename = import->fileName.toString();
- if (filename.isEmpty())
- return true;
-
- const QFileInfo file(filename);
- const QString absolute =
- file.isRelative() ? QDir(m_implicitImportDirectory).filePath(filename) : filename;
-
- QFileInfo path(absolute);
- if (path.isDir()) {
- m_importedDirectories.append(filename);
- } else if (path.isFile() && absolute.endsWith(u".qml"_qs)) {
- m_importedFiles.append(filename);
- }
- return true;
-}
-
bool Visitor::visit(QQmlJS::AST::UiInlineComponent *component)
{
if (!QQmlJSImportVisitor::visit(component))
diff --git a/tools/qmltc/prototype/visitor.h b/tools/qmltc/prototype/visitor.h
index 2df72b25ae..730021b66c 100644
--- a/tools/qmltc/prototype/visitor.h
+++ b/tools/qmltc/prototype/visitor.h
@@ -44,19 +44,11 @@
namespace Qmltc {
class Visitor : public QQmlJSImportVisitor
{
- QStringList m_importedDirectories;
- QStringList m_importedFiles;
-
public:
Visitor(QQmlJSImporter *importer, QQmlJSLogger *logger, const QString &implicitImportDirectory,
const QStringList &qmltypesFiles = QStringList());
- bool visit(QQmlJS::AST::UiImport *import) override;
bool visit(QQmlJS::AST::UiInlineComponent *) override;
-
- QString getImplicitImportDirectory() const { return m_implicitImportDirectory; }
- QStringList getImportedDirectories() const { return m_importedDirectories; }
- QStringList getImportedQmlFiles() const { return m_importedFiles; }
};
}