File: identifier.h

package info (click to toggle)
kdevelop 4%3A22.12.2-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 70,096 kB
  • sloc: cpp: 284,635; javascript: 3,558; python: 3,422; sh: 1,319; ansic: 685; xml: 331; php: 95; lisp: 66; makefile: 39; sed: 12
file content (492 lines) | stat: -rw-r--r-- 16,405 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
/*
    SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
    SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>

    SPDX-License-Identifier: LGPL-2.0-only
*/

#ifndef KDEVPLATFORM_IDENTIFIER_H
#define KDEVPLATFORM_IDENTIFIER_H

#include <QList>
#include <QMetaType>
#include <QStringView>

#include <util/kdevvarlengtharray.h>

#include <language/languageexport.h>
#include <serialization/referencecounting.h>

//We use shared d-pointers, which is even better than a d-pointer, but krazy probably won't get it, so exclude the test.
//krazy:excludeall=dpointer

class QStringList;

namespace KDevelop {
class IndexedTypeIdentifier;
class Identifier;
class QualifiedIdentifier;
template <bool>
class QualifiedIdentifierPrivate;
template <bool>
class IdentifierPrivate;
class IndexedString;

/**
 * @note Move constructor and move assignment operator are deliberately not implemented for
 * Indexed[Qualified]Identifier. The move operations are tricky to implement correctly and more
 * efficiently in practice than the copy operations. swap() could be specialized for these two
 * classes, but it would never be called in practice. See a similar note for class IndexedString.
 */

/**
 * A helper-class to store an identifier by index in a type-safe way.
 *
 * The difference to Identifier is that this class only stores the index of an identifier that is in the repository, without any dynamic
 * abilities or access to the contained data.
 *
 * This class does "disk reference counting"
 *
 * @warning Do not use this after QCoreApplication::aboutToQuit() has been emitted, items that are not disk-referenced will be invalid at that point.
 */
class KDEVPLATFORMLANGUAGE_EXPORT IndexedIdentifier
    : public ReferenceCountManager
{
public:
    IndexedIdentifier();
    explicit IndexedIdentifier(const Identifier& id);
    IndexedIdentifier(const IndexedIdentifier& rhs) noexcept;
    IndexedIdentifier& operator=(const Identifier& id);
    IndexedIdentifier& operator=(const IndexedIdentifier& rhs) noexcept;
    ~IndexedIdentifier();
    bool operator==(const IndexedIdentifier& rhs) const;
    bool operator!=(const IndexedIdentifier& rhs) const;
    bool operator==(const Identifier& id) const;

    bool isEmpty() const;

    Identifier identifier() const;
    operator Identifier() const;

    unsigned int index() const
    {
        return m_index;
    }

private:
    explicit IndexedIdentifier(unsigned int index);
    IndexedIdentifier& operator=(unsigned int index);

    unsigned int m_index;
};

/**
 * A helper-class to store an identifier by index in a type-safe way.
 *
 * The difference to QualifiedIdentifier is that this class only stores the index of an identifier that is in the repository, without any dynamic
 * abilities or access to the contained data.
 *
 * This class does "disk reference counting"
 *
 * @warning Do not use this after QCoreApplication::aboutToQuit() has been emitted, items that are not disk-referenced will be invalid at that point.
 */
class KDEVPLATFORMLANGUAGE_EXPORT IndexedQualifiedIdentifier
    : public ReferenceCountManager
{
public:
    IndexedQualifiedIdentifier();
    IndexedQualifiedIdentifier(const QualifiedIdentifier& id);
    IndexedQualifiedIdentifier(const IndexedQualifiedIdentifier& rhs) noexcept;
    IndexedQualifiedIdentifier& operator=(const QualifiedIdentifier& id);
    IndexedQualifiedIdentifier& operator=(const IndexedQualifiedIdentifier& id) noexcept;
    ~IndexedQualifiedIdentifier();
    bool operator==(const IndexedQualifiedIdentifier& rhs) const;
    bool operator==(const QualifiedIdentifier& id) const;

    bool operator<(const IndexedQualifiedIdentifier& rhs) const
    {
        return m_index < rhs.m_index;
    }

    bool isValid() const;
    bool isEmpty() const;

    QualifiedIdentifier identifier() const;
    operator QualifiedIdentifier() const;

    unsigned int index() const
    {
        return m_index;
    }

private:
    explicit IndexedQualifiedIdentifier(unsigned int index);
    IndexedQualifiedIdentifier& operator=(unsigned int index);
    unsigned int m_index;
};

/**
 * Flags to control the string representation of identifiers.
 */
enum IdentifierStringFormattingOption {
    NoOptions = 0x0,

    /// Removes explicit global prefix from the result.
    /// When enabled, global identifiers will be formatted as "globalIdentifierFormattedString"
    /// instead "::globalIdentifierFormattedString".
    RemoveExplicitlyGlobalPrefix = 0x1,

    /// Removes template information from the result.
    /// When enabled, TemplateClass< someDataType > will be formatted as plain "TemplateClass".
    RemoveTemplateInformation = 0x2
};
Q_DECLARE_FLAGS(IdentifierStringFormattingOptions, IdentifierStringFormattingOption)

/**
 * Represents a single unqualified identifier
 */
class KDEVPLATFORMLANGUAGE_EXPORT Identifier
{
    friend class QualifiedIdentifier;

public:
    /**
     * @param start The position in the given string where to start searching for the identifier. (optional)
     * @param takenRange If this is nonzero, it will be filled with the length of the range from the beginning
     *                   of the given string, that was used to construct this identifier. (optional)
     *
     * @warning The identifier is parsed in a C++-similar way, and the result may not be what you expect.
     *          If you want to prevent that parsing, use the constructor that takes IndexedString.
     */
    explicit Identifier(QStringView str, uint start = 0, uint* takenRange = nullptr);
    explicit Identifier(const QString& str, uint start = 0, uint* takenRange = nullptr)
        : Identifier(QStringView{str}, start, takenRange)
    {
    }

    /**
     * Preferred constructor, use this if you already have an IndexedString available. This does not decompose the given string.
     */
    explicit Identifier(const IndexedString& str);
    Identifier(const Identifier& rhs);
    explicit Identifier(uint index);
    Identifier();
    Identifier(Identifier&& rhs) Q_DECL_NOEXCEPT;
    ~Identifier();
    Identifier& operator=(const Identifier& rhs);
    Identifier& operator=(Identifier&& rhs) Q_DECL_NOEXCEPT;

    static Identifier unique(int token);

    bool isUnique() const;
    int uniqueToken() const;
    /**
     * If \a token is non-zero, turns this Identifier into the special per-document unique identifier.
     *
     * This is used e.g. for anonymous namespaces.
     *
     * Pass a token which is specific to the document to allow correct equality comparison.
     */
    void setUnique(int token);

    const IndexedString identifier() const;
    void setIdentifier(QStringView identifier);
    /**
     * Should be preferred over the other version
     */
    void setIdentifier(const IndexedString& identifier);

    uint hash() const;

    /**
     * Comparison ignoring the template-identifiers
     */
    bool nameEquals(const Identifier& rhs) const;

    /**
     * @warning This is expensive.
     */
    IndexedTypeIdentifier templateIdentifier(int num) const;
    uint templateIdentifiersCount() const;
    void appendTemplateIdentifier(const IndexedTypeIdentifier& identifier);
    void clearTemplateIdentifiers();
    void setTemplateIdentifiers(const QList<IndexedTypeIdentifier>& templateIdentifiers);

    QString toString(IdentifierStringFormattingOptions options = NoOptions) const;

    bool operator==(const Identifier& rhs) const;
    bool operator!=(const Identifier& rhs) const;

    bool isEmpty() const;

    /**
     * @return a unique index within the global identifier repository for this identifier.
     *
     * If the identifier isn't in the repository yet, it is added to the repository.
     */
    uint index() const;

    bool inRepository() const;

private:
    void makeConstant() const;
    void prepareWrite();

    //Only one of the following pointers is valid at a given time
    mutable uint m_index; //Valid if cd is valid
    union {
        mutable IdentifierPrivate<true>* dd; //Dynamic, owned by this identifier
        mutable const IdentifierPrivate<false>* cd; //Constant, owned by the repository
    };
};

/**
 * Represents a qualified identifier
 *
 * QualifiedIdentifier has it's hash-values stored, so using the hash-values is very efficient.
 */
class KDEVPLATFORMLANGUAGE_EXPORT QualifiedIdentifier
{
public:
    explicit QualifiedIdentifier(QStringView id, bool isExpression = false);
    explicit QualifiedIdentifier(const QString& id, bool isExpression = false)
        : QualifiedIdentifier(QStringView{id}, isExpression)
    {
    }

    explicit QualifiedIdentifier(const Identifier& id);
    QualifiedIdentifier(const QualifiedIdentifier& id);
    explicit QualifiedIdentifier(uint index);
    QualifiedIdentifier();
    QualifiedIdentifier(QualifiedIdentifier&& rhs) Q_DECL_NOEXCEPT;
    ~QualifiedIdentifier();
    QualifiedIdentifier& operator=(const QualifiedIdentifier& rhs);
    QualifiedIdentifier& operator=(QualifiedIdentifier&& rhs) Q_DECL_NOEXCEPT;

    /**
     * Append @p id to this qualified identifier.
     */
    void push(const IndexedIdentifier& id);
    /**
     * Append @p id to this qualified identifier.
     *
     * NOTE: If you have an indexed identifier available, use the above method instead.
     */
    void push(const Identifier& id);
    /**
     * Append all identifiers of @p id to this qualified identifier.
     */
    void push(const QualifiedIdentifier& id);

    /**
     * Pops one identifier from back:
     */
    void pop();
    void clear();
    bool isEmpty() const;
    int count() const;
    Identifier first() const;
    IndexedIdentifier indexedFirst() const;
    Identifier last() const;
    IndexedIdentifier indexedLast() const;
    Identifier top() const;
    Identifier at(int i) const;
    IndexedIdentifier indexedAt(int i) const;
    /**
     * @param pos Position where to start the copy.
     * @param len If this is -1, the whole following part will be returned.
     */
    QualifiedIdentifier mid(int pos, int len = -1) const;

    /**
     * Copy the leftmost \a len number of identifiers.
     *
     * @param len The number of identifiers to copy, or if negative, the number of identifiers to omit from the right
     */
    inline QualifiedIdentifier left(int len) const
    {
        return mid(0, len > 0 ? len : count() + len);
    }

    ///@todo Remove this flag
    bool explicitlyGlobal() const;
    void setExplicitlyGlobal(bool eg);
    bool isQualified() const;

    /**
     * A flag that can be set by setIsExpression
     */
    bool isExpression() const;
    /**
     * Set the expression-flag, that can be retrieved by isExpression().
     * This flag is not respected while creating the hash-value and while operator==() comparison.
     * It is respected while isSame(..) comparison.
     */
    void setIsExpression(bool);

    QString toString(IdentifierStringFormattingOptions options = NoOptions) const;
    QStringList toStringList(IdentifierStringFormattingOptions options = NoOptions) const;

    QualifiedIdentifier operator+(const QualifiedIdentifier& rhs) const;
    QualifiedIdentifier& operator+=(const QualifiedIdentifier& rhs);

    /**
     * Nicer interfaces to merge
     */
    QualifiedIdentifier operator+(const Identifier& rhs) const;
    QualifiedIdentifier& operator+=(const Identifier& rhs);

    QualifiedIdentifier operator+(const IndexedIdentifier& rhs) const;
    QualifiedIdentifier& operator+=(const IndexedIdentifier& rhs);

    /**
     * @return a QualifiedIdentifier with this one appended to the other.
     *
     * It is explicitly global if either this or base is.
     */
    QualifiedIdentifier merge(const QualifiedIdentifier& base) const;

    /**
     * The comparison-operators do not respect explicitlyGlobal and isExpression, they only respect the real scope.
     * This is for convenient use in hash-tables etc.
     */
    bool operator==(const QualifiedIdentifier& rhs) const;
    bool operator!=(const QualifiedIdentifier& rhs) const;

    bool beginsWith(const QualifiedIdentifier& other) const;

    uint index() const;

    /**
     * @return true if this qualified identifier is already in the persistent identifier repository
     */
    bool inRepository() const;

    /**
     * The hash does not respect explicitlyGlobal, only the real scope.
     */
    uint hash() const;

protected:
    bool sameIdentifiers(const QualifiedIdentifier& rhs) const;

    void makeConstant() const;
    void prepareWrite();

    mutable uint m_index;
    union {
        mutable QualifiedIdentifierPrivate<true>* dd;
        mutable const QualifiedIdentifierPrivate<false>* cd;
    };
};

/**
 * Extends IndexedQualifiedIdentifier by:
 * - Arbitrary count of pointer-poperators with cv-qualifiers
 * - Reference operator
 * All the properties set here are respected in the hash value.
 */
class KDEVPLATFORMLANGUAGE_EXPORT IndexedTypeIdentifier
{
public:
    /**
     * Variables like pointerDepth, isReference, etc. are not parsed from the string, so this parsing is quite limited.
     */
    explicit IndexedTypeIdentifier(const IndexedQualifiedIdentifier& identifier = IndexedQualifiedIdentifier());
    explicit IndexedTypeIdentifier(QStringView identifer, bool isExpression = false);

    bool isReference() const;
    void setIsReference(bool);

    bool isRValue() const;
    void setIsRValue(bool);

    bool isConstant() const;
    void setIsConstant(bool);

    bool isVolatile() const;
    void setIsVolatile(bool);

    IndexedQualifiedIdentifier identifier() const;

    void setIdentifier(const IndexedQualifiedIdentifier& id);

    /**
     * @return the pointer depth. Example for C++: "char*" has pointer-depth 1, "char***" has pointer-depth 3
     */
    int pointerDepth() const;
    /**
     * Sets the pointer-depth to the specified count.
     *
     * When the pointer-depth is increased, the "isConstPointer" values for new depths will be initialized with false.
     *
     * For efficiency-reasons the maximum currently is 23.
     */
    void setPointerDepth(int);

    /**
     * Whether the target of pointer 'depthNumber' is constant
     */
    bool isConstPointer(int depthNumber) const;
    void setIsConstPointer(int depthNumber, bool constant);

    QString toString(IdentifierStringFormattingOptions options = NoOptions) const;

    uint hash() const;

    /**
     * The comparison-operators do not respect explicitlyGlobal and isExpression, they only respect the real scope.
     * This is for convenient use in hash-tables etc.
     */
    bool operator==(const IndexedTypeIdentifier& rhs) const;
    bool operator!=(const IndexedTypeIdentifier& rhs) const;

private:
    IndexedQualifiedIdentifier m_identifier;
    // The overall number of bits shared by these bit-fields should not exceed 32,
    // so that we don't waste space. IndexedTypeIdentifer should be as compact as possible.
    bool m_isConstant : 1;
    bool m_isReference : 1;
    bool m_isRValue : 1;
    bool m_isVolatile : 1;
    uint m_pointerDepth : 5;
    uint m_pointerConstMask : 23;
};

KDEVPLATFORMLANGUAGE_EXPORT uint qHash(const IndexedTypeIdentifier& id);
KDEVPLATFORMLANGUAGE_EXPORT uint qHash(const QualifiedIdentifier& id);
KDEVPLATFORMLANGUAGE_EXPORT uint qHash(const Identifier& id);

inline uint qHash(const IndexedIdentifier& id)
{
    return id.index();
}

inline uint qHash(const IndexedQualifiedIdentifier& id)
{
    return id.index();
}
}

Q_DECLARE_TYPEINFO(KDevelop::IndexedTypeIdentifier, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(KDevelop::IndexedQualifiedIdentifier, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(KDevelop::IndexedIdentifier, Q_MOVABLE_TYPE);
Q_DECLARE_METATYPE(KDevelop::IndexedQualifiedIdentifier)
Q_DECLARE_METATYPE(KDevelop::IndexedIdentifier)

Q_DECLARE_TYPEINFO(KDevelop::QualifiedIdentifier, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(KDevelop::Identifier, Q_MOVABLE_TYPE);
Q_DECLARE_METATYPE(KDevelop::QualifiedIdentifier)
Q_DECLARE_METATYPE(KDevelop::Identifier)

/**
 * {q,k}Debug() stream operator: Writes the Identifier to the debug output.
 */
KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug s, const KDevelop::Identifier& identifier);

/**
 * {q,k}Debug() stream operator: Writes the QualifiedIdentifier to the debug output.
 */
KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug s, const KDevelop::QualifiedIdentifier& identifier);

#endif // KDEVPLATFORM_IDENTIFIER_H