@Override
  public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
    boolean needToAddNewline = false;
    if (first == last && first.getElementType() == DOC_TAG) {
      if (anchor == null) {
        anchor = getLastChildNode(); // this is a '*/'
        final ASTNode prevBeforeWS =
            TreeUtil.skipElementsBack(anchor.getTreePrev(), ElementType.JAVA_WHITESPACE_BIT_SET);
        if (prevBeforeWS != null) {
          anchor = prevBeforeWS;
          before = Boolean.FALSE;
        } else {
          before = Boolean.TRUE;
        }
        needToAddNewline = true;
      }
      if (anchor.getElementType() != DOC_TAG) {
        final CharTable charTable = SharedImplUtil.findCharTableByTree(this);
        final TreeElement newLine =
            Factory.createSingleLeafElement(DOC_COMMENT_DATA, "\n", 0, 1, charTable, getManager());
        final TreeElement leadingAsterisk =
            Factory.createSingleLeafElement(
                DOC_COMMENT_LEADING_ASTERISKS, "*", 0, 1, charTable, getManager());
        final TreeElement commentData =
            Factory.createSingleLeafElement(DOC_COMMENT_DATA, " ", 0, 1, charTable, getManager());
        final TreeElement indentWS =
            Factory.createSingleLeafElement(DOC_COMMENT_DATA, " ", 0, 1, charTable, getManager());
        newLine.getTreeParent().addChild(indentWS);
        newLine.getTreeParent().addChild(leadingAsterisk);
        newLine.getTreeParent().addChild(commentData);
        super.addInternal(newLine, commentData, anchor, Boolean.FALSE);

        anchor = commentData;
        before = Boolean.FALSE;
      } else {
        needToAddNewline = true;
      }
    }
    if (before) anchor.getTreeParent().addChildren(first, last.getTreeNext(), anchor);
    else anchor.getTreeParent().addChildren(first, last.getTreeNext(), anchor.getTreeNext());

    if (needToAddNewline) {
      if (first.getTreePrev() != null && first.getTreePrev().getElementType() == DOC_TAG) {
        addNewLineToTag((CompositeElement) first.getTreePrev(), getProject());
      }
      if (first.getTreeNext() != null && first.getTreeNext().getElementType() == DOC_TAG) {
        addNewLineToTag((CompositeElement) first, getProject());
      } else {
        removeEndingAsterisksFromTag((CompositeElement) first);
      }
    }
    return first;
  }
 private static void removeEndingAsterisksFromTag(CompositeElement tag) {
   ASTNode current = tag.getLastChildNode();
   while (current != null && current.getElementType() == DOC_COMMENT_DATA) {
     current = current.getTreePrev();
   }
   if (current != null && current.getElementType() == DOC_COMMENT_LEADING_ASTERISKS) {
     final ASTNode prevWhiteSpace =
         TreeUtil.skipElementsBack(current.getTreePrev(), ElementType.JAVA_WHITESPACE_BIT_SET);
     ASTNode toBeDeleted = prevWhiteSpace.getTreeNext();
     while (toBeDeleted != null) {
       ASTNode next = toBeDeleted.getTreeNext();
       tag.deleteChildInternal(toBeDeleted);
       toBeDeleted = next;
     }
   }
 }