Changeset View
Changeset View
Standalone View
Standalone View
duchain/helpers.h
Show All 39 Lines | |||||
40 | #include "pythonduchainexport.h" | 40 | #include "pythonduchainexport.h" | ||
41 | #include "types/unsuretype.h" | 41 | #include "types/unsuretype.h" | ||
42 | #include "declarations/functiondeclaration.h" | 42 | #include "declarations/functiondeclaration.h" | ||
43 | #include "ast.h" | 43 | #include "ast.h" | ||
44 | 44 | | |||
45 | using namespace KDevelop; | 45 | using namespace KDevelop; | ||
46 | 46 | | |||
47 | namespace Python { | 47 | namespace Python { | ||
48 | namespace Helper { | ||||
48 | 49 | | |||
49 | class KDEVPYTHONDUCHAIN_EXPORT Helper { | | |||
50 | public: | | |||
51 | /** get search paths for python files **/ | 50 | /** get search paths for python files **/ | ||
52 | static QVector<QUrl> getSearchPaths(const QUrl& workingOnDocument); | 51 | KDEVPYTHONDUCHAIN_EXPORT QVector<QUrl> getSearchPaths(const QUrl& workingOnDocument); | ||
53 | static QStringList dataDirs; | 52 | QStringList& dataDirs(); | ||
54 | static IndexedString documentationFile; | 53 | IndexedString& documentationFile(); | ||
55 | static QStringList correctionFileDirs; | 54 | QStringList& correctionFileDirs(); | ||
56 | static QString localCorrectionFileDir; | 55 | QString& localCorrectionFileDir(); | ||
57 | static DUChainPointer<TopDUContext> documentationFileContext; | 56 | DUChainPointer<TopDUContext>& documentationFileContext(); | ||
58 | 57 | | |||
59 | static QStringList getDataDirs(); | 58 | QStringList getDataDirs(); | ||
60 | static IndexedString getDocumentationFile(); | 59 | IndexedString getDocumentationFile(); | ||
61 | static ReferencedTopDUContext getDocumentationFileContext(); | 60 | KDEVPYTHONDUCHAIN_EXPORT ReferencedTopDUContext getDocumentationFileContext(); | ||
62 | 61 | | |||
63 | static QUrl getCorrectionFile(const QUrl& document); | 62 | KDEVPYTHONDUCHAIN_EXPORT QUrl getCorrectionFile(const QUrl& document); | ||
64 | static QUrl getLocalCorrectionFile(const QUrl& document); | 63 | KDEVPYTHONDUCHAIN_EXPORT QUrl getLocalCorrectionFile(const QUrl& document); | ||
65 | 64 | | |||
66 | static QMutex cacheMutex; | 65 | KDEVPYTHONDUCHAIN_EXPORT QMutex& cacheMutex(); | ||
67 | static QMap<IProject*, QVector<QUrl>> cachedCustomIncludes; | 66 | KDEVPYTHONDUCHAIN_EXPORT QMap<IProject*, QVector<QUrl>>& cachedCustomIncludes(); | ||
68 | static QMap<IProject*, QVector<QUrl>> cachedSearchPaths; | 67 | KDEVPYTHONDUCHAIN_EXPORT QMap<IProject*, QVector<QUrl>>& cachedSearchPaths(); | ||
69 | 68 | | |||
70 | static QMutex projectPathLock; | 69 | KDEVPYTHONDUCHAIN_EXPORT QMutex& projectPathLock(); | ||
71 | static QVector<QUrl> projectSearchPaths; | 70 | KDEVPYTHONDUCHAIN_EXPORT QVector<QUrl>& projectSearchPaths(); | ||
72 | 71 | | |||
73 | static AbstractType::Ptr extractTypeHints(AbstractType::Ptr type); | 72 | AbstractType::Ptr extractTypeHints(AbstractType::Ptr type); | ||
74 | 73 | | |||
75 | /** | 74 | /** | ||
76 | * @brief Get the declaration of 'accessed.attribute', or return null. | 75 | * @brief Get the declaration of 'accessed.attribute', or return null. | ||
77 | * | 76 | * | ||
78 | * @param accessed Type (Structure or Unsure) that should have this attribute. | 77 | * @param accessed Type (Structure or Unsure) that should have this attribute. | ||
79 | * @param attribute Which attribute to look for. | 78 | * @param attribute Which attribute to look for. | ||
80 | * @param topContext Top context (for this file?) | 79 | * @param topContext Top context (for this file?) | ||
81 | * @return Declaration* of the attribute, or null. | 80 | * @return Declaration* of the attribute, or null. | ||
82 | * If UnsureType with >1 matching attributes, returns an arbitrary choice. | 81 | * If UnsureType with >1 matching attributes, returns an arbitrary choice. | ||
83 | **/ | 82 | **/ | ||
84 | static KDevelop::Declaration* accessAttribute(const KDevelop::AbstractType::Ptr accessed, | 83 | KDEVPYTHONDUCHAIN_EXPORT KDevelop::Declaration* accessAttribute(const KDevelop::AbstractType::Ptr accessed, | ||
85 | const KDevelop::IndexedIdentifier& attribute, | 84 | const KDevelop::IndexedIdentifier& attribute, | ||
86 | const KDevelop::TopDUContext* topContext); | 85 | const KDevelop::TopDUContext* topContext); | ||
87 | 86 | | |||
88 | static KDevelop::Declaration* accessAttribute(const KDevelop::AbstractType::Ptr accessed, | 87 | inline KDevelop::Declaration* accessAttribute(const KDevelop::AbstractType::Ptr accessed, | ||
89 | const QString& attribute, const KDevelop::TopDUContext* topContext) { | 88 | const QString& attribute, const KDevelop::TopDUContext* topContext) | ||
89 | { | ||||
90 | return accessAttribute(accessed, IndexedIdentifier(KDevelop::Identifier(attribute)), topContext); | 90 | return accessAttribute(accessed, IndexedIdentifier(KDevelop::Identifier(attribute)), topContext); | ||
91 | } | 91 | } | ||
92 | 92 | | |||
93 | static AbstractType::Ptr resolveAliasType(const AbstractType::Ptr eventualAlias); | 93 | KDEVPYTHONDUCHAIN_EXPORT AbstractType::Ptr resolveAliasType(const AbstractType::Ptr eventualAlias); | ||
94 | 94 | | |||
95 | /** | 95 | /** | ||
96 | * @brief Get the content type(s) of something that is an iterable. | 96 | * @brief Get the content type(s) of something that is an iterable. | ||
97 | * | 97 | * | ||
98 | * @param iterable Type to get the contents of. Can be an unsure. | 98 | * @param iterable Type to get the contents of. Can be an unsure. | ||
99 | * @return KDevelop::AbstractType::Ptr Content type. Might be an unsure. | 99 | * @return KDevelop::AbstractType::Ptr Content type. Might be an unsure. | ||
100 | */ | 100 | */ | ||
101 | static AbstractType::Ptr contentOfIterable(const AbstractType::Ptr iterable, const TopDUContext* topContext); | 101 | AbstractType::Ptr contentOfIterable(const AbstractType::Ptr iterable, const TopDUContext* topContext); | ||
102 | 102 | | |||
103 | /** | 103 | /** | ||
104 | * @brief Get a list of types inside the passed type which match the specified filter. | 104 | * @brief Get a list of types inside the passed type which match the specified filter. | ||
105 | * The filter will be matched against the type only if it is not an unsure type, | 105 | * The filter will be matched against the type only if it is not an unsure type, | ||
106 | * or else against all types inside that unsure type. | 106 | * or else against all types inside that unsure type. | ||
107 | * @param type The type to search | 107 | * @param type The type to search | ||
108 | * @param accept Filter function, return true if you want the type. | 108 | * @param accept Filter function, return true if you want the type. | ||
109 | * @return QList< KDevelop::AbstractType::Ptr > list of types accepted by the filter. | 109 | * @return QList< KDevelop::AbstractType::Ptr > list of types accepted by the filter. | ||
110 | */ | 110 | */ | ||
111 | template <typename T> | 111 | template <typename T> | ||
112 | static QList<typename T::Ptr> filterType(AbstractType::Ptr type, std::function<bool(AbstractType::Ptr)> accept, | 112 | QList<typename T::Ptr> filterType(AbstractType::Ptr type, std::function<bool(AbstractType::Ptr)> accept, | ||
113 | std::function<typename T::Ptr(AbstractType::Ptr)> map = | 113 | std::function<typename T::Ptr(AbstractType::Ptr)> map = | ||
114 | std::function<typename T::Ptr(AbstractType::Ptr)>()) | 114 | std::function<typename T::Ptr(AbstractType::Ptr)>()) | ||
115 | { | 115 | { | ||
116 | QList<typename T::Ptr> types; | 116 | QList<typename T::Ptr> types; | ||
117 | if ( ! type ) { | 117 | if ( ! type ) { | ||
118 | return types; | 118 | return types; | ||
119 | } | 119 | } | ||
120 | if ( type->whichType() == KDevelop::AbstractType::TypeUnsure ) { | 120 | if ( type->whichType() == KDevelop::AbstractType::TypeUnsure ) { | ||
121 | UnsureType::Ptr unsure(type.cast<UnsureType>()); | 121 | UnsureType::Ptr unsure(type.cast<UnsureType>()); | ||
122 | for ( unsigned int i = 0; i < unsure->typesSize(); i++ ) { | 122 | for ( unsigned int i = 0; i < unsure->typesSize(); i++ ) { | ||
123 | AbstractType::Ptr t = unsure->types()[i].abstractType(); | 123 | AbstractType::Ptr t = unsure->types()[i].abstractType(); | ||
124 | if ( accept(t) ) { | 124 | if ( accept(t) ) { | ||
125 | types << ( map ? map(t) : t.cast<T>() ); | 125 | types << ( map ? map(t) : t.cast<T>() ); | ||
126 | } | 126 | } | ||
127 | } | 127 | } | ||
128 | } | 128 | } | ||
129 | else if ( accept(type) ) { | 129 | else if ( accept(type) ) { | ||
130 | types << ( map ? map(type) : type.cast<T>() ); | 130 | types << ( map ? map(type) : type.cast<T>() ); | ||
131 | } | 131 | } | ||
132 | return types; | 132 | return types; | ||
133 | } | 133 | } | ||
134 | 134 | | |||
135 | static void scheduleDependency(const IndexedString& dependency, int betterThanPriority); | 135 | void scheduleDependency(const IndexedString& dependency, int betterThanPriority); | ||
136 | 136 | | |||
137 | static KDevelop::IndexedDeclaration declarationUnderCursor(bool allowUse = true); | 137 | KDEVPYTHONDUCHAIN_EXPORT KDevelop::IndexedDeclaration declarationUnderCursor(bool allowUse = true); | ||
138 | 138 | | |||
139 | struct FuncInfo { FunctionDeclaration* declaration; bool isConstructor; }; | 139 | struct FuncInfo { FunctionDeclaration* declaration; bool isConstructor; }; | ||
140 | /** | 140 | /** | ||
141 | * @brief Finds whether the specified called declaration is a function declaration, and if not, | 141 | * @brief Finds whether the specified called declaration is a function declaration, and if not, | ||
142 | * checks for a class declaration; then returns the constructor | 142 | * checks for a class declaration; then returns the constructor | ||
143 | * | 143 | * | ||
144 | * @param called the declaration to check | 144 | * @param called the declaration to check | ||
145 | * @param isAlias whether the called declaration aliases a class or function definition. | 145 | * @param isAlias whether the called declaration aliases a class or function definition. | ||
146 | * @return the function pointer which was found, or an invalid pointer, and a bool | 146 | * @return the function pointer which was found, or an invalid pointer, and a bool | ||
147 | * which is true when it is a constructor | 147 | * which is true when it is a constructor | ||
148 | **/ | 148 | **/ | ||
149 | static FuncInfo functionForCalled(Declaration* called, bool isAlias=true); | 149 | KDEVPYTHONDUCHAIN_EXPORT FuncInfo functionForCalled(Declaration* called, bool isAlias=true); | ||
150 | 150 | | |||
151 | static bool docstringContainsHint(const QString& comment, const QString& hintName, QStringList* args = nullptr) { | 151 | inline bool docstringContainsHint(const QString& comment, const QString& hintName, QStringList* args = nullptr) { | ||
152 | // TODO cache types! this is horribly inefficient | 152 | // TODO cache types! this is horribly inefficient | ||
153 | const QString search = "! " + hintName + " !"; | 153 | const QString search = "! " + hintName + " !"; | ||
154 | int index = comment.indexOf(search); | 154 | int index = comment.indexOf(search); | ||
155 | if ( index >= 0 ) { | 155 | if ( index >= 0 ) { | ||
156 | if ( args ) { | 156 | if ( args ) { | ||
157 | int eol = comment.indexOf('\n', index); | 157 | int eol = comment.indexOf('\n', index); | ||
158 | int start = index+search.size()+1; | 158 | int start = index+search.size()+1; | ||
159 | QString decl = comment.mid(start, eol-start); | 159 | QString decl = comment.mid(start, eol-start); | ||
160 | *args = decl.split(' '); | 160 | *args = decl.split(' '); | ||
161 | } | 161 | } | ||
162 | return true; | 162 | return true; | ||
163 | } | 163 | } | ||
164 | return false; | 164 | return false; | ||
165 | } | 165 | } | ||
166 | 166 | | |||
167 | /** | 167 | /** | ||
168 | * @copydoc TypeUtils::mergeTypes | 168 | * @copydoc TypeUtils::mergeTypes | ||
169 | */ | 169 | */ | ||
170 | static AbstractType::Ptr mergeTypes(AbstractType::Ptr type, const AbstractType::Ptr newType); | 170 | AbstractType::Ptr mergeTypes(AbstractType::Ptr type, const AbstractType::Ptr newType); | ||
171 | 171 | | |||
172 | /** | 172 | /** | ||
173 | * @brief Like mergeTypes(), but merges a list of types into a newly allocated type. | 173 | * @brief Like mergeTypes(), but merges a list of types into a newly allocated type. | ||
174 | * Returns mixed if the list is empty. | 174 | * Returns mixed if the list is empty. | ||
175 | * @return KDevelop::AbstractType::Ptr an unsure type consisting of all types in the list. | 175 | * @return KDevelop::AbstractType::Ptr an unsure type consisting of all types in the list. | ||
176 | */ | 176 | */ | ||
177 | template <typename T> | 177 | template <typename T> | ||
178 | static AbstractType::Ptr foldTypes(QList<T> types, std::function<AbstractType::Ptr(const T&)> transform | 178 | AbstractType::Ptr foldTypes(QList<T> types, std::function<AbstractType::Ptr(const T&)> transform | ||
179 | = std::function<AbstractType::Ptr(const T&)>()) | 179 | = std::function<AbstractType::Ptr(const T&)>()) | ||
180 | { | 180 | { | ||
181 | AbstractType::Ptr result(new IntegralType(IntegralType::TypeMixed)); | 181 | AbstractType::Ptr result(new IntegralType(IntegralType::TypeMixed)); | ||
182 | for ( T type : types ) { | 182 | for ( T type : types ) { | ||
183 | result = Helper::mergeTypes(result, transform ? transform(type) : AbstractType::Ptr::staticCast(type)); | 183 | result = Helper::mergeTypes(result, transform ? transform(type) : AbstractType::Ptr::staticCast(type)); | ||
184 | } | 184 | } | ||
185 | return result; | 185 | return result; | ||
186 | }; | 186 | }; | ||
187 | 187 | | |||
188 | /** check whether the argument is a null, mixed, or none integral type **/ | 188 | /** check whether the argument is a null, mixed, or none integral type **/ | ||
189 | static bool isUsefulType(AbstractType::Ptr type); | 189 | bool isUsefulType(AbstractType::Ptr type); | ||
190 | 190 | | |||
191 | enum ContextSearchFlags { | 191 | enum ContextSearchFlags { | ||
192 | NoFlags, | 192 | NoFlags, | ||
193 | PublicOnly | 193 | PublicOnly | ||
194 | }; | 194 | }; | ||
195 | 195 | | |||
196 | /** | 196 | /** | ||
197 | * @brief Find all internal contexts for this class and its base classes recursively | 197 | * @brief Find all internal contexts for this class and its base classes recursively | ||
198 | * | 198 | * | ||
199 | * @param classType Type object for the class to search contexts | 199 | * @param classType Type object for the class to search contexts | ||
200 | * @param context TopContext for finding the declarations for types | 200 | * @param context TopContext for finding the declarations for types | ||
201 | * @return list of contexts which were found | 201 | * @return list of contexts which were found | ||
202 | **/ | 202 | **/ | ||
203 | static QVector<DUContext*> internalContextsForClass(const KDevelop::StructureType::Ptr classType, | 203 | KDEVPYTHONDUCHAIN_EXPORT QVector<DUContext*> internalContextsForClass(const KDevelop::StructureType::Ptr classType, | ||
204 | const TopDUContext* context, | 204 | const TopDUContext* context, | ||
205 | ContextSearchFlags flags = NoFlags, int depth = 0); | 205 | ContextSearchFlags flags = NoFlags, int depth = 0); | ||
206 | /** | 206 | /** | ||
207 | * @brief Resolve the given declaration if it is an alias declaration. | 207 | * @brief Resolve the given declaration if it is an alias declaration. | ||
208 | * | 208 | * | ||
209 | * @param decl the declaration to resolve | 209 | * @param decl the declaration to resolve | ||
210 | * @return :Declaration* decl if not an alias declaration, decl->aliasedDeclaration().data otherwise | 210 | * @return :Declaration* decl if not an alias declaration, decl->aliasedDeclaration().data otherwise | ||
211 | * DUChain must be read locked | 211 | * DUChain must be read locked | ||
212 | **/ | 212 | **/ | ||
213 | static Declaration* resolveAliasDeclaration(Declaration* decl); | 213 | KDEVPYTHONDUCHAIN_EXPORT Declaration* resolveAliasDeclaration(Declaration* decl); | ||
214 | 214 | | |||
215 | static Declaration* declarationForName(const QString& name, const CursorInRevision& location, | 215 | KDEVPYTHONDUCHAIN_EXPORT Declaration* declarationForName(const QString& name, const CursorInRevision& location, | ||
216 | DUChainPointer<const DUContext> context); | 216 | DUChainPointer<const DUContext> context); | ||
217 | 217 | | |||
218 | static Declaration* declarationForName(const Python::NameAst* name, CursorInRevision location, | 218 | Declaration* declarationForName(const Python::NameAst* name, CursorInRevision location, | ||
219 | DUChainPointer<const DUContext> context); | 219 | DUChainPointer<const DUContext> context); | ||
220 | 220 | | |||
221 | static QString getPythonExecutablePath(IProject* project); | 221 | KDEVPYTHONDUCHAIN_EXPORT QString getPythonExecutablePath(IProject* project); | ||
222 | }; | | |||
223 | 222 | | |||
224 | } | | |||
225 | 223 | | |||
226 | #endif | 224 | } // namespace Helper | ||
225 | } // namespace Python | ||||
227 | 226 | | |||
227 | #endif |