diff options
author | Sami Shalayel <sami.shalayel@qt.io> | 2022-09-28 20:04:44 +0200 |
---|---|---|
committer | Sami Shalayel <sami.shalayel@qt.io> | 2022-11-23 10:05:30 +0100 |
commit | aa3e01645ddc675c2532c6966c1eae3d1967a73d (patch) | |
tree | 3a81b26e35189f8fff05e220ba40190fa6ffd60a /tools | |
parent | 9b3813be282ab00d594c48d62f1e13d73f36d514 (diff) |
qmltc: add singleton support
Add singleton support to qmltc.
Add the QML_SINGLETON annotation to the class, generate a static T*
create(QQmlEngine*, QJSEngine*) method for the engine and also add test
this new functionality.
Fixes: QTBUG-106828
Change-Id: I7b6b39ab0c8a427b3166562c3f04cf4a7eaa20e2
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/qmltc/qmltccodewriter.cpp | 8 | ||||
-rw-r--r-- | tools/qmltc/qmltccompiler.cpp | 25 | ||||
-rw-r--r-- | tools/qmltc/qmltcoutputir.h | 3 |
3 files changed, 29 insertions, 7 deletions
diff --git a/tools/qmltc/qmltccodewriter.cpp b/tools/qmltc/qmltccodewriter.cpp index 7820af5ed8..68bd803b15 100644 --- a/tools/qmltc/qmltccodewriter.cpp +++ b/tools/qmltc/qmltccodewriter.cpp @@ -49,6 +49,7 @@ static QString getFunctionCategory(const QmltcMethod &method) category += u" Q_SLOTS"_s; break; case QQmlJSMetaMethod::Method: + case QQmlJSMetaMethod::StaticMethod: break; } return category; @@ -287,6 +288,8 @@ void QmltcCodeWriter::write(QmltcOutputWrapper &code, const QmltcType &type) // TODO: ignoreInit must be eliminated QmltcCodeWriter::write(code, type.externalCtor); + if (type.staticCreate) + QmltcCodeWriter::write(code, *type.staticCreate); } // dtor @@ -384,7 +387,10 @@ void QmltcCodeWriter::write(QmltcOutputWrapper &code, const QmltcMethod &method) { const auto [hSignature, cppSignature] = functionSignatures(method); // Note: augment return type with preambles in declaration - code.rawAppendToHeader(functionReturnType(method) + u" " + hSignature + u";"); + code.rawAppendToHeader((method.type == QQmlJSMetaMethod::StaticMethod + ? u"static " + functionReturnType(method) + : functionReturnType(method)) + + u" " + hSignature + u";"); // do not generate method implementation if it is a signal const auto methodType = method.type; diff --git a/tools/qmltc/qmltccompiler.cpp b/tools/qmltc/qmltccompiler.cpp index ddb10879db..f7d06d8e9a 100644 --- a/tools/qmltc/qmltccompiler.cpp +++ b/tools/qmltc/qmltccompiler.cpp @@ -165,11 +165,6 @@ void QmltcCompiler::compileType( QmltcType ¤t, const QQmlJSScope::ConstPtr &type, std::function<void(QmltcType &, const QQmlJSScope::ConstPtr &)> compileElements) { - if (type->isSingleton()) { - recordError(type->sourceLocation(), u"Singleton types are not supported"_s); - return; - } - Q_ASSERT(!type->internalName().isEmpty()); current.cppType = type->internalName(); Q_ASSERT(!type->baseType()->internalName().isEmpty()); @@ -182,6 +177,7 @@ void QmltcCompiler::compileType( const bool documentRoot = (type == rootType); const bool inlineComponent = type->isInlineComponent(); const bool isAnonymous = !documentRoot || type->internalName().at(0).isLower(); + const bool isSingleton = type->isSingleton(); QmltcCodeGenerator generator { m_url, m_visitor }; @@ -231,7 +227,7 @@ void QmltcCompiler::compileType( // add special member functions current.baselineCtor.access = QQmlJSMetaMethod::Protected; - if (documentRoot || inlineComponent) { + if (documentRoot || inlineComponent || isSingleton) { current.externalCtor.access = QQmlJSMetaMethod::Public; } else { current.externalCtor.access = QQmlJSMetaMethod::Protected; @@ -318,6 +314,23 @@ void QmltcCompiler::compileType( + u"(creator, engine, QQmlData::get(parent)->outerContext);"; } + if (isSingleton) { + // see https://doc.qt.io/qt-6/qqmlengine.html#QML_SINGLETON for context + current.mocCode.append(u"QML_SINGLETON"_s); + auto &staticCreate = current.staticCreate.emplace(); + staticCreate.comments + << u"Used by the engine for singleton creation."_s + << u"See also \\l {https://doc.qt.io/qt-6/qqmlengine.html#QML_SINGLETON}."_s; + staticCreate.type = QQmlJSMetaMethod::StaticMethod; + staticCreate.access = QQmlJSMetaMethod::Public; + staticCreate.name = u"create"_s; + staticCreate.returnType = u"%1 *"_s.arg(current.cppType); + QmltcVariable jsEngine(u"QJSEngine*"_s, u"jsEngine"_s); + staticCreate.parameterList = { engine, jsEngine }; + staticCreate.body << u"Q_UNUSED(jsEngine);"_s + << u"%1 *result = new %1(engine, nullptr);"_s.arg(current.cppType) + << u"return result;"_s; + } auto postponedQmlContextSetup = generator.generate_initCode(current, type); generator.generate_endInitCode(current, type); generator.generate_setComplexBindingsCode(current, type); diff --git a/tools/qmltc/qmltcoutputir.h b/tools/qmltc/qmltcoutputir.h index 46f8e46ee8..8884ddc3a3 100644 --- a/tools/qmltc/qmltcoutputir.h +++ b/tools/qmltc/qmltcoutputir.h @@ -128,6 +128,9 @@ struct QmltcType // TODO: only needed for binding callables - should not be needed, generally bool ignoreInit = false; // specifies whether init and externalCtor should be ignored + + // needed for singletons + std::optional<QmltcMethod> staticCreate{}; }; // Represents whole QML program, compiled to C++ |