@Override
  public void fillCompletionVariants(
      @NotNull final CompletionParameters parameters, @NotNull final CompletionResultSet result) {
    final JavaCompletionSession session = new JavaCompletionSession(result);
    ResultTracker tracker =
        new ResultTracker(result) {
          @Override
          public void consume(CompletionResult plainResult) {
            super.consume(plainResult);

            LookupElement element = plainResult.getLookupElement();
            Object o = element.getObject();
            if (o instanceof PsiClass) {
              session.registerClass((PsiClass) o);
            }
            if (element instanceof TypeArgumentCompletionProvider.TypeArgsLookupElement) {
              ((TypeArgumentCompletionProvider.TypeArgsLookupElement) element)
                  .registerSingleClass(session);
            }
          }
        };
    result.runRemainingContributors(parameters, tracker);
    final boolean empty = tracker.containsOnlyPackages || suggestAllAnnotations(parameters);

    if (!empty && parameters.getInvocationCount() == 0) {
      result.restartCompletionWhenNothingMatches();
    }

    if (empty) {
      delegate(parameters, JavaCompletionSorting.addJavaSorting(parameters, result), session);
    } else if (Registry.is("ide.completion.show.better.matching.classes")) {
      if (parameters.getCompletionType() == CompletionType.BASIC
          && parameters.getInvocationCount() <= 1
          && JavaCompletionContributor.mayStartClassName(result)
          && JavaCompletionContributor.isClassNamePossible(parameters)
          && !JavaSmartCompletionContributor.AFTER_NEW.accepts(parameters.getPosition())) {
        suggestNonImportedClasses(
            parameters,
            JavaCompletionSorting.addJavaSorting(
                parameters, result.withPrefixMatcher(tracker.betterMatcher)),
            session);
      }
    }
  }
  private static void delegate(
      CompletionParameters parameters, CompletionResultSet result, JavaCompletionSession session) {
    if (parameters.getCompletionType() == CompletionType.BASIC) {
      PsiElement position = parameters.getPosition();
      suggestCollectionUtilities(parameters, result, position);

      if (parameters.getInvocationCount() <= 1
          && (JavaCompletionContributor.mayStartClassName(result)
              || suggestAllAnnotations(parameters))
          && JavaCompletionContributor.isClassNamePossible(parameters)) {
        suggestNonImportedClasses(parameters, result, session);
        return;
      }

      suggestChainedCalls(parameters, result, position);
    }

    if (parameters.getCompletionType() == CompletionType.SMART
        && parameters.getInvocationCount() == 2) {
      result.runRemainingContributors(parameters.withInvocationCount(3), true);
    }
  }
  @Override
  protected void delegate(
      CompletionParameters parameters,
      CompletionResultSet result,
      Consumer<CompletionResult> passResult) {
    if (parameters.getCompletionType() == CompletionType.BASIC) {
      PsiElement position = parameters.getPosition();
      if (parameters.getInvocationCount() <= 1
          && JavaCompletionContributor.mayStartClassName(result, false)
          && JavaCompletionContributor.isClassNamePossible(position)) {
        suggestNonImportedClasses(parameters, result);
        return;
      }

      suggestChainedCalls(parameters, result, position);
    }

    if (parameters.getCompletionType() == CompletionType.SMART
        && parameters.getInvocationCount() == 2) {
      result.runRemainingContributors(parameters.withInvocationCount(3), passResult);
    }
  }