Community
Participate
Working Groups
Build Identifier: 20110301-1815 If we disable the "Rename in editor without dialog" option in the Java preferences page, then undo doesn't work properly for renames triggered from inside the editor. Reproducible: Always Steps to Reproduce: 1. Disable the "Rename in editor without dialog" option 2. Create an empty Java project. 3. Add a simple class. This one will do public class Bar { Bar foo; } 4. Select the name of class in the Java editor 5. Alt-Shift-R 6. Type "Foo" for the new name and click "Finish" 7. Click the edit menu and find "undo" item Observed: - It says "Undo typing" instead of "Undo rename..." - Performing the undo marks the file as changed, but doesn't actually make any changes. - Trying to save the "changed" file produces an error java.lang.IllegalArgumentException: Illegal value: -1 at org.eclipse.core.internal.resources.Resource.revertModificationStamp(Resource.java:1702) at org.eclipse.core.internal.filebuffers.ResourceTextFileBuffer.commitFileBufferContent(ResourceTextFileBuffer.java:396) at org.eclipse.core.internal.filebuffers.ResourceFileBuffer.commit(ResourceFileBuffer.java:325) at org.eclipse.jdt.internal.ui.javaeditor.DocumentAdapter.save(DocumentAdapter.java:472) at org.eclipse.jdt.internal.core.CommitWorkingCopyOperation.executeOperation(CommitWorkingCopyOperation.java:123) at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:728) at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1975) at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:793) at org.eclipse.jdt.internal.core.CompilationUnit.commitWorkingCopy(CompilationUnit.java:392) at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider.commitWorkingCopy(CompilationUnitDocumentProvider.java:1361) at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider$4.execute(CompilationUnitDocumentProvider.java:1432) at org.eclipse.ui.editors.text.TextFileDocumentProvider$DocumentProviderOperation.run(TextFileDocumentProvider.java:132) at org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation.execute(WorkspaceModifyDelegatingOperation.java:69) at org.eclipse.ui.actions.WorkspaceModifyOperation$1.run(WorkspaceModifyOperation.java:106) at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1975) at org.eclipse.ui.actions.WorkspaceModifyOperation.run(WorkspaceModifyOperation.java:118) at org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner.run(WorkspaceOperationRunner.java:75) at org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner.run(WorkspaceOperationRunner.java:65) at org.eclipse.ui.editors.text.TextFileDocumentProvider.executeOperation(TextFileDocumentProvider.java:456) at org.eclipse.ui.editors.text.TextFileDocumentProvider.saveDocument(TextFileDocumentProvider.java:772) at org.eclipse.ui.texteditor.AbstractTextEditor.performSave(AbstractTextEditor.java:4879) at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor.performSave(CompilationUnitEditor.java:1230) at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor.doSave(CompilationUnitEditor.java:1283) at org.eclipse.ui.texteditor.AbstractTextEditor$TextEditorSavable.doSave(AbstractTextEditor.java:7003) at org.eclipse.ui.Saveable.doSave(Saveable.java:214) at org.eclipse.ui.internal.SaveableHelper.doSaveModel(SaveableHelper.java:349) at org.eclipse.ui.internal.SaveableHelper$3.run(SaveableHelper.java:195) at org.eclipse.ui.internal.SaveableHelper$5.run(SaveableHelper.java:277) at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464) at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372) at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:759) at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:756) at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2606) at org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOperation(SaveableHelper.java:285) at org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOperation(SaveableHelper.java:264) at org.eclipse.ui.internal.SaveableHelper.saveModels(SaveableHelper.java:207) at org.eclipse.ui.internal.SaveableHelper.savePart(SaveableHelper.java:144) at org.eclipse.ui.internal.EditorManager.savePart(EditorManager.java:1369) at org.eclipse.ui.internal.WorkbenchPage.savePart(WorkbenchPage.java:3334) at org.eclipse.ui.internal.WorkbenchPage.saveEditor(WorkbenchPage.java:3347) at org.eclipse.ui.internal.SaveAction.run(SaveAction.java:76) at org.eclipse.jface.action.Action.runWithEvent(Action.java:498) at org.eclipse.ui.commands.ActionHandler.execute(ActionHandler.java:185) at org.eclipse.ui.internal.handlers.LegacyHandlerWrapper.execute(LegacyHandlerWrapper.java:109) at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476) at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508) at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand(WorkbenchKeyboard.java:468) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:786) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:885) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings(WorkbenchKeyboard.java:567) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$3(WorkbenchKeyboard.java:508) at org.eclipse.ui.internal.keys.WorkbenchKeyboard$KeyDownFilter.handleEvent(WorkbenchKeyboard.java:123) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1524) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1257) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1282) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1267) at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1294) at org.eclipse.swt.widgets.Widget.gtk_key_press_event(Widget.java:730) at org.eclipse.swt.widgets.Control.gtk_key_press_event(Control.java:2841) at org.eclipse.swt.widgets.Composite.gtk_key_press_event(Composite.java:734) at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:1743) at org.eclipse.swt.widgets.Control.windowProc(Control.java:4796) at org.eclipse.swt.widgets.Display.windowProc(Display.java:4360) at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method) at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(OS.java:8189) at org.eclipse.swt.widgets.Display.eventProc(Display.java:1238) at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method) at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:2237) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3159) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2640) at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604) at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2438) at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:671) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:664) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:620) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:575) at org.eclipse.equinox.launcher.Main.run(Main.java:1408)
I've also been able to trigger (what I think is) the same bug by triggering the refactoring wizard from the package explorer. How to reproduce. First follow the same steps as described in the original bug report to create a simple test project. Steps 1..4 as in orginal report 5. click the class in the package explorer and use "Refactor >> Rename" menu 6. type a new name and click finish. Now... if you were to trigger the undo immediately from the menu it would work... However, instead do 7. Click in the editor that has the class to make it get the focus 8. Now open the "Edit >> Undo" method from menu bar. Observed: Same as in original bug report: - it says "undo typing" (not undo rename) - undoing marks file as dirty but makes no aparant changes - trying to save the file causes an error "invalid argument -1"
BTW: it is important to note that given the second way to trigger the bug, it is probably a more significant problem, since the second method of triggering the bug is possible with "Rename in editor without dialog" on its default setting.
I think the "weird" edit that causes trouble is the one created in org.eclipse.text.undo.DocumentUndoManager At around line 1279 in method transferUndoHistory Seems to have something to do with copying undo history for a moving file.
Also broken in 3.5.2 and in HEAD. To reproduce with the option enabled, you can also press Alt+Shift+R twice in the editor. It's not that horrible when the type is inside a package. Then you also have the wrong "Undo Typing" in the editor, but at least the refactoring undo works in the Package Explorer.
I quickly compared the "Rename in Editor" and "Rename in Package Explorer / via dialog" scenarios, and the difference seems to be that in the former case, in DefaultOperationHistory#add(IUndoableOperation) there's already an openComposite operation available, whereas in the latter case, the editor has not been touched and no batch operation is open to which the refactoring operations could be added.
*** Bug 301746 has been marked as a duplicate of this bug. ***
This also happens with Move Refactoring, or any ProcessorBasedRefactoring which moves a java file.
If we can keep an "openComposite operation" in DefaultOperationHistory#add(IUndoableOperation) long enough things work.. For instance I tried introducing a delay in UndoManager2.changePerformed(Change, boolean) before closing the operation, and things work smoothly. Of course, we need a proper way to get the sequence of events right :-) ------------------------------------------------------------------------- public void changePerformed(Change change, boolean successful) { if (fIsOpen && fActiveOperation != null) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } fOperationHistory.closeOperation(successful, false, IOperationHistory.EXECUTE); fIsOpen= false; } } -------------------------------------------------------------------------
If you move a java file via a quick assist e.g. using "Move 'A.java' to package 'p'" quick assist then things also work correctly as everything happens in the 'main' thread, and the sequence of events is (somehow) right. However, with Rename refactoring via dialog there are two threads involved, see PerformChangeOperation.executeChange(...).
The issue is with the sequence of events in the threads of refactoring undo manager (UndoManager2) and DocumentUndoManager. We need to wait inside UndoManager2.changePerformed(Change, boolean) before closing the composite operation i.e. we want to replace the timed sleep in comment #8 with some valid condition. We could try the following approaches: - Listening to operation history events: Before closing the composite operation in refactoring undo manager, we need to know if text editor has finished working or more specifically if DocumentUndoManager has added the UndoableTextChange edit to the operation. If the operation is added to an open operation, no event notification is done by history. We get ADDED notification only if the operation is added separately. Hence, we will not get the ADDED notification from history when editor adds it to the open operation. DONE is sent after closing or executing, but we need to wait before closing the operation. - Undo contexts: by checking the validity of undo contexts. Some undo context will probably be deleted because the undo manager gets disposed and recreated on file move, so we might have to add some new API where we can check whether the context is still valid or not. In changePerformed(..) of refactoring undo manager, fActiveOperation (which is the open operation in history also) contains only 1 undo context (i.e. RefactoringUndoContext) initially. We don't have access to the old/new document undo manager's ObjectUndoContext from the refactoring undo manager to check if it is valid or not, until the new document undo manager has added the new operation to history.
*** Bug 417005 has been marked as a duplicate of this bug. ***
*** Bug 473920 has been marked as a duplicate of this bug. ***
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug. If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie.