aboutsummaryrefslogtreecommitdiffstats
path: root/tools/qmlplugindump/main.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2023-06-08 14:55:35 +0200
committerUlf Hermann <ulf.hermann@qt.io>2023-06-30 10:47:17 +0200
commitd158c61cef35c35d8893db9e7db266782ece264d (patch)
treed32485daa976d250c58ef47dfad0670b1258bd7f /tools/qmlplugindump/main.cpp
parent85dcfcae790ea9cf2f59e5eb3913a10d29728038 (diff)
Improve string handling in qmltyperegistrar
Use QLatin1StringView for all the constants and define them in one place. Parse the Json into Cbor in order to be able to retrieve UTF-8 data from it. Avoid conversion to QString wherever possible. We could further improve QQmlJSStreamWriter to avoid temporary allocations. Add some TODOs to this effect. This change shows some API gaps in our various string view classes. To work around them, we need our own QAnyStringViewUtils. Change-Id: I41054a5057102d29e1db9e66a5998569d97382f9 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Diffstat (limited to 'tools/qmlplugindump/main.cpp')
-rw-r--r--tools/qmlplugindump/main.cpp205
1 files changed, 108 insertions, 97 deletions
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index eeb8c6cde3..42b9544b04 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -68,13 +68,6 @@ QString inObjectInstantiation;
}
-static QString enquote(const QString &string)
-{
- QString s = string;
- return QString("\"%1\"").arg(s.replace(QLatin1Char('\\'), QLatin1String("\\\\"))
- .replace(QLatin1Char('"'),QLatin1String("\\\"")));
-}
-
struct QmlVersionInfo
{
QString pluginImportUri;
@@ -348,7 +341,7 @@ public:
relocatableModuleUri = uri;
}
- QString getExportString(const QQmlType &type, const QmlVersionInfo &versionInfo)
+ QByteArray getExportString(const QQmlType &type, const QmlVersionInfo &versionInfo)
{
const QString module = type.module().isEmpty() ? versionInfo.pluginImportUri
: type.module();
@@ -358,12 +351,14 @@ public:
type.version().hasMinorVersion() ? type.version().minorVersion()
: versionInfo.version.minorVersion());
- const QString versionedElement = type.elementName()
- + QString::fromLatin1(" %1.%2").arg(version.majorVersion()).arg(version.minorVersion());
+ const QByteArray versionedElement
+ = (type.elementName() + QString::fromLatin1(" %1.%2")
+ .arg(version.majorVersion())
+ .arg(version.minorVersion())).toUtf8();
- return enquote((module == relocatableModuleUri)
+ return (module == relocatableModuleUri)
? versionedElement
- : module + QLatin1Char('/') + versionedElement);
+ : module.toUtf8() + '/' + versionedElement;
}
void writeMetaContent(const QMetaObject *meta, KnownAttributes *knownAttributes = nullptr)
@@ -375,30 +370,31 @@ public:
for (int index = meta->methodOffset(); index < meta->methodCount(); ++index) {
QMetaMethod method = meta->method(index);
QByteArray signature = method.methodSignature();
- if (signature == QByteArrayLiteral("destroyed(QObject*)")
- || signature == QByteArrayLiteral("destroyed()")
- || signature == QByteArrayLiteral("deleteLater()"))
+ if (signature == "destroyed(QObject*)"
+ || signature == "destroyed()"
+ || signature == "deleteLater()") {
continue;
+ }
dump(method, implicitSignals, knownAttributes);
}
// and add toString(), destroy() and destroy(int)
- if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("toString"), 0, QTypeRevision::zero())) {
- qml->writeStartObject(QLatin1String("Method"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("toString")));
+ if (!knownAttributes || !knownAttributes->knownMethod("toString", 0, QTypeRevision::zero())) {
+ qml->writeStartObject("Method");
+ qml->writeStringBinding("name", QLatin1String("toString"));
qml->writeEndObject();
}
- if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("destroy"), 0, QTypeRevision::zero())) {
- qml->writeStartObject(QLatin1String("Method"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy")));
+ if (!knownAttributes || !knownAttributes->knownMethod("destroy", 0, QTypeRevision::zero())) {
+ qml->writeStartObject("Method");
+ qml->writeStringBinding("name", QLatin1String("destroy"));
qml->writeEndObject();
}
- if (!knownAttributes || !knownAttributes->knownMethod(QByteArray("destroy"), 1, QTypeRevision::zero())) {
- qml->writeStartObject(QLatin1String("Method"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("destroy")));
- qml->writeStartObject(QLatin1String("Parameter"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QLatin1String("delay")));
- qml->writeScriptBinding(QLatin1String("type"), enquote(QLatin1String("int")));
+ if (!knownAttributes || !knownAttributes->knownMethod("destroy", 1, QTypeRevision::zero())) {
+ qml->writeStartObject("Method");
+ qml->writeStringBinding("name", QLatin1String("destroy"));
+ qml->writeStartObject("Parameter");
+ qml->writeStringBinding("name", QLatin1String("delay"));
+ qml->writeStringBinding("type", QLatin1String("int"));
qml->writeEndObject();
qml->writeEndObject();
}
@@ -408,12 +404,12 @@ public:
}
}
- QString getPrototypeNameForCompositeType(
+ QByteArray getPrototypeNameForCompositeType(
const QMetaObject *metaObject, QList<const QMetaObject *> *objectsToMerge,
const QmlVersionInfo &versionInfo)
{
auto ty = QQmlMetaType::qmlType(metaObject);
- QString prototypeName;
+ QByteArray prototypeName;
if (matchingImportUri(ty, versionInfo)) {
// dynamic meta objects can break things badly
// but extended types are usually fine
@@ -464,35 +460,36 @@ public:
QList<const QMetaObject *> objectsToMerge;
KnownAttributes knownAttributes;
// Get C++ base class name for the composite type
- QString prototypeName = getPrototypeNameForCompositeType(mainMeta, &objectsToMerge,
- versionInfo);
- qml->writeScriptBinding(QLatin1String("prototype"), enquote(prototypeName));
+ QByteArray prototypeName = getPrototypeNameForCompositeType(
+ mainMeta, &objectsToMerge, versionInfo);
+ qml->writeStringBinding("prototype", QUtf8StringView(prototypeName));
- QString qmlTyName = compositeType.qmlTypeName();
- const QString exportString = getExportString(compositeType, versionInfo);
+ const QByteArray exportString = getExportString(compositeType, versionInfo);
// TODO: why don't we simply output the compositeType.elementName() here?
// That would make more sense, but it would change the format quite a bit.
- qml->writeScriptBinding(QLatin1String("name"), exportString);
+ qml->writeStringBinding("name", QUtf8StringView(exportString));
- qml->writeArrayBinding(QLatin1String("exports"), QStringList() << exportString);
+ qml->writeStringListBinding(
+ "exports", QList<QAnyStringView> { QUtf8StringView(exportString) });
// TODO: shouldn't this be metaObjectRevision().value<quint16>()
// rather than version().minorVersion()
- qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), QStringList()
- << QString::number(compositeType.version().minorVersion()));
+ qml->writeArrayBinding(
+ "exportMetaObjectRevisions",
+ QByteArrayList() << QByteArray::number(compositeType.version().minorVersion()));
- qml->writeBooleanBinding(QLatin1String("isComposite"), true);
+ qml->writeBooleanBinding("isComposite", true);
if (compositeType.isSingleton()) {
- qml->writeBooleanBinding(QLatin1String("isCreatable"), false);
- qml->writeBooleanBinding(QLatin1String("isSingleton"), true);
+ qml->writeBooleanBinding("isCreatable", false);
+ qml->writeBooleanBinding("isSingleton", true);
}
for (int index = mainMeta->classInfoCount() - 1 ; index >= 0 ; --index) {
QMetaClassInfo classInfo = mainMeta->classInfo(index);
- if (QLatin1String(classInfo.name()) == QLatin1String("DefaultProperty")) {
- qml->writeScriptBinding(QLatin1String("defaultProperty"), enquote(QLatin1String(classInfo.value())));
+ if (QUtf8StringView(classInfo.name()) == QUtf8StringView("DefaultProperty")) {
+ qml->writeStringBinding("defaultProperty", QUtf8StringView(classInfo.value()));
break;
}
}
@@ -507,22 +504,29 @@ public:
qml->writeEndObject();
}
- QString getDefaultProperty(const QMetaObject *meta)
+ QByteArray getDefaultProperty(const QMetaObject *meta)
{
for (int index = meta->classInfoCount() - 1; index >= 0; --index) {
QMetaClassInfo classInfo = meta->classInfo(index);
if (QLatin1String(classInfo.name()) == QLatin1String("DefaultProperty")) {
- return QLatin1String(classInfo.value());
+ return QByteArray(classInfo.value());
}
}
- return QString();
+ return QByteArray();
}
struct QmlTypeInfo {
QmlTypeInfo() {}
- QmlTypeInfo(const QString &exportString, QTypeRevision revision, const QMetaObject *extendedObject, QByteArray attachedTypeId)
- : exportString(exportString), revision(revision), extendedObject(extendedObject), attachedTypeId(attachedTypeId) {}
- QString exportString;
+ QmlTypeInfo(
+ const QByteArray &exportString, QTypeRevision revision,
+ const QMetaObject *extendedObject, QByteArray attachedTypeId)
+ : exportString(exportString)
+ , revision(revision)
+ , extendedObject(extendedObject)
+ , attachedTypeId(attachedTypeId)
+ {}
+
+ QByteArray exportString;
QTypeRevision revision = QTypeRevision::zero();
const QMetaObject *extendedObject = nullptr;
QByteArray attachedTypeId;
@@ -533,11 +537,12 @@ public:
qml->writeStartObject("Component");
QByteArray id = convertToId(meta);
- qml->writeScriptBinding(QLatin1String("name"), enquote(id));
+ qml->writeStringBinding("name", QUtf8StringView(id));
// collect type information
QVector<QmlTypeInfo> typeInfo;
- for (QQmlType type : qmlTypesByCppName.value(meta->className())) {
+ const auto types = qmlTypesByCppName.value(meta->className());
+ for (const QQmlType &type : types) {
const QMetaObject *extendedObject = type.extensionFunction() ? type.metaObject() : nullptr;
QByteArray attachedTypeId;
if (const QMetaObject *attachedType = type.attachedPropertiesType(engine)) {
@@ -546,7 +551,8 @@ public:
if (attachedType != meta)
attachedTypeId = convertToId(attachedType);
}
- const QString exportString = getExportString(type, { QString(), QTypeRevision(), false });
+ const QByteArray exportString = getExportString(
+ type, { QString(), QTypeRevision(), false });
QTypeRevision metaObjectRevision = type.metaObjectRevision();
if (extendedObject) {
// emulate custom metaobjectrevision out of import
@@ -564,7 +570,7 @@ public:
// determine default property
// TODO: support revisioning of default property
- QString defaultProperty = getDefaultProperty(meta);
+ QByteArray defaultProperty = getDefaultProperty(meta);
if (defaultProperty.isEmpty()) {
for (const QmlTypeInfo &iter : typeInfo) {
if (iter.extendedObject) {
@@ -575,31 +581,33 @@ public:
}
}
if (!defaultProperty.isEmpty())
- qml->writeScriptBinding(QLatin1String("defaultProperty"), enquote(defaultProperty));
+ qml->writeStringBinding("defaultProperty", defaultProperty);
if (meta->superClass())
- qml->writeScriptBinding(QLatin1String("prototype"), enquote(convertToId(meta->superClass())));
+ qml->writeStringBinding("prototype", convertToId(meta->superClass()));
if (!typeInfo.isEmpty()) {
- QMap<QString, QString> exports; // sort exports
- for (const QmlTypeInfo &iter : typeInfo)
- exports.insert(iter.exportString, QString::number(iter.revision.toEncodedVersion<quint16>()));
+ QMap<QAnyStringView, QByteArray> exports; // sort exports
+ for (const QmlTypeInfo &iter : typeInfo) {
+ exports.insert(
+ QUtf8StringView(iter.exportString),
+ QByteArray::number(iter.revision.toEncodedVersion<quint16>()));
+ }
- QStringList exportStrings = exports.keys();
- QStringList metaObjectRevisions = exports.values();
- qml->writeArrayBinding(QLatin1String("exports"), exportStrings);
+ QByteArrayList metaObjectRevisions = exports.values();
+ qml->writeStringListBinding("exports", exports.keys());
if (isUncreatable)
- qml->writeBooleanBinding(QLatin1String("isCreatable"), false);
+ qml->writeBooleanBinding("isCreatable", false);
if (isSingleton)
- qml->writeBooleanBinding(QLatin1String("isSingleton"), true);
+ qml->writeBooleanBinding("isSingleton", true);
- qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), metaObjectRevisions);
+ qml->writeArrayBinding("exportMetaObjectRevisions", metaObjectRevisions);
for (const QmlTypeInfo &iter : typeInfo) {
if (!iter.attachedTypeId.isEmpty()) {
- qml->writeScriptBinding(QLatin1String("attachedType"), enquote(iter.attachedTypeId));
+ qml->writeStringBinding("attachedType", iter.attachedTypeId);
break;
}
}
@@ -611,7 +619,7 @@ public:
writeMetaContent(meta);
// dump properties from extended metaobjects last
- for (auto iter : typeInfo) {
+ for (const auto &iter : typeInfo) {
if (iter.extendedObject)
dumpMetaProperties(iter.extendedObject, iter.revision);
}
@@ -647,13 +655,13 @@ private:
bool isList = false, isPointer = false;
removePointerAndList(&typeName, &isList, &isPointer);
- qml->writeScriptBinding(QLatin1String("type"), enquote(typeName));
+ qml->writeStringBinding("type", QUtf8StringView(typeName));
if (isList)
- qml->writeScriptBinding(QLatin1String("isList"), QLatin1String("true"));
+ qml->writeBooleanBinding("isList", true);
if (!isWritable)
- qml->writeScriptBinding(QLatin1String("isReadonly"), QLatin1String("true"));
+ qml->writeBooleanBinding("isReadonly", true);
if (isPointer)
- qml->writeScriptBinding(QLatin1String("isPointer"), QLatin1String("true"));
+ qml->writeBooleanBinding("isPointer", true);
}
void dump(const QMetaProperty &prop, QTypeRevision metaRevision = QTypeRevision(),
@@ -667,9 +675,9 @@ private:
if (knownAttributes && knownAttributes->knownProperty(propName, revision))
return;
qml->writeStartObject("Property");
- qml->writeScriptBinding(QLatin1String("name"), enquote(QString::fromUtf8(prop.name())));
+ qml->writeStringBinding("name", QUtf8StringView(prop.name()));
if (revision != QTypeRevision::zero())
- qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision.toEncodedVersion<quint16>()));
+ qml->writeNumberBinding("revision", revision.toEncodedVersion<quint16>());
writeTypeProperties(prop.typeName(), prop.isWritable());
qml->writeEndObject();
@@ -701,13 +709,13 @@ private:
}
QByteArray name = meth.name();
- const QString typeName = convertToId(meth.typeName());
+ const QByteArray typeName = convertToId(meth.typeName());
if (implicitSignals.contains(name)
&& !meth.revision()
&& meth.methodType() == QMetaMethod::Signal
&& meth.parameterNames().isEmpty()
- && typeName == QLatin1String("void")) {
+ && typeName == "void") {
// don't mention implicit signals
return;
}
@@ -716,24 +724,24 @@ private:
if (knownAttributes && knownAttributes->knownMethod(name, meth.parameterNames().size(), revision))
return;
if (meth.methodType() == QMetaMethod::Signal)
- qml->writeStartObject(QLatin1String("Signal"));
+ qml->writeStartObject("Signal");
else
- qml->writeStartObject(QLatin1String("Method"));
+ qml->writeStartObject("Method");
- qml->writeScriptBinding(QLatin1String("name"), enquote(name));
+ qml->writeStringBinding("name", QUtf8StringView(name));
if (revision != QTypeRevision::zero())
- qml->writeScriptBinding(QLatin1String("revision"), QString::number(revision.toEncodedVersion<quint16>()));
+ qml->writeNumberBinding("revision", revision.toEncodedVersion<quint16>());
- if (typeName != QLatin1String("void"))
- qml->writeScriptBinding(QLatin1String("type"), enquote(typeName));
+ if (typeName != "void")
+ qml->writeStringBinding("type", QUtf8StringView(typeName));
for (int i = 0; i < meth.parameterTypes().size(); ++i) {
QByteArray argName = meth.parameterNames().at(i);
- qml->writeStartObject(QLatin1String("Parameter"));
- if (! argName.isEmpty())
- qml->writeScriptBinding(QLatin1String("name"), enquote(argName));
+ qml->writeStartObject("Parameter");
+ if (!argName.isEmpty())
+ qml->writeStringBinding("name", QUtf8StringView(argName));
writeTypeProperties(meth.parameterTypes().at(i), true);
qml->writeEndObject();
}
@@ -743,17 +751,16 @@ private:
void dump(const QMetaEnum &e)
{
- qml->writeStartObject(QLatin1String("Enum"));
- qml->writeScriptBinding(QLatin1String("name"), enquote(QString::fromUtf8(e.name())));
+ qml->writeStartObject("Enum");
+ qml->writeStringBinding("name", QUtf8StringView(e.name()));
- QList<QPair<QString, QString> > namesValues;
+ QList<QPair<QAnyStringView, int>> namesValues;
const int keyCount = e.keyCount();
namesValues.reserve(keyCount);
- for (int index = 0; index < keyCount; ++index) {
- namesValues.append(qMakePair(enquote(QString::fromUtf8(e.key(index))), QString::number(e.value(index))));
- }
+ for (int index = 0; index < keyCount; ++index)
+ namesValues.append(qMakePair(QUtf8StringView(e.key(index)), e.value(index)));
- qml->writeScriptObjectLiteralBinding(QLatin1String("values"), namesValues);
+ qml->writeEnumObjectLiteralBinding("values", namesValues);
qml->writeEndObject();
}
};
@@ -1167,17 +1174,17 @@ int main(int argc, char *argv[])
// Merge file.
QStringList mergeDependencies;
- QString mergeComponents;
+ QByteArray mergeComponents;
if (!mergeFile.isEmpty()) {
const QStringList merge = readQmlTypes(mergeFile);
if (!merge.isEmpty()) {
- QRegularExpression re("(\\w+\\.*\\w*\\s*\\d+\\.\\d+)");
+ static const QRegularExpression re("(\\w+\\.*\\w*\\s*\\d+\\.\\d+)");
QRegularExpressionMatchIterator i = re.globalMatch(merge[1]);
while (i.hasNext()) {
QRegularExpressionMatch m = i.next();
mergeDependencies << m.captured(1);
}
- mergeComponents = merge [2];
+ mergeComponents = merge[2].toUtf8();
}
}
@@ -1317,16 +1324,20 @@ int main(int argc, char *argv[])
QQmlJSStreamWriter qml(&bytes);
qml.writeStartDocument();
- qml.writeLibraryImport(QLatin1String("QtQuick.tooling"), 1, 2);
- qml.write(QString("\n"
+ qml.writeLibraryImport("QtQuick.tooling", 1, 2);
+ qml.write("\n"
"// This file describes the plugin-supplied types contained in the library.\n"
"// It is used for QML tooling purposes only.\n"
"//\n"
"// This file was auto-generated by:\n"
- "// '%1 %2'\n"
+ "// '");
+ qml.write(QFileInfo(args.at(0)).baseName().toUtf8());
+ qml.write(" ");
+ qml.write(args.mid(1).join(QLatin1Char(' ')).toUtf8());
+ qml.write("'\n"
"//\n"
"// qmlplugindump is deprecated! You should use qmltyperegistrar instead.\n"
- "\n").arg(QFileInfo(args.at(0)).baseName(), args.mid(1).join(QLatin1Char(' '))));
+ "\n");
qml.writeStartObject("Module");
// put the metaobjects into a map so they are always dumped in the same order