diff options
Diffstat (limited to 'src/tools/moc/moc.cpp')
| -rw-r--r-- | src/tools/moc/moc.cpp | 89 |
1 files changed, 84 insertions, 5 deletions
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 64af8c10fc1..7f05f34edb6 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -17,6 +17,10 @@ #include <private/qmetaobject_moc_p.h> #include <private/qduplicatetracker_p.h> +// This is a bootstrapped tool, so we can't rely on QCryptographicHash for the +// faster SHA1 implementations from OpenSSL. +#include "../../3rdparty/sha1/sha1.cpp" + QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; @@ -1191,6 +1195,24 @@ static QByteArrayList requiredQtContainers(const QList<ClassDef> &classes) return required; } +QByteArray classDefJsonObjectHash(const QJsonObject &object) +{ + const QByteArray json = QJsonDocument(object).toJson(QJsonValue::JsonFormat::Compact); + QByteArray hash(20, 0); // SHA1 produces 160 bits of data + + { + Sha1State state; + sha1InitState(&state); + sha1Update(&state, reinterpret_cast<const uchar *>(json.constData()), json.size()); + sha1FinalizeState(&state); + sha1ToHash(&state, reinterpret_cast<uchar *>(hash.data())); + } + + static const char revisionPrefix[] = "0$"; + const QByteArray hashB64 = hash.toBase64(QByteArray::OmitTrailingEquals); + return revisionPrefix + hashB64; +} + void Moc::generate(FILE *out, FILE *jsonOutput) { QByteArrayView fn = strippedFileName(); @@ -1247,14 +1269,40 @@ void Moc::generate(FILE *out, FILE *jsonOutput) "#endif\n\n"); #endif + // filter out undeclared enumerators and sets + for (ClassDef &cdef : classList) { + QList<EnumDef> enumList; + for (EnumDef def : std::as_const(cdef.enumList)) { + if (cdef.enumDeclarations.contains(def.name)) { + enumList += def; + } + def.enumName = def.name; + QByteArray alias = cdef.flagAliases.value(def.name); + if (cdef.enumDeclarations.contains(alias)) { + def.name = alias; + def.flags |= cdef.enumDeclarations[alias]; + enumList += def; + } + } + cdef.enumList = enumList; + } + fprintf(out, "QT_WARNING_PUSH\n"); fprintf(out, "QT_WARNING_DISABLE_DEPRECATED\n"); fprintf(out, "QT_WARNING_DISABLE_GCC(\"-Wuseless-cast\")\n"); + QHash<QByteArray, QJsonObject> classDefJsonObjects; + QHash<QByteArray, QByteArray> metaObjectHashes; + for (const ClassDef &def : std::as_const(classList)) { + const QJsonObject jsonObject = def.toJson(); + classDefJsonObjects.insert(def.qualified, jsonObject); + metaObjectHashes.insert(def.qualified, classDefJsonObjectHash(jsonObject)); + } + fputs("", out); - for (ClassDef &def : classList) { - Generator generator(this, &def, metaTypes, knownQObjectClasses, knownGadgets, out, - requireCompleteTypes); + for (const ClassDef &def : std::as_const(classList)) { + Generator generator(this, &def, metaTypes, knownQObjectClasses, knownGadgets, + metaObjectHashes, out, requireCompleteTypes); generator.generateCode(); // generator.generateCode() should have already registered all strings @@ -1273,13 +1321,20 @@ void Moc::generate(FILE *out, FILE *jsonOutput) mocData["inputFile"_L1] = QLatin1StringView(fn.constData()); QJsonArray classesJsonFormatted; + QJsonObject hashesJsonObject; - for (const ClassDef &cdef: std::as_const(classList)) - classesJsonFormatted.append(cdef.toJson()); + for (const ClassDef &cdef : std::as_const(classList)) { + classesJsonFormatted.append(classDefJsonObjects[cdef.qualified]); + hashesJsonObject.insert(QString::fromLatin1(cdef.qualified), + QString::fromLatin1(metaObjectHashes[cdef.qualified])); + } if (!classesJsonFormatted.isEmpty()) mocData["classes"_L1] = classesJsonFormatted; + if (!hashesJsonObject.isEmpty()) + mocData["hashes"_L1] = hashesJsonObject; + QJsonDocument jsonDoc(mocData); fputs(jsonDoc.toJson().constData(), jsonOutput); } @@ -1434,6 +1489,9 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) next(IDENTIFIER); propDef.name = lexem(); continue; + } else if (l[0] == 'O' && l == "OVERRIDE") { + propDef.override = true; + continue; } else if (l[0] == 'R' && l == "REQUIRED") { propDef.required = true; continue; @@ -1441,6 +1499,9 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) prev(); propDef.revision = parseRevision().toEncodedVersion<int>(); continue; + } else if (l[0] == 'V' && l == "VIRTUAL") { + propDef.virtual_ = true; + continue; } QByteArray v, v2; @@ -1545,6 +1606,24 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) propDef.write = ""; warning(msg.constData()); } + if (propDef.override && propDef.virtual_) { + const QByteArray msg = "Issue with property declaration " + propDef.name + + ": VIRTUAL is redundant when overriding a property. The OVERRIDE " + "must only be used when actually overriding an existing property; using it on a " + "new property is an error."; + error(msg.constData()); + } + if (propDef.override && propDef.final) { + const QByteArray msg = "Issue with property declaration " + propDef.name + + ": OVERRIDE is redundant when property is marked FINAL"; + error(msg.constData()); + } + if (propDef.virtual_ && propDef.final) { + const QByteArray msg = "Issue with property declaration " + propDef.name + + ": The VIRTUAL cannot be combined with FINAL, as these attributes are mutually " + "exclusive"; + error(msg.constData()); + } } void Moc::parseProperty(ClassDef *def, Moc::PropertyMode mode) |
