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-2013 Sven Brauch <svenbrauch@googlemail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "expressionvisitor.h"
0009 #include "types/nonetype.h"
0010 #include "types/indexedcontainer.h"
0011 #include "declarations/functiondeclaration.h"
0012 #include "pythonduchainexport.h"
0013 #include "pythoneditorintegrator.h"
0014 #include "helpers.h"
0015 
0016 #include <language/duchain/types/containertypes.h>
0017 #include <language/duchain/types/unsuretype.h>
0018 #include <language/duchain/types/integraltype.h>
0019 #include <language/duchain/types/typeregister.h>
0020 #include <language/duchain/types/typesystemdata.h>
0021 #include <language/duchain/types/functiontype.h>
0022 #include <language/duchain/declaration.h>
0023 #include <language/duchain/functiondeclaration.h>
0024 #include <language/duchain/classdeclaration.h>
0025 #include <language/duchain/aliasdeclaration.h>
0026 #include <language/duchain/ducontext.h>
0027 
0028 #include <QDebug>
0029 #include "duchaindebug.h"
0030 
0031 #include <KLocalizedString>
0032 
0033 #include <functional>
0034 
0035 using namespace KDevelop;
0036 using namespace Python;
0037 using namespace KTextEditor;
0038 
0039 namespace Python {
0040 
0041 QHash<NameConstantAst::NameConstantTypes, KDevelop::AbstractType::Ptr> ExpressionVisitor::m_defaultTypes;
0042 
0043 AbstractType::Ptr ExpressionVisitor::encounterPreprocess(AbstractType::Ptr type)
0044 {
0045     return Helper::resolveAliasType(type);
0046 }
0047 
0048 ExpressionVisitor::ExpressionVisitor(const DUContext* ctx)
0049     : DynamicLanguageExpressionVisitor(ctx)
0050 {
0051     if ( m_defaultTypes.isEmpty() ) {
0052         m_defaultTypes.insert(NameConstantAst::True, AbstractType::Ptr(new IntegralType(IntegralType::TypeBoolean)));
0053         m_defaultTypes.insert(NameConstantAst::False, AbstractType::Ptr(new IntegralType(IntegralType::TypeBoolean)));
0054         m_defaultTypes.insert(NameConstantAst::None, AbstractType::Ptr(new NoneType()));
0055     }
0056     Q_ASSERT(context());
0057     Q_ASSERT(context()->topContext());
0058 }
0059 
0060 ExpressionVisitor::ExpressionVisitor(ExpressionVisitor* parent, const DUContext* overrideContext)
0061     : DynamicLanguageExpressionVisitor(parent)
0062     , m_forceGlobalSearching(parent->m_forceGlobalSearching)
0063     , m_reportUnknownNames(parent->m_reportUnknownNames)
0064     , m_scanUntilCursor(parent->m_scanUntilCursor)
0065 {
0066     if ( overrideContext ) {
0067         m_context = overrideContext;
0068     }
0069     Q_ASSERT(context());
0070 }
0071 
0072 void ExpressionVisitor::encounter(AbstractType::Ptr type, DeclarationPointer declaration, bool alias)
0073 {
0074     setLastIsAlias(alias);
0075     DynamicLanguageExpressionVisitor::encounter(type, declaration);
0076 }
0077 
0078 void ExpressionVisitor::visitAttribute(AttributeAst* node)
0079 {
0080     ExpressionVisitor v(this);
0081     v.visitNode(node->value);
0082     setConfident(false);
0083 
0084     // Find a matching declaration which is made inside the type of the accessed object.
0085     // Like, for B.C where B is an instance of foo, find a property of foo called C.
0086     DUChainReadLocker lock;
0087     auto attribute = Helper::accessAttribute(v.lastType(), node->attribute->value, topContext());
0088     auto resolved = Helper::resolveAliasDeclaration(attribute);
0089     if ( ! resolved ) {
0090         encounterUnknown();
0091         return;
0092     }
0093     auto function = dynamic_cast<FunctionDeclaration*>(resolved);
0094     if ( function && function->type<FunctionType>() &&
0095           function->isProperty() ) {
0096         encounter(function->type<FunctionType>()->returnType(), DeclarationPointer(function));
0097         return;
0098     }
0099     encounter(attribute->abstractType(), DeclarationPointer(attribute));
0100     setLastIsAlias(function ||
0101                     dynamic_cast<AliasDeclaration*>(attribute) ||
0102                     dynamic_cast<ClassDeclaration*>(resolved) );
0103 }
0104 
0105 void ExpressionVisitor::visitCall(CallAst* node)
0106 {
0107     visitNodeList(node->arguments);
0108     ExpressionVisitor v(this);
0109     v.visitNode(node->function);
0110     auto declaration = Helper::resolveAliasDeclaration(v.lastDeclaration().data());
0111     if ( ! v.isAlias() && v.lastType() ) {
0112         if ( auto functionType = v.lastType().dynamicCast<FunctionType>() ) {
0113             encounter(functionType->returnType());
0114             return;
0115         }
0116         if ( auto classType = v.lastType().dynamicCast<StructureType>() ) {
0117             declaration = classType->declaration(topContext());
0118         }
0119     }
0120     if ( ! declaration ) {
0121         encounterUnknown();
0122         return;
0123     }
0124     ClassDeclaration* classDecl = dynamic_cast<ClassDeclaration*>(declaration);
0125     DUChainReadLocker lock;
0126     auto function = Helper::functionForCalled(declaration, v.isAlias());
0127     lock.unlock();
0128 
0129     AbstractType::Ptr type;
0130     Declaration* decl;
0131 
0132     if ( function.isConstructor && classDecl ) {
0133         // Don't use return type from constructor.
0134         // It's wrong for builtins, or classes without their own __init__ methods().
0135         type = classDecl->abstractType();
0136         decl = classDecl;
0137     }
0138     else if ( function.declaration && function.declaration->type<FunctionType>() ) {
0139         // But do use the return value of normal functions or __call__().
0140         type = function.declaration->type<FunctionType>()->returnType();
0141         decl = function.declaration;
0142     }
0143     else {
0144         qCDebug(KDEV_PYTHON_DUCHAIN) << "Declaration is not a class or function declaration";
0145         encounterUnknown();
0146         return;
0147     }
0148     if ( function.declaration ) {
0149         auto docstring = function.declaration->comment();
0150         if ( ! docstring.isEmpty() ) {
0151             // Our documentation data uses special docstrings that override the return type
0152             //  of some functions (including constructors).
0153             type = docstringTypeOverride(node, type, docstring);
0154         }
0155     }
0156     encounter(type, DeclarationPointer(decl));
0157 }
0158 
0159 AbstractType::Ptr ExpressionVisitor::docstringTypeOverride(
0160     CallAst* node, const AbstractType::Ptr normalType, const QString& docstring)
0161 {
0162     auto docstringType = normalType;
0163     auto listOfTuples = [&](AbstractType::Ptr key, AbstractType::Ptr value) {
0164         auto newType = typeObjectForIntegralType<ListType>("list");
0165         IndexedContainer::Ptr newContents = typeObjectForIntegralType<IndexedContainer>("tuple");
0166         if ( ! newType || ! newContents ) {
0167             return AbstractType::Ptr(new IntegralType(IntegralType::TypeMixed));
0168         }
0169         if ( ! key ) {
0170             key = AbstractType::Ptr(new IntegralType(IntegralType::TypeMixed));
0171         }
0172         if ( ! value ) {
0173             value = AbstractType::Ptr(new IntegralType(IntegralType::TypeMixed));
0174         }
0175         newContents->addEntry(key);
0176         newContents->addEntry(value);
0177         newType->addContentType<Python::UnsureType>(newContents);
0178         return newType.staticCast<AbstractType>();
0179     };
0180 
0181     QHash< QString, std::function<bool(QStringList, QString)> > knownDocstringHints;
0182     knownDocstringHints["getsType"] = [&](QStringList /*arguments*/, QString /*currentHint*/) {
0183         if ( node->function->astType != Ast::AttributeAstType ) {
0184             return false;
0185         }
0186         ExpressionVisitor baseTypeVisitor(this);
0187         // when calling foo.bar[3].baz.iteritems(), find the type of "foo.bar[3].baz"
0188         baseTypeVisitor.visitNode(static_cast<AttributeAst*>(node->function)->value);
0189         if ( auto t = baseTypeVisitor.lastType().dynamicCast<ListType>() ) {
0190             docstringType = t->contentType().abstractType();
0191             return true;
0192         }
0193         return false;
0194     };
0195 
0196     knownDocstringHints["getsList"] = [&](QStringList /*arguments*/, QString currentHint) {
0197         if ( node->function->astType != Ast::AttributeAstType ) {
0198             return false;
0199         }
0200         ExpressionVisitor baseTypeVisitor(this);
0201         // when calling foo.bar[3].baz.iteritems(), find the type of "foo.bar[3].baz"
0202         baseTypeVisitor.visitNode(static_cast<AttributeAst*>(node->function)->value);
0203         DUChainReadLocker lock;
0204         if ( auto t = baseTypeVisitor.lastType().dynamicCast<ListType>() ) {
0205             auto newType = typeObjectForIntegralType<ListType>("list");
0206             if ( ! newType ) {
0207                 return false;
0208             }
0209             AbstractType::Ptr contentType;
0210             if ( currentHint == "getsList" ) {
0211                 contentType = t->contentType().abstractType();
0212             }
0213             else if ( auto map = t.dynamicCast<MapType>() ) {
0214                 contentType = map->keyType().abstractType();
0215             }
0216             newType->addContentType<Python::UnsureType>(contentType);
0217             docstringType = newType;
0218             return true;
0219         }
0220         return false;
0221     };
0222     knownDocstringHints["getListOfKeys"] = knownDocstringHints["getsList"];
0223 
0224     knownDocstringHints["enumerate"] = [&](QStringList /*arguments*/, QString /*currentHint*/) {
0225         if ( node->function->astType != Ast::NameAstType || node->arguments.size() < 1 ) {
0226             return false;
0227         }
0228         ExpressionVisitor enumeratedTypeVisitor(this);
0229         enumeratedTypeVisitor.visitNode(node->arguments.first());
0230 
0231         DUChainReadLocker lock;
0232         auto intType = typeObjectForIntegralType<AbstractType>("int");
0233         auto enumerated = enumeratedTypeVisitor.lastType();
0234         docstringType = listOfTuples(intType, Helper::contentOfIterable(enumerated, topContext()));
0235         return true;
0236     };
0237 
0238     knownDocstringHints["getsListOfBoth"] = [&](QStringList /*arguments*/, QString /*currentHint*/) {
0239         if ( node->function->astType != Ast::AttributeAstType ) {
0240             return false;
0241         }
0242         ExpressionVisitor baseTypeVisitor(this);
0243         // when calling foo.bar[3].baz.iteritems(), find the type of "foo.bar[3].baz"
0244         baseTypeVisitor.visitNode(static_cast<AttributeAst*>(node->function)->value);
0245         DUChainReadLocker lock;
0246         if ( auto t = baseTypeVisitor.lastType().dynamicCast<MapType>() ) {
0247             docstringType = listOfTuples(t->keyType().abstractType(), t->contentType().abstractType());
0248             return true;
0249         }
0250         return false;
0251     };
0252 
0253     knownDocstringHints["returnContentEqualsContentOf"] = [&](QStringList arguments, QString /*currentHint*/) {
0254         const int argNum = ! arguments.isEmpty() ? (int) arguments.at(0).toUInt() : 0;
0255         if ( argNum >= node->arguments.length() ) {
0256             return false;
0257         }
0258         ExpressionAst* relevantArgument = node->arguments.at(argNum);
0259         ExpressionVisitor v(this);
0260         v.visitNode(relevantArgument);
0261         if ( ! v.lastType() ) {
0262             return false;
0263         }
0264         AbstractType::Ptr newType;
0265         if ( auto targetContainer = normalType.dynamicCast<ListType>() ) {
0266             // Copy the return type, to set contents for this call only.
0267             docstringType = AbstractType::Ptr(targetContainer->clone());
0268             // Add content type of the source.
0269             auto sourceContentType = Helper::contentOfIterable(v.lastType(), topContext());
0270             docstringType.staticCast<ListType>()->addContentType<Python::UnsureType>(sourceContentType);
0271         }
0272         else if ( auto sourceContainer = v.lastType().dynamicCast<ListType>() ) {
0273             // if the function does not force a return type, just copy the source (like for reversed())
0274             docstringType = AbstractType::Ptr(sourceContainer->clone());
0275         }
0276         else {
0277             return false; // No target container type
0278         }
0279         Q_ASSERT(docstringType);
0280         return true;
0281     };
0282 
0283     foreach ( const QString& currentHint, knownDocstringHints.keys() ) {
0284         QStringList arguments;
0285         if ( ! Helper::docstringContainsHint(docstring, currentHint, &arguments) ) {
0286             continue;
0287         }
0288         // If the hint word appears in the docstring, run the evaluation function.
0289         if ( knownDocstringHints[currentHint](arguments, currentHint) ) {
0290             // We indeed found something, so we're done.
0291             break;
0292         }
0293     }
0294     return docstringType;
0295 }
0296 
0297 long integerValue(ExpressionAst* node, long wrapTo=0) {
0298     bool invert = false;
0299     if ( node->astType == Ast::UnaryOperationAstType ) {
0300         auto unaryOp = static_cast<UnaryOperationAst*>(node);
0301         if ( unaryOp->type == Ast::UnaryOperatorSub ) {
0302             node = unaryOp->operand;
0303             invert = true;
0304         }
0305     }
0306     if ( node->astType == Ast::NumberAstType ) {
0307         auto number = static_cast<NumberAst*>(node);
0308         if ( number->isInt ) {
0309             // Clamp in case of `a[-9999999:9999999]` or similar.
0310             // -1 is just as out-of-range as -99999999, but doesn't cause a huge loop.
0311             long upperBound = wrapTo ? wrapTo : LONG_MAX;
0312             if (invert) {
0313                 return qBound(-1L, wrapTo - number->value, upperBound);
0314             }
0315             return qBound(-1L, number->value, upperBound);
0316         }
0317     }
0318     return LONG_MIN;
0319 }
0320 
0321 void ExpressionVisitor::visitSubscript(SubscriptAst* node)
0322 {
0323     AstDefaultVisitor::visitNode(node->value);
0324 
0325     auto valueTypes = Helper::filterType<AbstractType>(lastType(), [](AbstractType::Ptr) { return true; });
0326     AbstractType::Ptr result(new IntegralType(IntegralType::TypeMixed));
0327 
0328     foreach (const auto& type, valueTypes) {
0329         if ( node->slice->astType == Ast::SliceAstType ) {
0330             auto slice = static_cast<SliceAst*>(node->slice);
0331             if ( auto tupleType = type.dynamicCast<IndexedContainer>() ) {
0332                 DUChainReadLocker lock;
0333                 auto newTuple = typeObjectForIntegralType<IndexedContainer>("tuple");
0334                 if ( ! newTuple ) {
0335                     continue;
0336                 }
0337                 long step = slice->step ? integerValue(slice->step) : 1;
0338                 int len = tupleType->typesCount();
0339                 long lower = slice->lower ? integerValue(slice->lower, len) : ((step > 0) ? 0 : len - 1);
0340                 long upper = slice->upper ? integerValue(slice->upper, len) : ((step > 0) ? len : -1);
0341                 if ( step != LONG_MIN && lower != LONG_MIN && upper != LONG_MIN) {
0342                     long ii = lower;
0343                     while ( (upper - ii) * step > 0 ) {
0344                         if ( 0 <= ii && ii < len ) {
0345                             newTuple->addEntry(tupleType->typeAt(ii).abstractType());
0346                         }
0347                         ii += step;
0348                     }
0349                 }
0350                 result = Helper::mergeTypes(result, newTuple);
0351                 continue;
0352             }
0353         }
0354         if ( (node->slice->astType == Ast::SliceAstType) && type.dynamicCast<ListType>() ) {
0355             if ( type.dynamicCast<MapType>() ) {
0356                 continue; // Can't slice dicts.
0357             }
0358             // Assume that slicing (e.g. foo[3:5]) a list returns the same type.
0359             result = Helper::mergeTypes(result, type);
0360         }
0361         else if ( const auto& indexed = type.dynamicCast<IndexedContainer>() ) {
0362             long sliceIndex = integerValue(node->slice, indexed->typesCount());
0363             if ( 0 <= sliceIndex && sliceIndex < indexed->typesCount() ) {
0364                 result = Helper::mergeTypes(result, indexed->typeAt(sliceIndex).abstractType());
0365                 continue;
0366             }
0367             // Index is unknown or invalid, could be returning any of the content types.
0368             result = Helper::mergeTypes(result, indexed->asUnsureType());
0369         }
0370         else if ( const auto& listType = type.dynamicCast<ListType>() ) {
0371             result = Helper::mergeTypes(result, listType->contentType().abstractType());
0372         }
0373         else {
0374             // Type wasn't one with custom handling, so use return type of __getitem__().
0375             DUChainReadLocker lock;
0376             static const IndexedIdentifier getitemIdentifier(KDevelop::Identifier("__getitem__"));
0377             auto function = Helper::accessAttribute(type, getitemIdentifier, topContext());
0378             if ( function && function->isFunctionDeclaration() ) {
0379                 if ( FunctionType::Ptr functionType = function->type<FunctionType>() ) {
0380                     result = Helper::mergeTypes(result, functionType->returnType());
0381                 }
0382             }
0383         }
0384     }
0385     encounter(result);
0386 }
0387 
0388 void ExpressionVisitor::visitLambda(LambdaAst* node)
0389 {
0390     AstDefaultVisitor::visitLambda(node);
0391     FunctionType::Ptr type(new FunctionType());
0392     AbstractType::Ptr mixed(new IntegralType(IntegralType::TypeMixed));
0393     for (int ii = 0; ii < node->arguments->arguments.length(); ++ii) {
0394         type->addArgument(mixed);
0395     }
0396     type->setReturnType(lastType());
0397     encounter(type);
0398 }
0399 
0400 void ExpressionVisitor::visitList(ListAst* node)
0401 {
0402     DUChainReadLocker lock;
0403     auto type = typeObjectForIntegralType<ListType>("list");
0404     lock.unlock();
0405     ExpressionVisitor contentVisitor(this);
0406     if ( type ) {
0407         foreach ( ExpressionAst* content, node->elements ) {
0408             contentVisitor.visitNode(content);
0409             if ( content->astType == Ast::StarredAstType ) {
0410                 auto contentType = Helper::contentOfIterable(contentVisitor.lastType(), topContext());
0411                 type->addContentType<Python::UnsureType>(contentType);
0412             }
0413             else {
0414                 type->addContentType<Python::UnsureType>(contentVisitor.lastType());
0415             }
0416         }
0417     }
0418     else {
0419         encounterUnknown();
0420         qCWarning(KDEV_PYTHON_DUCHAIN) << " [ !!! ] did not get a typetrack container object when expecting one! Fix code / setup.";
0421     }
0422     encounter(type);
0423 }
0424 
0425 void ExpressionVisitor::visitDictionaryComprehension(DictionaryComprehensionAst* node)
0426 {
0427     DUChainReadLocker lock;
0428     auto type = typeObjectForIntegralType<MapType>("dict");
0429     if ( type ) {
0430         DUContext* comprehensionContext = context()->findContextAt(CursorInRevision(node->startLine, node->startCol));
0431         lock.unlock();
0432         Q_ASSERT(comprehensionContext);
0433         DUContext* ctx = m_forceGlobalSearching ? context()->topContext() : comprehensionContext;
0434         ExpressionVisitor v(this, ctx);
0435         v.visitNode(node->value);
0436         if ( v.lastType() ) {
0437             type->addContentType<Python::UnsureType>(v.lastType());
0438         }
0439         ExpressionVisitor k(this, ctx);
0440         k.visitNode(node->key);
0441         if ( k.lastType() ) {
0442             type->addKeyType<Python::UnsureType>(k.lastType());
0443         }
0444     }
0445     else {
0446         return encounterUnknown();
0447     }
0448     encounter(type);
0449 }
0450 
0451 void ExpressionVisitor::visitSetComprehension(SetComprehensionAst* node)
0452 {
0453     Python::AstDefaultVisitor::visitSetComprehension(node);
0454     DUChainReadLocker lock;
0455     auto type = typeObjectForIntegralType<ListType>("set");
0456     if ( type ) {
0457         DUContext* comprehensionContext = context()->findContextAt(CursorInRevision(node->startLine, node->startCol), true);
0458         lock.unlock();
0459         auto ctx = m_forceGlobalSearching ? context()->topContext() : comprehensionContext;
0460         ExpressionVisitor v(this, ctx);
0461         v.visitNode(node->element);
0462         if ( v.lastType() ) {
0463             type->addContentType<Python::UnsureType>(v.lastType());
0464         }
0465     }
0466     encounter(type);
0467 }
0468 
0469 void ExpressionVisitor::visitListComprehension(ListComprehensionAst* node)
0470 {
0471     AstDefaultVisitor::visitListComprehension(node);
0472     DUChainReadLocker lock;
0473     auto type = typeObjectForIntegralType<ListType>("list");
0474     if ( type && ! m_forceGlobalSearching ) { // TODO fixme
0475         DUContext* comprehensionContext = context()->findContextAt(CursorInRevision(node->startLine, node->startCol), true);
0476         lock.unlock();
0477         ExpressionVisitor v(this, comprehensionContext);
0478         Q_ASSERT(comprehensionContext);
0479         v.visitNode(node->element);
0480         if ( v.lastType() ) {
0481             type->addContentType<Python::UnsureType>(v.lastType());
0482         }
0483     }
0484     else {
0485         return encounterUnknown();
0486     }
0487     encounter(type);
0488 }
0489 
0490 void ExpressionVisitor::visitTuple(TupleAst* node) {
0491     DUChainReadLocker lock;
0492     IndexedContainer::Ptr type = typeObjectForIntegralType<IndexedContainer>("tuple");
0493     if ( type ) {
0494         lock.unlock();
0495         foreach ( ExpressionAst* expr, node->elements ) {
0496             ExpressionVisitor v(this);
0497             v.visitNode(expr);
0498             if ( expr->astType == Ast::StarredAstType ) {
0499                 // foo = a, *b, c
0500                 if ( auto unpackedType = v.lastType().dynamicCast<IndexedContainer>() ) {
0501                     for ( int ii = 0; ii < unpackedType->typesCount(); ++ii ) {
0502                         type->addEntry(unpackedType->typeAt(ii).abstractType());
0503                     }
0504                 } // Unpacking something else, do nothing (i.e. assume it was empty).
0505             } else {
0506                 type->addEntry(v.lastType());
0507             }
0508         }
0509         encounter(type);
0510     }
0511     else {
0512         qCWarning(KDEV_PYTHON_DUCHAIN) << "tuple type object is not available";
0513         return encounterUnknown();
0514     }
0515 }
0516 
0517 void ExpressionVisitor::visitIfExpression(IfExpressionAst* node)
0518 {
0519     AstDefaultVisitor::visitIfExpression(node);
0520     if ( node->body && node->orelse ) {
0521         ExpressionVisitor v(this);
0522         v.visitNode(node->body);
0523         AbstractType::Ptr first = v.lastType();
0524         v.visitNode(node->orelse);
0525         AbstractType::Ptr second = v.lastType();
0526         encounter(Helper::mergeTypes(first, second));
0527     }
0528 }
0529 
0530 void ExpressionVisitor::visitSet(SetAst* node)
0531 {
0532     DUChainReadLocker lock;
0533     auto type = typeObjectForIntegralType<ListType>("set");
0534     lock.unlock();
0535     ExpressionVisitor contentVisitor(this);
0536     if ( type ) {
0537         foreach ( ExpressionAst* content, node->elements ) {
0538             contentVisitor.visitNode(content);
0539             if ( content->astType == Ast::StarredAstType ) {
0540                 auto contentType = Helper::contentOfIterable(contentVisitor.lastType(), topContext());
0541                 type->addContentType<Python::UnsureType>(contentType);
0542             }
0543             else {
0544                 type->addContentType<Python::UnsureType>(contentVisitor.lastType());
0545             }
0546         }
0547     }
0548     encounter(type);
0549 }
0550 
0551 void ExpressionVisitor::visitDict(DictAst* node)
0552 {
0553     DUChainReadLocker lock;
0554     auto type = typeObjectForIntegralType<MapType>("dict");
0555     lock.unlock();
0556     ExpressionVisitor contentVisitor(this);
0557     ExpressionVisitor keyVisitor(this);
0558     if ( type ) {
0559         Q_ASSERT(node->keys.length() == node->values.length());
0560         for ( int ii = 0; ii < node->values.length(); ++ii ) {
0561             contentVisitor.visitNode(node->values.at(ii));
0562             if ( node->keys.at(ii) ) {
0563                 type->addContentType<Python::UnsureType>(contentVisitor.lastType());
0564                 keyVisitor.visitNode(node->keys.at(ii));
0565                 type->addKeyType<Python::UnsureType>(keyVisitor.lastType());
0566             }
0567             else if ( auto unpackedType = contentVisitor.lastType().dynamicCast<MapType>() ) {
0568                 // Key is null for `{**foo}`
0569                 type->addContentType<Python::UnsureType>(unpackedType->contentType().abstractType());
0570                 type->addKeyType<Python::UnsureType>(unpackedType->keyType().abstractType());
0571             }
0572         }
0573     }
0574     encounter(type);
0575 }
0576 
0577 void ExpressionVisitor::visitNumber(Python::NumberAst* number)
0578 {
0579     AbstractType::Ptr type;
0580     DUChainReadLocker lock;
0581     if ( number->isInt ) {
0582         type = typeObjectForIntegralType<AbstractType>("int");
0583     }
0584     else {
0585         type = typeObjectForIntegralType<AbstractType>("float");
0586     }
0587     encounter(type);
0588 }
0589 
0590 void ExpressionVisitor::visitString(Python::StringAst* )
0591 {
0592     DUChainReadLocker lock;
0593     StructureType::Ptr type = typeObjectForIntegralType<StructureType>("str");
0594     encounter(type);
0595 }
0596 
0597 void ExpressionVisitor::visitBytes(Python::BytesAst* ) {
0598     DUChainReadLocker lock;
0599     auto type = typeObjectForIntegralType<StructureType>("bytes");
0600     encounter(type);
0601 }
0602 
0603 void ExpressionVisitor::visitFormattedValue(Python::FormattedValueAst* ) {
0604     DUChainReadLocker lock;
0605     StructureType::Ptr type = typeObjectForIntegralType<StructureType>("str");
0606     encounter(type);
0607 }
0608 
0609 void ExpressionVisitor::visitJoinedString(Python::JoinedStringAst* )
0610 {
0611     DUChainReadLocker lock;
0612     StructureType::Ptr type = typeObjectForIntegralType<StructureType>("str");
0613     encounter(type);
0614 }
0615 
0616 RangeInRevision nodeRange(Python::Ast* node)
0617 {
0618     return RangeInRevision(node->startLine, node->startCol, node->endLine,node->endCol);
0619 }
0620 
0621 void ExpressionVisitor::addUnknownName(const QString& name)
0622 {
0623     if ( m_parentVisitor ) {
0624         static_cast<ExpressionVisitor*>(m_parentVisitor)->addUnknownName(name);
0625     }
0626     else if ( ! m_unknownNames.contains(name) ) {
0627         m_unknownNames.insert(name);
0628     }
0629 }
0630 
0631 void ExpressionVisitor::visitNameConstant(NameConstantAst* node)
0632 {
0633     // handles "True", "False", "None"
0634     auto defId = m_defaultTypes.constFind(node->value);
0635     if ( defId != m_defaultTypes.constEnd() ) {
0636         return encounter(*defId);
0637     }
0638 }
0639 
0640 void ExpressionVisitor::visitName(Python::NameAst* node)
0641 {
0642     CursorInRevision findNameBefore;
0643     if ( m_scanUntilCursor.isValid() ) {
0644         findNameBefore = m_scanUntilCursor;
0645     }
0646     else if ( m_forceGlobalSearching ) {
0647         findNameBefore = CursorInRevision::invalid();
0648     }
0649     else {
0650         findNameBefore = CursorInRevision(node->endLine, node->endCol);
0651     }
0652     DUChainReadLocker lock;
0653     Declaration* d = Helper::declarationForName(node, findNameBefore,
0654                                                 DUChainPointer<const DUContext>(context()));
0655 
0656     if ( d ) {
0657         bool isAlias = dynamic_cast<AliasDeclaration*>(d) || d->isFunctionDeclaration() || dynamic_cast<ClassDeclaration*>(d);
0658         return encounter(d->abstractType(), DeclarationPointer(d), isAlias);
0659     }
0660     else {
0661         if ( m_reportUnknownNames ) {
0662             addUnknownName(node->identifier->value);
0663         }
0664         return encounterUnknown();
0665     }
0666 }
0667 
0668 void ExpressionVisitor::visitCompare(CompareAst* node)
0669 {
0670     Python::AstDefaultVisitor::visitCompare(node);
0671     encounter(AbstractType::Ptr(new IntegralType(IntegralType::TypeBoolean)));
0672 }
0673 
0674 AbstractType::Ptr ExpressionVisitor::fromBinaryOperator(AbstractType::Ptr lhs, AbstractType::Ptr rhs, const QString& op) {
0675     DUChainReadLocker lock;
0676     auto operatorReturnType = [&op, this](const AbstractType::Ptr& p) {
0677         auto type = p.dynamicCast<StructureType>();
0678         if ( ! type ) {
0679             return AbstractType::Ptr();
0680         }
0681         auto func = Helper::accessAttribute(type, op, topContext());
0682         if ( ! func ) {
0683             return AbstractType::Ptr();
0684         }
0685         auto operatorFunctionType = func->type<FunctionType>();
0686         DUChainReadLocker lock;
0687         auto context = Helper::getDocumentationFileContext();
0688         if ( context ) {
0689             auto object_decl = context->findDeclarations(QualifiedIdentifier("object"));
0690             if ( ! object_decl.isEmpty() && object_decl.first()->internalContext() == func->context() ) {
0691                 // if the operator is only declared in object(), do not include its type (which is void).
0692                 return AbstractType::Ptr();
0693             }
0694         }
0695         return operatorFunctionType ? operatorFunctionType->returnType() : AbstractType::Ptr();
0696     };
0697 
0698     return Helper::mergeTypes(operatorReturnType(lhs), operatorReturnType(rhs));
0699 }
0700 
0701 void ExpressionVisitor::visitBinaryOperation(Python::BinaryOperationAst* node)
0702 {
0703     ExpressionVisitor lhsVisitor(this);
0704     ExpressionVisitor rhsVisitor(this);
0705     AbstractType::Ptr result;
0706 
0707     lhsVisitor.visitNode(node->lhs);
0708     rhsVisitor.visitNode(node->rhs);
0709 
0710     if ( lhsVisitor.lastType() && lhsVisitor.lastType()->whichType() == AbstractType::TypeUnsure ) {
0711         auto unsure = lhsVisitor.lastType().staticCast<KDevelop::UnsureType>();
0712         const IndexedType* types = unsure->types();
0713         for( uint i = 0; i < unsure->typesSize(); i++ ) {
0714             result = Helper::mergeTypes(result, fromBinaryOperator(types[i].abstractType(),
0715                                                                    rhsVisitor.lastType(), node->methodName()));
0716         }
0717     } else {
0718         result = fromBinaryOperator(lhsVisitor.lastType(), rhsVisitor.lastType(), node->methodName());
0719     }
0720     if ( ! Helper::isUsefulType(result) ) {
0721         result = Helper::mergeTypes(lhsVisitor.lastType(), rhsVisitor.lastType());
0722     }
0723     return encounter(result);
0724 }
0725 
0726 void ExpressionVisitor::visitUnaryOperation(Python::UnaryOperationAst* node)
0727 {
0728     // Only visit the value, and use that as the result. Unary operators usually
0729     // don't change the type of the object (i.e. -a has the same type as a)
0730     visitNode(node->operand);
0731 }
0732 
0733 void ExpressionVisitor::visitBooleanOperation(Python::BooleanOperationAst* node)
0734 {
0735     ExpressionVisitor v(this);
0736     AbstractType::Ptr result;
0737 
0738     for (const auto& expr : node->values) {
0739         v.visitNode(expr);
0740         result = Helper::mergeTypes(result, v.lastType());
0741     }
0742 
0743     encounter(result);
0744 }
0745 
0746 void ExpressionVisitor::visitAssignmentExpression(Python::AssignmentExpressionAst* node) {
0747     visitNode(node->value);
0748 }
0749 
0750 }
0751