1 /*
2     SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
3     SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
4 
5     SPDX-License-Identifier: LGPL-2.0-only
6 */
7 
8 #ifndef KDEVPLATFORM_DECLARATION_H
9 #define KDEVPLATFORM_DECLARATION_H
10 
11 #include <QList>
12 #include <QMap>
13 
14 #include "types/abstracttype.h"
15 #include "duchainbase.h"
16 #include "instantiationinformation.h"
17 #include "identifier.h"
18 #include "indexeddeclaration.h"
19 
20 class QByteArray;
21 
22 namespace KDevelop {
23 class AbstractType;
24 class DUContext;
25 class IndexedString;
26 class DeclarationData;
27 class DeclarationId;
28 class Declaration;
29 class IndexedTopDUContext;
30 class TopDUContext;
31 
32 /**
33  * \short Represents a single declaration in a definition-use chain.
34  *
35  * \note A du-context can be freely edited as long as it's parent-context is zero.
36  * In the moment the parent-context is set, the context may only be edited when it
37  * is allowed to edited it's top-level context (@see TopLevelContext::inDUChain())
38  */
39 class KDEVPLATFORMLANGUAGE_EXPORT Declaration
40     : public DUChainBase
41 {
42 public:
43     /// Access types
44     enum AccessPolicy : quint8 {
45         Public /**< a public declaration */,
46         Protected /**< a protected declaration */,
47         Private /**< a private declaration */,
48         DefaultAccess /**<a declaration with default access; in java, only package-level access. */
49     };
50     /// Enumeration of the types of declarations
51     enum Kind : quint8 {
52         Type /**< A type is declared, like a class-declaration or function-declaration, or a typedef("class MyClass {};") */,
53         Instance /**< An instance of a type is declared("MyClass m;") */,
54         NamespaceAlias /**< This is a namespace-alias. You can safely cast this object to NamespaceAliasDeclaration. */,
55         Alias, /**<This is an alias-declaration. You can safely cast this object to AliasDeclaration. */
56         Namespace, /**< Declaration of a namespace. */
57         Import, /**< Declaration marks the Import of a file. */
58         Macro /**< Declaration of a macro such as "#define FOO 1". */
59     };
60 
61     /**
62      * Constructor.
63      *
64      * If \a parentContext is in the symbol table, the declaration will automatically
65      * be added into the symbol table.
66      *
67      * \param range range of the alias declaration's identifier
68      * \param parentContext context in which this declaration occurred
69      * */
70     Declaration(const RangeInRevision& range, DUContext* parentContext);
71     ///Copy-constructor for cloning
72     Declaration(const Declaration& rhs);
73     /// Destructor
74     ~Declaration() override;
75     /// Uses the given data
76     explicit Declaration(DeclarationData& dd);
77 
78     Declaration& operator=(const Declaration& rhs) = delete;
79 
80     TopDUContext* topContext() const override;
81 
82     /**
83      * Determine whether this declaration is a forward declaration.
84      *
85      * \returns true if this is a forward declaration, otherwise returns false.
86      */
87     virtual bool isForwardDeclaration() const;
88 
89     /**
90      * Determine whether this declaration is a function declaration.
91      *
92      * \returns true if this is a function declaration, otherwise returns false.
93      */
94     virtual bool isFunctionDeclaration() const;
95 
96     /**
97      * Determine whether this declaration is accessible through the du-chain.
98      * If it is, it cannot be edited without holding the du-chain write lock.
99      *
100      * \sa DUChain::lock()
101      * \sa DUChainWriteLocker
102      *
103      * \returns true if the Declaration is already inserted into a duchain.
104      */
105     virtual bool inDUChain() const;
106 
107     /**
108      * Determine whether this declaration is also a definition.
109      *
110      * \returns true if this declaration is also a definition, otherwise false.
111      */
112     bool isDefinition() const;
113     /**
114      * Set whether this declaration is also a definition.
115      *
116      * \param dd set this to true if this declaration is also a definition, otherwise false.
117      */
118     void setDeclarationIsDefinition(bool dd);
119 
120     /**
121      * Determine if this declaration is a type-alias (in c++ typedef).
122      *
123      * \returns true if the declaration is a type alias, otherwise false.
124      */
125     bool isTypeAlias() const;
126     /**
127      * Set whether this declaration is a type alias.
128      *
129      * \param typeAlias true if the declaration is a type alias, otherwise false.
130      */
131     void setIsTypeAlias(bool typeAlias);
132 
133     /**
134      * Determine whether the declaration is deprecated.
135      */
136     bool isDeprecated() const;
137     /**
138      * Set whether the declaration is deprecated.
139      *
140      * \param deprecated true if the declaration is deprecated, otherwise false.
141      */
142     void setDeprecated(bool deprecated);
143 
144     /**
145      * Changes whether this declaration must be direct in all cases or not.
146      *
147      * By default this is set to false.
148      *
149      * \param direct true to force direct, false otherwise.
150      */
151     void setAlwaysForceDirect(bool direct);
152     /**
153      * Determine whether this declaration must always be direct.
154      */
155     bool alwaysForceDirect() const;
156 
157     /**
158      * Changes whether this declaration is "implicitly created".
159      *
160      * An implicit declaration is not declared in the class context,
161      * but written somewhere else outside.
162      *
163      * Declarations are by default not implicitly declared.
164      *
165      * \param _auto true for implicit, false for default behaviour
166      */
167     void setAutoDeclaration(bool _auto);
168     /**
169      * Determine whether this declaration is implicitly created or not.
170      */
171     bool isAutoDeclaration() const;
172 
173     /**
174      * Changes whether this declaration is "explicitly deleted", i.e. not implicitly declared or accessible.
175      *
176      * \param deleted true for deleted, false for default behaviour
177      * */
178     void setExplicitlyDeleted(bool deleted);
179     /**
180      * Determine whether this declaration is "explicitly deleted" or not.
181      */
182     bool isExplicitlyDeleted() const;
183 
184     /**
185      * Changes whether this declaration is explicitly typed.
186      *
187      * Explicitly typed declaration has the type written as part of the
188      * declaration. The opposite, implicitly typed declaration, has the type
189      * deduced by the compiler.
190      *
191      * E.g. in C++ variable declarations are explicitly typed unless the "auto"
192      * keyword is used.
193      *
194      * \param explicitlyTyped true for explicitly typed, false for implicitly typed
195      */
196     void setExplicitlyTyped(bool explicitlyTyped);
197     /**
198      * Determine whether this declaration is explicitly typed.
199      */
200     bool isExplicitlyTyped() const;
201 
202     /**
203      * Retrieve the declaration which is specialized with the given
204      * \a specialization index as seen from \a topContext.
205      *
206      * \param specialization the specialization index (see DeclarationId)
207      * \param topContext the top context representing the perspective from which to specialize.
208      *                   if @p topContext is zero, only already existing specializations are returned,
209      *                   and if none exists, zero is returned.
210      * \param upDistance upwards distance in the context-structure of the
211      *                   given specialization-info. This allows specializing children.
212      */
213     virtual Declaration* specialize(const IndexedInstantiationInformation& specialization,
214                                     const TopDUContext* topContext, int upDistance = 0);
215 
216     /**
217      * Retrieve the context that is opened by this declaration, if one exists.
218      *
219      * For example, a class will have a declaration which is contained within the context in which
220      * it is declared, and a new context will be created to hold class members.  This function returns
221      * that context.
222      * The declaration has to be part of the same top-context.
223      *
224      * \returns the internal context for this declaration or, if none exists, nullptr
225      */
226     DUContext* internalContext() const;
227 
228     /**
229      * Set the internal \a context for this declaration.
230      *
231      * \param context the internal context
232      */
233     void setInternalContext(DUContext* context);
234 
235     /**
236      * Determine the logical internal context for the resolved form of this declaration.
237      *
238      * \li If this declaration has a definition, and the definition is resolved,
239      *     it returns the internal context of the definition.
240      * \li If this declaration is a forward-declaration, the forward-declaration is
241      *     resolved, it returns the internal context of the resolved declaration.
242      * \li If this is a type-alias, it returns the internal context of the actual type.
243      * \li Otherwise, it returns the same as internalContext().
244      *
245      * \param topContext Needed to resolve forward-declarations.
246      * \returns the resolved internal context, as described above
247      */
248     virtual DUContext* logicalInternalContext(const TopDUContext* topContext) const;
249 
250     /**
251      * This is a convenience function to determine the resolved declaration, if this is a forward declaration.
252      * Otherwise, it just returns this declaration.
253      * \param topContext Context within which to search for the resolved declaration.
254      * \returns the resolved declaration if one was found, otherwise this declaration.
255      * */
256     const Declaration* logicalDeclaration(const TopDUContext* topContext) const;
257 
258     /// \copydoc
259     Declaration* logicalDeclaration(const TopDUContext* topContext);
260 
261     /**
262      * Access the parent context of this declaration.
263      * \returns the parent context of this declaration.
264      */
265     DUContext* context() const;
266 
267     /**
268      * Set the context in which this declaration occurs.
269      *
270      * When setContext() is called, this declaration is inserted into the given context.
271      * You only need to be able to write this declaration. You do not need write-privileges
272      * for the context, because addDeclaration(..) works separately to that.
273      *
274      * If the given context is not in the symbol-table, or if the declaration is inserted anonymously,
275      * or if the context is zero, this declaration is removed from the symbol-table.
276      * Else it is added to the symbol table with the new scope. See TopDUContext for information
277      * about the symbol table.
278      *
279      * \param context New context which contains this declaration. The context must have a
280      *                top-context if it is not zero.
281      * \param anonymous If this is set, this declaration will be added anonymously into the parent-context.
282      *                  This way it can never be found through any of the context's functions, and will
283      *                  not be deleted when the context is deleted, so it must be deleted from elsewhere.
284      */
285     void setContext(DUContext* context, bool anonymous = false);
286 
287     /**
288      * Convenience function to return this declaration's type dynamically casted to \a T.
289      *
290      * \returns this declaration's type as \a T, or null if there is no type or it is not of type \a T.
291      */
292     template <class T>
type()293     TypePtr<T> type() const { return TypePtr<T>::dynamicCast(abstractType()); }
294 
295     /**
296      * Access this declaration's type.
297      *
298      * \note You should not compare or permanently store instances of AbstractType::Ptr. Use IndexedType instead.
299      * \returns this declaration's type, or null if none has been assigned.
300      */
301     AbstractType::Ptr abstractType() const;
302 
303     /**
304      * Set this declaration's type.
305      *
306      * \param type the type to assign.
307      */
308     template <class T>
setType(TypePtr<T> type)309     void setType(TypePtr<T> type) { setAbstractType(AbstractType::Ptr::staticCast(type)); }
310 
311     /**
312      * Set this declaration's \a type.
313      *
314      * \param type this declaration's new type.
315      */
316     virtual void setAbstractType(AbstractType::Ptr type);
317 
318     /**
319      * Return an indexed form of this declaration's type.
320      * Should be preferred, this is the fastest way, and the correct way for doing equality-comparison.
321      *
322      * \returns the declaration's type.
323      */
324     IndexedType indexedType() const;
325 
326     /**
327      * Set this declaration's \a identifier.
328      *
329      * \param identifier this declaration's new identifier
330      */
331     void setIdentifier(const Identifier& identifier);
332 
333     /**
334      * Access this declaration's \a identifier.
335      *
336      * \returns this declaration's identifier.
337      */
338     Identifier identifier() const;
339 
340     /**
341      * Access this declaration's \a identifier.
342      *
343      * \return this declaration's identifier in indexed form. This is faster than identifier(), because it
344      *         equals the internal representation. Use this for example to do equality-comparison.
345      */
346     const IndexedIdentifier& indexedIdentifier() const;
347 
348     /**
349      * Determine the global qualified identifier of this declaration.
350      *
351      * \note This function is expensive, equalQualifiedIdentifier() is preferred if you
352      *       just want to compare equality.
353      */
354     QualifiedIdentifier qualifiedIdentifier() const;
355 
356     /**
357      * Compares the qualified identifier of this declaration with the other one, without needing to compute it.
358      * This is more efficient than comparing the results of qualifiedIdentifier().
359      *
360      * \param rhs declaration to compare identifiers with
361      * \returns true if the identifiers are equal, otherwise false.
362      */
363     bool equalQualifiedIdentifier(const Declaration* rhs) const;
364 
365     /**
366      * Returns the kind of this declaration. @see Kind
367      */
368     Kind kind() const;
369 
370     /**
371      * Set the kind.
372      *
373      * \param kind new kind
374      */
375     void setKind(Kind kind);
376 
377     /**
378      * Returns the comment associated to this declaration in the source-code,
379      * or an invalid string if there is none.
380      *
381      * Stored in utf-8 encoding.
382      */
383     QByteArray comment() const;
384 
385     /**
386      * Sets the comment for this declaration.
387      *
388      * @note Should be utf-8 encoded.
389      */
390     void setComment(const QByteArray& str);
391     /**
392      * Sets the comment for this declaration.
393      */
394     void setComment(const QString& str);
395 
396     /**
397      * Access whether this declaration is in the symbol table.
398      *
399      * \returns true if this declaration is in the symbol table, otherwise false.
400      */
401     bool inSymbolTable() const;
402 
403     /**
404      * Adds or removes this declaration to/from the symbol table.
405      *
406      * \param inSymbolTable true to add this declaration to the symbol table, false to remove it.
407      */
408     virtual void setInSymbolTable(bool inSymbolTable);
409 
410     /**
411      * Equivalence operator.
412      *
413      * \param other Other declaration to compare.
414      * \returns true if the declarations are equal, otherwise false.
415      */
416     bool operator==(const Declaration& other) const;
417 
418     /**
419      * Determine this declaration as a string. \returns this declaration as a string.
420      */
421     virtual QString toString() const;
422 
423     /**
424      * Returns a map of files to use-ranges.
425      *
426      * The key of the returned map is an url of a file. The value
427      * is a list with all use-ranges of this declaration in that file.
428      *
429      * \note The ranges are in the documents local revision,
430      *       use \c DUChainUtils::transformFromRevision or \c usesCurrentRevision()
431      *
432      * \note The uses are unique, no 2 uses are returned that have the same range within the same file.
433      *
434      * \note This is a non-trivial operation and hence expensive.
435      */
436     QMap<IndexedString, QVector<RangeInRevision>> uses() const;
437 
438     /**
439      * Determines whether the declaration has any uses or not.
440      *
441      * Cheaper than calling uses().
442      */
443     bool hasUses() const;
444 
445     /**
446      * Returns a map of files to use-ranges.
447      *
448      * The key of the returned map is an url of a file. The value
449      * is a list with all use-ranges of this declaration in that file.
450      *
451      * \note The uses are unique, no 2 uses are returned that have the same range within the same file.
452      *
453      * \warning This must be called only from within the foreground, or with the foreground lock locked.
454      *
455      * \note This is a non-trivial operation and hence expensive.
456      */
457     QMap<IndexedString, QVector<KTextEditor::Range>> usesCurrentRevision() const;
458 
459     /**
460      * This hash-value should differentiate between multiple different
461      * declarations that have the same qualifiedIdentifier, but should have a different
462      * identity, and thus own Definitions and own Uses assigned.
463      *
464      * Affected by function-arguments, whether this is a template-declaration, etc..
465      */
466     virtual uint additionalIdentity() const;
467 
468     /**
469      * TODO document
470      * */
471     virtual IndexedInstantiationInformation specialization() const;
472 
473     /**
474      * \see DeclarationId
475      *
476      * \param forceDirect When this is true, the DeclarationId is force to be direct,
477      *                    and can be resolved without a symbol-table and top-context.
478      *                    The same goes for Declarations that have \c alwaysForceDirect()
479      *                    set to true.
480      */
481     virtual DeclarationId id(bool forceDirect = false) const;
482 
483     /**
484      * Returns an index that uniquely identifies this declaration within its surrounding top-context.
485      *
486      * That index can be passed to \c TopDUContext::declarationFromIndex(index) to get the declaration.
487      * This is only valid when the declaration is not a specialization (\c specialization() returns 0),
488      * and if it is not anonymous in its context.
489      *
490      * \note for this to be valid, allocateOwnIndex() must have been called first.
491      * \note the highest big of the index is always zero!
492      * \returns the index of the declaration within its TopDUContext.
493      */
494     uint ownIndex() const;
495 
496     /**
497      * Whether this declaration has been inserted anonymously into its parent-context
498      */
499     bool isAnonymous() const;
500 
501     /**
502      * Clear the index for this declaration in the top context that was allocated with allocateOwnIndex().
503      */
504     void clearOwnIndex();
505 
506     /**
507      * Create an index to this declaration from the topContext().  Needed to be able to retrieve ownIndex().
508      */
509     void allocateOwnIndex();
510 
511     /**
512      * Returns a clone of this declaration, with the difference that the returned declaration
513      * has no context set, i.e. \c context() returns zero.
514      *
515      * The declaration will not be registered anywhere, so you must care about its deletion.
516      *
517      * This declaration's text-range will be referenced from the clone, so the clone must not
518      * live longer than the original.
519      */
520     Declaration* clone() const;
521 
522     /**
523      * Signalized that among multiple possible specializations, this one should be used in the UI from now on.
524      *
525      * Currently mainly used in C++ for template support. The default-implementation registers the current
526      * specialization of this declaration to SpecializationStore if it is nonzero.
527      */
528     virtual void activateSpecialization();
529 
530     enum {
531         Identity = 7
532     };
533 
534 protected:
535 
536     /**
537      * Constructor for copy constructors in subclasses.
538      *
539      * \param dd data to copy.
540      * \param range text range which this object covers.
541      */
542     Declaration(DeclarationData& dd, const RangeInRevision& range);
543 
544     /**
545      * Returns true if this declaration is being currently destroyed persistently,
546      * which means that it should eventually deregister itself from persistent storage facilities.
547      *
548      * Only call this from destructors.
549      */
550     bool persistentlyDestroying() const;
551 
552     DUCHAIN_DECLARE_DATA(Declaration)
553 
554 private:
555     /**
556      * Sub-classes should implement this and should copy as much information into the clone as possible without breaking the du-chain.
557      * Sub-classes should also implement a public copy-constructor that can be used for cloning by sub-classes.
558      *
559      * \note You do not have to implement this for your language if you are not going to use it(the du-chain itself does not and should not depend on it).
560      * */
561     virtual Declaration* clonePrivate() const;
562 
563     void updateCodeModel();
564 
565     void rebuildDynamicData(DUContext* parent, uint ownIndex) override;
566 
567     friend class DUContext;
568     friend class IndexedDeclaration;
569     friend class LocalIndexedDeclaration;
570     friend class TopDUContextDynamicData;
571 
572     DUContext* m_context = nullptr;
573     TopDUContext* m_topContext = nullptr;
574     int m_indexInTopContext = 0;
575 };
576 }
577 
578 #endif // KDEVPLATFORM_DECLARATION_H
579