Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qmetatypesjsonprocessor.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
5
11
12#include <QtCore/qcborarray.h>
13#include <QtCore/qcbormap.h>
14#include <QtCore/qfile.h>
15#include <QtCore/qjsondocument.h>
16#include <QtCore/qqueue.h>
17
19
20using namespace Qt::StringLiterals;
21using namespace Constants;
22using namespace Constants::MetatypesDotJson;
24using namespace QAnyStringViewUtils;
25
26const MetaTypePrivate MetaType::s_empty;
27
28// TODO: This could be optimized to store the objects in a more compact way.
29std::vector<std::unique_ptr<MetaTypePrivate>> s_pool;
30
32{
33 const QJsonDocument jsonValue = QJsonDocument::fromJson(json, error);
34 if (jsonValue.isArray())
35 return QCborValue::fromJsonValue(jsonValue.array());
36 if (jsonValue.isObject())
37 return QCborValue::fromJsonValue(jsonValue.object());
38 return QCborValue();
39}
40
41QList<QAnyStringView> MetaTypesJsonProcessor::namespaces(const MetaType &classDef)
42{
43 const QAnyStringView unqualified = classDef.className();
44 const QAnyStringView qualified = classDef.qualifiedClassName();
45
46 QList<QAnyStringView> namespaces;
47 if (qualified != unqualified) {
48 namespaces = split(qualified, "::"_L1);
49 Q_ASSERT(namespaces.last() == unqualified);
50 namespaces.pop_back();
51 }
52
53 return namespaces;
54}
55
57{
58 for (const QString &source: files) {
59 QCborValue metaObjects;
60 {
61 QFile f(source);
62 if (!f.open(QIODevice::ReadOnly)) {
63 error(source) << "Cannot open file for reading";
64 return false;
65 }
67 metaObjects = fromJson(f.readAll(), &parseError);
68 if (parseError.error != QJsonParseError::NoError) {
70 << "Failed to parse JSON:" << parseError.error
71 << parseError.errorString();
72 return false;
73 }
74 }
75
76 if (metaObjects.isArray()) {
77 const QCborArray metaObjectsArray = metaObjects.toArray();
78 for (const QCborValue &metaObject : metaObjectsArray) {
79 if (!metaObject.isMap()) {
80 error(source) << "JSON is not an object";
81 return false;
82 }
83
84 processTypes(metaObject.toMap());
85 }
86 } else if (metaObjects.isMap()) {
87 processTypes(metaObjects.toMap());
88 } else {
89 error(source) << "JSON is not an object or an array";
90 return false;
91 }
92 }
93
94 return true;
95}
96
98{
99 QFile typesFile(types);
100 if (!typesFile.open(QIODevice::ReadOnly)) {
101 error(types) << "Cannot open foreign types file";
102 return false;
103 }
104
106 QCborValue foreignMetaObjects = fromJson(typesFile.readAll(), &parseError);
107 if (parseError.error != QJsonParseError::NoError) {
108 error(types)
109 << "Failed to parse JSON:" << parseError.error
110 << parseError.errorString();
111 return false;
112 }
113
114 const QCborArray foreignObjectsArray = foreignMetaObjects.toArray();
115 for (const QCborValue &metaObject : foreignObjectsArray) {
116 if (!metaObject.isMap()) {
117 error(types) << "JSON is not an object";
118 return false;
119 }
120
122 }
123
124 return true;
125}
126
128{
129 bool success = true;
130
131 for (const QString &types : foreignTypesFiles) {
133 success = false;
134 }
135 return success;
136}
137
138template<typename String>
139static void sortStringList(QList<String> *list)
140{
141 std::sort(list->begin(), list->end());
142 const auto newEnd = std::unique(list->begin(), list->end());
144}
145
147{
148 sortTypes(m_types);
149}
150
152{
153 sortTypes(m_foreignTypes);
154 sortStringList(&m_primitiveTypes);
155 addRelatedTypes();
156 sortStringList(&m_referencedTypes);
157 sortStringList(&m_includes);
158}
159
161{
162 QString registrationHelper;
163 for (const auto &obj: m_types) {
164 const QString className = obj.className().toString();
165 const QString qualifiedClassName = obj.qualifiedClassName().toString();
166 const QString foreignClassName = className + u"Foreign";
167 QStringList qmlElements;
168 QString qmlUncreatable;
169 QString qmlAttached;
170 bool isSingleton = false;
171 bool isExplicitlyUncreatable = false;
172 bool isNamespace = obj.kind() == MetaType::Kind::Namespace;
173 for (const ClassInfo &entry: obj.classInfos()) {
174 const auto name = entry.name;
175 const auto value = entry.value;
176 if (name == S_ELEMENT) {
177 if (value == S_AUTO) {
178 qmlElements.append(u"QML_NAMED_ELEMENT("_s + className + u")"_s);
179 } else if (value == S_ANONYMOUS) {
180 qmlElements.append(u"QML_ANONYMOUS"_s);
181 } else {
182 qmlElements.append(u"QML_NAMED_ELEMENT("_s + value.toString() + u")");
183 }
184 } else if (name == S_CREATABLE && value == S_FALSE) {
185 isExplicitlyUncreatable = true;
186 } else if (name == S_UNCREATABLE_REASON) {
187 qmlUncreatable = u"QML_UNCREATABLE(\""_s + value.toString() + u"\")";
188 } else if (name == S_ATTACHED) {
189 qmlAttached = u"QML_ATTACHED("_s + value.toString() + u")";
190 } else if (name == S_SINGLETON) {
191 isSingleton = true;
192 }
193 }
194 if (qmlElements.isEmpty())
195 continue; // no relevant entries found
196 const QString spaces = u" "_s;
197 if (isNamespace) {
198 registrationHelper += u"\nnamespace "_s + foreignClassName + u"{\n Q_NAMESPACE\n"_s;
199 registrationHelper += spaces + u"QML_FOREIGN_NAMESPACE(" + qualifiedClassName + u")\n"_s;
200 } else {
201 registrationHelper += u"\nstruct "_s + foreignClassName + u"{\n Q_GADGET\n"_s;
202 registrationHelper += spaces + u"QML_FOREIGN(" + qualifiedClassName + u")\n"_s;
203 }
204 registrationHelper += spaces + qmlElements.join(u"\n"_s) + u"\n"_s;
205 if (isSingleton)
206 registrationHelper += spaces + u"QML_SINGLETON\n"_s;
207 if (isExplicitlyUncreatable) {
208 if (qmlUncreatable.isEmpty())
209 registrationHelper += spaces + uR"(QML_UNCREATABLE(""))" + u"n";
210 else
211 registrationHelper += spaces + qmlUncreatable + u"\n";
212 }
213 if (!qmlAttached.isEmpty())
214 registrationHelper += spaces + qmlAttached + u"\n";
215 registrationHelper += u"}";
216 if (!isNamespace)
217 registrationHelper += u";";
218 registrationHelper += u"\n";
219 }
220 return registrationHelper;
221}
222
223MetaTypesJsonProcessor::PreProcessResult MetaTypesJsonProcessor::preProcess(
224 const MetaType &classDef, PopulateMode populateMode)
225{
226 // If this type is a self-extending value type or a sequence type or has a JavaScript extension
227 // and is not the root object, then it's foreign type has no entry of its own.
228 // In that case we need to generate a "primitive" entry.
229
230 QList<QAnyStringView> aliases;
231 QAnyStringView foreign;
232 RegistrationMode mode = NoRegistration;
233 bool isSelfExtendingValueType = false;
234 bool hasJavaScriptExtension = false;
235 bool isRootObject = false;
236 bool isSequence = false;
237
238 for (const ClassInfo &classInfo : classDef.classInfos()) {
239 if (classInfo.name == S_FOREIGN)
240 foreign = classInfo.value;
241 else if (classInfo.name == S_PRIMITIVE_ALIAS)
242 aliases.append(classInfo.value);
243 else if (classInfo.name == S_EXTENSION_IS_JAVA_SCRIPT)
244 hasJavaScriptExtension = (classInfo.value == S_TRUE);
245 else if (classInfo.name == S_EXTENDED && classDef.kind() == MetaType::Kind::Gadget)
246 isSelfExtendingValueType = classInfo.value == classDef.className();
247 else if (classInfo.name == S_ROOT)
248 isRootObject = (classInfo.value == S_TRUE);
249 else if (classInfo.name == S_SEQUENCE)
250 isSequence = true;
251 else if (populateMode == PopulateMode::Yes && classInfo.name == S_ELEMENT) {
252 switch (classDef.kind()) {
253 case MetaType::Kind::Object:
254 mode = ObjectRegistration;
255 break;
256 case MetaType::Kind::Gadget:
257 mode = GadgetRegistration;
258 break;
259 case MetaType::Kind::Namespace:
260 mode = NamespaceRegistration;
261 break;
262 default:
263 warning(classDef)
264 << "Not registering a classInfo which is neither an object,"
265 << "nor a gadget, nor a namespace:"
266 << classInfo.name.toString();
267 break;
268 }
269 }
270 }
271
272 return PreProcessResult {
273 aliases,
274 (!isRootObject && (isSequence || isSelfExtendingValueType || hasJavaScriptExtension))
275 ? foreign
276 : QAnyStringView(),
277 mode
278 };
279
280}
281
282// TODO: Remove this when QAnyStringView gets a proper qHash()
283static size_t qHash(QAnyStringView string, size_t seed = 0)
284{
285 return string.visit([seed](auto view) {
286 if constexpr (std::is_same_v<decltype(view), QStringView>)
287 return qHash(view, seed);
288 if constexpr (std::is_same_v<decltype(view), QLatin1StringView>)
289 return qHash(view, seed);
290 if constexpr (std::is_same_v<decltype(view), QUtf8StringView>)
291 return qHash(QByteArrayView(view.data(), view.length()), seed);
292 });
293}
294
295static bool qualifiedClassNameLessThan(const MetaType &a, const MetaType &b)
296{
297 return a.qualifiedClassName() < b.qualifiedClassName();
298}
299
300void MetaTypesJsonProcessor::addRelatedTypes()
301{
302 QSet<QAnyStringView> processedRelatedNativeNames;
303 QSet<QAnyStringView> processedRelatedJavaScriptNames;
304 QSet<QAnyStringView> unresolvedForeignNames;
305 QQueue<MetaType> typeQueue;
306 typeQueue.append(m_types);
307
308 const auto addRelatedName
309 = [&](QAnyStringView relatedName, const QList<QAnyStringView> &namespaces) {
311 m_types, m_foreignTypes, relatedName, namespaces)) {
312
313 if (!related.javaScript.isEmpty())
314 processedRelatedJavaScriptNames.insert(related.javaScript.qualifiedClassName());
315
316 if (!related.native.isEmpty())
317 processedRelatedNativeNames.insert(related.native.qualifiedClassName());
318
319 return true;
320 } else {
321 return false;
322 }
323 };
324
325 const auto addRelatedType = [&](const MetaType &type) {
326 const QAnyStringView qualifiedName = type.qualifiedClassName();
327 if (type.inputFile().isEmpty())
328 processedRelatedJavaScriptNames.insert(qualifiedName);
329 else
330 processedRelatedNativeNames.insert(qualifiedName);
331 };
332
333 // First mark all classes registered from this module as already processed.
334 for (const MetaType &type : std::as_const(m_types)) {
335 addRelatedType(type);
336 for (const ClassInfo &obj : type.classInfos()) {
337 if (obj.name == S_FOREIGN) {
338 const QAnyStringView foreign = obj.value;
339 if (!addRelatedName(foreign, namespaces(type)))
340 unresolvedForeignNames.insert(foreign);
341 break;
342 }
343 }
344 }
345
346 // Then mark all classes registered from other modules as already processed.
347 // We don't want to generate them again for this module.
348 for (const MetaType &foreignType : std::as_const(m_foreignTypes)) {
349 bool seenQmlPrefix = false;
350 for (const ClassInfo &obj : foreignType.classInfos()) {
351 const QAnyStringView name = obj.name;
352 if (!seenQmlPrefix && startsWith(name, "QML."_L1)) {
353 addRelatedType(foreignType);
354 seenQmlPrefix = true;
355 }
356 if (name == S_FOREIGN) {
357 const QAnyStringView foreign = obj.value;
358 if (!addRelatedName(foreign, namespaces(foreignType)))
359 unresolvedForeignNames.insert(foreign);
360 break;
361 }
362 }
363 }
364
365 const auto addReference = [&](const MetaType &type, QSet<QAnyStringView> *processedRelatedNames,
366 FoundType::Origin origin) {
367 if (type.isEmpty())
368 return;
369 QAnyStringView qualifiedName = type.qualifiedClassName();
370 m_referencedTypes.append(qualifiedName);
371 const qsizetype size = processedRelatedNames->size();
372 processedRelatedNames->insert(qualifiedName);
373
374 if (processedRelatedNames->size() == size)
375 return;
376
377 typeQueue.enqueue(type);
378
379 if (origin == FoundType::OwnTypes)
380 return;
381
382 // Add to own types since we need it for our registrations.
383 const auto insert = std::lower_bound(
384 m_types.constBegin(), m_types.constEnd(), type,
386 m_types.insert(insert, type);
387
388 // Also add its include. We don't want to rely on transitive inclues.
389 const QString inputFile = type.inputFile();
390 if (!inputFile.isEmpty())
391 m_includes.append(inputFile);
392
393 // Remove from the foreign types to avoid the ODR warning.
394 const auto remove = std::equal_range(
395 m_foreignTypes.constBegin(), m_foreignTypes.constEnd(), type,
397 for (auto it = remove.first; it != remove.second; ++it) {
398 if (*it == type) {
399 m_foreignTypes.erase(it);
400 break;
401 }
402 }
403 };
404
405 const auto addInterface
406 = [&](QAnyStringView typeName, const QList<QAnyStringView> &namespaces) {
408 m_types, m_foreignTypes, typeName, namespaces)) {
409 if (!other.native.isEmpty()) {
410 addReference(other.native, &processedRelatedNativeNames, other.nativeOrigin);
411 return true;
412 }
413 } else {
414 // Do not warn about unresolved interfaces.
415 // They don't have to have Q_OBJECT or Q_GADGET.
416 unresolvedForeignNames.insert(typeName);
417 }
418
419 processedRelatedNativeNames.insert(typeName);
420 return false;
421 };
422
423 const auto addType = [&](const MetaType &context, QAnyStringView typeName,
424 const QList<QAnyStringView> &namespaces, QAnyStringView relation) {
426 m_types, m_foreignTypes, typeName, namespaces)) {
427 addReference(other.native, &processedRelatedNativeNames, other.nativeOrigin);
428 addReference(other.javaScript, &processedRelatedJavaScriptNames, other.javaScriptOrigin);
429 return true;
430 }
431
432 // If it's an enum, add the surrounding type.
433 const QLatin1StringView separator("::");
434 if (const qsizetype index = lastIndexOf(typeName, separator); index > 0) {
436 m_types, m_foreignTypes, typeName.left(index), namespaces)) {
437
438 const QAnyStringView enumName = typeName.mid(index + separator.length());
439
440 for (const Enum &enumerator : other.native.enums()) {
441 if (enumerator.name != enumName && enumerator.alias != enumName)
442 continue;
443
444 addReference(other.native, &processedRelatedNativeNames, other.nativeOrigin);
445 addReference(
446 other.javaScript, &processedRelatedJavaScriptNames,
447 other.javaScriptOrigin);
448 return true;
449 }
450 }
451 }
452
453 // If it's an enum of the context type itself, we don't have to do anything.
454 for (const Enum &enumerator : context.enums()) {
455 if (enumerator.name == typeName || enumerator.alias == typeName)
456 return true;
457 }
458
459 // If we've detected this type as unresolved foreign and it actually belongs to this module,
460 // we'll get to it again when we process it as foreign type. In that case we'll look at the
461 // special cases for sequences and extensions.
462 if (!unresolvedForeignNames.contains(typeName) && !isPrimitive(typeName))
463 warning(context) << typeName << "is used as" << relation << "type but cannot be found.";
464
465 processedRelatedNativeNames.insert(typeName);
466 processedRelatedJavaScriptNames.insert(typeName);
467 return false;
468 };
469
470 const auto doAddReferences = [&](QAnyStringView typeName,
471 const QList<QAnyStringView> &namespaces) {
473 m_types, m_foreignTypes, typeName, namespaces)) {
474 addReference(
475 other.native, &processedRelatedNativeNames, other.nativeOrigin);
476 addReference(
477 other.javaScript, &processedRelatedJavaScriptNames, other.javaScriptOrigin);
478 return true;
479 }
480
481 return false;
482 };
483
484 const auto addSupers = [&](const MetaType &context, const QList<QAnyStringView> &namespaces) {
485 for (const Interface &iface : context.ifaces())
486 addInterface(interfaceName(iface), namespaces);
487
488 // We don't warn about missing bases for value types. They don't have to be registered.
489 bool warnAboutSupers = context.kind() != MetaType::Kind::Gadget;
490
491 QList<QAnyStringView> missingSupers;
492
493 for (const BaseType &superObject : context.superClasses()) {
494 if (superObject.access != Access::Public)
495 continue;
496
497 QAnyStringView typeName = superObject.name;
498 if (doAddReferences(typeName, namespaces))
499 warnAboutSupers = false;
500 else
501 missingSupers.append(typeName);
502 }
503
504 for (QAnyStringView typeName : std::as_const(missingSupers)) {
505 // If we've found one valid base type, don't complain about the others.
506 if (warnAboutSupers
507 && !unresolvedForeignNames.contains(typeName)
508 && !isPrimitive(typeName)) {
509 warning(context) << typeName << "is used as base type but cannot be found.";
510 }
511
512 processedRelatedNativeNames.insert(typeName);
513 processedRelatedJavaScriptNames.insert(typeName);
514 }
515 };
516
517 const auto addProperties = [&](const MetaType &context,
518 const QList<QAnyStringView> &namespaces) {
519 for (const Property &property : context.properties()) {
520 ResolvedTypeAlias resolved(property.type);
521 if (!resolved.type.isEmpty())
522 addType(context, resolved.type, namespaces, "property");
523 }
524 };
525
526 const auto addMethods = [&](const MetaType &context,
527 const QList<QAnyStringView> &namespaces) {
528 for (const Method::Container &methods
529 : {context.methods(), context.constructors(), context.sigs() }) {
530 for (const Method &methodObject : methods) {
531 for (const Argument &argument : std::as_const(methodObject.arguments)) {
532 ResolvedTypeAlias resolved(argument.type);
533 if (!resolved.type.isEmpty())
534 addType(context, resolved.type, namespaces, "argument");
535 }
536
537 ResolvedTypeAlias resolved(methodObject.returnType);
538 if (!resolved.type.isEmpty())
539 addType(context, resolved.type, namespaces, "return");
540 }
541 }
542 };
543
544 const auto addEnums = [&](const MetaType &context,
545 const QList<QAnyStringView> &namespaces) {
546 for (const Enum &enumerator : context.enums()) {
547 ResolvedTypeAlias resolved(enumerator.type);
548 if (!resolved.type.isEmpty())
549 addType(context, resolved.type, namespaces, "enum");
550 }
551 };
552
553 const auto addRelation = [&](const MetaType &classDef, const ClassInfo &obj,
554 const QList<QAnyStringView> &namespaces) {
555 const QAnyStringView objNameValue = obj.name;
556 if (objNameValue == S_ATTACHED) {
557 addType(classDef, obj.value, namespaces, "attached");
558 return true;
559 } else if (objNameValue == S_SEQUENCE) {
561 addType(classDef, value.type, namespaces, "sequence value");
562 return true;
563 } else if (objNameValue == S_EXTENDED) {
564 const QAnyStringView value = obj.value;
565 addType(classDef, value, namespaces, "extension");
566 return true;
567 }
568 return false;
569 };
570
571 // Then recursively iterate the super types and attached types, marking the
572 // ones we are interested in as related.
573 while (!typeQueue.isEmpty()) {
574 QAnyStringView unresolvedForeign;
575
576 const MetaType classDef = typeQueue.dequeue();
577 const QList<QAnyStringView> namespaces = MetaTypesJsonProcessor::namespaces(classDef);
578
579 for (const ClassInfo &obj : classDef.classInfos()) {
580 if (addRelation(classDef, obj, namespaces))
581 continue;
582 if (obj.name != S_FOREIGN)
583 continue;
584
585 const QAnyStringView foreignClassName = obj.value;
586
587 // A type declared as QML_FOREIGN will usually be a foreign type, but it can
588 // actually be an additional registration of a local type, too.
590 m_foreignTypes, {}, foreignClassName, namespaces)) {
591 const MetaType other = found.select(classDef, "Foreign");
592 const QList<QAnyStringView> otherNamespaces
594 addSupers(other, otherNamespaces);
595 addProperties(other, otherNamespaces);
596 addMethods(other, otherNamespaces);
597 addEnums(other, otherNamespaces);
598
599 for (const ClassInfo &obj : other.classInfos()) {
600 if (addRelation(classDef, obj, otherNamespaces))
601 break;
602 // No, you cannot chain S_FOREIGN declarations. Sorry.
603 }
605 m_types, {}, foreignClassName, namespaces)) {
606 unresolvedForeign = foreignClassName;
607 }
608 }
609
610 if (!unresolvedForeign.isEmpty() && !isPrimitive(unresolvedForeign)) {
611 warning(classDef)
612 << unresolvedForeign
613 << "is declared as foreign type, but cannot be found.";
614 }
615
616 addSupers(classDef, namespaces);
617 addProperties(classDef, namespaces);
618 addMethods(classDef, namespaces);
619 addEnums(classDef, namespaces);
620 }
621}
622
623void MetaTypesJsonProcessor::sortTypes(QVector<MetaType> &types)
624{
625 std::sort(types.begin(), types.end(), qualifiedClassNameLessThan);
626}
627
628QString MetaTypesJsonProcessor::resolvedInclude(QAnyStringView include)
629{
630 if (!m_privateIncludes)
631 return include.toString();
632
633 if (endsWith(include, "_p.h"_L1))
634 return QLatin1String("private/") + include.toString();
635
636 if (startsWith(include, "qplatform"_L1) || startsWith(include, "qwindowsystem"_L1))
637 return QLatin1String("qpa/") + include.toString();
638
639 return include.toString();
640}
641
643{
644 const QString include = resolvedInclude(toStringView(types, S_INPUT_FILE));
645 const QCborArray classes = types[S_CLASSES].toArray();
646 for (const QCborValue &cls : classes) {
647 const MetaType classDef(cls.toMap(), include);
648
649 const PreProcessResult preprocessed = preProcess(classDef, PopulateMode::Yes);
650 switch (preprocessed.mode) {
651 case NamespaceRegistration:
652 case GadgetRegistration:
653 case ObjectRegistration: {
654 if (!endsWith(include, QLatin1String(".h"))
655 && !endsWith(include, QLatin1String(".hpp"))
656 && !endsWith(include, QLatin1String(".hxx"))
657 && !endsWith(include, QLatin1String(".hh"))
658 && !endsWith(include, QLatin1String(".py"))
659 && contains(include, QLatin1Char('.'))) {
660 warning(include)
661 << "Class" << classDef.qualifiedClassName()
662 << "is declared in" << include << "which appears not to be a header."
663 << "The compilation of its registration to QML may fail.";
664 }
665 m_includes.append(include);
666 m_types.emplaceBack(classDef);
667 break;
668 }
669 case NoRegistration:
670 m_foreignTypes.emplaceBack(classDef);
671 break;
672 }
673
674 if (!preprocessed.foreignPrimitive.isEmpty()) {
675 m_primitiveTypes.emplaceBack(preprocessed.foreignPrimitive);
676 m_primitiveTypes.append(preprocessed.primitiveAliases);
677 }
678 }
679}
680
682{
683 const QString include = resolvedInclude(toStringView(types, S_INPUT_FILE));
684 const QCborArray classes = types[S_CLASSES].toArray();
685 for (const QCborValue &cls : classes) {
686 const MetaType classDef(cls.toMap(), include);
687 PreProcessResult preprocessed = preProcess(classDef, PopulateMode::No);
688
689 m_foreignTypes.emplaceBack(classDef);
690 if (!preprocessed.foreignPrimitive.isEmpty()) {
691 m_primitiveTypes.emplaceBack(preprocessed.foreignPrimitive);
692 m_primitiveTypes.append(preprocessed.primitiveAliases);
693 }
694 }
695}
696
698{
699 const auto it = cbor.find(S_REVISION);
700 return it == cbor.end()
701 ? QTypeRevision()
703}
704
705static Access getAccess(const QCborMap &cbor)
706{
708 if (access == S_PUBLIC)
709 return Access::Public;
710 if (access == S_PROTECTED)
711 return Access::Protected;
712 return Access::Private;
713}
714
716 : name(toStringView(cbor, S_NAME))
717 , access(getAccess(cbor))
718{
719}
720
722 : name(toStringView(cbor, S_NAME))
723 , value(toStringView(cbor, S_VALUE))
724{
725}
726
728{
729 if (cbor.isArray()) {
730 QCborArray needlessWrapping = cbor.toArray();
731 className = needlessWrapping.size() > 0
732 ? toStringView(needlessWrapping[0].toMap(), S_CLASS_NAME)
733 : QAnyStringView();
734 } else {
736 }
737}
738
740 : name(toStringView(cbor, S_NAME))
741 , type(toStringView(cbor, S_TYPE))
742 , member(toStringView(cbor, S_MEMBER))
743 , read(toStringView(cbor, S_READ))
744 , write(toStringView(cbor, S_WRITE))
745 , reset(toStringView(cbor, S_RESET))
746 , notify(toStringView(cbor, S_NOTIFY))
747 , bindable(toStringView(cbor, S_BINDABLE))
748 , privateClass(toStringView(cbor, S_PRIVATE_CLASS))
749 , index(cbor[S_INDEX].toInteger(-1))
750 , revision(getRevision(cbor))
751 , isFinal(cbor[S_FINAL].toBool())
752 , isConstant(cbor[S_CONSTANT].toBool())
753 , isRequired(cbor[S_REQUIRED].toBool())
754{
755}
756
758 : name(toStringView(cbor, S_NAME))
759 , type(toStringView(cbor, S_TYPE))
760{
761}
762
763Method::Method(const QCborMap &cbor, bool isConstructor)
764 : name(toStringView(cbor, S_NAME))
765 , returnType(toStringView(cbor, S_RETURN_TYPE))
766 , revision(getRevision(cbor))
767 , access(getAccess(cbor))
768 , isCloned(cbor[S_IS_CLONED].toBool())
769 , isJavaScriptFunction(cbor[S_IS_JAVASCRIPT_FUNCTION].toBool())
770 , isConstructor(isConstructor || cbor[S_IS_CONSTRUCTOR].toBool())
771{
772 const QCborArray args = cbor[S_ARGUMENTS].toArray();
773 for (const QCborValue &argument : args)
774 arguments.emplace_back(argument.toMap());
775
776 if (arguments.size() == 1) {
777 const QAnyStringView type = arguments[0].type;
778 if (type == "QQmlV4FunctionPtr"_L1 || type == "QQmlV4Function*"_L1)
780 }
781}
782
784 : name(toStringView(cbor, S_NAME))
785 , alias(toStringView(cbor, S_ALIAS))
786 , type(toStringView(cbor, S_TYPE))
787 , isFlag(cbor[S_IS_FLAG].toBool())
788 , isClass(cbor[S_IS_CLASS].toBool())
789{
790 const QCborArray vals = cbor[S_VALUES].toArray();
791 for (const QCborValue &value : vals)
792 values.emplace_back(toStringView(value));
793}
794
796 : cbor(cbor)
797 , inputFile(inputFile)
798{
801
802 const QCborArray cborSuperClasses = cbor[S_SUPER_CLASSES].toArray();
803 for (const QCborValue &superClass : cborSuperClasses)
804 superClasses.emplace_back(superClass.toMap());
805
806 const QCborArray cborClassInfos = cbor[S_CLASS_INFOS].toArray();
807 for (const QCborValue &classInfo : cborClassInfos)
808 classInfos.emplace_back(classInfo.toMap());
809
810 const QCborArray cborIfaces = cbor[S_INTERFACES].toArray();
811 for (const QCborValue &iface : cborIfaces)
812 ifaces.emplace_back(iface);
813
814 const QCborArray cborProperties = cbor[S_PROPERTIES].toArray();
815 for (const QCborValue &property : cborProperties)
816 properties.emplace_back(property.toMap());
817
818 for (const QCborArray &cborMethods : { cbor[S_METHODS].toArray(), cbor[S_SLOTS].toArray() }) {
819 for (const QCborValue &method : cborMethods)
820 methods.emplace_back(method.toMap(), false);
821 }
822
823 const QCborArray cborSigs = cbor[S_SIGNALS].toArray();
824 for (const QCborValue &sig : cborSigs)
825 sigs.emplace_back(sig.toMap(), false);
826
827 const QCborArray cborConstructors = cbor[S_CONSTRUCTORS].toArray();
828 for (const QCborValue &constructor : cborConstructors)
829 constructors.emplace_back(constructor.toMap(), true);
830
831 const QCborArray cborEnums = cbor[S_ENUMS].toArray();
832 for (const QCborValue &enumerator : cborEnums)
833 enums.emplace_back(enumerator.toMap());
834
835 if (cbor[S_GADGET].toBool())
837 else if (cbor[S_OBJECT].toBool())
839 else if (cbor[S_NAMESPACE].toBool())
841}
842
843MetaType::MetaType(const QCborMap &cbor, const QString &inputFile)
844 : d(s_pool.emplace_back(std::make_unique<MetaTypePrivate>(cbor, inputFile)).get())
845{}
846
static JNINativeMethod methods[]
MetaType()=default
bool processForeignTypes(const QString &foreignTypesFile)
static QList< QAnyStringView > namespaces(const MetaType &classDef)
bool processTypes(const QStringList &files)
\inmodule QtCore
constexpr qsizetype size() const noexcept
Returns the size of this string view, in the encoding's code points.
QString toString() const
Returns a deep copy of this string view's data as a QString.
Definition qstring.h:1218
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qcborarray.h:20
\inmodule QtCore\reentrant
Definition qcbormap.h:21
iterator end()
Returns a map iterator representing an element just past the last element in the map.
Definition qcbormap.h:318
iterator find(qint64 key)
Definition qcbormap.cpp:795
\inmodule QtCore\reentrant
Definition qcborvalue.h:47
QCborArray toArray() const
QCborMap toMap() const
bool isArray() const
Returns true if this QCborValue is of the array type.
Definition qcborvalue.h:158
static QCborValue fromJsonValue(const QJsonValue &v)
Converts the JSON value contained in v into its corresponding CBOR value and returns it.
bool isMap() const
Returns true if this QCborValue is of the map type.
Definition qcborvalue.h:159
\inmodule QtCore
Definition qfile.h:93
\inmodule QtCore\reentrant
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=nullptr)
Parses json as a UTF-8 encoded JSON document, and creates a QJsonDocument from it.
iterator erase(const_iterator begin, const_iterator end)
Definition qlist.h:889
iterator end()
Definition qlist.h:626
reference emplaceBack(Args &&... args)
Definition qlist.h:882
iterator begin()
Definition qlist.h:625
void append(parameter_type t)
Definition qlist.h:458
const_iterator constEnd() const noexcept
Definition qlist.h:633
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
\inmodule QtCore
static constexpr QTypeRevision fromEncodedVersion(Integer value)
Produces a QTypeRevision from the given value.
T & emplace_back(Args &&...args)
cache insert(employee->id(), employee)
QSet< QString >::iterator it
QList< QVariant > arguments
static constexpr QLatin1StringView S_UNCREATABLE_REASON
static constexpr QLatin1StringView S_ATTACHED
static constexpr QLatin1StringView S_FOREIGN
static constexpr QLatin1StringView S_SEQUENCE
static constexpr QLatin1StringView S_PRIMITIVE_ALIAS
static constexpr QLatin1StringView S_EXTENDED
static constexpr QLatin1StringView S_SINGLETON
static constexpr QLatin1StringView S_EXTENSION_IS_JAVA_SCRIPT
static constexpr QLatin1StringView S_ELEMENT
static constexpr QLatin1StringView S_CREATABLE
static constexpr QLatin1StringView S_ROOT
static constexpr QLatin1StringView S_VALUE
static constexpr QLatin1StringView S_PROTECTED
static constexpr QLatin1StringView S_ANONYMOUS
static constexpr QLatin1StringView S_SIGNALS
static constexpr QLatin1StringView S_QUALIFIED_CLASS_NAME
static constexpr QLatin1StringView S_NAME
static constexpr QLatin1StringView S_SUPER_CLASSES
static constexpr QLatin1StringView S_TYPE
static constexpr QLatin1StringView S_INPUT_FILE
static constexpr QLatin1StringView S_CONSTRUCTORS
static constexpr QLatin1StringView S_TRUE
static constexpr QLatin1StringView S_PRIVATE_CLASS
static constexpr QLatin1StringView S_ARGUMENTS
static constexpr QLatin1StringView S_CONSTANT
static constexpr QLatin1StringView S_ACCESS
static constexpr QLatin1StringView S_ALIAS
static constexpr QLatin1StringView S_REQUIRED
static constexpr QLatin1StringView S_IS_JAVASCRIPT_FUNCTION
static constexpr QLatin1StringView S_CLASS_NAME
static constexpr QLatin1StringView S_NOTIFY
static constexpr QLatin1StringView S_CLASS_INFOS
static constexpr QLatin1StringView S_RETURN_TYPE
static constexpr QLatin1StringView S_RESET
static constexpr QLatin1StringView S_MEMBER
static constexpr QLatin1StringView S_IS_CONSTRUCTOR
static constexpr QLatin1StringView S_REVISION
static constexpr QLatin1StringView S_PUBLIC
static constexpr QLatin1StringView S_SLOTS
static constexpr QLatin1StringView S_PROPERTIES
static constexpr QLatin1StringView S_IS_CLONED
static constexpr QLatin1StringView S_FALSE
static constexpr QLatin1StringView S_IS_CLASS
static constexpr QLatin1StringView S_VALUES
static constexpr QLatin1StringView S_READ
static constexpr QLatin1StringView S_GADGET
static constexpr QLatin1StringView S_CLASSES
static constexpr QLatin1StringView S_FINAL
static constexpr QLatin1StringView S_ENUMS
static constexpr QLatin1StringView S_IS_FLAG
static constexpr QLatin1StringView S_INDEX
static constexpr QLatin1StringView S_WRITE
static constexpr QLatin1StringView S_METHODS
static constexpr QLatin1StringView S_INTERFACES
static constexpr QLatin1StringView S_AUTO
static constexpr QLatin1StringView S_NAMESPACE
static constexpr QLatin1StringView S_BINDABLE
static constexpr QLatin1StringView S_OBJECT
QAnyStringView toStringView(const QCborValue &value)
bool endsWith(QAnyStringView whole, QLatin1StringView part)
bool startsWith(QAnyStringView whole, QLatin1StringView part)
Combined button and popup list for selecting options.
constexpr QBindableInterface iface
Definition qproperty.h:666
static void * context
static const QCssKnownValue properties[NumProperties - 1]
DBusConnection const char DBusError * error
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
static QDBusError::ErrorType get(const char *name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
const char * typeName
static Access getAccess(const QCborMap &cbor)
static QCborValue fromJson(const QByteArray &json, QJsonParseError *error)
static void sortStringList(QList< String > *list)
static QTypeRevision getRevision(const QCborMap &cbor)
static bool qualifiedClassNameLessThan(const MetaType &a, const MetaType &b)
std::vector< std::unique_ptr< MetaTypePrivate > > s_pool
static size_t qHash(QAnyStringView string, size_t seed=0)
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean b
GLenum mode
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLsizei GLenum GLenum * types
GLfloat GLfloat f
GLenum type
GLenum access
GLuint name
GLsizei GLsizei GLchar * source
GLhandleARB obj
[2]
GLboolean reset
GLuint entry
static QStringList aliases(const QQmlJSScope::ConstPtr &scope)
QAnyStringView interfaceName(const Interface &iface)
QDebug warning(QAnyStringView fileName, int lineNumber)
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static void split(QT_FT_Vector *b)
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
ptrdiff_t qsizetype
Definition qtypes.h:165
ReturnedValue read(const char *data)
const char property[13]
Definition qwizard.cpp:101
const char className[16]
[1]
Definition qwizard.cpp:100
QList< int > list
[14]
gzip write("uncompressed data")
settings remove("monkey")
obj metaObject() -> className()
QCborValue(QCborTag(2), QByteArray("\x01\0\0\0\0\0\0\0\0", 9))
[0]
value toMap().value(key)
[3]
list lastIndexOf("B")
QSharedPointer< T > other(t)
[5]
QStringList files
[8]
QQuickView * view
[0]
QDBusArgument argument
QJSValueList args
Argument()=default
BaseType()=default
ClassInfo()=default
Enum()=default
QAnyStringView className
Interface()=default
MetaTypePrivate()=default
ClassInfo::Container classInfos
BaseType::Container superClasses
Property::Container properties
Interface::Container ifaces
QAnyStringView qualifiedClassName
Method::Container constructors
std::vector< Method > Container
Method()=default
Argument::Container arguments
Property()=default
\inmodule QtCore\reentrant
ParseError error
QString errorString() const
\variable QJsonParseError::error
\inmodule QtCore \reentrant
Definition qchar.h:18
static FoundType findType(const QVector< MetaType > &types, const QVector< MetaType > &foreign, const QAnyStringView &name, const QList< QAnyStringView > &namespaces)
QT_BEGIN_NAMESPACE bool toBool(const QString &str)
Definition utils.h:14