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>
29std::vector<std::unique_ptr<MetaTypePrivate>>
s_pool;
34 if (jsonValue.isArray())
36 if (jsonValue.isObject())
47 if (qualified != unqualified) {
67 metaObjects =
fromJson(
f.readAll(), &parseError);
70 <<
"Failed to parse JSON:" << parseError.
error
86 }
else if (metaObjects.
isMap()) {
89 error(
source) <<
"JSON is not an object or an array";
101 error(
types) <<
"Cannot open foreign types file";
109 <<
"Failed to parse JSON:" << parseError.
error
114 const QCborArray foreignObjectsArray = foreignMetaObjects.toArray();
138template<
typename String>
153 sortTypes(m_foreignTypes);
164 for (
const auto &
obj: m_types) {
166 const QString qualifiedClassName =
obj.qualifiedClassName().toString();
171 bool isSingleton =
false;
172 bool isExplicitlyUncreatable =
false;
173 bool isNamespace =
obj.kind() == MetaType::Kind::Namespace;
179 qmlElements.append(u
"QML_NAMED_ELEMENT("_s +
className + u
")"_s);
181 qmlElements.append(u
"QML_ANONYMOUS"_s);
183 qmlElements.append(u
"QML_NAMED_ELEMENT("_s +
value.toString() + u
")");
186 isExplicitlyUncreatable =
true;
188 qmlUncreatable = u
"QML_UNCREATABLE(\""_s +
value.toString() + u
"\")";
190 qmlAttached = u
"QML_ATTACHED("_s +
value.toString() + u
")";
195 if (qmlElements.isEmpty())
199 registrationHelper += u
"\nnamespace "_s + foreignClassName + u
"{\n Q_NAMESPACE\n"_s;
200 registrationHelper += spaces + u
"QML_FOREIGN_NAMESPACE(" + qualifiedClassName + u
")\n"_s;
202 registrationHelper += u
"\nstruct "_s + foreignClassName + u
"{\n Q_GADGET\n"_s;
203 registrationHelper += spaces + u
"QML_FOREIGN(" + qualifiedClassName + u
")\n"_s;
205 registrationHelper += spaces + qmlElements.join(u
"\n"_s) + u
"\n"_s;
207 registrationHelper += spaces + u
"QML_SINGLETON\n"_s;
208 if (isExplicitlyUncreatable) {
209 if (qmlUncreatable.isEmpty())
210 registrationHelper += spaces + uR
"(QML_UNCREATABLE(""))" + u"n";
212 registrationHelper += spaces + qmlUncreatable + u
"\n";
214 if (!qmlAttached.isEmpty())
215 registrationHelper += spaces + qmlAttached + u
"\n";
216 registrationHelper += u
"}";
218 registrationHelper += u
";";
219 registrationHelper += u
"\n";
221 return registrationHelper;
224MetaTypesJsonProcessor::PreProcessResult MetaTypesJsonProcessor::preProcess(
225 const MetaType &classDef, PopulateMode populateMode)
231 QList<QAnyStringView> primitiveAliases;
234 RegistrationMode
mode = NoRegistration;
235 bool isSelfExtendingValueType =
false;
236 bool hasJavaScriptExtension =
false;
237 bool isRootObject =
false;
238 bool isSequence =
false;
240 for (
const ClassInfo &classInfo : classDef.classInfos()) {
242 usingDeclaration.
alias = classInfo.value;
244 primitiveAliases.append(classInfo.value);
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);
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;
260 case MetaType::Kind::Gadget:
261 mode = GadgetRegistration;
263 case MetaType::Kind::Namespace:
264 mode = NamespaceRegistration;
268 <<
"Not registering a classInfo which is neither an object,"
269 <<
"nor a gadget, nor a namespace:"
270 << classInfo.name.toString();
276 return PreProcessResult {
277 std::move(primitiveAliases),
279 (!isRootObject && (isSequence || isSelfExtendingValueType || hasJavaScriptExtension))
280 ? usingDeclaration.
alias
290 return string.visit([
seed](
auto view) {
302 return a.qualifiedClassName() <
b.qualifiedClassName();
305void MetaTypesJsonProcessor::addRelatedTypes()
307 QSet<QAnyStringView> processedRelatedNativeNames;
308 QSet<QAnyStringView> processedRelatedJavaScriptNames;
309 QSet<QAnyStringView> unresolvedForeignNames;
310 QQueue<MetaType> typeQueue;
311 typeQueue.append(m_types);
313 const auto addRelatedName
316 m_types, m_foreignTypes, relatedName,
namespaces)) {
318 if (!related.javaScript.isEmpty())
319 processedRelatedJavaScriptNames.insert(related.javaScript.qualifiedClassName());
321 if (!related.native.isEmpty())
322 processedRelatedNativeNames.insert(related.native.qualifiedClassName());
332 if (
type.inputFile().isEmpty())
333 processedRelatedJavaScriptNames.insert(qualifiedName);
335 processedRelatedNativeNames.insert(qualifiedName);
340 addRelatedType(
type);
345 unresolvedForeignNames.insert(foreign);
353 for (
const MetaType &foreignType :
std::as_const(m_foreignTypes)) {
354 bool seenQmlPrefix =
false;
358 addRelatedType(foreignType);
359 seenQmlPrefix =
true;
366 if (!addRelatedName(foreign.type,
namespaces(foreignType)))
367 unresolvedForeignNames.insert(foreign.type);
373 const auto addReference = [&](
const MetaType &
type, QSet<QAnyStringView> *processedRelatedNames,
378 m_referencedTypes.
append(qualifiedName);
380 processedRelatedNames->insert(qualifiedName);
382 if (processedRelatedNames->size() ==
size)
385 typeQueue.enqueue(
type);
391 const auto insert = std::lower_bound(
392 m_types.constBegin(), m_types.constEnd(),
type,
399 m_includes.
append(inputFile);
402 const auto remove = std::equal_range(
403 m_foreignTypes.constBegin(), m_foreignTypes.constEnd(),
type,
407 m_foreignTypes.erase(
it);
413 const auto addInterface
417 if (!
other.native.isEmpty()) {
418 addReference(
other.native, &processedRelatedNativeNames,
other.nativeOrigin);
424 unresolvedForeignNames.insert(
typeName);
427 processedRelatedNativeNames.insert(
typeName);
435 addReference(
other.native, &processedRelatedNativeNames,
other.nativeOrigin);
436 addReference(
other.javaScript, &processedRelatedJavaScriptNames,
other.javaScriptOrigin);
448 for (
const Enum &enumerator :
other.native.enums()) {
449 if (enumerator.name != enumName && enumerator.alias != enumName)
452 addReference(
other.native, &processedRelatedNativeNames,
other.nativeOrigin);
454 other.javaScript, &processedRelatedJavaScriptNames,
455 other.javaScriptOrigin);
471 warning(context) <<
typeName <<
"is used as" << relation <<
"type but cannot be found.";
473 processedRelatedNativeNames.insert(
typeName);
474 processedRelatedJavaScriptNames.insert(
typeName);
483 other.native, &processedRelatedNativeNames,
other.nativeOrigin);
485 other.javaScript, &processedRelatedJavaScriptNames,
other.javaScriptOrigin);
497 bool warnAboutSupers =
context.kind() != MetaType::Kind::Gadget;
499 QList<QAnyStringView> missingSupers;
507 warnAboutSupers =
false;
515 && !unresolvedForeignNames.contains(
typeName)
517 warning(context) <<
typeName <<
"is used as base type but cannot be found.";
520 processedRelatedNativeNames.insert(
typeName);
521 processedRelatedJavaScriptNames.insert(
typeName);
529 if (!resolved.type.isEmpty())
530 addType(context, resolved.type,
namespaces,
"property");
541 if (!resolved.type.isEmpty())
542 addType(context, resolved.type,
namespaces,
"argument");
546 if (!resolved.type.isEmpty())
547 addType(context, resolved.type,
namespaces,
"return");
556 if (!resolved.type.isEmpty())
557 addType(context, resolved.type,
namespaces,
"enum");
581 while (!typeQueue.isEmpty()) {
584 const MetaType classDef = typeQueue.dequeue();
598 m_foreignTypes, {}, foreignClassName,
namespaces)) {
600 const QList<QAnyStringView> otherNamespaces
602 addSupers(
other, otherNamespaces);
603 addProperties(
other, otherNamespaces);
604 addMethods(
other, otherNamespaces);
605 addEnums(
other, otherNamespaces);
608 if (addRelation(classDef,
obj, otherNamespaces))
614 unresolvedForeign = foreignClassName;
618 if (!unresolvedForeign.isEmpty() && !isPrimitive(unresolvedForeign)) {
621 <<
"is declared as foreign type, but cannot be found.";
631void MetaTypesJsonProcessor::sortTypes(QVector<MetaType> &
types)
638 if (!m_privateIncludes)
655 const MetaType classDef(cls.toMap(), include);
657 const PreProcessResult preprocessed = preProcess(classDef, PopulateMode::Yes);
658 switch (preprocessed.mode) {
659 case NamespaceRegistration:
660 case GadgetRegistration:
661 case ObjectRegistration: {
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.";
673 m_includes.
append(include);
674 m_types.emplaceBack(classDef);
678 m_foreignTypes.emplaceBack(classDef);
682 if (!preprocessed.foreignPrimitive.isEmpty()) {
683 m_primitiveTypes.
emplaceBack(preprocessed.foreignPrimitive);
684 m_primitiveTypes.
append(preprocessed.primitiveAliases);
687 if (preprocessed.usingDeclaration.isValid())
688 m_usingDeclarations.
append(preprocessed.usingDeclaration);
697 const MetaType classDef(cls.toMap(), include);
698 PreProcessResult preprocessed = preProcess(classDef, PopulateMode::No);
700 m_foreignTypes.emplaceBack(classDef);
701 if (!preprocessed.foreignPrimitive.isEmpty()) {
702 m_primitiveTypes.
emplaceBack(preprocessed.foreignPrimitive);
703 m_primitiveTypes.
append(preprocessed.primitiveAliases);
706 if (preprocessed.usingDeclaration.isValid())
707 m_usingDeclarations.
append(preprocessed.usingDeclaration);
714 return it == cbor.
end()
792 if (
type ==
"QQmlV4FunctionPtr"_L1 ||
type ==
"QQmlV4Function*"_L1)
811 , inputFile(inputFile)
817 for (
const QCborValue &superClass : cborSuperClasses)
821 for (
const QCborValue &classInfo : cborClassInfos)
839 sigs.emplace_back(sig.toMap(),
false);
842 for (
const QCborValue &constructor : cborConstructors)
846 for (
const QCborValue &enumerator : cborEnums)
847 enums.emplace_back(enumerator.toMap());
static JNINativeMethod methods[]
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.
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
iterator end()
Returns a map iterator representing an element just past the last element in the map.
iterator find(qint64 key)
\inmodule QtCore\reentrant
QCborArray toArray() const
bool isArray() const
Returns true if this QCborValue is of the array type.
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.
\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)
reference emplaceBack(Args &&... args)
void append(parameter_type t)
const_iterator constEnd() const noexcept
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
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
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
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]
static bool contains(const QJsonArray &haystack, unsigned needle)
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLenum GLenum * types
GLsizei GLsizei GLchar * source
QAnyStringView interfaceName(const Interface &iface)
QDebug warning(QAnyStringView fileName, int lineNumber)
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
static void split(QT_FT_Vector *b)
QLatin1StringView QLatin1String
ReturnedValue read(const char *data)
const char className[16]
[1]
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]
std::vector< Method > Container
Argument::Container arguments
bool isJavaScriptFunction
\inmodule QtCore\reentrant
QString errorString() const
\variable QJsonParseError::error
\inmodule QtCore \reentrant
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)