1 /*
2     SPDX-FileCopyrightText: 2002-2005 Roberto Raggi <roberto@kdevelop.org>
3     SPDX-FileCopyrightText: 2006 Adam Treat <treat@kde.org>
4     SPDX-FileCopyrightText: 2006-2008 Hamish Rodda <rodda@kde.org>
5     SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
6 
7     SPDX-License-Identifier: LGPL-2.0-only
8 */
9 
10 #ifndef KDEVPLATFORM_IDENTIFIEDTYPE_H
11 #define KDEVPLATFORM_IDENTIFIEDTYPE_H
12 
13 #include "../identifier.h"
14 #include "../declarationid.h"
15 
16 namespace KDevelop {
17 class DUContext;
18 class Declaration;
19 class DeclarationId;
20 class TopDUContext;
21 class AbstractType;
22 
23 /**
24  * Data structure for identified types.
25  */
26 class IdentifiedTypeData
27 {
28 public:
29     DeclarationId m_id;
30 };
31 
32 /**
33  * \short An IdentifiedType is a type that has a declaration.
34  *
35  * Example of an identified type:
36  * - A class type
37  *
38  * Example of types which are not identified:
39  * - Pointer types (they can point to identified types, but by themselves have no declaration)
40  * - Reference types (the same)
41  * */
42 class KDEVPLATFORMLANGUAGE_EXPORT IdentifiedType
43 {
44 public:
45     /// Destructor
46     virtual ~IdentifiedType();
47 
48     /**
49      * Test for equivalence with another type.
50      *
51      * \param rhs other type to check for equivalence
52      * \returns true if equal, otherwise false.
53      */
54     bool equals(const IdentifiedType* rhs) const;
55 
56     /// Clear the identifier
57     void clear();
58 
59     /**
60      * Determine the qualified identifier for this identified type.
61      *
62      * \note This is relatively expensive. Use declarationId() instead when possible!
63      * \returns the type's qualified identifier
64      */
65     QualifiedIdentifier qualifiedIdentifier() const;
66 
67     /// Determine this identified type's hash value. \returns the hash value
68     uint hash() const;
69 
70     /**
71      * Access the identified type's declaration id, which is a unique global identifier for the
72      * type even when the same identifier represents a different type in a different context
73      * or source file.
74      *
75      * \returns the declaration identifier.
76      * \sa DeclarationId
77      */
78     DeclarationId declarationId() const;
79 
80     /**
81      * Set the globally unique declaration \a id.
82      * \param id new identifier
83      */
84     void setDeclarationId(const DeclarationId& id);
85 
86     /**
87      * Look up the declaration of this type in the given \a top context.
88      *
89      * \param top Top context to search for the declaration within
90      * \returns the declaration corresponding to this identified type
91      */
92     Declaration* declaration(const TopDUContext* top) const;
93 
94     /**
95      * \param top Top context to search for the declaration within
96      * Convenience function that returns the internal context of the attached declaration,
97      * or zero if no declaration is found, or if it does not have an internal context.
98      */
99     DUContext* internalContext(const TopDUContext* top) const;
100 
101     /**
102      * Set the declaration which created this type.
103      *
104      * \note You should be careful when setting this, because it also changes the meaning of the declaration.
105      *
106      * The logic is:
107      * If a declaration has a set abstractType(), and that abstractType() has set the same declaration as declaration(),
108      * then the declaration declares the type(thus it is a type-declaration, see Declaration::kind())
109      *
110      * \param declaration Declaration which created the type
111      * */
112     void setDeclaration(Declaration* declaration);
113 
114     /// Allow IdentifiedType to access its data.
115     virtual IdentifiedTypeData* idData() = 0;
116     /// Allow IdentifiedType to access its data.
117     virtual const IdentifiedTypeData* idData() const = 0;
118 };
119 
120 ///Implements everything necessary to merge the given Parent class with IdentifiedType
121 ///Your used Data class must be based on the Data member class
122 template <class Parent>
123 class MergeIdentifiedType
124     : public Parent
125     , public IdentifiedType
126 {
127 public:
128 
129     class Data
130         : public Parent::Data
131         , public IdentifiedTypeData
132     {
133     };
134 
MergeIdentifiedType()135     MergeIdentifiedType()
136     {
137     }
138 
MergeIdentifiedType(Data & data)139     explicit MergeIdentifiedType(Data& data) : Parent(data)
140     {
141     }
142 
143     MergeIdentifiedType(const MergeIdentifiedType& rhs) = delete;
144 
idData()145     IdentifiedTypeData* idData() override
146     {
147         return static_cast<Data*>(this->d_func_dynamic());
148     }
149 
idData()150     const IdentifiedTypeData* idData() const override
151     {
152         return static_cast<const Data*>(this->d_func());
153     }
154 
equals(const KDevelop::AbstractType * rhs)155     bool equals(const KDevelop::AbstractType* rhs) const override
156     {
157         if (!Parent::equals(rhs))
158             return false;
159 
160         const auto* rhsId = dynamic_cast<const IdentifiedType*>(rhs);
161         Q_ASSERT(rhsId);
162 
163         return IdentifiedType::equals(static_cast<const IdentifiedType*>(rhsId));
164     }
165 };
166 }
167 
168 #endif
169