@SuppressWarnings("unchecked")
  private static void fixCommonProblems(@NotNull List<? extends ProblemDescriptor> problems,
                                        @NotNull PsiComment comment,
                                        final @NotNull Document document,
                                        @NotNull Project project) {
    List<RangeMarker> toRemove = new ArrayList<>();
    List<ProblemDescriptor> problemsToApply = new ArrayList<>();
    for (ProblemDescriptor problem : problems) {
      PsiElement element = problem.getPsiElement();
      if (element == null) {
        continue;
      }
      if ((!(element instanceof PsiDocToken) || !JavaDocTokenType.DOC_COMMENT_START.equals(((PsiDocToken)element).getTokenType())) &&
          comment.getTextRange().contains(element.getTextRange())) {
        // Unnecessary element like '@return' at the void method's javadoc.
        for (PsiElement e = element; e != null; e = e.getParent()) {
          if (e instanceof PsiDocTag) {
            toRemove.add(document.createRangeMarker(e.getTextRange()));
            break;
          }
        }
      }
      else {
        problemsToApply.add(problem);
      }
    }

    for (ProblemDescriptor problem : problemsToApply) {
      // Problems like 'missing @param'.
      QuickFix[] fixes = problem.getFixes();
      if (fixes != null && fixes.length > 0) {
        fixes[0].applyFix(project, problem);
      }
    }

    PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project);
    if (toRemove.isEmpty()) {
      psiDocumentManager.commitDocument(document);
      return;
    }

    psiDocumentManager.doPostponedOperationsAndUnblockDocument(document);
    CharSequence text = document.getCharsSequence();
    List<TextRange> toDelete = new ArrayList<>();
    for (RangeMarker rangeMarker : toRemove) {
      TextRange range = rangeMarker.getTextRange();
      int startOffset = range.getStartOffset();
      int startLine = document.getLineNumber(startOffset);
      int i = CharArrayUtil.shiftBackward(text, startOffset - 1, " \t");
      if (i >= 0) {
        char c = text.charAt(i);
        if (c == '*') {
          i = CharArrayUtil.shiftBackward(text, i - 1, " \t");
        }
      }
      if (i >= 0 && text.charAt(i) == '\n') {
        startOffset = Math.max(i, document.getLineStartOffset(startLine) - 1);
      }

      int endOffset = range.getEndOffset();
      // Javadoc PSI is awkward, it includes next line text before the next tag. That's why we need to strip it.
      i = CharArrayUtil.shiftBackward(text, endOffset - 1, " \t*");
      if (i > 0 && text.charAt(i) == '\n') {
        endOffset = i;
      }
      toDelete.add(new TextRange(startOffset, endOffset));
      rangeMarker.dispose();
    }

    toDelete.sort(COMPARATOR);
    for (TextRange range : toDelete) {
      document.deleteString(range.getStartOffset(), range.getEndOffset());
    }

    psiDocumentManager.commitDocument(document);
  }
@SuppressWarnings("unchecked")
  private static void fixCommonProblems(@NotNull List<? extends ProblemDescriptor> problems,
                                        @NotNull PsiComment comment,
                                        final @NotNull Document document,
                                        @NotNull Project project)