diff --git a/duchain/helpers.cpp b/duchain/helpers.cpp --- a/duchain/helpers.cpp +++ b/duchain/helpers.cpp @@ -179,43 +179,45 @@ Declaration* Helper::declarationForName(const QualifiedIdentifier& identifier, const RangeInRevision& nodeRange, KDevelop::DUChainPointer context) { - QList declarations; - QList localDeclarations; - QList importedLocalDeclarations; - { - DUChainReadLocker lock(DUChain::lock()); - if ( context.data() == context->topContext() && nodeRange.isValid() ) { - declarations = context->topContext()->findDeclarations(identifier, nodeRange.end); - } - else { - declarations = context->topContext()->findDeclarations(identifier, CursorInRevision::invalid()); - } - localDeclarations = context->findLocalDeclarations(identifier.last(), nodeRange.end, 0, - AbstractType::Ptr(0), DUContext::DontResolveAliases); - importedLocalDeclarations = context->findDeclarations(identifier.last(), nodeRange.end); - } - Declaration* declaration = 0; - if ( localDeclarations.length() ) { - declaration = localDeclarations.last(); + DUChainReadLocker lock(DUChain::lock()); + auto localDeclarations = context->findLocalDeclarations(identifier.last(), nodeRange.end, 0, + AbstractType::Ptr(0), DUContext::DontResolveAliases); + if ( !localDeclarations.isEmpty() ) { + return localDeclarations.last(); } - else if ( importedLocalDeclarations.length() ) { - // don't use declarations from class decls, they must be referenced through "self." - do { - declaration = importedLocalDeclarations.last(); - importedLocalDeclarations.pop_back(); - if ( !declaration || (declaration->context()->type() == DUContext::Class && context->type() != DUContext::Function) ) { - declaration = 0; + + QList declarations; + const DUContext* currentContext = context.data(); + bool findInNext = true, findBeyondUse = false; + do { + if (findInNext) { + CursorInRevision findUntil = findBeyondUse ? currentContext->topContext()->range().end : nodeRange.end; + declarations = currentContext->findDeclarations(identifier.last(), findUntil); + + for (Declaration* declaration: declarations) { + if (declaration->context()->type() != DUContext::Class || + (currentContext->type() == DUContext::Function && declaration->context() == currentContext->parentContext())) { + // Declarations from class decls must be referenced through `self.`, except + // in their local scope (handled above) or when used as default arguments for methods of the same class. + // Otherwise, we're done! + return declaration; + } } - if ( importedLocalDeclarations.isEmpty() ) { - break; + if (!declarations.isEmpty()) { + // If we found declarations but rejected all of them (i.e. didn't return), we need to keep searching. + findInNext = true; + declarations.clear(); } - } while ( ! importedLocalDeclarations.isEmpty() ); - } + } - if ( !declaration && declarations.length() ) { - declaration = declarations.last(); - } - return declaration; + if (!findBeyondUse && currentContext->owner() && currentContext->owner()->isFunctionDeclaration()) { + // Names in the body may be defined after the function definition, before the function is called. + // Note: only the parameter list has type DUContext::Function, so we have to do this instead. + findBeyondUse = findInNext = true; + } + } while ((currentContext = currentContext->parentContext())); + + return nullptr; } QVector Helper::internalContextsForClass(const StructureType::Ptr classType,