1 11 package org.eclipse.text.edits; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.HashMap ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Map ; 19 20 import org.eclipse.core.runtime.Assert; 21 22 import org.eclipse.jface.text.BadLocationException; 23 import org.eclipse.jface.text.IDocument; 24 import org.eclipse.jface.text.IRegion; 25 import org.eclipse.jface.text.Region; 26 27 45 public final class MoveSourceEdit extends TextEdit { 46 47 private MoveTargetEdit fTarget; 48 private ISourceModifier fModifier; 49 50 private String fSourceContent; 51 private MultiTextEdit fSourceRoot; 52 53 59 public MoveSourceEdit(int offset, int length) { 60 super(offset, length); 61 } 62 63 70 public MoveSourceEdit(int offset, int length, MoveTargetEdit target) { 71 this(offset, length); 72 setTargetEdit(target); 73 } 74 75 78 private MoveSourceEdit(MoveSourceEdit other) { 79 super(other); 80 if (other.fModifier != null) 81 fModifier= other.fModifier.copy(); 82 } 83 84 90 public MoveTargetEdit getTargetEdit() { 91 return fTarget; 92 } 93 94 102 public void setTargetEdit(MoveTargetEdit edit) { 103 fTarget= edit; 104 fTarget.setSourceEdit(this); 105 } 106 107 113 public ISourceModifier getSourceModifier() { 114 return fModifier; 115 } 116 117 123 public void setSourceModifier(ISourceModifier modifier) { 124 fModifier= modifier; 125 } 126 127 129 String getContent() { 130 if (fSourceContent == null) 134 return ""; return fSourceContent; 136 } 137 138 MultiTextEdit getSourceRoot() { 139 return fSourceRoot; 140 } 141 142 void clearContent() { 143 fSourceContent= null; 144 fSourceRoot= null; 145 } 146 147 149 152 protected TextEdit doCopy() { 153 return new MoveSourceEdit(this); 154 } 155 156 159 protected void postProcessCopy(TextEditCopier copier) { 160 if (fTarget != null) { 161 MoveSourceEdit source= (MoveSourceEdit)copier.getCopy(this); 162 MoveTargetEdit target= (MoveTargetEdit)copier.getCopy(fTarget); 163 if (source != null && target != null) 164 source.setTargetEdit(target); 165 } 166 } 167 168 170 173 protected void accept0(TextEditVisitor visitor) { 174 boolean visitChildren= visitor.visit(this); 175 if (visitChildren) { 176 acceptChildren(visitor); 177 } 178 } 179 180 182 int traverseConsistencyCheck(TextEditProcessor processor, IDocument document, List sourceEdits) { 183 int result= super.traverseConsistencyCheck(processor, document, sourceEdits); 184 if (fSourceContent == null) { 188 if (sourceEdits.size() <= result) { 189 List list= new ArrayList (); 190 list.add(this); 191 for (int i= sourceEdits.size(); i < result; i++) 192 sourceEdits.add(null); 193 sourceEdits.add(list); 194 } else { 195 List list= (List )sourceEdits.get(result); 196 if (list == null) { 197 list= new ArrayList (); 198 sourceEdits.add(result, list); 199 } 200 list.add(this); 201 } 202 } 203 return result; 204 } 205 206 void performConsistencyCheck(TextEditProcessor processor, IDocument document) throws MalformedTreeException { 207 if (fTarget == null) 208 throw new MalformedTreeException(getParent(), this, TextEditMessages.getString("MoveSourceEdit.no_target")); if (fTarget.getSourceEdit() != this) 210 throw new MalformedTreeException(getParent(), this, TextEditMessages.getString("MoveSourceEdit.different_source")); 215 } 216 217 219 void traverseSourceComputation(TextEditProcessor processor, IDocument document) { 220 performSourceComputation(processor, document); 224 } 225 226 void performSourceComputation(TextEditProcessor processor, IDocument document) { 227 try { 228 TextEdit[] children= removeChildren(); 229 if (children.length > 0) { 230 String content= document.get(getOffset(), getLength()); 231 EditDocument subDocument= new EditDocument(content); 232 fSourceRoot= new MultiTextEdit(getOffset(), getLength()); 233 fSourceRoot.addChildren(children); 234 fSourceRoot.internalMoveTree(-getOffset()); 235 int processingStyle= getStyle(processor); 236 TextEditProcessor subProcessor= TextEditProcessor.createSourceComputationProcessor(subDocument, fSourceRoot, processingStyle); 237 subProcessor.performEdits(); 238 if (needsTransformation()) 239 applyTransformation(subDocument, processingStyle); 240 fSourceContent= subDocument.get(); 241 } else { 242 fSourceContent= document.get(getOffset(), getLength()); 243 if (needsTransformation()) { 244 EditDocument subDocument= new EditDocument(fSourceContent); 245 applyTransformation(subDocument, getStyle(processor)); 246 fSourceContent= subDocument.get(); 247 } 248 } 249 } catch (BadLocationException cannotHappen) { 250 Assert.isTrue(false); 251 } 252 } 253 254 private int getStyle(TextEditProcessor processor) { 255 if ((processor.getStyle() & TextEdit.UPDATE_REGIONS) != 0) 257 return TextEdit.UPDATE_REGIONS; 258 return TextEdit.NONE; 259 } 260 261 263 int performDocumentUpdating(IDocument document) throws BadLocationException { 264 document.replace(getOffset(), getLength(), ""); fDelta= -getLength(); 266 return fDelta; 267 } 268 269 271 274 boolean deleteChildren() { 275 return false; 276 } 277 278 280 private boolean needsTransformation() { 281 return fModifier != null; 282 } 283 284 private void applyTransformation(IDocument document, int style) throws MalformedTreeException { 285 if ((style & TextEdit.UPDATE_REGIONS) != 0 && fSourceRoot != null) { 286 Map editMap= new HashMap (); 287 TextEdit newEdit= createEdit(editMap); 288 List replaces= new ArrayList (Arrays.asList(fModifier.getModifications(document.get()))); 289 insertEdits(newEdit, replaces); 290 try { 291 newEdit.apply(document, style); 292 } catch (BadLocationException cannotHappen) { 293 Assert.isTrue(false); 294 } 295 restorePositions(editMap); 296 } else { 297 MultiTextEdit newEdit= new MultiTextEdit(0, document.getLength()); 298 TextEdit[] replaces= fModifier.getModifications(document.get()); 299 for (int i= 0; i < replaces.length; i++) { 300 newEdit.addChild(replaces[i]); 301 } 302 try { 303 newEdit.apply(document, style); 304 } catch (BadLocationException cannotHappen) { 305 Assert.isTrue(false); 306 } 307 } 308 } 309 310 private TextEdit createEdit(Map editMap) { 311 MultiTextEdit result= new MultiTextEdit(0, fSourceRoot.getLength()); 312 editMap.put(result, fSourceRoot); 313 createEdit(fSourceRoot, result, editMap); 314 return result; 315 } 316 317 private static void createEdit(TextEdit source, TextEdit target, Map editMap) { 318 TextEdit[] children= source.getChildren(); 319 for (int i= 0; i < children.length; i++) { 320 TextEdit child= children[i]; 321 if (child.isDeleted()) 324 continue; 325 RangeMarker marker= new RangeMarker(child.getOffset(), child.getLength()); 326 target.addChild(marker); 327 editMap.put(marker, child); 328 createEdit(child, marker, editMap); 329 } 330 } 331 332 private void insertEdits(TextEdit root, List edits) { 333 while(edits.size() > 0) { 334 ReplaceEdit edit= (ReplaceEdit)edits.remove(0); 335 insert(root, edit, edits); 336 } 337 } 338 private static void insert(TextEdit parent, ReplaceEdit edit, List edits) { 339 if (!parent.hasChildren()) { 340 parent.addChild(edit); 341 return; 342 } 343 TextEdit[] children= parent.getChildren(); 344 int removed= 0; 346 for (int i= 0; i < children.length; i++) { 347 TextEdit child= children[i]; 348 if (child.covers(edit)) { 349 insert(child, edit, edits); 350 return; 351 } else if (edit.covers(child)) { 352 parent.removeChild(i - removed++); 353 edit.addChild(child); 354 } else { 355 IRegion intersect= intersect(edit, child); 356 if (intersect != null) { 357 ReplaceEdit[] splits= splitEdit(edit, intersect); 358 insert(child, splits[0], edits); 359 edits.add(splits[1]); 360 return; 361 } 362 } 363 } 364 parent.addChild(edit); 365 } 366 367 public static IRegion intersect(TextEdit op1, TextEdit op2) { 368 int offset1= op1.getOffset(); 369 int length1= op1.getLength(); 370 int end1= offset1 + length1 - 1; 371 int offset2= op2.getOffset(); 372 if (end1 < offset2) 373 return null; 374 int length2= op2.getLength(); 375 int end2= offset2 + length2 - 1; 376 if (end2 < offset1) 377 return null; 378 379 int end= Math.min(end1, end2); 380 if (offset1 < offset2) { 381 return new Region(offset2, end - offset2 + 1); 382 } 383 return new Region(offset1, end - offset1 + 1); 384 } 385 386 private static ReplaceEdit[] splitEdit(ReplaceEdit edit, IRegion intersect) { 387 if (edit.getOffset() != intersect.getOffset()) 388 return splitIntersectRight(edit, intersect); 389 return splitIntersectLeft(edit, intersect); 390 } 391 392 private static ReplaceEdit[] splitIntersectRight(ReplaceEdit edit, IRegion intersect) { 393 ReplaceEdit[] result= new ReplaceEdit[2]; 394 result[0]= new ReplaceEdit(intersect.getOffset(), intersect.getLength(), ""); result[1]= new ReplaceEdit( 397 edit.getOffset(), 398 intersect.getOffset() - edit.getOffset(), 399 edit.getText()); 400 return result; 401 } 402 403 private static ReplaceEdit[] splitIntersectLeft(ReplaceEdit edit, IRegion intersect) { 404 ReplaceEdit[] result= new ReplaceEdit[2]; 405 result[0]= new ReplaceEdit(intersect.getOffset(), intersect.getLength(), edit.getText()); 406 result[1]= new ReplaceEdit( intersect.getOffset() + intersect.getLength(), 408 edit.getLength() - intersect.getLength(), 409 ""); return result; 411 } 412 413 private static void restorePositions(Map editMap) { 414 for (Iterator iter= editMap.keySet().iterator(); iter.hasNext();) { 415 TextEdit marker= (TextEdit)iter.next(); 416 TextEdit edit= (TextEdit)editMap.get(marker); 417 if (marker.isDeleted()) { 418 edit.markAsDeleted(); 419 } else { 420 edit.adjustOffset(marker.getOffset() - edit.getOffset()); 421 edit.adjustLength(marker.getLength() - edit.getLength()); 422 } 423 } 424 } 425 } 426 | Popular Tags |