File: declarationid.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 (201 lines) | stat: -rw-r--r-- 7,236 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
/*
    SPDX-FileCopyrightText: 2008 David Nolden <david.nolden.kdevelop@art-master.de>

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

#ifndef KDEVPLATFORM_DECLARATION_ID_H
#define KDEVPLATFORM_DECLARATION_ID_H

#include "indexeddeclaration.h"
#include "identifier.h"
#include "instantiationinformation.h"
#include <language/util/kdevhash.h>

//krazy:excludeall=dpointer

namespace KDevelop {
class Declaration;
class TopDUContext;

/**
 * \short Allows clearly identifying a Declaration.
 *
 * DeclarationId is needed to uniquely address Declarations that are in another top-context,
 * because there may be multiple parsed versions of a file.
 *
 * There are two forms of DeclarationId, one indirect and one direct.  The direct form
 * holds a reference to the Declaration instance, whereas the indirect form stores the qualified
 * identifier and an additional index to disambiguate instances of multiple declarations with the same
 * identifier.
 *
 * Both forms also have a specialization index. It can be used in a language-specific way to pick other
 * versions of the declaration. When the declaration is found, Declaration::specialize() is called on
 * the found declaration with this value, and the returned value is the actually found declaration.
 *
 * \note This only works when the Declaration is in the symbol table.
 * */
class KDEVPLATFORMLANGUAGE_EXPORT DeclarationId
{
public:
    /**
     * Constructor for indirect access to a declaration.  The resulting DeclarationId will not
     * have a direct reference to the Declaration, but will look it up as needed.
     *
     * \param id Identifier for this declaration id.
     * \param additionalId Additional index to disambiguate
     * \param specialization Specialization index (see class documentation).
     */
    explicit DeclarationId(const IndexedQualifiedIdentifier& id = IndexedQualifiedIdentifier(),
                           uint additionalId = 0,
                           const IndexedInstantiationInformation& specialization = IndexedInstantiationInformation());

    /**
     * Constructor for direct access to a declaration.  The resulting DeclarationId will
     * directly reference the Declaration
     *
     * \param decl Declaration to reference.
     * \param specialization Specialization index (see class documentation).
     */
    explicit DeclarationId(const IndexedDeclaration& decl,
                           const IndexedInstantiationInformation& specialization = IndexedInstantiationInformation());

    DeclarationId(const DeclarationId& rhs);

    ~DeclarationId();

    DeclarationId& operator=(const DeclarationId& rhs);

    /**
     * Equality operator.
     *
     * \param rhs declaration identifier to compare.
     * \returns true if equal, otherwise false.
     */
    bool operator==(const DeclarationId& rhs) const
    {
        if (m_isDirect != rhs.m_isDirect)
            return false;

        if (!m_isDirect)
            return m_indirectData.identifier == rhs.m_indirectData.identifier
                   && m_indirectData.additionalIdentity == rhs.m_indirectData.additionalIdentity
                   && m_specialization == rhs.m_specialization;
        else
            return m_directData == rhs.m_directData && m_specialization == rhs.m_specialization;
    }

    /**
     * Not equal operator.
     *
     * \param rhs declaration identifier to compare.
     * \returns true if not equal, otherwise false.
     */
    bool operator!=(const DeclarationId& rhs) const
    {
        return !operator==(rhs);
    }

    /**
     * Determine whether this declaration identifier references a valid declaration.
     */
    bool isValid() const
    {
        return (m_isDirect && m_directData.isValid()) || m_indirectData.identifier.isValid();
    }

    /**
     * Hash function for this declaration identifier.
     *
     * \warning This may return different hashes for the same declaration,
     *          depending on whether the id is direct or indirect,
     *          and thus you cannot compare hashes for declaration equality (use operator==() instead)
     */
    uint hash() const
    {
        if (m_isDirect)
            return KDevHash() << m_directData.hash() << m_specialization.index();
        else
            return KDevHash() << m_indirectData.identifier.index() << m_indirectData.additionalIdentity <<
                   m_specialization.index();
    }

    /**
     * Retrieve the declaration, from the perspective of \a context.
     * In order to be retrievable, the declaration must be in the symbol table.
     *
     * \param context Context in which to search for the Declaration.
     * \param instantiateIfRequired Whether the declaration should be instantiated if required
     * \returns the referenced Declaration, or null if none was found.
     * */
    Declaration* declaration(const TopDUContext* context, bool instantiateIfRequired = true) const;

    /**
     * Same as declaration(..), but returns all matching declarations if there are multiple.
     * This also returns found forward-declarations.
     */
    KDevVarLengthArray<Declaration*> declarations(const TopDUContext* context) const;

    /**
     * Set the specialization index (see class documentation).
     *
     * \param spec the new specialization index.
     */
    void setSpecialization(const IndexedInstantiationInformation& spec);

    /**
     * Retrieve the specialization index (see class documentation).
     *
     * \returns the specialization index.
     */
    IndexedInstantiationInformation specialization() const;

    /**
     * Determine whether this DeclarationId directly references a Declaration by indices,
     * or if it uses identifiers and other data to reference the Declaration.
     *
     * \returns true if direct, false if indirect.
     */
    bool isDirect() const;

    /**
     * Return the qualified identifier for this declaration.
     *
     * \warning This is relatively expensive, and not 100% correct in all cases(actually a top-context would be needed to resolve this correctly),
     *          so avoid using this, except for debugging purposes.
     */
    QualifiedIdentifier qualifiedIdentifier() const;

private:
    /// An indirect reference to the declaration, which uses the symbol-table for lookup. Should be preferred for all
    /// declarations that are in the symbol-table
    struct Indirect
    {
        IndexedQualifiedIdentifier identifier;
        /// Hash from signature, or similar. Used to disambiguate multiple declarations of the same name.
        uint additionalIdentity;

        Indirect& operator=(const Indirect& rhs) = default;
    };

    union {
        Indirect m_indirectData;
        IndexedDeclaration m_directData;
    };
    bool m_isDirect;

    // Can be used in a language-specific way to pick other versions of the declaration.
    // When the declaration is found, pickSpecialization is called on the found declaration
    // with this value, and the returned value is the actually found declaration.
    IndexedInstantiationInformation m_specialization;
};

inline uint qHash(const KDevelop::DeclarationId& id)
{
    return id.hash();
}
}

Q_DECLARE_TYPEINFO(KDevelop::DeclarationId, Q_MOVABLE_TYPE);

#endif