181 output << uR"(/****************************************************************************
182** Generated QML type registration code
183**
184** WARNING! All changes made in this file will be lost!
185*****************************************************************************/
186
187)"_s;
189 output << u"#include <QtQml/qqml.h>\n"_s;
190 output << u"#include <QtQml/qqmlmoduleregistration.h>\n"_s;
192 for (
const QString &include : m_includes) {
193 output << u"\n#if __has_include(<%1>)"_s.arg(include);
194 output << u"\n# include <%1>"_s.arg(include);
195 output << u"\n#endif"_s;
201 QString moduleAsSymbol = m_module;
202 static const QRegularExpression nonAlnumRegexp(QLatin1String(
"[^A-Za-z0-9]"));
203 moduleAsSymbol.replace(nonAlnumRegexp, QStringLiteral(
"_"));
205 QString underscoredModuleAsSymbol = m_module;
206 underscoredModuleAsSymbol.replace(QLatin1Char(
'.'), QLatin1Char(
'_'));
208 if (underscoredModuleAsSymbol != moduleAsSymbol
209 || underscoredModuleAsSymbol.isEmpty()
210 || underscoredModuleAsSymbol.front().isDigit()) {
211 warning(outFileName) << m_module <<
"is an invalid QML module URI. You cannot import this.";
214 const QString functionName = QStringLiteral(
"qml_register_types_") + moduleAsSymbol;
216#if !defined(QT_STATIC)
217#define Q_QMLTYPE_EXPORT Q_DECL_EXPORT
218#else
219#define Q_QMLTYPE_EXPORT
220#endif
221)"_s;
223 if (!m_targetNamespace.isEmpty())
224 output << u"namespace "_s << m_targetNamespace << u" {\n"_s;
226 output << u"Q_QMLTYPE_EXPORT void "_s << functionName << u"()\n{"_s;
227 const quint8 majorVersion = m_moduleVersion.majorVersion();
228 const quint8 minorVersion = m_moduleVersion.minorVersion();
230 for (
const auto &version : m_pastMajorVersions) {
232 qmlRegisterModule("%1", %2, 0);
233 qmlRegisterModule("%1", %2, 254);)"_s.arg(m_module)
237 if (minorVersion != 0) {
239 qmlRegisterModule("%1", %2, 0);)"_s.arg(m_module)
244 QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED)"_s;
246 QVector<QAnyStringView> typesRegisteredAnonymously;
248 const auto fillTypesRegisteredAnonymously = [&](
const auto &members, QAnyStringView typeName) {
249 bool foundRevisionEntry =
false;
250 for (
const auto &entry : members) {
251 if (entry.revision.isValid()) {
252 foundRevisionEntry =
true;
257 if (!foundRevisionEntry)
260 if (typesRegisteredAnonymously.contains(typeName))
263 typesRegisteredAnonymously.append(typeName);
265 if (m_followForeignVersioning) {
267 qmlRegisterAnonymousTypesAndRevisions<%1>("%2", %3);)"_s.arg(typeName.toString(),m_module)
272 for (
const auto &version
273 : m_pastMajorVersions +
decltype(m_pastMajorVersions){ majorVersion }) {
275 qmlRegisterAnonymousType<%1, 254>("%2", %3);)"_s.arg(typeName.toString(),m_module)
283 QHash<QString, QList<ExclusiveVersionRange>> qmlElementInfos;
285 for (
const MetaType &classDef : std::as_const(m_types)) {
288 if (classDef.inputFile().isEmpty())
291 QString className = classDef.qualifiedClassName().toString();
292 QString targetName = className;
296 bool targetIsNamespace = classDef.kind() == MetaType::Kind::Namespace;
298 QAnyStringView extendedName;
299 QList<QString> qmlElementNames;
300 QTypeRevision addedIn;
301 QTypeRevision removedIn;
303 for (
const ClassInfo &v : classDef.classInfos()) {
304 const QAnyStringView name = v.name;
305 if (name == S_ELEMENT) {
306 qmlElementNames.append(v.value.toString());
307 }
else if (name == S_FOREIGN) {
308 targetName = v.value.toString();
309 }
else if (name == S_FOREIGN_IS_NAMESPACE) {
310 targetIsNamespace = targetIsNamespace || (v.value == S_TRUE);
311 }
else if (name == S_EXTENDED) {
312 extendedName = v.value;
313 }
else if (name == S_ADDED_IN_VERSION) {
314 int version = toInt(v.value);
315 addedIn = QTypeRevision::fromEncodedVersion(version);
316 addedIn = handleInMinorVersion(addedIn, majorVersion);
317 }
else if (name == S_REMOVED_IN_VERSION) {
318 int version = toInt(v.value);
319 removedIn = QTypeRevision::fromEncodedVersion(version);
320 removedIn = handleInMinorVersion(removedIn, majorVersion);
324 for (QString qmlElementName : std::as_const(qmlElementNames)) {
325 if (qmlElementName == S_ANONYMOUS)
327 if (qmlElementName == S_AUTO)
328 qmlElementName = className;
329 qmlElementInfos[qmlElementName].append({
330 classDef.inputFile(),
340 const QList<QAnyStringView> namespaces
341 = MetaTypesJsonProcessor::namespaces(classDef);
343 const FoundType target = QmlTypesClassDescription::findType(
344 m_types, m_foreignTypes, targetName, namespaces);
348 if (!target.native.isEmpty())
349 targetName = target.native.qualifiedClassName().toString();
351 if (targetIsNamespace) {
355 QString targetTypeName = targetName;
357 if (!target.javaScript.isEmpty() && target.native.isEmpty())
358 warning(target.javaScript) <<
"JavaScript type cannot be used as namespace";
360 if (target.native.kind() == MetaType::Kind::Object)
361 targetTypeName +=
" *"_L1;
366 if (className == targetName || target.native.kind() == MetaType::Kind::Namespace) {
368 {
369 Q_CONSTINIT static auto metaType = QQmlPrivate::metaTypeForNamespace(
370 [](const QtPrivate::QMetaTypeInterface *) {return &%1::staticMetaObject;},
371 "%2");
372 QMetaType(&metaType).id();
373 })"_s.arg(targetName,targetTypeName);
375 Q_ASSERT(!targetTypeName.isEmpty());
376 output << u"\n QMetaType::fromType<%1>().id();"_s.arg(targetTypeName);
379 auto metaObjectPointer = [](QAnyStringView name) -> QString {
381 const QLatin1StringView staticMetaObject =
"::staticMetaObject"_L1;
382 result.reserve(1 + name.length() + staticMetaObject.length());
383 result.append(
'&'_L1);
384 name.visit([&](
auto view) { result.append(view); });
385 result.append(staticMetaObject);
389 if (!qmlElementNames.isEmpty()) {
391 qmlRegisterNamespaceAndRevisions(%1, "%2", %3, nullptr, %4, %5);)"_s
392 .arg(metaObjectPointer(targetName), m_module)
394 .arg(metaObjectPointer(className),
395 extendedName.isEmpty() ? QStringLiteral(
"nullptr")
396 : metaObjectPointer(extendedName));
399 if (!qmlElementNames.isEmpty()) {
400 auto checkRevisions = [&](
const auto &array, QLatin1StringView type) {
401 for (
auto it = array.begin(); it != array.end(); ++it) {
402 if (!it->revision.isValid())
405 QTypeRevision revision = it->revision;
406 if (m_moduleVersion < revision) {
408 << className <<
"is trying to register" << type
410 <<
"with future version" << revision
411 <<
"when module version is only" << m_moduleVersion;
416 const Method::Container methods = classDef.methods();
417 const Property::Container properties = classDef.properties();
419 if (m_moduleVersion.isValid()) {
420 checkRevisions(properties, S_PROPERTY);
421 checkRevisions(methods, S_METHOD);
425 qmlRegisterTypesAndRevisions<%1>("%2", %3);)"_s.arg(className,m_module).arg(majorVersion);
427 const BaseType::Container superClasses = classDef.superClasses();
429 for (
const BaseType &object : classDef.superClasses()) {
430 if (object.access != Access::Public)
433 QAnyStringView superClassName = object.name;
435 QVector<QAnyStringView> classesToCheck;
437 auto checkForRevisions = [&](QAnyStringView typeName) ->
void {
438 auto typeAsMap = findType(typeName);
440 if (typeAsMap.isEmpty()) {
441 typeAsMap = findTypeForeign(typeName);
442 if (typeAsMap.isEmpty())
445 if (!fillTypesRegisteredAnonymously(
446 typeAsMap.properties(), typeName)) {
447 if (!fillTypesRegisteredAnonymously(
448 typeAsMap.sigs(), typeName)) {
449 fillTypesRegisteredAnonymously(
450 typeAsMap.methods(), typeName);
455 for (
const BaseType &object : typeAsMap.superClasses()) {
456 if (object.access == Access::Public)
457 classesToCheck << object.name;
461 checkForRevisions(superClassName);
463 while (!classesToCheck.isEmpty())
464 checkForRevisions(classesToCheck.takeFirst());
467 Q_ASSERT(!className.isEmpty());
470 Q_ASSERT(className == targetName);
473 QMetaType::fromType<%1%2>().id();)"_s.arg(
474 className, classDef.kind() == MetaType::Kind::Object ? u" *" : u"");
478 const auto enums = target.native.enums();
479 for (
const auto &enumerator : enums) {
481 qmlRegisterEnum<%1::%2>("%1::%2");)"_s.arg(
482 targetName, enumerator.name.toString());
483 if (!enumerator.alias.isEmpty()) {
485 qmlRegisterEnum<%1::%2>("%1::%2");)"_s.arg(
486 targetName, enumerator.alias.toString());
491 for (
const auto [qmlName, exportsForSameQmlName] : qmlElementInfos.asKeyValueRange()) {
494 if (exportsForSameQmlName.size() < 2)
498 std::sort(exportsForSameQmlName.begin(), exportsForSameQmlName.end());
499 auto conflictingExportStartIt = exportsForSameQmlName.cbegin();