KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > dom > rewrite > ASTRewriteAnalyzer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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  *******************************************************************************/

11 package org.eclipse.jdt.internal.core.dom.rewrite;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.IdentityHashMap JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Map JavaDoc;
18 import java.util.Stack JavaDoc;
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 /**
40  * Infrastructure to support code modifications. Existing code must stay untouched, new code
41  * added with correct formatting, moved code left with the user's formatting / comments.
42  * Idea:
43  * - Get the AST for existing code
44  * - Describe changes
45  * - This visitor analyzes the changes or annotations and generates text edits
46  * (text manipulation API) that describe the required code changes.
47  */

48 public final class ASTRewriteAnalyzer extends ASTVisitor {
49     
50     /**
51      * Internal synonym for deprecated constant AST.JLS2
52      * to alleviate deprecated warnings.
53      * @deprecated
54      */

55     /*package*/ static final int JLS2_INTERNAL = AST.JLS2;
56     
57     TextEdit currentEdit;
58     final RewriteEventStore eventStore; // used from inner classes
59

60     private TokenScanner tokenScanner; // shared scanner
61

62     private final Map JavaDoc sourceCopyInfoToEdit;
63     private final Stack JavaDoc 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     /**
73      * Constructor for ASTRewriteAnalyzer.
74      * @param content the content of the compilation unit to rewrite.
75      * @param lineInfo line information for the content of the compilation unit to rewrite.
76      * @param rootEdit the edit to add all generated edits to
77      * @param eventStore the event store containing the description of changes
78      * @param nodeInfos annotations to nodes, such as if a node is a string placeholder or a copy target
79      * @param comments list of comments of the compilation unit to rewrite (elements of type <code>Comment</code>) or <code>null</code>.
80      * @param options the current jdt.core options (formatting/compliance) or <code>null</code>.
81      * @param extendedSourceRangeComputer the source range computer to use
82      */

83     public ASTRewriteAnalyzer(char[] content, LineInformation lineInfo, String JavaDoc lineDelim, TextEdit rootEdit, RewriteEventStore eventStore, NodeInfoStore nodeInfos, List JavaDoc comments, Map JavaDoc 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 JavaDoc();
91         this.sourceCopyEndNodes= new Stack JavaDoc();
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     /**
117      * Returns the extended source range for a node.
118      *
119      * @return an extended source range (never null)
120      * @since 3.1
121      */

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 JavaDoc getOriginalValue(ASTNode parent, StructuralPropertyDescriptor property) {
203         return this.eventStore.getOriginalValue(parent, property);
204     }
205     
206     private final Object JavaDoc 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 JavaDoc getLineDelimiter() {
215         return this.formatter.getLineDelimiter();
216     }
217     
218     final String JavaDoc createIndentString(int indent) {
219         return this.formatter.createIndentString(indent);
220     }
221     
222     final private String JavaDoc 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 JavaDoc(cont, lineStart, i - lineStart);
232         }
233         return new String JavaDoc();
234     }
235     
236         
237     final String JavaDoc getIndentAtOffset(int pos) {
238         return this.formatter.getIndentString(getIndentOfLine(pos));
239     }
240     
241     final void doTextInsert(int offset, String JavaDoc insertString, TextEditGroup editGroup) {
242         if (insertString.length() > 0) {
243             // bug fix for 95839: problem with inserting at the end of a line comment
244
if (this.lineCommentEndOffsets.isEndOfLineComment(offset, this.content)) {
245                 if (!insertString.startsWith(getLineDelimiter())) {
246                     TextEdit edit= new InsertEdit(offset, getLineDelimiter()); // add a line delimiter
247
addEdit(edit);
248                     if (editGroup != null) {
249                         addEditGroup(editGroup, edit);
250                     }
251                 }
252                 this.lineCommentEndOffsets.remove(offset); // only one line delimiter per line comment required
253
}
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 JavaDoc node= getOriginalValue(parent, property);
296         if (property.isChildProperty() && node != null) {
297             return doVisit((ASTNode) node);
298         } else if (property.isChildListProperty()) {
299             return doVisitList((List JavaDoc) node, offset);
300         }
301         return offset;
302     }
303     
304     private int doVisitList(List JavaDoc list, int offset) {
305         int endPos= offset;
306         for (Iterator JavaDoc 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 JavaDoc node= getOriginalValue(parent, property);
319         if (property.isChildProperty() && node != null) {
320             voidVisit((ASTNode) node);
321         } else if (property.isChildListProperty()) {
322             voidVisitList((List JavaDoc) node);
323         }
324     }
325     
326     private void voidVisitList(List JavaDoc list) {
327         for (Iterator JavaDoc iter= list.iterator(); iter.hasNext();) {
328             doVisit(((ASTNode) iter.next()));
329         }
330     }
331     
332     private final boolean doVisitUnchangedChildren(ASTNode parent) {
333         List JavaDoc 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 JavaDoc 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 JavaDoc 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()); //$NON-NLS-1$
379
}
380     
381     
382     class ListRewriter {
383         protected String JavaDoc 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 JavaDoc 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 JavaDoc keyword, String JavaDoc 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 JavaDoc 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) { // only inserts
472
if (keyword.length() > 0) { // creating a new list -> insert keyword first (e.g. " throws ")
473
TextEditGroup editGroup= getEditGroup(this.list[0]); // first node is insert
474
doTextInsert(offset, keyword, editGroup);
475                 }
476                 currPos= offset;
477             }
478             if (lastNonDelete == -1) { // all removed, set back to start so the keyword is removed as well
479
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) { // element after last existing element (but not first)
497
doTextInsert(currPos, getSeparatorString(i - 1), editGroup); // insert separator
498
separatorState= NEW;
499                     }
500                     if (separatorState == NEW || insertAfterSeparator(node)) {
501                         doTextInsert(currPos, node, getNodeIndent(i), true, editGroup); // insert node
502

503                         separatorState= NEW;
504                         if (i != lastNonDelete) {
505                             if (this.list[nextIndex].getChangeKind() != RewriteEvent.INSERTED) {
506                                 doTextInsert(currPos, getSeparatorString(i), editGroup); // insert separator
507
} else {
508                                 separatorState= NONE;
509                             }
510                         }
511                     } else { // EXISTING && insert before separator
512
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                         // is last, remove previous separator: split delete to allow range copies
521
doTextRemove(prevEnd, currPos - prevEnd, editGroup); // remove separator
522
doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup); // remove node
523
currPos= currEnd;
524                         prevEnd= currEnd;
525                     } else {
526                         // remove element and next separator
527
int end= getStartOfNextNode(nextIndex, currEnd); // start of next
528
doTextRemoveAndVisit(currPos, currEnd - currPos, node, getEditGroup(currEvent)); // remove node
529
doTextRemove(currEnd, end - currEnd, editGroup); // remove separator
530
currPos= end;
531                         prevEnd= currEnd;
532                         separatorState= NEW;
533                     }
534                 } else { // replaced or unchanged
535
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 { // is unchanged
546
ASTNode node= (ASTNode) currEvent.getOriginalValue();
547                         voidVisit(node);
548                     }
549                     if (i == lastNonInsert) { // last node or next nodes are all inserts
550
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                         // no updates needed while nodes are unchanged
558
if (currMark == RewriteEvent.UNCHANGED) {
559                             ASTNode node= (ASTNode) currEvent.getOriginalValue();
560                             prevEnd= getEndOfNode(node);
561                         }
562                         currPos= getStartOfNextNode(nextIndex, prevEnd); // start of next
563
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                     // if there is a prefix, remove the prefix as well
606
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 JavaDoc 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     /*
645      * endpos can be -1 -> use the end pos of the body
646      */

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 JavaDoc[] 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                     // if there is a prefix, remove the prefix as well
670
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 JavaDoc[] strings= context.getPrefixAndSuffix(indent, replacingNode, this.eventStore);
684                     doTextRemoveAndVisit(offset, nodeLen, node, editGroup);
685                     
686                     String JavaDoc prefix= strings[0];
687                     doTextInsert(offset, prefix, editGroup);
688                     String JavaDoc lineInPrefix= getCurrentLine(prefix, prefix.length());
689                     if (prefix.length() != lineInPrefix.length()) {
690                         // prefix contains a new line: update the indent to the one used in the prefix
691
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); //$NON-NLS-1$
715
return startPos;
716                 }
717                 case RewriteEvent.REMOVED: {
718                     try {
719                         ASTNode node= (ASTNode) event.getOriginalValue();
720                         TextEditGroup editGroup= getEditGroup(event);
721                         int dotEnd= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameDOT, node.getStartPosition() + node.getLength());
722                         doTextRemoveAndVisit(startPos, dotEnd - startPos, node, editGroup);
723                         return dotEnd;
724                     } catch (CoreException e) {
725                         handleException(e);
726                     }
727                     break;
728                 }
729                 case RewriteEvent.REPLACED: {
730                     ASTNode node= (ASTNode) event.getOriginalValue();
731                     TextEditGroup editGroup= getEditGroup(event);
732                     SourceRange range= getExtendedRange(node);
733                     int offset= range.getStartPosition();
734                     int length= range.getLength();
735                     
736                     doTextRemoveAndVisit(offset, length, node, editGroup);
737                     doTextInsert(offset, (ASTNode) event.getNewValue(), getIndent(startPos), true, editGroup);
738                     try {
739                         return getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameDOT, offset + length);
740                     } catch (CoreException e) {
741                         handleException(e);
742                     }
743                     break;
744                 }
745             }
746         }
747         Object JavaDoc node= getOriginalValue(parent, property);
748         if (node == null) {
749             return startPos;
750         }
751         int pos= doVisit((ASTNode) node);
752         try {
753             return getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameDOT, pos);
754         } catch (CoreException e) {
755             handleException(e);
756         }
757         return pos;
758     }
759     
760     class ParagraphListRewriter extends ListRewriter {
761         
762         public final static int DEFAULT_SPACING= 1;
763         
764         private int initialIndent;
765         private int separatorLines;
766         
767         public ParagraphListRewriter(int initialIndent, int separator) {
768             this.initialIndent= initialIndent;
769             this.separatorLines= separator;
770         }
771         
772         protected int getInitialIndent() {
773             return this.initialIndent;
774         }
775                         
776         protected String JavaDoc getSeparatorString(int nodeIndex) {
777             int newLines= this.separatorLines == -1 ? getNewLines(nodeIndex) : this.separatorLines;
778             
779             String JavaDoc lineDelim= getLineDelimiter();
780             StringBuffer JavaDoc buf= new StringBuffer JavaDoc(lineDelim);
781             for (int i= 0; i < newLines; i++) {
782                 buf.append(lineDelim);
783             }
784             buf.append(createIndentString(getNodeIndent(nodeIndex + 1)));
785             return buf.toString();
786         }
787         
788         private ASTNode getNode(int nodeIndex) {
789             ASTNode elem= (ASTNode) this.list[nodeIndex].getOriginalValue();
790             if (elem == null) {
791                 elem= (ASTNode) this.list[nodeIndex].getNewValue();
792             }
793             return elem;
794         }
795         
796         private int getNewLines(int nodeIndex) {
797             ASTNode curr= getNode(nodeIndex);
798             ASTNode next= getNode(nodeIndex + 1);
799             
800             int currKind= curr.getNodeType();
801             int nextKind= next.getNodeType();
802
803             ASTNode last= null;
804             ASTNode secondLast= null;
805             for (int i= 0; i < this.list.length; i++) {
806                 ASTNode elem= (ASTNode) this.list[i].getOriginalValue();
807                 if (elem != null) {
808                     if (last != null) {
809                         if (elem.getNodeType() == nextKind && last.getNodeType() == currKind) {
810                             return countEmptyLines(last);
811                         }
812                         secondLast= last;
813                     }
814                     last= elem;
815                 }
816             }
817             if (currKind == ASTNode.FIELD_DECLARATION && nextKind == ASTNode.FIELD_DECLARATION ) {
818                 return 0;
819             }
820             if (secondLast != null) {
821                 return countEmptyLines(secondLast);
822             }
823             return DEFAULT_SPACING;
824         }
825
826         private int countEmptyLines(ASTNode last) {
827             LineInformation lineInformation= getLineInformation();
828             int lastLine= lineInformation.getLineOfOffset(getExtendedEnd(last));
829             if (lastLine >= 0) {
830                 int startLine= lastLine + 1;
831                 int start= lineInformation.getLineOffset(startLine);
832                 if (start < 0) {
833                     return 0;
834                 }
835                 char[] cont= getContent();
836                 int i= start;
837                 while (i < cont.length && ScannerHelper.isWhitespace(cont[i])) {
838                     i++;
839                 }
840                 if (i > start) {
841                     lastLine= lineInformation.getLineOfOffset(i);
842                     if (lastLine > startLine) {
843                         return lastLine - startLine;
844                     }
845                 }
846             }
847             return 0;
848         }
849     }
850         
851     private int rewriteParagraphList(ASTNode parent, StructuralPropertyDescriptor property, int insertPos, int insertIndent, int separator, int lead) {
852         RewriteEvent event= getEvent(parent, property);
853         if (event == null || event.getChangeKind() == RewriteEvent.UNCHANGED) {
854             return doVisit(parent, property, insertPos);
855         }
856         
857         RewriteEvent[] events= event.getChildren();
858         ParagraphListRewriter listRewriter= new ParagraphListRewriter(insertIndent, separator);
859         StringBuffer JavaDoc leadString= new StringBuffer JavaDoc();
860         if (isAllOfKind(events, RewriteEvent.INSERTED)) {
861             for (int i= 0; i < lead; i++) {
862                 leadString.append(getLineDelimiter());
863             }
864             leadString.append(createIndentString(insertIndent));
865         }
866         return listRewriter.rewriteList(parent, property, insertPos, leadString.toString());
867     }
868     
869     private int rewriteOptionalTypeParameters(ASTNode parent, StructuralPropertyDescriptor property, int offset, String JavaDoc keyword, boolean adjustOnNext, boolean needsSpaceOnRemoveAll) {
870         int pos= offset;
871         RewriteEvent event= getEvent(parent, property);
872         if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
873             RewriteEvent[] children= event.getChildren();
874             try {
875                 boolean isAllInserted= isAllOfKind(children, RewriteEvent.INSERTED);
876                 if (isAllInserted && adjustOnNext) {
877                     pos= getScanner().getNextStartOffset(pos, false); // adjust on next element
878
}
879                 boolean isAllRemoved= !isAllInserted && isAllOfKind(children, RewriteEvent.REMOVED);
880                 if (isAllRemoved) { // all removed: set start to left bracket
881
int posBeforeOpenBracket= getScanner().getTokenStartOffset(ITerminalSymbols.TokenNameLESS, pos);
882                     if (posBeforeOpenBracket != pos) {
883                         needsSpaceOnRemoveAll= false;
884                     }
885                     pos= posBeforeOpenBracket;
886                 }
887                 pos= new ListRewriter().rewriteList(parent, property, pos, String.valueOf('<'), ", "); //$NON-NLS-1$
888
if (isAllRemoved) { // all removed: remove right and space up to next element
889
int endPos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameGREATER, pos); // set pos to '>'
890
endPos= getScanner().getNextStartOffset(endPos, false);
891                     String JavaDoc replacement= needsSpaceOnRemoveAll ? String.valueOf(' ') : new String JavaDoc();
892                     doTextReplace(pos, endPos - pos, replacement, getEditGroup(children[children.length - 1]));
893                     return endPos;
894                 } else if (isAllInserted) {
895                     doTextInsert(pos, String.valueOf('>' + keyword), getEditGroup(children[children.length - 1]));
896                     return pos;
897                 }
898             } catch (CoreException e) {
899                 handleException(e);
900             }
901         } else {
902             pos= doVisit(parent, property, pos);
903         }
904         if (pos != offset) { // list contained some type -> parse after closing bracket
905
try {
906                 return getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameGREATER, pos);
907             } catch (CoreException e) {
908                 handleException(e);
909             }
910         }
911         return pos;
912     }
913     
914     private boolean isAllOfKind(RewriteEvent[] children, int kind) {
915         for (int i= 0; i < children.length; i++) {
916             if (children[i].getChangeKind() != kind) {
917                 return false;
918             }
919         }
920         return true;
921     }
922     
923     private int rewriteNodeList(ASTNode parent, StructuralPropertyDescriptor property, int pos, String JavaDoc keyword, String JavaDoc separator) {
924         RewriteEvent event= getEvent(parent, property);
925         if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
926             return new ListRewriter().rewriteList(parent, property, pos, keyword, separator);
927         }
928         return doVisit(parent, property, pos);
929     }
930     
931     private void rewriteMethodBody(MethodDeclaration parent, int startPos) {
932         RewriteEvent event= getEvent(parent, MethodDeclaration.BODY_PROPERTY);
933         if (event != null) {
934             switch (event.getChangeKind()) {
935                 case RewriteEvent.INSERTED: {
936                     int endPos= parent.getStartPosition() + parent.getLength();
937                     TextEditGroup editGroup= getEditGroup(event);
938                     ASTNode body= (ASTNode) event.getNewValue();
939                     doTextRemove(startPos, endPos - startPos, editGroup);
940                     int indent= getIndent(parent.getStartPosition());
941                     String JavaDoc prefix= this.formatter.METHOD_BODY.getPrefix(indent);
942                     doTextInsert(startPos, prefix, editGroup);
943                     doTextInsert(startPos, body, indent, true, editGroup);
944                     return;
945                 }
946                 case RewriteEvent.REMOVED: {
947                     TextEditGroup editGroup= getEditGroup(event);
948                     ASTNode body= (ASTNode) event.getOriginalValue();
949                     int endPos= parent.getStartPosition() + parent.getLength();
950                     doTextRemoveAndVisit(startPos, endPos - startPos, body, editGroup);
951                     doTextInsert(startPos, ";", editGroup); //$NON-NLS-1$
952
return;
953                 }
954                 case RewriteEvent.REPLACED: {
955                     TextEditGroup editGroup= getEditGroup(event);
956                     ASTNode body= (ASTNode) event.getOriginalValue();
957                     doTextRemoveAndVisit(body.getStartPosition(), body.getLength(), body, editGroup);
958                     doTextInsert(body.getStartPosition(), (ASTNode) event.getNewValue(), getIndent(body.getStartPosition()), true, editGroup);
959                     return;
960                 }
961             }
962         }
963         voidVisit(parent, MethodDeclaration.BODY_PROPERTY);
964     }
965     
966     private int rewriteExtraDimensions(ASTNode parent, StructuralPropertyDescriptor property, int pos) {
967         RewriteEvent event= getEvent(parent, property);
968         if (event == null || event.getChangeKind() == RewriteEvent.UNCHANGED) {
969             return ((Integer JavaDoc) getOriginalValue(parent, property)).intValue();
970         }
971         int oldDim= ((Integer JavaDoc) event.getOriginalValue()).intValue();
972         int newDim= ((Integer JavaDoc) event.getNewValue()).intValue();
973         
974         if (oldDim != newDim) {
975             TextEditGroup editGroup= getEditGroup(event);
976             rewriteExtraDimensions(oldDim, newDim, pos, editGroup);
977         }
978         return oldDim;
979     }
980     
981     private void rewriteExtraDimensions(int oldDim, int newDim, int pos, TextEditGroup editGroup) {
982             
983         if (oldDim < newDim) {
984             for (int i= oldDim; i < newDim; i++) {
985                 doTextInsert(pos, "[]", editGroup); //$NON-NLS-1$
986
}
987         } else if (newDim < oldDim) {
988             try {
989                 getScanner().setOffset(pos);
990                 for (int i= newDim; i < oldDim; i++) {
991                     getScanner().readToToken(ITerminalSymbols.TokenNameRBRACKET);
992                 }
993                 doTextRemove(pos, getScanner().getCurrentEndOffset() - pos, editGroup);
994             } catch (CoreException e) {
995                 handleException(e);
996             }
997         }
998     }
999         
1000    /*
1001     * Next token is a left brace. Returns the offset after the brace. For incomplete code, return the start offset.
1002     */

1003    private int getPosAfterLeftBrace(int pos) {
1004        try {
1005            int nextToken= getScanner().readNext(pos, true);
1006            if (nextToken == ITerminalSymbols.TokenNameLBRACE) {
1007                return getScanner().getCurrentEndOffset();
1008            }
1009        } catch (CoreException e) {
1010            handleException(e);
1011        }
1012        return pos;
1013    }
1014    
1015    final int getIndent(int offset) {
1016        return this.formatter.computeIndentUnits(getIndentOfLine(offset));
1017    }
1018
1019    final void doTextInsert(int insertOffset, ASTNode node, int initialIndentLevel, boolean removeLeadingIndent, TextEditGroup editGroup) {
1020        ArrayList JavaDoc markers= new ArrayList JavaDoc();
1021        String JavaDoc formatted= this.formatter.getFormattedResult(node, initialIndentLevel, markers);
1022
1023        
1024        int currPos= 0;
1025        if (removeLeadingIndent) {
1026            while (currPos < formatted.length() && ScannerHelper.isWhitespace(formatted.charAt(currPos))) {
1027                currPos++;
1028            }
1029        }
1030        for (int i= 0; i < markers.size(); i++) { // markers.size can change!
1031
NodeMarker curr= (NodeMarker) markers.get(i);
1032            
1033            int offset= curr.offset;
1034            if (offset != currPos) {
1035                String JavaDoc insertStr= formatted.substring(currPos, offset);
1036                doTextInsert(insertOffset, insertStr, editGroup); // insert until the marker's begin
1037
}
1038
1039            Object JavaDoc data= curr.data;
1040            if (data instanceof TextEditGroup) { // tracking a node
1041
// need to split and create 2 edits as tracking node can surround replaced node.
1042
TextEdit edit= new RangeMarker(insertOffset, 0);
1043                addEditGroup((TextEditGroup) data, edit);
1044                addEdit(edit);
1045                if (curr.length != 0) {
1046                    int end= offset + curr.length;
1047                    int k= i + 1;
1048                    while (k < markers.size() && ((NodeMarker) markers.get(k)).offset < end) {
1049                        k++;
1050                    }
1051                    curr.offset= end;
1052                    curr.length= 0;
1053                    markers.add(k, curr); // add again for end position
1054
}
1055                currPos= offset;
1056            } else {
1057                String JavaDoc destIndentString= this.formatter.getIndentString(getCurrentLine(formatted, offset));
1058                if (data instanceof CopyPlaceholderData) { // replace with a copy/move target
1059
CopySourceInfo copySource= ((CopyPlaceholderData) data).copySource;
1060                    int srcIndentLevel= getIndent(copySource.getNode().getStartPosition());
1061                    TextEdit sourceEdit= getCopySourceEdit(copySource);
1062                    doTextCopy(sourceEdit, insertOffset, srcIndentLevel, destIndentString, editGroup);
1063                    currPos= offset + curr.length; // continue to insert after the replaced string
1064
if (needsNewLineForLineComment(copySource.getNode(), formatted, currPos)) {
1065                        doTextInsert(insertOffset, getLineDelimiter(), editGroup);
1066                    }
1067                } else if (data instanceof StringPlaceholderData) { // replace with a placeholder
1068
String JavaDoc code= ((StringPlaceholderData) data).code;
1069                    String JavaDoc str= this.formatter.changeIndent(code, 0, destIndentString);
1070                    doTextInsert(insertOffset, str, editGroup);
1071                    currPos= offset + curr.length; // continue to insert after the replaced string
1072
}
1073            }
1074
1075        }
1076        if (currPos < formatted.length()) {
1077            String JavaDoc insertStr= formatted.substring(currPos);
1078            doTextInsert(insertOffset, insertStr, editGroup);
1079        }
1080    }
1081    
1082    private boolean needsNewLineForLineComment(ASTNode node, String JavaDoc formatted, int offset) {
1083        if (!this.lineCommentEndOffsets.isEndOfLineComment(getExtendedEnd(node), this.content)) {
1084            return false;
1085        }
1086        // copied code ends with a line comment, but doesn't contain the new line
1087
return offset < formatted.length() && !IndentManipulation.isLineDelimiterChar(formatted.charAt(offset));
1088    }
1089    
1090    private String JavaDoc getCurrentLine(String JavaDoc str, int pos) {
1091        for (int i= pos - 1; i>= 0; i--) {
1092            char ch= str.charAt(i);
1093            if (IndentManipulation.isLineDelimiterChar(ch)) {
1094                return str.substring(i + 1, pos);
1095            }
1096        }
1097        return str.substring(0, pos);
1098    }
1099    
1100
1101    private void rewriteModifiers(ASTNode parent, StructuralPropertyDescriptor property, int offset) {
1102        RewriteEvent event= getEvent(parent, property);
1103        if (event == null || event.getChangeKind() != RewriteEvent.REPLACED) {
1104            return;
1105        }
1106        try {
1107            int oldModifiers= ((Integer JavaDoc) event.getOriginalValue()).intValue();
1108            int newModifiers= ((Integer JavaDoc) event.getNewValue()).intValue();
1109            TextEditGroup editGroup= getEditGroup(event);
1110        
1111            TokenScanner scanner= getScanner();
1112
1113            int tok= scanner.readNext(offset, false);
1114            int startPos= scanner.getCurrentStartOffset();
1115            int nextStart= startPos;
1116            loop: while (true) {
1117                if (TokenScanner.isComment(tok)) {
1118                    tok= scanner.readNext(true); // next non-comment token
1119
}
1120                boolean keep= true;
1121                switch (tok) {
1122                    case ITerminalSymbols.TokenNamepublic: keep= Modifier.isPublic(newModifiers); break;
1123                    case ITerminalSymbols.TokenNameprotected: keep= Modifier.isProtected(newModifiers); break;
1124                    case ITerminalSymbols.TokenNameprivate: keep= Modifier.isPrivate(newModifiers); break;
1125                    case ITerminalSymbols.TokenNamestatic: keep= Modifier.isStatic(newModifiers); break;
1126                    case ITerminalSymbols.TokenNamefinal: keep= Modifier.isFinal(newModifiers); break;
1127                    case ITerminalSymbols.TokenNameabstract: keep= Modifier.isAbstract(newModifiers); break;
1128                    case ITerminalSymbols.TokenNamenative: keep= Modifier.isNative(newModifiers); break;
1129                    case ITerminalSymbols.TokenNamevolatile: keep= Modifier.isVolatile(newModifiers); break;
1130                    case ITerminalSymbols.TokenNamestrictfp: keep= Modifier.isStrictfp(newModifiers); break;
1131                    case ITerminalSymbols.TokenNametransient: keep= Modifier.isTransient(newModifiers); break;
1132                    case ITerminalSymbols.TokenNamesynchronized: keep= Modifier.isSynchronized(newModifiers); break;
1133                    default:
1134                        break loop;
1135                }
1136                tok= getScanner().readNext(false); // include comments
1137
int currPos= nextStart;
1138                nextStart= getScanner().getCurrentStartOffset();
1139                if (!keep) {
1140                    doTextRemove(currPos, nextStart - currPos, editGroup);
1141                }
1142            }
1143            int addedModifiers= newModifiers & ~oldModifiers;
1144            if (addedModifiers != 0) {
1145                if (startPos != nextStart) {
1146                    int visibilityModifiers= addedModifiers & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
1147                    if (visibilityModifiers != 0) {
1148                        StringBuffer JavaDoc buf= new StringBuffer JavaDoc();
1149                        ASTRewriteFlattener.printModifiers(visibilityModifiers, buf);
1150                        doTextInsert(startPos, buf.toString(), editGroup);
1151                        addedModifiers &= ~visibilityModifiers;
1152                    }
1153                }
1154                StringBuffer JavaDoc buf= new StringBuffer JavaDoc();
1155                ASTRewriteFlattener.printModifiers(addedModifiers, buf);
1156                doTextInsert(nextStart, buf.toString(), editGroup);
1157            }
1158        } catch (CoreException e) {
1159            handleException(e);
1160        }
1161    }
1162    
1163    class ModifierRewriter extends ListRewriter {
1164        
1165        private final Prefix annotationSeparation;
1166
1167        public ModifierRewriter(Prefix annotationSeparation) {
1168            this.annotationSeparation= annotationSeparation;
1169        }
1170        
1171        /* (non-Javadoc)
1172         * @see org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.ListRewriter#getSeparatorString(int)
1173         */

1174        protected String JavaDoc getSeparatorString(int nodeIndex) {
1175            ASTNode curr= getNewNode(nodeIndex);
1176            if (curr instanceof Annotation) {
1177                return this.annotationSeparation.getPrefix(getNodeIndent(nodeIndex + 1));
1178            }
1179            return super.getSeparatorString(nodeIndex);
1180        }
1181    }
1182    
1183    
1184    private int rewriteModifiers2(ASTNode node, ChildListPropertyDescriptor property, int pos) {
1185        RewriteEvent event= getEvent(node, property);
1186        if (event == null || event.getChangeKind() == RewriteEvent.UNCHANGED) {
1187            return doVisit(node, property, pos);
1188        }
1189        RewriteEvent[] children= event.getChildren();
1190        boolean isAllInsert= isAllOfKind(children, RewriteEvent.INSERTED);
1191        boolean isAllRemove= isAllOfKind(children, RewriteEvent.REMOVED);
1192        if (isAllInsert || isAllRemove) {
1193            // update pos
1194
try {
1195                pos= getScanner().getNextStartOffset(pos, false);
1196            } catch (CoreException e) {
1197                handleException(e);
1198            }
1199        }
1200        
1201        int endPos= new ModifierRewriter(this.formatter.ANNOTATION_SEPARATION).rewriteList(node, property, pos, "", " "); //$NON-NLS-1$ //$NON-NLS-2$
1202

1203        try {
1204            int nextPos= getScanner().getNextStartOffset(endPos, false);
1205            
1206            boolean lastUnchanged= children[children.length - 1].getChangeKind() != RewriteEvent.UNCHANGED;
1207            
1208            if (isAllRemove) {
1209                doTextRemove(endPos, nextPos - endPos, getEditGroup(children[children.length - 1]));
1210                return nextPos;
1211            } else if (isAllInsert || (nextPos == endPos && lastUnchanged)) { // see bug 165654
1212
RewriteEvent lastChild= children[children.length - 1];
1213                String JavaDoc separator;
1214                if (lastChild.getNewValue() instanceof Annotation) {
1215                    separator= this.formatter.ANNOTATION_SEPARATION.getPrefix(getIndent(pos));
1216                } else {
1217                    separator= String.valueOf(' ');
1218                }
1219                doTextInsert(endPos, separator, getEditGroup(lastChild));
1220            }
1221        } catch (CoreException e) {
1222            handleException(e);
1223        }
1224        return endPos;
1225    }
1226    
1227    
1228    private void replaceOperation(int posBeforeOperation, String JavaDoc newOperation, TextEditGroup editGroup) {
1229        try {
1230            getScanner().readNext(posBeforeOperation, true);
1231            doTextReplace(getScanner().getCurrentStartOffset(), getScanner().getCurrentLength(), newOperation, editGroup);
1232        } catch (CoreException e) {
1233            handleException(e);
1234        }
1235    }
1236    
1237    private void rewriteOperation(ASTNode parent, StructuralPropertyDescriptor property, int posBeforeOperation) {
1238        RewriteEvent event= getEvent(parent, property);
1239        if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
1240            try {
1241                String JavaDoc newOperation= event.getNewValue().toString();
1242                TextEditGroup editGroup= getEditGroup(event);
1243                getScanner().readNext(posBeforeOperation, true);
1244                doTextReplace(getScanner().getCurrentStartOffset(), getScanner().getCurrentLength(), newOperation, editGroup);
1245            } catch (CoreException e) {
1246                handleException(e);
1247            }
1248        }
1249    }
1250    
1251    /* (non-Javadoc)
1252     * @see org.eclipse.jdt.core.dom.ASTVisitor#postVisit(ASTNode)
1253     */

1254    public void postVisit(ASTNode node) {
1255        TextEditGroup editGroup= this.eventStore.getTrackedNodeData(node);
1256        if (editGroup != null) {
1257            this.currentEdit= this.currentEdit.getParent();
1258        }
1259        // remove copy source edits
1260
doCopySourcePostVisit(node, this.sourceCopyEndNodes);
1261    }
1262
1263    /* (non-Javadoc)
1264     * @see org.eclipse.jdt.core.dom.ASTVisitor#preVisit(ASTNode)
1265     */

1266    public void preVisit(ASTNode node) {
1267        // copies, then range marker
1268

1269        CopySourceInfo[] infos= this.eventStore.getNodeCopySources(node);
1270        doCopySourcePreVisit(infos, this.sourceCopyEndNodes);
1271
1272        TextEditGroup editGroup= this.eventStore.getTrackedNodeData(node);
1273        if (editGroup != null) {
1274            SourceRange range= getExtendedRange(node);
1275            int offset= range.getStartPosition();
1276            int length= range.getLength();
1277            TextEdit edit= new RangeMarker(offset, length);
1278            addEditGroup(editGroup, edit);
1279            addEdit(edit);
1280            this.currentEdit= edit;
1281        }
1282    }
1283    
1284    final void doCopySourcePreVisit(CopySourceInfo[] infos, Stack JavaDoc nodeEndStack) {
1285        if (infos != null) {
1286            for (int i= 0; i < infos.length; i++) {
1287                CopySourceInfo curr= infos[i];
1288                TextEdit edit= getCopySourceEdit(curr);
1289                addEdit(edit);
1290                this.currentEdit= edit;
1291                nodeEndStack.push(curr.getNode());
1292            }
1293        }
1294    }
1295    
1296    final void doCopySourcePostVisit(ASTNode node, Stack JavaDoc nodeEndStack) {
1297        while (!nodeEndStack.isEmpty() && nodeEndStack.peek() == node) {
1298            nodeEndStack.pop();
1299            this.currentEdit= this.currentEdit.getParent();
1300        }
1301    }
1302
1303    /* (non-Javadoc)
1304     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(CompilationUnit)
1305     */

1306    public boolean visit(CompilationUnit node) {
1307        if (!hasChildrenChanges(node)) {
1308            return doVisitUnchangedChildren(node);
1309        }
1310        
1311        int startPos= rewriteNode(node, CompilationUnit.PACKAGE_PROPERTY, 0, ASTRewriteFormatter.NONE);
1312            
1313        if (getChangeKind(node, CompilationUnit.PACKAGE_PROPERTY) == RewriteEvent.INSERTED) {
1314            doTextInsert(0, getLineDelimiter(), getEditGroup(node, CompilationUnit.PACKAGE_PROPERTY));
1315        }
1316                
1317        startPos= rewriteParagraphList(node, CompilationUnit.IMPORTS_PROPERTY, startPos, 0, 0, 2);
1318        rewriteParagraphList(node, CompilationUnit.TYPES_PROPERTY, startPos, 0, -1, 2);
1319        return false;
1320    }
1321
1322
1323    /* (non-Javadoc)
1324     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(TypeDeclaration)
1325     */

1326    public boolean visit(TypeDeclaration node) {
1327        if (!hasChildrenChanges(node)) {
1328            return doVisitUnchangedChildren(node);
1329        }
1330        int apiLevel= node.getAST().apiLevel();
1331        
1332        int pos= rewriteJavadoc(node, TypeDeclaration.JAVADOC_PROPERTY);
1333        
1334        if (apiLevel == JLS2_INTERNAL) {
1335            rewriteModifiers(node, TypeDeclaration.MODIFIERS_PROPERTY, pos);
1336        } else {
1337            rewriteModifiers2(node, TypeDeclaration.MODIFIERS2_PROPERTY, pos);
1338        }
1339        
1340        boolean isInterface= ((Boolean JavaDoc) getOriginalValue(node, TypeDeclaration.INTERFACE_PROPERTY)).booleanValue();
1341        // modifiers & class/interface
1342
boolean invertType= isChanged(node, TypeDeclaration.INTERFACE_PROPERTY);
1343        if (invertType) {
1344            try {
1345                int typeToken= isInterface ? ITerminalSymbols.TokenNameinterface : ITerminalSymbols.TokenNameclass;
1346                getScanner().readToToken(typeToken, node.getStartPosition());
1347                
1348                String JavaDoc str= isInterface ? "class" : "interface"; //$NON-NLS-1$ //$NON-NLS-2$
1349
int start= getScanner().getCurrentStartOffset();
1350                int end= getScanner().getCurrentEndOffset();
1351                
1352                doTextReplace(start, end - start, str, getEditGroup(node, TypeDeclaration.INTERFACE_PROPERTY));
1353            } catch (CoreException e) {
1354                // ignore
1355
}
1356        }
1357        
1358        // name
1359
pos= rewriteRequiredNode(node, TypeDeclaration.NAME_PROPERTY);
1360        
1361        if (apiLevel >= AST.JLS3) {
1362            pos= rewriteOptionalTypeParameters(node, TypeDeclaration.TYPE_PARAMETERS_PROPERTY, pos, "", false, true); //$NON-NLS-1$
1363
}
1364        
1365        // superclass
1366
if (!isInterface || invertType) {
1367            ChildPropertyDescriptor superClassProperty= (apiLevel == JLS2_INTERNAL) ? TypeDeclaration.SUPERCLASS_PROPERTY : TypeDeclaration.SUPERCLASS_TYPE_PROPERTY;
1368
1369            RewriteEvent superClassEvent= getEvent(node, superClassProperty);
1370            
1371            int changeKind= superClassEvent != null ? superClassEvent.getChangeKind() : RewriteEvent.UNCHANGED;
1372            switch (changeKind) {
1373                case RewriteEvent.INSERTED: {
1374                    doTextInsert(pos, " extends ", getEditGroup(superClassEvent)); //$NON-NLS-1$
1375
doTextInsert(pos, (ASTNode) superClassEvent.getNewValue(), 0, false, getEditGroup(superClassEvent));
1376                    break;
1377                }
1378                case RewriteEvent.REMOVED: {
1379                    ASTNode superClass= (ASTNode) superClassEvent.getOriginalValue();
1380                    int endPos= getExtendedEnd(superClass);
1381                    doTextRemoveAndVisit(pos, endPos - pos, superClass, getEditGroup(superClassEvent));
1382                    pos= endPos;
1383                    break;
1384                }
1385                case RewriteEvent.REPLACED: {
1386                    ASTNode superClass= (ASTNode) superClassEvent.getOriginalValue();
1387                    SourceRange range= getExtendedRange(superClass);
1388                    int offset= range.getStartPosition();
1389                    int length= range.getLength();
1390                    doTextRemoveAndVisit(offset, length, superClass, getEditGroup(superClassEvent));
1391                    doTextInsert(offset, (ASTNode) superClassEvent.getNewValue(), 0, false, getEditGroup(superClassEvent));
1392                    pos= offset + length;
1393                    break;
1394                }
1395                case RewriteEvent.UNCHANGED: {
1396                    pos= doVisit(node, superClassProperty, pos);
1397                }
1398            }
1399        }
1400        // extended interfaces
1401
ChildListPropertyDescriptor superInterfaceProperty= (apiLevel == JLS2_INTERNAL) ? TypeDeclaration.SUPER_INTERFACES_PROPERTY : TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY;
1402
1403        RewriteEvent interfaceEvent= getEvent(node, superInterfaceProperty);
1404        if (interfaceEvent == null || interfaceEvent.getChangeKind() == RewriteEvent.UNCHANGED) {
1405            if (invertType) {
1406                List JavaDoc originalNodes= (List JavaDoc) getOriginalValue(node, superInterfaceProperty);
1407                if (!originalNodes.isEmpty()) {
1408                    String JavaDoc keyword= isInterface ? " implements " : " extends "; //$NON-NLS-1$ //$NON-NLS-2$
1409
ASTNode firstNode= (ASTNode) originalNodes.get(0);
1410                    doTextReplace(pos, firstNode.getStartPosition() - pos, keyword, getEditGroup(node, TypeDeclaration.INTERFACE_PROPERTY));
1411                }
1412            }
1413            pos= doVisit(node, superInterfaceProperty, pos);
1414        } else {
1415            String JavaDoc keyword= (isInterface == invertType) ? " implements " : " extends "; //$NON-NLS-1$ //$NON-NLS-2$
1416
if (invertType) {
1417                List JavaDoc newNodes= (List JavaDoc) interfaceEvent.getNewValue();
1418                if (!newNodes.isEmpty()) {
1419                    List JavaDoc origNodes= (List JavaDoc) interfaceEvent.getOriginalValue();
1420                    int firstStart= pos;
1421                    if (!origNodes.isEmpty()) {
1422                        firstStart= ((ASTNode) origNodes.get(0)).getStartPosition();
1423                    }
1424                    doTextReplace(pos, firstStart - pos, keyword, getEditGroup(node, TypeDeclaration.INTERFACE_PROPERTY));
1425                    keyword= ""; //$NON-NLS-1$
1426
pos= firstStart;
1427                }
1428            }
1429            pos= rewriteNodeList(node, superInterfaceProperty, pos, keyword, ", "); //$NON-NLS-1$
1430
}
1431        
1432        // type members
1433
// startPos : find position after left brace of type, be aware that bracket might be missing
1434
int startIndent= getIndent(node.getStartPosition()) + 1;
1435        int startPos= getPosAfterLeftBrace(pos);
1436        rewriteParagraphList(node, TypeDeclaration.BODY_DECLARATIONS_PROPERTY, startPos, startIndent, -1, 2);
1437        return false;
1438    }
1439
1440    private void rewriteReturnType(MethodDeclaration node, boolean isConstructor, boolean isConstructorChange) {
1441        ChildPropertyDescriptor property= (node.getAST().apiLevel() == JLS2_INTERNAL) ? MethodDeclaration.RETURN_TYPE_PROPERTY : MethodDeclaration.RETURN_TYPE2_PROPERTY;
1442
1443        // weakness in the AST: return type can exist, even if missing in source
1444
ASTNode originalReturnType= (ASTNode) getOriginalValue(node, property);
1445        boolean returnTypeExists= originalReturnType != null && originalReturnType.getStartPosition() != -1;
1446        if (!isConstructorChange && returnTypeExists) {
1447            rewriteRequiredNode(node, property);
1448            return;
1449        }
1450        // difficult cases: return type insert or remove
1451
ASTNode newReturnType= (ASTNode) getNewValue(node, property);
1452        if (isConstructorChange || !returnTypeExists && newReturnType != originalReturnType) {
1453            // use the start offset of the method name to insert
1454
ASTNode originalMethodName= (ASTNode) getOriginalValue(node, MethodDeclaration.NAME_PROPERTY);
1455            int nextStart= originalMethodName.getStartPosition(); // see bug 84049: can't use extended offset
1456
TextEditGroup editGroup= getEditGroup(node, property);
1457            if (isConstructor || !returnTypeExists) { // insert
1458
doTextInsert(nextStart, newReturnType, getIndent(nextStart), true, editGroup);
1459                doTextInsert(nextStart, " ", editGroup); //$NON-NLS-1$
1460
} else { // remove up to the method name
1461
int offset= getExtendedOffset(originalReturnType);
1462                doTextRemoveAndVisit(offset, nextStart - offset, originalReturnType, editGroup);
1463            }
1464        }
1465    }
1466    
1467    
1468    /* (non-Javadoc)
1469     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(MethodDeclaration)
1470     */

1471    public boolean visit(MethodDeclaration node) {
1472        if (!hasChildrenChanges(node)) {
1473            return doVisitUnchangedChildren(node);
1474        }
1475        int pos= rewriteJavadoc(node, MethodDeclaration.JAVADOC_PROPERTY);
1476        if (node.getAST().apiLevel() == JLS2_INTERNAL) {
1477            rewriteModifiers(node, MethodDeclaration.MODIFIERS_PROPERTY, pos);
1478        } else {
1479            pos= rewriteModifiers2(node, MethodDeclaration.MODIFIERS2_PROPERTY, pos);
1480            pos= rewriteOptionalTypeParameters(node, MethodDeclaration.TYPE_PARAMETERS_PROPERTY, pos, " ", true, pos != node.getStartPosition()); //$NON-NLS-1$
1481
}
1482        
1483        boolean isConstructorChange= isChanged(node, MethodDeclaration.CONSTRUCTOR_PROPERTY);
1484        boolean isConstructor= ((Boolean JavaDoc) getOriginalValue(node, MethodDeclaration.CONSTRUCTOR_PROPERTY)).booleanValue();
1485        if (!isConstructor || isConstructorChange) {
1486            rewriteReturnType(node, isConstructor, isConstructorChange);
1487        }
1488        // method name
1489
pos= rewriteRequiredNode(node, MethodDeclaration.NAME_PROPERTY);
1490        
1491        // parameters
1492
try {
1493            if (isChanged(node, MethodDeclaration.PARAMETERS_PROPERTY)) {
1494                pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, pos);
1495                pos= rewriteNodeList(node, MethodDeclaration.PARAMETERS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
1496
} else {
1497                pos= doVisit(node, MethodDeclaration.PARAMETERS_PROPERTY, pos);
1498            }
1499            
1500            pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRPAREN, pos);
1501            
1502            int extraDims= rewriteExtraDimensions(node, MethodDeclaration.EXTRA_DIMENSIONS_PROPERTY, pos);
1503            
1504            boolean hasExceptionChanges= isChanged(node, MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY);
1505            
1506            int bodyChangeKind= getChangeKind(node, MethodDeclaration.BODY_PROPERTY);
1507            
1508            if ((extraDims > 0) && (hasExceptionChanges || bodyChangeKind == RewriteEvent.INSERTED || bodyChangeKind == RewriteEvent.REMOVED)) {
1509                int dim= ((Integer JavaDoc) getOriginalValue(node, MethodDeclaration.EXTRA_DIMENSIONS_PROPERTY)).intValue();
1510                while (dim > 0) {
1511                    pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRBRACKET, pos);
1512                    dim--;
1513                }
1514            }
1515            
1516            pos= rewriteNodeList(node, MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY, pos, " throws ", ", "); //$NON-NLS-1$ //$NON-NLS-2$
1517
rewriteMethodBody(node, pos);
1518        } catch (CoreException e) {
1519            // ignore
1520
}
1521        return false;
1522    }
1523    
1524    /* (non-Javadoc)
1525     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(Block)
1526     */

1527    public boolean visit(Block node) {
1528        if (!hasChildrenChanges(node)) {
1529            return doVisitUnchangedChildren(node);
1530        }
1531        
1532        int startPos;
1533        if (isCollapsed(node)) {
1534            startPos= node.getStartPosition();
1535        } else {
1536            startPos= getPosAfterLeftBrace(node.getStartPosition());
1537        }
1538        int startIndent= getIndent(node.getStartPosition()) + 1;
1539        rewriteParagraphList(node, Block.STATEMENTS_PROPERTY, startPos, startIndent, 0, 1);
1540        return false;
1541    }
1542    
1543    /* (non-Javadoc)
1544     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ReturnStatement)
1545     */

1546    public boolean visit(ReturnStatement node) {
1547        if (!hasChildrenChanges(node)) {
1548            return doVisitUnchangedChildren(node);
1549        }
1550        
1551        try {
1552            int offset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNamereturn, node.getStartPosition());
1553            ensureSpaceBeforeReplace(node, ReturnStatement.EXPRESSION_PROPERTY, offset, 0);
1554            
1555            rewriteNode(node, ReturnStatement.EXPRESSION_PROPERTY, offset, ASTRewriteFormatter.SPACE);
1556        } catch (CoreException e) {
1557            handleException(e);
1558        }
1559        return false;
1560    }
1561    
1562
1563    /* (non-Javadoc)
1564     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(AnonymousClassDeclaration)
1565     */

1566    public boolean visit(AnonymousClassDeclaration node) {
1567        if (!hasChildrenChanges(node)) {
1568            return doVisitUnchangedChildren(node);
1569        }
1570        
1571        int startPos= getPosAfterLeftBrace(node.getStartPosition());
1572        int startIndent= getIndent(node.getStartPosition()) + 1;
1573        rewriteParagraphList(node, AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY, startPos, startIndent, -1, 2);
1574        return false;
1575    }
1576
1577    /* (non-Javadoc)
1578     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ArrayAccess)
1579     */

1580    public boolean visit(ArrayAccess node) {
1581        if (!hasChildrenChanges(node)) {
1582            return doVisitUnchangedChildren(node);
1583        }
1584        
1585        rewriteRequiredNode(node, ArrayAccess.ARRAY_PROPERTY);
1586        rewriteRequiredNode(node, ArrayAccess.INDEX_PROPERTY);
1587        return false;
1588    }
1589
1590    /* (non-Javadoc)
1591     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ArrayCreation)
1592     */

1593    public boolean visit(ArrayCreation node) {
1594        if (!hasChildrenChanges(node)) {
1595            return doVisitUnchangedChildren(node);
1596        }
1597        
1598        ArrayType arrayType= (ArrayType) getOriginalValue(node, ArrayCreation.TYPE_PROPERTY);
1599        int nOldBrackets= getDimensions(arrayType); // number of total brackets
1600
int nNewBrackets= nOldBrackets;
1601        
1602        TextEditGroup editGroup= null;
1603        RewriteEvent typeEvent= getEvent(node, ArrayCreation.TYPE_PROPERTY);
1604        if (typeEvent != null && typeEvent.getChangeKind() == RewriteEvent.REPLACED) { // changed arraytype can have different dimension or type name
1605
ArrayType replacingType= (ArrayType) typeEvent.getNewValue();
1606            editGroup= getEditGroup(typeEvent);
1607            Type newType= replacingType.getElementType();
1608            Type oldType= getElementType(arrayType);
1609            if (!newType.equals(oldType)) {
1610                SourceRange range= getExtendedRange(oldType);
1611                int offset= range.getStartPosition();
1612                int length= range.getLength();
1613                doTextRemove(offset, length, editGroup);
1614                doTextInsert(offset, newType, 0, false, editGroup);
1615            }
1616            nNewBrackets= replacingType.getDimensions(); // is replaced type
1617
}
1618        voidVisit(arrayType);
1619        
1620
1621        try {
1622            int offset= getScanner().getTokenStartOffset(ITerminalSymbols.TokenNameLBRACKET, arrayType.getStartPosition());
1623            // dimension node with expressions
1624
RewriteEvent dimEvent= getEvent(node, ArrayCreation.DIMENSIONS_PROPERTY);
1625            boolean hasDimensionChanges= (dimEvent != null && dimEvent.getChangeKind() != RewriteEvent.UNCHANGED);
1626            if (hasDimensionChanges) {
1627                RewriteEvent[] events= dimEvent.getChildren();
1628                // offset on first opening brace
1629
for (int i= 0; i < events.length; i++) {
1630                    RewriteEvent event= events[i];
1631                    int changeKind= event.getChangeKind();
1632                    if (changeKind == RewriteEvent.INSERTED) { // insert new dimension
1633
editGroup= getEditGroup(event);
1634                        doTextInsert(offset, "[", editGroup); //$NON-NLS-1$
1635
doTextInsert(offset, (ASTNode) event.getNewValue(), 0, false, editGroup);
1636                        doTextInsert(offset, "]", editGroup); //$NON-NLS-1$
1637
nNewBrackets--;
1638                    } else {
1639                        ASTNode elem= (ASTNode) event.getOriginalValue();
1640                        int elemEnd= elem.getStartPosition() + elem.getLength();
1641                        int endPos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRBRACKET, elemEnd);
1642                        if (changeKind == RewriteEvent.REMOVED) {
1643                            editGroup= getEditGroup(event);
1644                            doTextRemoveAndVisit(offset, endPos - offset, elem, editGroup);
1645                        } else if (changeKind == RewriteEvent.REPLACED) {
1646                            editGroup= getEditGroup(event);
1647                            SourceRange range= getExtendedRange(elem);
1648                            int elemOffset= range.getStartPosition();
1649                            int elemLength= range.getLength();
1650                            doTextRemoveAndVisit(elemOffset, elemLength, elem, editGroup);
1651                            doTextInsert(elemOffset, (ASTNode) event.getNewValue(), 0, false, editGroup);
1652                            nNewBrackets--;
1653                        } else {
1654                            voidVisit(elem);
1655                            nNewBrackets--;
1656                        }
1657                        offset= endPos;
1658                        nOldBrackets--;
1659                    }
1660                }
1661            } else {
1662                offset= doVisit(node, ArrayCreation.DIMENSIONS_PROPERTY, offset);
1663            }
1664            if (nOldBrackets != nNewBrackets) {
1665                if (!hasDimensionChanges) {
1666                    offset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRBRACKET, offset);
1667                }
1668                rewriteExtraDimensions(nOldBrackets, nNewBrackets, offset, editGroup);
1669            }
1670                
1671            int kind= getChangeKind(node, ArrayCreation.INITIALIZER_PROPERTY);
1672            if (kind == RewriteEvent.REMOVED) {
1673                offset= getScanner().getPreviousTokenEndOffset(ITerminalSymbols.TokenNameLBRACE, offset);
1674            } else {
1675                offset= node.getStartPosition() + node.getLength(); // insert pos
1676
}
1677            rewriteNode(node, ArrayCreation.INITIALIZER_PROPERTY, offset, ASTRewriteFormatter.SPACE);
1678        } catch (CoreException e) {
1679            handleException(e);
1680        }
1681        return false;
1682    }
1683    
1684    private Type getElementType(ArrayType parent) {
1685        Type t = (Type) getOriginalValue(parent, ArrayType.COMPONENT_TYPE_PROPERTY);
1686        while (t.isArrayType()) {
1687            t = (Type) getOriginalValue(t, ArrayType.COMPONENT_TYPE_PROPERTY);
1688        }
1689        return t;
1690    }
1691    
1692    private int getDimensions(ArrayType parent) {
1693        Type t = (Type) getOriginalValue(parent, ArrayType.COMPONENT_TYPE_PROPERTY);
1694        int dimensions = 1; // always include this array type
1695
while (t.isArrayType()) {
1696            dimensions++;
1697            t = (Type) getOriginalValue(t, ArrayType.COMPONENT_TYPE_PROPERTY);
1698        }
1699        return dimensions;
1700    }
1701
1702    /* (non-Javadoc)
1703     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ArrayInitializer)
1704     */

1705    public boolean visit(ArrayInitializer node) {
1706        if (!hasChildrenChanges(node)) {
1707            return doVisitUnchangedChildren(node);
1708        }
1709
1710        int startPos= getPosAfterLeftBrace(node.getStartPosition());
1711        rewriteNodeList(node, ArrayInitializer.EXPRESSIONS_PROPERTY, startPos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
1712
return false;
1713    }
1714
1715
1716
1717    /* (non-Javadoc)
1718     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ArrayType)
1719     */

1720    public boolean visit(ArrayType node) {
1721        if (!hasChildrenChanges(node)) {
1722            return doVisitUnchangedChildren(node);
1723        }
1724        
1725        rewriteRequiredNode(node, ArrayType.COMPONENT_TYPE_PROPERTY);
1726        return false;
1727    }
1728
1729    /* (non-Javadoc)
1730     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(AssertStatement)
1731     */

1732    public boolean visit(AssertStatement node) {
1733        if (!hasChildrenChanges(node)) {
1734            return doVisitUnchangedChildren(node);
1735        }
1736        
1737        ensureSpaceBeforeReplace(node, AssertStatement.EXPRESSION_PROPERTY, node.getStartPosition(), 1);
1738        int offset= rewriteRequiredNode(node, AssertStatement.EXPRESSION_PROPERTY);
1739        rewriteNode(node, AssertStatement.MESSAGE_PROPERTY, offset, ASTRewriteFormatter.ASSERT_COMMENT);
1740        return false;
1741    }
1742
1743    /* (non-Javadoc)
1744     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(Assignment)
1745     */

1746    public boolean visit(Assignment node) {
1747        if (!hasChildrenChanges(node)) {
1748            return doVisitUnchangedChildren(node);
1749        }
1750        
1751        int pos= rewriteRequiredNode(node, Assignment.LEFT_HAND_SIDE_PROPERTY);
1752        rewriteOperation(node, Assignment.OPERATOR_PROPERTY, pos);
1753        rewriteRequiredNode(node, Assignment.RIGHT_HAND_SIDE_PROPERTY);
1754        return false;
1755    }
1756
1757    /* (non-Javadoc)
1758     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(BooleanLiteral)
1759     */

1760    public boolean visit(BooleanLiteral node) {
1761        if (!hasChildrenChanges(node)) {
1762            return doVisitUnchangedChildren(node);
1763        }
1764        
1765        Boolean JavaDoc newLiteral= (Boolean JavaDoc) getNewValue(node, BooleanLiteral.BOOLEAN_VALUE_PROPERTY);
1766        TextEditGroup group = getEditGroup(node, BooleanLiteral.BOOLEAN_VALUE_PROPERTY);
1767        doTextReplace(node.getStartPosition(), node.getLength(), newLiteral.toString(), group);
1768        return false;
1769    }
1770
1771    /* (non-Javadoc)
1772     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(BreakStatement)
1773     */

1774    public boolean visit(BreakStatement node) {
1775        if (!hasChildrenChanges(node)) {
1776            return doVisitUnchangedChildren(node);
1777        }
1778
1779        try {
1780            int offset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNamebreak, node.getStartPosition());
1781            rewriteNode(node, BreakStatement.LABEL_PROPERTY, offset, ASTRewriteFormatter.SPACE); // space between break and label
1782
} catch (CoreException e) {
1783            handleException(e);
1784        }
1785        return false;
1786    }
1787
1788    /* (non-Javadoc)
1789     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(CastExpression)
1790     */

1791    public boolean visit(CastExpression node) {
1792        if (!hasChildrenChanges(node)) {
1793            return doVisitUnchangedChildren(node);
1794        }
1795        
1796        rewriteRequiredNode(node, CastExpression.TYPE_PROPERTY);
1797        rewriteRequiredNode(node, CastExpression.EXPRESSION_PROPERTY);
1798        return false;
1799    }
1800
1801    /* (non-Javadoc)
1802     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(CatchClause)
1803     */

1804    public boolean visit(CatchClause node) { // catch (Exception) Block
1805
if (!hasChildrenChanges(node)) {
1806            return doVisitUnchangedChildren(node);
1807        }
1808        
1809        rewriteRequiredNode(node, CatchClause.EXCEPTION_PROPERTY);
1810        rewriteRequiredNode(node, CatchClause.BODY_PROPERTY);
1811        return false;
1812    }
1813
1814    /* (non-Javadoc)
1815     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(CharacterLiteral)
1816     */

1817    public boolean visit(CharacterLiteral node) {
1818        if (!hasChildrenChanges(node)) {
1819            return doVisitUnchangedChildren(node);
1820        }
1821        
1822        String JavaDoc escapedSeq= (String JavaDoc) getNewValue(node, CharacterLiteral.ESCAPED_VALUE_PROPERTY);
1823        TextEditGroup group = getEditGroup(node, CharacterLiteral.ESCAPED_VALUE_PROPERTY);
1824        doTextReplace(node.getStartPosition(), node.getLength(), escapedSeq, group);
1825        return false;
1826    }
1827
1828    /* (non-Javadoc)
1829     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ClassInstanceCreation)
1830     */

1831    public boolean visit(ClassInstanceCreation node) {
1832        if (!hasChildrenChanges(node)) {
1833            return doVisitUnchangedChildren(node);
1834        }
1835        
1836        int pos= rewriteOptionalQualifier(node, ClassInstanceCreation.EXPRESSION_PROPERTY, node.getStartPosition());
1837        if (node.getAST().apiLevel() == JLS2_INTERNAL) {
1838            pos= rewriteRequiredNode(node, ClassInstanceCreation.NAME_PROPERTY);
1839        } else {
1840            if (isChanged(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY)) {
1841                try {
1842                    pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNamenew, pos); //after 'new'
1843
rewriteOptionalTypeParameters(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY, pos, " ", true, true); //$NON-NLS-1$
1844
} catch (CoreException e) {
1845                    handleException(e);
1846                }
1847            } else {
1848                voidVisit(node, ClassInstanceCreation.TYPE_ARGUMENTS_PROPERTY);
1849            }
1850            pos= rewriteRequiredNode(node, ClassInstanceCreation.TYPE_PROPERTY);
1851        }
1852
1853        if (isChanged(node, ClassInstanceCreation.ARGUMENTS_PROPERTY)) {
1854            try {
1855                int startpos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, pos);
1856                rewriteNodeList(node, ClassInstanceCreation.ARGUMENTS_PROPERTY, startpos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
1857
} catch (CoreException e) {
1858                handleException(e);
1859            }
1860        } else {
1861            voidVisit(node, ClassInstanceCreation.ARGUMENTS_PROPERTY);
1862        }
1863        
1864        int kind= getChangeKind(node, ClassInstanceCreation.ANONYMOUS_CLASS_DECLARATION_PROPERTY);
1865        if (kind == RewriteEvent.REMOVED) {
1866            try {
1867                pos= getScanner().getPreviousTokenEndOffset(ITerminalSymbols.TokenNameLBRACE, pos);
1868            } catch (CoreException e) {
1869                handleException(e);
1870            }
1871        } else {
1872            pos= node.getStartPosition() + node.getLength(); // insert pos
1873
}
1874        rewriteNode(node, ClassInstanceCreation.ANONYMOUS_CLASS_DECLARATION_PROPERTY, pos, ASTRewriteFormatter.SPACE);
1875        return false;
1876    }
1877
1878    /* (non-Javadoc)
1879     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ConditionalExpression)
1880     */

1881    public boolean visit(ConditionalExpression node) { // expression ? thenExpression : elseExpression
1882
if (!hasChildrenChanges(node)) {
1883            return doVisitUnchangedChildren(node);
1884        }
1885        
1886        rewriteRequiredNode(node, ConditionalExpression.EXPRESSION_PROPERTY);
1887        rewriteRequiredNode(node, ConditionalExpression.THEN_EXPRESSION_PROPERTY);
1888        rewriteRequiredNode(node, ConditionalExpression.ELSE_EXPRESSION_PROPERTY);
1889        return false;
1890    }
1891
1892    /* (non-Javadoc)
1893     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ConstructorInvocation)
1894     */

1895    public boolean visit(ConstructorInvocation node) {
1896        if (!hasChildrenChanges(node)) {
1897            return doVisitUnchangedChildren(node);
1898        }
1899        int pos= node.getStartPosition();
1900        if (node.getAST().apiLevel() >= AST.JLS3) {
1901            pos= rewriteOptionalTypeParameters(node, ConstructorInvocation.TYPE_ARGUMENTS_PROPERTY, pos, "", false, false); //$NON-NLS-1$
1902
}
1903        try {
1904            pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, pos);
1905            rewriteNodeList(node, ConstructorInvocation.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
1906
} catch (CoreException e) {
1907            handleException(e);
1908        }
1909        return false;
1910    }
1911
1912    /* (non-Javadoc)
1913     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ContinueStatement)
1914     */

1915    public boolean visit(ContinueStatement node) {
1916        if (!hasChildrenChanges(node)) {
1917            return doVisitUnchangedChildren(node);
1918        }
1919        
1920        try {
1921            int offset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNamecontinue, node.getStartPosition());
1922            rewriteNode(node, ContinueStatement.LABEL_PROPERTY, offset, ASTRewriteFormatter.SPACE); // space between continue and label
1923
} catch (CoreException e) {
1924            handleException(e);
1925        }
1926        return false;
1927    }
1928
1929    /* (non-Javadoc)
1930     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(DoStatement)
1931     */

1932    public boolean visit(DoStatement node) { // do statement while expression
1933
if (!hasChildrenChanges(node)) {
1934            return doVisitUnchangedChildren(node);
1935        }
1936        
1937        int pos= node.getStartPosition();
1938        try {
1939            RewriteEvent event= getEvent(node, DoStatement.BODY_PROPERTY);
1940            if (event != null && event.getChangeKind() == RewriteEvent.REPLACED) {
1941                int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNamedo, pos);
1942                ASTNode body= (ASTNode) event.getOriginalValue();
1943                int bodyEnd= body.getStartPosition() + body.getLength();
1944                int endPos= getScanner().getTokenStartOffset(ITerminalSymbols.TokenNamewhile, bodyEnd);
1945                rewriteBodyNode(node, DoStatement.BODY_PROPERTY, startOffset, endPos, getIndent(node.getStartPosition()), this.formatter.DO_BLOCK); // body
1946
} else {
1947                voidVisit(node, DoStatement.BODY_PROPERTY);
1948            }
1949        } catch (CoreException e) {
1950            handleException(e);
1951        }
1952
1953        rewriteRequiredNode(node, DoStatement.EXPRESSION_PROPERTY);
1954        return false;
1955    }
1956
1957    /* (non-Javadoc)
1958     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(EmptyStatement)
1959     */

1960    public boolean visit(EmptyStatement node) {
1961        if (!hasChildrenChanges(node)) {
1962            return doVisitUnchangedChildren(node);
1963        }
1964        
1965        changeNotSupported(node); // no modification possible
1966
return false;
1967    }
1968
1969    /* (non-Javadoc)
1970     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ExpressionStatement)
1971     */

1972    public boolean visit(ExpressionStatement node) { // expression
1973
if (!hasChildrenChanges(node)) {
1974            return doVisitUnchangedChildren(node);
1975        }
1976        
1977        rewriteRequiredNode(node, ExpressionStatement.EXPRESSION_PROPERTY);
1978        return false;
1979    }
1980
1981    /* (non-Javadoc)
1982     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(FieldAccess)
1983     */

1984    public boolean visit(FieldAccess node) { // expression.name
1985
if (!hasChildrenChanges(node)) {
1986            return doVisitUnchangedChildren(node);
1987        }
1988        
1989        rewriteRequiredNode(node, FieldAccess.EXPRESSION_PROPERTY); // expression
1990
rewriteRequiredNode(node, FieldAccess.NAME_PROPERTY); // name
1991
return false;
1992    }
1993
1994    /* (non-Javadoc)
1995     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(FieldDeclaration)
1996     */

1997    public boolean visit(FieldDeclaration node) { //{ Modifier } Type VariableDeclarationFragment { ',' VariableDeclarationFragment } ';'
1998
if (!hasChildrenChanges(node)) {
1999            return doVisitUnchangedChildren(node);
2000        }
2001        int pos= rewriteJavadoc(node, FieldDeclaration.JAVADOC_PROPERTY);
2002
2003        if (node.getAST().apiLevel() == JLS2_INTERNAL) {
2004            rewriteModifiers(node, FieldDeclaration.MODIFIERS_PROPERTY, pos);
2005        } else {
2006            rewriteModifiers2(node, FieldDeclaration.MODIFIERS2_PROPERTY, pos);
2007        }
2008        
2009        pos= rewriteRequiredNode(node, FieldDeclaration.TYPE_PROPERTY);
2010        rewriteNodeList(node, FieldDeclaration.FRAGMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
2011
return false;
2012    }
2013
2014    /* (non-Javadoc)
2015     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ForStatement)
2016     */

2017    public boolean visit(ForStatement node) {
2018        if (!hasChildrenChanges(node)) {
2019            return doVisitUnchangedChildren(node);
2020        }
2021        
2022        try {
2023            int pos= node.getStartPosition();
2024            
2025            if (isChanged(node, ForStatement.INITIALIZERS_PROPERTY)) {
2026                // position after opening parent
2027
int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, pos);
2028                pos= rewriteNodeList(node, ForStatement.INITIALIZERS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
2029
} else {
2030                pos= doVisit(node, ForStatement.INITIALIZERS_PROPERTY, pos);
2031            }
2032            
2033            // position after first semicolon
2034
pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameSEMICOLON, pos);
2035            
2036            pos= rewriteNode(node, ForStatement.EXPRESSION_PROPERTY, pos, ASTRewriteFormatter.NONE);
2037            
2038            if (isChanged(node, ForStatement.UPDATERS_PROPERTY)) {
2039                int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameSEMICOLON, pos);
2040                pos= rewriteNodeList(node, ForStatement.UPDATERS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
2041
} else {
2042                pos= doVisit(node, ForStatement.UPDATERS_PROPERTY, pos);
2043            }
2044
2045            RewriteEvent bodyEvent= getEvent(node, ForStatement.BODY_PROPERTY);
2046            if (bodyEvent != null && bodyEvent.getChangeKind() == RewriteEvent.REPLACED) {
2047                int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRPAREN, pos);
2048                rewriteBodyNode(node, ForStatement.BODY_PROPERTY, startOffset, -1, getIndent(node.getStartPosition()), this.formatter.FOR_BLOCK); // body
2049
} else {
2050                voidVisit(node, ForStatement.BODY_PROPERTY);
2051            }
2052            
2053        } catch (CoreException e) {
2054            handleException(e);
2055        }
2056            
2057        
2058        return false;
2059    }
2060
2061    /* (non-Javadoc)
2062     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(IfStatement)
2063     */

2064    public boolean visit(IfStatement node) {
2065        if (!hasChildrenChanges(node)) {
2066            return doVisitUnchangedChildren(node);
2067        }
2068        
2069        int pos= rewriteRequiredNode(node, IfStatement.EXPRESSION_PROPERTY); // statement
2070

2071        RewriteEvent thenEvent= getEvent(node, IfStatement.THEN_STATEMENT_PROPERTY);
2072        int elseChange= getChangeKind(node, IfStatement.ELSE_STATEMENT_PROPERTY);
2073
2074        if (thenEvent != null && thenEvent.getChangeKind() != RewriteEvent.UNCHANGED) {
2075            try {
2076                pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRPAREN, pos); // after the closing parent
2077
int indent= getIndent(node.getStartPosition());
2078                
2079                int endPos= -1;
2080                Object JavaDoc elseStatement= getOriginalValue(node, IfStatement.ELSE_STATEMENT_PROPERTY);
2081                if (elseStatement != null) {
2082                    ASTNode thenStatement = (ASTNode) thenEvent.getOriginalValue();
2083                    endPos= getScanner().getTokenStartOffset(ITerminalSymbols.TokenNameelse, thenStatement.getStartPosition() + thenStatement.getLength()); // else keyword
2084
}
2085                if (elseStatement == null || elseChange != RewriteEvent.UNCHANGED) {
2086                    pos= rewriteBodyNode(node, IfStatement.THEN_STATEMENT_PROPERTY, pos, endPos, indent, this.formatter.IF_BLOCK_NO_ELSE);
2087                } else {
2088                    pos= rewriteBodyNode(node, IfStatement.THEN_STATEMENT_PROPERTY, pos, endPos, indent, this.formatter.IF_BLOCK_WITH_ELSE);
2089                }
2090            } catch (CoreException e) {
2091                handleException(e);
2092            }
2093        } else {
2094            pos= doVisit(node, IfStatement.THEN_STATEMENT_PROPERTY, pos);
2095        }
2096
2097        if (elseChange != RewriteEvent.UNCHANGED) {
2098            int indent= getIndent(node.getStartPosition());
2099            Object JavaDoc newThen= getNewValue(node, IfStatement.THEN_STATEMENT_PROPERTY);
2100            if (newThen instanceof Block) {
2101                rewriteBodyNode(node, IfStatement.ELSE_STATEMENT_PROPERTY, pos, -1, indent, this.formatter.ELSE_AFTER_BLOCK);
2102            } else {
2103                rewriteBodyNode(node, IfStatement.ELSE_STATEMENT_PROPERTY, pos, -1, indent, this.formatter.ELSE_AFTER_STATEMENT);
2104            }
2105        } else {
2106            pos= doVisit(node, IfStatement.ELSE_STATEMENT_PROPERTY, pos);
2107        }
2108        return false;
2109    }
2110
2111    /* (non-Javadoc)
2112     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ImportDeclaration)
2113     */

2114    public boolean visit(ImportDeclaration node) {
2115        if (!hasChildrenChanges(node)) {
2116            return doVisitUnchangedChildren(node);
2117        }
2118        if (node.getAST().apiLevel() >= AST.JLS3) {
2119            RewriteEvent event= getEvent(node, ImportDeclaration.STATIC_PROPERTY);
2120            if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
2121                try {
2122                    int pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameimport, node.getStartPosition());
2123                    boolean wasStatic= ((Boolean JavaDoc) event.getOriginalValue()).booleanValue();
2124                    if (wasStatic) {
2125                        int endPos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNamestatic, pos);
2126                        doTextRemove(pos, endPos - pos, getEditGroup(event));
2127                    } else {
2128                        doTextInsert(pos, " static", getEditGroup(event)); //$NON-NLS-1$
2129
}
2130                } catch (CoreException e) {
2131                    handleException(e);
2132                }
2133            }
2134        }
2135        
2136        int pos= rewriteRequiredNode(node, ImportDeclaration.NAME_PROPERTY);
2137        
2138        RewriteEvent event= getEvent(node, ImportDeclaration.ON_DEMAND_PROPERTY);
2139        if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
2140            boolean isOnDemand= ((Boolean JavaDoc) event.getOriginalValue()).booleanValue();
2141            if (!isOnDemand) {
2142                doTextInsert(pos, ".*", getEditGroup(event)); //$NON-NLS-1$
2143
} else {
2144                try {
2145                    int endPos= getScanner().getTokenStartOffset(ITerminalSymbols.TokenNameSEMICOLON, pos);
2146                    doTextRemove(pos, endPos - pos, getEditGroup(event));
2147                } catch (CoreException e) {
2148                    handleException(e);
2149                }
2150            }
2151        }
2152        return false;
2153    }
2154    
2155
2156    
2157
2158    /* (non-Javadoc)
2159     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(InfixExpression)
2160     */

2161    public boolean visit(InfixExpression node) {
2162        if (!hasChildrenChanges(node)) {
2163            return doVisitUnchangedChildren(node);
2164        }
2165        
2166        int pos= rewriteRequiredNode(node, InfixExpression.LEFT_OPERAND_PROPERTY);
2167        
2168        boolean needsNewOperation= isChanged(node, InfixExpression.OPERATOR_PROPERTY);
2169        String JavaDoc operation= getNewValue(node, InfixExpression.OPERATOR_PROPERTY).toString();
2170        if (needsNewOperation) {
2171            replaceOperation(pos, operation, getEditGroup(node, InfixExpression.OPERATOR_PROPERTY));
2172        }
2173            
2174        pos= rewriteRequiredNode(node, InfixExpression.RIGHT_OPERAND_PROPERTY);
2175        
2176        RewriteEvent event= getEvent(node, InfixExpression.EXTENDED_OPERANDS_PROPERTY);
2177        String JavaDoc prefixString= ' ' + operation + ' ';
2178        
2179        if (needsNewOperation) {
2180            int startPos= pos;
2181            TextEditGroup editGroup= getEditGroup(node, InfixExpression.OPERATOR_PROPERTY);
2182            
2183            if (event != null && event.getChangeKind() != RewriteEvent.UNCHANGED) {
2184                RewriteEvent[] extendedOperands= event.getChildren();
2185                for (int i= 0; i < extendedOperands.length; i++) {
2186                    RewriteEvent curr= extendedOperands[i];
2187                    ASTNode elem= (ASTNode) curr.getOriginalValue();
2188                    if (elem != null) {
2189                        if (curr.getChangeKind() != RewriteEvent.REPLACED) {
2190                            replaceOperation(startPos, operation, editGroup);
2191                        }
2192                        startPos= elem.getStartPosition() + elem.getLength();
2193                    }
2194                }
2195            } else {
2196                List JavaDoc extendedOperands= (List JavaDoc) getOriginalValue(node, InfixExpression.EXTENDED_OPERANDS_PROPERTY);
2197                for (int i= 0; i < extendedOperands.size(); i++) {
2198                    ASTNode elem= (ASTNode) extendedOperands.get(i);
2199                    replaceOperation(startPos, operation, editGroup);
2200                    startPos= elem.getStartPosition() + elem.getLength();
2201                }
2202            }
2203        }
2204        rewriteNodeList(node, InfixExpression.EXTENDED_OPERANDS_PROPERTY, pos, prefixString, prefixString);
2205        return false;
2206    }
2207
2208    /* (non-Javadoc)
2209     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(Initializer)
2210     */

2211    public boolean visit(Initializer node) {
2212        if (!hasChildrenChanges(node)) {
2213            return doVisitUnchangedChildren(node);
2214        }
2215        int pos= rewriteJavadoc(node, Initializer.JAVADOC_PROPERTY);
2216        if (node.getAST().apiLevel() == JLS2_INTERNAL) {
2217            rewriteModifiers(node, Initializer.MODIFIERS_PROPERTY, pos);
2218        } else {
2219            rewriteModifiers2(node, Initializer.MODIFIERS2_PROPERTY, pos);
2220        }
2221        rewriteRequiredNode(node, Initializer.BODY_PROPERTY);
2222        return false;
2223    }
2224
2225    /* (non-Javadoc)
2226     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(InstanceofExpression)
2227     */

2228    public boolean visit(InstanceofExpression node) {
2229        if (!hasChildrenChanges(node)) {
2230            return doVisitUnchangedChildren(node);
2231        }
2232                
2233        rewriteRequiredNode(node, InstanceofExpression.LEFT_OPERAND_PROPERTY);
2234        ensureSpaceAfterReplace(node, InstanceofExpression.LEFT_OPERAND_PROPERTY);
2235        rewriteRequiredNode(node, InstanceofExpression.RIGHT_OPERAND_PROPERTY);
2236        return false;
2237    }
2238    
2239    public void ensureSpaceAfterReplace(ASTNode node, ChildPropertyDescriptor desc) {
2240        if (getChangeKind(node, desc) == RewriteEvent.REPLACED) {
2241            int leftOperandEnd= getExtendedEnd((ASTNode) getOriginalValue(node, desc));
2242            try {
2243                int offset= getScanner().getNextStartOffset(leftOperandEnd, true); // instanceof
2244

2245                if (offset == leftOperandEnd) {
2246                    doTextInsert(offset, String.valueOf(' '), getEditGroup(node, desc));
2247                }
2248            } catch (CoreException e) {
2249                handleException(e);
2250            }
2251        }
2252    }
2253    
2254    public void ensureSpaceBeforeReplace(ASTNode node, ChildPropertyDescriptor desc, int offset, int numTokenBefore) {
2255        // bug 103970
2256
if (getChangeKind(node, desc) == RewriteEvent.REPLACED) {
2257            try {
2258                while (numTokenBefore > 0) {
2259                    offset= getScanner().getNextEndOffset(offset, true);
2260                    numTokenBefore--;
2261                }
2262                if (offset == getExtendedOffset((ASTNode) getOriginalValue(node, desc))) {
2263                    doTextInsert(offset, String.valueOf(' '), getEditGroup(node, desc));
2264                }
2265            } catch (CoreException e) {
2266                handleException(e);
2267            }
2268        }
2269    }
2270    
2271    
2272
2273    /* (non-Javadoc)
2274     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(Javadoc)
2275     */

2276    public boolean visit(Javadoc node) {
2277        if (!hasChildrenChanges(node)) {
2278            return doVisitUnchangedChildren(node);
2279        }
2280        int startPos= node.getStartPosition() + 3;
2281        String JavaDoc separator= getLineDelimiter() + getIndentAtOffset(node.getStartPosition()) + " * "; //$NON-NLS-1$
2282

2283        rewriteNodeList(node, Javadoc.TAGS_PROPERTY, startPos, separator, separator);
2284        return false;
2285    }
2286
2287    /* (non-Javadoc)
2288     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(LabeledStatement)
2289     */

2290    public boolean visit(LabeledStatement node) {
2291        if (!hasChildrenChanges(node)) {
2292            return doVisitUnchangedChildren(node);
2293        }
2294        
2295        rewriteRequiredNode(node, LabeledStatement.LABEL_PROPERTY);
2296        rewriteRequiredNode(node, LabeledStatement.BODY_PROPERTY);
2297        return false;
2298    }
2299
2300    /* (non-Javadoc)
2301     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(MethodInvocation)
2302     */

2303    public boolean visit(MethodInvocation node) {
2304        if (!hasChildrenChanges(node)) {
2305            return doVisitUnchangedChildren(node);
2306        }
2307        
2308        int pos= rewriteOptionalQualifier(node, MethodInvocation.EXPRESSION_PROPERTY, node.getStartPosition());
2309        if (node.getAST().apiLevel() >= AST.JLS3) {
2310            pos= rewriteOptionalTypeParameters(node, MethodInvocation.TYPE_ARGUMENTS_PROPERTY, pos, "", false, false); //$NON-NLS-1$
2311
}
2312
2313        pos= rewriteRequiredNode(node, MethodInvocation.NAME_PROPERTY);
2314        
2315        if (isChanged(node, MethodInvocation.ARGUMENTS_PROPERTY)) {
2316            // eval position after opening parent
2317
try {
2318                int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, pos);
2319                rewriteNodeList(node, MethodInvocation.ARGUMENTS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
2320
} catch (CoreException e) {
2321                handleException(e);
2322            }
2323        } else {
2324            voidVisit(node, MethodInvocation.ARGUMENTS_PROPERTY);
2325        }
2326        return false;
2327    }
2328
2329    /* (non-Javadoc)
2330     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(NullLiteral)
2331     */

2332    public boolean visit(NullLiteral node) {
2333        if (!hasChildrenChanges(node)) {
2334            return doVisitUnchangedChildren(node);
2335        }
2336        
2337        changeNotSupported(node); // no modification possible
2338
return false;
2339    }
2340
2341    /* (non-Javadoc)
2342     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(NumberLiteral)
2343     */

2344    public boolean visit(NumberLiteral node) {
2345        if (!hasChildrenChanges(node)) {
2346            return doVisitUnchangedChildren(node);
2347        }
2348        String JavaDoc newLiteral= (String JavaDoc) getNewValue(node, NumberLiteral.TOKEN_PROPERTY);
2349        TextEditGroup group = getEditGroup(node, NumberLiteral.TOKEN_PROPERTY);
2350        doTextReplace(node.getStartPosition(), node.getLength(), newLiteral, group);
2351        return false;
2352    }
2353
2354    /* (non-Javadoc)
2355     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(PackageDeclaration)
2356     */

2357    public boolean visit(PackageDeclaration node) {
2358        if (!hasChildrenChanges(node)) {
2359            return doVisitUnchangedChildren(node);
2360        }
2361        if (node.getAST().apiLevel() >= AST.JLS3) {
2362            int pos= rewriteJavadoc(node, PackageDeclaration.JAVADOC_PROPERTY);
2363            rewriteNodeList(node, PackageDeclaration.ANNOTATIONS_PROPERTY, pos, "", " "); //$NON-NLS-1$ //$NON-NLS-2$
2364
}
2365        
2366        rewriteRequiredNode(node, PackageDeclaration.NAME_PROPERTY);
2367        return false;
2368    }
2369
2370    /* (non-Javadoc)
2371     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ParenthesizedExpression)
2372     */

2373    public boolean visit(ParenthesizedExpression node) {
2374        if (!hasChildrenChanges(node)) {
2375            return doVisitUnchangedChildren(node);
2376        }
2377        
2378        rewriteRequiredNode(node, ParenthesizedExpression.EXPRESSION_PROPERTY);
2379        return false;
2380    }
2381
2382    /* (non-Javadoc)
2383     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(PostfixExpression)
2384     */

2385    public boolean visit(PostfixExpression node) {
2386        if (!hasChildrenChanges(node)) {
2387            return doVisitUnchangedChildren(node);
2388        }
2389        
2390        int pos= rewriteRequiredNode(node, PostfixExpression.OPERAND_PROPERTY);
2391        rewriteOperation(node, PostfixExpression.OPERATOR_PROPERTY, pos);
2392        return false;
2393    }
2394
2395    /* (non-Javadoc)
2396     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(PrefixExpression)
2397     */

2398    public boolean visit(PrefixExpression node) {
2399        if (!hasChildrenChanges(node)) {
2400            return doVisitUnchangedChildren(node);
2401        }
2402        
2403        rewriteOperation(node, PrefixExpression.OPERATOR_PROPERTY, node.getStartPosition());
2404        rewriteRequiredNode(node, PrefixExpression.OPERAND_PROPERTY);
2405        return false;
2406    }
2407
2408    /* (non-Javadoc)
2409     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(PrimitiveType)
2410     */

2411    public boolean visit(PrimitiveType node) {
2412        if (!hasChildrenChanges(node)) {
2413            return doVisitUnchangedChildren(node);
2414        }
2415        PrimitiveType.Code newCode= (PrimitiveType.Code) getNewValue(node, PrimitiveType.PRIMITIVE_TYPE_CODE_PROPERTY);
2416        TextEditGroup group = getEditGroup(node, PrimitiveType.PRIMITIVE_TYPE_CODE_PROPERTY);
2417        doTextReplace(node.getStartPosition(), node.getLength(), newCode.toString(), group);
2418        return false;
2419    }
2420
2421    /* (non-Javadoc)
2422     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(QualifiedName)
2423     */

2424    public boolean visit(QualifiedName node) {
2425        if (!hasChildrenChanges(node)) {
2426            return doVisitUnchangedChildren(node);
2427        }
2428        
2429        rewriteRequiredNode(node, QualifiedName.QUALIFIER_PROPERTY);
2430        rewriteRequiredNode(node, QualifiedName.NAME_PROPERTY);
2431        return false;
2432    }
2433
2434    /* (non-Javadoc)
2435     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SimpleName)
2436     */

2437    public boolean visit(SimpleName node) {
2438        if (!hasChildrenChanges(node)) {
2439            return doVisitUnchangedChildren(node);
2440        }
2441        String JavaDoc newString= (String JavaDoc) getNewValue(node, SimpleName.IDENTIFIER_PROPERTY);
2442        TextEditGroup group = getEditGroup(node, SimpleName.IDENTIFIER_PROPERTY);
2443        doTextReplace(node.getStartPosition(), node.getLength(), newString, group);
2444        return false;
2445    }
2446
2447    /* (non-Javadoc)
2448     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SimpleType)
2449     */

2450    public boolean visit(SimpleType node) {
2451        if (!hasChildrenChanges(node)) {
2452            return doVisitUnchangedChildren(node);
2453        }
2454        
2455        rewriteRequiredNode(node, SimpleType.NAME_PROPERTY);
2456        return false;
2457    }
2458
2459    /* (non-Javadoc)
2460     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SingleVariableDeclaration)
2461     */

2462    public boolean visit(SingleVariableDeclaration node) {
2463        if (!hasChildrenChanges(node)) {
2464            return doVisitUnchangedChildren(node);
2465        }
2466        int pos= node.getStartPosition();
2467        if (node.getAST().apiLevel() == JLS2_INTERNAL) {
2468            rewriteModifiers(node, SingleVariableDeclaration.MODIFIERS_PROPERTY, pos);
2469        } else {
2470            rewriteModifiers2(node, SingleVariableDeclaration.MODIFIERS2_PROPERTY, pos);
2471        }
2472        pos= rewriteRequiredNode(node, SingleVariableDeclaration.TYPE_PROPERTY);
2473        if (node.getAST().apiLevel() >= AST.JLS3) {
2474            if (isChanged(node, SingleVariableDeclaration.VARARGS_PROPERTY)) {
2475                if (getNewValue(node, SingleVariableDeclaration.VARARGS_PROPERTY).equals(Boolean.TRUE)) {
2476                    doTextInsert(pos, "...", getEditGroup(node, SingleVariableDeclaration.VARARGS_PROPERTY)); //$NON-NLS-1$
2477
} else {
2478                    try {
2479                        int ellipsisEnd= getScanner().getNextEndOffset(pos, true);
2480                        doTextRemove(pos, ellipsisEnd - pos, getEditGroup(node, SingleVariableDeclaration.VARARGS_PROPERTY));
2481                    } catch (CoreException e) {
2482                        handleException(e);
2483                    }
2484                }
2485            }
2486        }
2487        
2488        pos= rewriteRequiredNode(node, SingleVariableDeclaration.NAME_PROPERTY);
2489        int extraDims= rewriteExtraDimensions(node, SingleVariableDeclaration.EXTRA_DIMENSIONS_PROPERTY, pos);
2490        
2491        if (extraDims > 0) {
2492            int kind= getChangeKind(node, SingleVariableDeclaration.INITIALIZER_PROPERTY);
2493            if (kind == RewriteEvent.REMOVED) {
2494                try {
2495                    pos= getScanner().getPreviousTokenEndOffset(ITerminalSymbols.TokenNameEQUAL, pos);
2496                } catch (CoreException e) {
2497                    handleException(e);
2498                }
2499            } else {
2500                pos= node.getStartPosition() + node.getLength(); // insert pos
2501
}
2502        }
2503        
2504        rewriteNode(node, SingleVariableDeclaration.INITIALIZER_PROPERTY, pos, this.formatter.VAR_INITIALIZER);
2505        return false;
2506    }
2507
2508    /* (non-Javadoc)
2509     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(StringLiteral)
2510     */

2511    public boolean visit(StringLiteral node) {
2512        if (!hasChildrenChanges(node)) {
2513            return doVisitUnchangedChildren(node);
2514        }
2515        String JavaDoc escapedSeq= (String JavaDoc) getNewValue(node, StringLiteral.ESCAPED_VALUE_PROPERTY);
2516        TextEditGroup group = getEditGroup(node, StringLiteral.ESCAPED_VALUE_PROPERTY);
2517        doTextReplace(node.getStartPosition(), node.getLength(), escapedSeq, group);
2518
2519        return false;
2520    }
2521
2522    /* (non-Javadoc)
2523     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SuperConstructorInvocation)
2524     */

2525    public boolean visit(SuperConstructorInvocation node) {
2526        if (!hasChildrenChanges(node)) {
2527            return doVisitUnchangedChildren(node);
2528        }
2529        
2530        int pos= rewriteOptionalQualifier(node, SuperConstructorInvocation.EXPRESSION_PROPERTY, node.getStartPosition());
2531
2532        if (node.getAST().apiLevel() >= AST.JLS3) {
2533            pos= rewriteOptionalTypeParameters(node, SuperConstructorInvocation.TYPE_ARGUMENTS_PROPERTY, pos, "", false, false); //$NON-NLS-1$
2534
}
2535        
2536        if (isChanged(node, SuperConstructorInvocation.ARGUMENTS_PROPERTY)) {
2537            // eval position after opening parent
2538
try {
2539                pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, pos);
2540                rewriteNodeList(node, SuperConstructorInvocation.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
2541
} catch (CoreException e) {
2542                handleException(e);
2543            }
2544        } else {
2545            voidVisit(node, SuperConstructorInvocation.ARGUMENTS_PROPERTY);
2546        }
2547        return false;
2548    }
2549
2550    /* (non-Javadoc)
2551     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SuperFieldAccess)
2552     */

2553    public boolean visit(SuperFieldAccess node) {
2554        if (!hasChildrenChanges(node)) {
2555            return doVisitUnchangedChildren(node);
2556        }
2557        
2558        rewriteOptionalQualifier(node, SuperFieldAccess.QUALIFIER_PROPERTY, node.getStartPosition());
2559        rewriteRequiredNode(node, SuperFieldAccess.NAME_PROPERTY);
2560        return false;
2561    }
2562
2563    /* (non-Javadoc)
2564     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SuperMethodInvocation)
2565     */

2566    public boolean visit(SuperMethodInvocation node) {
2567        if (!hasChildrenChanges(node)) {
2568            return doVisitUnchangedChildren(node);
2569        }
2570        
2571        int pos= rewriteOptionalQualifier(node, SuperMethodInvocation.QUALIFIER_PROPERTY, node.getStartPosition());
2572        
2573        if (node.getAST().apiLevel() >= AST.JLS3) {
2574            if (isChanged(node, SuperMethodInvocation.TYPE_ARGUMENTS_PROPERTY)) {
2575                try {
2576                    pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameDOT, pos);
2577                    rewriteOptionalTypeParameters(node, SuperMethodInvocation.TYPE_ARGUMENTS_PROPERTY, pos, "", false, false); //$NON-NLS-1$
2578
} catch (CoreException e) {
2579                    handleException(e);
2580                }
2581            }
2582        }
2583        
2584        pos= rewriteRequiredNode(node, SuperMethodInvocation.NAME_PROPERTY);
2585        
2586        if (isChanged(node, SuperMethodInvocation.ARGUMENTS_PROPERTY)) {
2587            // eval position after opening parent
2588
try {
2589                pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, pos);
2590                rewriteNodeList(node, SuperMethodInvocation.ARGUMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
2591
} catch (CoreException e) {
2592                handleException(e);
2593            }
2594        } else {
2595            voidVisit(node, SuperMethodInvocation.ARGUMENTS_PROPERTY);
2596        }
2597        return false;
2598    }
2599
2600    /* (non-Javadoc)
2601     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SwitchCase)
2602     */

2603    public boolean visit(SwitchCase node) {
2604        if (!hasChildrenChanges(node)) {
2605            return doVisitUnchangedChildren(node);
2606        }
2607        
2608        // dont allow switching from case to default or back. New statements should be created.
2609
rewriteRequiredNode(node, SwitchCase.EXPRESSION_PROPERTY);
2610        return false;
2611    }
2612
2613    class SwitchListRewriter extends ParagraphListRewriter {
2614
2615        public SwitchListRewriter(int initialIndent) {
2616            super(initialIndent, 0);
2617        }
2618        
2619        protected int getNodeIndent(int nodeIndex) {
2620            int indent= getInitialIndent();
2621            ASTNode node= (ASTNode) this.list[nodeIndex].getOriginalValue();
2622            if (node == null) {
2623                node= (ASTNode) this.list[nodeIndex].getNewValue();
2624            }
2625            if (node.getNodeType() != ASTNode.SWITCH_CASE) {
2626                indent++;
2627            }
2628            return indent;
2629        }
2630    }
2631
2632    /* (non-Javadoc)
2633     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SwitchStatement)
2634     */

2635    public boolean visit(SwitchStatement node) {
2636        if (!hasChildrenChanges(node)) {
2637            return doVisitUnchangedChildren(node);
2638        }
2639        
2640        int pos= rewriteRequiredNode(node, SwitchStatement.EXPRESSION_PROPERTY);
2641        
2642        ChildListPropertyDescriptor property= SwitchStatement.STATEMENTS_PROPERTY;
2643        if (getChangeKind(node, property) != RewriteEvent.UNCHANGED) {
2644            try {
2645                pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLBRACE, pos);
2646                int insertIndent= getIndent(node.getStartPosition()) + 1;
2647                
2648                ParagraphListRewriter listRewriter= new SwitchListRewriter(insertIndent);
2649                StringBuffer JavaDoc leadString= new StringBuffer JavaDoc();
2650                leadString.append(getLineDelimiter());
2651                leadString.append(createIndentString(insertIndent));
2652                listRewriter.rewriteList(node, property, pos, leadString.toString());
2653            } catch (CoreException e) {
2654                handleException(e);
2655            }
2656        } else {
2657            voidVisit(node, SwitchStatement.STATEMENTS_PROPERTY);
2658        }
2659        return false;
2660    }
2661
2662    /* (non-Javadoc)
2663     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(SynchronizedStatement)
2664     */

2665    public boolean visit(SynchronizedStatement node) {
2666        if (!hasChildrenChanges(node)) {
2667            return doVisitUnchangedChildren(node);
2668        }
2669        
2670        rewriteRequiredNode(node, SynchronizedStatement.EXPRESSION_PROPERTY);
2671        rewriteRequiredNode(node, SynchronizedStatement.BODY_PROPERTY);
2672        return false;
2673    }
2674
2675    /* (non-Javadoc)
2676     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ThisExpression)
2677     */

2678    public boolean visit(ThisExpression node) {
2679        if (!hasChildrenChanges(node)) {
2680            return doVisitUnchangedChildren(node);
2681        }
2682        
2683        rewriteOptionalQualifier(node, ThisExpression.QUALIFIER_PROPERTY, node.getStartPosition());
2684        return false;
2685    }
2686
2687    /* (non-Javadoc)
2688     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(ThrowStatement)
2689     */

2690    public boolean visit(ThrowStatement node) {
2691        if (!hasChildrenChanges(node)) {
2692            return doVisitUnchangedChildren(node);
2693        }
2694        
2695        rewriteRequiredNode(node, ThrowStatement.EXPRESSION_PROPERTY);
2696        return false;
2697    }
2698
2699    /* (non-Javadoc)
2700     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(TryStatement)
2701     */

2702    public boolean visit(TryStatement node) {
2703        if (!hasChildrenChanges(node)) {
2704            return doVisitUnchangedChildren(node);
2705        }
2706        
2707        int pos= rewriteRequiredNode(node, TryStatement.BODY_PROPERTY);
2708        
2709        if (isChanged(node, TryStatement.CATCH_CLAUSES_PROPERTY)) {
2710            int indent= getIndent(node.getStartPosition());
2711            String JavaDoc prefix= this.formatter.CATCH_BLOCK.getPrefix(indent);
2712            pos= rewriteNodeList(node, TryStatement.CATCH_CLAUSES_PROPERTY, pos, prefix, prefix);
2713        } else {
2714            pos= doVisit(node, TryStatement.CATCH_CLAUSES_PROPERTY, pos);
2715        }
2716        rewriteNode(node, TryStatement.FINALLY_PROPERTY, pos, this.formatter.FINALLY_BLOCK);
2717        return false;
2718    }
2719
2720
2721
2722    /* (non-Javadoc)
2723     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(TypeDeclarationStatement)
2724     */

2725    public boolean visit(TypeDeclarationStatement node) {
2726        if (!hasChildrenChanges(node)) {
2727            return doVisitUnchangedChildren(node);
2728        }
2729        if (node.getAST().apiLevel() == JLS2_INTERNAL) {
2730            rewriteRequiredNode(node, TypeDeclarationStatement.TYPE_DECLARATION_PROPERTY);
2731        } else {
2732            rewriteRequiredNode(node, TypeDeclarationStatement.DECLARATION_PROPERTY);
2733        }
2734        return false;
2735    }
2736
2737    /* (non-Javadoc)
2738     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(TypeLiteral)
2739     */

2740    public boolean visit(TypeLiteral node) {
2741        if (!hasChildrenChanges(node)) {
2742            return doVisitUnchangedChildren(node);
2743        }
2744        
2745        rewriteRequiredNode(node, TypeLiteral.TYPE_PROPERTY);
2746        return false;
2747    }
2748
2749    /* (non-Javadoc)
2750     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(VariableDeclarationExpression)
2751     */

2752    public boolean visit(VariableDeclarationExpression node) {
2753        if (!hasChildrenChanges(node)) {
2754            return doVisitUnchangedChildren(node);
2755        }
2756        
2757        // same code as FieldDeclaration
2758
int pos= node.getStartPosition();
2759        if (node.getAST().apiLevel() == JLS2_INTERNAL) {
2760            rewriteModifiers(node, VariableDeclarationExpression.MODIFIERS_PROPERTY, pos);
2761        } else {
2762            rewriteModifiers2(node, VariableDeclarationExpression.MODIFIERS2_PROPERTY, pos);
2763        }
2764        pos= rewriteRequiredNode(node, VariableDeclarationExpression.TYPE_PROPERTY);
2765        rewriteNodeList(node, VariableDeclarationExpression.FRAGMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
2766
return false;
2767    }
2768
2769    /* (non-Javadoc)
2770     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(VariableDeclarationFragment)
2771     */

2772    public boolean visit(VariableDeclarationFragment node) {
2773        if (!hasChildrenChanges(node)) {
2774            return doVisitUnchangedChildren(node);
2775        }
2776        
2777        int pos= rewriteRequiredNode(node, VariableDeclarationFragment.NAME_PROPERTY);
2778    
2779        int extraDims= rewriteExtraDimensions(node, VariableDeclarationFragment.EXTRA_DIMENSIONS_PROPERTY, pos);
2780        
2781        if (extraDims > 0) {
2782            int kind= getChangeKind(node, VariableDeclarationFragment.INITIALIZER_PROPERTY);
2783            if (kind == RewriteEvent.REMOVED) {
2784                try {
2785                    pos= getScanner().getPreviousTokenEndOffset(ITerminalSymbols.TokenNameEQUAL, pos);
2786                } catch (CoreException e) {
2787                    handleException(e);
2788                }
2789            } else {
2790                pos= node.getStartPosition() + node.getLength(); // insert pos
2791
}
2792        }
2793        rewriteNode(node, VariableDeclarationFragment.INITIALIZER_PROPERTY, pos, this.formatter.VAR_INITIALIZER);
2794        return false;
2795    }
2796
2797    /* (non-Javadoc)
2798     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(VariableDeclarationStatement)
2799     */

2800    public boolean visit(VariableDeclarationStatement node) {
2801        if (!hasChildrenChanges(node)) {
2802            return doVisitUnchangedChildren(node);
2803        }
2804        
2805        // same code as FieldDeclaration
2806
int pos= node.getStartPosition();
2807        if (node.getAST().apiLevel() == JLS2_INTERNAL) {
2808            rewriteModifiers(node, VariableDeclarationStatement.MODIFIERS_PROPERTY, pos);
2809        } else {
2810            rewriteModifiers2(node, VariableDeclarationStatement.MODIFIERS2_PROPERTY, pos);
2811        }
2812        pos= rewriteRequiredNode(node, VariableDeclarationStatement.TYPE_PROPERTY);
2813        
2814        rewriteNodeList(node, VariableDeclarationStatement.FRAGMENTS_PROPERTY, pos, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
2815
return false;
2816    }
2817
2818    /* (non-Javadoc)
2819     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(WhileStatement)
2820     */

2821    public boolean visit(WhileStatement node) {
2822        if (!hasChildrenChanges(node)) {
2823            return doVisitUnchangedChildren(node);
2824        }
2825        
2826        int pos= rewriteRequiredNode(node, WhileStatement.EXPRESSION_PROPERTY);
2827        
2828        try {
2829            if (isChanged(node, WhileStatement.BODY_PROPERTY)) {
2830                int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRPAREN, pos);
2831                rewriteBodyNode(node, WhileStatement.BODY_PROPERTY, startOffset, -1, getIndent(node.getStartPosition()), this.formatter.WHILE_BLOCK); // body
2832
} else {
2833                voidVisit(node, WhileStatement.BODY_PROPERTY);
2834            }
2835        } catch (CoreException e) {
2836            handleException(e);
2837        }
2838        return false;
2839    }
2840    
2841    /* (non-Javadoc)
2842     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberRef)
2843     */

2844    public boolean visit(MemberRef node) {
2845        if (!hasChildrenChanges(node)) {
2846            return doVisitUnchangedChildren(node);
2847        }
2848        rewriteNode(node, MemberRef.QUALIFIER_PROPERTY, node.getStartPosition(), ASTRewriteFormatter.NONE);
2849
2850        rewriteRequiredNode(node, MemberRef.NAME_PROPERTY);
2851        return false;
2852    }
2853    
2854    /* (non-Javadoc)
2855     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRef)
2856     */

2857    public boolean visit(MethodRef node) {
2858        if (!hasChildrenChanges(node)) {
2859            return doVisitUnchangedChildren(node);
2860        }
2861        rewriteNode(node, MethodRef.QUALIFIER_PROPERTY, node.getStartPosition(), ASTRewriteFormatter.NONE);
2862
2863        int pos= rewriteRequiredNode(node, MethodRef.NAME_PROPERTY);
2864
2865        if (isChanged(node, MethodRef.PARAMETERS_PROPERTY)) {
2866            // eval position after opening parent
2867
try {
2868                int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, pos);
2869                rewriteNodeList(node, MethodRef.PARAMETERS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
2870
} catch (CoreException e) {
2871                handleException(e);
2872            }
2873        } else {
2874            voidVisit(node, MethodRef.PARAMETERS_PROPERTY);
2875        }
2876        return false;
2877    }
2878    
2879    /* (non-Javadoc)
2880     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRefParameter)
2881     */

2882    public boolean visit(MethodRefParameter node) {
2883        if (!hasChildrenChanges(node)) {
2884            return doVisitUnchangedChildren(node);
2885        }
2886        int pos= rewriteRequiredNode(node, MethodRefParameter.TYPE_PROPERTY);
2887        if (node.getAST().apiLevel() >= AST.JLS3) {
2888            if (isChanged(node, MethodRefParameter.VARARGS_PROPERTY)) {
2889                if (getNewValue(node, MethodRefParameter.VARARGS_PROPERTY).equals(Boolean.TRUE)) {
2890                    doTextInsert(pos, "...", getEditGroup(node, MethodRefParameter.VARARGS_PROPERTY)); //$NON-NLS-1$
2891
} else {
2892                    try {
2893                        int ellipsisEnd= getScanner().getNextEndOffset(pos, true);
2894                        doTextRemove(pos, ellipsisEnd - pos, getEditGroup(node, MethodRefParameter.VARARGS_PROPERTY));
2895                    } catch (CoreException e) {
2896                        handleException(e);
2897                    }
2898                }
2899            }
2900        }
2901        rewriteNode(node, MethodRefParameter.NAME_PROPERTY, pos, ASTRewriteFormatter.SPACE);
2902        return false;
2903    }
2904    
2905    /* (non-Javadoc)
2906     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TagElement)
2907     */

2908    public boolean visit(TagElement node) {
2909        if (!hasChildrenChanges(node)) {
2910            return doVisitUnchangedChildren(node);
2911        }
2912        
2913        int changeKind= getChangeKind(node, TagElement.TAG_NAME_PROPERTY);
2914        switch (changeKind) {
2915            case RewriteEvent.INSERTED: {
2916                String JavaDoc newTagName= (String JavaDoc) getNewValue(node, TagElement.TAG_NAME_PROPERTY);
2917                doTextInsert(node.getStartPosition(), newTagName, getEditGroup(node, TagElement.TAG_NAME_PROPERTY));
2918                break;
2919            }
2920            case RewriteEvent.REMOVED: {
2921                doTextRemove(node.getStartPosition(), findTagNameEnd(node) - node.getStartPosition(), getEditGroup(node, TagElement.TAG_NAME_PROPERTY));
2922                break;
2923            }
2924            case RewriteEvent.REPLACED: {
2925                String JavaDoc newTagName= (String JavaDoc) getNewValue(node, TagElement.TAG_NAME_PROPERTY);
2926                doTextReplace(node.getStartPosition(), findTagNameEnd(node) - node.getStartPosition(), newTagName, getEditGroup(node, TagElement.TAG_NAME_PROPERTY));
2927                break;
2928            }
2929        }
2930                
2931        if (isChanged(node, TagElement.FRAGMENTS_PROPERTY)) {
2932            // eval position after name
2933
int endOffset= findTagNameEnd(node);
2934            rewriteNodeList(node, TagElement.FRAGMENTS_PROPERTY, endOffset, " ", " "); //$NON-NLS-1$//$NON-NLS-2$
2935
} else {
2936            voidVisit(node, TagElement.FRAGMENTS_PROPERTY);
2937        }
2938        return false;
2939    }
2940        
2941    private int findTagNameEnd(TagElement tagNode) {
2942        if (tagNode.getTagName() != null) {
2943            char[] cont= getContent();
2944            int len= cont.length;
2945            int i= tagNode.getStartPosition();
2946            while (i < len && !IndentManipulation.isIndentChar(cont[i])) {
2947                i++;
2948            }
2949            return i;
2950        }
2951        return tagNode.getStartPosition();
2952    }
2953        
2954    
2955    /* (non-Javadoc)
2956     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TextElement)
2957     */

2958    public boolean visit(TextElement node) {
2959        if (!hasChildrenChanges(node)) {
2960            return doVisitUnchangedChildren(node);
2961        }
2962        String JavaDoc newText= (String JavaDoc) getNewValue(node, TextElement.TEXT_PROPERTY);
2963        TextEditGroup group = getEditGroup(node, TextElement.TEXT_PROPERTY);
2964        doTextReplace(node.getStartPosition(), node.getLength(), newText, group);
2965        return false;
2966    }
2967
2968
2969    /* (non-Javadoc)
2970     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration)
2971     */

2972    public boolean visit(AnnotationTypeDeclaration node) {
2973        if (!hasChildrenChanges(node)) {
2974            return doVisitUnchangedChildren(node);
2975        }
2976        int pos= rewriteJavadoc(node, AnnotationTypeDeclaration.JAVADOC_PROPERTY);
2977        rewriteModifiers2(node, AnnotationTypeDeclaration.MODIFIERS2_PROPERTY, pos);
2978        pos= rewriteRequiredNode(node, AnnotationTypeDeclaration.NAME_PROPERTY);
2979        
2980        int startIndent= getIndent(node.getStartPosition()) + 1;
2981        int startPos= getPosAfterLeftBrace(pos);
2982        rewriteParagraphList(node, AnnotationTypeDeclaration.BODY_DECLARATIONS_PROPERTY, startPos, startIndent, -1, 2);
2983        return false;
2984    }
2985    
2986    /* (non-Javadoc)
2987     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration)
2988     */

2989    public boolean visit(AnnotationTypeMemberDeclaration node) {
2990        if (!hasChildrenChanges(node)) {
2991            return doVisitUnchangedChildren(node);
2992        }
2993        int pos= rewriteJavadoc(node, AnnotationTypeMemberDeclaration.JAVADOC_PROPERTY);
2994        rewriteModifiers2(node, AnnotationTypeMemberDeclaration.MODIFIERS2_PROPERTY, pos);
2995        rewriteRequiredNode(node, AnnotationTypeMemberDeclaration.TYPE_PROPERTY);
2996        pos= rewriteRequiredNode(node, AnnotationTypeMemberDeclaration.NAME_PROPERTY);
2997        
2998        try {
2999            int changeKind= getChangeKind(node, AnnotationTypeMemberDeclaration.DEFAULT_PROPERTY);
3000            if (changeKind == RewriteEvent.INSERTED || changeKind == RewriteEvent.REMOVED) {
3001                pos= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRPAREN, pos);
3002            }
3003            rewriteNode(node, AnnotationTypeMemberDeclaration.DEFAULT_PROPERTY, pos, this.formatter.ANNOT_MEMBER_DEFAULT);
3004        } catch (CoreException e) {
3005            handleException(e);
3006        }
3007        return false;
3008    }
3009    
3010    /* (non-Javadoc)
3011     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnhancedForStatement)
3012     */

3013    public boolean visit(EnhancedForStatement node) {
3014        if (!hasChildrenChanges(node)) {
3015            return doVisitUnchangedChildren(node);
3016        }
3017        rewriteRequiredNode(node, EnhancedForStatement.PARAMETER_PROPERTY);
3018        int pos= rewriteRequiredNode(node, EnhancedForStatement.EXPRESSION_PROPERTY);
3019
3020        RewriteEvent bodyEvent= getEvent(node, EnhancedForStatement.BODY_PROPERTY);
3021        if (bodyEvent != null && bodyEvent.getChangeKind() == RewriteEvent.REPLACED) {
3022            int startOffset;
3023            try {
3024                startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameRPAREN, pos);
3025                rewriteBodyNode(node, EnhancedForStatement.BODY_PROPERTY, startOffset, -1, getIndent(node.getStartPosition()), this.formatter.FOR_BLOCK); // body
3026
} catch (CoreException e) {
3027                handleException(e);
3028            }
3029        } else {
3030            voidVisit(node, EnhancedForStatement.BODY_PROPERTY);
3031        }
3032        return false;
3033    }
3034    
3035    /* (non-Javadoc)
3036     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
3037     */

3038    public boolean visit(EnumConstantDeclaration node) {
3039        if (!hasChildrenChanges(node)) {
3040            return doVisitUnchangedChildren(node);
3041        }
3042        int pos= rewriteJavadoc(node, EnumConstantDeclaration.JAVADOC_PROPERTY);
3043        rewriteModifiers2(node, EnumConstantDeclaration.MODIFIERS2_PROPERTY, pos);
3044        pos= rewriteRequiredNode(node, EnumConstantDeclaration.NAME_PROPERTY);
3045        RewriteEvent argsEvent= getEvent(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY);
3046        if (argsEvent != null && argsEvent.getChangeKind() != RewriteEvent.UNCHANGED) {
3047            RewriteEvent[] children= argsEvent.getChildren();
3048            try {
3049                int nextTok= getScanner().readNext(pos, true);
3050                boolean hasParents= (nextTok == ITerminalSymbols.TokenNameLPAREN);
3051                boolean isAllRemoved= hasParents && isAllOfKind(children, RewriteEvent.REMOVED);
3052                String JavaDoc prefix= ""; //$NON-NLS-1$
3053
if (!hasParents) {
3054                    prefix= "("; //$NON-NLS-1$
3055
} else if (!isAllRemoved) {
3056                    pos= getScanner().getCurrentEndOffset();
3057                }
3058                pos= rewriteNodeList(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY, pos, prefix, ", "); //$NON-NLS-1$
3059

3060                if (!hasParents) {
3061                    doTextInsert(pos, ")", getEditGroup(children[children.length - 1])); //$NON-NLS-1$
3062
} else if (isAllRemoved) {
3063                    int afterClosing= getScanner().getNextEndOffset(pos, true);
3064                    doTextRemove(pos, afterClosing - pos, getEditGroup(children[children.length - 1]));
3065                    pos= afterClosing;
3066                }
3067            } catch (CoreException e) {
3068                handleException(e);
3069            }
3070        } else {
3071            pos= doVisit(node, EnumConstantDeclaration.ARGUMENTS_PROPERTY, pos);
3072        }
3073        
3074        if (isChanged(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY)) {
3075            int kind= getChangeKind(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY);
3076            if (kind == RewriteEvent.REMOVED) {
3077                try {
3078                    // 'pos' can be before brace
3079
pos= getScanner().getPreviousTokenEndOffset(ITerminalSymbols.TokenNameLBRACE, pos);
3080                } catch (CoreException e) {
3081                    handleException(e);
3082                }
3083            } else {
3084                pos= node.getStartPosition() + node.getLength(); // insert pos
3085
}
3086            rewriteNode(node, EnumConstantDeclaration.ANONYMOUS_CLASS_DECLARATION_PROPERTY, pos, ASTRewriteFormatter.SPACE);
3087        }
3088        return false;
3089    }
3090    /* (non-Javadoc)
3091     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumDeclaration)
3092     */

3093    public boolean visit(EnumDeclaration node) {
3094        if (!hasChildrenChanges(node)) {
3095            return doVisitUnchangedChildren(node);
3096        }
3097        int pos= rewriteJavadoc(node, EnumDeclaration.JAVADOC_PROPERTY);
3098        rewriteModifiers2(node, EnumDeclaration.MODIFIERS2_PROPERTY, pos);
3099        pos= rewriteRequiredNode(node, EnumDeclaration.NAME_PROPERTY);
3100        pos= rewriteNodeList(node, EnumDeclaration.SUPER_INTERFACE_TYPES_PROPERTY, pos, " implements ", ", "); //$NON-NLS-1$ //$NON-NLS-2$
3101

3102        pos= getPosAfterLeftBrace(pos);
3103        
3104        String JavaDoc leadString= ""; //$NON-NLS-1$
3105
RewriteEvent constEvent= getEvent(node, EnumDeclaration.ENUM_CONSTANTS_PROPERTY);
3106
3107        if (constEvent != null && constEvent.getChangeKind() != RewriteEvent.UNCHANGED) {
3108            RewriteEvent[] events= constEvent.getChildren();
3109            if (isAllOfKind(events, RewriteEvent.INSERTED)) {
3110                leadString= this.formatter.FIRST_ENUM_CONST.getPrefix(getIndent(node.getStartPosition()));
3111            }
3112        }
3113        pos= rewriteNodeList(node, EnumDeclaration.ENUM_CONSTANTS_PROPERTY, pos, leadString, ", "); //$NON-NLS-1$
3114

3115        RewriteEvent bodyEvent= getEvent(node, EnumDeclaration.BODY_DECLARATIONS_PROPERTY);
3116        int indent= 0;
3117        if (bodyEvent != null && bodyEvent.getChangeKind() != RewriteEvent.UNCHANGED) {
3118            boolean hasConstants= !((List JavaDoc) getNewValue(node, EnumDeclaration.ENUM_CONSTANTS_PROPERTY)).isEmpty();
3119            
3120            RewriteEvent[] children= bodyEvent.getChildren();
3121            try {
3122                if (hasConstants) {
3123                    indent= getIndent(pos);
3124                } else {
3125                    indent= getIndent(node.getStartPosition()) + 1;
3126                }
3127                int token= getScanner().readNext(pos, true);
3128                boolean hasSemicolon= token == ITerminalSymbols.TokenNameSEMICOLON;
3129                if (!hasSemicolon && isAllOfKind(children, RewriteEvent.INSERTED)) {
3130                    if (!hasConstants) {
3131                        String JavaDoc str= this.formatter.FIRST_ENUM_CONST.getPrefix(indent - 1);
3132                        doTextInsert(pos, str, getEditGroup(children[0]));
3133                    }
3134                    doTextInsert(pos, ";", getEditGroup(children[0])); //$NON-NLS-1$
3135
} else if (hasSemicolon) {
3136                    int endPos= getScanner().getCurrentEndOffset();
3137                    if (isAllOfKind(children, RewriteEvent.REMOVED)) {
3138                        doTextRemove(pos, endPos - pos, getEditGroup(children[0]));
3139                    }
3140                    pos= endPos;
3141                }
3142            } catch (CoreException e) {
3143                handleException(e);
3144            }
3145        }
3146        rewriteParagraphList(node, EnumDeclaration.BODY_DECLARATIONS_PROPERTY, pos, indent, -1, 2);
3147        return false;
3148    }
3149    /* (non-Javadoc)
3150     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MarkerAnnotation)
3151     */

3152    public boolean visit(MarkerAnnotation node) {
3153        if (!hasChildrenChanges(node)) {
3154            return doVisitUnchangedChildren(node);
3155        }
3156        rewriteRequiredNode(node, MarkerAnnotation.TYPE_NAME_PROPERTY);
3157        return false;
3158    }
3159    /* (non-Javadoc)
3160     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberValuePair)
3161     */

3162    public boolean visit(MemberValuePair node) {
3163        if (!hasChildrenChanges(node)) {
3164            return doVisitUnchangedChildren(node);
3165        }
3166        rewriteRequiredNode(node, MemberValuePair.NAME_PROPERTY);
3167        rewriteRequiredNode(node, MemberValuePair.VALUE_PROPERTY);
3168
3169        return false;
3170    }
3171    /* (non-Javadoc)
3172     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Modifier)
3173     */

3174    public boolean visit(Modifier node) {
3175        if (!hasChildrenChanges(node)) {
3176            return doVisitUnchangedChildren(node);
3177        }
3178        String JavaDoc newText= getNewValue(node, Modifier.KEYWORD_PROPERTY).toString(); // type Modifier.ModifierKeyword
3179
TextEditGroup group = getEditGroup(node, Modifier.KEYWORD_PROPERTY);
3180        doTextReplace(node.getStartPosition(), node.getLength(), newText, group);
3181        return false;
3182    }
3183    /* (non-Javadoc)
3184     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NormalAnnotation)
3185     */

3186    public boolean visit(NormalAnnotation node) {
3187        if (!hasChildrenChanges(node)) {
3188            return doVisitUnchangedChildren(node);
3189        }
3190        int pos= rewriteRequiredNode(node, NormalAnnotation.TYPE_NAME_PROPERTY);
3191        if (isChanged(node, NormalAnnotation.VALUES_PROPERTY)) {
3192            // eval position after opening parent
3193
try {
3194                int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLPAREN, pos);
3195                rewriteNodeList(node, NormalAnnotation.VALUES_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
3196
} catch (CoreException e) {
3197                handleException(e);
3198            }
3199        } else {
3200            voidVisit(node, NormalAnnotation.VALUES_PROPERTY);
3201        }
3202        return false;
3203    }
3204    /* (non-Javadoc)
3205     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ParameterizedType)
3206     */

3207    public boolean visit(ParameterizedType node) {
3208        if (!hasChildrenChanges(node)) {
3209            return doVisitUnchangedChildren(node);
3210        }
3211        int pos= rewriteRequiredNode(node, ParameterizedType.TYPE_PROPERTY);
3212        if (isChanged(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY)) {
3213            // eval position after opening parent
3214
try {
3215                int startOffset= getScanner().getTokenEndOffset(ITerminalSymbols.TokenNameLESS, pos);
3216                rewriteNodeList(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY, startOffset, "", ", "); //$NON-NLS-1$ //$NON-NLS-2$
3217
} catch (CoreException e) {
3218                handleException(e);
3219            }
3220        } else {
3221            voidVisit(node, ParameterizedType.TYPE_ARGUMENTS_PROPERTY);
3222        }
3223        return false;
3224    }
3225    /* (non-Javadoc)
3226     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.QualifiedType)
3227     */

3228    public boolean visit(QualifiedType node) {
3229        if (!hasChildrenChanges(node)) {
3230            return doVisitUnchangedChildren(node);
3231        }
3232        rewriteRequiredNode(node, QualifiedType.QUALIFIER_PROPERTY);
3233        rewriteRequiredNode(node, QualifiedType.NAME_PROPERTY);
3234        return false;
3235    }
3236    /* (non-Javadoc)
3237     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleMemberAnnotation)
3238     */

3239    public boolean visit(SingleMemberAnnotation node) {
3240        if (!hasChildrenChanges(node)) {
3241            return doVisitUnchangedChildren(node);
3242        }
3243        rewriteRequiredNode(node, SingleMemberAnnotation.TYPE_NAME_PROPERTY);
3244        rewriteRequiredNode(node, SingleMemberAnnotation.VALUE_PROPERTY);
3245        return false;
3246    }
3247    /* (non-Javadoc)
3248     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter)
3249     */

3250    public boolean visit(TypeParameter node) {
3251        if (!hasChildrenChanges(node)) {
3252            return doVisitUnchangedChildren(node);
3253        }
3254        int pos= rewriteRequiredNode(node, TypeParameter.NAME_PROPERTY);
3255        if (isChanged(node, TypeParameter.TYPE_BOUNDS_PROPERTY)) {
3256            rewriteNodeList(node, TypeParameter.TYPE_BOUNDS_PROPERTY, pos, " extends ", " & "); //$NON-NLS-1$ //$NON-NLS-2$
3257
} else {
3258            voidVisit(node, TypeParameter.TYPE_BOUNDS_PROPERTY);
3259        }
3260        return false;
3261    }
3262    /* (non-Javadoc)
3263     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WildcardType)
3264     */

3265    public boolean visit(WildcardType node) {
3266        if (!hasChildrenChanges(node)) {
3267            return doVisitUnchangedChildren(node);
3268        }
3269        try {
3270            int pos= getScanner().getNextEndOffset(node.getStartPosition(), true); // pos after question mark
3271

3272            Prefix prefix;
3273            if (Boolean.TRUE.equals(getNewValue(node, WildcardType.UPPER_BOUND_PROPERTY))) {
3274                prefix= this.formatter.WILDCARD_EXTENDS;
3275            } else {
3276                prefix= this.formatter.WILDCARD_SUPER;
3277            }
3278            
3279            int boundKindChange= getChangeKind(node, WildcardType.UPPER_BOUND_PROPERTY);
3280            if (boundKindChange != RewriteEvent.UNCHANGED) {
3281                int boundTypeChange= getChangeKind(node, WildcardType.BOUND_PROPERTY);
3282                if (boundTypeChange != RewriteEvent.INSERTED && boundTypeChange != RewriteEvent.REMOVED) {
3283                    ASTNode type= (ASTNode) getOriginalValue(node, WildcardType.BOUND_PROPERTY);
3284                    String JavaDoc str= prefix.getPrefix(0);
3285                    doTextReplace(pos, type.getStartPosition() - pos, str, getEditGroup(node, WildcardType.BOUND_PROPERTY));
3286                }
3287            }
3288            rewriteNode(node, WildcardType.BOUND_PROPERTY, pos, prefix);
3289        } catch (CoreException e) {
3290            handleException(e);
3291        }
3292        return false;
3293    }
3294    
3295    final void handleException(Throwable JavaDoc e) {
3296        IllegalArgumentException JavaDoc runtimeException= new IllegalArgumentException JavaDoc("Document does not match the AST"); //$NON-NLS-1$
3297
runtimeException.initCause(e);
3298        throw runtimeException;
3299    }
3300}
3301
Popular Tags