File indexing completed on 2024-04-21 15:25:24
0001 /* 0002 SPDX-FileCopyrightText: 2011-2012 Sven Brauch <svenbrauch@googlemail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef GLOBALHELPERS_H 0008 #define GLOBALHELPERS_H 0009 0010 #include "pythonduchainexport.h" 0011 #include "types/unsuretype.h" 0012 #include "ast.h" 0013 0014 #include <interfaces/iproject.h> 0015 #include <language/duchain/declaration.h> 0016 #include <language/duchain/types/unsuretype.h> 0017 #include <language/duchain/topducontext.h> 0018 #include <language/duchain/types/structuretype.h> 0019 #include <language/duchain/types/integraltype.h> 0020 #include <language/duchain/classdeclaration.h> 0021 #include <language/duchain/functiondeclaration.h> 0022 0023 #include <QList> 0024 0025 #include <functional> 0026 0027 #include "declarations/functiondeclaration.h" 0028 0029 using namespace KDevelop; 0030 0031 namespace Python { 0032 0033 class KDEVPYTHONDUCHAIN_EXPORT Helper { 0034 public: 0035 /** get search paths for python files **/ 0036 static QVector<QUrl> getSearchPaths(const QUrl& workingOnDocument); 0037 static QStringList dataDirs; 0038 static IndexedString documentationFile; 0039 static QStringList correctionFileDirs; 0040 static QString localCorrectionFileDir; 0041 static DUChainPointer<TopDUContext> documentationFileContext; 0042 0043 static QStringList getDataDirs(); 0044 static IndexedString getDocumentationFile(); 0045 static ReferencedTopDUContext getDocumentationFileContext(); 0046 0047 static QUrl getCorrectionFile(const QUrl& document); 0048 static QUrl getLocalCorrectionFile(const QUrl& document); 0049 0050 static QMutex cacheMutex; 0051 static QMap<IProject*, QVector<QUrl>> cachedCustomIncludes; 0052 static QMap<IProject*, QVector<QUrl>> cachedSearchPaths; 0053 0054 static QMutex projectPathLock; 0055 static QVector<QUrl> projectSearchPaths; 0056 0057 static AbstractType::Ptr extractTypeHints(AbstractType::Ptr type); 0058 0059 /** 0060 * @brief Get the declaration of 'accessed.attribute', or return null. 0061 * 0062 * @param accessed Type (Structure or Unsure) that should have this attribute. 0063 * @param attribute Which attribute to look for. 0064 * @param topContext Top context (for this file?) 0065 * @return Declaration* of the attribute, or null. 0066 * If UnsureType with >1 matching attributes, returns an arbitrary choice. 0067 **/ 0068 static KDevelop::Declaration* accessAttribute(const KDevelop::AbstractType::Ptr accessed, 0069 const KDevelop::IndexedIdentifier& attribute, 0070 const KDevelop::TopDUContext* topContext); 0071 0072 static KDevelop::Declaration* accessAttribute(const KDevelop::AbstractType::Ptr accessed, 0073 const QString& attribute, const KDevelop::TopDUContext* topContext) { 0074 return accessAttribute(accessed, IndexedIdentifier(KDevelop::Identifier(attribute)), topContext); 0075 } 0076 0077 static AbstractType::Ptr resolveAliasType(const AbstractType::Ptr eventualAlias); 0078 0079 /** 0080 * @brief Get the content type(s) of something that is an iterable. 0081 * 0082 * @param iterable Type to get the contents of. Can be an unsure. 0083 * @return KDevelop::AbstractType::Ptr Content type. Might be an unsure. 0084 */ 0085 static AbstractType::Ptr contentOfIterable(const AbstractType::Ptr iterable, const TopDUContext* topContext); 0086 0087 /** 0088 * @brief Get a list of types inside the passed type which match the specified filter. 0089 * The filter will be matched against the type only if it is not an unsure type, 0090 * or else against all types inside that unsure type. 0091 * @param type The type to search 0092 * @param accept Filter function, return true if you want the type. 0093 * @return QList< KDevelop::AbstractType::Ptr > list of types accepted by the filter. 0094 */ 0095 template <typename T> 0096 static QList<typename T::Ptr> filterType(AbstractType::Ptr type, std::function<bool(AbstractType::Ptr)> accept, 0097 std::function<typename T::Ptr(AbstractType::Ptr)> map = 0098 std::function<typename T::Ptr(AbstractType::Ptr)>()) 0099 { 0100 QList<typename T::Ptr> types; 0101 if ( ! type ) { 0102 return types; 0103 } 0104 if ( type->whichType() == KDevelop::AbstractType::TypeUnsure ) { 0105 auto unsure = type.staticCast<UnsureType>(); 0106 for ( unsigned int i = 0; i < unsure->typesSize(); i++ ) { 0107 AbstractType::Ptr t = unsure->types()[i].abstractType(); 0108 if ( accept(t) ) { 0109 types << ( map ? map(t) : t.dynamicCast<T>() ); 0110 } 0111 } 0112 } 0113 else if ( accept(type) ) { 0114 types << ( map ? map(type) : type.dynamicCast<T>() ); 0115 } 0116 return types; 0117 } 0118 0119 static void scheduleDependency(const IndexedString& dependency, int betterThanPriority); 0120 0121 static KDevelop::IndexedDeclaration declarationUnderCursor(bool allowUse = true); 0122 0123 struct FuncInfo { FunctionDeclaration* declaration; bool isConstructor; }; 0124 /** 0125 * @brief Finds whether the specified called declaration is a function declaration, and if not, 0126 * checks for a class declaration; then returns the constructor 0127 * 0128 * @param called the declaration to check 0129 * @param isAlias whether the called declaration aliases a class or function definition. 0130 * @return the function pointer which was found, or an invalid pointer, and a bool 0131 * which is true when it is a constructor 0132 **/ 0133 static FuncInfo functionForCalled(Declaration* called, bool isAlias=true); 0134 0135 static bool docstringContainsHint(const QString& comment, const QString& hintName, QStringList* args = nullptr) { 0136 // TODO cache types! this is horribly inefficient 0137 const QString search = "! " + hintName + " !"; 0138 int index = comment.indexOf(search); 0139 if ( index >= 0 ) { 0140 if ( args ) { 0141 int eol = comment.indexOf('\n', index); 0142 int start = index+search.size()+1; 0143 QString decl = comment.mid(start, eol-start); 0144 *args = decl.split(' '); 0145 } 0146 return true; 0147 } 0148 return false; 0149 } 0150 0151 /** 0152 * @copydoc TypeUtils::mergeTypes 0153 */ 0154 static AbstractType::Ptr mergeTypes(AbstractType::Ptr type, const AbstractType::Ptr newType); 0155 0156 /** 0157 * @brief Like mergeTypes(), but merges a list of types into a newly allocated type. 0158 * Returns mixed if the list is empty. 0159 * @return KDevelop::AbstractType::Ptr an unsure type consisting of all types in the list. 0160 */ 0161 template <typename T> 0162 static AbstractType::Ptr foldTypes(QList<T> types, std::function<AbstractType::Ptr(const T&)> transform 0163 = std::function<AbstractType::Ptr(const T&)>()) 0164 { 0165 AbstractType::Ptr result(new IntegralType(IntegralType::TypeMixed)); 0166 for ( T type : types ) { 0167 result = Helper::mergeTypes(result, transform ? transform(type) : type); 0168 } 0169 return result; 0170 }; 0171 0172 /** check whether the argument is a null, mixed, or none integral type **/ 0173 static bool isUsefulType(AbstractType::Ptr type); 0174 0175 enum ContextSearchFlags { 0176 NoFlags, 0177 PublicOnly 0178 }; 0179 0180 /** 0181 * @brief Find all internal contexts for this class and its base classes recursively 0182 * 0183 * @param classType Type object for the class to search contexts 0184 * @param context TopContext for finding the declarations for types 0185 * @return list of contexts which were found 0186 **/ 0187 static QVector<DUContext*> internalContextsForClass(const KDevelop::StructureType::Ptr classType, 0188 const TopDUContext* context, 0189 ContextSearchFlags flags = NoFlags, int depth = 0); 0190 /** 0191 * @brief Resolve the given declaration if it is an alias declaration. 0192 * 0193 * @param decl the declaration to resolve 0194 * @return :Declaration* decl if not an alias declaration, decl->aliasedDeclaration().data otherwise 0195 * DUChain must be read locked 0196 **/ 0197 static Declaration* resolveAliasDeclaration(Declaration* decl); 0198 0199 static Declaration* declarationForName(const QString& name, const CursorInRevision& location, 0200 DUChainPointer<const DUContext> context); 0201 0202 static Declaration* declarationForName(const Python::NameAst* name, CursorInRevision location, 0203 DUChainPointer<const DUContext> context); 0204 0205 static QString getPythonExecutablePath(IProject* project); 0206 }; 0207 0208 } 0209 0210 #endif 0211