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