7#include "cppgenerator.h" 
   10#include "typehelper.h" 
   16CppGenerator::CppGenerator()
 
   20CppGenerator::~CppGenerator()
 
   24bool CppGenerator::generate(
Node const *node)
 
   26    Q_ASSERT(node->
type() == Node::Document);
 
   28    mHeaderFile.setFileName(QStringLiteral(
"protocol_gen.h"));
 
   30        std::cerr << qPrintable(mHeaderFile.errorString()) << std::endl;
 
   33    mHeader.setDevice(&mHeaderFile);
 
   35    mImplFile.setFileName(QStringLiteral(
"protocol_gen.cpp"));
 
   37        std::cerr << qPrintable(mImplFile.errorString()) << std::endl;
 
   40    mImpl.setDevice(&mImplFile);
 
   42    return generateDocument(
static_cast<DocumentNode 
const *
>(node));
 
   45void CppGenerator::writeHeaderHeader(DocumentNode 
const *node)
 
   47    mHeader << 
"// This is an auto-generated file.\n" 
   48               "// Any changes to this file will be overwritten\n" 
   50               "// clazy:excludeall=function-args-by-value\n" 
   52               "namespace Akonadi {\n" 
   53               "namespace Protocol {\n" 
   55               "AKONADIPRIVATE_EXPORT int version();\n" 
   59    for (
const auto *child : std::as_const(node->children())) {
 
   60        if (child->type() == Node::Class) {
 
   61            mHeader << 
"class " << 
static_cast<const ClassNode *
>(child)->className() << 
";\n";
 
   66               "} // namespace Protocol\n" 
   67               "} // namespace Akonadi\n\n";
 
   70void CppGenerator::writeHeaderFooter(DocumentNode 
const * )
 
   75void CppGenerator::writeImplHeader(DocumentNode 
const *node)
 
   77    mImpl << 
"// This is an auto-generated file.\n" 
   78             "// Any changes to this file will be overwritten\n" 
   80             "// clazy:excludeall=function-args-by-value\n" 
   82             "namespace Akonadi {\n" 
   83             "namespace Protocol {\n" 
   94void CppGenerator::writeImplFooter(DocumentNode 
const * )
 
   96    mImpl << 
"} // namespace Protocol\n" 
   97             "} // namespace Akonadi\n";
 
  100bool CppGenerator::generateDocument(DocumentNode 
const *node)
 
  102    writeHeaderHeader(node);
 
  103    writeImplHeader(node);
 
  105    writeImplSerializer(node);
 
  107    for (
const auto *classNode : node->children()) {
 
  108        if (!generateClass(
static_cast<ClassNode 
const *
>(classNode))) {
 
  113    writeHeaderFooter(node);
 
  114    writeImplFooter(node);
 
  119void CppGenerator::writeImplSerializer(DocumentNode 
const *node)
 
  121    mImpl << 
"void serialize(DataStream &stream, const CommandPtr &cmd)\n" 
  123             "    switch (static_cast<int>(cmd->type() | (cmd->isResponse() ? Command::_ResponseBit : 0))) {\n" 
  124             "    case Command::Invalid:\n" 
  125             "        stream << cmdCast<Command>(cmd);\n" 
  127             "    case Command::Invalid | Command::_ResponseBit:\n" 
  128             "        stream << cmdCast<Response>(cmd);\n" 
  130    for (
const auto *child : std::as_const(node->children())) {
 
  131        const auto *classNode = 
static_cast<ClassNode 
const *
>(child);
 
  132        if (classNode->classType() == ClassNode::Response) {
 
  133            mImpl << 
"    case Command::" << classNode->name()
 
  134                  << 
" | Command::_ResponseBit:\n" 
  135                     "        stream << cmdCast<" 
  136                  << classNode->className()
 
  139        } 
else if (classNode->classType() == ClassNode::Command) {
 
  140            mImpl << 
"    case Command::" << classNode->name()
 
  142                     "        stream << cmdCast<" 
  143                  << classNode->className()
 
  146        } 
else if (classNode->classType() == ClassNode::Notification) {
 
  147            mImpl << 
"    case Command::" << classNode->name()
 
  149                     "        stream << cmdCast<" 
  150                  << classNode->className()
 
  158    mImpl << 
"CommandPtr deserialize(QIODevice *device)\n" 
  160             "    DataStream stream(device);\n" 
  161             "    stream.waitForData(sizeof(Command::Type));\n" 
  162             "    Command::Type cmdType;\n" 
  163             "    if (Q_UNLIKELY(device->peek((char *) &cmdType, sizeof(Command::Type)) != sizeof(Command::Type))) {\n" 
  164             "        throw ProtocolException(\"Failed to peek command type\");\n" 
  167             "    if (cmdType & Command::_ResponseBit) {\n" 
  168             "        cmd = Factory::response(Command::Type(cmdType & ~Command::_ResponseBit));\n" 
  170             "        cmd = Factory::command(cmdType);\n" 
  172             "    switch (static_cast<int>(cmdType)) {\n" 
  173             "    case Command::Invalid:\n" 
  174             "        stream >> cmdCast<Command>(cmd);\n" 
  176             "    case Command::Invalid | Command::_ResponseBit:\n" 
  177             "        stream >> cmdCast<Response>(cmd);\n" 
  179    for (
const auto *child : std::as_const(node->children())) {
 
  180        const auto *classNode = 
static_cast<ClassNode 
const *
>(child);
 
  181        if (classNode->classType() == ClassNode::Response) {
 
  182            mImpl << 
"    case Command::" << classNode->name()
 
  183                  << 
" | Command::_ResponseBit:\n" 
  184                     "        stream >> cmdCast<" 
  185                  << classNode->className()
 
  188        } 
else if (classNode->classType() == ClassNode::Command) {
 
  189            mImpl << 
"    case Command::" << classNode->name()
 
  191                     "        stream >> cmdCast<" 
  192                  << classNode->className()
 
  195        } 
else if (classNode->classType() == ClassNode::Notification) {
 
  196            mImpl << 
"    case Command::" << classNode->name()
 
  198                     "        stream >> cmdCast<" 
  199                  << classNode->className()
 
  205             "    return CommandPtr::create();\n" 
  209    mImpl << 
"QString debugString(const Command &cmd)\n" 
  212             "    switch (static_cast<int>(cmd.type() | (cmd.isResponse() ? Command::_ResponseBit : 0))) {\n" 
  213             "    case Command::Invalid:\n" 
  214             "        QDebug(&out).noquote() << static_cast<const Command &>(cmd);\n" 
  216             "    case Command::Invalid | Command::_ResponseBit:\n" 
  217             "        QDebug(&out).noquote() << static_cast<const Response &>(cmd);\n" 
  219    for (
const auto *child : std::as_const(node->children())) {
 
  220        const auto *classNode = 
static_cast<ClassNode 
const *
>(child);
 
  221        if (classNode->classType() == ClassNode::Response) {
 
  222            mImpl << 
"    case Command::" << classNode->name()
 
  223                  << 
" | Command::_ResponseBit:\n" 
  224                     "        QDebug(&out).noquote() << static_cast<const " 
  225                  << classNode->className()
 
  228        } 
else if (classNode->classType() == ClassNode::Command) {
 
  229            mImpl << 
"    case Command::" << classNode->name()
 
  231                     "        QDebug(&out).noquote() << static_cast<const " 
  232                  << classNode->className()
 
  235        } 
else if (classNode->classType() == ClassNode::Notification) {
 
  236            mImpl << 
"    case Command::" << classNode->name()
 
  238                     "        QDebug(&out).noquote() << static_cast<const " 
  239                  << classNode->className()
 
  245             "    return QString();\n" 
  250void CppGenerator::writeHeaderEnum(EnumNode 
const *node)
 
  252    mHeader << 
"    enum " << node->name() << 
" {\n";
 
  253    for (
const auto *enumChild : node->children()) {
 
  254        Q_ASSERT(enumChild->type() == Node::EnumValue);
 
  255        const auto *
const valueNode = 
static_cast<EnumValueNode 
const *
>(enumChild);
 
  256        mHeader << 
"        " << valueNode->name();
 
  257        if (!valueNode->value().isEmpty()) {
 
  258            mHeader << 
" = " << valueNode->value();
 
  263    if (node->enumType() == EnumNode::TypeFlag) {
 
  264        mHeader << 
"    Q_DECLARE_FLAGS(" << node->name() << 
"s, " << node->name() << 
")\n\n";
 
  268void CppGenerator::writeHeaderClass(ClassNode 
const *node)
 
  271    const QString parentClass = node->parentClassName();
 
  272    const bool isTypeClass = node->classType() == ClassNode::Class;
 
  274    mHeader << 
"namespace Akonadi {\n" 
  275               "namespace Protocol {\n\n" 
  276               "AKONADIPRIVATE_EXPORT DataStream &operator<<(DataStream &stream, const " 
  279               "AKONADIPRIVATE_EXPORT DataStream &operator>>(DataStream &stream, " 
  282               "AKONADIPRIVATE_EXPORT QDebug operator<<(QDebug dbg, const " 
  287            << node->className() << 
"Ptr = QSharedPointer<" << node->className()
 
  291        mHeader << 
"class AKONADIPRIVATE_EXPORT " << node->className() << 
"\n";
 
  293        mHeader << 
"class AKONADIPRIVATE_EXPORT " << node->className() << 
" : public " << parentClass << 
"\n";
 
  299    for (
const auto *child : node->children()) {
 
  300        if (child->type() == Node::Enum) {
 
  301            const auto *
const enumNode = 
static_cast<EnumNode 
const *
>(child);
 
  302            writeHeaderEnum(enumNode);
 
  307    for (
const auto *child : std::as_const(node->children())) {
 
  308        if (child->type() == Node::Ctor) {
 
  309            const auto *
const ctor = 
static_cast<const CtorNode *
>(child);
 
  310            const auto args = ctor->arguments();
 
  311            mHeader << 
"    explicit " << node->className() << 
"(";
 
  312            for (
int i = 0; i < args.count(); ++i) {
 
  313                const auto &arg = args[i];
 
  314                if (TypeHelper::isNumericType(arg.type) || TypeHelper::isBoolType(arg.type)) {
 
  315                    mHeader << arg.type << 
" " << arg.name;
 
  317                    mHeader << 
"const " << arg.type << 
" &" << arg.name;
 
  319                if (!arg.defaultValue.isEmpty()) {
 
  320                    mHeader << 
" = " << arg.defaultValue;
 
  322                if (i < args.count() - 1) {
 
  330    mHeader << 
"    " << node->className() << 
"(const " << node->className()
 
  331            << 
" &) = default;\n" 
  333            << node->className() << 
"(" << node->className()
 
  334            << 
" &&) = default;\n" 
  340            << node->className() << 
" &operator=(const " << node->className()
 
  341            << 
" &) = default;\n" 
  343            << node->className() << 
" &operator=(" << node->className()
 
  344            << 
" &&) = default;\n" 
  345               "    bool operator==(const " 
  347            << 
" &other) const;\n" 
  348               "    inline bool operator!=(const " 
  349            << node->className() << 
" &other) const { return !operator==(other); }\n";
 
  352    for (
const auto *child : node->children()) {
 
  353        if (child->type() == Node::Property) {
 
  354            const auto *
const prop = 
static_cast<PropertyNode 
const *
>(child);
 
  355            if (prop->asReference()) {
 
  356                mHeader << 
"    inline const " << prop->type() << 
" &" << prop->name() << 
"() const { return " << prop->mVariableName()
 
  359                        << prop->type() << 
" &" << prop->name() << 
"() { return " << prop->mVariableName() << 
"; }\n";
 
  361                mHeader << 
"    inline " << prop->type() << 
" " << prop->name() << 
"() const { return " << prop->mVariableName() << 
"; }\n";
 
  363            if (!prop->readOnly()) {
 
  364                if (
auto *setter = prop->setter()) {
 
  365                    mHeader << 
"    void " << setter->name << 
"(const " << setter->type << 
" &" << prop->name() << 
");\n";
 
  366                } 
else if (!prop->dependencies().isEmpty()) {
 
  368                    if (TypeHelper::isNumericType(prop->type()) || TypeHelper::isBoolType(prop->type())) {
 
  369                        varType = QLatin1Char(
'(') + prop->type() + QLatin1Char(
' ');
 
  371                        varType = QLatin1StringView(
"(const ") + prop->type() + QLatin1StringView(
" &");
 
  373                    mHeader << 
"    void " << prop->setterName() << varType << prop->name() << 
");\n";
 
  376                    if (TypeHelper::isNumericType(prop->type()) || TypeHelper::isBoolType(prop->type())) {
 
  377                        varType = QLatin1Char(
'(') + prop->type() + QLatin1Char(
' ');
 
  379                        varType = QLatin1StringView(
"(const ") + prop->type() + QLatin1StringView(
" &");
 
  381                    mHeader << 
"    inline void " << prop->setterName() << varType << prop->name() << 
") { " << prop->mVariableName() << 
" = " << prop->name()
 
  383                    if (!TypeHelper::isNumericType(prop->type()) && !TypeHelper::isBoolType(prop->type())) {
 
  384                        mHeader << 
"    inline void " << prop->setterName() << 
"(" << prop->type() << 
" &&" << prop->name() << 
") { " << prop->mVariableName()
 
  385                                << 
" = std::move(" << prop->name() << 
"); }\n";
 
  392    mHeader << 
"    void toJson(QJsonObject &stream) const;\n";
 
  395    mHeader << 
"protected:\n";
 
  397    for (
const auto *prop : properties) {
 
  398        mHeader << 
"    " << prop->type() << 
" " << prop->mVariableName();
 
  399        const auto defaultValue = prop->defaultValue();
 
  400        const bool isDefaultValue = !defaultValue.isEmpty();
 
  401        const bool isNumeric = TypeHelper::isNumericType(prop->type());
 
  402        const bool isBool = TypeHelper::isBoolType(prop->type());
 
  403        if (isDefaultValue) {
 
  404            mHeader << 
" = " << defaultValue;
 
  405        } 
else if (isNumeric) {
 
  408            mHeader << 
" = false";
 
  415               "    friend AKONADIPRIVATE_EXPORT Akonadi::Protocol::DataStream &operator<<(Akonadi::Protocol::DataStream &stream, const Akonadi::Protocol::" 
  418               "    friend AKONADIPRIVATE_EXPORT Akonadi::Protocol::DataStream &operator>>(Akonadi::Protocol::DataStream &stream, Akonadi::Protocol::" 
  421               "    friend AKONADIPRIVATE_EXPORT QDebug operator<<(QDebug dbg, const Akonadi::Protocol::" 
  425               "} // namespace Protocol\n" 
  426               "} // namespace Akonadi\n" 
  428    mHeader << 
"Q_DECLARE_METATYPE(Akonadi::Protocol::" << node->className() << 
")\n\n";
 
  429    if (node->classType() != ClassNode::Class) {
 
  430        mHeader << 
"Q_DECLARE_METATYPE(Akonadi::Protocol::" << node->className() << 
"Ptr)\n\n";
 
  434void CppGenerator::writeImplSerializer(PropertyNode 
const *node, 
const char *streamingOperator)
 
  436    const auto deps = node->dependencies();
 
  437    if (deps.isEmpty()) {
 
  438        mImpl << 
"    stream " << streamingOperator << 
" obj." << node->mVariableName() << 
";\n";
 
  441        auto it = deps.cend();
 
  444            const QString mVar = it.key();
 
  446                  << 
"m" << mVar[0].
toUpper() << QStringView(mVar).
mid(1) << 
" & " << it.value() << 
")";
 
  447            if (it == deps.cbegin()) {
 
  455              << streamingOperator << 
" obj." << node->mVariableName()
 
  461void CppGenerator::writeImplClass(ClassNode 
const *node)
 
  463    const QString parentClass = node->parentClassName();
 
  464    const auto &children = node->children();
 
  468    for (
const auto *child : children) {
 
  469        if (child->type() == Node::Ctor) {
 
  470            const auto *
const ctor = 
static_cast<CtorNode 
const *
>(child);
 
  471            const auto args = ctor->arguments();
 
  472            mImpl << node->className() << 
"::" << node->className() << 
"(";
 
  473            for (
int i = 0; i < args.count(); ++i) {
 
  474                const auto &arg = args[i];
 
  475                if (TypeHelper::isNumericType(arg.type) || TypeHelper::isBoolType(arg.type)) {
 
  476                    mImpl << arg.type << 
" " << arg.name;
 
  478                    mImpl << 
"const " << arg.type << 
" &" << arg.name;
 
  480                if (i < args.count() - 1) {
 
  485            char startChar = 
',';
 
  487                const QString 
type = node->name() + ((node->classType() == ClassNode::Notification) ? QStringLiteral(
"Notification") : QString());
 
  488                mImpl << 
"    : " << parentClass << 
"(Command::" << 
type << 
")\n";
 
  492            for (
const auto *prop : properties) {
 
  493                auto arg = std::find_if(args.cbegin(), args.cend(), [prop](
const CtorNode::Argument &arg) {
 
  494                    return arg.name == prop->name();
 
  496                if (arg != args.cend()) {
 
  497                    mImpl << 
"    " << startChar << 
" " << prop->mVariableName() << 
"(" << arg->name << 
")\n";
 
  508    mImpl << 
"bool " << node->className() << 
"::operator==(const " << node->className()
 
  509          << 
" &other) const\n" 
  511    mImpl << 
"    return true // simplifies generation\n";
 
  513        mImpl << 
"        && " << parentClass << 
"::operator==(other)\n";
 
  515    for (
const auto *prop : properties) {
 
  516        if (prop->isPointer()) {
 
  517            mImpl << 
"        && *" << prop->mVariableName() << 
" == *other." << prop->mVariableName() << 
"\n";
 
  518        } 
else if (TypeHelper::isContainer(prop->type())) {
 
  519            mImpl << 
"        && containerComparator(" << prop->mVariableName() << 
", other." << prop->mVariableName() << 
")\n";
 
  521            mImpl << 
"        && " << prop->mVariableName() << 
" == other." << prop->mVariableName() << 
"\n";
 
  529    for (
const auto *prop : properties) {
 
  530        if (prop->readOnly()) {
 
  534        if (
auto *
const setter = prop->setter()) {
 
  535            mImpl << 
"void " << node->className() << 
"::" << setter->name << 
"(const " << setter->type
 
  538            if (!setter->append.isEmpty()) {
 
  539                mImpl << 
"    m" << setter->append[0].toUpper() << QStringView(setter->append).mid(1) << 
" << val;\n";
 
  541            if (!setter->remove.isEmpty()) {
 
  542                const QString mVar = QLatin1StringView(
"m") + setter->
remove[0].
toUpper() + QStringView(setter->remove).
mid(1);
 
  543                mImpl << 
"    auto it = std::find(" << mVar << 
".begin(), " << mVar
 
  553            writeImplPropertyDependencies(prop);
 
  555        } 
else if (!prop->dependencies().isEmpty()) {
 
  556            if (TypeHelper::isNumericType(prop->type()) || TypeHelper::isBoolType(prop->type())) {
 
  557                mImpl << 
"void " << node->className() << 
"::" << prop->setterName() << 
"(" << prop->type()
 
  561                      << prop->mVariableName() << 
" = val;\n";
 
  564                mImpl << 
"void " << node->className() << 
"::" << prop->setterName() << 
"(const " << prop->type()
 
  568                      << prop->mVariableName() << 
" = val;\n";
 
  570            writeImplPropertyDependencies(prop);
 
  577    CppHelper::sortMembersForSerialization(serializeProperties);
 
  579    mImpl << 
"DataStream &operator<<(DataStream &stream, const " << node->className()
 
  583        mImpl << 
"    stream << static_cast<const " << parentClass << 
" &>(obj);\n";
 
  585    for (
const auto *prop : std::as_const(serializeProperties)) {
 
  586        writeImplSerializer(prop, 
"<<");
 
  588    mImpl << 
"    return stream;\n" 
  593    mImpl << 
"DataStream &operator>>(DataStream &stream, " << node->className()
 
  597        mImpl << 
"    stream >> static_cast<" << parentClass << 
" &>(obj);\n";
 
  599    for (
const auto *prop : std::as_const(serializeProperties)) {
 
  600        writeImplSerializer(prop, 
">>");
 
  602    mImpl << 
"    return stream;\n" 
  607    mImpl << 
"QDebug operator<<(QDebug dbg, const " << node->className()
 
  611        mImpl << 
"    dbg.noquote() << static_cast<const " << parentClass << 
" &>(obj)\n";
 
  613        mImpl << 
"    dbg.noquote()\n";
 
  616    for (
const auto *prop : std::as_const(serializeProperties)) {
 
  617        if (prop->isPointer()) {
 
  618            mImpl << 
"        << \"" << prop->name() << 
":\" << *obj." << prop->mVariableName() << 
" << \"\\n\"\n";
 
  619        } 
else if (TypeHelper::isContainer(prop->type())) {
 
  620            mImpl << 
"        << \"" << prop->name()
 
  622                     "    for (const auto &type : std::as_const(obj." 
  623                  << prop->mVariableName()
 
  625                     "        dbg.noquote() << \"    \" << ";
 
  626            if (TypeHelper::isPointerType(TypeHelper::containerType(prop->type()))) {
 
  631            mImpl << 
" << \"\\n\";\n" 
  633                     "    dbg.noquote() << \"]\\n\"\n";
 
  635            mImpl << 
"        << \"" << prop->name() << 
":\" << obj." << prop->mVariableName() << 
" << \"\\n\"\n";
 
  644    mImpl << 
"void " << node->className()
 
  645          << 
"::toJson(QJsonObject &json) const\n" 
  648        mImpl << 
"    static_cast<const " << parentClass << 
" *>(this)->toJson(json);\n";
 
  649    } 
else if (serializeProperties.isEmpty()) {
 
  650        mImpl << 
"    Q_UNUSED(json)\n";
 
  652    for (
const auto *prop : std::as_const(serializeProperties)) {
 
  653        if (prop->isPointer()) {
 
  655                     "        QJsonObject jsonObject;\n" 
  657                  << prop->mVariableName()
 
  658                  << 
"->toJson(jsonObject);\n" 
  659                     "        json[QStringLiteral(\"" 
  661                  << 
"\")] = jsonObject;\n" 
  663        } 
else if (TypeHelper::isContainer(prop->type())) {
 
  664            const auto &containerType = TypeHelper::containerType(prop->type());
 
  666                     "        QJsonArray jsonArray;\n" 
  667                     "        for (const auto &type : std::as_const(" 
  668                  << prop->mVariableName() << 
")) {\n";
 
  669            if (TypeHelper::isPointerType(containerType)) {
 
  670                mImpl << 
"            QJsonObject jsonObject;\n" 
  671                         "            type->toJson(jsonObject); /* " 
  674                         "            jsonArray.append(jsonObject);\n";
 
  675            } 
else if (TypeHelper::isNumericType(containerType) || TypeHelper::isBoolType(containerType)) {
 
  676                mImpl << 
"            jsonArray.append(type); /* " << containerType << 
" */\n";
 
  677            } 
else if (containerType == QLatin1StringView(
"QByteArray")) {
 
  678                mImpl << 
"            jsonArray.append(QString::fromUtf8(type)); /* " << containerType << 
"*/\n";
 
  679            } 
else if (TypeHelper::isBuiltInType(containerType)) {
 
  680                if (TypeHelper::containerType(prop->type()) == QLatin1StringView(
"Akonadi::Protocol::ChangeNotification::Relation")) {
 
  681                    mImpl << 
"            QJsonObject jsonObject;\n" 
  682                             "            type.toJson(jsonObject); /* " 
  685                             "            jsonArray.append(jsonObject);\n";
 
  687                    mImpl << 
"            jsonArray.append(type); /* " << containerType << 
" */\n";
 
  690                mImpl << 
"            QJsonObject jsonObject;\n" 
  691                         "            type.toJson(jsonObject); /* " 
  694                         "            jsonArray.append(jsonObject);\n";
 
  697                  << 
"        json[QStringLiteral(\"" << prop->name() << 
"\")] = jsonArray;\n" 
  699        } 
else if (prop->type() == QLatin1StringView(
"uint")) {
 
  700            mImpl << 
"    json[QStringLiteral(\"" << prop->name() << 
"\")] = static_cast<int>(" << prop->mVariableName() << 
");/* " << prop->type() << 
" */\n";
 
  701        } 
else if (TypeHelper::isNumericType(prop->type()) || TypeHelper::isBoolType(prop->type())) {
 
  702            mImpl << 
"    json[QStringLiteral(\"" << prop->name() << 
"\")] = " << prop->mVariableName() << 
";/* " << prop->type() << 
" */\n";
 
  703        } 
else if (TypeHelper::isBuiltInType(prop->type())) {
 
  704            if (prop->type() == QLatin1StringView(
"QStringList")) {
 
  705                mImpl << 
"    json[QStringLiteral(\"" << prop->name() << 
"\")] = QJsonArray::fromStringList(" << prop->mVariableName() << 
");/* " 
  706                      << prop->type() << 
" */\n";
 
  707            } 
else if (prop->type() == QLatin1StringView(
"QDateTime")) {
 
  708                mImpl << 
"    json[QStringLiteral(\"" << prop->name() << 
"\")] = " << prop->mVariableName() << 
".toString()/* " << prop->type() << 
" */;\n";
 
  709            } 
else if (prop->type() == QLatin1StringView(
"QByteArray")) {
 
  710                mImpl << 
"    json[QStringLiteral(\"" << prop->name() << 
"\")] = QString::fromUtf8(" << prop->mVariableName() << 
")/* " << prop->type()
 
  712            } 
else if (prop->type() == QLatin1StringView(
"Scope")) {
 
  714                         "        QJsonObject jsonObject;\n" 
  716                      << prop->mVariableName() << 
".toJson(jsonObject); /* " << prop->type()
 
  718                         "        json[QStringLiteral(\"" 
  719                      << prop->name() << 
"\")] = " 
  722            } 
else if (prop->type() == QLatin1StringView(
"Tristate")) {
 
  723                mImpl << 
"    switch (" << prop->mVariableName()
 
  725                         "    case Tristate::True:\n" 
  726                         "        json[QStringLiteral(\"" 
  728                      << 
"\")] = QStringLiteral(\"True\");\n" 
  730                         "    case Tristate::False:\n" 
  731                         "        json[QStringLiteral(\"" 
  733                      << 
"\")] = QStringLiteral(\"False\");\n" 
  735                         "    case Tristate::Undefined:\n" 
  736                         "        json[QStringLiteral(\"" 
  738                      << 
"\")] = QStringLiteral(\"Undefined\");\n" 
  741            } 
else if (prop->type() == QLatin1StringView(
"Akonadi::Protocol::Attributes")) {
 
  743                         "        QJsonObject jsonObject;\n" 
  745                      << prop->mVariableName()
 
  746                      << 
".constBegin();\n" 
  747                         "        const auto &end = " 
  748                      << prop->mVariableName()
 
  750                         "        while (i != end) {\n" 
  751                         "            jsonObject[QString::fromUtf8(i.key())] = QString::fromUtf8(i.value());\n" 
  754                         "        json[QStringLiteral(\"" 
  756                      << 
"\")] = jsonObject;\n" 
  758            } 
else if (prop->isEnum()) {
 
  759                mImpl << 
"    json[QStringLiteral(\"" << prop->name() << 
"\")] = static_cast<int>(" << prop->mVariableName() << 
");/* " << prop->type()
 
  762                mImpl << 
"    json[QStringLiteral(\"" << prop->name() << 
"\")] = " << prop->mVariableName() << 
";/* " << prop->type() << 
"*/\n";
 
  766                     "         QJsonObject jsonObject;\n" 
  768                  << prop->mVariableName() << 
".toJson(jsonObject); /* " << prop->type()
 
  770                     "         json[QStringLiteral(\"" 
  772                  << 
"\")] = jsonObject;\n" 
  780void CppGenerator::writeImplPropertyDependencies(
const PropertyNode *node)
 
  782    const auto deps = node->dependencies();
 
  786    for (
auto it = deps.cbegin(), end = deps.cend(); it != end; ++it) {
 
  787        if (key != it.key()) {
 
  789            const auto children = node->parent()->children();
 
  790            for (
const auto *child : children) {
 
  791                if (child->type() == Node::Property && child != node) {
 
  792                    const auto *prop = 
static_cast<const PropertyNode *
>(child);
 
  793                    if (prop->name() == key) {
 
  794                        enumType = prop->type();
 
  800                mImpl << 
"    m" << key[0].
toUpper() << QStringView(key).
mid(1) << 
" |= " << enumType << 
"(" << values.
join(QLatin1StringView(
" | ")) << 
");\n";
 
  808        mImpl << 
"    m" << key[0].
toUpper() << QStringView(key).
mid(1) << 
" |= " << enumType << 
"(" << values.
join(QLatin1StringView(
" | ")) << 
");\n";
 
  812bool CppGenerator::generateClass(ClassNode 
const *node)
 
  814    writeHeaderClass(node);
 
  816    mImpl << 
"\n\n/************************* " << node->className() << 
" *************************/\n\n";
 
  817    writeImplClass(node);
 
virtual QString type() const
 
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
 
bool isEmpty() const const
 
bool isEmpty() const const
 
QString mid(qsizetype position, qsizetype n) const const
 
QString & remove(QChar ch, Qt::CaseSensitivity cs)
 
QString toUpper() const const
 
QString join(QChar separator) const const