void (@NotNull Project project, @NotNull Editor editor, @NotNull FindModel aModel, int caretOffset, boolean toPrompt, ReplaceDelegate delegate) { FindManager findManager = FindManager.getInstance(project); final FindModel model = aModel.clone(); int occurrences = 0; List<Pair<TextRange, String>> rangesToChange = new ArrayList<>(); boolean replaced = false; boolean reallyReplaced = false; int offset = caretOffset; Document document = editor.getDocument(); while (offset >= 0 && offset < document.getTextLength()) { caretOffset = offset; FindResult result = doSearch(project, editor, offset, !replaced, model, toPrompt); if (result == null) { break; } int startResultOffset = result.getStartOffset(); model.setFromCursor(true); int startOffset = result.getStartOffset(); int endOffset = result.getEndOffset(); String foundString = document.getCharsSequence().subSequence(startOffset, endOffset).toString(); String toReplace; try { toReplace = findManager.getStringToReplace(foundString, model, startOffset, document.getCharsSequence()); } catch (FindManager.MalformedReplacementStringException e) { if (!ApplicationManager.getApplication().isUnitTestMode()) { Messages.showErrorDialog(project, e.getMessage(), FindBundle.message("find.replace.invalid.replacement.string.title")); } break; } if (toPrompt) { int promptResult = findManager.showPromptDialog(model, FindBundle.message("find.replace.dialog.title")); if (promptResult == FindManager.PromptResult.SKIP) { offset = model.isForward() ? result.getEndOffset() : startResultOffset; continue; } if (promptResult == FindManager.PromptResult.CANCEL) { break; } if (promptResult == FindManager.PromptResult.ALL) { toPrompt = false; } } int newOffset; if (delegate == null || delegate.shouldReplace(result, toReplace)) { if (toPrompt) { //[SCR 7258] if (!reallyReplaced) { editor.getCaretModel().moveToOffset(0); reallyReplaced = true; } } TextRange textRange = doReplace(project, document, model, result, toReplace, toPrompt, rangesToChange); replaced = true; newOffset = model.isForward() ? textRange.getEndOffset() : textRange.getStartOffset(); if (textRange.isEmpty()) ++newOffset; occurrences++; } else { newOffset = model.isForward() ? result.getEndOffset() : result.getStartOffset(); } if (newOffset == offset) { newOffset += model.isForward() ? 1 : -1; } offset = newOffset; } if (replaced) { if (toPrompt) { if (caretOffset > document.getTextLength()) { caretOffset = document.getTextLength(); } editor.getCaretModel().moveToOffset(caretOffset); } else { CharSequence text = document.getCharsSequence(); final StringBuilder newText = new StringBuilder(document.getTextLength()); rangesToChange.sort(Comparator.comparingInt(o -> o.getFirst().getStartOffset())); int offsetBefore = 0; for (Pair<TextRange, String> pair : rangesToChange) { TextRange range = pair.getFirst(); String replace = pair.getSecond(); newText.append(text, offsetBefore, range.getStartOffset()); //before change if (delegate == null || delegate.shouldReplace(range, replace)) { newText.append(replace); } else { newText.append(text.subSequence(range.getStartOffset(), range.getEndOffset())); } offsetBefore = range.getEndOffset(); if (offsetBefore < caretOffset) { caretOffset += replace.length() - range.getLength(); } } newText.append(text, offsetBefore, text.length()); //tail if (caretOffset > newText.length()) { caretOffset = newText.length(); } final int finalCaretOffset = caretOffset; CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> { document.setText(newText); editor.getCaretModel().moveToOffset(finalCaretOffset); if (model.isGlobal()) { editor.getSelectionModel().removeSelection(); } }), null, null); } } ReplaceInProjectManager.reportNumberReplacedOccurrences(project, occurrences); }