File indexing completed on 2024-05-12 04:37:46
0001 /* 0002 SPDX-FileCopyrightText: 2008 Hamish Rodda <rodda@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #ifndef KDEVPLATFORM_ASTCHANGESET_H 0008 #define KDEVPLATFORM_ASTCHANGESET_H 0009 0010 #include <QVariant> 0011 0012 namespace KDevelop { 0013 template <typename AstNode> 0014 class AstChangeSet; 0015 0016 class AstChange; 0017 0018 /** 0019 * \short A reference to an existing read-only AST node. 0020 * 0021 * This class represents an AST node, and allows changes to be planned 0022 * for that node. 0023 * 0024 * \warning you must not create cyclic references. 0025 * 0026 * \author Hamish Rodda <rodda@kde.org> 0027 */ 0028 template <typename AstNode> 0029 class AstNodeRef 0030 { 0031 friend class AstChangeSet<AstNode>; 0032 0033 public: 0034 /// Destructor. 0035 virtual ~AstNodeRef() 0036 { 0037 qDeleteAll(m_changes); 0038 0039 if (m_newNode) 0040 delete m_node; 0041 } 0042 0043 using AstNodeList = QList<AstNodeRef*>; 0044 0045 /** 0046 * \short Container class for a change to an AST node. 0047 * 0048 * \author Hamish Rodda <rodda@kde.org> 0049 */ 0050 class AstChange 0051 { 0052 public: 0053 enum ChangeTypes { 0054 ListRewrite, 0055 ListClear, 0056 ItemReplace, 0057 ItemMove 0058 }; 0059 0060 explicit AstChange(ChangeTypes t) 0061 : type(t) 0062 , newNode(0) 0063 , listOffset(-1) 0064 , newValue(-1) 0065 { 0066 } 0067 0068 ChangeTypes type; 0069 // The index of the item in the node to be changed 0070 int nodeIndex; 0071 0072 // The new node to occupy this position, if relevant 0073 AstNodeRef* newNode; 0074 // The list of nodes to occupy this position, if relevant 0075 AstNodeList newList; 0076 // The position to apply the node(s) in the list, if relevant 0077 int listOffset; 0078 // The value of the position, if relevant 0079 QVariant newValue; 0080 }; 0081 0082 virtual const AstNode* node() const 0083 { 0084 return m_newNode ? 0 : m_node; 0085 } 0086 0087 virtual AstNodeRef* nodeRef() const 0088 { 0089 return m_nodeRef; 0090 } 0091 0092 virtual AstNode* newNode() const 0093 { 0094 return m_newNode ? m_node : 0; 0095 } 0096 0097 const QList<AstChange*>& changes() const 0098 { 0099 return m_changes; 0100 } 0101 0102 /// Adds a change to this node reference. Takes ownership of the \a change. 0103 AstChange* newChange(AstChange* change) 0104 { 0105 m_changes.append(change); 0106 return change; 0107 } 0108 0109 /// Removes a change from this node reference, and deletes it. 0110 void deleteChange(AstChange* change) 0111 { 0112 Q_ASSERT(m_changes.contains(change)); 0113 m_changes.removeAll(change); 0114 delete change; 0115 } 0116 0117 protected: 0118 /// Default constructor. \todo is this needed? 0119 AstNodeRef(AstChangeSet<AstNode>* set) 0120 : m_changeSet(set) 0121 , m_node(0) 0122 , m_nodeRef(0) 0123 , m_newNode(false) 0124 { 0125 } 0126 0127 /// Constructor. Either takes an existing \a node (\a newNode = false), or a newly created \a node (\a newNode = true) 0128 AstNodeRef(AstChangeSet<AstNode>* set, AstNode* node, bool newNode) 0129 : m_changeSet(set) 0130 , m_node(node) 0131 , m_nodeRef(0) 0132 , m_newNode(newNode) 0133 { 0134 } 0135 0136 /// Constructor. Takes another node reference. 0137 AstNodeRef(AstChangeSet<AstNode>* set, AstNodeRef* original) 0138 : m_changeSet(set) 0139 , m_node(0) 0140 , m_nodeRef(original) 0141 , m_newNode(false) 0142 { 0143 } 0144 0145 AstNode* m_nodeChanges; 0146 0147 private: 0148 AstChangeSet<AstNode>* m_changeSet; 0149 AstNode* m_node; 0150 AstNodeRef* m_nodeRef; 0151 bool m_newNode; 0152 0153 QList<AstChange*> m_changes; 0154 }; 0155 0156 /** 0157 * \short A set of changes to an AST. 0158 * 0159 * This class holds a set of all changes to an AST. 0160 * 0161 * \author Hamish Rodda <rodda@kde.org> 0162 */ 0163 template <typename AstNode> 0164 class AstChangeSet 0165 { 0166 public: 0167 /** 0168 * Constructor. 0169 * 0170 * \param topNode the top node of the read-only Ast to modify, or set to null if creating 0171 * a new Ast from scratch. 0172 */ 0173 AstChangeSet(const AstNode* topNode = 0) 0174 : m_topNode(topNode) 0175 { 0176 } 0177 0178 /** 0179 * Destructor, deletes all nodes owned by this change set. 0180 */ 0181 virtual ~AstChangeSet() 0182 { 0183 qDeleteAll(m_nodeRefs); 0184 } 0185 0186 /** 0187 * Register a new node that you have created to insert at some point in this Ast. 0188 * You may modify this node directly. The change set takes ownership, so that 0189 * the new node will be deleted when the change set is no longer needed. 0190 * 0191 * \returns the new node that has been registered. 0192 */ 0193 AstNodeRef<AstNode>* registerNewNode(AstNode* node) 0194 { 0195 AstNodeRef<AstNode>* newRef = new AstNodeRef<AstNode>(this, node, true); 0196 m_nodeRefs.append(newRef); 0197 return newRef; 0198 } 0199 0200 /** 0201 * Create a blank reference to a node. 0202 * 0203 * The change set takes ownership, so that 0204 * the new node will be deleted when the change set is no longer needed. 0205 * 0206 * \returns the new node reference 0207 */ 0208 AstNodeRef<AstNode>* registerNewRef(AstNodeRef<AstNode>* ref) 0209 { 0210 m_nodeRefs.append(ref); 0211 return ref; 0212 } 0213 0214 /** 0215 * Copy an existing node (whether from the Ast or from the change set). 0216 * 0217 * You may then modify this reference, and the modifications will be applied to the node when the change set is finalised. 0218 * 0219 * \returns a copy of \a source, which you may modify directly. 0220 */ 0221 AstNodeRef<AstNode>* copyNode(AstNode* source) 0222 { 0223 AstNodeRef<AstNode>* newRef = new AstNodeRef<AstNode>(this, source, false); 0224 m_nodeRefs.append(newRef); 0225 return newRef; 0226 } 0227 0228 private: 0229 const AstNode* m_topNode; 0230 QList<AstNodeRef<AstNode>*> m_nodeRefs; 0231 }; 0232 } 0233 0234 #endif // KDEVPLATFORM_ASTCHANGESET_H