File indexing completed on 2024-05-05 16:42:28

0001 /*
0002     SPDX-FileCopyrightText: 2010 Miquel Canes Gonzalez <miquelcanes@gmail.com>
0003     SPDX-FileCopyrightText: 2011-2014 Sven Brauch <svenbrauch@googlemail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #ifndef EXPRESSIONVISITOR_H
0009 #define EXPRESSIONVISITOR_H
0010 
0011 #include <QHash>
0012 #include <KLocalizedString>
0013 
0014 #include <language/duchain/types/abstracttype.h>
0015 #include <language/duchain/types/integraltype.h>
0016 #include <language/duchain/types/typesystemdata.h>
0017 #include <language/duchain/types/typeregister.h>
0018 #include <language/duchain/types/containertypes.h>
0019 #include <language/duchain/duchainpointer.h>
0020 #include <language/duchain/declaration.h>
0021 #include <language/duchain/types/structuretype.h>
0022 #include <language/duchain/classdeclaration.h>
0023 #include <language/duchain/functiondeclaration.h>
0024 #include <language/duchain/builders/dynamiclanguageexpressionvisitor.h>
0025 
0026 #include "astdefaultvisitor.h"
0027 #include "pythonduchainexport.h"
0028 #include "pythoneditorintegrator.h"
0029 
0030 #include "duchain/declarations/functiondeclaration.h"
0031 #include "duchain/helpers.h"
0032 
0033 using namespace KDevelop;
0034 class Identifier;
0035 
0036 namespace Python
0037 {
0038 
0039 typedef DUChainPointer<FunctionDeclaration> FunctionDeclarationPointer;
0040 
0041 class KDEVPYTHONDUCHAIN_EXPORT ExpressionVisitor : public AstDefaultVisitor, public DynamicLanguageExpressionVisitor
0042 {
0043 public:
0044     ExpressionVisitor(const KDevelop::DUContext* ctx);
0045     /// Use this to construct the expression-visitor recursively
0046     ExpressionVisitor(Python::ExpressionVisitor* parent, const DUContext* overrideContext=nullptr);
0047 
0048     void visitBinaryOperation(BinaryOperationAst* node) override;
0049     void visitUnaryOperation(UnaryOperationAst* node) override;
0050     void visitBooleanOperation(BooleanOperationAst* node) override;
0051     void visitCompare(CompareAst* node) override;
0052 
0053     void visitString(StringAst* node) override;
0054     void visitBytes(BytesAst* node) override;
0055     void visitFormattedValue(FormattedValueAst * node) override;
0056     void visitJoinedString(JoinedStringAst* node) override;
0057     void visitNumber(NumberAst* node) override;
0058     void visitName(NameAst* node) override;
0059     void visitList(ListAst* node) override;
0060     void visitDict(DictAst* node) override;
0061     void visitSet(SetAst* node) override;
0062     void visitSubscript(SubscriptAst* node) override;
0063     void visitCall(CallAst* node) override;
0064     void visitAttribute(AttributeAst* node) override;
0065     void visitTuple(TupleAst* node) override;
0066     void visitLambda(LambdaAst* node) override;
0067     void visitListComprehension(ListComprehensionAst* node) override;
0068     void visitDictionaryComprehension(DictionaryComprehensionAst* node) override;
0069     void visitSetComprehension(SetComprehensionAst* node) override;
0070     void visitIfExpression(IfExpressionAst* node) override;
0071     void visitNameConstant(NameConstantAst* node) override;
0072     void visitAssignmentExpression(AssignmentExpressionAst* node) override;
0073 
0074     /**
0075      * @brief Checks for magic docstrings that override a call's return type.
0076      *
0077      * @param node The node to visit.
0078      * @param normalType The return type as determined without docstrings.
0079      * @param docstring Docstring of the function.
0080      */
0081     AbstractType::Ptr docstringTypeOverride(CallAst* node, const AbstractType::Ptr normalType,
0082                                               const QString& docstring);
0083 
0084     bool isAlias() const {
0085         return m_isAlias;
0086     }
0087 
0088     void enableGlobalSearching() {
0089         m_forceGlobalSearching = true;
0090     }
0091 
0092     void enableUnknownNameReporting() {
0093         m_reportUnknownNames = true;
0094     }
0095 
0096     void scanUntil(const CursorInRevision& end) {
0097         m_scanUntilCursor = end;
0098     }
0099 
0100     QSet<QString> unknownNames() const {
0101         return m_unknownNames;
0102     }
0103 
0104     template<typename T>
0105     static TypePtr<T> typeObjectForIntegralType(const QString& typeDescriptor) {
0106         auto context = Helper::getDocumentationFileContext();
0107         if ( ! context ) {
0108             return {};
0109         }
0110         auto decls = context->findDeclarations(QualifiedIdentifier(typeDescriptor));
0111         auto decl = decls.isEmpty() ? nullptr : dynamic_cast<Declaration*>(decls.first());
0112         if ( ! decl ) {
0113             return {};
0114         }
0115         return decl->abstractType().dynamicCast<T>();
0116     }
0117 
0118 private:
0119     AbstractType::Ptr fromBinaryOperator(AbstractType::Ptr lhs, AbstractType::Ptr rhs, const QString& op);
0120     AbstractType::Ptr encounterPreprocess(AbstractType::Ptr type, bool merge=false);
0121     void encounter(AbstractType::Ptr type, DeclarationPointer declaration=DeclarationPointer(), bool alias=false);
0122 
0123     void addUnknownName(const QString& name);
0124 
0125     AbstractType::Ptr encounterPreprocess(AbstractType::Ptr type) override;
0126 
0127     void setLastIsAlias(bool alias) {
0128         m_isAlias = alias;
0129     }
0130 
0131 private:
0132     /// tells whether the returned declaration is an alias
0133     bool m_isAlias = false;
0134     /// used by code completion to disable range checks on declaration searches
0135     bool m_forceGlobalSearching = false;
0136     /// used by code completion to detect unknown NameAst elements in expressions
0137     bool m_reportUnknownNames = false;
0138     CursorInRevision m_scanUntilCursor = CursorInRevision::invalid();
0139     static QHash<NameConstantAst::NameConstantTypes, KDevelop::AbstractType::Ptr> m_defaultTypes;
0140     QSet<QString> m_unknownNames;
0141 };
0142 
0143 }
0144 
0145 #endif // EXPRESSIONVISITOR_H