@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 suggestNonImportedClasses(
      CompletionParameters parameters, CompletionResultSet result) {
    final ClassByNameMerger merger =
        new ClassByNameMerger(parameters.getInvocationCount() == 0, result);

    JavaClassNameCompletionContributor.addAllClasses(
        parameters,
        true,
        JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(),
        new Consumer<LookupElement>() {
          @Override
          public void consume(LookupElement element) {
            JavaPsiClassReferenceElement classElement =
                element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
            if (classElement != null) {
              classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
            }

            merger.consume(classElement);
          }
        });

    merger.finishedClassProcessing();
  }
  @Override
  public void fillCompletionVariants(
      final CompletionParameters parameters, final CompletionResultSet _result) {
    if (parameters.getCompletionType() != CompletionType.BASIC) {
      return;
    }

    final PsiElement position = parameters.getPosition();
    if (!isInJavaContext(position)) {
      return;
    }

    if (AFTER_NUMBER_LITERAL.accepts(position)
        || UNEXPECTED_REFERENCE_AFTER_DOT.accepts(position)) {
      _result.stopHere();
      return;
    }

    final CompletionResultSet result = JavaCompletionSorting.addJavaSorting(parameters, _result);

    if (ANNOTATION_ATTRIBUTE_NAME.accepts(position)
        && !JavaCompletionData.isAfterPrimitiveOrArrayType(position)) {
      JavaCompletionData.addExpectedTypeMembers(parameters, result);
      completeAnnotationAttributeName(result, position, parameters);
      result.stopHere();
      return;
    }

    final InheritorsHolder inheritors = new InheritorsHolder(position, result);
    if (JavaSmartCompletionContributor.IN_TYPE_ARGS.accepts(position)) {
      new TypeArgumentCompletionProvider(false, inheritors)
          .addCompletions(parameters, new ProcessingContext(), result);
    }

    PrefixMatcher matcher = result.getPrefixMatcher();
    if (JavaSmartCompletionContributor.AFTER_NEW.accepts(position)) {
      new JavaInheritorsGetter(ConstructorInsertHandler.BASIC_INSTANCE)
          .generateVariants(parameters, matcher, inheritors);
    }

    if (IMPORT_REFERENCE.accepts(position)) {
      result.addElement(LookupElementBuilder.create("*"));
    }

    addKeywords(parameters, result);

    Set<String> usedWords = addReferenceVariants(parameters, result, inheritors);

    if (psiElement().inside(PsiLiteralExpression.class).accepts(position)) {
      PsiReference reference = position.getContainingFile().findReferenceAt(parameters.getOffset());
      if (reference == null || reference.isSoft()) {
        WordCompletionContributor.addWordCompletionVariants(result, parameters, usedWords);
      }
    }

    JavaGenerateMemberCompletionContributor.fillCompletionVariants(parameters, result);

    addAllClasses(parameters, result, inheritors);

    final PsiElement parent = position.getParent();
    if (parent instanceof PsiReferenceExpression
        && !((PsiReferenceExpression) parent).isQualified()
        && parameters.isExtendedCompletion()
        && StringUtil.isNotEmpty(matcher.getPrefix())) {
      new JavaStaticMemberProcessor(parameters).processStaticMethodsGlobally(matcher, result);
    }
    result.stopHere();
  }