| 1 11 package org.eclipse.jdt.internal.core.dom.rewrite; 12 13 import java.util.ArrayList ; 14 import java.util.IdentityHashMap ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import java.util.Map ; 18 import java.util.Stack ; 19 20 import org.eclipse.core.runtime.Assert; 21 import org.eclipse.core.runtime.CoreException; 22 import org.eclipse.jdt.core.ToolFactory; 23 import org.eclipse.jdt.core.compiler.IScanner; 24 import org.eclipse.jdt.core.compiler.ITerminalSymbols; 25 import org.eclipse.jdt.core.dom.*; 26 import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer; 27 import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer.SourceRange; 28 import org.eclipse.jdt.core.formatter.IndentManipulation; 29 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; 30 import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.BlockContext; 31 import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.NodeMarker; 32 import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.Prefix; 33 import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore.CopyPlaceholderData; 34 import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore.StringPlaceholderData; 35 import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo; 36 import org.eclipse.text.edits.*; 37 38 39 48 public final class ASTRewriteAnalyzer extends ASTVisitor { 49 50 55 static final int JLS2_INTERNAL = AST.JLS2; 56 57 TextEdit currentEdit; 58 final RewriteEventStore eventStore; 60 private TokenScanner tokenScanner; 62 private final Map sourceCopyInfoToEdit; 63 private final Stack sourceCopyEndNodes; 64 65 private final char[] content; 66 private final LineInformation lineInfo; 67 private final ASTRewriteFormatter formatter; 68 private final NodeInfoStore nodeInfos; 69 private final TargetSourceRangeComputer extendedSourceRangeComputer; 70 private final LineCommentEndOffsets lineCommentEndOffsets; 71 72 83 public ASTRewriteAnalyzer(char[] content, LineInformation lineInfo, String lineDelim, TextEdit rootEdit, RewriteEventStore eventStore, NodeInfoStore nodeInfos, List comments, Map options, TargetSourceRangeComputer extendedSourceRangeComputer) { 84 this.eventStore= eventStore; 85 this.content= content; 86 this.lineInfo= lineInfo; 87 this.nodeInfos= nodeInfos; 88 this.tokenScanner= null; 89 this.currentEdit= rootEdit; 90 this.sourceCopyInfoToEdit= new IdentityHashMap (); 91 this.sourceCopyEndNodes= new Stack (); 92 93 this.formatter= new ASTRewriteFormatter(nodeInfos, eventStore, options, lineDelim); 94 95 this.extendedSourceRangeComputer = extendedSourceRangeComputer; 96 this.lineCommentEndOffsets= new LineCommentEndOffsets(comments); 97 } 98 99 final TokenScanner getScanner() { 100 if (this.tokenScanner == null) { 101 IScanner scanner= ToolFactory.createScanner(true, false, false, false); 102 scanner.setSource(this.content); 103 this.tokenScanner= new TokenScanner(scanner); 104 } 105 return this.tokenScanner; 106 } 107 108 final char[] getContent() { 109 return this.content; 110 } 111 112 final LineInformation getLineInformation() { 113 return this.lineInfo; 114 } 115 116 122 final SourceRange getExtendedRange(ASTNode node) { 123 if (this.eventStore.isRangeCopyPlaceholder(node)) { 124 return new SourceRange(node.getStartPosition(), node.getLength()); 125 } 126 return this.extendedSourceRangeComputer.computeSourceRange(node); 127 } 128 129 final int getExtendedOffset(ASTNode node) { 130 return getExtendedRange(node).getStartPosition(); 131 } 132 133 final int getExtendedEnd(ASTNode node) { 134 TargetSourceRangeComputer.SourceRange range= getExtendedRange(node); 135 return range.getStartPosition() + range.getLength(); 136 } 137 138 final TextEdit getCopySourceEdit(CopySourceInfo info) { 139 TextEdit edit= (TextEdit) this.sourceCopyInfoToEdit.get(info); 140 if (edit == null) { 141 SourceRange range= getExtendedRange(info.getNode()); 142 int start= range.getStartPosition(); 143 int end= start + range.getLength(); 144 if (info.isMove) { 145 MoveSourceEdit moveSourceEdit= new MoveSourceEdit(start, end - start); 146 moveSourceEdit.setTargetEdit(new MoveTargetEdit(0)); 147 edit= moveSourceEdit; 148 } else { 149 CopySourceEdit copySourceEdit= new CopySourceEdit(start, end - start); 150 copySourceEdit.setTargetEdit(new CopyTargetEdit(0)); 151 edit= copySourceEdit; 152 } 153 this.sourceCopyInfoToEdit.put(info, edit); 154 } 155 return edit; 156 } 157 158 private final int getChangeKind(ASTNode node, StructuralPropertyDescriptor property) { 159 RewriteEvent event= getEvent(node, property); 160 if (event != null) { 161 return event.getChangeKind(); 162 } 163 return RewriteEvent.UNCHANGED; 164 } 165 166 private final boolean hasChildrenChanges(ASTNode node) { 167 return this.eventStore.hasChangedProperties(node); 168 } 169 170 private final boolean isChanged(ASTNode node, StructuralPropertyDescriptor property) { 171 RewriteEvent event= getEvent(node, property); 172 if (event != null) { 173 return event.getChangeKind() != RewriteEvent.UNCHANGED; 174 } 175 return false; 176 } 177 178 private final boolean isCollapsed(ASTNode node) { 179 return this.nodeInfos.isCollapsed(node); 180 } 181 182 final boolean isInsertBoundToPrevious(ASTNode node) { 183 return this.eventStore.isInsertBoundToPrevious(node); 184 } 185 186 private final TextEditGroup getEditGroup(ASTNode parent, StructuralPropertyDescriptor property) { 187 RewriteEvent event= getEvent(parent, property); 188 if (event != null) { 189 return getEditGroup(event); 190 } 191 return null; 192 } 193 194 final RewriteEvent getEvent(ASTNode parent, StructuralPropertyDescriptor property) { 195 return this.eventStore.getEvent(parent, property); 196 } 197 198 final TextEditGroup getEditGroup(RewriteEvent change) { 199 return this.eventStore.getEventEditGroup(change); 200 } 201 202 private final Object getOriginalValue(ASTNode parent, StructuralPropertyDescriptor property) { 203 return this.eventStore.getOriginalValue(parent, property); 204 } 205 206 private final Object getNewValue(ASTNode parent, StructuralPropertyDescriptor property) { 207 return this.eventStore.getNewValue(parent, property); 208 } 209 210 final void addEdit(TextEdit edit) { 211 this.currentEdit.addChild(edit); 212 } 213 214 final String getLineDelimiter() { 215 return this.formatter.getLineDelimiter(); 216 } 217 218 final String createIndentString(int indent) { 219 return this.formatter.createIndentString(indent); 220 } 221 222 final private String getIndentOfLine(int pos) { 223 int line= getLineInformation().getLineOfOffset(pos); 224 if (line >= 0) { 225 char[] cont= getContent(); 226 int lineStart= getLineInformation().getLineOffset(line); 227 int i= lineStart; 228 while (i < cont.length && IndentManipulation.isIndentChar(content[i])) { 229 i++; 230 } 231 return new String (cont, lineStart, i - lineStart); 232 } 233 return new String (); 234 } 235 236 237 final String getIndentAtOffset(int pos) { 238 return this.formatter.getIndentString(getIndentOfLine(pos)); 239 } 240 241 final void doTextInsert(int offset, String insertString, TextEditGroup editGroup) { 242 if (insertString.length() > 0) { 243 if (this.lineCommentEndOffsets.isEndOfLineComment(offset, this.content)) { 245 if (!insertString.startsWith(getLineDelimiter())) { 246 TextEdit edit= new InsertEdit(offset, getLineDelimiter()); addEdit(edit); 248 if (editGroup != null) { 249 addEditGroup(editGroup, edit); 250 } 251 } 252 this.lineCommentEndOffsets.remove(offset); } 254 TextEdit edit= new InsertEdit(offset, insertString); 255 addEdit(edit); 256 if (editGroup != null) { 257 addEditGroup(editGroup, edit); 258 } 259 } 260 } 261 262 final void addEditGroup(TextEditGroup editGroup, TextEdit edit) { 263 editGroup.addTextEdit(edit); 264 } 265 266 final TextEdit doTextRemove(int offset, int len, TextEditGroup editGroup) { 267 if (len == 0) { 268 return null; 269 } 270 TextEdit edit= new DeleteEdit(offset, len); 271 addEdit(edit); 272 if (editGroup != null) { 273 addEditGroup(editGroup, edit); 274 } 275 return edit; 276 } 277 278 final void doTextRemoveAndVisit(int offset, int len, ASTNode node, TextEditGroup editGroup) { 279 TextEdit edit= doTextRemove(offset, len, editGroup); 280 if (edit != null) { 281 this.currentEdit= edit; 282 voidVisit(node); 283 this.currentEdit= edit.getParent(); 284 } else { 285 voidVisit(node); 286 } 287 } 288 289 final int doVisit(ASTNode node) { 290 node.accept(this); 291 return getExtendedEnd(node); 292 } 293 294 private final int doVisit(ASTNode parent, StructuralPropertyDescriptor property, int offset) { 295 Object node= getOriginalValue(parent, property); 296 if (property.isChildProperty() && node != null) { 297 return doVisit((ASTNode) node); 298 } else if (property.isChildListProperty()) { 299 return doVisitList((List ) node, offset); 300 } 301 return offset; 302 } 303 304 private int doVisitList(List list, int offset) { 305 int endPos= offset; 306 for (Iterator iter= list.iterator(); iter.hasNext();) { 307 ASTNode curr= ((ASTNode) iter.next()); 308 endPos= doVisit(curr); 309 } 310 return endPos; 311 } 312 313 final void voidVisit(ASTNode node) { 314 node.accept(this); 315 } 316 317 private final void voidVisit(ASTNode parent, StructuralPropertyDescriptor property) { 318 Object node= getOriginalValue(parent, property); 319 if (property.isChildProperty() && node != null) { 320 voidVisit((ASTNode) node); 321 } else if (property.isChildListProperty()) { 322 voidVisitList((List ) node); 323 } 324 } 325 326 private void voidVisitList(List list) { 327 for (Iterator iter= list.iterator(); iter.hasNext();) { 328 doVisit(((ASTNode) iter.next())); 329 } 330 } 331 332 private final boolean doVisitUnchangedChildren(ASTNode parent) { 333 List properties= parent.structuralPropertiesForType(); 334 for (int i= 0; i < properties.size(); i++) { 335 voidVisit(parent, (StructuralPropertyDescriptor) properties.get(i)); 336 } 337 return false; 338 } 339 340 341 private final void doTextReplace(int offset, int len, String insertString, TextEditGroup editGroup) { 342 if (len > 0 || insertString.length() > 0) { 343 TextEdit edit= new ReplaceEdit(offset, len, insertString); 344 addEdit(edit); 345 if (editGroup != null) { 346 addEditGroup(editGroup, edit); 347 } 348 } 349 } 350 351 private final TextEdit doTextCopy(TextEdit sourceEdit, int destOffset, int sourceIndentLevel, String destIndentString, TextEditGroup editGroup) { 352 TextEdit targetEdit; 353 SourceModifier modifier= new SourceModifier(sourceIndentLevel, destIndentString, this.formatter.getTabWidth(), this.formatter.getIndentWidth()); 354 355 if (sourceEdit instanceof MoveSourceEdit) { 356 MoveSourceEdit moveEdit= (MoveSourceEdit) sourceEdit; 357 moveEdit.setSourceModifier(modifier); 358 359 targetEdit= new MoveTargetEdit(destOffset, moveEdit); 360 addEdit(targetEdit); 361 } else { 362 CopySourceEdit copyEdit= (CopySourceEdit) sourceEdit; 363 copyEdit.setSourceModifier(modifier); 364 365 targetEdit= new CopyTargetEdit(destOffset, copyEdit); 366 addEdit(targetEdit); 367 } 368 369 if (editGroup != null) { 370 addEditGroup(editGroup, sourceEdit); 371 addEditGroup(editGroup, targetEdit); 372 } 373 return targetEdit; 374 375 } 376 377 private void changeNotSupported(ASTNode node) { 378 Assert.isTrue(false, "Change not supported in " + node.getClass().getName()); } 380 381 382 class ListRewriter { 383 protected String contantSeparator; 384 protected int startPos; 385 386 protected RewriteEvent[] list; 387 388 protected final ASTNode getOriginalNode(int index) { 389 return (ASTNode) this.list[index].getOriginalValue(); 390 } 391 392 protected final ASTNode getNewNode(int index) { 393 return (ASTNode) this.list[index].getNewValue(); 394 } 395 396 protected String getSeparatorString(int nodeIndex) { 397 return this.contantSeparator; 398 } 399 400 protected int getInitialIndent() { 401 return getIndent(this.startPos); 402 } 403 404 protected int getNodeIndent(int nodeIndex) { 405 ASTNode node= getOriginalNode(nodeIndex); 406 if (node == null) { 407 for (int i= nodeIndex - 1; i>= 0; i--) { 408 ASTNode curr= getOriginalNode(i); 409 if (curr != null) { 410 return getIndent(curr.getStartPosition()); 411 } 412 } 413 return getInitialIndent(); 414 } 415 return getIndent(node.getStartPosition()); 416 } 417 418 protected int getStartOfNextNode(int nextIndex, int defaultPos) { 419 for (int i= nextIndex; i < this.list.length; i++) { 420 RewriteEvent elem= this.list[i]; 421 if (elem.getChangeKind() != RewriteEvent.INSERTED) { 422 ASTNode node= (ASTNode) elem.getOriginalValue(); 423 return getExtendedOffset(node); 424 } 425 } 426 return defaultPos; 427 } 428 429 protected int getEndOfNode(ASTNode node) { 430 return getExtendedEnd(node); 431 } 432 433 public final int rewriteList(ASTNode parent, StructuralPropertyDescriptor property, int offset, String keyword, String separator) { 434 this.contantSeparator= separator; 435 return rewriteList(parent, property, offset, keyword); 436 } 437 438 private boolean insertAfterSeparator(ASTNode node) { 439 return !isInsertBoundToPrevious(node); 440 } 441 442 public final int rewriteList(ASTNode parent, StructuralPropertyDescriptor property, int offset, String keyword) { 443 this.startPos= offset; 444 this.list= getEvent(parent, property).getChildren(); 445 446 int total= this.list.length; 447 if (total == 0) { 448 return this.startPos; 449 } 450 451 int currPos= -1; 452 453 int lastNonInsert= -1; 454 int lastNonDelete= -1; 455 456 for (int i= 0; i < total; i++) { 457 int currMark= this.list[i].getChangeKind(); 458 459 if (currMark != RewriteEvent.INSERTED) { 460 lastNonInsert= i; 461 if (currPos == -1) { 462 ASTNode elem= (ASTNode) this.list[i].getOriginalValue(); 463 currPos= getExtendedOffset(elem); 464 } 465 } 466 if (currMark != RewriteEvent.REMOVED) { 467 lastNonDelete= i; 468 } 469 } 470 471 if (currPos == -1) { if (keyword.length() > 0) { TextEditGroup editGroup= getEditGroup(this.list[0]); doTextInsert(offset, keyword, editGroup); 475 } 476 currPos= offset; 477 } 478 if (lastNonDelete == -1) { currPos= offset; 480 } 481 482 int prevEnd= currPos; 483 484 final int NONE= 0, NEW= 1, EXISTING= 2; 485 int separatorState= NEW; 486 487 for (int i= 0; i < total; i++) { 488 RewriteEvent currEvent= this.list[i]; 489 int currMark= currEvent.getChangeKind(); 490 int nextIndex= i + 1; 491 492 if (currMark == RewriteEvent.INSERTED) { 493 TextEditGroup editGroup= getEditGroup(currEvent); 494 ASTNode node= (ASTNode) currEvent.getNewValue(); 495 496 if (separatorState == NONE) { doTextInsert(currPos, getSeparatorString(i - 1), editGroup); separatorState= NEW; 499 } 500 if (separatorState == NEW || insertAfterSeparator(node)) { 501 doTextInsert(currPos, node, getNodeIndent(i), true, editGroup); 503 separatorState= NEW; 504 if (i != lastNonDelete) { 505 if (this.list[nextIndex].getChangeKind() != RewriteEvent.INSERTED) { 506 doTextInsert(currPos, getSeparatorString(i), editGroup); } else { 508 separatorState= NONE; 509 } 510 } 511 } else { doTextInsert(prevEnd, getSeparatorString(i - 1), editGroup); 513 doTextInsert(prevEnd, node, getNodeIndent(i), true, editGroup); 514 } 515 } else if (currMark == RewriteEvent.REMOVED) { 516 ASTNode node= (ASTNode) currEvent.getOriginalValue(); 517 TextEditGroup editGroup= getEditGroup(currEvent); 518 int currEnd= getEndOfNode(node); 519 if (i > lastNonDelete && separatorState == EXISTING) { 520 doTextRemove(prevEnd, currPos - prevEnd, editGroup); doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup); currPos= currEnd; 524 prevEnd= currEnd; 525 } else { 526 int end= getStartOfNextNode(nextIndex, currEnd); doTextRemoveAndVisit(currPos, currEnd - currPos, node, getEditGroup(currEvent)); doTextRemove(currEnd, end - currEnd, editGroup); currPos= end; 531 prevEnd= currEnd; 532 separatorState= NEW; 533 } 534 } else { if (currMark == RewriteEvent.REPLACED) { 536 ASTNode node= (ASTNode) currEvent.getOriginalValue(); 537 int currEnd= getEndOfNode(node); 538 539 TextEditGroup editGroup= getEditGroup(currEvent); 540 ASTNode changed= (ASTNode) currEvent.getNewValue(); 541 doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup); 542 doTextInsert(currPos, changed, getNodeIndent(i), true, editGroup); 543 544 prevEnd= currEnd; 545 } else { ASTNode node= (ASTNode) currEvent.getOriginalValue(); 547 voidVisit(node); 548 } 549 if (i == lastNonInsert) { separatorState= NONE; 551 if (currMark == RewriteEvent.UNCHANGED) { 552 ASTNode node= (ASTNode) currEvent.getOriginalValue(); 553 prevEnd= getEndOfNode(node); 554 } 555 currPos= prevEnd; 556 } else if (this.list[nextIndex].getChangeKind() != RewriteEvent.UNCHANGED) { 557 if (currMark == RewriteEvent.UNCHANGED) { 559 ASTNode node= (ASTNode) currEvent.getOriginalValue(); 560 prevEnd= getEndOfNode(node); 561 } 562 currPos= getStartOfNextNode(nextIndex, prevEnd); separatorState= EXISTING; 564 } 565 } 566 567 } 568 return currPos; 569 } 570 571 } 572 573 private int rewriteRequiredNode(ASTNode parent, StructuralPropertyDescriptor property) { 574 RewriteEvent event= getEvent(parent, property); 575 if (event != null && event.getChangeKind() == RewriteEvent.REPLACED) { 576 ASTNode node= (ASTNode) event.getOriginalValue(); 577 TextEditGroup editGroup= getEditGroup(event); 578 SourceRange range= getExtendedRange(node); 579 int offset= range.getStartPosition(); 580 int length= range.getLength(); 581 doTextRemoveAndVisit(offset, length, node, editGroup); 582 doTextInsert(offset, (ASTNode) event.getNewValue(), getIndent(offset), true, editGroup); 583 return offset + length; 584 } 585 return doVisit(parent, property, 0); 586 } 587 588 private int rewriteNode(ASTNode parent, StructuralPropertyDescriptor property, int offset, Prefix prefix) { 589 RewriteEvent event= getEvent(parent, property); 590 if (event != null) { 591 switch (event.getChangeKind()) { 592 case RewriteEvent.INSERTED: { 593 ASTNode node= (ASTNode) event.getNewValue(); 594 TextEditGroup editGroup= getEditGroup(event); 595 int indent= getIndent(offset); 596 doTextInsert(offset, prefix.getPrefix(indent), editGroup); 597 doTextInsert(offset, node, indent, true, editGroup); 598 return offset; 599 } 600 case RewriteEvent.REMOVED: { 601 ASTNode node= (ASTNode) event.getOriginalValue(); 602 TextEditGroup editGroup= getEditGroup(event); 603 604 int nodeEnd= getExtendedEnd(node); 605 int len= nodeEnd - offset; 607 doTextRemoveAndVisit(offset, len, node, editGroup); 608 return nodeEnd; 609 } 610 case RewriteEvent.REPLACED: { 611 ASTNode node= (ASTNode) event.getOriginalValue(); 612 TextEditGroup editGroup= getEditGroup(event); 613 SourceRange range= getExtendedRange(node); 614 int nodeOffset= range.getStartPosition(); 615 int nodeLen= range.getLength(); 616 doTextRemoveAndVisit(nodeOffset, nodeLen, node, editGroup); 617 doTextInsert(nodeOffset, (ASTNode) event.getNewValue(), getIndent(offset), true, editGroup); 618 return nodeOffset + nodeLen; 619 } 620 } 621 } 622 return doVisit(parent, property, offset); 623 } 624 625 private int rewriteJavadoc(ASTNode node, StructuralPropertyDescriptor property) { 626 int pos= rewriteNode(node, property, node.getStartPosition(), ASTRewriteFormatter.NONE); 627 int changeKind= getChangeKind(node, property); 628 if (changeKind == RewriteEvent.INSERTED) { 629 String indent= getLineDelimiter() + getIndentAtOffset(pos); 630 doTextInsert(pos, indent, getEditGroup(node, property)); 631 } else if (changeKind == RewriteEvent.REMOVED) { 632 try { 633 getScanner().readNext(pos, false); 634 doTextRemove(pos, getScanner().getCurrentStartOffset() - pos, getEditGroup(node, property)); 635 pos= getScanner().getCurrentStartOffset(); 636 } catch (CoreException e) { 637 handleException(e); 638 } 639 } 640 return pos; 641 } 642 643 644 647 private int rewriteBodyNode(ASTNode parent, StructuralPropertyDescriptor property, int offset, int endPos, int indent, BlockContext context) { 648 RewriteEvent event= getEvent(parent, property); 649 if (event != null) { 650 switch (event.getChangeKind()) { 651 case RewriteEvent.INSERTED: { 652 ASTNode node= (ASTNode) event.getNewValue(); 653 TextEditGroup editGroup= getEditGroup(event); 654 655 String [] strings= context.getPrefixAndSuffix(indent, node, this.eventStore); 656 657 doTextInsert(offset, strings[0], editGroup); 658 doTextInsert(offset, node, indent, true, editGroup); 659 doTextInsert(offset, strings[1], editGroup); 660 return offset; 661 } 662 case RewriteEvent.REMOVED: { 663 ASTNode node= (ASTNode) event.getOriginalValue(); 664 if (endPos == -1) { 665 endPos= getExtendedEnd(node); 666 } 667 668 TextEditGroup editGroup= getEditGroup(event); 669 int len= endPos - offset; 671 doTextRemoveAndVisit(offset, len, node, editGroup); 672 return endPos; 673 } 674 case RewriteEvent.REPLACED: { 675 ASTNode node= (ASTNode) event.getOriginalValue(); 676 if (endPos == -1) { 677 endPos= getExtendedEnd(node); 678 } 679 TextEditGroup editGroup= getEditGroup(event); 680 int nodeLen= endPos - offset; 681 682 ASTNode replacingNode= (ASTNode) event.getNewValue(); 683 String [] strings= context.getPrefixAndSuffix(indent, replacingNode, this.eventStore); 684 doTextRemoveAndVisit(offset, nodeLen, node, editGroup); 685 686 String prefix= strings[0]; 687 doTextInsert(offset, prefix, editGroup); 688 String lineInPrefix= getCurrentLine(prefix, prefix.length()); 689 if (prefix.length() != lineInPrefix.length()) { 690 indent= this.formatter.computeIndentUnits(lineInPrefix); 692 } 693 doTextInsert(offset, replacingNode, indent, true, editGroup); 694 doTextInsert(offset, strings[1], editGroup); 695 return endPos; 696 } 697 } 698 } 699 int pos= doVisit(parent, property, offset); 700 if (endPos != -1) { 701 return endPos; 702 } 703 return pos; 704 } 705 706 private int rewriteOptionalQualifier(ASTNode parent, StructuralPropertyDescriptor property, int startPos) { 707 RewriteEvent event= getEvent(parent, property); 708 if (event != null) { 709 switch (event.getChangeKind()) { 710 case RewriteEvent.INSERTED: { 711 ASTNode node= (ASTNode) event.getNewValue(); 712 TextEditGroup editGroup= getEditGroup(event); 713 doTextInsert(startPos, node, getIndent(startPos), true, editGroup); 714 doTextInsert(startPos, ".", editGroup); return startPos; 716 } 717 case RewriteEvent.REMOVED: { 718 try { 719 ASTNode node= (ASTNode) event.getOriginalValue(); 720 TextEditGroup editGroup= getEditGroup(event); 721 <
|