@Override
  public boolean checkAvailable(final @NotNull Editor editor, final @NotNull PsiFile file, final @NotNull MoveInfo info, final boolean down) {
    if (!(file instanceof PsiJavaFile)) {
      return false;
    }

    boolean available = super.checkAvailable(editor, file, info, down);
    if (!available) return false;

    final Pair<PsiElement, PsiElement> psiRange = getElementRange(editor, file, info.toMove);
    if (psiRange == null) return false;

    final PsiMember firstMember = PsiTreeUtil.getParentOfType(psiRange.getFirst(), PsiMember.class, false);
    PsiElement endElement = psiRange.getSecond();
    if (firstMember instanceof PsiEnumConstant && endElement instanceof PsiJavaToken) {
      final IElementType tokenType = ((PsiJavaToken)endElement).getTokenType();
      if (down && tokenType == JavaTokenType.SEMICOLON) {
        return info.prohibitMove();
      }
      if (tokenType == JavaTokenType.COMMA || tokenType == JavaTokenType.SEMICOLON) {
        endElement = PsiTreeUtil.skipWhitespacesBackward(endElement);
      }
    }
    PsiMember lastMember = PsiTreeUtil.getParentOfType(endElement, PsiMember.class, false);
    if (firstMember == null || lastMember == null) return false;
    if (lastMember instanceof PsiEnumConstantInitializer enumConstantInitializer) {
      lastMember = enumConstantInitializer.getEnumConstant();
    }

    LineRange range;
    if (firstMember == lastMember) {
      moveEnumConstant = firstMember instanceof PsiEnumConstant;
      range = memberRange(firstMember, editor, info.toMove);
      if (range == null) return false;
      range.firstElement = range.lastElement = firstMember;
    }
    else {
      final PsiElement parent = PsiTreeUtil.findCommonParent(firstMember, lastMember);
      if (parent == null) return false;

      final Pair<PsiElement, PsiElement> combinedRange = getElementRange(parent, firstMember, lastMember);
      if (combinedRange == null) return false;
      final LineRange lineRange1 = memberRange(combinedRange.getFirst(), editor, info.toMove);
      if (lineRange1 == null) return false;
      final LineRange lineRange2 = memberRange(combinedRange.getSecond(), editor, info.toMove);
      if (lineRange2 == null) return false;
      range = new LineRange(lineRange1.startLine, lineRange2.endLine);
      range.firstElement = combinedRange.getFirst();
      range.lastElement = combinedRange.getSecond();
    }
    Document document = editor.getDocument();

    PsiElement sibling = (down ? range.endLine >= document.getLineCount() : range.startLine == 0) ? null :
                         firstNonWhiteElement(down ? document.getLineStartOffset(range.endLine)
                                                   : document.getLineEndOffset(range.startLine - 1),
                                              file, down);
    if (range.lastElement instanceof PsiEnumConstant) {
      if (sibling instanceof PsiJavaToken token) {
        final IElementType tokenType = token.getTokenType();
        if (down && tokenType == JavaTokenType.SEMICOLON) {
          return info.prohibitMove();
        }
        if (tokenType == JavaTokenType.COMMA) {
          sibling = down ?
                    PsiTreeUtil.skipWhitespacesForward(sibling) :
                    PsiTreeUtil.skipWhitespacesBackward(sibling);
        }
      }
      else if (sibling instanceof PsiField && !(sibling instanceof PsiEnumConstant)) {
        // do not move enum constant past regular field
        return info.prohibitMove();
      }
    }
    final boolean areWeMovingClass = range.firstElement instanceof PsiClass;
    info.toMove = range;

    int neighbourLine = down ? range.endLine : range.startLine - 1;
    if (neighbourLine >= 0 && neighbourLine < document.getLineCount() &&
        CharArrayUtil.containsOnlyWhiteSpaces(document.getImmutableCharSequence().subSequence(document.getLineStartOffset(neighbourLine),
                                                                                              document.getLineEndOffset(neighbourLine))) &&
      emptyLineCanBeDeletedAccordingToCodeStyle(file, document, document.getLineEndOffset(neighbourLine))) {
      info.toMove2 = new LineRange(neighbourLine, neighbourLine + 1);
    }
    else {
      try {
        LineRange intraClassRange = moveInsideOutsideClassPosition(editor, sibling, down, areWeMovingClass);
        if (intraClassRange == null) {
          Couple<LineRange> splitRange = extractCommentRange(sibling);
          info.toMove2 = splitRange.first.startLine == splitRange.first.endLine || !down ? splitRange.second : splitRange.first;
          if (down && sibling.getNextSibling() == null) return false;
        }
        else {
          info.toMove2 = intraClassRange;
        }
        if (down ? info.toMove2.startLine < info.toMove.endLine : info.toMove2.endLine > info.toMove.startLine) {
          return false;
        }
      }
      catch (IllegalMoveException e) {
        info.prohibitMove();
      }
    }
    return true;
  }
@Override
  public boolean checkAvailable(final @NotNull Editor editor, final @NotNull PsiFile file, final @NotNull MoveInfo info, final boolean down)