Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/TextEditUtil.java')
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/TextEditUtil.java219
1 files changed, 219 insertions, 0 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/TextEditUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/TextEditUtil.java
new file mode 100644
index 00000000000..3b5b2b6f5b1
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/TextEditUtil.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Sergey Prigogin (Google)
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core.dom.rewrite.changegenerator;
+
+import org.eclipse.text.edits.CopyTargetEdit;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MoveSourceEdit;
+import org.eclipse.text.edits.MoveTargetEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+
+public class TextEditUtil {
+ // Do not instantiate. All methods are static.
+ private TextEditUtil() {
+ }
+
+ /**
+ * Degenerates the given edit tree into a list.<br>
+ * All nodes of the result are leafs.<br>
+ * <strong>The given edit is modified and can no longer be used.</strong>
+ *
+ * @param edit the edit tree to flatten
+ * @return a MultiTextEdit containing the list of edits
+ */
+ public static MultiTextEdit flatten(TextEdit edit) {
+ MultiTextEdit result= new MultiTextEdit();
+ flatten(edit, result);
+ return result;
+ }
+
+ private static void flatten(TextEdit edit, MultiTextEdit result) {
+ if (edit.hasChildren()) {
+ TextEdit[] children= edit.getChildren();
+ for (int i= 0; i < children.length; i++) {
+ TextEdit child= children[i];
+ child.getParent().removeChild(0);
+ flatten(child, result);
+ }
+ } else if (!(edit instanceof MultiTextEdit)) {
+ result.addChild(edit);
+ }
+ }
+
+ /**
+ * Create an edit which contains <code>edit1</code> and <code>edit2</code>
+ * <p><strong>The given edits are modified and they can no longer be used.</strong></p>
+ *
+ * @param edit1 the edit to merge with edit2
+ * @param edit2 the edit to merge with edit1
+ * @return the merged tree
+ * @throws MalformedTreeException if the two edits ovelap
+ */
+ public static TextEdit merge(TextEdit edit1, TextEdit edit2) {
+ if (edit1 instanceof MultiTextEdit && !edit1.hasChildren()) {
+ return edit2;
+ }
+
+ if (edit2 instanceof MultiTextEdit && !edit2.hasChildren()) {
+ return edit1;
+ }
+
+ MultiTextEdit result= new MultiTextEdit();
+ merge(edit1, edit2, result);
+ return result;
+ }
+
+ private static void merge(TextEdit edit1, TextEdit edit2, MultiTextEdit result) {
+ if (edit1 instanceof MultiTextEdit && edit2 instanceof MultiTextEdit) {
+ MultiTextEdit multiTextEdit1= (MultiTextEdit) edit1;
+ if (!multiTextEdit1.hasChildren()) {
+ result.addChild(edit2);
+ return;
+ }
+
+ MultiTextEdit multiTextEdit2= (MultiTextEdit) edit2;
+ if (!multiTextEdit2.hasChildren()) {
+ result.addChild(edit1);
+ return;
+ }
+
+ TextEdit[] children1= multiTextEdit1.getChildren();
+ TextEdit[] children2= multiTextEdit2.getChildren();
+
+ int i1= 0;
+ int i2= 0;
+ while (i1 < children1.length && i2 < children2.length) {
+ while (i1 < children1.length && children1[i1].getExclusiveEnd() < children2[i2].getOffset()) {
+ edit1.removeChild(0);
+ result.addChild(children1[i1]);
+ i1++;
+ }
+ if (i1 >= children1.length)
+ break;
+
+ while (i2 < children2.length && children2[i2].getExclusiveEnd() < children1[i1].getOffset()) {
+ edit2.removeChild(0);
+ result.addChild(children2[i2]);
+ i2++;
+ }
+ if (i2 >= children2.length)
+ break;
+
+ if (children1[i1].getExclusiveEnd() < children2[i2].getOffset())
+ continue;
+
+ edit1.removeChild(0);
+ edit2.removeChild(0);
+ merge(children1[i1], children2[i2], result);
+
+ i1++;
+ i2++;
+ }
+
+ while (i1 < children1.length) {
+ edit1.removeChild(0);
+ result.addChild(children1[i1]);
+ i1++;
+ }
+
+ while (i2 < children2.length) {
+ edit2.removeChild(0);
+ result.addChild(children2[i2]);
+ i2++;
+ }
+ } else if (edit1 instanceof MultiTextEdit) {
+ TextEdit[] children= edit1.getChildren();
+
+ int i= 0;
+ while (children[i].getExclusiveEnd() < edit2.getOffset()) {
+ edit1.removeChild(0);
+ result.addChild(children[i]);
+ i++;
+ if (i >= children.length) {
+ result.addChild(edit2);
+ return;
+ }
+ }
+ edit1.removeChild(0);
+ merge(children[i], edit2, result);
+ i++;
+ while (i < children.length) {
+ edit1.removeChild(0);
+ result.addChild(children[i]);
+ i++;
+ }
+ } else if (edit2 instanceof MultiTextEdit) {
+ TextEdit[] children= edit2.getChildren();
+
+ int i= 0;
+ while (children[i].getExclusiveEnd() < edit1.getOffset()) {
+ edit2.removeChild(0);
+ result.addChild(children[i]);
+ i++;
+ if (i >= children.length) {
+ result.addChild(edit1);
+ return;
+ }
+ }
+ edit2.removeChild(0);
+ merge(edit1, children[i], result);
+ i++;
+ while (i < children.length) {
+ edit2.removeChild(0);
+ result.addChild(children[i]);
+ i++;
+ }
+ } else {
+ if (edit1.getExclusiveEnd() < edit2.getOffset()) {
+ result.addChild(edit1);
+ result.addChild(edit2);
+ } else {
+ result.addChild(edit2);
+ result.addChild(edit1);
+ }
+ }
+ }
+
+ /**
+ * Returns the difference in the document length caused by the edit. {@code InsertEdit}s have
+ * positive delta, {@code DeleteEdit}s have negative one.
+ * @param edit the edit to determine delta for.
+ * @return the delta
+ */
+ public static int delta(TextEdit edit) {
+ int delta = 0;
+ for (TextEdit child : edit.getChildren()) {
+ delta += delta(child);
+ }
+ delta += ownDelta(edit);
+ return delta;
+ }
+
+ private static int ownDelta(TextEdit edit) {
+ if (edit instanceof DeleteEdit || edit instanceof MoveSourceEdit) {
+ return -edit.getLength();
+ } else if (edit instanceof InsertEdit) {
+ return ((InsertEdit) edit).getText().length();
+ } else if (edit instanceof ReplaceEdit) {
+ return ((ReplaceEdit) edit).getText().length() - edit.getLength();
+ } else if (edit instanceof CopyTargetEdit) {
+ return ((CopyTargetEdit) edit).getSourceEdit().getLength();
+ } else if (edit instanceof MoveTargetEdit) {
+ return ((MoveTargetEdit) edit).getSourceEdit().getLength();
+ }
+ return 0;
+ }
+}

Back to the top