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 sortStringList(&m_usingDeclarations);
156 addRelatedTypes();
157 sortStringList(&m_referencedTypes);
158 sortStringList(&m_includes);
159}
160
162{
163 QString registrationHelper;
164 for (const auto &obj: m_types) {
165 const QString className = obj.className().toString();
166 const QString qualifiedClassName = obj.qualifiedClassName().toString();
167 const QString foreignClassName = className + u"Foreign";
168 QStringList qmlElements;
169 QString qmlUncreatable;
170 QString qmlAttached;
171 bool isSingleton = false;
172 bool isExplicitlyUncreatable = false;
173 bool isNamespace = obj.kind() == MetaType::Kind::Namespace;
174 for (const ClassInfo &entry: obj.classInfos()) {
175 const auto name = entry.name;
176 const auto value = entry.value;
177 if (name == S_ELEMENT) {
178 if (value == S_AUTO) {
179 qmlElements.append(u"QML_NAMED_ELEMENT("_s + className + u")"_s);
180 } else if (value == S_ANONYMOUS) {
181 qmlElements.append(u"QML_ANONYMOUS"_s);
182 } else {
183 qmlElements.append(u"QML_NAMED_ELEMENT("_s + value.toString() + u")");
184 }
185 } else if (name == S_CREATABLE && value == S_FALSE) {
186 isExplicitlyUncreatable = true;
187 } else if (name == S_UNCREATABLE_REASON) {
188 qmlUncreatable = u"QML_UNCREATABLE(\""_s + value.toString() + u"\")";
189 } else if (name == S_ATTACHED) {
190 qmlAttached = u"QML_ATTACHED("_s + value.toString() + u")";
191 } else if (name == S_SINGLETON) {
192 isSingleton = true;
193 }
194 }
195 if (qmlElements.isEmpty())
196 continue; // no relevant entries found
197 const QString spaces = u" "_s;
198 if (isNamespace) {
199 registrationHelper += u"\nnamespace "_s + foreignClassName + u"{\n Q_NAMESPACE\n"_s;
200 registrationHelper += spaces + u"QML_FOREIGN_NAMESPACE(" + qualifiedClassName + u")\n"_s;
201 } else {
202 registrationHelper += u"\nstruct "_s + foreignClassName + u"{\n Q_GADGET\n"_s;
203 registrationHelper += spaces + u"QML_FOREIGN(" + qualifiedClassName + u")\n"_s;
204 }
205 registrationHelper += spaces + qmlElements.join(u"\n"_s) + u"\n"_s;
206 if (isSingleton)
207 registrationHelper += spaces + u"QML_SINGLETON\n"_s;
208 if (isExplicitlyUncreatable) {
209 if (qmlUncreatable.isEmpty())
210 registrationHelper += spaces + uR"(QML_UNCREATABLE(""))" + u"n";
211 else
212 registrationHelper += spaces + qmlUncreatable + u"\n";
213 }
214 if (!qmlAttached.isEmpty())
215 registrationHelper += spaces + qmlAttached + u"\n";
216 registrationHelper += u"}";
217 if (!isNamespace)
218 registrationHelper += u";";
219 registrationHelper += u"\n";
220 }
221 return registrationHelper;
222}
223
224MetaTypesJsonProcessor::PreProcessResult MetaTypesJsonProcessor::preProcess(
225 const MetaType &classDef, PopulateMode populateMode)
226{
227 // If this type is a self-extending value type or a sequence type or has a JavaScript extension
228 // and is not the root object, then it's foreign type has no entry of its own.
229 // In that case we need to generate a "primitive" entry.
230
231 QList<QAnyStringView> primitiveAliases;
232 UsingDeclaration usingDeclaration;
233
234 RegistrationMode mode = NoRegistration;
235 bool isSelfExtendingValueType = false;
236 bool hasJavaScriptExtension = false;
237 bool isRootObject = false;
238 bool isSequence = false;
239
240 for (const ClassInfo &classInfo : classDef.classInfos()) {
241 if (classInfo.name == S_FOREIGN)
242 usingDeclaration.alias = classInfo.value;
243 else if (classInfo.name == S_PRIMITIVE_ALIAS)
244 primitiveAliases.append(classInfo.value);
245 else if (classInfo.name == S_EXTENSION_IS_JAVA_SCRIPT)
246 hasJavaScriptExtension = (classInfo.value == S_TRUE);
247 else if (classInfo.name == S_EXTENDED && classDef.kind() == MetaType::Kind::Gadget)
248 isSelfExtendingValueType = classInfo.value == classDef.className();
249 else if (classInfo.name == S_ROOT)
250 isRootObject = (classInfo.value == S_TRUE);
251 else if (classInfo.name == S_SEQUENCE)
252 isSequence = true;
253 else if (classInfo.name == S_USING)
254 usingDeclaration.original = classInfo.value;
255 else if (populateMode == PopulateMode::Yes && classInfo.name == S_ELEMENT) {
256 switch (classDef.kind()) {
257 case MetaType::Kind::Object:
258 mode = ObjectRegistration;
259 break;
260 case MetaType::Kind::Gadget:
261 mode = GadgetRegistration;
262 break;
263 case MetaType::Kind::Namespace:
264 mode = NamespaceRegistration;
265 break;
266 default:
267 warning(classDef)
268 << "Not registering a classInfo which is neither an object,"
269 << "nor a gadget, nor a namespace:"
270 << classInfo.name.toString();
271 break;
272 }
273 }
274 }
275
276 return PreProcessResult {
277 std::move(primitiveAliases),
278 usingDeclaration,
279 (!isRootObject && (isSequence || isSelfExtendingValueType || hasJavaScriptExtension))
280 ? usingDeclaration.alias
281 : QAnyStringView(),
282 mode
283 };
284
285}
286
287// TODO: Remove this when QAnyStringView gets a proper qHash()
288static size_t qHash(QAnyStringView string, size_t seed = 0)
289{
290 return string.visit([seed](auto view) {
291 if constexpr (std::is_same_v<decltype(view), QStringView>)
292 return qHash(view, seed);
293 if constexpr (std::is_same_v<decltype(view), QLatin1StringView>)
294 return qHash(view, seed);
295 if constexpr (std::is_same_v<decltype(view), QUtf8StringView>)
296 return qHash(QByteArrayView(view.data(), view.length()), seed);
297 });
298}
299
300static bool qualifiedClassNameLessThan(const MetaType &a, const MetaType &b)
301{
302 return a.qualifiedClassName() < b.qualifiedClassName();
303}
304
305void MetaTypesJsonProcessor::addRelatedTypes()
306{
307 QSet<QAnyStringView> processedRelatedNativeNames;
308 QSet<QAnyStringView> processedRelatedJavaScriptNames;
309 QSet<QAnyStringView> unresolvedForeignNames;
310 QQueue<MetaType> typeQueue;
311 typeQueue.append(m_types);
312
313 const auto addRelatedName
314 = [&](QAnyStringView relatedName, const QList<QAnyStringView> &namespaces) {
316 m_types, m_foreignTypes, relatedName, namespaces)) {
317
318 if (!related.javaScript.isEmpty())
319 processedRelatedJavaScriptNames.insert(related.javaScript.qualifiedClassName());
320
321 if (!related.native.isEmpty())
322 processedRelatedNativeNames.insert(related.native.qualifiedClassName());
323
324 return true;
325 } else {
326 return false;
327 }
328 };
329
330 const auto addRelatedType = [&](const MetaType &type) {
331 const QAnyStringView qualifiedName = type.qualifiedClassName();
332 if (type.inputFile().isEmpty())
333 processedRelatedJavaScriptNames.insert(qualifiedName);
334 else
335 processedRelatedNativeNames.insert(qualifiedName);
336 };
337
338 // First mark all classes registered from this module as already processed.
339 for (const MetaType &type : std::as_const(m_types)) {
340 addRelatedType(type);
341 for (const ClassInfo &obj : type.classInfos()) {
342 if (obj.name == S_FOREIGN) {
343 const QAnyStringView foreign = obj.value;
344 if (!addRelatedName(foreign, namespaces(type)))
345 unresolvedForeignNames.insert(foreign);
346 break;
347 }
348 }
349 }
350
351 // Then mark all classes registered from other modules as already processed.
352 // We don't want to generate them again for this module.
353 for (const MetaType &foreignType : std::as_const(m_foreignTypes)) {
354 bool seenQmlPrefix = false;
355 for (const ClassInfo &obj : foreignType.classInfos()) {
356 const QAnyStringView name = obj.name;
357 if (!seenQmlPrefix && startsWith(name, "QML."_L1)) {
358 addRelatedType(foreignType);
359 seenQmlPrefix = true;
360 }
361 if (name == S_FOREIGN
362 || name == S_EXTENDED
363 || name == S_ATTACHED
364 || name == S_SEQUENCE) {
365 ResolvedTypeAlias foreign(obj.value, m_usingDeclarations);
366 if (!addRelatedName(foreign.type, namespaces(foreignType)))
367 unresolvedForeignNames.insert(foreign.type);
368 break;
369 }
370 }
371 }
372
373 const auto addReference = [&](const MetaType &type, QSet<QAnyStringView> *processedRelatedNames,
374 FoundType::Origin origin) {
375 if (type.isEmpty())
376 return;
377 QAnyStringView qualifiedName = type.qualifiedClassName();
378 m_referencedTypes.append(qualifiedName);
379 const qsizetype size = processedRelatedNames->size();
380 processedRelatedNames->insert(qualifiedName);
381
382 if (processedRelatedNames->size() == size)
383 return;
384
385 typeQueue.enqueue(type);
386
387 if (origin == FoundType::OwnTypes)
388 return;
389
390 // Add to own types since we need it for our registrations.
391 const auto insert = std::lower_bound(
392 m_types.constBegin(), m_types.constEnd(), type,
394 m_types.insert(insert, type);
395
396 // Also add its include. We don't want to rely on transitive inclues.
397 const QString inputFile = type.inputFile();
398 if (!inputFile.isEmpty())
399 m_includes.append(inputFile);
400
401 // Remove from the foreign types to avoid the ODR warning.
402 const auto remove = std::equal_range(
403 m_foreignTypes.constBegin(), m_foreignTypes.constEnd(), type,
405 for (auto it = remove.first; it != remove.second; ++it) {
406 if (*it == type) {
407 m_foreignTypes.erase(it);
408 break;
409 }
410 }
411 };
412
413 const auto addInterface
414 = [&](QAnyStringView typeName, const QList<QAnyStringView> &namespaces) {
416 m_types, m_foreignTypes, typeName, namespaces)) {
417 if (!other.native.isEmpty()) {
418 addReference(other.native, &processedRelatedNativeNames, other.nativeOrigin);
419 return true;
420 }
421 } else {
422 // Do not warn about unresolved interfaces.
423 // They don't have to have Q_OBJECT or Q_GADGET.
424 unresolvedForeignNames.insert(typeName);
425 }
426
427 processedRelatedNativeNames.insert(typeName);
428 return false;
429 };
430
431 const auto addType = [&](const MetaType &context, QAnyStringView typeName,
432 const QList<QAnyStringView> &namespaces, QAnyStringView relation) {
434 m_types, m_foreignTypes, typeName, namespaces)) {
435 addReference(other.native, &processedRelatedNativeNames, other.nativeOrigin);
436 addReference(other.javaScript, &processedRelatedJavaScriptNames, other.javaScriptOrigin);
437 return true;
438 }
439
440 // If it's an enum, add the surrounding type.
441 const QLatin1StringView separator("::");
442 if (const qsizetype index = lastIndexOf(typeName, separator); index > 0) {
444 m_types, m_foreignTypes, typeName.left(index), namespaces)) {
445
446 const QAnyStringView enumName = typeName.mid(index + separator.length());
447
448 for (const Enum &enumerator : other.native.enums()) {
449 if (enumerator.name != enumName && enumerator.alias != enumName)
450 continue;
451
452 addReference(other.native, &processedRelatedNativeNames, other.nativeOrigin);
453 addReference(
454 other.javaScript, &processedRelatedJavaScriptNames,
455 other.javaScriptOrigin);
456 return true;
457 }
458 }
459 }
460
461 // If it's an enum of the context type itself, we don't have to do anything.
462 for (const Enum &enumerator : context.enums()) {
463 if (enumerator.name == typeName || enumerator.alias == typeName)
464 return true;
465 }
466
467 // If we've detected this type as unresolved foreign and it actually belongs to this module,
468 // we'll get to it again when we process it as foreign type. In that case we'll look at the
469 // special cases for sequences and extensions.
470 if (!unresolvedForeignNames.contains(typeName) && !isPrimitive(typeName))
471 warning(context) << typeName << "is used as" << relation << "type but cannot be found.";
472
473 processedRelatedNativeNames.insert(typeName);
474 processedRelatedJavaScriptNames.insert(typeName);
475 return false;
476 };
477
478 const auto doAddReferences = [&](QAnyStringView typeName,
479 const QList<QAnyStringView> &namespaces) {
481 m_types, m_foreignTypes, typeName, namespaces)) {
482 addReference(
483 other.native, &processedRelatedNativeNames, other.nativeOrigin);
484 addReference(
485 other.javaScript, &processedRelatedJavaScriptNames, other.javaScriptOrigin);
486 return true;
487 }
488
489 return false;
490 };
491
492 const auto addSupers = [&](const MetaType &context, const QList<QAnyStringView> &namespaces) {
493 for (const Interface &iface : context.ifaces())
494 addInterface(interfaceName(iface), namespaces);
495
496 // We don't warn about missing bases for value types. They don't have to be registered.
497 bool warnAboutSupers = context.kind() != MetaType::Kind::Gadget;
498
499 QList<QAnyStringView> missingSupers;
500
501 for (const BaseType &superObject : context.superClasses()) {
502 if (superObject.access != Access::Public)
503 continue;
504
505 QAnyStringView typeName = superObject.name;
506 if (doAddReferences(typeName, namespaces))
507 warnAboutSupers = false;
508 else
509 missingSupers.append(typeName);
510 }
511
512 for (QAnyStringView typeName : std::as_const(missingSupers)) {
513 // If we've found one valid base type, don't complain about the others.
514 if (warnAboutSupers
515 && !unresolvedForeignNames.contains(typeName)
516 && !isPrimitive(typeName)) {
517 warning(context) << typeName << "is used as base type but cannot be found.";
518 }
519
520 processedRelatedNativeNames.insert(typeName);
521 processedRelatedJavaScriptNames.insert(typeName);
522 }
523 };
524
525 const auto addProperties = [&](const MetaType &context,
526 const QList<QAnyStringView> &namespaces) {
527 for (const Property &property : context.properties()) {
528 ResolvedTypeAlias resolved(property.type, m_usingDeclarations);
529 if (!resolved.type.isEmpty())
530 addType(context, resolved.type, namespaces, "property");
531 }
532 };
533
534 const auto addMethods = [&](const MetaType &context,
535 const QList<QAnyStringView> &namespaces) {
536 for (const Method::Container &methods
537 : {context.methods(), context.constructors(), context.sigs() }) {
538 for (const Method &methodObject : methods) {
539 for (const Argument &argument : std::as_const(methodObject.arguments)) {
540 ResolvedTypeAlias resolved(argument.type, m_usingDeclarations);
541 if (!resolved.type.isEmpty())
542 addType(context, resolved.type, namespaces, "argument");
543 }
544
545 ResolvedTypeAlias resolved(methodObject.returnType, m_usingDeclarations);
546 if (!resolved.type.isEmpty())
547 addType(context, resolved.type, namespaces, "return");
548 }
549 }
550 };
551
552 const auto addEnums = [&](const MetaType &context,
553 const QList<QAnyStringView> &namespaces) {
554 for (const Enum &enumerator : context.enums()) {
555 ResolvedTypeAlias resolved(enumerator.type, m_usingDeclarations);
556 if (!resolved.type.isEmpty())
557 addType(context, resolved.type, namespaces, "enum");
558 }
559 };
560
561 const auto addRelation = [&](const MetaType &classDef, const ClassInfo &obj,
562 const QList<QAnyStringView> &namespaces) {
563 const QAnyStringView objNameValue = obj.name;
564 if (objNameValue == S_ATTACHED) {
565 addType(classDef, obj.value, namespaces, "attached");
566 return true;
567 } else if (objNameValue == S_SEQUENCE) {
568 ResolvedTypeAlias value(obj.value, m_usingDeclarations);
569 addType(classDef, value.type, namespaces, "sequence value");
570 return true;
571 } else if (objNameValue == S_EXTENDED) {
572 const QAnyStringView value = obj.value;
573 addType(classDef, value, namespaces, "extension");
574 return true;
575 }
576 return false;
577 };
578
579 // Then recursively iterate the super types and attached types, marking the
580 // ones we are interested in as related.
581 while (!typeQueue.isEmpty()) {
582 QAnyStringView unresolvedForeign;
583
584 const MetaType classDef = typeQueue.dequeue();
585 const QList<QAnyStringView> namespaces = MetaTypesJsonProcessor::namespaces(classDef);
586
587 for (const ClassInfo &obj : classDef.classInfos()) {
588 if (addRelation(classDef, obj, namespaces))
589 continue;
590 if (obj.name != S_FOREIGN)
591 continue;
592
593 const QAnyStringView foreignClassName = obj.value;
594
595 // A type declared as QML_FOREIGN will usually be a foreign type, but it can
596 // actually be an additional registration of a local type, too.
598 m_foreignTypes, {}, foreignClassName, namespaces)) {
599 const MetaType other = found.select(classDef, "Foreign");
600 const QList<QAnyStringView> otherNamespaces
602 addSupers(other, otherNamespaces);
603 addProperties(other, otherNamespaces);
604 addMethods(other, otherNamespaces);
605 addEnums(other, otherNamespaces);
606
607 for (const ClassInfo &obj : other.classInfos()) {
608 if (addRelation(classDef, obj, otherNamespaces))
609 break;
610 // No, you cannot chain S_FOREIGN declarations. Sorry.
611 }
613 m_types, {}, foreignClassName, namespaces)) {
614 unresolvedForeign = foreignClassName;
615 }
616 }
617
618 if (!unresolvedForeign.isEmpty() && !isPrimitive(unresolvedForeign)) {
619 warning(classDef)
620 << unresolvedForeign
621 << "is declared as foreign type, but cannot be found.";
622 }
623
624 addSupers(classDef, namespaces);
625 addProperties(classDef, namespaces);
626 addMethods(classDef, namespaces);
627 addEnums(classDef, namespaces);
628 }
629}
630
631void MetaTypesJsonProcessor::sortTypes(QVector<MetaType> &types)
632{
633 std::sort(types.begin(), types.end(), qualifiedClassNameLessThan);
634}
635
636QString MetaTypesJsonProcessor::resolvedInclude(QAnyStringView include)
637{
638 if (!m_privateIncludes)
639 return include.toString();
640
641 if (endsWith(include, "_p.h"_L1))
642 return QLatin1String("private/") + include.toString();
643
644 if (startsWith(include, "qplatform"_L1) || startsWith(include, "qwindowsystem"_L1))
645 return QLatin1String("qpa/") + include.toString();
646
647 return include.toString();
648}
649
651{
652 const QString include = resolvedInclude(toStringView(types, S_INPUT_FILE));
653 const QCborArray classes = types[S_CLASSES].toArray();
654 for (const QCborValue &cls : classes) {
655 const MetaType classDef(cls.toMap(), include);
656
657 const PreProcessResult preprocessed = preProcess(classDef, PopulateMode::Yes);
658 switch (preprocessed.mode) {
659 case NamespaceRegistration:
660 case GadgetRegistration:
661 case ObjectRegistration: {
662 if (!endsWith(include, QLatin1String(".h"))
663 && !endsWith(include, QLatin1String(".hpp"))
664 && !endsWith(include, QLatin1String(".hxx"))
665 && !endsWith(include, QLatin1String(".hh"))
666 && !endsWith(include, QLatin1String(".py"))
667 && contains(include, QLatin1Char('.'))) {
668 warning(include)
669 << "Class" << classDef.qualifiedClassName()
670 << "is declared in" << include << "which appears not to be a header."
671 << "The compilation of its registration to QML may fail.";
672 }
673 m_includes.append(include);
674 m_types.emplaceBack(classDef);
675 break;
676 }
677 case NoRegistration:
678 m_foreignTypes.emplaceBack(classDef);
679 break;
680 }
681
682 if (!preprocessed.foreignPrimitive.isEmpty()) {
683 m_primitiveTypes.emplaceBack(preprocessed.foreignPrimitive);
684 m_primitiveTypes.append(preprocessed.primitiveAliases);
685 }
686
687 if (preprocessed.usingDeclaration.isValid())
688 m_usingDeclarations.append(preprocessed.usingDeclaration);
689 }
690}
691
693{
694 const QString include = resolvedInclude(toStringView(types, S_INPUT_FILE));
695 const QCborArray classes = types[S_CLASSES].toArray();
696 for (const QCborValue &cls : classes) {
697 const MetaType classDef(cls.toMap(), include);
698 PreProcessResult preprocessed = preProcess(classDef, PopulateMode::No);
699
700 m_foreignTypes.emplaceBack(classDef);
701 if (!preprocessed.foreignPrimitive.isEmpty()) {
702 m_primitiveTypes.emplaceBack(preprocessed.foreignPrimitive);
703 m_primitiveTypes.append(preprocessed.primitiveAliases);
704 }
705
706 if (preprocessed.usingDeclaration.isValid())
707 m_usingDeclarations.append(preprocessed.usingDeclaration);
708 }
709}
710
712{
713 const auto it = cbor.find(S_REVISION);
714 return it == cbor.end()
715 ? QTypeRevision()
717}
718
719static Access getAccess(const QCborMap &cbor)
720{
722 if (access == S_PUBLIC)
723 return Access::Public;
724 if (access == S_PROTECTED)
725 return Access::Protected;
726 return Access::Private;
727}
728
730 : name(toStringView(cbor, S_NAME))
731 , access(getAccess(cbor))
732{
733}
734
736 : name(toStringView(cbor, S_NAME))
737 , value(toStringView(cbor, S_VALUE))
738{
739}
740
742{
743 if (cbor.isArray()) {
744 QCborArray needlessWrapping = cbor.toArray();
745 className = needlessWrapping.size() > 0
746 ? toStringView(needlessWrapping[0].toMap(), S_CLASS_NAME)
747 : QAnyStringView();
748 } else {
750 }
751}
752
754 : name(toStringView(cbor, S_NAME))
755 , type(toStringView(cbor, S_TYPE))
756 , member(toStringView(cbor, S_MEMBER))
757 , read(toStringView(cbor, S_READ))
758 , write(toStringView(cbor, S_WRITE))
759 , reset(toStringView(cbor, S_RESET))
760 , notify(toStringView(cbor, S_NOTIFY))
761 , bindable(toStringView(cbor, S_BINDABLE))
762 , privateClass(toStringView(cbor, S_PRIVATE_CLASS))
763 , index(cbor[S_INDEX].toInteger(-1))
764 , revision(getRevision(cbor))
765 , isFinal(cbor[S_FINAL].toBool())
766 , isConstant(cbor[S_CONSTANT].toBool())
767 , isRequired(cbor[S_REQUIRED].toBool())
768{
769}
770
772 : name(toStringView(cbor, S_NAME))
773 , type(toStringView(cbor, S_TYPE))
774{
775}
776
777Method::Method(const QCborMap &cbor, bool isConstructor)
778 : name(toStringView(cbor, S_NAME))
779 , returnType(toStringView(cbor, S_RETURN_TYPE))
780 , revision(getRevision(cbor))
781 , access(getAccess(cbor))
782 , isCloned(cbor[S_IS_CLONED].toBool())
783 , isJavaScriptFunction(cbor[S_IS_JAVASCRIPT_FUNCTION].toBool())
784 , isConstructor(isConstructor || cbor[S_IS_CONSTRUCTOR].toBool())
785{
786 const QCborArray args = cbor[S_ARGUMENTS].toArray();
787 for (const QCborValue &argument : args)
788 arguments.emplace_back(argument.toMap());
789
790 if (arguments.size() == 1) {
791 const QAnyStringView type = arguments[0].type;
792 if (type == "QQmlV4FunctionPtr"_L1 || type == "QQmlV4Function*"_L1)
794 }
795}
796
798 : name(toStringView(cbor, S_NAME))
799 , alias(toStringView(cbor, S_ALIAS))
800 , type(toStringView(cbor, S_TYPE))
801 , isFlag(cbor[S_IS_FLAG].toBool())
802 , isClass(cbor[S_IS_CLASS].toBool())
803{
804 const QCborArray vals = cbor[S_VALUES].toArray();
805 for (const QCborValue &value : vals)
806 values.emplace_back(toStringView(value));
807}
808
810 : cbor(cbor)
811 , inputFile(inputFile)
812{
815
816 const QCborArray cborSuperClasses = cbor[S_SUPER_CLASSES].toArray();
817 for (const QCborValue &superClass : cborSuperClasses)
818 superClasses.emplace_back(superClass.toMap());
819
820 const QCborArray cborClassInfos = cbor[S_CLASS_INFOS].toArray();
821 for (const QCborValue &classInfo : cborClassInfos)
822 classInfos.emplace_back(classInfo.toMap());
823
824 const QCborArray cborIfaces = cbor[S_INTERFACES].toArray();
825 for (const QCborValue &iface : cborIfaces)
826 ifaces.emplace_back(iface);
827
828 const QCborArray cborProperties = cbor[S_PROPERTIES].toArray();
829 for (const QCborValue &property : cborProperties)
830 properties.emplace_back(property.toMap());
831
832 for (const QCborArray &cborMethods : { cbor[S_SLOTS].toArray(), cbor[S_METHODS].toArray() }) {
833 for (const QCborValue &method : cborMethods)
834 methods.emplace_back(method.toMap(), false);
835 }
836
837 const QCborArray cborSigs = cbor[S_SIGNALS].toArray();
838 for (const QCborValue &sig : cborSigs)
839 sigs.emplace_back(sig.toMap(), false);
840
841 const QCborArray cborConstructors = cbor[S_CONSTRUCTORS].toArray();
842 for (const QCborValue &constructor : cborConstructors)
843 constructors.emplace_back(constructor.toMap(), true);
844
845 const QCborArray cborEnums = cbor[S_ENUMS].toArray();
846 for (const QCborValue &enumerator : cborEnums)
847 enums.emplace_back(enumerator.toMap());
848
849 if (cbor[S_GADGET].toBool())
851 else if (cbor[S_OBJECT].toBool())
853 else if (cbor[S_NAMESPACE].toBool())
855}
856
857MetaType::MetaType(const QCborMap &cbor, const QString &inputFile)
858 : d(s_pool.emplace_back(std::make_unique<MetaTypePrivate>(cbor, inputFile)).get())
859{}
860
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:890
iterator end()
Definition qlist.h:627
reference emplaceBack(Args &&... args)
Definition qlist.h:883
iterator begin()
Definition qlist.h:626
void append(parameter_type t)
Definition qlist.h:459
const_iterator constEnd() const noexcept
Definition qlist.h:634
\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_USING
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:667
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
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:100
const char className[16]
[1]
Definition qwizard.cpp:99
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