@Nullable
  private static PyQualifiedNameOwner getTypeParameterScope(@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);
  }
@Nullable
  private static PyQualifiedNameOwner getTypeParameterScope(@NotNull String name, @NotNull PyExpression typeHint, @NotNull Context context)