1 11 package org.eclipse.ltk.core.refactoring; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.List ; 16 17 import org.eclipse.text.edits.MalformedTreeException; 18 import org.eclipse.text.edits.MultiTextEdit; 19 import org.eclipse.text.edits.TextEdit; 20 import org.eclipse.text.edits.TextEditCopier; 21 import org.eclipse.text.edits.TextEditGroup; 22 import org.eclipse.text.edits.TextEditProcessor; 23 import org.eclipse.text.edits.UndoEdit; 24 25 import org.eclipse.core.runtime.Assert; 26 import org.eclipse.core.runtime.CoreException; 27 import org.eclipse.core.runtime.IProgressMonitor; 28 import org.eclipse.core.runtime.NullProgressMonitor; 29 import org.eclipse.core.runtime.SubProgressMonitor; 30 31 import org.eclipse.jface.text.BadLocationException; 32 import org.eclipse.jface.text.Document; 33 import org.eclipse.jface.text.DocumentRewriteSession; 34 import org.eclipse.jface.text.DocumentRewriteSessionType; 35 import org.eclipse.jface.text.IDocument; 36 import org.eclipse.jface.text.IDocumentExtension4; 37 import org.eclipse.jface.text.IRegion; 38 import org.eclipse.jface.text.Region; 39 40 import org.eclipse.ltk.internal.core.refactoring.Changes; 41 42 68 public abstract class TextChange extends TextEditBasedChange { 69 70 private TextEdit fEdit; 71 private TextEditCopier fCopier; 72 73 85 protected TextChange(String name) { 86 super(name); 87 } 88 89 91 98 public void setEdit(TextEdit edit) { 99 Assert.isTrue(fEdit == null, "Root edit can only be set once"); Assert.isTrue(edit != null); 101 fEdit= edit; 102 } 103 104 110 public TextEdit getEdit() { 111 return fEdit; 112 } 113 114 121 public void addTextEditGroup(TextEditGroup group) { 122 addTextEditChangeGroup(new TextEditChangeGroup(this, group)); 123 } 124 125 133 public void addTextEditChangeGroup(TextEditChangeGroup group) { 134 Assert.isTrue(fEdit != null, "Can only add a description if a root edit exists"); addChangeGroup(group); 136 } 137 138 144 public TextEditChangeGroup[] getTextEditChangeGroups() { 145 final TextEditBasedChangeGroup[] groups= getChangeGroups(); 146 final TextEditChangeGroup[] result= new TextEditChangeGroup[groups.length]; 147 System.arraycopy(groups, 0, result, 0, groups.length); 148 return result; 149 } 150 151 162 public void addEdit(TextEdit edit) throws MalformedTreeException { 163 Assert.isTrue(fEdit != null, "root must exist to add an edit"); fEdit.addChild(edit); 165 } 166 167 169 184 protected abstract IDocument acquireDocument(IProgressMonitor pm) throws CoreException; 185 186 197 protected abstract void commit(IDocument document, IProgressMonitor pm) throws CoreException; 198 199 208 protected abstract void releaseDocument(IDocument document, IProgressMonitor pm) throws CoreException; 209 210 223 protected abstract Change createUndoChange(UndoEdit edit); 224 225 228 public Change perform(IProgressMonitor pm) throws CoreException { 229 pm.beginTask("", 3); IDocument document= null; 231 DocumentRewriteSession session= null; 232 233 try { 234 document= acquireDocument(new SubProgressMonitor(pm, 1)); 235 if (document instanceof IDocumentExtension4) { 236 session= ((IDocumentExtension4)document).startRewriteSession( 237 DocumentRewriteSessionType.UNRESTRICTED); 238 } 239 TextEditProcessor processor= createTextEditProcessor(document, TextEdit.CREATE_UNDO, false); 240 UndoEdit undo= processor.performEdits(); 241 commit(document, new SubProgressMonitor(pm, 1)); 242 return createUndoChange(undo); 243 } catch (BadLocationException e) { 244 throw Changes.asCoreException(e); 245 } finally { 246 if (document != null) { 247 try { 248 if (session != null) { 249 ((IDocumentExtension4)document).stopRewriteSession(session); 250 } 251 } finally { 252 releaseDocument(document, new SubProgressMonitor(pm, 1)); 253 } 254 } 255 pm.done(); 256 } 257 } 258 259 261 278 public IDocument getCurrentDocument(IProgressMonitor pm) throws CoreException { 279 if (pm == null) 280 pm= new NullProgressMonitor(); 281 IDocument result= null; 282 pm.beginTask("", 2); try{ 284 result= acquireDocument(new SubProgressMonitor(pm, 1)); 285 } finally { 286 if (result != null) 287 releaseDocument(result, new SubProgressMonitor(pm, 1)); 288 } 289 pm.done(); 290 return result; 291 } 292 293 296 public String getCurrentContent(IProgressMonitor pm) throws CoreException { 297 return getCurrentDocument(pm).get(); 298 } 299 300 303 public String getCurrentContent(IRegion region, boolean expandRegionToFullLine, int surroundingLines, IProgressMonitor pm) throws CoreException { 304 Assert.isNotNull(region); 305 Assert.isTrue(surroundingLines >= 0); 306 IDocument document= getCurrentDocument(pm); 307 Assert.isTrue(document.getLength() >= region.getOffset() + region.getLength()); 308 return getContent(document, region, expandRegionToFullLine, surroundingLines); 309 } 310 311 313 328 public TextEdit getPreviewEdit(TextEdit original) { 329 Assert.isTrue(getKeepPreviewEdits() && fCopier != null && original != null); 330 return fCopier.getCopy(original); 331 } 332 333 350 public TextEdit[] getPreviewEdits(TextEdit[] originals) { 351 Assert.isTrue(getKeepPreviewEdits() && fCopier != null && originals != null); 352 if (originals.length == 0) 353 return new TextEdit[0]; 354 List result= new ArrayList (originals.length); 355 for (int i= 0; i < originals.length; i++) { 356 TextEdit copy= fCopier.getCopy(originals[i]); 357 if (copy != null) 358 result.add(copy); 359 } 360 return (TextEdit[]) result.toArray(new TextEdit[result.size()]); 361 } 362 363 375 public IDocument getPreviewDocument(IProgressMonitor pm) throws CoreException { 376 PreviewAndRegion result= getPreviewDocument(ALL_EDITS, pm); 377 return result.document; 378 } 379 380 383 public String getPreviewContent(IProgressMonitor pm) throws CoreException { 384 return getPreviewDocument(pm).get(); 385 } 386 387 425 public String getPreviewContent(TextEditChangeGroup[] changeGroups, IRegion region, boolean expandRegionToFullLine, int surroundingLines, IProgressMonitor pm) throws CoreException { 426 return getPreviewContent((TextEditBasedChangeGroup[])changeGroups, region, expandRegionToFullLine, surroundingLines, pm); 427 } 428 429 469 public String getPreviewContent(TextEditBasedChangeGroup[] changeGroups, IRegion region, boolean expandRegionToFullLine, int surroundingLines, IProgressMonitor pm) throws CoreException { 470 IRegion currentRegion= getRegion(changeGroups); 471 Assert.isTrue(region.getOffset() <= currentRegion.getOffset() && 472 currentRegion.getOffset() + currentRegion.getLength() <= region.getOffset() + region.getLength()); 473 TextEdit root= getEdit(); 475 Assert.isNotNull(root, "No root edit"); for (int c= 0; c < changeGroups.length; c++) { 477 TextEditBasedChangeGroup group= changeGroups[c]; 478 TextEdit[] edits= group.getTextEdits(); 479 for (int e= 0; e < edits.length; e++) { 480 481 } 485 } 486 PreviewAndRegion result= getPreviewDocument(changeGroups, pm); 487 int delta; 488 if (result.region == null) { delta= -currentRegion.getLength(); 490 } else { 491 delta= result.region.getLength() - currentRegion.getLength(); 492 } 493 return getContent(result.document, new Region(region.getOffset(), region.getLength() + delta), expandRegionToFullLine, surroundingLines); 494 495 } 496 497 499 private PreviewAndRegion getPreviewDocument(TextEditBasedChangeGroup[] changes, IProgressMonitor pm) throws CoreException { 500 IDocument document= new Document(getCurrentDocument(pm).get()); 501 boolean trackChanges= getKeepPreviewEdits(); 502 setKeepPreviewEdits(true); 503 TextEditProcessor processor= changes == ALL_EDITS 504 ? createTextEditProcessor(document, TextEdit.NONE, true) 505 : createTextEditProcessor(document, TextEdit.NONE, changes); 506 try { 507 processor.performEdits(); 508 return new PreviewAndRegion(document, getNewRegion(changes)); 509 } catch (BadLocationException e) { 510 throw Changes.asCoreException(e); 511 } finally { 512 setKeepPreviewEdits(trackChanges); 513 } 514 } 515 516 private TextEditProcessor createTextEditProcessor(IDocument document, int flags, boolean preview) { 517 if (fEdit == null) 518 return new TextEditProcessor(document, new MultiTextEdit(0,0), flags); 519 List excludes= new ArrayList (0); 520 TextEditBasedChangeGroup[] groups= getChangeGroups(); 521 for (int index= 0; index < groups.length; index++) { 522 TextEditBasedChangeGroup edit= groups[index]; 523 if (!edit.isEnabled()) { 524 excludes.addAll(Arrays.asList(edit.getTextEditGroup().getTextEdits())); 525 } 526 } 527 if (preview) { 528 fCopier= new TextEditCopier(fEdit); 529 TextEdit copiedEdit= fCopier.perform(); 530 boolean keep= getKeepPreviewEdits(); 531 if (keep) 532 flags= flags | TextEdit.UPDATE_REGIONS; 533 LocalTextEditProcessor result= new LocalTextEditProcessor(document, copiedEdit, flags); 534 result.setExcludes(mapEdits( 535 (TextEdit[])excludes.toArray(new TextEdit[excludes.size()]), 536 fCopier)); 537 if (!keep) 538 fCopier= null; 539 return result; 540 } else { 541 LocalTextEditProcessor result= new LocalTextEditProcessor(document, fEdit, flags | TextEdit.UPDATE_REGIONS); 542 result.setExcludes((TextEdit[])excludes.toArray(new TextEdit[excludes.size()])); 543 return result; 544 } 545 } 546 547 private TextEditProcessor createTextEditProcessor(IDocument document, int flags, TextEditBasedChangeGroup[] changes) { 548 if (fEdit == null) 549 return new TextEditProcessor(document, new MultiTextEdit(0,0), flags); 550 List includes= new ArrayList (0); 551 for (int c= 0; c < changes.length; c++) { 552 TextEditBasedChangeGroup change= changes[c]; 553 Assert.isTrue(change.getTextEditChange() == this); 554 if (change.isEnabled()) { 555 includes.addAll(Arrays.asList(change.getTextEditGroup().getTextEdits())); 556 } 557 } 558 fCopier= new TextEditCopier(fEdit); 559 TextEdit copiedEdit= fCopier.perform(); 560 boolean keep= getKeepPreviewEdits(); 561 if (keep) 562 flags= flags | TextEdit.UPDATE_REGIONS; 563 LocalTextEditProcessor result= new LocalTextEditProcessor(document, copiedEdit, flags); 564 result.setIncludes(mapEdits( 565 (TextEdit[])includes.toArray(new TextEdit[includes.size()]), 566 fCopier)); 567 if (!keep) 568 fCopier= null; 569 return result; 570 } 571 572 private IRegion getRegion(TextEditBasedChangeGroup[] changes) { 573 if (changes == ALL_EDITS) { 574 if (fEdit == null) 575 return null; 576 return fEdit.getRegion(); 577 } else { 578 List edits= new ArrayList (); 579 for (int i= 0; i < changes.length; i++) { 580 edits.addAll(Arrays.asList(changes[i].getTextEditGroup().getTextEdits())); 581 } 582 if (edits.size() == 0) 583 return null; 584 return TextEdit.getCoverage((TextEdit[]) edits.toArray(new TextEdit[edits.size()])); 585 } 586 } 587 588 private IRegion getNewRegion(TextEditBasedChangeGroup[] changes) { 589 if (changes == ALL_EDITS) { 590 if (fEdit == null) 591 return null; 592 return fCopier.getCopy(fEdit).getRegion(); 593 } else { 594 List result= new ArrayList (); 595 for (int c= 0; c < changes.length; c++) { 596 TextEdit[] edits= changes[c].getTextEditGroup().getTextEdits(); 597 for (int e= 0; e < edits.length; e++) { 598 TextEdit copy= fCopier.getCopy(edits[e]); 599 if (copy != null) 600 result.add(copy); 601 } 602 } 603 if (result.size() == 0) 604 return null; 605 return TextEdit.getCoverage((TextEdit[]) result.toArray(new TextEdit[result.size()])); 606 } 607 } 608 609 612 public void setKeepPreviewEdits(boolean keep) { 613 super.setKeepPreviewEdits(keep); 614 615 if (!keep) 616 fCopier= null; 617 } 618 } 619 | Popular Tags |