List<QualifiedRatedResolveResult> (@NotNull PyResolveContext resolveContext, @NotNull Predicate<? super PyTargetExpression> follow) { final List<QualifiedRatedResolveResult> result = new ArrayList<>(); final Queue<MultiFollowQueueNode> queue = new LinkedList<>(); final Set<PyReferenceExpression> visited = new HashSet<>(); queue.add(MultiFollowQueueNode.create(null, this)); visited.add(this); final TypeEvalContext context = resolveContext.getTypeEvalContext(); while (!queue.isEmpty()) { final MultiFollowQueueNode node = queue.remove(); for (ResolveResult resolveResult : node.myReferenceExpression.getReference(resolveContext).multiResolve(false)) { final PsiElement element = resolveResult.getElement(); if (element instanceof PyTargetExpression target && follow.test((PyTargetExpression)element)) { final List<PsiElement> assignedFromElements = context.maySwitchToAST(target) ? Collections.singletonList(target.findAssignedValue()) : target.multiResolveAssignedValue(resolveContext); for (PsiElement assignedFrom : assignedFromElements) { if (assignedFrom instanceof PyReferenceExpression assignedReference) { if (!visited.add(assignedReference)) continue; queue.add(MultiFollowQueueNode.create(node, assignedReference)); } else if (assignedFrom != null) { result.add( new QualifiedRatedResolveResult( assignedFrom, node.myQualifiers, resolveResult instanceof RatedResolveResult ? ((RatedResolveResult)resolveResult).getRate() : 0, resolveResult instanceof ImplicitResolveResult ) ); } } } else if (element != null && resolveResult.isValidResult()) { result.add( new QualifiedRatedResolveResult( element, node.myQualifiers, resolveResult instanceof RatedResolveResult ? ((RatedResolveResult)resolveResult).getRate() : 0, resolveResult instanceof ImplicitResolveResult ) ); } } } return result; }