void (final @NotNull ReplacementInfo info, @NotNull ReplaceOptions options) { final PsiElement elementToReplace = StructuralSearchUtil.getPresentableElement(info.getMatch(0)); if (elementToReplace == null) { return; } final PsiElement elementParent = elementToReplace.getParent(); String replacementToMake = info.getReplacement(); final boolean listContext = isListContext(elementToReplace); if (elementToReplace instanceof PsiAnnotation && !replacementToMake.isEmpty() && !StringUtil.startsWithChar(replacementToMake, '@')) { replacementToMake = "@" + replacementToMake; } final LanguageFileType fileType = myReplaceOptions.getMatchOptions().getFileType(); assert fileType != null; final PsiElement[] replacements = MatcherImplUtil.createTreeFromText( replacementToMake, elementToReplace instanceof PsiMember && !isSymbolReplacement(elementToReplace) ? PatternTreeContext.Class : PatternTreeContext.Block, fileType, myProject); if (elementToReplace instanceof PsiAnnotation && replacements.length == 1) { if (replacements[0] instanceof PsiDeclarationStatement declarationStatement && declarationStatement.getFirstChild() instanceof PsiModifierList modifierList) { copyUnmatchedElements(elementToReplace, declarationStatement, info); for (PsiElement child : modifierList.getChildren()) { elementParent.addBefore(child, elementToReplace); } } elementToReplace.delete(); return; } if (listContext) { if (replacements.length == 1 && replacements[0] instanceof PsiExpressionListStatement statement) { PsiElement[] children = statement.getExpressionList().getChildren(); elementParent.addRangeBefore(children[0], children[children.length - 1], elementToReplace); } else if (replacements.length > 1) { final PsiElement replacement = elementParent.addRangeBefore(replacements[0], replacements[replacements.length - 1], elementToReplace); copyUnmatchedElements(elementToReplace, replacement, info); } else if (replacements.length == 1) { PsiElement replacement = getMatchExpr(replacements[0], elementToReplace); if (elementToReplace instanceof PsiParameter && replacement instanceof PsiLocalVariable) { final PsiVariable variable = (PsiVariable)replacement; final PsiIdentifier identifier = variable.getNameIdentifier(); assert identifier != null; final String text = variable.getText(); // chop off unneeded semicolons & initializers final String parameterText = text.substring(0, identifier.getStartOffsetInParent() + identifier.getTextLength()); replacement = JavaPsiFacade.getElementFactory(variable.getProject()).createParameterFromText(parameterText, variable); } final PsiElement patternElement = patternElements[0]; if (elementToReplace instanceof PsiAnonymousClass anonymousClass && patternElement instanceof PsiClass && !(patternElement instanceof PsiAnonymousClass) && replacement instanceof PsiClass replacementClass && !(replacement instanceof PsiAnonymousClass)) { final PsiExpressionList argumentList = anonymousClass.getArgumentList(); final PsiElement brace = replacementClass.getLBrace(); assert brace != null; String typeParametersText = ""; if (!replacementClass.hasTypeParameters()) { if (!((PsiClass)patternElement).hasTypeParameters()) { final PsiReferenceParameterList parameterList = anonymousClass.getBaseClassReference().getParameterList(); if (parameterList != null) { typeParametersText = parameterList.getText(); } } } else { final PsiTypeParameterList parameterList = replacementClass.getTypeParameterList(); if (parameterList != null) { typeParametersText = parameterList.getText(); } } final PsiElementFactory factory = JavaPsiFacade.getElementFactory(elementToReplace.getProject()); final PsiNewExpression newExpression = (PsiNewExpression) factory.createExpressionFromText("new " + replacementClass.getName() + typeParametersText + (argumentList == null ? "()" : argumentList.getText()) + replacementClass.getText().substring(brace.getStartOffsetInParent()), elementToReplace); replacement = newExpression.getAnonymousClass(); assert replacement != null; } copyUnmatchedElements(elementToReplace, replacement, info); replacement = handleSymbolReplacement(replacement, elementToReplace); if (replacement instanceof PsiTryStatement tryStatement) { final List<? extends PsiElement> unmatchedElements = elementToReplace.getUserData(GlobalMatchingVisitor.UNMATCHED_ELEMENTS_KEY); if (unmatchedElements != null && !unmatchedElements.isEmpty()) { final PsiElement firstElement = unmatchedElements.get(0); if (firstElement instanceof PsiResourceList) addElementAfterAnchor(tryStatement, firstElement, tryStatement.getFirstChild()); outer: for (final PsiElement element : unmatchedElements) { if (element instanceof PsiCatchSection catchSection) { final PsiCatchSection[] catches = tryStatement.getCatchSections(); if (catches.length == 0) { addElementAfterAnchor(tryStatement, element, tryStatement.getTryBlock()); } else { final PsiType newType = catchSection.getCatchType(); for (PsiCatchSection existingCatch : catches) { final PsiType existingType = existingCatch.getCatchType(); if (existingType != null && newType != null) { if (existingType.isAssignableFrom(newType)) { addElementBeforeAnchor(tryStatement, element, existingCatch); continue outer; } } } addElementAfterAnchor(tryStatement, element, catches[catches.length - 1]); } } } final PsiElement lastElement = unmatchedElements.get(unmatchedElements.size() - 1); if (lastElement instanceof PsiCodeBlock) { final PsiElement finallyKeyword = PsiTreeUtil.skipWhitespacesBackward(lastElement); assert finallyKeyword != null; final PsiElement finallyAnchor = tryStatement.getLastChild(); addElementAfterAnchor(tryStatement, lastElement, finallyAnchor); addElementAfterAnchor(tryStatement, finallyKeyword, finallyAnchor); } } } try { final PsiElement inserted = elementParent.addBefore(replacement, elementToReplace); if (replacement instanceof PsiComment && (elementParent instanceof PsiIfStatement || elementParent instanceof PsiLoopStatement)) { elementParent.addAfter(createSemicolon(replacement), inserted); } } catch (IncorrectOperationException e) { elementToReplace.replace(replacement); } } } else if (replacements.length > 0) { PsiElement replacement = ReplacerUtil.copySpacesAndCommentsBefore(elementToReplace, replacements, replacementToMake, elementParent); replacement = getMatchExpr(replacement, elementToReplace); if (replacement instanceof PsiStatement && !(replacement.getLastChild() instanceof PsiJavaToken) && !(replacement.getLastChild() instanceof PsiComment) ) { // assert w/o ; final PsiElement prevLastChildInParent = replacement.getLastChild().getPrevSibling(); if (prevLastChildInParent != null) { elementParent.addRangeBefore(replacement.getFirstChild(), prevLastChildInParent, elementToReplace); } else { elementParent.addBefore(replacement.getFirstChild(), elementToReplace); } elementToReplace.getNode().getTreeParent().removeChild(elementToReplace.getNode()); } else { copyUnmatchedElements(elementToReplace, replacement, info); replacement = handleSymbolReplacement(replacement, elementToReplace); elementToReplace.replace(replacement); } } else { final PsiElement nextSibling = elementToReplace.getNextSibling(); elementToReplace.delete(); if (nextSibling instanceof PsiWhiteSpace && nextSibling.isValid()) { nextSibling.delete(); } } if (listContext) { final int matchSize = info.getMatchesCount(); for (int i = 0; i < matchSize; ++i) { final PsiElement matchElement = info.getMatch(i); final PsiElement element = StructuralSearchUtil.getPresentableElement(matchElement); if (element == null) continue; PsiElement firstToDelete = element; PsiElement lastToDelete = element; PsiElement prevSibling = element.getPrevSibling(); PsiElement nextSibling = element.getNextSibling(); if (prevSibling instanceof PsiWhiteSpace) { firstToDelete = prevSibling; prevSibling = prevSibling.getPrevSibling(); } else if (prevSibling == null && nextSibling instanceof PsiWhiteSpace) { lastToDelete = nextSibling; } if (element instanceof PsiExpression) { final PsiElement parent = element.getParent().getParent(); if ((parent instanceof PsiCall || parent instanceof PsiAnonymousClass) && PsiUtil.isJavaToken(prevSibling, JavaTokenType.COMMA)) { firstToDelete = prevSibling; } } else if (element instanceof PsiParameter && PsiUtil.isJavaToken(prevSibling, JavaTokenType.COMMA)) { firstToDelete = prevSibling; } else if (element instanceof PsiField) { while (PsiUtil.isJavaToken(nextSibling, JavaTokenType.COMMA)) { lastToDelete = PsiTreeUtil.skipWhitespacesForward(nextSibling); nextSibling = PsiTreeUtil.skipWhitespacesForward(lastToDelete); } } element.getParent().deleteChildRange(firstToDelete, lastToDelete); } } }