boolean (boolean drop, boolean disableConfirmation) { if (!myUndoableGroup.isUndoable()) { reportNonUndoable(myUndoableGroup.getAffectedDocuments()); return false; } Set<DocumentReference> clashing = getStacksHolder().collectClashingActions(myUndoableGroup); if (!clashing.isEmpty()) { reportClashingDocuments(clashing); return false; } Map<DocumentReference, Set<ActionChangeRange>> reference2Ranges = decompose(myUndoableGroup, isRedo()); SharedUndoRedoStacksHolder sharedStacksHolder = getSharedStacksHolder(); boolean shouldMove = false; for (Map.Entry<DocumentReference, Set<ActionChangeRange>> entry : reference2Ranges.entrySet()) { MovementAvailability availability = sharedStacksHolder.canMoveToStackTop(entry.getKey(), entry.getValue()); if (availability == MovementAvailability.CANNOT_MOVE) { reportCannotAdjust(Collections.singleton(entry.getKey())); return false; } if (availability == MovementAvailability.CAN_MOVE) { shouldMove = true; } } if (shouldMove) { for (Map.Entry<DocumentReference, Set<ActionChangeRange>> entry : reference2Ranges.entrySet()) { sharedStacksHolder.moveToStackTop(entry.getKey(), entry.getValue()); } } if (!disableConfirmation && myUndoableGroup.shouldAskConfirmation(isRedo()) && !UndoManagerImpl.ourNeverAskUser) { if (!askUser()) return false; } else { if (!shouldMove && restore(getBeforeState(), true)) { setBeforeState(new EditorAndState(myEditor, myEditor.getState(FileEditorStateLevel.UNDO))); return true; } } Collection<VirtualFile> readOnlyFiles = collectReadOnlyAffectedFiles(); if (!readOnlyFiles.isEmpty()) { final Project project = myManager.getProject(); if (project == null) { return false; } final ReadonlyStatusHandler.OperationStatus operationStatus = ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(readOnlyFiles); if (operationStatus.hasReadonlyFiles()) { return false; } } Collection<Document> readOnlyDocuments = collectReadOnlyDocuments(); if (!readOnlyDocuments.isEmpty()) { for (Document document : readOnlyDocuments) { document.fireReadOnlyModificationAttempt(); } return false; } getStacksHolder().removeFromStacks(myUndoableGroup); if (!drop) { getReverseStacksHolder().addToStacks(myUndoableGroup); } SharedUndoRedoStacksHolder sharedReverseStacksHolder = getSharedReverseStacksHolder(); for (Map.Entry<DocumentReference, Set<ActionChangeRange>> entry : reference2Ranges.entrySet()) { DocumentReference reference = entry.getKey(); int rangeCount = entry.getValue().size(); // All related ranges must be on the shared stack's top at this moment // so just pick them one by one and move to reverse stack for (int i = 0; i < rangeCount; i++) { ActionChangeRange changeRange = sharedStacksHolder.removeLastFromStack(reference); ActionChangeRange inverted = changeRange.asInverted(); if (drop) { inverted = inverted.createIndependentCopy(true); } sharedReverseStacksHolder.addToStack(reference, inverted); } } try { performAction(); } catch (UnexpectedUndoException e) { reportException(e); return false; } if (!shouldMove) { restore(getAfterState(), false); } return true; }