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