private static void showParameterHint(
      final PsiElement element,
      final Editor editor,
      final Object[] descriptors,
      final Project project,
      @Nullable PsiElement highlighted,
      final int elementStart,
      final ParameterInfoHandler handler,
      final boolean requestFocus) {
    if (ParameterInfoController.isAlreadyShown(editor, elementStart)) return;

    if (editor.isDisposed() || !editor.getComponent().isVisible()) return;
    final ParameterInfoComponent component =
        new ParameterInfoComponent(descriptors, editor, handler, requestFocus);
    component.setParameterOwner(element);
    component.setRequestFocus(requestFocus);
    if (highlighted != null) {
      component.setHighlightedParameter(highlighted);
    }

    component.update(); // to have correct preferred size

    final LightweightHint hint = new LightweightHint(component);
    hint.setSelectingHint(true);
    final HintManagerImpl hintManager = HintManagerImpl.getInstanceImpl();
    final ShowParameterInfoHandler.BestLocationPointProvider provider =
        new MyBestLocationPointProvider(editor);
    final Pair<Point, Short> pos =
        provider.getBestPointPosition(hint, element, elementStart, true, HintManager.UNDER);

    PsiDocumentManager.getInstance(project)
        .performLaterWhenAllCommitted(
            () -> {
              if (editor.isDisposed() || DumbService.isDumb(project)) return;

              final Document document = editor.getDocument();
              if (document.getTextLength() < elementStart) return;

              HintHint hintHint =
                  HintManagerImpl.createHintHint(editor, pos.getFirst(), hint, pos.getSecond());
              hintHint.setExplicitClose(true);
              hintHint.setRequestFocus(requestFocus);

              Editor editorToShow =
                  editor instanceof EditorWindow ? ((EditorWindow) editor).getDelegate() : editor;
              // is case of injection we need to calculate position for EditorWindow
              // also we need to show the hint in the main editor because of intention bulb
              hintManager.showEditorHint(
                  hint,
                  editorToShow,
                  pos.getFirst(),
                  HintManager.HIDE_BY_ESCAPE | HintManager.UPDATE_BY_SCROLLING,
                  0,
                  false,
                  hintHint);
              new ParameterInfoController(project, editor, elementStart, hint, handler, provider);
            });
  }
 @TestOnly
 public static ParameterInfoUIContextEx createContext(
     Object[] objects,
     Editor editor,
     @NotNull ParameterInfoHandler handler,
     int currentParameterIndex,
     @Nullable PsiElement parameterOwner) {
   final ParameterInfoComponent infoComponent =
       new ParameterInfoComponent(objects, editor, handler);
   infoComponent.setCurrentParameterIndex(currentParameterIndex);
   infoComponent.setParameterOwner(parameterOwner);
   return infoComponent.new MyParameterContext();
 }
  public Object[] getSelectedElements() {
    ParameterInfoContext context =
        new ParameterInfoContext() {
          @Override
          public Project getProject() {
            return myProject;
          }

          @Override
          public PsiFile getFile() {
            return myComponent.getParameterOwner().getContainingFile();
          }

          @Override
          public int getOffset() {
            return myEditor.getCaretModel().getOffset();
          }

          @Override
          @NotNull
          public Editor getEditor() {
            return myEditor;
          }
        };

    if (!myHandler.tracksParameterIndex()) {
      return myHandler.getParametersForDocumentation(myComponent.getObjects()[0], context);
    }

    final Object[] objects = myComponent.getObjects();
    int selectedParameterIndex = myComponent.getCurrentParameterIndex();
    List<Object> params = new ArrayList<>(objects.length);

    final Object highlighted = myComponent.getHighlighted();
    for (Object o : objects) {
      if (highlighted != null && !o.equals(highlighted)) continue;
      collectParams(context, selectedParameterIndex, params, o);
    }

    // choose anything when highlighted is not applicable
    if (highlighted != null && params.isEmpty()) {
      for (Object o : objects) {
        collectParams(context, selectedParameterIndex, params, o);
      }
    }

    return ArrayUtil.toObjectArray(params);
  }
  private void updateComponent() {
    if (!myHint.isVisible()) {
      Disposer.dispose(this);
      return;
    }

    final PsiFile file =
        PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument());
    CharSequence chars = myEditor.getDocument().getCharsSequence();
    boolean noDelimiter =
        myHandler instanceof ParameterInfoHandlerWithTabActionSupport
            && ((ParameterInfoHandlerWithTabActionSupport) myHandler)
                    .getActualParameterDelimiterType()
                == TokenType.WHITE_SPACE;
    int caretOffset = myEditor.getCaretModel().getOffset();
    final int offset =
        noDelimiter ? caretOffset : CharArrayUtil.shiftBackward(chars, caretOffset - 1, " \t") + 1;

    final UpdateParameterInfoContext context = new MyUpdateParameterInfoContext(offset, file);
    final Object elementForUpdating = myHandler.findElementForUpdatingParameterInfo(context);

    if (elementForUpdating != null) {
      myHandler.updateParameterInfo(elementForUpdating, context);
      if (!myDisposed
          && myHint.isVisible()
          && !myEditor.isDisposed()
          && myEditor.getComponent().getRootPane() != null) {
        myComponent.update();
        IdeTooltip tooltip = myHint.getCurrentIdeTooltip();
        short position =
            tooltip != null ? toShort(tooltip.getPreferredPosition()) : HintManager.UNDER;
        Pair<Point, Short> pos =
            myProvider.getBestPointPosition(
                myHint,
                elementForUpdating instanceof PsiElement ? (PsiElement) elementForUpdating : null,
                caretOffset,
                true,
                position);
        HintManagerImpl.adjustEditorHintPosition(myHint, myEditor, pos.getFirst(), pos.getSecond());
      }
    } else {
      context.removeHint();
    }
  }