private static Set<LookupElement> suggestQualifierItems(
      CompletionParameters parameters,
      PsiJavaCodeReferenceElement qualifier,
      ElementFilter filter) {
    String referenceName = qualifier.getReferenceName();
    if (referenceName == null) {
      return Collections.emptySet();
    }

    PrefixMatcher qMatcher = new CamelHumpMatcher(referenceName);
    Set<LookupElement> plainVariants =
        JavaSmartCompletionContributor.completeReference(
            qualifier, qualifier, filter, true, true, parameters, qMatcher);

    for (PsiClass aClass :
        PsiShortNamesCache.getInstance(qualifier.getProject())
            .getClassesByName(referenceName, qualifier.getResolveScope())) {
      plainVariants.add(JavaClassNameCompletionContributor.createClassLookupItem(aClass, true));
    }

    if (!plainVariants.isEmpty()) {
      return plainVariants;
    }

    final Set<LookupElement> allClasses = new LinkedHashSet<LookupElement>();
    PsiElement qualifierName = qualifier.getReferenceNameElement();
    if (qualifierName != null) {
      JavaClassNameCompletionContributor.addAllClasses(
          parameters.withPosition(qualifierName, qualifierName.getTextRange().getEndOffset()),
          true,
          qMatcher,
          new CollectConsumer<LookupElement>(allClasses));
    }
    return allClasses;
  }
  static List<? extends LookupElement> createLookupElements(
      CompletionElement completionElement, PsiJavaReference reference) {
    Object completion = completionElement.getElement();
    assert !(completion instanceof LookupElement);

    if (reference instanceof PsiJavaCodeReferenceElement) {
      if (completion instanceof PsiMethod
          && ((PsiJavaCodeReferenceElement) reference).getParent()
              instanceof PsiImportStaticStatement) {
        return Collections.singletonList(
            JavaLookupElementBuilder.forMethod((PsiMethod) completion, PsiSubstitutor.EMPTY));
      }

      if (completion instanceof PsiClass) {
        return JavaClassNameCompletionContributor.createClassLookupItems(
            (PsiClass) completion,
            JavaClassNameCompletionContributor.AFTER_NEW.accepts(reference),
            JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER,
            Conditions.<PsiClass>alwaysTrue());
      }
    }

    if (reference instanceof PsiMethodReferenceExpression
        && completion instanceof PsiMethod
        && ((PsiMethod) completion).isConstructor()) {
      return Collections.singletonList(
          JavaLookupElementBuilder.forMethod(
              (PsiMethod) completion, "new", PsiSubstitutor.EMPTY, null));
    }

    PsiSubstitutor substitutor = completionElement.getSubstitutor();
    if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
    if (completion instanceof PsiClass) {
      return Collections.singletonList(
          JavaClassNameCompletionContributor.createClassLookupItem((PsiClass) completion, true)
              .setSubstitutor(substitutor));
    }
    if (completion instanceof PsiMethod) {
      return Collections.singletonList(
          new JavaMethodCallElement((PsiMethod) completion).setQualifierSubstitutor(substitutor));
    }
    if (completion instanceof PsiVariable) {
      return Collections.singletonList(
          new VariableLookupItem((PsiVariable) completion).setSubstitutor(substitutor));
    }

    return Collections.singletonList(LookupItemUtil.objectToLookupItem(completion));
  }
  public static void addAllClasses(
      CompletionParameters parameters,
      final CompletionResultSet result,
      final InheritorsHolder inheritors) {
    if (!isClassNamePossible(parameters) || !mayStartClassName(result)) {
      return;
    }

    if (parameters.getInvocationCount() >= 2) {
      JavaClassNameCompletionContributor.addAllClasses(
          parameters,
          parameters.getInvocationCount() <= 2,
          result.getPrefixMatcher(),
          new Consumer<LookupElement>() {
            @Override
            public void consume(LookupElement element) {
              if (!inheritors.alreadyProcessed(element)) {
                result.addElement(element);
              }
            }
          });
    } else {
      advertiseSecondCompletion(parameters.getPosition().getProject(), result);
    }
  }
  private static void suggestNonImportedClasses(
      CompletionParameters parameters,
      CompletionResultSet result,
      @Nullable JavaCompletionSession session) {
    JavaClassNameCompletionContributor.addAllClasses(
        parameters,
        true,
        result.getPrefixMatcher(),
        element -> {
          if (session != null && session.alreadyProcessed(element)) {
            return;
          }
          JavaPsiClassReferenceElement classElement =
              element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
          if (classElement != null) {
            classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
            element =
                JavaClassNameCompletionContributor.highlightIfNeeded(classElement, parameters);
          }

          result.addElement(element);
        });
  }
  private static List<? extends LookupElement> createLookupElements(
      CompletionElement completionElement, PsiJavaReference reference) {
    Object completion = completionElement.getElement();
    assert !(completion instanceof LookupElement);

    if (reference instanceof PsiJavaCodeReferenceElement) {
      if (completion instanceof PsiMethod
          && ((PsiJavaCodeReferenceElement) reference).getParent()
              instanceof PsiImportStaticStatement) {
        return Collections.singletonList(
            JavaLookupElementBuilder.forMethod((PsiMethod) completion, PsiSubstitutor.EMPTY));
      }

      if (completion instanceof PsiClass) {
        return JavaClassNameCompletionContributor.createClassLookupItems(
            (PsiClass) completion,
            JavaClassNameCompletionContributor.AFTER_NEW.accepts(reference),
            JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER,
            Conditions.<PsiClass>alwaysTrue());
      }
    }

    if (reference instanceof PsiMethodReferenceExpression
        && completion instanceof PsiMethod
        && ((PsiMethod) completion).isConstructor()) {
      return Collections.singletonList(
          JavaLookupElementBuilder.forMethod(
              (PsiMethod) completion, "new", PsiSubstitutor.EMPTY, null));
    }

    LookupElement _ret = LookupItemUtil.objectToLookupItem(completion);
    if (_ret instanceof LookupItem) {
      final PsiSubstitutor substitutor = completionElement.getSubstitutor();
      if (substitutor != null) {
        ((LookupItem<?>) _ret).setAttribute(LookupItem.SUBSTITUTOR, substitutor);
      }
    }
    return Collections.singletonList(_ret);
  }
  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();
  }