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

0001 /*
0002     SPDX-FileCopyrightText: 2007 Piyush verma <piyush.verma@gmail.com>
0003     SPDX-FileCopyrightText: 2007 Andreas Pakulat <apaku@gmx.de>
0004     SPDX-FileCopyrightText: 2010-2016 Sven Brauch <svenbrauch@googlemail.com>
0005     SPDX-FileCopyrightText: 2016 Francis Herne <mail@flherne.uk>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "declarationbuilder.h"
0011 #include "duchain/declarations/functiondeclaration.h"
0012 
0013 #include "types/hintedtype.h"
0014 #include "types/unsuretype.h"
0015 #include "types/nonetype.h"
0016 #include "types/indexedcontainer.h"
0017 #include "contextbuilder.h"
0018 #include "expressionvisitor.h"
0019 #include "pythoneditorintegrator.h"
0020 #include "helpers.h"
0021 #include "assistants/missingincludeassistant.h"
0022 #include "correctionhelper.h"
0023 
0024 #include <language/duchain/classdeclaration.h>
0025 #include <language/duchain/functiondeclaration.h>
0026 #include <language/duchain/declaration.h>
0027 #include <language/duchain/duchain.h>
0028 #include <language/duchain/types/alltypes.h>
0029 #include <language/duchain/builders/abstracttypebuilder.h>
0030 #include <language/duchain/aliasdeclaration.h>
0031 #include <language/duchain/duchainutils.h>
0032 #include <language/backgroundparser/backgroundparser.h>
0033 #include <language/backgroundparser/parsejob.h>
0034 #include <interfaces/ilanguagecontroller.h>
0035 
0036 #include <QByteArray>
0037 #include <QtGlobal>
0038 
0039 #include <QDebug>
0040 #include "duchaindebug.h"
0041 
0042 #include <functional>
0043 
0044 using namespace KTextEditor;
0045 using namespace KDevelop;
0046 
0047 namespace Python
0048 {
0049 
0050 DeclarationBuilder::DeclarationBuilder(Python::PythonEditorIntegrator* editor, int ownPriority)
0051     : DeclarationBuilderBase()
0052     , m_ownPriority(ownPriority)
0053 {
0054     setEditor(editor);
0055 }
0056 
0057 DeclarationBuilder:: ~DeclarationBuilder()
0058 {
0059     if ( ! m_scheduledForDeletion.isEmpty() ) {
0060         DUChainWriteLocker lock;
0061         foreach ( DUChainBase* d, m_scheduledForDeletion ) {
0062             delete d;
0063         }
0064         m_scheduledForDeletion.clear();
0065     }
0066 }
0067 
0068 void DeclarationBuilder::setPrebuilding(bool prebuilding)
0069 {
0070     m_prebuilding = prebuilding;
0071 }
0072 
0073 ReferencedTopDUContext DeclarationBuilder::build(const IndexedString& url, Ast* node,
0074                                                  const ReferencedTopDUContext& updateContext_)
0075 {
0076     ReferencedTopDUContext updateContext(updateContext_);
0077     m_correctionHelper.reset(new CorrectionHelper(url, this));
0078 
0079     // The declaration builder needs to run twice, so it can resolve uses of e.g. functions
0080     // which are called before they are defined (which is easily possible, due to python's dynamic nature).
0081     if ( ! m_prebuilding ) {
0082         DeclarationBuilder* prebuilder = new DeclarationBuilder(editor(), m_ownPriority);
0083         prebuilder->m_currentlyParsedDocument = currentlyParsedDocument();
0084         prebuilder->setPrebuilding(true);
0085         prebuilder->m_futureModificationRevision = m_futureModificationRevision;
0086         updateContext = prebuilder->build(url, node, updateContext);
0087         delete prebuilder;
0088         qCDebug(KDEV_PYTHON_DUCHAIN) << "Second declarationbuilder pass";
0089     }
0090     else {
0091         qCDebug(KDEV_PYTHON_DUCHAIN) << "Prebuilding declarations";
0092     }
0093     return DeclarationBuilderBase::build(url, node, updateContext);
0094 }
0095 
0096 int DeclarationBuilder::jobPriority() const
0097 {
0098     return m_ownPriority;
0099 }
0100 
0101 void DeclarationBuilder::closeDeclaration()
0102 {
0103     if ( lastContext() ) {
0104         DUChainReadLocker lock(DUChain::lock());
0105         currentDeclaration()->setKind(Declaration::Type);
0106     }
0107     
0108     Q_ASSERT(currentDeclaration()->alwaysForceDirect());
0109 
0110     eventuallyAssignInternalContext();
0111 
0112     DeclarationBuilderBase::closeDeclaration();
0113 }
0114 
0115 template<typename T> T* DeclarationBuilder::eventuallyReopenDeclaration(Identifier* name, FitDeclarationType mustFitType)
0116 {
0117     QList<Declaration*> existingDeclarations = existingDeclarationsForNode(name);
0118 
0119     Declaration* dec = nullptr;
0120     reopenFittingDeclaration<T>(existingDeclarations, mustFitType, editorFindRange(name, name), &dec);
0121     bool declarationOpened = (bool) dec;
0122     if ( ! declarationOpened ) {
0123         dec = openDeclaration<T>(name);
0124     }
0125     Q_ASSERT(dynamic_cast<T*>(dec));
0126     return static_cast<T*>(dec);
0127 }
0128 
0129 template<typename T> T* DeclarationBuilder::visitVariableDeclaration(Ast* node, Declaration* previous,
0130                                                                      AbstractType::Ptr type, VisitVariableFlags flags)
0131 {
0132     if ( node->astType == Ast::NameAstType ) {
0133         NameAst* currentVariableDefinition = static_cast<NameAst*>(node);
0134         // those contexts can invoke a variable declaration
0135         // this prevents "bar" from being declared in something like "foo = bar"
0136         // This is just a sanity check, the code should never request creation of a variable
0137         // in such cases.
0138         if ( currentVariableDefinition->context != ExpressionAst::Context::Store ) {
0139             return nullptr;
0140         }
0141         return visitVariableDeclaration<T>(currentVariableDefinition->identifier, previous, type, flags);
0142     }
0143     else if ( node->astType == Ast::IdentifierAstType ) {
0144         return visitVariableDeclaration<T>(static_cast<Identifier*>(node), previous, type, flags);
0145     }
0146     else {
0147         qCWarning(KDEV_PYTHON_DUCHAIN) << "cannot create variable declaration for non-(name|identifier) AST, this is a programming error";
0148         return static_cast<T*>(nullptr);
0149     }
0150 }
0151 
0152 QList< Declaration* > DeclarationBuilder::existingDeclarationsForNode(Identifier* node)
0153 {
0154     return currentContext()->findDeclarations(
0155         identifierForNode(node).last(), CursorInRevision::invalid(), nullptr,
0156         (DUContext::SearchFlag) (DUContext::DontSearchInParent | DUContext::DontResolveAliases)
0157     );
0158 }
0159 
0160 DeclarationBuilder::FitDeclarationType DeclarationBuilder::kindForType(AbstractType::Ptr type, bool isAlias)
0161 {
0162     if ( type ) {
0163         if ( type->whichType() == AbstractType::TypeFunction ) {
0164             return FunctionDeclarationType;
0165         }
0166     }
0167     if ( isAlias ) {
0168         return AliasDeclarationType;
0169     }
0170     return InstanceDeclarationType;
0171 }
0172 
0173 template<typename T> QList<Declaration*> DeclarationBuilder::reopenFittingDeclaration(
0174     QList<Declaration*> declarations, FitDeclarationType mustFitType,
0175     RangeInRevision updateRangeTo, Declaration** ok )
0176 {
0177     // Search for a declaration from a previous parse pass which should be re-used
0178     QList<Declaration*> remainingDeclarations;
0179     *ok = nullptr;
0180     foreach ( Declaration* d, declarations ) {
0181         Declaration* fitting = dynamic_cast<T*>(d);
0182         if ( ! fitting ) {
0183             // Only use a declaration if the type matches
0184             qCDebug(KDEV_PYTHON_DUCHAIN) << "skipping" << d->toString() << "which could not be cast to the requested type";
0185             continue;
0186         }
0187         // Do not use declarations which have been encountered previously;
0188         // this function only handles declarations from previous parser passes which have not
0189         // been encountered yet in this pass
0190         bool reallyEncountered = wasEncountered(d) && ! m_scheduledForDeletion.contains(d);
0191         bool invalidType = false;
0192         if ( d->abstractType() && mustFitType != NoTypeRequired ) {
0193             invalidType = ( ( d->isFunctionDeclaration() ) != ( mustFitType == FunctionDeclarationType ) );
0194             if ( ! invalidType ) {
0195                 invalidType = ( ( dynamic_cast<AliasDeclaration*>(d) != nullptr ) != ( mustFitType == AliasDeclarationType ) );
0196             }
0197         }
0198         if ( fitting && ! reallyEncountered && ! invalidType ) {
0199             if ( d->topContext() == currentContext()->topContext() ) {
0200                 openDeclarationInternal(d);
0201                 d->setRange(updateRangeTo);
0202                 *ok = d;
0203                 setEncountered(d);
0204                 break;
0205             }
0206             else {
0207                 qCDebug(KDEV_PYTHON_DUCHAIN) << "Not opening previously existing declaration because it's in another top context";
0208             }
0209         }
0210         else if ( ! invalidType ) {
0211             remainingDeclarations << d;
0212         }
0213     }
0214     return remainingDeclarations;
0215 }
0216 
0217 template<typename T> T* DeclarationBuilder::visitVariableDeclaration(Identifier* node, Declaration* previous,
0218                                                                      AbstractType::Ptr type, VisitVariableFlags flags)
0219 {
0220     DUChainWriteLocker lock;
0221     RangeInRevision range = editorFindRange(node, node);
0222     // ask the correction file library if there's a user-specified type for this object
0223     if ( AbstractType::Ptr hint = m_correctionHelper->hintForLocal(node->value) ) {
0224         type = hint;
0225     }
0226 
0227     // If no type is known, display "mixed".
0228     if ( ! type ) {
0229         type = AbstractType::Ptr(new IntegralType(IntegralType::TypeMixed));
0230     }
0231     
0232     QList<Declaration*> existingDeclarations;
0233     if ( previous ) {
0234         existingDeclarations << previous;
0235     }
0236     else {
0237         // declarations declared at an earlier range in this top-context
0238         existingDeclarations = existingDeclarationsForNode(node);
0239     }
0240     
0241     // declaration existing in a previous version of this top-context
0242     Declaration* dec = nullptr;
0243     existingDeclarations = reopenFittingDeclaration<T>(existingDeclarations, kindForType(type), range, &dec);
0244     bool declarationOpened = (bool) dec;
0245     if ( flags & AbortIfReopenMismatch && previous && ! declarationOpened ) {
0246         return nullptr;
0247     }
0248     
0249     // tells whether the declaration found for updating is in the same top context
0250     bool inSameTopContext = true;
0251     // tells whether there's fitting declarations to update (update is not the same as re-open! one is for
0252     // code which uses the same variable twice, the other is for multiple passes of the parser)
0253     bool haveFittingDeclaration = false;
0254     if ( ! existingDeclarations.isEmpty() && existingDeclarations.last() ) {
0255         Declaration* d = Helper::resolveAliasDeclaration(existingDeclarations.last());
0256         DUChainReadLocker lock;
0257         if ( d && d->topContext() != topContext() ) {
0258             inSameTopContext = false;
0259         }
0260         if ( dynamic_cast<T*>(existingDeclarations.last()) ) {
0261             haveFittingDeclaration = true;
0262         }
0263     }
0264     if ( currentContext() && currentContext()->type() == DUContext::Class && ! haveFittingDeclaration ) {
0265         // If the current context is a class, then this is a class member variable.
0266         if ( ! dec ) {
0267             dec = openDeclaration<ClassMemberDeclaration>(node);
0268             Q_ASSERT(! declarationOpened);
0269             declarationOpened = true;
0270         }
0271         if ( declarationOpened ) {
0272             DeclarationBuilderBase::closeDeclaration();
0273         }
0274         dec->setType(AbstractType::Ptr(type));
0275         dec->setKind(KDevelop::Declaration::Instance);
0276     } else if ( ! haveFittingDeclaration ) {
0277         // This name did not previously appear in the user code, so a new variable is declared
0278         // check whether a declaration from a previous parser pass must be updated
0279         if ( ! dec ) {
0280             dec = openDeclaration<T>(node);
0281             Q_ASSERT(! declarationOpened);
0282             declarationOpened = true;
0283         }
0284         if ( declarationOpened ) {
0285             DeclarationBuilderBase::closeDeclaration();
0286         }
0287         
0288         AbstractType::Ptr newType;
0289         if ( currentContext()->type() == DUContext::Function ) {
0290             // check for argument type hints (those are created when calling functions)
0291             AbstractType::Ptr hints = Helper::extractTypeHints(dec->abstractType());
0292             if ( hints.dynamicCast<IndexedContainer>() || hints.dynamicCast<ListType>() ) {
0293                 // This only happens when the type hint is a tuple, which means the vararg/kwarg of a function is being processed.
0294                 newType = hints;
0295             }
0296             else {
0297                 newType = Helper::mergeTypes(hints, type);
0298             }
0299         }
0300         else {
0301             newType = type;
0302         }
0303         dec->setType(newType);
0304         dec->setKind(KDevelop::Declaration::Instance);
0305     }
0306     else if ( inSameTopContext ) {
0307         // The name appeared previously in the user code, so no new variable is declared, but just
0308         // the type is modified accordingly.
0309         dec = existingDeclarations.last();
0310         AbstractType::Ptr currentType = dec->abstractType();
0311         AbstractType::Ptr newType = type;
0312         if ( newType ) {
0313             if ( currentType && currentType->indexed() != newType->indexed() ) {
0314                 // If the previous and new type are different, use an unsure type
0315                 dec->setType(Helper::mergeTypes(currentType, newType));
0316             }
0317             else {
0318                 // If no type was set previously, use only the new one.
0319                 dec->setType(AbstractType::Ptr(type));
0320             }
0321         }
0322     }
0323 
0324     T* result = dynamic_cast<T*>(dec);
0325     if ( ! result ) qCWarning(KDEV_PYTHON_DUCHAIN) << "variable declaration does not have the expected type";
0326     return result;
0327 }
0328 
0329 void DeclarationBuilder::visitCode(CodeAst* node)
0330 {
0331     Q_ASSERT(currentlyParsedDocument().toUrl().isValid());
0332     m_unresolvedImports.clear();
0333     DeclarationBuilderBase::visitCode(node);
0334 }
0335 
0336 void DeclarationBuilder::visitExceptionHandler(ExceptionHandlerAst* node)
0337 {
0338     if ( node->name ) {
0339         // Python allows to assign the caught exception to a variable; create that variable if required.
0340         ExpressionVisitor v(currentContext());
0341         v.visitNode(node->type);
0342         visitVariableDeclaration<Declaration>(node->name, nullptr, v.lastType());
0343     }
0344     DeclarationBuilderBase::visitExceptionHandler(node);
0345 }
0346 
0347 void DeclarationBuilder::visitWithItem(WithItemAst* node)
0348 {
0349     if ( node->optionalVars ) {
0350         // For statements like "with open(f) as x", a new variable must be created; do this here.
0351         ExpressionVisitor v(currentContext());
0352         v.visitNode(node->contextExpression);
0353         auto mgrType = v.lastType();
0354         auto enterType = mgrType; // If we can't find __enter__(), assume it returns `self` like file objects.
0355 
0356         static const IndexedIdentifier enterId(KDevelop::Identifier("__enter__"));
0357 
0358         DUChainReadLocker lock;
0359         if ( auto enterFunc = dynamic_cast<FunctionDeclaration*>(
0360                 Helper::accessAttribute(mgrType, enterId, topContext()))) {
0361             if ( auto enterFuncType = enterFunc->type<FunctionType>() ) {
0362                 enterType = enterFuncType->returnType();
0363             }
0364         }
0365         lock.unlock();
0366         // This may be any assignable expression, e.g. `with foo() as bar[3]: ...`
0367         assignToUnknown(node->optionalVars, enterType);
0368     }
0369     Python::AstDefaultVisitor::visitWithItem(node);
0370 }
0371 
0372 void DeclarationBuilder::visitFor(ForAst* node)
0373 {
0374     if ( node->iterator ) {
0375         ExpressionVisitor v(currentContext());
0376         v.visitNode(node->iterator);
0377         assignToUnknown(node->target, Helper::contentOfIterable(v.lastType(), topContext()));
0378     }
0379     Python::ContextBuilder::visitFor(node);
0380 }
0381 
0382 Declaration* DeclarationBuilder::findDeclarationInContext(QStringList dottedNameIdentifier, TopDUContext* ctx) const
0383 {
0384     DUChainReadLocker lock(DUChain::lock());
0385     DUContext* currentContext = ctx;
0386     // TODO make this a bit faster, it wastes time
0387     Declaration* lastAccessedDeclaration = nullptr;
0388     int i = 0;
0389     int identifierCount = dottedNameIdentifier.length();
0390     foreach ( const QString& currentIdentifier, dottedNameIdentifier ) {
0391         Q_ASSERT(currentContext);
0392         i++;
0393         QList<Declaration*> declarations = currentContext->findDeclarations(QualifiedIdentifier(currentIdentifier).first(),
0394                                                                             CursorInRevision::invalid(), nullptr, DUContext::NoFiltering);
0395         // break if the list of identifiers is not yet totally worked through and no
0396         // declaration with an internal context was found
0397         if ( declarations.isEmpty() || ( !declarations.last()->internalContext() && identifierCount != i ) ) {
0398             qCDebug(KDEV_PYTHON_DUCHAIN) << "Declaration not found: " << dottedNameIdentifier << "in top context" << ctx->url().toUrl().path();
0399             return nullptr;
0400         }
0401         else {
0402             lastAccessedDeclaration = declarations.last();
0403             currentContext = lastAccessedDeclaration->internalContext();
0404         }
0405     }
0406     return lastAccessedDeclaration;
0407 }
0408 
0409 QString DeclarationBuilder::buildModuleNameFromNode(ImportFromAst* node, AliasAst* alias, const QString& intermediate) const
0410 {
0411     QString moduleName = alias->name->value;
0412     if ( ! intermediate.isEmpty() ) {
0413         moduleName.prepend('.').prepend(intermediate);
0414     }
0415     if ( node->module ) {
0416         moduleName.prepend('.').prepend(node->module->value);
0417     }
0418     // To handle relative imports correctly, add node level in the beginning of the path
0419     // This will allow findModulePath to deduce module search direcotry properly
0420     moduleName.prepend(QString(node->level, '.'));
0421     return moduleName;
0422 }
0423 
0424 void DeclarationBuilder::visitImportFrom(ImportFromAst* node)
0425 {
0426     Python::AstDefaultVisitor::visitImportFrom(node);
0427     QString moduleName;
0428     QString declarationName;
0429     foreach ( AliasAst* name, node->names ) {
0430         // iterate over all the names that are imported, like "from foo import bar as baz, bang as asdf"
0431         Identifier* declarationIdentifier = nullptr;
0432         declarationName.clear();
0433         if ( name->asName ) {
0434             // use either the alias ("as foo"), or the object name itself if no "as" is given
0435             declarationIdentifier = name->asName;
0436             declarationName = name->asName->value;
0437         }
0438         else {
0439             declarationIdentifier = name->name;
0440             declarationName = name->name->value;
0441         }
0442         // This is a bit hackish, it tries to find the specified object twice twice -- once it tries to
0443         // import the name from a module's __init__.py file, and once from a "real" python file
0444         // TODO improve this code-wise
0445         ProblemPointer problem(nullptr);
0446         QString intermediate;
0447         moduleName = buildModuleNameFromNode(node, name, intermediate);
0448         Declaration* success = createModuleImportDeclaration(moduleName, declarationName, declarationIdentifier, problem);
0449         if ( ! success && (node->module || node->level) ) {
0450             ProblemPointer problem_init(nullptr);
0451             intermediate = QString("__init__");
0452             moduleName = buildModuleNameFromNode(node, name, intermediate);
0453             success = createModuleImportDeclaration(moduleName, declarationName, declarationIdentifier, problem_init);
0454         }
0455         if ( ! success && problem ) {
0456             DUChainWriteLocker lock;
0457             topContext()->addProblem(problem);
0458         }
0459     }
0460 }
0461 
0462 void DeclarationBuilder::visitComprehension(ComprehensionAst* node)
0463 {
0464     Python::AstDefaultVisitor::visitComprehension(node);
0465     ExpressionVisitor v(currentContext());
0466     v.visitNode(node->iterator);
0467     assignToUnknown(node->target, Helper::contentOfIterable(v.lastType(), topContext()));
0468 }
0469 
0470 void DeclarationBuilder::visitImport(ImportAst* node)
0471 {
0472     Python::ContextBuilder::visitImport(node);
0473     DUChainWriteLocker lock;
0474     foreach ( AliasAst* name, node->names ) {
0475         QString moduleName = name->name->value;
0476         // use alias if available, name otherwise
0477         Identifier* declarationIdentifier = name->asName ? name->asName : name->name;
0478         ProblemPointer problem(nullptr);
0479         createModuleImportDeclaration(moduleName, declarationIdentifier->value, declarationIdentifier, problem);
0480         if ( problem ) {
0481             DUChainWriteLocker lock;
0482             topContext()->addProblem(problem);
0483         }
0484     }
0485 }
0486 
0487 void DeclarationBuilder::scheduleForDeletion(DUChainBase* d, bool doschedule)
0488 {
0489     if ( doschedule ) {
0490         m_scheduledForDeletion.append(d);
0491     }
0492     else {
0493         m_scheduledForDeletion.removeAll(d);
0494     }
0495 }
0496 
0497 
0498 Declaration* DeclarationBuilder::createDeclarationTree(const QStringList& nameComponents, Identifier* declarationIdentifier,
0499                                        const ReferencedTopDUContext& innerCtx, Declaration* aliasDeclaration,
0500                                        const RangeInRevision& range)
0501 {
0502     // This actually handles two use cases which are very similar -- thus this check:
0503     // There might be either one declaration which should be imported from another module,
0504     // or there might be a whole context. In "import foo.bar", the "bar" might be either
0505     // a single class/function/whatever, or a whole file to import.
0506     // NOTE: The former case can't actually happen in python, it's not allowed. However,
0507     // it is still handled here, because it's very useful for documentation files (pyQt for example
0508     // makes heavy use of that feature).
0509     Q_ASSERT( ( innerCtx.data() || aliasDeclaration ) && "exactly one of innerCtx or aliasDeclaration must be provided");
0510     Q_ASSERT( ( !innerCtx.data() || !aliasDeclaration ) && "exactly one of innerCtx or aliasDeclaration must be provided");
0511     
0512     qCDebug(KDEV_PYTHON_DUCHAIN) << "creating declaration tree for" << nameComponents;
0513     
0514     Declaration* lastDeclaration = nullptr;
0515     int depth = 0;
0516     
0517     // check for already existing trees to update
0518     for ( int i = nameComponents.length() - 1; i >= 0; i-- ) {
0519         QStringList currentName;
0520         for ( int j = 0; j < i; j++ ) {
0521             currentName.append(nameComponents.at(j));
0522         }
0523         lastDeclaration = findDeclarationInContext(currentName, topContext());
0524         if ( lastDeclaration && (!range.isValid() || lastDeclaration->range() < range) ) {
0525             depth = i;
0526             break;
0527         }
0528     }
0529     
0530     DUContext* extendingPreviousImportCtx = nullptr;
0531     QStringList remainingNameComponents;
0532     bool injectingContext = false;
0533     if ( lastDeclaration && lastDeclaration->internalContext() ) {
0534         qCDebug(KDEV_PYTHON_DUCHAIN) << "Found existing import statement while creating declaration for " << declarationIdentifier->value;
0535         for ( int i = depth; i < nameComponents.length(); i++ ) {
0536             remainingNameComponents.append(nameComponents.at(i));
0537         }
0538         extendingPreviousImportCtx = lastDeclaration->internalContext();
0539         injectContext(extendingPreviousImportCtx);
0540         injectingContext = true;
0541         qCDebug(KDEV_PYTHON_DUCHAIN) << "remaining identifiers:" << remainingNameComponents;
0542     }
0543     else {
0544         remainingNameComponents = nameComponents;
0545         extendingPreviousImportCtx = topContext();
0546     }
0547     
0548     // now, proceed in creating the declaration tree with whatever context
0549     QList<Declaration*> openedDeclarations;
0550     QList<StructureType::Ptr> openedTypes;
0551     QList<DUContext*> openedContexts;
0552     
0553     RangeInRevision displayRange = RangeInRevision::invalid();
0554     
0555     DUChainWriteLocker lock;
0556     for ( int i = 0; i < remainingNameComponents.length(); i++ ) {
0557         // Iterate over all the names, and create a declaration + sub-context for each of them
0558         const QString& component = remainingNameComponents.at(i);
0559         Identifier temporaryIdentifier(component);
0560         Declaration* d = nullptr;
0561         temporaryIdentifier.copyRange(declarationIdentifier);
0562         temporaryIdentifier.endCol = temporaryIdentifier.startCol;
0563         temporaryIdentifier.startCol += 1;
0564         displayRange = editorFindRange(&temporaryIdentifier, &temporaryIdentifier); // TODO fixme
0565         
0566         bool done = false;
0567         if ( aliasDeclaration && i == remainingNameComponents.length() - 1 ) {
0568             // it's the last level, so if we have an alias declaration create it and stop
0569             if (    aliasDeclaration->isFunctionDeclaration() 
0570                  || dynamic_cast<ClassDeclaration*>(aliasDeclaration) 
0571                  || dynamic_cast<AliasDeclaration*>(aliasDeclaration) 
0572                ) {
0573                 aliasDeclaration = Helper::resolveAliasDeclaration(aliasDeclaration);
0574                 AliasDeclaration* adecl = eventuallyReopenDeclaration<AliasDeclaration>(&temporaryIdentifier,
0575                                                                                         AliasDeclarationType);
0576                 if ( adecl ) {
0577                     adecl->setAliasedDeclaration(aliasDeclaration);
0578                 }
0579                 d = adecl;
0580                 closeDeclaration();
0581             }
0582             else {
0583                 d = visitVariableDeclaration<Declaration>(&temporaryIdentifier);
0584                 d->setAbstractType(aliasDeclaration->abstractType());
0585             }
0586             openedDeclarations.append(d);
0587             done = true;
0588         }
0589         
0590         if ( ! done ) {
0591             // create the next level of the tree hierarchy if not done yet.
0592             d = visitVariableDeclaration<Declaration>(&temporaryIdentifier);
0593         }
0594         if ( d ) {
0595             if ( topContext() != currentContext() ) {
0596                 d->setRange(RangeInRevision(currentContext()->range().start, currentContext()->range().start));
0597             }
0598             else {
0599                 d->setRange(displayRange);
0600             }
0601             d->setAutoDeclaration(true);
0602             currentContext()->createUse(d->ownIndex(), d->range());
0603             qCDebug(KDEV_PYTHON_DUCHAIN) << "really encountered:" << d << "; scheduled:" << m_scheduledForDeletion;
0604             qCDebug(KDEV_PYTHON_DUCHAIN) << d->toString();
0605             scheduleForDeletion(d, false);
0606             qCDebug(KDEV_PYTHON_DUCHAIN) << "scheduled:" << m_scheduledForDeletion;
0607         }
0608         if ( done ) break;
0609 
0610         qCDebug(KDEV_PYTHON_DUCHAIN) << "creating context for " << component;
0611 
0612         // otherwise, create a new "level" entry (a pseudo type + context + declaration which contains all imported items)
0613         StructureType::Ptr moduleType = StructureType::Ptr(new StructureType());
0614         openType(moduleType);
0615 
0616         // the identifier is needed so the context does not get re-opened if
0617         // more contexts are opened for other files with the same range
0618         Python::Identifier contextIdentifier(component);
0619         auto moduleContext = openContext(declarationIdentifier, KDevelop::DUContext::Other, &contextIdentifier);
0620         openedContexts.append(moduleContext);
0621 
0622         foreach ( Declaration* local, currentContext()->localDeclarations() ) {
0623             // keep all the declarations until the builder finished
0624             // kdevelop would otherwise delete them as soon as the context is closed
0625             if ( ! wasEncountered(local) ) {
0626                 setEncountered(local);
0627                 scheduleForDeletion(local, true);
0628             }
0629         }
0630 
0631         openedDeclarations.append(d);
0632         openedTypes.append(moduleType);
0633         if ( i == remainingNameComponents.length() - 1 ) {
0634             if ( innerCtx ) {
0635                 qCDebug(KDEV_PYTHON_DUCHAIN) << "adding imported context to inner declaration";
0636                 currentContext()->addImportedParentContext(innerCtx);
0637             }
0638             else if ( aliasDeclaration ) {
0639                 qCDebug(KDEV_PYTHON_DUCHAIN) << "setting alias declaration on inner declaration";
0640             }
0641         }
0642     }
0643     for ( int i = openedContexts.length() - 1; i >= 0; i-- ) {
0644         // Close all the declarations and contexts opened previosly, and assign the types.
0645         qCDebug(KDEV_PYTHON_DUCHAIN) << "closing context";
0646         closeType();
0647         closeContext();
0648         auto d = openedDeclarations.at(i);
0649         // because no context will be opened for an alias declaration, this will not happen if there's one
0650         if ( d ) {
0651             openedTypes[i]->setDeclaration(d);
0652             d->setType(openedTypes.at(i));
0653             d->setInternalContext(openedContexts.at(i));
0654         }
0655     }
0656     
0657     if ( injectingContext ) {
0658         closeInjectedContext();
0659     }
0660     
0661     if ( ! openedDeclarations.isEmpty() ) {
0662         // return the lowest-level element in the tree, for the caller to do stuff with
0663         return openedDeclarations.last();
0664     }
0665     else return nullptr;
0666 }
0667 
0668 Declaration* DeclarationBuilder::createModuleImportDeclaration(QString moduleName, QString declarationName,
0669                                                                Identifier* declarationIdentifier,
0670                                                                ProblemPointer& problemEncountered, Ast* rangeNode)
0671 {
0672     // Search the disk for a python file which contains the requested declaration
0673     auto moduleInfo = findModulePath(moduleName, currentlyParsedDocument().toUrl());
0674     RangeInRevision range(RangeInRevision::invalid());
0675     if ( rangeNode ) {
0676         range = rangeForNode(rangeNode, false);
0677     }
0678     else {
0679         range = rangeForNode(declarationIdentifier, false);
0680     }
0681     Q_ASSERT(range.isValid());
0682     
0683     qCDebug(KDEV_PYTHON_DUCHAIN) << "Found module path [path/path in file]: " << moduleInfo;
0684     qCDebug(KDEV_PYTHON_DUCHAIN) << "Declaration identifier:" << declarationIdentifier->value;
0685     DUChainWriteLocker lock;
0686     const IndexedString modulePath = IndexedString(moduleInfo.first);
0687     ReferencedTopDUContext moduleContext = DUChain::self()->chainForDocument(modulePath);
0688     lock.unlock();
0689     Declaration* resultingDeclaration = nullptr;
0690     if ( ! moduleInfo.first.isValid() ) {
0691         // The file was not found -- this is either an error in the user's code,
0692         // a missing module, or a C module (.so) which is unreadable for kdevelop
0693         // TODO imrpove error handling in case the module exists as a shared object or .pyc file only
0694         qCDebug(KDEV_PYTHON_DUCHAIN) << "invalid or non-existent URL:" << moduleInfo;
0695         KDevelop::Problem *p = new Python::MissingIncludeProblem(moduleName, currentlyParsedDocument());
0696         p->setFinalLocation(DocumentRange(currentlyParsedDocument(), range.castToSimpleRange()));
0697         p->setSource(KDevelop::IProblem::SemanticAnalysis);
0698         p->setSeverity(KDevelop::IProblem::Warning);
0699         p->setDescription(i18n("Module \"%1\" not found", moduleName));
0700         m_missingModules.append(IndexedString(moduleName));
0701         problemEncountered = p;
0702         return nullptr;
0703     }
0704     if ( ! moduleContext ) {
0705         // schedule the include file for parsing, and schedule the current one for reparsing after that is done
0706         qCDebug(KDEV_PYTHON_DUCHAIN) << "No module context, recompiling";
0707         m_unresolvedImports.append(modulePath);
0708         Helper::scheduleDependency(modulePath, m_ownPriority);
0709         // parseDocuments() must *not* be called from a background thread!
0710         // KDevelop::ICore::self()->languageController()->backgroundParser()->parseDocuments();
0711         return nullptr;
0712     }
0713     if ( moduleInfo.second.isEmpty() ) {
0714         // import the whole module
0715         resultingDeclaration = createDeclarationTree(declarationName.split("."),
0716                                                      declarationIdentifier, moduleContext, nullptr, range);
0717         auto initFile = QStringLiteral("/__init__.py");
0718         auto path = moduleInfo.first.path();
0719         if ( path.endsWith(initFile) ) {
0720             // if the __init__ file is imported, import all the other files in that directory as well
0721             QDir dir(path.left(path.size() - initFile.size()));
0722             dir.setNameFilters({"*.py"});
0723             dir.setFilter(QDir::Files);
0724             auto files = dir.entryList();
0725             foreach ( const auto& file, files ) {
0726                 if ( file == QStringLiteral("__init__.py") ) {
0727                     continue;
0728                 }
0729                 const auto filePath = declarationName.split(".") << file.left(file.lastIndexOf(".py"));
0730                 const auto fileUrl = QUrl::fromLocalFile(dir.path() + "/" + file);
0731                 ReferencedTopDUContext fileContext;
0732                 {
0733                     DUChainReadLocker lock;
0734                     fileContext = DUChain::self()->chainForDocument(IndexedString(fileUrl));
0735                 }
0736                 if ( fileContext ) {
0737                     Identifier id = *declarationIdentifier;
0738                     id.value.append(".").append(filePath.last());
0739                     createDeclarationTree(filePath,
0740                                           &id, fileContext, nullptr);
0741                 }
0742                 else {
0743                     m_unresolvedImports.append(IndexedString(fileUrl));
0744                     Helper::scheduleDependency(IndexedString(fileUrl), m_ownPriority);
0745                 }
0746             }
0747         }
0748     }
0749     else {
0750         // import a specific declaration from the given file
0751         lock.lock();
0752         if ( declarationIdentifier->value == "*" ) {
0753             qCDebug(KDEV_PYTHON_DUCHAIN) << "Importing * from module";
0754             currentContext()->addImportedParentContext(moduleContext);
0755         }
0756         else {
0757             qCDebug(KDEV_PYTHON_DUCHAIN) << "Got module, importing declaration: " << moduleInfo.second;
0758             Declaration* originalDeclaration = findDeclarationInContext(moduleInfo.second, moduleContext);
0759             if ( originalDeclaration ) {
0760                 DUChainWriteLocker lock(DUChain::lock());
0761                 resultingDeclaration = createDeclarationTree(declarationName.split("."), declarationIdentifier,
0762                                                              ReferencedTopDUContext(nullptr), originalDeclaration,
0763                                                              editorFindRange(declarationIdentifier, declarationIdentifier));
0764             }
0765             else {
0766                 KDevelop::Problem *p = new Python::MissingIncludeProblem(moduleName, currentlyParsedDocument());
0767                 p->setFinalLocation(DocumentRange(currentlyParsedDocument(), range.castToSimpleRange())); // TODO ok?
0768                 p->setSource(KDevelop::IProblem::SemanticAnalysis);
0769                 p->setSeverity(KDevelop::IProblem::Warning);
0770                 p->setDescription(i18n("Declaration for \"%1\" not found in specified module", moduleInfo.second.join(".")));
0771                 problemEncountered = p;
0772             }
0773         }
0774     }
0775     return resultingDeclaration;
0776 }
0777 
0778 void DeclarationBuilder::visitYield(YieldAst* node)
0779 {
0780     // Functions containing "yield" statements will return lists in our abstraction.
0781     // The content type of that list can be guessed from the yield statements.
0782     AstDefaultVisitor::visitYield(node);
0783     
0784     // Determine the type of the argument to "yield", like "int" in "yield 3"
0785     ExpressionVisitor v(currentContext());
0786     v.visitNode(node->value);
0787     AbstractType::Ptr encountered = v.lastType();
0788     
0789     // In some obscure (or wrong) cases, "yield" might appear outside of a function body,
0790     // so check for that here.
0791     if ( ! node->value || ! hasCurrentType() ) {
0792         return;
0793     }
0794 
0795     TypePtr<FunctionType> t = currentType<FunctionType>();
0796     if ( ! t ) {
0797         return;
0798     }
0799     if ( auto previous = t->returnType().dynamicCast<ListType>() ) {
0800         // If the return type of the function already is set to a list, *add* the encountered type
0801         // to its possible content types.
0802         DUChainWriteLocker lock;
0803         previous->addContentType<Python::UnsureType>(encountered);
0804         t->setReturnType(previous);
0805     }
0806     else {
0807         // Otherwise, create a new container type, and set it as the function's return type.
0808         DUChainWriteLocker lock;
0809         auto container = ExpressionVisitor::typeObjectForIntegralType<ListType>("list");
0810         if ( container ) {
0811             openType(container);
0812             container->addContentType<Python::UnsureType>(encountered);
0813             t->setReturnType(Helper::mergeTypes(t->returnType(), container));
0814             closeType();
0815         }
0816     }
0817 }
0818 
0819 void DeclarationBuilder::visitLambda(LambdaAst* node)
0820 {
0821     DUChainWriteLocker lock;
0822     // A context must be opened, because the lamdba's arguments are local to the lambda:
0823     // d = lambda x: x*2; print x # <- gives an error
0824     openContext(node, editorFindRange(node, node->body), DUContext::Other);
0825     foreach ( ArgAst* argument, node->arguments->arguments ) {
0826         visitVariableDeclaration<Declaration>(argument->argumentName);
0827     }
0828     visitNodeList(node->arguments->defaultValues);
0829     if (node->arguments->vararg) {
0830         visitVariableDeclaration<Declaration>(node->arguments->vararg->argumentName);
0831     }
0832     if (node->arguments->kwarg) {
0833         visitVariableDeclaration<Declaration>(node->arguments->kwarg->argumentName);
0834     }
0835     visitNode(node->body);
0836     closeContext();
0837 }
0838 
0839 void DeclarationBuilder::applyDocstringHints(CallAst* node, FunctionDeclaration::Ptr function)
0840 {
0841     ExpressionVisitor v(currentContext());
0842     v.visitNode(static_cast<AttributeAst*>(node->function)->value);
0843 
0844     // Don't do anything if the object the function is being called on is not a container.
0845     auto container = v.lastType().dynamicCast<ListType>();
0846     if ( ! container || ! function ) {
0847         return;
0848     }
0849     // Don't do updates to pre-defined functions.
0850     if ( ! v.lastDeclaration() || v.lastDeclaration()->topContext()->url() == Helper::getDocumentationFile() ) {
0851         return;
0852     }
0853     // Check for the different types of modifiers such a function can have
0854     QStringList args;
0855     QHash< QString, std::function<void()> > items;
0856     items["addsTypeOfArg"] = [&]() {
0857         const int offset = ! args.isEmpty() ? (int) args.at(0).toUInt() : 0;
0858         if ( node->arguments.length() <= offset ) {
0859             return;
0860         }
0861         // Check which type should be added to the list
0862         ExpressionVisitor argVisitor(currentContext());
0863         argVisitor.visitNode(node->arguments.at(offset));
0864         // Actually add that type
0865         if ( ! argVisitor.lastType() ) {
0866             return;
0867         }
0868         DUChainWriteLocker wlock;
0869         qCDebug(KDEV_PYTHON_DUCHAIN) << "Adding content type: " << argVisitor.lastType()->toString();
0870         container->addContentType<Python::UnsureType>(argVisitor.lastType());
0871         v.lastDeclaration()->setType(container);
0872     };
0873     items["addsTypeOfArgContent"] = [&]() {
0874         const int offset = ! args.isEmpty() ? (int) args.at(0).toUInt() : 0;
0875         if ( node->arguments.length() <= offset ) {
0876             return;
0877         }
0878         ExpressionVisitor argVisitor(currentContext());
0879         argVisitor.visitNode(node->arguments.at(offset));
0880         if ( argVisitor.lastType() ) {
0881             DUChainWriteLocker wlock;
0882             auto contentType = Helper::contentOfIterable(argVisitor.lastType(), topContext());
0883             container->addContentType<Python::UnsureType>(contentType);
0884             v.lastDeclaration()->setType(container);
0885         }
0886     };
0887     auto docstring = function->comment();
0888     if ( ! docstring.isEmpty() ) {
0889         foreach ( const auto& key, items.keys() ) {
0890             if ( Helper::docstringContainsHint(docstring, key, &args) ) {
0891                 items[key]();
0892             }
0893         }
0894     }
0895 }
0896 
0897 void DeclarationBuilder::addArgumentTypeHints(CallAst* node, DeclarationPointer called)
0898 {
0899     DUChainReadLocker lock;
0900     auto funcInfo = Helper::functionForCalled(called.data());
0901     auto function = funcInfo.declaration;
0902 
0903     if ( ! function ) {
0904         return;
0905     }
0906     if ( function->topContext()->url() == Helper::getDocumentationFile() ) {
0907         return;
0908     }
0909     // Note: within this function:
0910     // - 'parameters' refers to the parameters of the function definition.
0911     // - 'arguments' refers to the arguments of the function call.
0912 
0913     DUContext* parameterContext = DUChainUtils::argumentContext(function);
0914     FunctionType::Ptr functionType = function->type<FunctionType>();
0915     if ( ! parameterContext || ! functionType ) {
0916         return;
0917     }
0918     QVector<Declaration*> parameters = parameterContext->localDeclarations();
0919     if ( parameters.isEmpty() ) {
0920         return;
0921     }
0922     const int specialParamsCount = (function->vararg() != -1) + (function->kwarg() != -1);
0923 
0924     // Look for the "self" in the argument list, the type of that should not be updated.
0925     bool hasSelfParam = false;
0926     if ( ( function->context()->type() == DUContext::Class || funcInfo.isConstructor )
0927             && ! function->isStatic() )
0928     {
0929         // ... unless for some reason the function only has *vararg, **kwarg as parameters
0930         // (this could happen for example if the method is static but kdev-python does not know,
0931         // or if the user just made a mistake in his code)
0932         if ( specialParamsCount < parameters.size() ) {
0933             hasSelfParam = true;
0934         }
0935     }
0936 
0937     lock.unlock();
0938 
0939     bool explicitSelfArgument = false;
0940     if ( hasSelfParam && ! function->isClassMethod() && node->function->astType == Ast::AttributeAstType ) {
0941         // Calling an attribute, e.g. `instance.foo(arg)` or `MyClass.foo(instance, arg)`.
0942         ExpressionVisitor valueVisitor(currentContext());
0943         valueVisitor.visitNode(static_cast<AttributeAst*>(node->function)->value);
0944         if ( valueVisitor.lastDeclaration().dynamicCast<ClassDeclaration>() && valueVisitor.isAlias() ) {
0945             // Function is attribute of a class _type_ (not instance), so first arg is used as `self`.
0946             explicitSelfArgument = true;
0947         }
0948     }
0949 
0950     int currentParamIndex = hasSelfParam;
0951     int currentArgumentIndex = explicitSelfArgument;
0952     int indexInVararg = -1;
0953     int paramsAvailable = qMin(functionType->arguments().length(), parameters.size());
0954     int argsAvailable = node->arguments.size();
0955     bool atVararg = false;
0956 
0957     // Iterate over all the arguments, trying to guess the type of the object being
0958     // passed as an argument, and update the parameter accordingly.
0959     // Stop if more parameters supplied than possible, and we're not at the vararg.
0960     for ( ; ( atVararg || currentParamIndex < paramsAvailable ) && currentArgumentIndex < argsAvailable;
0961             currentArgumentIndex++ )
0962     {
0963         atVararg = atVararg || currentParamIndex == function->vararg(); // Not >=, nonexistent vararg is -1.
0964 
0965         ExpressionAst* arg = node->arguments.at(currentArgumentIndex);
0966 
0967         ExpressionVisitor argumentVisitor(currentContext());
0968         argumentVisitor.visitNode(arg);
0969         AbstractType::Ptr argumentType = argumentVisitor.lastType();
0970 
0971         // Update the parameter type: change both the type of the function argument,
0972         // and the type of the declaration which belongs to that argument
0973         HintedType::Ptr addType = HintedType::Ptr(new HintedType());
0974         openType(addType);
0975         addType->setType(argumentVisitor.lastType());
0976         addType->setCreatedBy(topContext(), m_futureModificationRevision);
0977         closeType();
0978 
0979         DUChainWriteLocker wlock;
0980         if ( atVararg ) {
0981             indexInVararg++;
0982             Declaration* parameter = parameters.at(function->vararg());
0983             IndexedContainer::Ptr varargContainer = parameter->type<IndexedContainer>();
0984             if ( ! varargContainer ) continue;
0985             if ( varargContainer->typesCount() > indexInVararg ) {
0986                 AbstractType::Ptr oldType = varargContainer->typeAt(indexInVararg).abstractType();
0987                 AbstractType::Ptr newType = Helper::mergeTypes(oldType, addType);
0988                 varargContainer->replaceType(indexInVararg, newType);
0989             }
0990             else {
0991                 varargContainer->addEntry(addType);
0992             }
0993             parameter->setAbstractType(varargContainer);
0994         }
0995         else {
0996             if ( ! argumentType ) continue;
0997             AbstractType::Ptr newType = Helper::mergeTypes(parameters.at(currentParamIndex)->abstractType(),
0998                                                            addType);
0999             // TODO this does not correctly update the types in quickopen! Investigate why.
1000             functionType->removeArgument(currentParamIndex);
1001             functionType->addArgument(newType, currentParamIndex);
1002             function->setAbstractType(functionType);
1003             parameters.at(currentParamIndex)->setType(newType);
1004             currentParamIndex++;
1005         }
1006     }
1007 
1008     // **kwargs is always the last parameter
1009     MapType::Ptr kwargsDict;
1010     if ( function->kwarg() != -1 ) {
1011         kwargsDict = parameters.last()->abstractType().dynamicCast<MapType>();
1012     }
1013     lock.unlock();
1014     DUChainWriteLocker wlock;
1015     foreach ( KeywordAst* keyword, node->keywords ) {
1016         wlock.unlock();
1017         ExpressionVisitor argumentVisitor(currentContext());
1018         argumentVisitor.visitNode(keyword->value);
1019         if ( ! argumentVisitor.lastType() ) {
1020             continue;
1021         }
1022         wlock.lock();
1023         bool matchedNamedParam = false;
1024         HintedType::Ptr addType = HintedType::Ptr(new HintedType());
1025         if ( keyword->argumentName ) {
1026             openType(addType);
1027             addType->setType(argumentVisitor.lastType());
1028             addType->setCreatedBy(topContext(), m_futureModificationRevision);
1029             closeType();
1030             for (int ip = currentParamIndex; ip < paramsAvailable; ++ip ) {
1031                 if ( parameters.at(ip)->identifier().toString() != keyword->argumentName->value ) {
1032                     continue;
1033                 }
1034                 matchedNamedParam = true;
1035                 auto newType = Helper::mergeTypes(parameters.at(ip)->abstractType(), addType);
1036                 functionType->removeArgument(ip);
1037                 functionType->addArgument(newType, ip);
1038                 parameters.at(ip)->setType(newType);
1039             }
1040         }
1041         else if ( auto unpackedDict = argumentVisitor.lastType().dynamicCast<MapType>() ) {
1042             // 'keyword is actually an unpacked dict: `foo(**{'a': 12}).
1043             openType(addType);
1044             addType->setType(unpackedDict->contentType().abstractType());
1045             addType->setCreatedBy(topContext(), m_futureModificationRevision);
1046             closeType();
1047         }
1048         else { // Maybe the dict type wasn't loaded yet, or something else happened.
1049             continue;
1050         }
1051         if ( ! matchedNamedParam && kwargsDict ) {
1052             DUChainWriteLocker lock;
1053             kwargsDict->addContentType<Python::UnsureType>(addType);
1054             parameters.last()->setAbstractType(kwargsDict);
1055         }
1056     }
1057     function->setAbstractType(functionType);
1058 }
1059 
1060 void DeclarationBuilder::visitMatch(MatchAst* node)
1061 {
1062     // What are we matching?
1063     ExpressionVisitor subjectVisitor(currentContext());
1064     subjectVisitor.visitNode(node->subject);
1065 
1066     for (auto* matchCase: node->cases) {
1067         if (!matchCase || !matchCase->pattern) {
1068             continue;
1069         }
1070         DUChainWriteLocker lock;
1071         // We only support some forms for now.
1072         switch (matchCase->pattern->astType) {
1073             case Ast::MatchSequenceAstType: {
1074                 auto* seq = static_cast<MatchSequenceAst*>(matchCase->pattern);
1075                 for (auto* element: seq->patterns) {
1076                     if (element->astType != Ast::MatchAsAstType) {
1077                         continue;
1078                     }
1079                     auto* asElement = static_cast<MatchAsAst*>(element);
1080                     auto type = Helper::contentOfIterable(subjectVisitor.lastType(), topContext());
1081                     visitVariableDeclaration<Declaration>(asElement->name, nullptr, type);
1082                 }
1083                 break;
1084             }
1085 
1086             case Ast::MatchAsAstType: {
1087                 auto* as = static_cast<MatchAsAst*>(matchCase->pattern);
1088                 if (!as->name) {
1089                     break;
1090                 }
1091                 visitVariableDeclaration<Declaration>(as->name, nullptr, subjectVisitor.lastType());
1092                 break;
1093             }
1094 
1095             default:
1096                 break;
1097         }
1098     }
1099 
1100     Python::AstDefaultVisitor::visitMatch(node);
1101 }
1102 
1103 void DeclarationBuilder::visitCall(CallAst* node)
1104 {
1105     Python::AstDefaultVisitor::visitCall(node);
1106     // Find the function being called; this code also handles cases where non-names
1107     // are called, for example:
1108     //     class myclass():
1109     //         def myfun(self): return 3
1110     //     l = [myclass()]
1111     //     x = l[0].myfun() # the called object is actually l[0].myfun
1112     // In the above example, this call will be evaluated to "myclass.myfun" in the following statement.
1113     ExpressionVisitor functionVisitor(currentContext());
1114     functionVisitor.visitNode(node);
1115 
1116     if ( node->function && node->function->astType == Ast::AttributeAstType && functionVisitor.lastDeclaration() ) {
1117         // Some special functions, like "append", update the content of the object they operate on.
1118         // Find the object the function is called on, like for d = [1, 2, 3]; d.append(5), this will give "d"
1119         FunctionDeclaration::Ptr function = functionVisitor.lastDeclaration().dynamicCast<FunctionDeclaration>();
1120         applyDocstringHints(node, function);
1121     }
1122     if ( ! m_prebuilding ) {
1123         return;
1124     }
1125 
1126     // The following code will try to update types of function parameters based on what is passed
1127     // for those when the function is used.
1128     // In case of this code:
1129     //     def foo(arg): print arg
1130     //     foo(3)
1131     // the following will change the type of "arg" to be "int" when it processes the second line.
1132     addArgumentTypeHints(node, functionVisitor.lastDeclaration());
1133 }
1134 
1135 void DeclarationBuilder::assignToName(NameAst* target, const DeclarationBuilder::SourceType& element)
1136 {
1137     if ( element.isAlias ) {
1138         DUChainWriteLocker lock;
1139         AliasDeclaration* decl = eventuallyReopenDeclaration<AliasDeclaration>(target->identifier, AliasDeclarationType);
1140         decl->setAliasedDeclaration(element.declaration.data());
1141         closeDeclaration();
1142     }
1143     else {
1144         DUChainWriteLocker lock;
1145         Declaration* dec = visitVariableDeclaration<Declaration>(target, nullptr, element.type);
1146         if ( dec && m_lastComment && ! m_lastComment->usedAsComment ) {
1147             dec->setComment(m_lastComment->value);
1148             m_lastComment->usedAsComment = true;
1149         }
1150         /** DEBUG **/
1151         if ( element.type && dec ) {
1152             Q_ASSERT(dec->abstractType());
1153         }
1154         /** END DEBUG **/
1155     }
1156 }
1157 
1158 void DeclarationBuilder::assignToSubscript(SubscriptAst* subscript, const DeclarationBuilder::SourceType& element)
1159 {
1160     ExpressionAst* v = subscript->value;
1161     if ( ! element.type ) {
1162         return;
1163     }
1164     ExpressionVisitor targetVisitor(currentContext());
1165     targetVisitor.visitNode(v);
1166     auto list = targetVisitor.lastType().dynamicCast<ListType>();
1167     if ( list ) {
1168         DUChainWriteLocker lock;
1169         list->addContentType<Python::UnsureType>(element.type);
1170     }
1171     auto map = list.dynamicCast<MapType>();
1172     if ( map ) {
1173         if ( subscript->slice && subscript->slice->astType != Ast::SliceAstType) {
1174             ExpressionVisitor keyVisitor(currentContext());
1175             keyVisitor.visitNode(subscript->slice);
1176             AbstractType::Ptr key = keyVisitor.lastType();
1177             if ( key ) {
1178                 map->addKeyType<Python::UnsureType>(key);
1179             }
1180         }
1181     }
1182     DeclarationPointer lastDecl = targetVisitor.lastDeclaration();
1183     if ( list && lastDecl ) {
1184         DUChainWriteLocker lock;
1185         lastDecl->setAbstractType(list);
1186     }
1187 }
1188 
1189 void DeclarationBuilder::assignToAttribute(AttributeAst* attrib, const DeclarationBuilder::SourceType& element)
1190 {
1191     // visit the base expression before the dot
1192     ExpressionVisitor checkPreviousAttributes(currentContext());
1193     checkPreviousAttributes.visitNode(attrib->value);
1194     DeclarationPointer parentObjectDeclaration = checkPreviousAttributes.lastDeclaration();
1195 
1196     DUContextPointer internal(nullptr);
1197 
1198     if ( ! parentObjectDeclaration ) {
1199         qCDebug(KDEV_PYTHON_DUCHAIN) << "No declaration for attribute base, aborting creation of attribute";
1200         return;
1201     }
1202     // if foo is a class, this is like foo.bar = 3
1203     if ( parentObjectDeclaration->internalContext() ) {
1204         internal = parentObjectDeclaration->internalContext();
1205     }
1206     // while this is like A = foo(); A.bar = 3
1207     else {
1208         DUChainReadLocker lock;
1209         auto structure = parentObjectDeclaration->abstractType().dynamicCast<StructureType>();
1210         if ( ! structure || ! structure->declaration(topContext()) ) {
1211             return;
1212         }
1213         parentObjectDeclaration = structure->declaration(topContext());
1214         internal = parentObjectDeclaration->internalContext();
1215     }
1216     if ( ! internal ) {
1217         qCDebug(KDEV_PYTHON_DUCHAIN) << "No internal context for structure type, aborting creation of attribute declaration";
1218         return;
1219     }
1220 
1221     Declaration* attributeDeclaration = nullptr;
1222     {
1223         DUChainReadLocker lock;
1224         attributeDeclaration = Helper::accessAttribute(parentObjectDeclaration->abstractType(),
1225                                                        attrib->attribute->value, topContext());
1226     }
1227 
1228     if ( ! attributeDeclaration || ! wasEncountered(attributeDeclaration) ) {
1229         // inject a new attribute into the class type
1230         DUContext* previousContext = currentContext();
1231         bool isAlreadyOpen = contextAlreadyOpen(internal);
1232         if ( isAlreadyOpen ) {
1233             activateAlreadyOpenedContext(internal);
1234             visitVariableDeclaration<ClassMemberDeclaration>(
1235                 attrib->attribute, attributeDeclaration, element.type, AbortIfReopenMismatch
1236             );
1237             closeAlreadyOpenedContext(internal);
1238         }
1239         else {
1240             injectContext(internal.data());
1241 
1242             Declaration* dec = visitVariableDeclaration<ClassMemberDeclaration>(
1243                 attrib->attribute, attributeDeclaration, element.type, AbortIfReopenMismatch
1244             );
1245             if ( dec ) {
1246                 dec->setRange(RangeInRevision(internal->range().start, internal->range().start));
1247                 dec->setAutoDeclaration(true);
1248                 DUChainWriteLocker lock;
1249                 previousContext->createUse(dec->ownIndex(), editorFindRange(attrib, attrib));
1250             }
1251 
1252             closeInjectedContext();
1253         }
1254     }
1255     else {
1256         DUChainWriteLocker lock;
1257         // the declaration is already there, just update the type
1258         if ( ! attributeDeclaration->type<FunctionType>() ) {
1259             auto newType = Helper::mergeTypes(attributeDeclaration->abstractType(), element.type);
1260             attributeDeclaration->setAbstractType(newType);
1261         }
1262     }
1263 }
1264 
1265 void DeclarationBuilder::tryUnpackType(AbstractType::Ptr sourceType, QVector<AbstractType::Ptr>& outTypes, int starred) {
1266     if ( const auto indexed = sourceType.dynamicCast<IndexedContainer>() ) {
1267         int spare = indexed->typesCount() - outTypes.length();
1268         if ( spare < -1 || (starred == -1 && spare != 0) ) {
1269             return; // Wrong number of elements to unpack.
1270         }
1271         for ( int i_out = 0, i_in = 0; i_out < outTypes.length(); ++i_out ) {
1272             if ( i_out == starred ) { // PEP-3132. Made into list in assignToTuple().
1273                 for (; spare >= 0; --spare, ++i_in ) {
1274                     auto content = indexed->typeAt(i_in).abstractType();
1275                     outTypes[i_out] = Helper::mergeTypes(outTypes.at(i_out), content);
1276                 }
1277             } else {
1278                 auto content = indexed->typeAt(i_in).abstractType();
1279                 outTypes[i_out] = Helper::mergeTypes(outTypes.at(i_out), content);
1280                 ++i_in;
1281             }
1282         }
1283     } else {
1284         auto content = Helper::contentOfIterable(sourceType, topContext());
1285         if ( !Helper::isUsefulType(content) ) {
1286             return;
1287         }
1288         for (auto out = outTypes.begin(); out != outTypes.end(); ++out) {
1289             *out = Helper::mergeTypes(*out, content);
1290         }
1291     }
1292 }
1293 
1294 void DeclarationBuilder::assignToTuple(TupleAst* tuple, const SourceType& element) {
1295     int starred = -1;  // Index (if any) of PEP-3132 starred assignment.
1296     for (int ii = 0; ii < tuple->elements.length(); ++ii) {
1297          if (tuple->elements.at(ii)->astType == Ast::StarredAstType) {
1298             starred = ii;
1299             break;
1300         }
1301     }
1302 
1303     QVector<AbstractType::Ptr> outTypes(tuple->elements.length());
1304 
1305     if ( auto unsure = element.type.dynamicCast<UnsureType>() ) {
1306         FOREACH_FUNCTION ( const auto& type, unsure->types ) {
1307             tryUnpackType(type.abstractType(), outTypes, starred);
1308         }
1309     } else {
1310         tryUnpackType(element.type, outTypes, starred);
1311     }
1312 
1313     for (int ii = 0; ii < outTypes.length(); ++ii) {
1314         const auto sourceType = outTypes.at(ii);
1315         auto target = tuple->elements.at(ii);
1316         if ( target->astType == Ast::StarredAstType ) {
1317             DUChainReadLocker lock;
1318             auto listType = ExpressionVisitor::typeObjectForIntegralType<ListType>("list");
1319             lock.unlock();
1320             if (listType) {
1321                 listType->addContentType<Python::UnsureType>(sourceType);
1322                 assignToUnknown(static_cast<StarredAst*>(target)->value, listType);
1323             }
1324         } else {
1325             assignToUnknown(target, sourceType);
1326         }
1327     }
1328 }
1329 
1330 void DeclarationBuilder::assignToUnknown(ExpressionAst* target, const AbstractType::Ptr type) {
1331     auto source = SourceType{
1332         type,
1333         DeclarationPointer(),
1334         false
1335     };
1336     assignToUnknown(target, source);
1337 }
1338 
1339 void DeclarationBuilder::assignToUnknown(ExpressionAst* target, const DeclarationBuilder::SourceType& element) {
1340     // Must be a nicer way to do this.
1341     if ( target->astType == Ast::TupleAstType ) {
1342         // Assignments of the form "a, b = 1, 2" or "a, b = c"
1343         assignToTuple(static_cast<TupleAst*>(target), element);
1344     }
1345     else if ( target->astType == Ast::NameAstType ) {
1346         // Assignments of the form "a = 3"
1347         assignToName(static_cast<NameAst*>(target), element);
1348     }
1349     else if ( target->astType == Ast::SubscriptAstType ) {
1350         // Assignments of the form "a[0] = 3"
1351         assignToSubscript(static_cast<SubscriptAst*>(target), element);
1352     }
1353     else if ( target->astType == Ast::AttributeAstType ) {
1354         // Assignments of the form "a.b = 3"
1355         assignToAttribute(static_cast<AttributeAst*>(target), element);
1356     }
1357 }
1358 
1359 void DeclarationBuilder::visitAssignment(AssignmentAst* node)
1360 {
1361     AstDefaultVisitor::visitAssignment(node);
1362 
1363     ExpressionVisitor v(currentContext());
1364     v.visitNode(node->value);
1365     auto sourceType = SourceType{
1366         v.lastType(),
1367         DeclarationPointer(Helper::resolveAliasDeclaration(v.lastDeclaration().data())),
1368         v.isAlias()
1369     };
1370 
1371     foreach(ExpressionAst* target, node->targets) {
1372         assignToUnknown(target, sourceType);
1373     }
1374 }
1375 
1376 void DeclarationBuilder::visitAnnotationAssignment(AnnotationAssignmentAst* node) {
1377     AstDefaultVisitor::visitAnnotationAssignment(node);
1378 
1379     ExpressionVisitor v(currentContext());
1380     v.visitNode(node->target);
1381     v.visitNode(node->value);
1382     auto assignType = v.lastType(); // Never mind aliasing, why annotate that?
1383     v.visitNode(node->annotation);
1384     assignType = Helper::mergeTypes(assignType, v.lastType());
1385     assignToUnknown(node->target, assignType);
1386 }
1387 
1388 void DeclarationBuilder::visitAssignmentExpression(AssignmentExpressionAst* node) {
1389     AstDefaultVisitor::visitAssignmentExpression(node);
1390 
1391     ExpressionVisitor v(currentContext());
1392     v.visitNode(node->value);
1393     assignToUnknown(node->target, v.lastType());
1394 }
1395 
1396 void DeclarationBuilder::visitClassDefinition( ClassDefinitionAst* node )
1397 {
1398     visitNodeList(node->decorators);
1399     visitNodeList(node->baseClasses);
1400     const CorrectionHelper::Recursion r(m_correctionHelper->enterClass(node->name->value));
1401 
1402     StructureType::Ptr type(new StructureType());
1403 
1404     DUChainWriteLocker lock;
1405     ClassDeclaration* dec = eventuallyReopenDeclaration<ClassDeclaration>(node->name, NoTypeRequired);
1406     eventuallyAssignInternalContext();
1407 
1408     dec->setKind(KDevelop::Declaration::Type);
1409     dec->clearBaseClasses();
1410     dec->setClassType(ClassDeclarationData::Class);
1411 
1412     auto docstring = getDocstring(node->body);
1413     dec->setComment(docstring);
1414     if ( ! docstring.isEmpty() ) {
1415         // check whether this is a type container (list, dict, ...) or just a "normal" class
1416         if ( Helper::docstringContainsHint(docstring, "TypeContainer") ) {
1417             ListType* container = nullptr;
1418             if ( Helper::docstringContainsHint(docstring, "hasTypedKeys") ) {
1419                 container = new MapType();
1420             }
1421             else {
1422                 container = new ListType();
1423             }
1424             type = StructureType::Ptr(container);
1425         }
1426         if ( Helper::docstringContainsHint(docstring, "IndexedTypeContainer") ) {
1427             IndexedContainer* container = new IndexedContainer();
1428             type = StructureType::Ptr(container);
1429         }
1430     }
1431     lock.unlock();
1432     foreach ( ExpressionAst* c, node->baseClasses ) {
1433         // Iterate over all the base classes, and add them to the duchain.
1434         ExpressionVisitor v(currentContext());
1435         v.visitNode(c);
1436         if ( v.lastType() && v.lastType()->whichType() == AbstractType::TypeStructure ) {
1437             auto baseClassType = v.lastType().staticCast<StructureType>();
1438             BaseClassInstance base;
1439             base.baseClass = baseClassType->indexed();
1440             base.access = KDevelop::Declaration::Public;
1441             lock.lock();
1442             dec->addBaseClass(base);
1443             lock.unlock();
1444         }
1445     }
1446     lock.lock();
1447     // every python class inherits from "object".
1448     // We use this to add all the __str__, __get__, ... methods.
1449     if ( dec->baseClassesSize() == 0 && node->name->value != "object" ) {
1450         DUChainWriteLocker wlock;
1451         ReferencedTopDUContext docContext = Helper::getDocumentationFileContext();
1452         if ( docContext ) {
1453             QList<Declaration*> object = docContext->findDeclarations(
1454                 QualifiedIdentifier("object")
1455             );
1456             if ( ! object.isEmpty() && object.first()->abstractType() ) {
1457                 Declaration* objDecl = object.first();
1458                 BaseClassInstance base;
1459                 base.baseClass = objDecl->abstractType()->indexed();
1460                 // this can be queried from autocompletion or elsewhere to hide the items, if required;
1461                 // of course, it's not private strictly speaking
1462                 base.access = KDevelop::Declaration::Private;
1463                 dec->addBaseClass(base);
1464             }
1465         }
1466     }
1467     
1468     type->setDeclaration(dec);
1469     dec->setType(type);
1470 
1471     openType(type);
1472     m_currentClassTypes.append(type);
1473 
1474     // needs to be done here, so the assignment of the internal context happens before visiting the body
1475     openContextForClassDefinition(node);
1476     dec->setInternalContext(currentContext());
1477 
1478     lock.unlock();
1479     visitNodeList(node->body);
1480     lock.lock();
1481 
1482     closeContext();
1483     m_currentClassTypes.removeLast();
1484     closeType();
1485     closeDeclaration();
1486 }
1487 
1488 void DeclarationBuilder::visitFunctionDefinition( FunctionDefinitionAst* node )
1489 {
1490     const CorrectionHelper::Recursion r(m_correctionHelper->enterFunction(node->name->value));
1491 
1492     // Search for an eventual containing class declaration;
1493     // if that exists, then this function is a member function
1494     DeclarationPointer eventualParentDeclaration(currentDeclaration());
1495     FunctionType::Ptr type(new FunctionType());
1496 
1497     DUChainWriteLocker lock;
1498     FunctionDeclaration* dec = eventuallyReopenDeclaration<FunctionDeclaration>(node->name,
1499                                                                                 FunctionDeclarationType);
1500 
1501     Q_ASSERT(dec->isFunctionDeclaration());
1502 
1503     // check for documentation
1504     dec->setComment(getDocstring(node->body));
1505 
1506     openType(type);
1507     dec->setInSymbolTable(false);
1508     dec->setType(type);
1509 
1510     lock.unlock();
1511     dec->setStatic(false);
1512     dec->setClassMethod(false);
1513     dec->setProperty(false);
1514     foreach ( auto decorator, node->decorators) {
1515         visitNode(decorator);
1516         switch (decorator->astType) {
1517           case Ast::AttributeAstType: {
1518             auto attr = static_cast<AttributeAst*>(decorator)->attribute->value;
1519             if ( attr == QStringLiteral("setter") ||
1520                  attr == QStringLiteral("getter") ||
1521                  attr == QStringLiteral("deleter") )
1522                 dec->setProperty(true);
1523             break;
1524           }
1525           case Ast::NameAstType: {
1526             auto name = static_cast<NameAst*>(decorator)->identifier->value;
1527             if ( name == QStringLiteral("staticmethod") )
1528                 dec->setStatic(true);
1529             else if ( name == QStringLiteral("classmethod") )
1530                 dec->setClassMethod(true);
1531             else if ( name == QStringLiteral("property") )
1532                 dec->setProperty(true);
1533             break;
1534           }
1535           default: {}
1536         }
1537     }
1538     visitFunctionArguments(node);
1539     visitFunctionBody(node);
1540     lock.lock();
1541 
1542     closeDeclaration();
1543     eventuallyAssignInternalContext();
1544 
1545     closeType();
1546 
1547     // python methods don't have their parents attributes directly inside them
1548     if ( eventualParentDeclaration && eventualParentDeclaration->internalContext() && dec->internalContext() ) {
1549         dec->internalContext()->removeImportedParentContext(eventualParentDeclaration->internalContext());
1550     }
1551     
1552     {
1553         static IndexedString constructorName("__init__");
1554         DUChainWriteLocker lock(DUChain::lock());
1555         if ( dec->identifier().identifier() == constructorName ) {
1556             // the constructor returns an instance of the object,
1557             // nice to display it in tooltips etc.
1558             type->setReturnType(currentType<AbstractType>());
1559         }
1560         if ( ! type->returnType() ) {
1561             type->setReturnType(AbstractType::Ptr(new NoneType()));
1562         }
1563         dec->setType(type);
1564     }
1565 
1566     if ( ! dec->isStatic() ) {
1567         DUContext* args = DUChainUtils::argumentContext(dec);
1568         if ( args )  {
1569             QVector<Declaration*> parameters = args->localDeclarations();
1570             static IndexedString newMethodName("__new__");
1571             static IndexedString selfArgumentName("self");
1572             static IndexedString clsArgumentName("cls");
1573             if ( currentContext()->type() == DUContext::Class && ! parameters.isEmpty() && ! dec->isClassMethod() ) {
1574                 QString description;
1575                 if ( dec->identifier().identifier() == newMethodName
1576                      && parameters[0]->identifier().identifier() != clsArgumentName )
1577                 {
1578                     description = i18n("First argument of __new__ method is not called cls, this is deprecated");
1579                 }
1580                 else if ( dec->identifier().identifier() != newMethodName
1581                           && parameters[0]->identifier().identifier() != selfArgumentName )
1582                 {
1583                     description = i18n("First argument of class method is not called self, this is deprecated");
1584                 }
1585                 if ( ! description.isEmpty() ) {
1586                     DUChainWriteLocker lock;
1587                     KDevelop::Problem *p = new KDevelop::Problem();
1588                     p->setDescription(description);
1589                     p->setFinalLocation(DocumentRange(currentlyParsedDocument(), parameters[0]->range().castToSimpleRange()));
1590                     p->setSource(KDevelop::IProblem::SemanticAnalysis);
1591                     p->setSeverity(KDevelop::IProblem::Warning);
1592                     ProblemPointer ptr(p);
1593                     topContext()->addProblem(ptr);
1594                 }
1595             }
1596             else if ( currentContext()->type() == DUContext::Class && parameters.isEmpty() ) {
1597                 DUChainWriteLocker lock;
1598                 KDevelop::Problem *p = new KDevelop::Problem();
1599                  // only mark first line
1600                 p->setFinalLocation(DocumentRange(currentlyParsedDocument(), KTextEditor::Range(node->startLine, node->startCol, node->startLine, 10000)));
1601                 p->setSource(KDevelop::IProblem::SemanticAnalysis);
1602                 p->setSeverity(KDevelop::IProblem::Warning);
1603                 p->setDescription(i18n("Non-static class method without arguments, must have at least one (self)"));
1604                 ProblemPointer ptr(p);
1605                 topContext()->addProblem(ptr);
1606             }
1607         }
1608     }
1609 
1610     if ( AbstractType::Ptr hint = m_correctionHelper->returnTypeHint() ) {
1611         type->setReturnType(hint);
1612         dec->setType(type);
1613     }
1614     
1615     // check for (python3) function annotations
1616     if ( node->returns ) {
1617         lock.unlock();
1618         ExpressionVisitor v(currentContext());
1619         v.visitNode(node->returns);
1620         lock.lock();
1621         if ( v.lastType() && v.isAlias() ) {
1622             type->setReturnType(Helper::mergeTypes(type->returnType(), v.lastType()));
1623             dec->setType(type);
1624         }
1625         else if ( ! v.isAlias()) {
1626             qCDebug(KDEV_PYTHON_DUCHAIN) << "not updating function return type because expression is not a type object";
1627         }
1628     }
1629     
1630     lock.lock();
1631     dec->setInSymbolTable(true);
1632 }
1633 
1634 QString DeclarationBuilder::getDocstring(QList< Python::Ast* > body) const
1635 {
1636     if ( ! body.isEmpty() && body.first()->astType == Ast::ExpressionAstType 
1637             && static_cast<ExpressionAst*>(body.first())->value->astType == Ast::StringAstType )
1638     {
1639         // If the first statement in a function/class body is a string, then that is the docstring.
1640         StringAst* docstring = static_cast<StringAst*>(static_cast<ExpressionAst*>(body.first())->value);
1641         docstring->usedAsComment = true;
1642         return docstring->value.trimmed();
1643     }
1644     return QString();
1645 }
1646 
1647 void DeclarationBuilder::visitAssertion(AssertionAst* node)
1648 {
1649     adjustForTypecheck(node->condition, false);
1650     Python::AstDefaultVisitor::visitAssertion(node);
1651 }
1652 
1653 void DeclarationBuilder::visitIf(IfAst* node)
1654 {
1655     adjustForTypecheck(node->condition, true);
1656     Python::AstDefaultVisitor::visitIf(node);
1657 }
1658 
1659 void DeclarationBuilder::adjustForTypecheck(Python::ExpressionAst* check, bool useUnsure)
1660 {
1661     if ( ! check ) return;
1662     if ( check->astType == Ast::UnaryOperationAstType
1663          && static_cast<UnaryOperationAst*>(check)->type == Ast::UnaryOperatorNot )
1664     {
1665         // It could be something like " if not isinstance(foo, Bar): return None ".
1666         check = static_cast<UnaryOperationAst*>(check)->operand;
1667     }
1668     if ( check->astType == Ast::CallAstType ) {
1669         // Is this a call of the form "isinstance(foo, bar)"?
1670         CallAst* call = static_cast<CallAst*>(check);
1671         if ( ! call->function ) {
1672             return;
1673         }
1674         if ( call->function->astType != Ast::NameAstType ) {
1675             return;
1676         }
1677         const QString functionName = static_cast<Python::NameAst*>(call->function)->identifier->value;
1678         if ( functionName != QLatin1String("isinstance") ) {
1679             return;
1680         }
1681         if ( call->arguments.length() != 2 ) {
1682             return;
1683         }
1684         adjustExpressionsForTypecheck(call->arguments.at(0), call->arguments.at(1), useUnsure);
1685     }
1686     else if ( check->astType == Ast::CompareAstType ) {
1687         // Is this a call of the form "type(ainstance) == a"?
1688         CompareAst* compare = static_cast<CompareAst*>(check);
1689         if ( compare->operators.size() != 1 || compare->comparands.size() != 1 ) {
1690             return;
1691         }
1692         if ( compare->operators.first() != Ast::ComparisonOperatorEquals ) {
1693             return;
1694         }
1695         ExpressionAst* c1 = compare->comparands.first();
1696         ExpressionAst* c2 = compare->leftmostElement;
1697         if ( ! ( (c1->astType == Ast::CallAstType) ^ (c2->astType == Ast::CallAstType) ) ) {
1698             // Exactly one of the two must be a call. TODO: support adjusting function return types
1699             return;
1700         }
1701         CallAst* typecall = static_cast<CallAst*>(c1->astType == Ast::CallAstType ? c1 : c2);
1702         if ( ! typecall->function || typecall->function->astType != Ast::NameAstType || typecall->arguments.length() != 1 ) {
1703             return;
1704         }
1705         const QString functionName = static_cast<Python::NameAst*>(typecall->function)->identifier->value;
1706         if ( functionName != QLatin1String("type") ) {
1707             return;
1708         }
1709         adjustExpressionsForTypecheck(typecall->arguments.at(0), c1->astType == Ast::CallAstType ? c2 : c1, useUnsure);
1710     }
1711 }
1712 
1713 void DeclarationBuilder::adjustExpressionsForTypecheck(Python::ExpressionAst* adjustExpr, Python::ExpressionAst* from, bool useUnsure)
1714 {
1715     // Find types of the two arguments
1716     ExpressionVisitor first(currentContext());
1717     ExpressionVisitor second(currentContext());
1718     first.visitNode(adjustExpr);
1719     second.visitNode(from);
1720     AbstractType::Ptr hint;
1721     DeclarationPointer adjust;
1722     if ( second.isAlias() && second.lastType() ) {
1723         hint = second.lastType();
1724         adjust = first.lastDeclaration();
1725     }
1726     if ( ! adjust || adjust->isFunctionDeclaration() ) {
1727         // no declaration for the thing to verify, can't adjust it.
1728         return;
1729     }
1730     else if ( adjust->topContext() == Helper::getDocumentationFileContext() ) {
1731         // do not motify types in the doc context
1732         return;
1733     }
1734     DUChainWriteLocker lock;
1735     if ( useUnsure ) {
1736         adjust->setAbstractType(Helper::mergeTypes(adjust->abstractType(), hint));
1737     }
1738     else {
1739         adjust->setAbstractType(hint);
1740     }
1741 }
1742 
1743 void DeclarationBuilder::visitReturn(ReturnAst* node)
1744 {
1745     static auto noneType = AbstractType::Ptr(new NoneType());
1746 
1747     if ( auto function = currentType<FunctionType>() ) {
1748         // Statements with no explicit value return `None`.
1749         auto encountered = noneType;
1750         if ( node->value ) {
1751             // Find the type of the object being "return"ed
1752             ExpressionVisitor v(currentContext());
1753             v.visitNode(node->value);
1754             encountered = v.lastType();
1755         }
1756         // Update the containing function's return type
1757         DUChainWriteLocker lock;
1758         function->setReturnType(Helper::mergeTypes(function->returnType(), encountered));
1759     } else {
1760         DUChainWriteLocker lock;
1761         KDevelop::Problem *p = new KDevelop::Problem();
1762         p->setFinalLocation(DocumentRange(currentlyParsedDocument(), node->range())); // only mark first line
1763         p->setSource(KDevelop::IProblem::SemanticAnalysis);
1764         p->setDescription(i18n("Return statement not within function declaration"));
1765         ProblemPointer ptr(p);
1766         topContext()->addProblem(ptr);
1767     }
1768     DeclarationBuilderBase::visitReturn(node);
1769 }
1770 
1771 void DeclarationBuilder::visitArguments( ArgumentsAst* node )
1772 {
1773     if ( ! currentDeclaration() || ! currentDeclaration()->isFunctionDeclaration() ) {
1774         return;
1775     }
1776     FunctionDeclaration* workingOnDeclaration = static_cast<FunctionDeclaration*>(Helper::resolveAliasDeclaration(currentDeclaration()));
1777     workingOnDeclaration->clearDefaultParameters();
1778     if ( ! hasCurrentType() || ! currentType<FunctionType>() ) {
1779         return;
1780     }
1781     FunctionType::Ptr type = currentType<FunctionType>();
1782     bool isFirst = true;
1783     int defaultParametersCount = node->defaultValues.length();
1784     int parametersCount = node->arguments.length();
1785     int firstDefaultParameterOffset = parametersCount - defaultParametersCount;
1786 
1787     int defaultKwParametersCount = node->defaultKwValues.length();
1788     int kwonlyCount = node->kwonlyargs.length();
1789     int posonlyCount = node->posonlyargs.length();
1790     int totalArgCount = parametersCount + posonlyCount + kwonlyCount;
1791     int firstDefaultKwParameterOffset = totalArgCount - defaultKwParametersCount;
1792     int currentIndex = 0;
1793     foreach ( ArgAst* arg, node->posonlyargs + node->arguments + node->kwonlyargs ) {
1794         // Iterate over all the function's arguments, create declarations, and add the arguments
1795         // to the functions FunctionType.
1796         currentIndex += 1;
1797 
1798         if ( ! arg->argumentName ) {
1799             continue;
1800         }
1801 
1802         // Create a variable declaration for the parameter, to be used in the function body.
1803         Declaration* paramDeclaration = nullptr;
1804         if ( currentIndex == 1 && workingOnDeclaration->isClassMethod() ) {
1805             DUChainWriteLocker lock;
1806             AliasDeclaration* decl = eventuallyReopenDeclaration<AliasDeclaration>(arg->argumentName,
1807                                                                                    AliasDeclarationType);
1808             if ( ! m_currentClassTypes.isEmpty() ) {
1809                 auto classDecl = m_currentClassTypes.last()->declaration(topContext());
1810 
1811                 decl->setAliasedDeclaration(classDecl);
1812             }
1813             closeDeclaration();
1814             paramDeclaration = decl;
1815         }
1816         else {
1817             paramDeclaration = visitVariableDeclaration<Declaration>(arg->argumentName);
1818         }
1819         if ( ! paramDeclaration ) {
1820             qCDebug(KDEV_PYTHON_DUCHAIN) << "could not create parameter declaration!";
1821             continue;
1822         }
1823 
1824         AbstractType::Ptr argumentType(new IntegralType(IntegralType::TypeMixed));
1825         if ( arg->annotation ) {
1826             ExpressionVisitor v(currentContext());
1827             v.visitNode(arg->annotation);
1828             if ( v.lastType() && v.isAlias() ) {
1829                 DUChainWriteLocker lock;
1830                 argumentType = Helper::mergeTypes(paramDeclaration->abstractType(), v.lastType());
1831             }
1832         }
1833         else if ( currentIndex > firstDefaultParameterOffset && currentIndex <= node->arguments.size() ) {
1834             // Handle arguments with default values, like def foo(bar = 3): pass
1835             // Find type of given default value, and assign it to the declaration
1836             ExpressionVisitor v(currentContext());
1837             v.visitNode(node->defaultValues.at(currentIndex - firstDefaultParameterOffset - 1));
1838             if ( v.lastType() ) {
1839                 argumentType = v.lastType();
1840             }
1841             // TODO add the real expression from the document here as default value
1842             workingOnDeclaration->addDefaultParameter(IndexedString("..."));
1843         }
1844         else if ( currentIndex > firstDefaultKwParameterOffset && currentIndex <= totalArgCount ) {
1845             // Handle kw only arguments with default values, like def foo(*, bar = 3): pass
1846             // Find type of given default value, and assign it to the declaration
1847             ExpressionVisitor v(currentContext());
1848             v.visitNode(node->defaultKwValues.at(currentIndex - firstDefaultKwParameterOffset - 1));
1849             if ( v.lastType() ) {
1850                 argumentType = v.lastType();
1851             }
1852             // TODO add the real expression from the document here as default value
1853             workingOnDeclaration->addDefaultParameter(IndexedString("..."));
1854         }
1855 
1856 
1857         if ( isFirst && ! workingOnDeclaration->isStatic() && currentContext() && currentContext()->parentContext() ) {
1858             DUChainReadLocker lock;
1859             if ( currentContext()->parentContext()->type() == DUContext::Class ) {
1860                 argumentType = m_currentClassTypes.last();
1861                 isFirst = false;
1862             }
1863         }
1864 
1865         DUChainWriteLocker lock;
1866         paramDeclaration->setAbstractType(Helper::mergeTypes(paramDeclaration->abstractType(), argumentType));
1867         type->addArgument(argumentType);
1868     }
1869     // Handle *args, **kwargs, and assign them a list / dictionary type.
1870     if ( node->vararg ) {
1871         // inject the vararg at the correct place
1872         int atIndex = 0;
1873         int useIndex = -1;
1874         foreach ( ArgAst* arg, node->arguments ) {
1875             if ( node->vararg && workingOnDeclaration->vararg() == -1 && node->vararg->appearsBefore(arg) ) {
1876                 useIndex = atIndex;
1877             }
1878             atIndex += 1;
1879         }
1880         if ( useIndex == -1 ) {
1881             // if the vararg does not appear in the middle of the params, place it at the end.
1882             // this is new in python3, you can do like def fun(a, b, *c, z): pass
1883             useIndex = type->arguments().size();
1884         }
1885         DUChainReadLocker lock;
1886         IndexedContainer::Ptr tupleType = ExpressionVisitor::typeObjectForIntegralType<IndexedContainer>("tuple");
1887         lock.unlock();
1888         if ( tupleType ) {
1889             visitVariableDeclaration<Declaration>(node->vararg->argumentName, nullptr, tupleType);
1890             workingOnDeclaration->setVararg(atIndex);
1891             type->addArgument(tupleType, useIndex);
1892         }
1893     }
1894 
1895     if ( node->kwarg ) {
1896         DUChainReadLocker lock;
1897         AbstractType::Ptr stringType = ExpressionVisitor::typeObjectForIntegralType<AbstractType>("str");
1898         auto dictType = ExpressionVisitor::typeObjectForIntegralType<MapType>("dict");
1899         lock.unlock();
1900         if ( dictType && stringType ) {
1901             dictType->addKeyType<Python::UnsureType>(stringType);
1902             visitVariableDeclaration<Declaration>(node->kwarg->argumentName, nullptr, dictType);
1903             type->addArgument(dictType);
1904             workingOnDeclaration->setKwarg(type->arguments().size() - 1);
1905         }
1906     }
1907 }
1908 
1909 void DeclarationBuilder::visitString(StringAst* node) {
1910     if ( node->parent && node->parent->astType == Ast::ExpressionAstType ) {
1911         m_lastComment = node;
1912     }
1913     DeclarationBuilderBase::visitString(node);
1914 }
1915 
1916 void DeclarationBuilder::visitNode(Ast* node) {
1917     DeclarationBuilderBase::visitNode(node);
1918     if ( node && node->astType >= Ast::StatementAstType && node->astType <= Ast::LastStatementType) {
1919         m_lastComment = nullptr;
1920     }
1921 }
1922 
1923 void DeclarationBuilder::visitGlobal(GlobalAst* node)
1924 {
1925     TopDUContext* top = topContext();
1926     foreach ( Identifier *id, node->names ) {
1927         QualifiedIdentifier qid = identifierForNode(id);
1928         DUChainWriteLocker lock;
1929         QList< Declaration* > existing = top->findLocalDeclarations(qid.first());
1930         if ( ! existing.empty() ) {
1931             AliasDeclaration* ndec = openDeclaration<AliasDeclaration>(id);
1932             ndec->setAliasedDeclaration(existing.first());
1933             closeDeclaration();
1934         }
1935         else {
1936             injectContext(top);
1937             Declaration* dec = visitVariableDeclaration<Declaration>(id);
1938             dec->setRange(editorFindRange(id, id));
1939             dec->setAutoDeclaration(true);
1940             closeContext();
1941             AliasDeclaration* ndec = openDeclaration<AliasDeclaration>(id);
1942             ndec->setAliasedDeclaration(dec);
1943             closeDeclaration();
1944         }
1945     }
1946 }
1947 
1948 }
1949 
1950