Bug 51704 multiple beginCompoundChange in LinkedUIKeyListener
build used: eclipse-SDK-I20040210-win32 I noticed some strange undo/redo behavior in the JDT Editor. I don't have a simple testcase to demonstrate the problem in the JDT Editor. But, I noticed if I set a breakpoint at the implementation of IRewriteTarget.beginCompoundChange, it's called multiple times while I'm in the linked edit mode of Local Rename (one time for each keystroke). But, endCompoundChange was only called one time at the end. I traced and noticed the origin of the multiple beginCompoundChange calls came from the LinkedUIKeyListener#controlUndoBehavior(int, int). LinkedUIKeyListener is an inner class in LinkedUIControl. I understand org.eclipse.jdt.internal.ui.text.link is an internal package. But, I hope the developer may agree that it's a simple problem to fix. That may avoid some hard- to-explain problems in the future because of this unmatching beginCompoundChange/endCompoundChange calls. Here is a copy of LinkedUIKeyListener#controlUndoBehavior(int, int). You may notice that target.beginCompoundChange() is called everytime position is not null. private boolean controlUndoBehavior(int offset, int length) { LinkedPosition position= fEnvironment.findPosition(new LinkedPosition( fCurrentTarget.getViewer().getDocument(), offset, length, LinkedPositionGroup.NO_STOP)); if (position != null) { ITextViewerExtension extension= (ITextViewerExtension) fCurrentTarget.getViewer(); IRewriteTarget target= extension.getRewriteTarget(); if (fPreviousPosition != null && !fPreviousPosition.equals(position)) target.endCompoundChange(); target.beginCompoundChange(); } fPreviousPosition= position; return fPreviousPosition != null; }
org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/link/LinkedUIControl.java
/**
		 * Returns the viewer represented by this target, never <code>null</code>.
		 * 
		 * @return the viewer associated with this target.
		 */
		abstract ITextViewer getViewer();
		/**
		 * Called by the linked UI when this target is being shown. An
		 * implementation could for example ensure that the corresponding
		 * editor is showing.
		 */
		abstract void enter();
		
		/**
		 * The viewer's text widget is initialized when the UI first connects
		 * to the viewer and never changed thereafter. This is to keep the
		 * reference of the widget that we have registered our listeners with,
		 * as the viewer, when it gets disposed, does not remember it, resulting
		 * in a situation where we cannot uninstall the listeners and a memory leak.
		 */
		StyledText fWidget;
		
		
		Shell fShell;
		
		
		LinkedUIKeyListener fKeyListener;