Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKai Maetzel2003-09-17 13:07:41 +0000
committerKai Maetzel2003-09-17 13:07:41 +0000
commit80f6ceec422cb0eb3e0e36e8733341c0ce22752d (patch)
treee00135fa3d3c4c7371f0dd3d24dc97b1e579a968
parentdc529584a725a395734649dd02c88075ec244525 (diff)
downloadeclipse.platform.text-80f6ceec422cb0eb3e0e36e8733341c0ce22752d.tar.gz
eclipse.platform.text-80f6ceec422cb0eb3e0e36e8733341c0ce22752d.tar.xz
eclipse.platform.text-80f6ceec422cb0eb3e0e36e8733341c0ce22752d.zip
updated edits
-rw-r--r--org.eclipse.text/src/org/eclipse/text/edits/Messages.properties4
-rw-r--r--org.eclipse.text/src/org/eclipse/text/edits/MultiTextEdit.java43
-rw-r--r--org.eclipse.text/src/org/eclipse/text/edits/TextEdit.java62
-rw-r--r--org.eclipse.text/src/org/eclipse/text/edits/TextEditProcessor.java112
-rw-r--r--org.eclipse.text/src/org/eclipse/text/edits/UndoEdit.java91
-rw-r--r--org.eclipse.text/src/org/eclipse/text/edits/UndoMemento.java101
-rw-r--r--org.eclipse.text/src/org/eclipse/text/edits/Updater.java38
7 files changed, 248 insertions, 203 deletions
diff --git a/org.eclipse.text/src/org/eclipse/text/edits/Messages.properties b/org.eclipse.text/src/org/eclipse/text/edits/Messages.properties
index 5438395c346..486880f2fbc 100644
--- a/org.eclipse.text/src/org/eclipse/text/edits/Messages.properties
+++ b/org.eclipse.text/src/org/eclipse/text/edits/Messages.properties
@@ -28,4 +28,6 @@ MoveTargetEdit.different_target= Source edit has different target edit.
MoveTargetEdit.wrong_parent=Source edit must not be the parent of the target.
TextEditProcessor.invalid_length=End position lies outside of document range
-UndoMemento.invalid_length=End position lies outside of document range
+
+UndoEdit.no_children=Can\'t add children to an undo edit
+UndoEdit.can_not_be_added=Can\'t add an undo edit to another edit
diff --git a/org.eclipse.text/src/org/eclipse/text/edits/MultiTextEdit.java b/org.eclipse.text/src/org/eclipse/text/edits/MultiTextEdit.java
index bf720bb15b3..f09faf456b7 100644
--- a/org.eclipse.text/src/org/eclipse/text/edits/MultiTextEdit.java
+++ b/org.eclipse.text/src/org/eclipse/text/edits/MultiTextEdit.java
@@ -58,21 +58,14 @@ public class MultiTextEdit extends TextEdit {
fDefined= true;
}
- /**
+ /*
* Copy constructor.
*/
- private MultiTextEdit(MultiTextEdit other) {
+ protected MultiTextEdit(MultiTextEdit other) {
super(other);
}
/* non Java-doc
- * @see TextEdit#perform
- */
- /* package */ final void perform(IDocument document) {
- // do nothing.
- }
-
- /* non Java-doc
* @see TextEdit#copy
*/
protected TextEdit doCopy() {
@@ -80,16 +73,28 @@ public class MultiTextEdit extends TextEdit {
return new MultiTextEdit(this);
}
+ /* non Java-doc
+ * @see TextEdit#perform
+ */
+ /* package */ final void perform(IDocument document) {
+ // do nothing.
+ }
+
/* package */ void aboutToBeAdded(TextEdit parent) {
- if (!fDefined) {
- if (hasChildren()) {
- IRegion region= getCoverage(getChildren());
- internalSetOffset(region.getOffset());
- internalSetLength(region.getLength());
- } else {
- internalSetOffset(parent.getOffset());
- internalSetLength(0);
- }
+ defineRegion(parent.getOffset());
+ }
+
+ /* package */ void defineRegion(int parentOffset) {
+ if (fDefined)
+ return;
+ if (hasChildren()) {
+ IRegion region= getCoverage(getChildren());
+ internalSetOffset(region.getOffset());
+ internalSetLength(region.getLength());
+ } else {
+ internalSetOffset(parentOffset);
+ internalSetLength(0);
}
- }
+ fDefined= true;
+ }
}
diff --git a/org.eclipse.text/src/org/eclipse/text/edits/TextEdit.java b/org.eclipse.text/src/org/eclipse/text/edits/TextEdit.java
index 5cc91929b17..87f899d1e5a 100644
--- a/org.eclipse.text/src/org/eclipse/text/edits/TextEdit.java
+++ b/org.eclipse.text/src/org/eclipse/text/edits/TextEdit.java
@@ -102,6 +102,9 @@ public abstract class TextEdit {
* the point in time when this call is made. Any subsequent changes
* to the edit's offset and length aren't reflected in the returned
* region object.
+ * <p>
+ * Creating a region for a deleted edit will result in an assertion
+ * failure.
*
* @return the manipulated region
*/
@@ -111,7 +114,8 @@ public abstract class TextEdit {
/**
* Returns the offset of the edit. An offset is a 0-based
- * character index.
+ * character index. Returns <code>-1</code> if the edit
+ * is marked as deleted
*
* @return the offset of the edit
*/
@@ -120,7 +124,8 @@ public abstract class TextEdit {
}
/**
- * Returns the length of the edit.
+ * Returns the length of the edit. Returns <code>-1</code>
+ * if the edit is marked as deleted.
*
* @return the length of the edit
*/
@@ -313,6 +318,17 @@ public abstract class TextEdit {
}
/**
+ * Returns the size of the managed children.
+ *
+ * @return the size of the children
+ */
+ public final int getChildrenSize() {
+ if (fChildren == null)
+ return 0;
+ return fChildren.size();
+ }
+
+ /**
* Returns the text range spawned by the given array of text edits.
* The method requires that the given array contains at least one
* edit. If all edits passed are deleted the method returns <code>
@@ -457,26 +473,10 @@ public abstract class TextEdit {
//---- Execution -------------------------------------------------------
/**
- * Returns whether the edit tree can be applied to the
- * given document or not.
- *
- * @return <code>true</code> if the edit tree can be
- * applied to the given document. Otherwise <code>false
- * </code> is returned.
- */
- public boolean canBeApplied(IDocument document) {
- try {
- TextEditProcessor processor= new TextEditProcessor(document);
- processor.add(this);
- return processor.canPerformEdits();
- } finally {
- // unconnect from text edit processor
- fParent= null;
- }
- }
-
- /**
- * Applies the edit tree rooted by this edit to the given document.
+ * Applies the edit tree rooted by this edit to the given document. To check
+ * if the edit tree can be applied to the document either catch <code>
+ * MalformedTreeException</code> or use <code>TextEditProcessor</code> to
+ * execute an edit tree.
*
* @param document the document to be manipulated
* @exception MalformedTreeException is thrown if the tree isn't
@@ -485,14 +485,14 @@ public abstract class TextEdit {
* @exception BadLocationException is thrown if one of the edits
* in the tree can't be executed. The state of the document is
* undefined if this exception is thrown.
+ *
* @see #checkIntegrity()
* @see #perform(IDocument)
+ * @see TextEditProcessor#performEdits()
*/
- public final UndoMemento apply(IDocument document) throws MalformedTreeException, BadLocationException {
+ public final UndoEdit apply(IDocument document) throws MalformedTreeException, BadLocationException {
try {
- TextEditProcessor processor= new TextEditProcessor(document);
- processor.add(this);
- processor.checkIntegrity();
+ TextEditProcessor processor= new TextEditProcessor(document, this);
return processor.performEdits();
} finally {
// unconnect from text edit processor
@@ -529,6 +529,14 @@ public abstract class TextEdit {
/* package */ abstract void perform(IDocument document) throws BadLocationException;
+ /* package */ UndoEdit dispatchPerformEdits(TextEditProcessor processor) throws BadLocationException {
+ return processor.executeDo();
+ }
+
+ /* package */ void dispatchCheckIntegrity(TextEditProcessor processor) throws MalformedTreeException {
+ processor.checkIntegrityDo();
+ }
+
//---- internal state accessors ----------------------------------------------------------
/* package */ void internalSetParent(TextEdit parent) {
@@ -697,7 +705,7 @@ public abstract class TextEdit {
}
}
- private static int getDelta(DocumentEvent event) {
+ /* package */ static int getDelta(DocumentEvent event) {
String text= event.getText();
return (text == null ? -event.getLength() : text.length()) - event.getLength();
}
diff --git a/org.eclipse.text/src/org/eclipse/text/edits/TextEditProcessor.java b/org.eclipse.text/src/org/eclipse/text/edits/TextEditProcessor.java
index c50cb2f9bc6..b6218a7c43d 100644
--- a/org.eclipse.text/src/org/eclipse/text/edits/TextEditProcessor.java
+++ b/org.eclipse.text/src/org/eclipse/text/edits/TextEditProcessor.java
@@ -30,18 +30,29 @@ import org.eclipse.jface.text.IDocument;
public class TextEditProcessor {
private IDocument fDocument;
- private MultiTextEdit fRoot;
+ private TextEdit fRoot;
+
+ private boolean fChecked;
+ private MalformedTreeException fException;
/**
* Constructs a new edit processor for the given
* document.
*
* @param document the document to manipulate
+ * @param root the root of the text edit tree describing
+ * the modifications. By passing a text edit a a text edit
+ * processor the ownership of the edit is transfered to the
+ * text edit processors. Clients must not modify the edit
+ * (e.g adding new children) any longer.
*/
- public TextEditProcessor(IDocument document) {
+ public TextEditProcessor(IDocument document, TextEdit root) {
Assert.isNotNull(document);
+ Assert.isNotNull(root);
fDocument= document;
- fRoot= new MultiTextEdit(0, fDocument.getLength());
+ fRoot= root;
+ if (fRoot instanceof MultiTextEdit)
+ ((MultiTextEdit)fRoot).defineRegion(0);
}
/**
@@ -63,23 +74,6 @@ public class TextEditProcessor {
}
/**
- * Adds an <code>Edit</code> to this edit processor. Adding an edit
- * to an edit processor transfers ownership of the edit to the
- * processor. So after an edit has been added to a processor the
- * creator of the edit <b>must</b> not continue modifying the edit.
- *
- * @param edit the edit to add
- * @exception MalformedTreeException if the text edit can not be
- * added to this edit processor.
- *
- * @see TextEdit#addChild(TextEdit)
- */
- public void add(TextEdit edit) throws MalformedTreeException {
- checkIntegrity(edit, fDocument);
- fRoot.addChild(edit);
- }
-
- /**
* Checks if the processor can execute all its edits.
*
* @return <code>true</code> if the edits can be executed. Return <code>false
@@ -88,7 +82,14 @@ public class TextEditProcessor {
* likely end in a <code>BadLocationException</code>.
*/
public boolean canPerformEdits() {
- return checkBufferLength(fRoot, fDocument.getLength()) == null;
+ try {
+ fRoot.dispatchCheckIntegrity(this);
+ fChecked= true;
+ } catch (MalformedTreeException e) {
+ fException= e;
+ return false;
+ }
+ return true;
}
/**
@@ -102,8 +103,14 @@ public class TextEditProcessor {
* tree can't be executed. The state of the document is undefined if this
* exception is thrown.
*/
- public UndoMemento performEdits() throws MalformedTreeException, BadLocationException {
- return execute();
+ public UndoEdit performEdits() throws MalformedTreeException, BadLocationException {
+ if (!fChecked) {
+ fRoot.dispatchCheckIntegrity(this);
+ } else {
+ if (fException != null)
+ throw fException;
+ }
+ return fRoot.dispatchPerformEdits(this);
}
/* non Java-doc
@@ -113,49 +120,41 @@ public class TextEditProcessor {
return true;
}
- /* protected */ void checkIntegrity() throws MalformedTreeException {
- TextEdit failure= checkBufferLength(fRoot, fDocument.getLength());
- if (failure != null) {
- throw new MalformedTreeException(failure.getParent(), failure, TextEditMessages.getString("TextEditProcessor.invalid_length")); //$NON-NLS-1$
- }
- }
+ //---- checking --------------------------------------------------------------------
- //---- Helper methods ------------------------------------------------------------------------
-
- private static TextEdit checkBufferLength(TextEdit root, int bufferLength) {
- if (root.getExclusiveEnd() > bufferLength)
- return root;
- List children= root.internalGetChildren();
- if (children != null) {
- for (Iterator iter= children.iterator(); iter.hasNext();) {
- TextEdit edit= (TextEdit)iter.next();
- TextEdit failure= null;
- if ((failure= checkBufferLength(edit, bufferLength)) != null)
- return failure;
- }
- }
- return null;
+ /* package */ void checkIntegrityDo() throws MalformedTreeException {
+ checkIntegrity(fRoot);
+ if (fRoot.getExclusiveEnd() > fDocument.getLength())
+ throw new MalformedTreeException(null, fRoot, TextEditMessages.getString("TextEditProcessor.invalid_length")); //$NON-NLS-1$
}
- private static void checkIntegrity(TextEdit root, IDocument document) {
+ private static void checkIntegrity(TextEdit root) throws MalformedTreeException {
root.checkIntegrity();
List children= root.internalGetChildren();
if (children != null) {
for (Iterator iter= children.iterator(); iter.hasNext();) {
TextEdit edit= (TextEdit)iter.next();
- checkIntegrity(edit, document);
+ checkIntegrity(edit);
}
}
}
- private UndoMemento execute() throws BadLocationException {
+ /* package */ void checkIntegrityUndo() {
+ if (fRoot.getExclusiveEnd() > fDocument.getLength())
+ throw new MalformedTreeException(null, fRoot, TextEditMessages.getString("TextEditProcessor.invalid_length")); //$NON-NLS-1$
+ }
+
+ //---- execution --------------------------------------------------------------------
+
+ /* package */ UndoEdit executeDo() throws BadLocationException {
Updater.DoUpdater updater= null;
try {
- updater= Updater.createDoUpdater();
+ updater= Updater.createDoUpdater(fRoot);
fDocument.addDocumentListener(updater);
updater.push(new TextEdit[] { fRoot });
updater.setIndex(0);
execute(fRoot, updater);
+ updater.storeRegion();
return updater.undo;
} finally {
if (updater != null)
@@ -178,4 +177,21 @@ public class TextEditProcessor {
edit.perform(fDocument);
}
}
+
+ /* package */ UndoEdit executeUndo() throws BadLocationException {
+ Updater updater= null;
+ try {
+ updater= Updater.createUndoUpdater(fRoot);
+ fDocument.addDocumentListener(updater);
+ TextEdit[] edits= fRoot.getChildren();
+ for (int i= edits.length - 1; i >= 0; i--) {
+ edits[i].perform(fDocument);
+ }
+ updater.storeRegion();
+ return updater.undo;
+ } finally {
+ if (updater != null)
+ fDocument.removeDocumentListener(updater);
+ }
+ }
}
diff --git a/org.eclipse.text/src/org/eclipse/text/edits/UndoEdit.java b/org.eclipse.text/src/org/eclipse/text/edits/UndoEdit.java
new file mode 100644
index 00000000000..ee5f0575648
--- /dev/null
+++ b/org.eclipse.text/src/org/eclipse/text/edits/UndoEdit.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.text.edits;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * This class encapsulates the reverse changes of an executed text
+ * edit tree. To apply an undo memento to a document use method
+ * <code>apply(IDocument)</code>.
+ * <p>
+ * Clients can add additional children to an undo edit nor can they
+ * add an undo edit as a child to another edit. Doing so results in
+ * both cases in a <code>MalformedTreeException<code>.
+ *
+ * @since 3.0
+ */
+public final class UndoEdit extends TextEdit {
+
+ /* package */ UndoEdit() {
+ super(0, Integer.MAX_VALUE);
+ }
+
+ private UndoEdit(UndoEdit other) {
+ super(other);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.text.edits.TextEdit#internalAdd(org.eclipse.text.edits.TextEdit)
+ */
+ /* package */ void internalAdd(TextEdit child) throws MalformedTreeException {
+ throw new MalformedTreeException(null, this, TextEditMessages.getString("UndoEdit.no_children")); //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.text.edits.MultiTextEdit#aboutToBeAdded(org.eclipse.text.edits.TextEdit)
+ */
+ /* package */ void aboutToBeAdded(TextEdit parent) {
+ throw new MalformedTreeException(parent, this, TextEditMessages.getString("UndoEdit.can_not_be_added")); //$NON-NLS-1$
+ }
+
+ /* package */ UndoEdit dispatchPerformEdits(TextEditProcessor processor) throws BadLocationException {
+ return processor.executeUndo();
+ }
+
+ /* package */ void dispatchCheckIntegrity(TextEditProcessor processor) throws MalformedTreeException {
+ processor.checkIntegrityUndo();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.text.edits.TextEdit#doCopy()
+ */
+ protected TextEdit doCopy() {
+ return new UndoEdit(this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.text.edits.TextEdit#perform(org.eclipse.jface.text.IDocument)
+ */
+ void perform(IDocument document) throws BadLocationException {
+ // do nothing. Only the children modify the
+ // document
+ }
+
+ /* package */ void add(ReplaceEdit edit) {
+ List children= internalGetChildren();
+ if (children == null) {
+ children= new ArrayList(2);
+ internalSetChildren(children);
+ }
+ children.add(edit);
+ }
+
+ /* package */ void defineRegion(int offset, int length) {
+ internalSetOffset(offset);
+ internalSetLength(length);
+ }
+}
+
diff --git a/org.eclipse.text/src/org/eclipse/text/edits/UndoMemento.java b/org.eclipse.text/src/org/eclipse/text/edits/UndoMemento.java
deleted file mode 100644
index d9de7b6db5e..00000000000
--- a/org.eclipse.text/src/org/eclipse/text/edits/UndoMemento.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.text.edits;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.jface.text.Assert;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-
-/**
- * This class encapsulates the reverse changes of an executed text
- * edit tree. To apply an undo memento to a document use method
- * <code>apply(IDocument)</code>.
- */
-public final class UndoMemento {
-
- private List fEdits;
-
- /**
- * Returns whether this undo memento can be applied to the
- * given document or not.
- *
- * @return <code>true</code> if the undo memento can be
- * applied to the given document. Otherwise <code>false
- * </code> is returned.
- */
- public boolean canBeApplied(IDocument document) {
- Assert.isNotNull(document);
- return checkBufferLength(document.getLength()) != null;
- }
-
- /**
- * Applies this undo memento to the given document.
- *
- * @param document the document to be manipulated
- *
- * @exception MalformedTreeException is thrown if the undo isn't
- * in a valid state. This exception is thrown before any edit
- * is executed. So the document is still in its original state.
- * @exception BadLocationException is thrown if one of the edits
- * of the undo can't be executed. The state of the document is
- * undefined if this exception is thrown.
- *
- * @see TextEdit#apply(IDocument)
- */
- public UndoMemento apply(IDocument document) throws MalformedTreeException, BadLocationException {
- Assert.isNotNull(document);
- TextEdit failure= checkBufferLength(document.getLength());
- if (failure != null)
- throw new MalformedTreeException(failure.getParent(), failure, TextEditMessages.getString("UndoMemento.invalid_length")); //$NON-NLS-1$
- return perform(document);
- }
-
- /* package */ UndoMemento() {
- fEdits= new ArrayList(5);
- }
-
- /* package */ void add(ReplaceEdit edit) {
- fEdits.add(edit);
- }
-
- private TextEdit checkBufferLength(int bufferLength) {
- for (int i= fEdits.size() - 1; i >= 0; i--) {
- ReplaceEdit edit= (ReplaceEdit)fEdits.get(i);
- if (edit.getExclusiveEnd() > bufferLength)
- return edit;
- bufferLength+= getDelta(edit);
- }
- return null;
- }
-
- private UndoMemento perform(IDocument document) throws BadLocationException {
- Updater updater= null;
- try {
- updater= Updater.createUndoUpdater();
- document.addDocumentListener(updater);
- for (int i= fEdits.size() - 1; i >= 0; i--) {
- ((TextEdit)fEdits.get(i)).perform(document);
- }
- return updater.undo;
- } finally {
- if (updater != null)
- document.removeDocumentListener(updater);
- }
- }
-
- private int getDelta(ReplaceEdit edit) {
- return edit.getText().length() - edit.getLength();
- }
-}
-
diff --git a/org.eclipse.text/src/org/eclipse/text/edits/Updater.java b/org.eclipse.text/src/org/eclipse/text/edits/Updater.java
index 2ad0ed80a3b..45887593d86 100644
--- a/org.eclipse.text/src/org/eclipse/text/edits/Updater.java
+++ b/org.eclipse.text/src/org/eclipse/text/edits/Updater.java
@@ -16,22 +16,26 @@ import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocumentListener;
-/* package */ class Updater implements IDocumentListener {
+/* package */ abstract class Updater implements IDocumentListener {
- protected UndoMemento undo= new UndoMemento();
+ protected UndoEdit undo= new UndoEdit();
- public static Updater createUndoUpdater() {
- return new Updater();
+ public static Updater createUndoUpdater(TextEdit root) {
+ return new UndoUpdater(root);
}
- public static DoUpdater createDoUpdater() {
- return new DoUpdater();
+ public static DoUpdater createDoUpdater(TextEdit root) {
+ return new DoUpdater(root);
}
public static class DoUpdater extends Updater {
+ private TextEdit fRoot;
private TextEdit fActiveEdit;
private TreeIterationInfo fIterationInfo= new TreeIterationInfo();
+ public DoUpdater(TextEdit root) {
+ fRoot= root;
+ }
public void push(TextEdit[] edits) {
fIterationInfo.push(edits);
}
@@ -47,6 +51,24 @@ import org.eclipse.jface.text.IDocumentListener;
public void documentChanged(DocumentEvent event) {
fActiveEdit.update(event, fIterationInfo);
}
+ public void storeRegion() {
+ undo.defineRegion(fRoot.getOffset(), fRoot.getLength());
+ }
+ }
+
+ public static class UndoUpdater extends Updater {
+ private int fOffset;
+ private int fLength;
+ private UndoUpdater(TextEdit root) {
+ fOffset= root.getOffset();
+ fLength= root.getLength();
+ }
+ public void documentChanged(DocumentEvent event) {
+ fLength+= TextEdit.getDelta(event);
+ }
+ public void storeRegion() {
+ undo.defineRegion(fOffset, fLength);
+ }
}
protected Updater() {
@@ -66,5 +88,7 @@ import org.eclipse.jface.text.IDocumentListener;
}
public void documentChanged(DocumentEvent event) {
- }
+ }
+
+ public abstract void storeRegion();
}

Back to the top