List<RatedResolveResult> (@NotNull String referencedName, @NotNull PyResolveProcessor processor, @Nullable PsiElement realContext, @Nullable PsiElement resolveRoof) { boolean unreachableLocalDeclaration = false; Supplier<ScopeOwner> resolveInParentScope = null; final ResolveResultList resultList = new ResolveResultList(); final ScopeOwner referenceOwner = ScopeUtil.getScopeOwner(realContext); final TypeEvalContext typeEvalContext = myContext.getTypeEvalContext(); final ScopeOwner resolvedOwner = processor.getOwner(); final Collection<PsiElement> resolvedElements = processor.getElements(); if (resolvedOwner != null && !resolvedElements.isEmpty() && !ControlFlowCache.getScope(resolvedOwner).isGlobal(referencedName)) { if (resolvedOwner == referenceOwner) { final List<Instruction> instructions = getLatestDefinitions(referencedName, resolvedOwner, realContext); // TODO: Use the results from the processor as a cache for resolving to latest defs final ResolveResultList latestDefs = resolveToLatestDefs(instructions, realContext, referencedName, typeEvalContext); if (!latestDefs.isEmpty()) { return StreamEx.of(latestDefs) .flatMap(r -> { if (r.getClass() != RatedResolveResult.class || !(r.getElement() instanceof PyFunction pyFunction)) { return StreamEx.of(r); } int adjustedRate = r.getRate() == RatedResolveResult.RATE_PY_FILE_OVERLOAD ? RatedResolveResult.RATE_LIFTED_PY_FILE_OVERLOAD : r.getRate(); return StreamEx.of(PyiUtil.getOverloads(pyFunction, typeEvalContext)) .map(overload -> new RatedResolveResult(getRate(overload, typeEvalContext), overload)) .prepend(StreamEx.ofNullable( PyiUtil.isInsideStub(myElement) ? null : new RatedResolveResult(adjustedRate, pyFunction) )); }) .toImmutableList(); } else if (resolvedOwner instanceof PyClass) { resolveInParentScope = () -> PyResolveUtil.parentScopeForUnresolvedClassLevelName((PyClass)resolvedOwner, referencedName); } else if (instructions.isEmpty() && allInOwnScopeComprehensions(resolvedElements)) { resolveInParentScope = () -> ScopeUtil.getScopeOwner(resolvedOwner); } else { unreachableLocalDeclaration = true; } } else if (referenceOwner != null) { if (!allowsForwardOutgoingReferencesInClass(myElement)) { final PyClass outermostNestedClass = outermostNestedClass(referenceOwner, resolvedOwner); if (outermostNestedClass != null) { final List<Instruction> instructions = PyDefUseUtil.getLatestDefs(resolvedOwner, referencedName, outermostNestedClass, false, true); return resolveToLatestDefs(instructions, outermostNestedClass, referencedName, typeEvalContext); } } final Scope referenceScope = ControlFlowCache.getScope(referenceOwner); if (referenceScope.containsDeclaration(referencedName)) { unreachableLocalDeclaration = true; } } } // TODO: Try resolve to latest defs for outer scopes starting from the last element in CFG (=> no need for a special rate for globals) if (!unreachableLocalDeclaration) { if (resolveInParentScope != null) { processor = new PyResolveProcessor(referencedName); final ScopeOwner parentScope = resolveInParentScope.get(); if (parentScope != null) { PyResolveUtil.scopeCrawlUp(processor, parentScope, referencedName, resolveRoof); } } for (Map.Entry<PsiElement, PyImportedNameDefiner> entry : processor.getResults().entrySet()) { final PsiElement resolved = entry.getKey(); final PyImportedNameDefiner definer = entry.getValue(); if (resolved != null) { if (typeEvalContext.maySwitchToAST(resolved) && isInnerComprehension(realContext, resolved)) { continue; } if (definer == null) { resultList.poke(resolved, getRate(resolved, typeEvalContext)); } else { resultList.poke(definer, getRate(definer, typeEvalContext)); resultList.add(new ImportedResolveResult(resolved, getRate(resolved, typeEvalContext), definer)); } } else if (definer != null) { resultList.add(new ImportedResolveResult(null, RatedResolveResult.RATE_LOW, definer)); } } if (!resultList.isEmpty()) { return resultList; } } return resolveByReferenceResolveProviders(); }