File indexing completed on 2024-05-12 05:46:43

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