File indexing completed on 2024-06-16 04:23:16

0001 /*
0002     SPDX-FileCopyrightText: 2011-2014 Sven Brauch <svenbrauch@googlemail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef KDEVPLATFORM_CONTAINER_TYPES_H
0008 #define KDEVPLATFORM_CONTAINER_TYPES_H
0009 
0010 #include "structuretype.h"
0011 #include "typesystemdata.h"
0012 #include "typeutils.h"
0013 #include "../duchainlock.h"
0014 
0015 #include <language/languageexport.h>
0016 
0017 namespace KDevelop {
0018 class KDEVPLATFORMLANGUAGE_EXPORT ListTypeData
0019     : public KDevelop::StructureTypeData
0020 {
0021 public:
0022     ListTypeData()
0023         : KDevelop::StructureTypeData()
0024         , m_contentType() { }
0025 
0026     ListTypeData(const ListTypeData& rhs)
0027         : KDevelop::StructureTypeData(rhs)
0028         , m_contentType(rhs.m_contentType) { }
0029 
0030     explicit ListTypeData(const KDevelop::StructureTypeData& rhs)
0031         : KDevelop::StructureTypeData(rhs)
0032         , m_contentType() { }
0033 
0034     ~ListTypeData() = default;
0035 
0036     ListTypeData& operator=(const ListTypeData& rhs) = delete;
0037 
0038     IndexedType m_contentType;
0039 };
0040 
0041 /**
0042  * @brief Represents a list-like object which can have a content type.
0043  *
0044  * Example for Python:
0045  * @code
0046  *     # in the file describing the built-in list type
0047  *     class List:         # (1)
0048  *         pass
0049  *
0050  *     # in the user's code:
0051  *     a = []              # (2)
0052  *     a.append(3)         # (3)
0053  * @endcode
0054  *
0055  * This type class can be used to determine the type of a as "list of int" as follows:
0056  *     (1) When creating the type for the List class,
0057  *         create a ListType instead of a structure type.
0058  *         (Your language plugin somehow needs to know
0059  *         which classes are list-like; Python does this
0060  *         through special comments for the class)
0061  *     (2) Set the type of a to the type declared by the
0062  *         List class, as usual.
0063  *     (3) Call
0064  *         \code
0065  *                static_cast<ListType*>(a->abstractType())->addContentType(int_type)
0066  *         \endcode
0067  *         (Your language plugin needs to know which methods
0068  *         add their argument's content to the type's content;
0069  *         Python does this through special comments for the method)
0070  */
0071 class KDEVPLATFORMLANGUAGE_EXPORT ListType
0072     : public KDevelop::StructureType
0073 {
0074 public:
0075     using Ptr = TypePtr<ListType>;
0076 
0077     ListType();
0078     ListType(const ListType& rhs);
0079     explicit ListType(StructureTypeData& data);
0080 
0081     ListType& operator=(const ListType& rhs) = delete;
0082 
0083     /**
0084      * @brief Adds @p typeToAdd to the content type of this list.
0085      *
0086      * If the list currently has no type, it is set to this type.
0087      * If @p typeToAdd equals this list's content type, or is a useless type
0088      * nothing happens.
0089      * Otherwise, the type of the list becomes an unsure type of the previous
0090      * and @p typeToAdd.
0091      *
0092      * Pass your language's UnsureType as a template parameter, as it will eventually
0093      * need to be instantiated.
0094      *
0095      * @note If the type is already assigned to a declaration, the duchain
0096      * must be write-locked when this is called.
0097      *
0098      * @param typeToAdd The new type the list's contents can possibly be of.
0099      */
0100     template <typename LanguageUnsureType>
0101     void addContentType(const AbstractType::Ptr& typeToAdd)
0102     {
0103         auto newContentType = TypeUtils::mergeTypes<LanguageUnsureType>(contentType().abstractType(), typeToAdd);
0104         d_func_dynamic()->m_contentType = IndexedType(newContentType);
0105     }
0106 
0107     /**
0108      * @brief Replaces this list's content type by @p newType.
0109      */
0110     void replaceContentType(const AbstractType::Ptr& newType);
0111 
0112     /**
0113      * @brief Get this lists's content type.
0114      */
0115     IndexedType contentType() const;
0116 
0117     /**
0118      * @brief Return only the container type, not the content type in a string.
0119      */
0120     QString containerToString() const;
0121 
0122     /**
0123      * @brief Formats this type (base type and content type) in a string.
0124      */
0125     QString toString() const override;
0126 
0127     AbstractType* clone() const override;
0128     uint hash() const override;
0129     bool equals(const AbstractType* rhs) const override;
0130 
0131     enum { Identity = 58 };
0132 
0133     using Data = ListTypeData;
0134 
0135 protected:
0136     TYPE_DECLARE_DATA(ListType);
0137 };
0138 
0139 class KDEVPLATFORMLANGUAGE_EXPORT MapTypeData
0140     : public ListTypeData
0141 {
0142 public:
0143     MapTypeData()
0144         : ListTypeData()
0145         , m_keyType() { }
0146 
0147     MapTypeData(const MapTypeData& rhs)
0148         : ListTypeData(rhs)
0149         , m_keyType(rhs.m_keyType) { }
0150 
0151     explicit MapTypeData(const ListTypeData& rhs)
0152         : ListTypeData(rhs)
0153         , m_keyType() { }
0154 
0155     ~MapTypeData() = default;
0156 
0157     MapTypeData& operator=(const ListTypeData& rhs) = delete;
0158 
0159     IndexedType m_keyType;
0160 };
0161 
0162 /**
0163  * @brief Represents a hashmap-like object which can have a key and a content type.
0164  *
0165  * @see ListType
0166  * This works the same as ListType, except that you can also track the object's key type.
0167  */
0168 class KDEVPLATFORMLANGUAGE_EXPORT MapType
0169     : public ListType
0170 {
0171 public:
0172     using Ptr = TypePtr<MapType>;
0173 
0174     MapType();
0175     MapType(const MapType& rhs);
0176     explicit MapType(ListTypeData& data);
0177 
0178     MapType& operator=(const MapType& rhs) = delete;
0179 
0180     /**
0181      * @brief Add @p typeToAdd to this map's key type.
0182      * Behaves like addContentType, except that it modifies the key type instead.
0183      */
0184     template <typename LanguageUnsureType>
0185     void addKeyType(const AbstractType::Ptr& typeToAdd)
0186     {
0187         auto newKeyType = TypeUtils::mergeTypes<LanguageUnsureType>(keyType().abstractType(), typeToAdd);
0188         DUChainWriteLocker lock;
0189         d_func_dynamic()->m_keyType = IndexedType(newKeyType);
0190     }
0191 
0192     /**
0193      * @brief Set this map's key type to @p newType.
0194      */
0195     void replaceKeyType(const AbstractType::Ptr& newType);
0196 
0197     /**
0198      * @brief Get this map's key type.
0199      */
0200     IndexedType keyType() const;
0201 
0202     /**
0203      * @brief Formats this type (base type and key+content type) in a string.
0204      */
0205     QString toString() const override;
0206 
0207     AbstractType* clone() const override;
0208     uint hash() const override;
0209     bool equals(const AbstractType* rhs) const override;
0210 
0211     enum { Identity = 57 };
0212 
0213     using Data = MapTypeData;
0214 
0215 protected:
0216     TYPE_DECLARE_DATA(MapType);
0217 };
0218 } // namespace KDevelop
0219 
0220 #endif // KDEVPLATFORM_CONTAINER_TYPES_H