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