PsiElement (@NotNull PsiExpression expression, @NotNull String replacementText, List<? extends PsiElement> toDelete) { List<PsiElement> trailingComments = new SmartList<>(); List<PsiElement> comments = grabCommentsBefore(PsiTreeUtil.lastChild(expression)); if (!comments.isEmpty()) { PsiParserFacade parser = PsiParserFacade.getInstance(expression.getProject()); for (PsiElement comment : comments) { PsiElement prev = comment.getPrevSibling(); if (prev instanceof PsiWhiteSpace) { String text = prev.getText(); if (!text.contains("\n")) trailingComments.add(parser.createWhiteSpaceFromText(" ")); else if (text.endsWith("\n")) trailingComments.add(parser.createWhiteSpaceFromText("\n")); // comment at first column else trailingComments.add(parser.createWhiteSpaceFromText("\n ")); // newline followed by space will cause formatter to indent } addIgnored(comment); trailingComments.add(comment.copy()); } if (isEndOfLineComment(trailingComments.get(trailingComments.size() - 1))) { PsiElement next = expression.getNextSibling(); if (next instanceof PsiErrorElement) next = next.getNextSibling(); if (isEndOfLineComment(next) || next instanceof PsiWhiteSpace && !next.getText().contains("\n") && isEndOfLineComment(next.getNextSibling())) { trailingComments.add(parser.createWhiteSpaceFromText("\n ")); } } Collections.reverse(trailingComments); } PsiElement replacement = replace(expression, replacementText); for (PsiElement element : trailingComments) { replacement.getParent().addAfter(element, replacement); } toDelete.forEach(this::delete); PsiElement anchor = replacement; while (anchor.getParent() != null && anchor.getPrevSibling() == null) { anchor = anchor.getParent(); } insertCommentsBefore(anchor); return replacement; }