PyQualifiedNameOwner (@NotNull String name, @NotNull PyExpression typeHint, @NotNull Context context) { PsiElement typeHintContext = getStubRetainedTypeHintContext(typeHint); // TODO: type aliases List<PyQualifiedNameOwner> typeParamOwnerCandidates = StreamEx.iterate(typeHintContext, Objects::nonNull, owner -> PsiTreeUtil.getStubOrPsiParentOfType(owner, ScopeOwner.class)) .filter(owner -> owner instanceof PyFunction || owner instanceof PyClass) .select(PyQualifiedNameOwner.class) .toList(); PyQualifiedNameOwner closestOwner = ContainerUtil.getFirstItem(typeParamOwnerCandidates); if (closestOwner instanceof PyClass) { return closestOwner; } return StreamEx.of(typeParamOwnerCandidates) .skip(1) .map(owner -> findSameTypeParameterInDefinition(owner, name, context)) .nonNull() .findFirst() .map(PyTypeParameterType::getScopeOwner) .orElse(closestOwner); }