static boolean isClassNamePossible(CompletionParameters parameters) {
    boolean isSecondCompletion = parameters.getInvocationCount() >= 2;

    PsiElement position = parameters.getPosition();
    if (JavaCompletionData.isInstanceofPlace(position)) return false;

    final PsiElement parent = position.getParent();
    if (!(parent instanceof PsiJavaCodeReferenceElement)) return isSecondCompletion;
    if (((PsiJavaCodeReferenceElement) parent).getQualifier() != null) return isSecondCompletion;

    if (parent instanceof PsiJavaCodeReferenceElementImpl
        && ((PsiJavaCodeReferenceElementImpl) parent).getKind()
            == PsiJavaCodeReferenceElementImpl.PACKAGE_NAME_KIND) {
      return false;
    }

    PsiElement grand = parent.getParent();
    if (grand instanceof PsiSwitchLabelStatement) {
      return false;
    }

    if (psiElement().inside(PsiImportStatement.class).accepts(parent)) {
      return isSecondCompletion;
    }

    if (grand instanceof PsiAnonymousClass) {
      grand = grand.getParent();
    }
    if (grand instanceof PsiNewExpression && ((PsiNewExpression) grand).getQualifier() != null) {
      return false;
    }

    if (JavaCompletionData.isAfterPrimitiveOrArrayType(position)) {
      return false;
    }

    return true;
  }
  @Nullable
  public static ElementFilter getReferenceFilter(PsiElement position) {
    // Completion after extends in interface, type parameter and implements in class
    final PsiClass containingClass =
        PsiTreeUtil.getParentOfType(
            position,
            PsiClass.class,
            false,
            PsiCodeBlock.class,
            PsiMethod.class,
            PsiExpressionList.class,
            PsiVariable.class,
            PsiAnnotation.class);
    if (containingClass != null
        && psiElement()
            .afterLeaf(PsiKeyword.EXTENDS, PsiKeyword.IMPLEMENTS, ",", "&")
            .accepts(position)) {
      return new AndFilter(
          ElementClassFilter.CLASS, new NotFilter(new AssignableFromContextFilter()));
    }

    if (ANNOTATION_NAME.accepts(position)) {
      return new AnnotationTypeFilter();
    }

    if (JavaCompletionData.DECLARATION_START.accepts(position)
        || JavaCompletionData.isInsideParameterList(position)
        || psiElement()
            .inside(psiElement(PsiJavaCodeReferenceElement.class).withParent(psiAnnotation()))
            .accepts(position)) {
      return new OrFilter(ElementClassFilter.CLASS, ElementClassFilter.PACKAGE_FILTER);
    }

    if (psiElement().afterLeaf(PsiKeyword.INSTANCEOF).accepts(position)) {
      return new ElementExtractorFilter(ElementClassFilter.CLASS);
    }

    if (JavaCompletionData.VARIABLE_AFTER_FINAL.accepts(position)) {
      return ElementClassFilter.CLASS;
    }

    if (JavaCompletionData.AFTER_TRY_BLOCK.isAcceptable(position, position)
        || JavaCompletionData.START_SWITCH.accepts(position)
        || JavaCompletionData.isInstanceofPlace(position)
        || JavaCompletionData.isAfterPrimitiveOrArrayType(position)) {
      return null;
    }

    if (JavaCompletionData.START_FOR.accepts(position)) {
      return new OrFilter(ElementClassFilter.CLASS, ElementClassFilter.VARIABLE);
    }

    if (JavaSmartCompletionContributor.AFTER_NEW.accepts(position)) {
      return ElementClassFilter.CLASS;
    }

    if (psiElement().inside(PsiReferenceParameterList.class).accepts(position)) {
      return ElementClassFilter.CLASS;
    }

    if (psiElement().inside(PsiAnnotationParameterList.class).accepts(position)) {
      return createAnnotationFilter(position);
    }

    if (psiElement().afterLeaf("=").inside(PsiVariable.class).accepts(position)) {
      return new OrFilter(
          new ClassFilter(PsiVariable.class, false),
          new ExcludeDeclaredFilter(new ClassFilter(PsiVariable.class)));
    }

    if (SWITCH_LABEL.accepts(position)) {
      return new ClassFilter(PsiField.class) {
        @Override
        public boolean isAcceptable(Object element, PsiElement context) {
          return element instanceof PsiEnumConstant;
        }
      };
    }

    return TrueFilter.INSTANCE;
  }