File indexing completed on 2024-05-05 16:46:04
0001 /* 0002 SPDX-FileCopyrightText: 2010, 2015 Alex Richardson <alex.richardson@gmx.de> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <QString> 0010 #include <QIcon> 0011 #include <memory> 0012 0013 #include <language/duchain/duchain.h> 0014 #include <language/duchain/duchainbase.h> 0015 #include <language/duchain/duchainlock.h> 0016 #include <language/duchain/duchainpointer.h> 0017 0018 0019 namespace KDevelop { 0020 class Declaration; 0021 class DUContext; 0022 } 0023 0024 class OutlineNode 0025 { 0026 Q_DISABLE_COPY(OutlineNode) 0027 void appendContext(KDevelop::DUContext* ctx, KDevelop::TopDUContext* top); 0028 void sortByLocation(bool requiresSorting); 0029 public: 0030 OutlineNode(const QString& text, OutlineNode* parent); 0031 OutlineNode(OutlineNode&& other) Q_DECL_NOEXCEPT; 0032 OutlineNode& operator=(OutlineNode&& other) Q_DECL_NOEXCEPT; 0033 OutlineNode(KDevelop::Declaration* decl, OutlineNode* parent); 0034 OutlineNode(KDevelop::DUContext* ctx, const QString& name, OutlineNode* parent); 0035 virtual ~OutlineNode(); 0036 QIcon icon() const; 0037 QString text() const; 0038 const OutlineNode* parent() const; 0039 const std::vector<OutlineNode>& children() const; 0040 int childCount() const; 0041 const OutlineNode* childAt(int index) const; 0042 int indexOf(const OutlineNode* child) const; 0043 static std::unique_ptr<OutlineNode> fromTopContext(KDevelop::TopDUContext* ctx); 0044 static std::unique_ptr<OutlineNode> dummyNode(); 0045 KDevelop::DUChainBase* duChainObject() const; 0046 friend void swap(OutlineNode& n1, OutlineNode& n2); 0047 private: 0048 QString m_cachedText; 0049 QIcon m_cachedIcon; 0050 KDevelop::DUChainBasePointer m_declOrContext; 0051 OutlineNode* m_parent; 0052 std::vector<OutlineNode> m_children; 0053 }; 0054 0055 inline int OutlineNode::childCount() const 0056 { 0057 return static_cast<int>(m_children.size()); 0058 } 0059 0060 inline const std::vector<OutlineNode>& OutlineNode::children() const 0061 { 0062 return m_children; 0063 } 0064 0065 inline const OutlineNode* OutlineNode::childAt(int index) const 0066 { 0067 return &m_children.at(index); 0068 } 0069 0070 inline const OutlineNode* OutlineNode::parent() const 0071 { 0072 return m_parent; 0073 } 0074 0075 inline int OutlineNode::indexOf(const OutlineNode* child) const 0076 { 0077 const auto max = m_children.size(); 0078 // Comparing the address here is only fine since we never modify the vector after initial creation 0079 for (size_t i = 0; i < max; i++) { 0080 if (child == &m_children[i]) { 0081 return static_cast<int>(i); 0082 } 0083 } 0084 return -1; 0085 } 0086 0087 inline QIcon OutlineNode::icon() const 0088 { 0089 return m_cachedIcon; 0090 } 0091 0092 inline QString OutlineNode::text() const 0093 { 0094 return m_cachedText; 0095 } 0096 0097 inline KDevelop::DUChainBase* OutlineNode::duChainObject() const 0098 { 0099 ENSURE_CHAIN_READ_LOCKED 0100 return m_declOrContext.data(); 0101 } 0102 0103 0104 inline OutlineNode::OutlineNode(OutlineNode&& other) Q_DECL_NOEXCEPT 0105 : m_cachedText(std::move(other.m_cachedText)) 0106 , m_cachedIcon(std::move(other.m_cachedIcon)) 0107 , m_declOrContext(std::move(other.m_declOrContext)) 0108 , m_parent(std::move(other.m_parent)) 0109 , m_children(std::move(other.m_children)) 0110 { 0111 // qDebug("Move ctor %p -> %p", &other, this); 0112 other.m_parent = nullptr; 0113 other.m_declOrContext = nullptr; 0114 for (OutlineNode& child : m_children) { 0115 // when we are moved the parent pointer has to be updated for the children! 0116 child.m_parent = this; 0117 } 0118 } 0119 0120 inline OutlineNode& OutlineNode::operator=(OutlineNode&& other) Q_DECL_NOEXCEPT 0121 { 0122 if (this == &other) { 0123 return *this; 0124 } 0125 m_cachedText = std::move(other.m_cachedText); 0126 m_cachedIcon = std::move(other.m_cachedIcon); 0127 m_declOrContext = std::move(other.m_declOrContext); 0128 m_parent = std::move(other.m_parent); 0129 m_children = std::move(other.m_children); 0130 // qDebug("Move assignment %p -> %p", &other, this); 0131 other.m_parent = nullptr; 0132 other.m_declOrContext = nullptr; 0133 for (OutlineNode& child : m_children) { 0134 // when we are moved the parent pointer has to be updated for the children! 0135 child.m_parent = this; 0136 } 0137 return *this; 0138 } 0139 0140 inline void swap(OutlineNode& n1, OutlineNode& n2) 0141 { 0142 // For some reason std::sort only sometimes calls swap and mostly uses move ctor + assign. 0143 // Probably it uses different algorithms for different sequence sizes 0144 // qDebug("Swapping %p and %p", &n1, &n2); 0145 std::swap(n1.m_cachedText, n2.m_cachedText); 0146 std::swap(n1.m_cachedIcon, n2.m_cachedIcon); 0147 std::swap(n1.m_declOrContext, n2.m_declOrContext); 0148 std::swap(n1.m_parent, n2.m_parent); 0149 std::swap(n1.m_children, n2.m_children); 0150 }