/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "fakemetaobject.h" #include using namespace LanguageUtils; FakeMetaEnum::FakeMetaEnum() {} FakeMetaEnum::FakeMetaEnum(const QString &name) : m_name(name) {} bool FakeMetaEnum::isValid() const { return !m_name.isEmpty(); } QString FakeMetaEnum::name() const { return m_name; } void FakeMetaEnum::setName(const QString &name) { m_name = name; } void FakeMetaEnum::addKey(const QString &key, int value) { m_keys.append(key); m_values.append(value); } QString FakeMetaEnum::key(int index) const { return m_keys.at(index); } int FakeMetaEnum::keyCount() const { return m_keys.size(); } QStringList FakeMetaEnum::keys() const { return m_keys; } bool FakeMetaEnum::hasKey(const QString &key) const { return m_keys.contains(key); } void FakeMetaEnum::addToHash(QCryptographicHash &hash) const { int len = m_name.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(m_name.constData()), len * sizeof(QChar)); len = m_keys.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); foreach (const QString &key, m_keys) { len = key.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(key.constData()), len * sizeof(QChar)); } len = m_values.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); foreach (int value, m_values) hash.addData(reinterpret_cast(&value), sizeof(value)); } QString FakeMetaEnum::describe(int baseIndent) const { QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent); QString res = QLatin1String("Enum "); res += name(); res += QLatin1String(":{"); for (int i = 0; i < keyCount(); ++i) { res += newLine; res += QLatin1String(" "); res += key(i); res += QLatin1String(": "); res += QString::number(m_values.value(i, -1)); } res += newLine; res += QLatin1Char('}'); return res; } QString FakeMetaEnum::toString() const { return describe(); } FakeMetaMethod::FakeMetaMethod(const QString &name, const QString &returnType) : m_name(name) , m_returnType(returnType) , m_methodTy(FakeMetaMethod::Method) , m_methodAccess(FakeMetaMethod::Public) , m_revision(0) {} FakeMetaMethod::FakeMetaMethod() : m_methodTy(FakeMetaMethod::Method) , m_methodAccess(FakeMetaMethod::Public) , m_revision(0) {} QString FakeMetaMethod::methodName() const { return m_name; } void FakeMetaMethod::setMethodName(const QString &name) { m_name = name; } void FakeMetaMethod::setReturnType(const QString &type) { m_returnType = type; } QStringList FakeMetaMethod::parameterNames() const { return m_paramNames; } QStringList FakeMetaMethod::parameterTypes() const { return m_paramTypes; } void FakeMetaMethod::addParameter(const QString &name, const QString &type) { m_paramNames.append(name); m_paramTypes.append(type); } int FakeMetaMethod::methodType() const { return m_methodTy; } void FakeMetaMethod::setMethodType(int methodType) { m_methodTy = methodType; } int FakeMetaMethod::access() const { return m_methodAccess; } int FakeMetaMethod::revision() const { return m_revision; } void FakeMetaMethod::setRevision(int r) { m_revision = r; } void FakeMetaMethod::addToHash(QCryptographicHash &hash) const { int len = m_name.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(m_name.constData()), len * sizeof(QChar)); hash.addData(reinterpret_cast(&m_methodAccess), sizeof(m_methodAccess)); hash.addData(reinterpret_cast(&m_methodTy), sizeof(m_methodTy)); hash.addData(reinterpret_cast(&m_revision), sizeof(m_revision)); len = m_paramNames.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); foreach (const QString &pName, m_paramNames) { len = pName.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(pName.constData()), len * sizeof(QChar)); } len = m_paramTypes.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); foreach (const QString &pType, m_paramTypes) { len = pType.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(pType.constData()), len * sizeof(QChar)); } len = m_returnType.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(m_returnType.constData()), len * sizeof(QChar)); } QString FakeMetaMethod::describe(int baseIndent) const { QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent); QString res = QLatin1String("Method {"); res += newLine; res += QLatin1String(" methodName:"); res += methodName(); res += newLine; res += QLatin1String(" methodType:"); res += methodType(); res += newLine; res += QLatin1String(" parameterNames:["); foreach (const QString &pName, parameterNames()) { res += newLine; res += QLatin1String(" "); res += pName; } res += QLatin1Char(']'); res += newLine; res += QLatin1String(" parameterTypes:["); foreach (const QString &pType, parameterTypes()) { res += newLine; res += QLatin1String(" "); res += pType; } res += QLatin1Char(']'); res += newLine; res += QLatin1Char('}'); return res; } QString FakeMetaMethod::toString() const { return describe(); } FakeMetaProperty::FakeMetaProperty(const QString &name, const QString &type, bool isList, bool isWritable, bool isPointer, int revision) : m_propertyName(name) , m_type(type) , m_isList(isList) , m_isWritable(isWritable) , m_isPointer(isPointer) , m_revision(revision) {} QString FakeMetaProperty::name() const { return m_propertyName; } QString FakeMetaProperty::typeName() const { return m_type; } bool FakeMetaProperty::isList() const { return m_isList; } bool FakeMetaProperty::isWritable() const { return m_isWritable; } bool FakeMetaProperty::isPointer() const { return m_isPointer; } int FakeMetaProperty::revision() const { return m_revision; } void FakeMetaProperty::addToHash(QCryptographicHash &hash) const { int len = m_propertyName.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(m_propertyName.constData()), len * sizeof(QChar)); hash.addData(reinterpret_cast(&m_revision), sizeof(m_revision)); int flags = (m_isList ? (1 << 0) : 0) + (m_isPointer ? (1 << 1) : 0) + (m_isWritable ? (1 << 2) : 0); hash.addData(reinterpret_cast(&flags), sizeof(flags)); len = m_type.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(m_type.constData()), len * sizeof(QChar)); } QString FakeMetaProperty::describe(int baseIndent) const { auto boolStr = [] (bool v) { return v ? QLatin1String("true") : QLatin1String("false"); }; QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent); QString res = QLatin1String("Property {"); res += newLine; res += QLatin1String(" name:"); res += name(); res += newLine; res += QLatin1String(" typeName:"); res += typeName(); res += newLine; res += QLatin1String(" typeName:"); res += QString::number(revision()); res += newLine; res += QLatin1String(" isList:"); res += boolStr(isList()); res += newLine; res += QLatin1String(" isPointer:"); res += boolStr(isPointer()); res += newLine; res += QLatin1String(" isWritable:"); res += boolStr(isWritable()); res += newLine; res += QLatin1Char('}'); return res; } QString FakeMetaProperty::toString() const { return describe(); } FakeMetaObject::FakeMetaObject() : m_isSingleton(false), m_isCreatable(true), m_isComposite(false) { } QString FakeMetaObject::className() const { return m_className; } void FakeMetaObject::setClassName(const QString &name) { m_className = name; } void FakeMetaObject::addExport(const QString &name, const QString &package, ComponentVersion version) { Export exp; exp.type = name; exp.package = package; exp.version = version; m_exports.append(exp); } void FakeMetaObject::setExportMetaObjectRevision(int exportIndex, int metaObjectRevision) { m_exports[exportIndex].metaObjectRevision = metaObjectRevision; } QList FakeMetaObject::exports() const { return m_exports; } FakeMetaObject::Export FakeMetaObject::exportInPackage(const QString &package) const { foreach (const Export &exp, m_exports) { if (exp.package == package) return exp; } return Export(); } void FakeMetaObject::setSuperclassName(const QString &superclass) { m_superName = superclass; } QString FakeMetaObject::superclassName() const { return m_superName; } void FakeMetaObject::addEnum(const FakeMetaEnum &fakeEnum) { m_enumNameToIndex.insert(fakeEnum.name(), m_enums.size()); m_enums.append(fakeEnum); } int FakeMetaObject::enumeratorCount() const { return m_enums.size(); } int FakeMetaObject::enumeratorOffset() const { return 0; } FakeMetaEnum FakeMetaObject::enumerator(int index) const { return m_enums.at(index); } int FakeMetaObject::enumeratorIndex(const QString &name) const { return m_enumNameToIndex.value(name, -1); } void FakeMetaObject::addProperty(const FakeMetaProperty &property) { m_propNameToIdx.insert(property.name(), m_props.size()); m_props.append(property); } int FakeMetaObject::propertyCount() const { return m_props.size(); } int FakeMetaObject::propertyOffset() const { return 0; } FakeMetaProperty FakeMetaObject::property(int index) const { return m_props.at(index); } int FakeMetaObject::propertyIndex(const QString &name) const { return m_propNameToIdx.value(name, -1); } void FakeMetaObject::addMethod(const FakeMetaMethod &method) { m_methods.append(method); } int FakeMetaObject::methodCount() const { return m_methods.size(); } int FakeMetaObject::methodOffset() const { return 0; } FakeMetaMethod FakeMetaObject::method(int index) const { return m_methods.at(index); } int FakeMetaObject::methodIndex(const QString &name) const //If performances becomes an issue, just use a nameToIdx hash { for (int i=0; i(&len), sizeof(len)); hash.addData(reinterpret_cast(m_className.constData()), len * sizeof(QChar)); len = m_attachedTypeName.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(m_attachedTypeName.constData()), len * sizeof(QChar)); len = m_defaultPropertyName.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(m_defaultPropertyName.constData()), len * sizeof(QChar)); len = m_enumNameToIndex.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); { QStringList keys(m_enumNameToIndex.keys()); keys.sort(); foreach (const QString &key, keys) { len = key.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(key.constData()), len * sizeof(QChar)); int value = m_enumNameToIndex.value(key); hash.addData(reinterpret_cast(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint... m_enums.at(value).addToHash(hash); } } len = m_exports.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); foreach (const Export &e, m_exports) e.addToHash(hash); // normalize order? len = m_exports.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); foreach (const FakeMetaMethod &m, m_methods) m.addToHash(hash); // normalize order? { QStringList keys(m_propNameToIdx.keys()); keys.sort(); foreach (const QString &key, keys) { len = key.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(key.constData()), len * sizeof(QChar)); int value = m_propNameToIdx.value(key); hash.addData(reinterpret_cast(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint... m_props.at(value).addToHash(hash); } } len = m_superName.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(m_superName.constData()), len * sizeof(QChar)); QByteArray res = hash.result(); res.append('F'); return res; } void FakeMetaObject::updateFingerprint() { m_fingerprint = calculateFingerprint(); } QByteArray FakeMetaObject::fingerprint() const { return m_fingerprint; } bool FakeMetaObject::isSingleton() const { return m_isSingleton; } bool FakeMetaObject::isCreatable() const { return m_isCreatable; } bool FakeMetaObject::isComposite() const { return m_isComposite; } void FakeMetaObject::setIsSingleton(bool value) { m_isSingleton = value; } void FakeMetaObject::setIsCreatable(bool value) { m_isCreatable = value; } void FakeMetaObject::setIsComposite(bool value) { m_isSingleton = value; } QString FakeMetaObject::toString() const { return describe(); } QString FakeMetaObject::describe(bool printDetails, int baseIndent) const { QString res = QString::fromLatin1("FakeMetaObject@%1") .arg((quintptr)(void *)this, 0, 16); if (!printDetails) return res; auto boolStr = [] (bool v) { return v ? QLatin1String("true") : QLatin1String("false"); }; QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent); res += QLatin1Char('{'); res += newLine; res += QLatin1String("className:"); res += className(); res += newLine; res += QLatin1String("superClassName:"); res += superclassName(); res += newLine; res += QLatin1String("isSingleton:"); res += boolStr(isSingleton()); res += newLine; res += QLatin1String("isCreatable:"); res += boolStr(isCreatable()); res += newLine; res += QLatin1String("isComposite:"); res += boolStr(isComposite()); res += newLine; res += QLatin1String("defaultPropertyName:"); res += defaultPropertyName(); res += newLine; res += QLatin1String("attachedTypeName:"); res += attachedTypeName(); res += newLine; res += QLatin1String("fingerprint:"); res += QString::fromUtf8(fingerprint()); res += newLine; res += QLatin1String("exports:["); foreach (const Export &e, exports()) { res += newLine; res += QLatin1String(" "); res += e.describe(baseIndent + 2); } res += QLatin1Char(']'); res += newLine; res += QLatin1String("enums:["); for (int iEnum = 0; iEnum < enumeratorCount() ; ++ iEnum) { FakeMetaEnum e = enumerator(enumeratorOffset() + iEnum); res += newLine; res += QLatin1String(" "); res += e.describe(baseIndent + 2); } res += QLatin1Char(']'); res += newLine; res += QLatin1String("properties:["); for (int iProp = 0; iProp < propertyCount() ; ++ iProp) { FakeMetaProperty prop = property(propertyOffset() + iProp); res += newLine; res += QLatin1String(" "); res += prop.describe(baseIndent + 2); } res += QLatin1Char(']'); res += QLatin1String("methods:["); for (int iMethod = 0; iMethod < methodOffset() ; ++ iMethod) { FakeMetaMethod m = method(methodOffset() + iMethod); res += newLine; res += QLatin1String(" "); m.describe(baseIndent + 2); } res += QLatin1Char(']'); res += newLine; res += QLatin1Char('}'); return res; } FakeMetaObject::Export::Export() : metaObjectRevision(0) {} bool FakeMetaObject::Export::isValid() const { return version.isValid() || !package.isEmpty() || !type.isEmpty(); } void FakeMetaObject::Export::addToHash(QCryptographicHash &hash) const { int len = package.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(package.constData()), len * sizeof(QChar)); len = type.size(); hash.addData(reinterpret_cast(&len), sizeof(len)); hash.addData(reinterpret_cast(type.constData()), len * sizeof(QChar)); version.addToHash(hash); hash.addData(reinterpret_cast(&metaObjectRevision), sizeof(metaObjectRevision)); } QString FakeMetaObject::Export::describe(int baseIndent) const { QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent); QString res = QLatin1String("Export {"); res += newLine; res += QLatin1String(" package:"); res += package; res += newLine; res += QLatin1String(" type:"); res += type; res += newLine; res += QLatin1String(" version:"); res += version.toString(); res += newLine; res += QLatin1String(" metaObjectRevision:"); res += QString::number(metaObjectRevision); res += newLine; res += QLatin1String(" isValid:"); res += QString::number(isValid()); res += newLine; res += QLatin1Char('}'); return res; } QString FakeMetaObject::Export::toString() const { return describe(); }