PageRenderTime 56ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/eclipse-cdt-8.1.0/org.eclipse.cdt-CDT_8_1_0/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/TextEditUtil.java

#
Java | 219 lines | 163 code | 21 blank | 35 comment | 47 complexity | 4dbd35fe15757e1e38f4276b56b69d19 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1
  1. /*******************************************************************************
  2. * Copyright (c) 2007, 2012 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. * Sergey Prigogin (Google)
  11. *******************************************************************************/
  12. package org.eclipse.cdt.internal.core.dom.rewrite.changegenerator;
  13. import org.eclipse.text.edits.CopyTargetEdit;
  14. import org.eclipse.text.edits.DeleteEdit;
  15. import org.eclipse.text.edits.InsertEdit;
  16. import org.eclipse.text.edits.MalformedTreeException;
  17. import org.eclipse.text.edits.MoveSourceEdit;
  18. import org.eclipse.text.edits.MoveTargetEdit;
  19. import org.eclipse.text.edits.MultiTextEdit;
  20. import org.eclipse.text.edits.ReplaceEdit;
  21. import org.eclipse.text.edits.TextEdit;
  22. public class TextEditUtil {
  23. // Do not instantiate. All methods are static.
  24. private TextEditUtil() {
  25. }
  26. /**
  27. * Degenerates the given edit tree into a list.<br>
  28. * All nodes of the result are leafs.<br>
  29. * <strong>The given edit is modified and can no longer be used.</strong>
  30. *
  31. * @param edit the edit tree to flatten
  32. * @return a MultiTextEdit containing the list of edits
  33. */
  34. public static MultiTextEdit flatten(TextEdit edit) {
  35. MultiTextEdit result= new MultiTextEdit();
  36. flatten(edit, result);
  37. return result;
  38. }
  39. private static void flatten(TextEdit edit, MultiTextEdit result) {
  40. if (edit.hasChildren()) {
  41. TextEdit[] children= edit.getChildren();
  42. for (int i= 0; i < children.length; i++) {
  43. TextEdit child= children[i];
  44. child.getParent().removeChild(0);
  45. flatten(child, result);
  46. }
  47. } else if (!(edit instanceof MultiTextEdit)) {
  48. result.addChild(edit);
  49. }
  50. }
  51. /**
  52. * Create an edit which contains <code>edit1</code> and <code>edit2</code>
  53. * <p><strong>The given edits are modified and they can no longer be used.</strong></p>
  54. *
  55. * @param edit1 the edit to merge with edit2
  56. * @param edit2 the edit to merge with edit1
  57. * @return the merged tree
  58. * @throws MalformedTreeException if the two edits ovelap
  59. */
  60. public static TextEdit merge(TextEdit edit1, TextEdit edit2) {
  61. if (edit1 instanceof MultiTextEdit && !edit1.hasChildren()) {
  62. return edit2;
  63. }
  64. if (edit2 instanceof MultiTextEdit && !edit2.hasChildren()) {
  65. return edit1;
  66. }
  67. MultiTextEdit result= new MultiTextEdit();
  68. merge(edit1, edit2, result);
  69. return result;
  70. }
  71. private static void merge(TextEdit edit1, TextEdit edit2, MultiTextEdit result) {
  72. if (edit1 instanceof MultiTextEdit && edit2 instanceof MultiTextEdit) {
  73. MultiTextEdit multiTextEdit1= (MultiTextEdit) edit1;
  74. if (!multiTextEdit1.hasChildren()) {
  75. result.addChild(edit2);
  76. return;
  77. }
  78. MultiTextEdit multiTextEdit2= (MultiTextEdit) edit2;
  79. if (!multiTextEdit2.hasChildren()) {
  80. result.addChild(edit1);
  81. return;
  82. }
  83. TextEdit[] children1= multiTextEdit1.getChildren();
  84. TextEdit[] children2= multiTextEdit2.getChildren();
  85. int i1= 0;
  86. int i2= 0;
  87. while (i1 < children1.length && i2 < children2.length) {
  88. while (i1 < children1.length && children1[i1].getExclusiveEnd() < children2[i2].getOffset()) {
  89. edit1.removeChild(0);
  90. result.addChild(children1[i1]);
  91. i1++;
  92. }
  93. if (i1 >= children1.length)
  94. break;
  95. while (i2 < children2.length && children2[i2].getExclusiveEnd() < children1[i1].getOffset()) {
  96. edit2.removeChild(0);
  97. result.addChild(children2[i2]);
  98. i2++;
  99. }
  100. if (i2 >= children2.length)
  101. break;
  102. if (children1[i1].getExclusiveEnd() < children2[i2].getOffset())
  103. continue;
  104. edit1.removeChild(0);
  105. edit2.removeChild(0);
  106. merge(children1[i1], children2[i2], result);
  107. i1++;
  108. i2++;
  109. }
  110. while (i1 < children1.length) {
  111. edit1.removeChild(0);
  112. result.addChild(children1[i1]);
  113. i1++;
  114. }
  115. while (i2 < children2.length) {
  116. edit2.removeChild(0);
  117. result.addChild(children2[i2]);
  118. i2++;
  119. }
  120. } else if (edit1 instanceof MultiTextEdit) {
  121. TextEdit[] children= edit1.getChildren();
  122. int i= 0;
  123. while (children[i].getExclusiveEnd() < edit2.getOffset()) {
  124. edit1.removeChild(0);
  125. result.addChild(children[i]);
  126. i++;
  127. if (i >= children.length) {
  128. result.addChild(edit2);
  129. return;
  130. }
  131. }
  132. edit1.removeChild(0);
  133. merge(children[i], edit2, result);
  134. i++;
  135. while (i < children.length) {
  136. edit1.removeChild(0);
  137. result.addChild(children[i]);
  138. i++;
  139. }
  140. } else if (edit2 instanceof MultiTextEdit) {
  141. TextEdit[] children= edit2.getChildren();
  142. int i= 0;
  143. while (children[i].getExclusiveEnd() < edit1.getOffset()) {
  144. edit2.removeChild(0);
  145. result.addChild(children[i]);
  146. i++;
  147. if (i >= children.length) {
  148. result.addChild(edit1);
  149. return;
  150. }
  151. }
  152. edit2.removeChild(0);
  153. merge(edit1, children[i], result);
  154. i++;
  155. while (i < children.length) {
  156. edit2.removeChild(0);
  157. result.addChild(children[i]);
  158. i++;
  159. }
  160. } else {
  161. if (edit1.getExclusiveEnd() < edit2.getOffset()) {
  162. result.addChild(edit1);
  163. result.addChild(edit2);
  164. } else {
  165. result.addChild(edit2);
  166. result.addChild(edit1);
  167. }
  168. }
  169. }
  170. /**
  171. * Returns the difference in the document length caused by the edit. {@code InsertEdit}s have
  172. * positive delta, {@code DeleteEdit}s have negative one.
  173. * @param edit the edit to determine delta for.
  174. * @return the delta
  175. */
  176. public static int delta(TextEdit edit) {
  177. int delta = 0;
  178. for (TextEdit child : edit.getChildren()) {
  179. delta += delta(child);
  180. }
  181. delta += ownDelta(edit);
  182. return delta;
  183. }
  184. private static int ownDelta(TextEdit edit) {
  185. if (edit instanceof DeleteEdit || edit instanceof MoveSourceEdit) {
  186. return -edit.getLength();
  187. } else if (edit instanceof InsertEdit) {
  188. return ((InsertEdit) edit).getText().length();
  189. } else if (edit instanceof ReplaceEdit) {
  190. return ((ReplaceEdit) edit).getText().length() - edit.getLength();
  191. } else if (edit instanceof CopyTargetEdit) {
  192. return ((CopyTargetEdit) edit).getSourceEdit().getLength();
  193. } else if (edit instanceof MoveTargetEdit) {
  194. return ((MoveTargetEdit) edit).getSourceEdit().getLength();
  195. }
  196. return 0;
  197. }
  198. }