| 242 | } |
| 243 | |
| 244 | QueryTreeNodePtr IQueryTreeNode::cloneAndReplace(const ReplacementMap & replacement_map) const |
| 245 | { |
| 246 | /** Clone tree with this node as root. |
| 247 | * |
| 248 | * Algorithm |
| 249 | * For each node we clone state and also create mapping old pointer to new pointer. |
| 250 | * For each cloned node we update weak pointers array. |
| 251 | * |
| 252 | * After that we can update pointer in weak pointers array using old pointer to new pointer mapping. |
| 253 | */ |
| 254 | std::unordered_map<const IQueryTreeNode *, QueryTreeNodePtr> old_pointer_to_new_pointer; |
| 255 | std::vector<QueryTreeNodeWeakPtr *> weak_pointers_to_update_after_clone; |
| 256 | |
| 257 | QueryTreeNodePtr result_cloned_node_place; |
| 258 | |
| 259 | std::vector<std::pair<const IQueryTreeNode *, QueryTreeNodePtr *>> nodes_to_clone; |
| 260 | nodes_to_clone.emplace_back(this, &result_cloned_node_place); |
| 261 | |
| 262 | while (!nodes_to_clone.empty()) |
| 263 | { |
| 264 | const auto [node_to_clone, place_for_cloned_node] = nodes_to_clone.back(); |
| 265 | nodes_to_clone.pop_back(); |
| 266 | |
| 267 | auto already_cloned_node_it = old_pointer_to_new_pointer.find(node_to_clone); |
| 268 | if (already_cloned_node_it != old_pointer_to_new_pointer.end()) |
| 269 | { |
| 270 | *place_for_cloned_node = already_cloned_node_it->second; |
| 271 | continue; |
| 272 | } |
| 273 | |
| 274 | auto it = replacement_map.find(node_to_clone); |
| 275 | auto node_clone = it != replacement_map.end() ? it->second : node_to_clone->cloneImpl(); |
| 276 | *place_for_cloned_node = node_clone; |
| 277 | |
| 278 | old_pointer_to_new_pointer.emplace(node_to_clone, node_clone); |
| 279 | |
| 280 | if (it != replacement_map.end()) |
| 281 | continue; |
| 282 | |
| 283 | node_clone->original_ast = node_to_clone->original_ast; |
| 284 | node_clone->setAlias(node_to_clone->alias); |
| 285 | node_clone->parenthesized = node_to_clone->parenthesized; |
| 286 | node_clone->children = node_to_clone->children; |
| 287 | node_clone->weak_pointers = node_to_clone->weak_pointers; |
| 288 | |
| 289 | for (auto & child : node_clone->children) |
| 290 | { |
| 291 | if (!child) |
| 292 | continue; |
| 293 | |
| 294 | nodes_to_clone.emplace_back(child.get(), &child); |
| 295 | } |
| 296 | |
| 297 | for (auto & weak_pointer : node_clone->weak_pointers) |
| 298 | { |
| 299 | weak_pointers_to_update_after_clone.push_back(&weak_pointer); |
| 300 | } |
| 301 | } |
no test coverage detected