File indexing completed on 2024-05-12 04:38:02
0001 /* 0002 SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> 0003 SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #ifndef KDEVPLATFORM_IDENTIFIER_H 0009 #define KDEVPLATFORM_IDENTIFIER_H 0010 0011 #include <QList> 0012 #include <QMetaType> 0013 #include <QStringView> 0014 0015 #include <util/kdevvarlengtharray.h> 0016 0017 #include <language/languageexport.h> 0018 #include <serialization/referencecounting.h> 0019 0020 //We use shared d-pointers, which is even better than a d-pointer, but krazy probably won't get it, so exclude the test. 0021 //krazy:excludeall=dpointer 0022 0023 class QStringList; 0024 0025 namespace KDevelop { 0026 class IndexedTypeIdentifier; 0027 class Identifier; 0028 class QualifiedIdentifier; 0029 template <bool> 0030 class QualifiedIdentifierPrivate; 0031 template <bool> 0032 class IdentifierPrivate; 0033 class IndexedString; 0034 0035 /** 0036 * @note Move constructor and move assignment operator are deliberately not implemented for 0037 * Indexed[Qualified]Identifier. The move operations are tricky to implement correctly and more 0038 * efficiently in practice than the copy operations. swap() could be specialized for these two 0039 * classes, but it would never be called in practice. See a similar note for class IndexedString. 0040 */ 0041 0042 /** 0043 * A helper-class to store an identifier by index in a type-safe way. 0044 * 0045 * The difference to Identifier is that this class only stores the index of an identifier that is in the repository, without any dynamic 0046 * abilities or access to the contained data. 0047 * 0048 * This class does "disk reference counting" 0049 * 0050 * @warning Do not use this after QCoreApplication::aboutToQuit() has been emitted, items that are not disk-referenced will be invalid at that point. 0051 */ 0052 class KDEVPLATFORMLANGUAGE_EXPORT IndexedIdentifier 0053 : public ReferenceCountManager 0054 { 0055 public: 0056 IndexedIdentifier(); 0057 explicit IndexedIdentifier(const Identifier& id); 0058 IndexedIdentifier(const IndexedIdentifier& rhs) noexcept; 0059 IndexedIdentifier& operator=(const Identifier& id); 0060 IndexedIdentifier& operator=(const IndexedIdentifier& rhs) noexcept; 0061 ~IndexedIdentifier(); 0062 bool operator==(const IndexedIdentifier& rhs) const; 0063 bool operator!=(const IndexedIdentifier& rhs) const; 0064 bool operator==(const Identifier& id) const; 0065 0066 bool isEmpty() const; 0067 0068 Identifier identifier() const; 0069 operator Identifier() const; 0070 0071 unsigned int index() const 0072 { 0073 return m_index; 0074 } 0075 0076 private: 0077 explicit IndexedIdentifier(unsigned int index); 0078 IndexedIdentifier& operator=(unsigned int index); 0079 0080 unsigned int m_index; 0081 }; 0082 0083 /** 0084 * A helper-class to store an identifier by index in a type-safe way. 0085 * 0086 * The difference to QualifiedIdentifier is that this class only stores the index of an identifier that is in the repository, without any dynamic 0087 * abilities or access to the contained data. 0088 * 0089 * This class does "disk reference counting" 0090 * 0091 * @warning Do not use this after QCoreApplication::aboutToQuit() has been emitted, items that are not disk-referenced will be invalid at that point. 0092 */ 0093 class KDEVPLATFORMLANGUAGE_EXPORT IndexedQualifiedIdentifier 0094 : public ReferenceCountManager 0095 { 0096 public: 0097 IndexedQualifiedIdentifier(); 0098 IndexedQualifiedIdentifier(const QualifiedIdentifier& id); 0099 IndexedQualifiedIdentifier(const IndexedQualifiedIdentifier& rhs) noexcept; 0100 IndexedQualifiedIdentifier& operator=(const QualifiedIdentifier& id); 0101 IndexedQualifiedIdentifier& operator=(const IndexedQualifiedIdentifier& id) noexcept; 0102 ~IndexedQualifiedIdentifier(); 0103 bool operator==(const IndexedQualifiedIdentifier& rhs) const; 0104 bool operator==(const QualifiedIdentifier& id) const; 0105 0106 bool operator<(const IndexedQualifiedIdentifier& rhs) const 0107 { 0108 return m_index < rhs.m_index; 0109 } 0110 0111 bool isValid() const; 0112 bool isEmpty() const; 0113 0114 QualifiedIdentifier identifier() const; 0115 operator QualifiedIdentifier() const; 0116 0117 unsigned int index() const 0118 { 0119 return m_index; 0120 } 0121 0122 private: 0123 explicit IndexedQualifiedIdentifier(unsigned int index); 0124 IndexedQualifiedIdentifier& operator=(unsigned int index); 0125 unsigned int m_index; 0126 }; 0127 0128 /** 0129 * Flags to control the string representation of identifiers. 0130 */ 0131 enum IdentifierStringFormattingOption { 0132 NoOptions = 0x0, 0133 0134 /// Removes explicit global prefix from the result. 0135 /// When enabled, global identifiers will be formatted as "globalIdentifierFormattedString" 0136 /// instead "::globalIdentifierFormattedString". 0137 RemoveExplicitlyGlobalPrefix = 0x1, 0138 0139 /// Removes template information from the result. 0140 /// When enabled, TemplateClass< someDataType > will be formatted as plain "TemplateClass". 0141 RemoveTemplateInformation = 0x2 0142 }; 0143 Q_DECLARE_FLAGS(IdentifierStringFormattingOptions, IdentifierStringFormattingOption) 0144 0145 /** 0146 * Represents a single unqualified identifier 0147 */ 0148 class KDEVPLATFORMLANGUAGE_EXPORT Identifier 0149 { 0150 friend class QualifiedIdentifier; 0151 0152 public: 0153 /** 0154 * @param start The position in the given string where to start searching for the identifier. (optional) 0155 * @param takenRange If this is nonzero, it will be filled with the length of the range from the beginning 0156 * of the given string, that was used to construct this identifier. (optional) 0157 * 0158 * @warning The identifier is parsed in a C++-similar way, and the result may not be what you expect. 0159 * If you want to prevent that parsing, use the constructor that takes IndexedString. 0160 */ 0161 explicit Identifier(QStringView str, uint start = 0, uint* takenRange = nullptr); 0162 explicit Identifier(const QString& str, uint start = 0, uint* takenRange = nullptr) 0163 : Identifier(QStringView{str}, start, takenRange) 0164 { 0165 } 0166 0167 /** 0168 * Preferred constructor, use this if you already have an IndexedString available. This does not decompose the given string. 0169 */ 0170 explicit Identifier(const IndexedString& str); 0171 Identifier(const Identifier& rhs); 0172 explicit Identifier(uint index); 0173 Identifier(); 0174 Identifier(Identifier&& rhs) Q_DECL_NOEXCEPT; 0175 ~Identifier(); 0176 Identifier& operator=(const Identifier& rhs); 0177 Identifier& operator=(Identifier&& rhs) Q_DECL_NOEXCEPT; 0178 0179 static Identifier unique(int token); 0180 0181 bool isUnique() const; 0182 int uniqueToken() const; 0183 /** 0184 * If \a token is non-zero, turns this Identifier into the special per-document unique identifier. 0185 * 0186 * This is used e.g. for anonymous namespaces. 0187 * 0188 * Pass a token which is specific to the document to allow correct equality comparison. 0189 */ 0190 void setUnique(int token); 0191 0192 const IndexedString identifier() const; 0193 void setIdentifier(QStringView identifier); 0194 /** 0195 * Should be preferred over the other version 0196 */ 0197 void setIdentifier(const IndexedString& identifier); 0198 0199 uint hash() const; 0200 0201 /** 0202 * Comparison ignoring the template-identifiers 0203 */ 0204 bool nameEquals(const Identifier& rhs) const; 0205 0206 /** 0207 * @warning This is expensive. 0208 */ 0209 IndexedTypeIdentifier templateIdentifier(int num) const; 0210 uint templateIdentifiersCount() const; 0211 void appendTemplateIdentifier(const IndexedTypeIdentifier& identifier); 0212 void clearTemplateIdentifiers(); 0213 void setTemplateIdentifiers(const QList<IndexedTypeIdentifier>& templateIdentifiers); 0214 0215 QString toString(IdentifierStringFormattingOptions options = NoOptions) const; 0216 0217 /** 0218 * Whether this identifier begins with an underscore followed by a capital letter or by another underscore. 0219 */ 0220 bool isReserved() const; 0221 0222 bool operator==(const Identifier& rhs) const; 0223 bool operator!=(const Identifier& rhs) const; 0224 0225 bool isEmpty() const; 0226 0227 /** 0228 * @return a unique index within the global identifier repository for this identifier. 0229 * 0230 * If the identifier isn't in the repository yet, it is added to the repository. 0231 */ 0232 uint index() const; 0233 0234 bool inRepository() const; 0235 0236 private: 0237 void makeConstant() const; 0238 void prepareWrite(); 0239 0240 //Only one of the following pointers is valid at a given time 0241 mutable uint m_index; //Valid if cd is valid 0242 union { 0243 mutable IdentifierPrivate<true>* dd; //Dynamic, owned by this identifier 0244 mutable const IdentifierPrivate<false>* cd; //Constant, owned by the repository 0245 }; 0246 }; 0247 0248 /** 0249 * Represents a qualified identifier 0250 * 0251 * QualifiedIdentifier has it's hash-values stored, so using the hash-values is very efficient. 0252 */ 0253 class KDEVPLATFORMLANGUAGE_EXPORT QualifiedIdentifier 0254 { 0255 public: 0256 explicit QualifiedIdentifier(QStringView id, bool isExpression = false); 0257 explicit QualifiedIdentifier(const QString& id, bool isExpression = false) 0258 : QualifiedIdentifier(QStringView{id}, isExpression) 0259 { 0260 } 0261 0262 explicit QualifiedIdentifier(const Identifier& id); 0263 QualifiedIdentifier(const QualifiedIdentifier& id); 0264 explicit QualifiedIdentifier(uint index); 0265 QualifiedIdentifier(); 0266 QualifiedIdentifier(QualifiedIdentifier&& rhs) Q_DECL_NOEXCEPT; 0267 ~QualifiedIdentifier(); 0268 QualifiedIdentifier& operator=(const QualifiedIdentifier& rhs); 0269 QualifiedIdentifier& operator=(QualifiedIdentifier&& rhs) Q_DECL_NOEXCEPT; 0270 0271 /** 0272 * Append @p id to this qualified identifier. 0273 */ 0274 void push(const IndexedIdentifier& id); 0275 /** 0276 * Append @p id to this qualified identifier. 0277 * 0278 * NOTE: If you have an indexed identifier available, use the above method instead. 0279 */ 0280 void push(const Identifier& id); 0281 /** 0282 * Append all identifiers of @p id to this qualified identifier. 0283 */ 0284 void push(const QualifiedIdentifier& id); 0285 0286 /** 0287 * Pops one identifier from back: 0288 */ 0289 void pop(); 0290 void clear(); 0291 bool isEmpty() const; 0292 int count() const; 0293 Identifier first() const; 0294 IndexedIdentifier indexedFirst() const; 0295 Identifier last() const; 0296 IndexedIdentifier indexedLast() const; 0297 Identifier top() const; 0298 Identifier at(int i) const; 0299 IndexedIdentifier indexedAt(int i) const; 0300 /** 0301 * @param pos Position where to start the copy. 0302 * @param len If this is -1, the whole following part will be returned. 0303 */ 0304 QualifiedIdentifier mid(int pos, int len = -1) const; 0305 0306 /** 0307 * Copy the leftmost \a len number of identifiers. 0308 * 0309 * @param len The number of identifiers to copy, or if negative, the number of identifiers to omit from the right 0310 */ 0311 inline QualifiedIdentifier left(int len) const 0312 { 0313 return mid(0, len > 0 ? len : count() + len); 0314 } 0315 0316 ///@todo Remove this flag 0317 bool explicitlyGlobal() const; 0318 void setExplicitlyGlobal(bool eg); 0319 bool isQualified() const; 0320 0321 /** 0322 * A flag that can be set by setIsExpression 0323 */ 0324 bool isExpression() const; 0325 /** 0326 * Set the expression-flag, that can be retrieved by isExpression(). 0327 * This flag is not respected while creating the hash-value and while operator==() comparison. 0328 * It is respected while isSame(..) comparison. 0329 */ 0330 void setIsExpression(bool); 0331 0332 QString toString(IdentifierStringFormattingOptions options = NoOptions) const; 0333 QStringList toStringList(IdentifierStringFormattingOptions options = NoOptions) const; 0334 0335 QualifiedIdentifier operator+(const QualifiedIdentifier& rhs) const; 0336 QualifiedIdentifier& operator+=(const QualifiedIdentifier& rhs); 0337 0338 /** 0339 * Nicer interfaces to merge 0340 */ 0341 QualifiedIdentifier operator+(const Identifier& rhs) const; 0342 QualifiedIdentifier& operator+=(const Identifier& rhs); 0343 0344 QualifiedIdentifier operator+(const IndexedIdentifier& rhs) const; 0345 QualifiedIdentifier& operator+=(const IndexedIdentifier& rhs); 0346 0347 /** 0348 * @return a QualifiedIdentifier with this one appended to the other. 0349 * 0350 * It is explicitly global if either this or base is. 0351 */ 0352 QualifiedIdentifier merge(const QualifiedIdentifier& base) const; 0353 0354 /** 0355 * The comparison-operators do not respect explicitlyGlobal and isExpression, they only respect the real scope. 0356 * This is for convenient use in hash-tables etc. 0357 */ 0358 bool operator==(const QualifiedIdentifier& rhs) const; 0359 bool operator!=(const QualifiedIdentifier& rhs) const; 0360 0361 bool beginsWith(const QualifiedIdentifier& other) const; 0362 0363 uint index() const; 0364 0365 /** 0366 * @return true if this qualified identifier is already in the persistent identifier repository 0367 */ 0368 bool inRepository() const; 0369 0370 /** 0371 * The hash does not respect explicitlyGlobal, only the real scope. 0372 */ 0373 uint hash() const; 0374 0375 protected: 0376 bool sameIdentifiers(const QualifiedIdentifier& rhs) const; 0377 0378 void makeConstant() const; 0379 void prepareWrite(); 0380 0381 mutable uint m_index; 0382 union { 0383 mutable QualifiedIdentifierPrivate<true>* dd; 0384 mutable const QualifiedIdentifierPrivate<false>* cd; 0385 }; 0386 }; 0387 0388 /** 0389 * Extends IndexedQualifiedIdentifier by: 0390 * - Arbitrary count of pointer-poperators with cv-qualifiers 0391 * - Reference operator 0392 * All the properties set here are respected in the hash value. 0393 */ 0394 class KDEVPLATFORMLANGUAGE_EXPORT IndexedTypeIdentifier 0395 { 0396 public: 0397 /** 0398 * Variables like pointerDepth, isReference, etc. are not parsed from the string, so this parsing is quite limited. 0399 */ 0400 explicit IndexedTypeIdentifier(const IndexedQualifiedIdentifier& identifier = IndexedQualifiedIdentifier()); 0401 explicit IndexedTypeIdentifier(QStringView identifer, bool isExpression = false); 0402 0403 bool isReference() const; 0404 void setIsReference(bool); 0405 0406 bool isRValue() const; 0407 void setIsRValue(bool); 0408 0409 bool isConstant() const; 0410 void setIsConstant(bool); 0411 0412 bool isVolatile() const; 0413 void setIsVolatile(bool); 0414 0415 IndexedQualifiedIdentifier identifier() const; 0416 0417 void setIdentifier(const IndexedQualifiedIdentifier& id); 0418 0419 /** 0420 * @return the pointer depth. Example for C++: "char*" has pointer-depth 1, "char***" has pointer-depth 3 0421 */ 0422 int pointerDepth() const; 0423 /** 0424 * Sets the pointer-depth to the specified count. 0425 * 0426 * When the pointer-depth is increased, the "isConstPointer" values for new depths will be initialized with false. 0427 * 0428 * For efficiency-reasons the maximum currently is 23. 0429 */ 0430 void setPointerDepth(int); 0431 0432 /** 0433 * Whether the target of pointer 'depthNumber' is constant 0434 */ 0435 bool isConstPointer(int depthNumber) const; 0436 void setIsConstPointer(int depthNumber, bool constant); 0437 0438 QString toString(IdentifierStringFormattingOptions options = NoOptions) const; 0439 0440 uint hash() const; 0441 0442 /** 0443 * The comparison-operators do not respect explicitlyGlobal and isExpression, they only respect the real scope. 0444 * This is for convenient use in hash-tables etc. 0445 */ 0446 bool operator==(const IndexedTypeIdentifier& rhs) const; 0447 bool operator!=(const IndexedTypeIdentifier& rhs) const; 0448 0449 private: 0450 IndexedQualifiedIdentifier m_identifier; 0451 // The overall number of bits shared by these bit-fields should not exceed 32, 0452 // so that we don't waste space. IndexedTypeIdentifer should be as compact as possible. 0453 bool m_isConstant : 1; 0454 bool m_isReference : 1; 0455 bool m_isRValue : 1; 0456 bool m_isVolatile : 1; 0457 uint m_pointerDepth : 5; 0458 uint m_pointerConstMask : 23; 0459 }; 0460 0461 KDEVPLATFORMLANGUAGE_EXPORT uint qHash(const IndexedTypeIdentifier& id); 0462 KDEVPLATFORMLANGUAGE_EXPORT uint qHash(const QualifiedIdentifier& id); 0463 KDEVPLATFORMLANGUAGE_EXPORT uint qHash(const Identifier& id); 0464 0465 inline uint qHash(const IndexedIdentifier& id) 0466 { 0467 return id.index(); 0468 } 0469 0470 inline uint qHash(const IndexedQualifiedIdentifier& id) 0471 { 0472 return id.index(); 0473 } 0474 } 0475 0476 Q_DECLARE_TYPEINFO(KDevelop::IndexedTypeIdentifier, Q_MOVABLE_TYPE); 0477 Q_DECLARE_TYPEINFO(KDevelop::IndexedQualifiedIdentifier, Q_MOVABLE_TYPE); 0478 Q_DECLARE_TYPEINFO(KDevelop::IndexedIdentifier, Q_MOVABLE_TYPE); 0479 Q_DECLARE_METATYPE(KDevelop::IndexedQualifiedIdentifier) 0480 Q_DECLARE_METATYPE(KDevelop::IndexedIdentifier) 0481 0482 Q_DECLARE_TYPEINFO(KDevelop::QualifiedIdentifier, Q_MOVABLE_TYPE); 0483 Q_DECLARE_TYPEINFO(KDevelop::Identifier, Q_MOVABLE_TYPE); 0484 Q_DECLARE_METATYPE(KDevelop::QualifiedIdentifier) 0485 Q_DECLARE_METATYPE(KDevelop::Identifier) 0486 0487 /** 0488 * {q,k}Debug() stream operator: Writes the Identifier to the debug output. 0489 */ 0490 KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug s, const KDevelop::Identifier& identifier); 0491 0492 /** 0493 * {q,k}Debug() stream operator: Writes the QualifiedIdentifier to the debug output. 0494 */ 0495 KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug s, const KDevelop::QualifiedIdentifier& identifier); 0496 0497 #endif // KDEVPLATFORM_IDENTIFIER_H