File indexing completed on 2024-11-10 04:40:46

0001 /*
0002     SPDX-FileCopyrightText: 2017 Daniel Vrátil <dvratil@kde.og>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "nodetree.h"
0008 #include "cpphelper.h"
0009 #include "typehelper.h"
0010 
0011 namespace
0012 {
0013 
0014 QString qualifiedName(const Node *node)
0015 {
0016     if (node->type() == Node::Class) {
0017         return static_cast<const ClassNode *>(node)->className();
0018     }
0019     if (node->type() == Node::Enum) {
0020         auto enumNode = static_cast<const EnumNode *>(node);
0021         if (enumNode->enumType() == EnumNode::TypeFlag) {
0022             return QStringLiteral("%1::%2").arg(qualifiedName(node->parent()), enumNode->flagsName());
0023         }
0024         return QStringLiteral("%1::%2").arg(qualifiedName(node->parent()), enumNode->name());
0025     }
0026 
0027     Q_ASSERT_X(false, "qualifiedName", "Invalid node type");
0028     return {};
0029 }
0030 
0031 } // namespace
0032 
0033 Node::Node(NodeType type, Node *parent)
0034     : mParent(parent)
0035     , mType(type)
0036 {
0037     if (parent) {
0038         parent->appendNode(this);
0039     }
0040 }
0041 
0042 Node::~Node()
0043 {
0044     qDeleteAll(mChildren);
0045 }
0046 
0047 Node::NodeType Node::type() const
0048 {
0049     return mType;
0050 }
0051 
0052 Node *Node::parent() const
0053 {
0054     return mParent;
0055 }
0056 
0057 void Node::appendNode(Node *child)
0058 {
0059     child->mParent = this;
0060     mChildren.push_back(child);
0061 }
0062 
0063 const QList<Node const *> &Node::children() const
0064 {
0065     return mChildren;
0066 }
0067 
0068 DocumentNode::DocumentNode(int version)
0069     : Node(Document, nullptr)
0070     , mVersion(version)
0071 {
0072 }
0073 
0074 int DocumentNode::version() const
0075 {
0076     return mVersion;
0077 }
0078 
0079 ClassNode::ClassNode(const QString &name, ClassType type, DocumentNode *parent)
0080     : Node(Node::Class, parent)
0081     , mName(name)
0082     , mClassType(type)
0083 {
0084 }
0085 
0086 QString ClassNode::name() const
0087 {
0088     return mName;
0089 }
0090 
0091 ClassNode::ClassType ClassNode::classType() const
0092 {
0093     return mClassType;
0094 }
0095 
0096 QString ClassNode::className() const
0097 {
0098     switch (mClassType) {
0099     case Class:
0100         return mName;
0101     case Command:
0102         return mName + QStringLiteral("Command");
0103     case Response:
0104         return mName + QStringLiteral("Response");
0105     case Notification:
0106         return mName + QStringLiteral("Notification");
0107     default:
0108         Q_ASSERT(false);
0109         return QString();
0110     }
0111 }
0112 
0113 QString ClassNode::parentClassName() const
0114 {
0115     switch (mClassType) {
0116     case Class:
0117         return QString();
0118     case Command:
0119         return QStringLiteral("Command");
0120     case Response:
0121         return QStringLiteral("Response");
0122     case Notification:
0123         return QStringLiteral("ChangeNotification");
0124     case Invalid:
0125         Q_ASSERT(false);
0126         return QString();
0127     }
0128     Q_UNREACHABLE();
0129 }
0130 
0131 ClassNode::ClassType ClassNode::elementNameToType(QStringView name)
0132 {
0133     if (name == QLatin1StringView("class")) {
0134         return Class;
0135     } else if (name == QLatin1StringView("command")) {
0136         return Command;
0137     } else if (name == QLatin1StringView("response")) {
0138         return Response;
0139     } else if (name == QLatin1StringView("notification")) {
0140         return Notification;
0141     } else {
0142         return Invalid;
0143     }
0144 }
0145 
0146 QList<PropertyNode const *> ClassNode::properties() const
0147 {
0148     QList<const PropertyNode *> rv;
0149     for (const auto node : std::as_const(mChildren)) {
0150         if (node->type() == Node::Property) {
0151             rv << static_cast<PropertyNode const *>(node);
0152         }
0153     }
0154     CppHelper::sortMembers(rv);
0155     return rv;
0156 }
0157 
0158 CtorNode::CtorNode(const QList<Argument> &args, ClassNode *parent)
0159     : Node(Ctor, parent)
0160     , mArgs(args)
0161 {
0162 }
0163 
0164 CtorNode::~CtorNode()
0165 {
0166 }
0167 
0168 QList<CtorNode::Argument> CtorNode::arguments() const
0169 {
0170     return mArgs;
0171 }
0172 
0173 void CtorNode::setArgumentType(const QString &name, const QString &type)
0174 {
0175     for (auto &arg : mArgs) {
0176         if (arg.name == name) {
0177             arg.type = type;
0178             break;
0179         }
0180     }
0181 }
0182 
0183 EnumNode::EnumNode(const QString &name, EnumType type, ClassNode *parent)
0184     : Node(Enum, parent)
0185     , mName(name)
0186     , mEnumType(type)
0187 {
0188 }
0189 
0190 QString EnumNode::name() const
0191 {
0192     return mName;
0193 }
0194 
0195 EnumNode::EnumType EnumNode::enumType() const
0196 {
0197     return mEnumType;
0198 }
0199 
0200 QString EnumNode::flagsName() const
0201 {
0202     if (mEnumType == TypeFlag) {
0203         return mName + QStringLiteral("s");
0204     }
0205 
0206     return {};
0207 }
0208 
0209 EnumNode::EnumType EnumNode::elementNameToType(QStringView name)
0210 {
0211     if (name == QLatin1StringView("enum")) {
0212         return TypeEnum;
0213     } else if (name == QLatin1StringView("flag")) {
0214         return TypeFlag;
0215     } else {
0216         return TypeInvalid;
0217     }
0218 }
0219 
0220 EnumValueNode::EnumValueNode(const QString &name, EnumNode *parent)
0221     : Node(EnumValue, parent)
0222     , mName(name)
0223     , mValue()
0224 {
0225 }
0226 
0227 QString EnumValueNode::name() const
0228 {
0229     return mName;
0230 }
0231 
0232 void EnumValueNode::setValue(const QString &value)
0233 {
0234     mValue = value;
0235 }
0236 
0237 QString EnumValueNode::value() const
0238 {
0239     return mValue;
0240 }
0241 
0242 PropertyNode::PropertyNode(const QString &name, const QString &type, ClassNode *parent)
0243     : Node(Property, parent)
0244     , mName(name)
0245     , mType(type)
0246     , mSetter(nullptr)
0247     , mReadOnly(false)
0248     , mAsReference(false)
0249 {
0250 }
0251 
0252 PropertyNode::~PropertyNode()
0253 {
0254     delete mSetter;
0255 }
0256 
0257 QString PropertyNode::type() const
0258 {
0259     return mType;
0260 }
0261 
0262 QString PropertyNode::name() const
0263 {
0264     return mName;
0265 }
0266 
0267 void PropertyNode::setDefaultValue(const QString &defaultValue)
0268 {
0269     mDefaultValue = defaultValue;
0270 }
0271 
0272 QString PropertyNode::defaultValue() const
0273 {
0274     return mDefaultValue;
0275 }
0276 
0277 bool PropertyNode::readOnly() const
0278 {
0279     return mReadOnly;
0280 }
0281 
0282 void PropertyNode::setReadOnly(bool readOnly)
0283 {
0284     mReadOnly = readOnly;
0285 }
0286 
0287 bool PropertyNode::asReference() const
0288 {
0289     return mAsReference;
0290 }
0291 
0292 void PropertyNode::setAsReference(bool asReference)
0293 {
0294     mAsReference = asReference;
0295 }
0296 
0297 bool PropertyNode::isPointer() const
0298 {
0299     return TypeHelper::isPointerType(mType);
0300 }
0301 
0302 bool PropertyNode::isEnum() const
0303 {
0304     auto parentClass = static_cast<ClassNode *>(parent());
0305     for (const auto node : parentClass->children()) {
0306         if (node->type() == Node::Enum) {
0307             const auto enumNode = static_cast<const EnumNode *>(node);
0308             if (qualifiedName(enumNode) == mType) {
0309                 return true;
0310             }
0311         }
0312     }
0313 
0314     return false;
0315 }
0316 
0317 QMultiMap<QString, QString> PropertyNode::dependencies() const
0318 {
0319     return mDepends;
0320 }
0321 
0322 void PropertyNode::addDependency(const QString &enumVar, const QString &enumValue)
0323 {
0324     mDepends.insert(enumVar, enumValue);
0325 }
0326 
0327 void PropertyNode::setSetter(Setter *setter)
0328 {
0329     mSetter = setter;
0330 }
0331 
0332 PropertyNode::Setter *PropertyNode::setter() const
0333 {
0334     return mSetter;
0335 }
0336 
0337 QString PropertyNode::mVariableName() const
0338 {
0339     return QStringLiteral("m") + mName[0].toUpper() + QStringView(mName).mid(1);
0340 }
0341 
0342 QString PropertyNode::setterName() const
0343 {
0344     return QStringLiteral("set") + mName[0].toUpper() + QStringView(mName).mid(1);
0345 }