Rectangle calculatePosition() {
    final JComponent lookupComponent = myLookup.getComponent();
    Dimension dim = lookupComponent.getPreferredSize();
    int lookupStart = myLookup.getLookupStart();
    Editor editor = myLookup.getTopLevelEditor();
    if (lookupStart < 0 || lookupStart > editor.getDocument().getTextLength()) {
      LOG.error(lookupStart + "; offset=" + editor.getCaretModel().getOffset() + "; element=" +
                myLookup.getPsiElement());
    }

    LogicalPosition pos = editor.offsetToLogicalPosition(lookupStart);
    Point location = editor.logicalPositionToXY(pos);
    if (LOG.isDebugEnabled()) {
      LOG.debug("START calculating lookup bounds (above the line = " + myPositionedAbove
                + ") with preferred size " + dim
                + " for editor offset " + lookupStart
                + " positioned at " + location);
    }
    int lineHeight = editor.getLineHeight();
    location.y += lineHeight;
    int textIndent = myLookup.cellRenderer.getTextIndent();
    location.x -= textIndent;
    if (LOG.isDebugEnabled()) {
      LOG.debug("Location after shifting by line height (" + lineHeight + ") and text indent (" + textIndent + "): " + location);
    }
    // extra check for other borders
    final Window window = ComponentUtil.getWindow(lookupComponent);
    if (window != null) {
      final Point point = SwingUtilities.convertPoint(lookupComponent, 0, 0, window);
      location.x -= point.x;
      if (LOG.isDebugEnabled()) {
        LOG.debug("Location after shifting by the window X coordinate (" + point.x + "): " + location);
      }
    }

    JComponent editorComponent = editor.getContentComponent();
    SwingUtilities.convertPointToScreen(location, editorComponent);
    final Rectangle screenRectangle = ScreenUtil.getScreenRectangle(editorComponent);
    if (LOG.isDebugEnabled()) {
      var editorLocation = editorComponent.getLocationOnScreen();
      LOG.debug("Location after converting to screen coordinates (editor component bounds " +
                new Rectangle(editorLocation, editorComponent.getSize()) +
                "): " +
                location);
      LOG.debug("Editor component screen rectangle is: " + screenRectangle);
    }

    int yLocationAboveCaret = location.y - lineHeight - dim.height;
    if (!isPositionedAboveCaret()) {
      int yScreenBottom = screenRectangle.y + screenRectangle.height;
      int yPopupBottom = location.y + dim.height;
      if (yPopupBottom > yScreenBottom && yLocationAboveCaret >= screenRectangle.y
          || myLookup.getPresentation().getPositionStrategy() == LookupPositionStrategy.ONLY_ABOVE) {
        if (LOG.isDebugEnabled()) {
          String reason = myLookup.getPresentation().getPositionStrategy() == LookupPositionStrategy.ONLY_ABOVE
                          ? "LookupPositionStrategy.ONLY_ABOVE is specified"
                          : "the popup won't fit below, but will fit above";
          LOG.debug("Positioning above the line because " + reason);
        }
        myPositionedAbove = true;
      }
      else {
        myPositionedAbove = false; // this assignment is necessary in case myPositionedAbove was to begin with
      }
    }
    if (isPositionedAboveCaret()) {
      location.y = yLocationAboveCaret;
      if (LOG.isDebugEnabled()) {
        LOG.debug("Location after shifting upwards by popup height plus line height to show above the line: " + location);
      }
    }

    if (!screenRectangle.contains(location)) {
      location = ScreenUtil.findNearestPointOnBorder(screenRectangle, location);
      if (LOG.isDebugEnabled()) {
        LOG.debug("Location after moving it to the nearest border because it doesn't fit into the screen: " + location);
      }
    }

    Rectangle candidate = new Rectangle(location, dim);
    ScreenUtil.cropRectangleToFitTheScreen(candidate);
    if (LOG.isDebugEnabled()) {
      LOG.debug("Bounds after cropping to fit into the screen: " + candidate);
    }

    if (isPositionedAboveCaret()) {
      // need to crop as well at bottom if lookup overlaps the current line
      Point caretLocation = editor.logicalPositionToXY(pos);
      SwingUtilities.convertPointToScreen(caretLocation, editorComponent);
      int offset = location.y + dim.height - caretLocation.y;
      if (offset > 0) {
        candidate.height -= offset;
        if (LOG.isDebugEnabled()) {
          LOG.debug("Bounds after cropping to avoid overlapping the current line: " + candidate);
        }
      }
    }

    JRootPane rootPane = editor.getComponent().getRootPane();
    if (rootPane != null) {
      SwingUtilities.convertPointFromScreen(location, rootPane.getLayeredPane());
      if (LOG.isDebugEnabled()) {
        var rootPaneLocation = rootPane.getLocationOnScreen();
        LOG.debug("Location after converting from screen coordinates (root pane bounds " +
                  new Rectangle(rootPaneLocation, rootPane.getSize()) +
                  "): " +
                  location);
      }
    }
    else {
      LOG.error("editor.disposed=" +
                editor.isDisposed() +
                "; lookup.disposed=" +
                myLookup.isLookupDisposed() +
                "; editorShowing=" +
                editorComponent.isShowing());
    }

    myMaximumHeight = candidate.height;
    Rectangle result = new Rectangle(location.x, location.y, dim.width, candidate.height);
    if (LOG.isDebugEnabled()) {
      LOG.debug("END calculating lookup bounds, result: " + result);
    }
    return result;
  }
Rectangle calculatePosition()