public static <T extends PsiElement> List<T> findElementsFromCaretsAndSelections(
    @NotNull Editor editor, @NotNull PsiFile file, @Nullable Class<?> stopAt, @NotNull Predicate<? super PsiElement> accept) {
    List<PsiElement> elements = new SmartList<>();
    for (Caret caret : editor.getCaretModel().getAllCarets()) {
      TextRange selectionRange = caret.getSelectionRange();
      PsiElement start = file.findElementAt(selectionRange.getStartOffset());
      if (start == null) continue;
      PsiElement end = file.findElementAt(selectionRange.getEndOffset());
      if (end == null) continue;

      PsiElement element = PsiTreeUtil.findCommonParent(start, end);
      if (element == null) continue;

      int size = elements.size();
      // first, go down into the psi tree
      PsiTreeUtil.processElements(element, e -> {
        if (accept.test(e)) {
          TextRange range = e.getTextRange();
          if (selectionRange.intersects(range)) {
            elements.add(e);
          }
        }
        return true;
      });
      // we have found something, continue with the next caret
      if (size < elements.size()) continue;

      // second, climb up into the psi tree
      while (element != null && !(element instanceof PsiFile)) {
        if (stopAt != null && stopAt.isInstance(element)) {
          break;
        }

        if (accept.test(element)) {
          elements.add(element);
          break;
        }
        element = element.getParent();
      }
    }
    //noinspection unchecked
    return (List<T>)elements;
  }
public static <T extends PsiElement> List<T> findElementsFromCaretsAndSelections(
    @NotNull Editor editor, @NotNull PsiFile file, @Nullable Class<?> stopAt, @NotNull Predicate<? super PsiElement> accept)