@Nullable
  public static CommentInjectionData findCommentInjectionData(@NotNull PsiElement context, boolean treeElementsIncludeComment, @Nullable Ref<? super PsiElement> causeRef) {
    PsiElement target = CompletionUtil.getOriginalOrSelf(context);
    Pair.NonNull<PsiComment, CommentInjectionData> pair = findClosestCommentInjectionData(target);
    if (pair == null) return null;
    PsiComment psiComment = pair.first;
    CommentInjectionData injectionData = pair.second;
    TextRange r0 = psiComment.getTextRange();

    // calculate topmost siblings & heights
    PsiElement commonParent = PsiTreeUtil.findCommonParent(psiComment, target);
    if (commonParent == null) return null;
    PsiElement topmostElement = target;
    PsiElement parent = target;
    while (parent != null && (treeElementsIncludeComment ? parent : parent.getParent()) != commonParent) {
      topmostElement = parent;
      parent = parent.getParent();
    }

    // make sure comment is close enough and ...
    int off1 = r0.getEndOffset();
    int off2 = topmostElement.getTextRange().getStartOffset();
    if (off2 - off1 > 120) {
      return null;
    }
    if (off2 - off1 > 2) {
      // ... there's no non-empty valid host in between comment and topmostElement
      Supplier<PsiElement> producer = prevWalker(topmostElement, commonParent);
      PsiElement e;
      while ( (e = producer.get()) != null && e != psiComment) {
        if (e instanceof PsiLanguageInjectionHost &&
            ((PsiLanguageInjectionHost)e).isValidHost() &&
            !StringUtil.isEmptyOrSpaces(e.getText())) {
          return null;
        }
      }
    }
    if (causeRef != null) {
      causeRef.set(psiComment);
    }
    return injectionData;
  }
@Nullable
  public static CommentInjectionData findCommentInjectionData(@NotNull PsiElement context, boolean treeElementsIncludeComment, @Nullable Ref<? super PsiElement> causeRef)