@Override
  public Object @NotNull [] getCompletionVariants(String prefix, PsiElement location, @NotNull ProcessingContext context) {
    if (isRecursive(context)) return ArrayUtilRt.EMPTY_OBJECT_ARRAY;
    final Set<String> visited = visitedNames(context);

    final PsiFile origin = location != null ? CompletionUtilCoreImpl.getOriginalOrSelf(location).getContainingFile() : null;
    final TypeEvalContext typeEvalContext = TypeEvalContext.codeCompletion(myClass.getProject(), origin);

    final boolean withinOurClass = withinClass(getPyClass(), location);
    final Condition<String> nameFilter = name -> {
      if (!withinOurClass && PyUtil.isClassPrivateName(name)) return false;
      if (!withinOurClass && isClassProtected(name) && prefix == null) return false;
      return visited.add(name);
    };

    final CompletionVariantsProcessor processor =
      new CompletionVariantsProcessor(location, null, nameFilter, false, context.get(CTX_SUPPRESS_PARENTHESES) != null);

    processMembers(processor, () -> processor.setAllowedNames(myClass.getSlots(typeEvalContext)));
    final List<Object> result = new ArrayList<>(processor.getResultList());

    processOwnSlots(
      slot -> {
        if (visited.add(slot)) result.add(LookupElementBuilder.create(slot));
        return true;
      },
      typeEvalContext
    );

    // provided
    processProvidedMembers(
      member -> {
        if (visited.add(member.getName())) result.add(PyCustomMemberUtils.toLookUpElement(member, getName()));
        return true;
      },
      location,
      typeEvalContext
    );

    // inherited
    prepareTypesForProcessingMembers(getSuperClassTypes(typeEvalContext))
      .flatArray(type -> type.getCompletionVariants(prefix, location, context))
      .into(result);

    processMetaClassMembers(
      typeType -> ContainerUtil.addAll(result, typeType.getCompletionVariants(prefix, location, context)),
      typeInstanceAttribute -> {
        result.add(LookupElementBuilder.create(typeInstanceAttribute));
        return true;
      },
      typeEvalContext
    );

    return result.toArray();
  }
@Override
  public Object @NotNull [] getCompletionVariants(String prefix, PsiElement location, @NotNull ProcessingContext context)