View | Details | Raw Unified | Return to bug 91938
Collapse All | Expand All

(-)dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java (-2 / +6 lines)
Lines 178-187 Link Here
178
		if (rootNode != null) {
178
		if (rootNode != null) {
179
			//validateASTNotModified(rootNode);
179
			//validateASTNotModified(rootNode);
180
			
180
			
181
			getRewriteEventStore().markMovedNodesRemoved();
181
			TargetSourceRangeComputer sourceRangeComputer= getExtendedSourceRangeComputer();
182
			
183
			this.eventStore.prepareMovedNodes(sourceRangeComputer);
182
184
183
			ASTRewriteAnalyzer visitor= new ASTRewriteAnalyzer(document, result, this.eventStore, this.nodeStore, options, getExtendedSourceRangeComputer());
185
			ASTRewriteAnalyzer visitor= new ASTRewriteAnalyzer(document, result, this.eventStore, this.nodeStore, options, sourceRangeComputer);
184
			rootNode.accept(visitor); // throws IllegalArgumentException
186
			rootNode.accept(visitor); // throws IllegalArgumentException
187
			
188
			this.eventStore.revertMovedNodes();
185
		}
189
		}
186
		return result;
190
		return result;
187
	}
191
	}
(-)dom/org/eclipse/jdt/core/dom/rewrite/ListRewrite.java (-13 / +46 lines)
Lines 13-31 Link Here
13
import java.util.Collections;
13
import java.util.Collections;
14
import java.util.List;
14
import java.util.List;
15
15
16
import org.eclipse.text.edits.TextEditGroup;
17
18
import org.eclipse.jdt.core.dom.ASTNode;
16
import org.eclipse.jdt.core.dom.ASTNode;
17
import org.eclipse.jdt.core.dom.Block;
19
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
18
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
20
import org.eclipse.jdt.core.dom.FieldDeclaration;
19
import org.eclipse.jdt.core.dom.FieldDeclaration;
21
import org.eclipse.jdt.core.dom.Statement;
20
import org.eclipse.jdt.core.dom.Statement;
22
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
21
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
23
24
import org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent;
22
import org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent;
25
import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
23
import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
26
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent;
24
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent;
27
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore;
25
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore;
28
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
26
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
27
import org.eclipse.text.edits.TextEditGroup;
29
28
30
/**
29
/**
31
 * For describing manipulations to a child list property of an AST node.
30
 * For describing manipulations to a child list property of an AST node.
Lines 290-307 Link Here
290
	}
289
	}
291
	
290
	
292
	
291
	
293
	private ASTNode createTargetNode(ASTNode first, ASTNode last, boolean isMove) {
292
	private ASTNode createTargetNode(ASTNode first, ASTNode last, boolean isMove, ASTNode replacingNode, TextEditGroup editGroup) {
294
		if (first == null || last == null) {
293
		if (first == null || last == null) {
295
			throw new IllegalArgumentException();
294
			throw new IllegalArgumentException();
296
		}
295
		}
297
		//validateIsInsideAST(node);
296
298
		CopySourceInfo info= getRewriteStore().markAsRangeCopySource(this.parent, this.childProperty, first, last, isMove);
299
	
300
		NodeInfoStore nodeStore= this.rewriter.getNodeStore();
297
		NodeInfoStore nodeStore= this.rewriter.getNodeStore();
301
		ASTNode placeholder= nodeStore.newPlaceholderNode(first.getNodeType()); // revisit: could use list type
298
		ASTNode placeholder= nodeStore.newPlaceholderNode(first.getNodeType()); // revisit: could use list type
302
		if (placeholder == null) {
299
		if (placeholder == null) {
303
			throw new IllegalArgumentException("Creating a target node is not supported for nodes of type" + first.getClass().getName()); //$NON-NLS-1$
300
			throw new IllegalArgumentException("Creating a target node is not supported for nodes of type" + first.getClass().getName()); //$NON-NLS-1$
304
		}
301
		}
302
		
303
		Block internalPlaceHolder= nodeStore.createCollapsePlaceholder();
304
		CopySourceInfo info= getRewriteStore().createRangeCopy(this.parent, this.childProperty, first, last, isMove, internalPlaceHolder, replacingNode, editGroup);
305
		nodeStore.markAsCopyTarget(placeholder, info);
305
		nodeStore.markAsCopyTarget(placeholder, info);
306
		
306
		
307
		return placeholder;		
307
		return placeholder;		
Lines 318-331 Link Here
318
	 * @param first the node that starts the range
318
	 * @param first the node that starts the range
319
	 * @param last the node that ends the range
319
	 * @param last the node that ends the range
320
	 * @return the new placeholder node
320
	 * @return the new placeholder node
321
	 * @throws IllegalArgumentException if the node is null, or if the node
321
	 * @throws IllegalArgumentException An exception is thrown if the first or last node
322
	 * is not part of this rewriter's AST
322
	 * are <code>null</code>, if a node is not a child of the current list or if the first node
323
	 * is not before the last node. An <code>IllegalArgumentException</code> is
324
	 * also thrown if the copied range is overlapping with an other moved or copied range. 
323
	 */
325
	 */
324
	public final ASTNode createCopyTarget(ASTNode first, ASTNode last) {
326
	public final ASTNode createCopyTarget(ASTNode first, ASTNode last) {
325
		if (first == last) {
327
		if (first == last) {
326
			return this.rewriter.createCopyTarget(first);
328
			return this.rewriter.createCopyTarget(first);
327
		} else {
329
		} else {
328
			return createTargetNode(first, last, false);
330
			return createTargetNode(first, last, false, null, null);
329
		}
331
		}
330
	}
332
	}
331
	
333
	
Lines 340-355 Link Here
340
	 * @param first the node that starts the range
342
	 * @param first the node that starts the range
341
	 * @param last the node that ends the range
343
	 * @param last the node that ends the range
342
	 * @return the new placeholder node
344
	 * @return the new placeholder node
343
	 * @throws IllegalArgumentException if the node is null, or if the node
345
	 * @throws IllegalArgumentException An exception is thrown if the first or last node
344
	 * is not part of this rewriter's AST
346
	 * are <code>null</code>, if a node is not a child of the current list or if the first node
347
	 * is not before the last node. An <code>IllegalArgumentException</code> is
348
	 * also thrown if the moved range is overlapping with an other moved or copied range. 
345
	 * 
349
	 * 
346
	 * @since 3.1
350
	 * @since 3.1
347
	 */
351
	 */
348
	public final ASTNode createMoveTarget(ASTNode first, ASTNode last) {
352
	public final ASTNode createMoveTarget(ASTNode first, ASTNode last) {
353
		return createMoveTarget(first, last, null, null);
354
	}
355
	
356
	/**
357
	 * Creates and returns a placeholder node for a move of a range of nodes of the
358
	 * current list. The moved nodes can optionally be replaced by a specified node.
359
	 * 
360
	 * The placeholder node can either be inserted as new or used to replace an
361
	 * existing node. When the document is rewritten, a copy of the source code 
362
	 * for the given node range is inserted into the output document at the position
363
	 * corresponding to the placeholder (indentation is adjusted).
364
	 * 
365
	 * @param first the node that starts the range
366
	 * @param last the node that ends the range
367
	 * @param replacingNode a node that is set at the location of the moved nodes
368
	 * or <code>null</code> to remove all nodes
369
	 * @param editGroup the edit group in which to collect the corresponding
370
	 * text edits fro a replace, or <code>null</code> if ungrouped
371
	 * @return the new placeholder node
372
	 * @throws IllegalArgumentException An exception is thrown if the first or
373
	 * last node are <code>null</code>, if a node is not a child of the current list or
374
	 * if the first node is not before the last node. An <code>IllegalArgumentException
375
	 * </code> is also thrown if the moved range is overlapping with an other moved
376
	 * or copied range. 
377
	 * 
378
	 * @since 3.1
379
	 */
380
	public final ASTNode createMoveTarget(ASTNode first, ASTNode last, ASTNode replacingNode, TextEditGroup editGroup) {
349
		if (first == last) {
381
		if (first == last) {
382
			replace(first, replacingNode, editGroup);
350
			return this.rewriter.createMoveTarget(first);
383
			return this.rewriter.createMoveTarget(first);
351
		} else {
384
		} else {
352
			return createTargetNode(first, last, true);
385
			return createTargetNode(first, last, true, replacingNode, editGroup);
353
		}
386
		}
354
	}
387
	}
355
	
388
	
(-)dom/org/eclipse/jdt/core/dom/rewrite/TargetSourceRangeComputer.java (-4 / +6 lines)
Lines 125-133 Link Here
125
	 * that should be replaced (or deleted)
125
	 * that should be replaced (or deleted)
126
	 */
126
	 */
127
	public SourceRange computeSourceRange(ASTNode node) {
127
	public SourceRange computeSourceRange(ASTNode node) {
128
		CompilationUnit cu = (CompilationUnit) node.getRoot();
128
		ASTNode root= node.getRoot();
129
		return new SourceRange(
129
		if (root instanceof CompilationUnit) {
130
				cu.getExtendedStartPosition(node),
130
			CompilationUnit cu= (CompilationUnit) root;
131
				cu.getExtendedLength(node));
131
			return new SourceRange(cu.getExtendedStartPosition(node), cu.getExtendedLength(node));
132
		}
133
		return new SourceRange(node.getStartPosition(), node.getLength());
132
	}
134
	}
133
}
135
}
(-)dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java (-98 / +25 lines)
Lines 114-154 Link Here
114
	}
114
	}
115
	
115
	
116
	/**
116
	/**
117
	 * Returns the extended source range computer for this AST rewriter.
117
	 * Returns the extended source range for a node.
118
	 * 
118
	 * 
119
	 * @return an extended source range computer (never null)
119
	 * @return an extended source range (never null)
120
	 * @since 3.1
120
	 * @since 3.1
121
	 */
121
	 */
122
	private TargetSourceRangeComputer getExtendedSourceRangeComputer() {
123
		return this.extendedSourceRangeComputer;
124
	}
125
	
126
	final SourceRange getExtendedRange(ASTNode node) {
122
	final SourceRange getExtendedRange(ASTNode node) {
127
		return getExtendedSourceRangeComputer().computeSourceRange(node);
123
		if (node.getParent() == null) {
124
			return new SourceRange(node.getStartPosition(), node.getLength());
125
		}
126
		return this.extendedSourceRangeComputer.computeSourceRange(node);
128
	}
127
	}
129
	
128
	
130
	final int getExtendedOffset(ASTNode node) {
129
	final int getExtendedOffset(ASTNode node) {
131
		return getExtendedSourceRangeComputer().computeSourceRange(node).getStartPosition();
130
		return getExtendedRange(node).getStartPosition();
132
	}
131
	}
133
	
132
	
134
	final int getExtendedEnd(ASTNode node) {
133
	final int getExtendedEnd(ASTNode node) {
135
		TargetSourceRangeComputer.SourceRange range =
134
		TargetSourceRangeComputer.SourceRange range= getExtendedRange(node);
136
			getExtendedSourceRangeComputer().computeSourceRange(node);
137
		return range.getStartPosition() + range.getLength();
135
		return range.getStartPosition() + range.getLength();
138
	}
136
	}
139
	
137
	
140
	final TextEdit getCopySourceEdit(CopySourceInfo info) {
138
	final TextEdit getCopySourceEdit(CopySourceInfo info) {
141
		TextEdit edit= (TextEdit) this.sourceCopyInfoToEdit.get(info);
139
		TextEdit edit= (TextEdit) this.sourceCopyInfoToEdit.get(info);
142
		if (edit == null) {
140
		if (edit == null) {
143
			int start, end;
141
			SourceRange range= getExtendedRange(info.getNode());
144
			if (info.getStartNode() == info.getEndNode()) {
142
			int start= range.getStartPosition();
145
				SourceRange range= getExtendedRange(info.getStartNode());
143
			int end= start + range.getLength();
146
				start= range.getStartPosition();
147
				end= start + range.getLength();
148
			} else {
149
				start= getExtendedOffset(info.getStartNode());
150
				end= getExtendedEnd(info.getEndNode());
151
			}
152
			if (info.isMove) {
144
			if (info.isMove) {
153
				MoveSourceEdit moveSourceEdit= new MoveSourceEdit(start, end - start);
145
				MoveSourceEdit moveSourceEdit= new MoveSourceEdit(start, end - start);
154
				moveSourceEdit.setTargetEdit(new MoveTargetEdit(0));
146
				moveSourceEdit.setTargetEdit(new MoveTargetEdit(0));
Lines 284-315 Link Here
284
		if (property.isChildProperty() && node != null) {
276
		if (property.isChildProperty() && node != null) {
285
			return doVisit((ASTNode) node);
277
			return doVisit((ASTNode) node);
286
		} else if (property.isChildListProperty()) {
278
		} else if (property.isChildListProperty()) {
287
			boolean hasRangeCopySources= this.eventStore.hasRangeCopySources(parent, property);
279
			return doVisitList((List) node, offset);
288
			return doVisitList((List) node, offset, hasRangeCopySources);
289
		}
280
		}
290
		return offset;
281
		return offset;
291
	}
282
	}
292
	
283
	
293
	private int doVisitList(List list, int offset, boolean hasRangeCopySources) {
284
	private int doVisitList(List list, int offset) {
294
		if (hasRangeCopySources) {
285
		int endPos= offset;
295
			// list with copy source ranges
286
		for (Iterator iter= list.iterator(); iter.hasNext();) {
296
			Stack nodeRangeEndStack= new Stack();
287
			ASTNode curr= ((ASTNode) iter.next());
297
			int endPos= offset;
288
			endPos= doVisit(curr);
298
			for (Iterator iter= list.iterator(); iter.hasNext();) {
299
				ASTNode curr= ((ASTNode) iter.next());
300
				doCopySourcePreVisit(this.eventStore.getRangeCopySources(curr), nodeRangeEndStack);
301
				endPos= doVisit(curr);
302
				doCopySourcePostVisit(curr, nodeRangeEndStack);
303
			}
304
			return endPos;
305
		} else {
306
			int endPos= offset;
307
			for (Iterator iter= list.iterator(); iter.hasNext();) {
308
				ASTNode curr= ((ASTNode) iter.next());
309
				endPos= doVisit(curr);
310
			}
311
			return endPos;
312
		}
289
		}
290
		return endPos;
313
	}
291
	}
314
	
292
	
315
	final void voidVisit(ASTNode node) {
293
	final void voidVisit(ASTNode node) {
Lines 321-362 Link Here
321
		if (property.isChildProperty() && node != null) {
299
		if (property.isChildProperty() && node != null) {
322
			voidVisit((ASTNode) node);
300
			voidVisit((ASTNode) node);
323
		} else if (property.isChildListProperty()) {
301
		} else if (property.isChildListProperty()) {
324
			boolean hasRangeCopySources= this.eventStore.hasRangeCopySources(parent, property);
302
			voidVisitList((List) node);
325
			voidVisitList((List) node, hasRangeCopySources);
326
		}
303
		}
327
	}
304
	}
328
	
305
	
329
	private void voidVisitList(List list, boolean hasRangeCopySources) {
306
	private void voidVisitList(List list) {
330
		if (hasRangeCopySources) {
307
		for (Iterator iter= list.iterator(); iter.hasNext();) {
331
			// list with copy source ranges
308
			doVisit(((ASTNode) iter.next()));
332
			Stack nodeRangeEndStack= new Stack();
333
			for (Iterator iter= list.iterator(); iter.hasNext();) {
334
				ASTNode curr= ((ASTNode) iter.next());
335
				doCopySourcePreVisit(this.eventStore.getRangeCopySources(curr), nodeRangeEndStack);
336
				doVisit(curr);
337
				doCopySourcePostVisit(curr, nodeRangeEndStack);
338
			}
339
		} else {
340
			for (Iterator iter= list.iterator(); iter.hasNext();) {
341
				doVisit(((ASTNode) iter.next()));
342
			}
343
		}
309
		}
344
	}
310
	}
345
	
311
	
346
	private final boolean doVisitUnchangedChildren(ASTNode parent) {
312
	private final boolean doVisitUnchangedChildren(ASTNode parent) {
347
		List properties= parent.structuralPropertiesForType();
313
		List properties= parent.structuralPropertiesForType();
348
		for (int i= 0; i < properties.size(); i++) {
314
		for (int i= 0; i < properties.size(); i++) {
349
			StructuralPropertyDescriptor property= (StructuralPropertyDescriptor) properties.get(i);
315
			voidVisit(parent, (StructuralPropertyDescriptor) properties.get(i));
350
			if (property.isChildProperty()) {
351
				ASTNode child= (ASTNode) parent.getStructuralProperty(property);
352
				if (child != null) {
353
					voidVisit(child);
354
				}
355
			} else if (property.isChildListProperty()) {
356
				List list= (List) parent.getStructuralProperty(property);
357
				boolean hasRangeCopySources= this.eventStore.hasRangeCopySources(parent, property);
358
				voidVisitList(list, hasRangeCopySources);
359
			}
360
		}
316
		}
361
		return false;
317
		return false;
362
	}
318
	}
Lines 409-416 Link Here
409
		
365
		
410
		protected RewriteEvent[] list;
366
		protected RewriteEvent[] list;
411
		
367
		
412
		private Stack copyRangeEndStack;
413
		
414
		protected final ASTNode getOriginalNode(int index) {
368
		protected final ASTNode getOriginalNode(int index) {
415
			return (ASTNode) this.list[index].getOriginalValue();
369
			return (ASTNode) this.list[index].getOriginalValue();
416
		}
370
		}
Lines 465-472 Link Here
465
			this.startPos= offset;
419
			this.startPos= offset;
466
			this.list= getEvent(parent, property).getChildren();
420
			this.list= getEvent(parent, property).getChildren();
467
			
421
			
468
			initCopyRangeChecks(parent, property);
469
			
470
			int total= this.list.length;
422
			int total= this.list.length;
471
			if (total == 0) {
423
			if (total == 0) {
472
				return this.startPos;
424
				return this.startPos;
Lines 543-559 Link Here
543
					if (i > lastNonDelete && separatorState == EXISTING) {
495
					if (i > lastNonDelete && separatorState == EXISTING) {
544
						// is last, remove previous separator: split delete to allow range copies
496
						// is last, remove previous separator: split delete to allow range copies
545
						doTextRemove(prevEnd, currPos - prevEnd, editGroup); // remove separator
497
						doTextRemove(prevEnd, currPos - prevEnd, editGroup); // remove separator
546
						checkForRangeStart(node);
547
						doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup); // remove node
498
						doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup); // remove node
548
						checkForRangeEnd(node);
549
						currPos= currEnd;
499
						currPos= currEnd;
550
						prevEnd= currEnd;
500
						prevEnd= currEnd;
551
					} else {
501
					} else {
552
						// remove element and next separator
502
						// remove element and next separator
553
						int end= getStartOfNextNode(nextIndex, currEnd); // start of next
503
						int end= getStartOfNextNode(nextIndex, currEnd); // start of next
554
						checkForRangeStart(node);
555
						doTextRemoveAndVisit(currPos, currEnd - currPos, node, getEditGroup(currEvent)); // remove node
504
						doTextRemoveAndVisit(currPos, currEnd - currPos, node, getEditGroup(currEvent)); // remove node
556
						checkForRangeEnd(node);
557
						doTextRemove(currEnd, end - currEnd, editGroup); // remove separator
505
						doTextRemove(currEnd, end - currEnd, editGroup); // remove separator
558
						currPos= end;
506
						currPos= end;
559
						prevEnd= currEnd;
507
						prevEnd= currEnd;
Lines 566-582 Link Here
566
						
514
						
567
						TextEditGroup editGroup= getEditGroup(currEvent);
515
						TextEditGroup editGroup= getEditGroup(currEvent);
568
						ASTNode changed= (ASTNode) currEvent.getNewValue();
516
						ASTNode changed= (ASTNode) currEvent.getNewValue();
569
						checkForRangeStart(node);
570
						doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup);
517
						doTextRemoveAndVisit(currPos, currEnd - currPos, node, editGroup);
571
						doTextInsert(currPos, changed, getNodeIndent(i), true, editGroup);
518
						doTextInsert(currPos, changed, getNodeIndent(i), true, editGroup);
572
						checkForRangeEnd(node);
573
						
519
						
574
						prevEnd= currEnd;
520
						prevEnd= currEnd;
575
					} else { // is unchanged
521
					} else { // is unchanged
576
						ASTNode node= (ASTNode) currEvent.getOriginalValue();
522
						ASTNode node= (ASTNode) currEvent.getOriginalValue();
577
						checkForRangeStart(node);
578
						voidVisit(node);
523
						voidVisit(node);
579
						checkForRangeEnd(node);
580
					}
524
					}
581
					if (i == lastNonInsert) { // last node or next nodes are all inserts
525
					if (i == lastNonInsert) { // last node or next nodes are all inserts
582
						separatorState= NONE;
526
						separatorState= NONE;
Lines 600-622 Link Here
600
			return currPos;
544
			return currPos;
601
		}
545
		}
602
		
546
		
603
		private void initCopyRangeChecks(ASTNode parent, StructuralPropertyDescriptor property) {
604
			if (ASTRewriteAnalyzer.this.eventStore.hasRangeCopySources(parent, property)) {
605
				this.copyRangeEndStack= new Stack();
606
			}
607
		}
608
609
		private void checkForRangeStart(ASTNode node) {
610
			if (this.copyRangeEndStack != null) {
611
				doCopySourcePreVisit(ASTRewriteAnalyzer.this.eventStore.getRangeCopySources(node), this.copyRangeEndStack);
612
			}
613
		}
614
		
615
		private void checkForRangeEnd(ASTNode node) {
616
			if (this.copyRangeEndStack != null) {
617
				doCopySourcePostVisit(node, this.copyRangeEndStack);
618
			}
619
		}
620
	}
547
	}
621
				
548
				
622
	private int rewriteRequiredNode(ASTNode parent, StructuralPropertyDescriptor property) {
549
	private int rewriteRequiredNode(ASTNode parent, StructuralPropertyDescriptor property) {
Lines 1109-1115 Link Here
1109
				String destIndentString=  this.formatter.getIndentString(getCurrentLine(formatted, offset));
1036
				String destIndentString=  this.formatter.getIndentString(getCurrentLine(formatted, offset));
1110
				if (data instanceof CopyPlaceholderData) { // replace with a copy/move target
1037
				if (data instanceof CopyPlaceholderData) { // replace with a copy/move target
1111
					CopySourceInfo copySource= ((CopyPlaceholderData) data).copySource;
1038
					CopySourceInfo copySource= ((CopyPlaceholderData) data).copySource;
1112
					int srcIndentLevel= getIndent(copySource.getStartNode().getStartPosition());
1039
					int srcIndentLevel= getIndent(copySource.getNode().getStartPosition());
1113
					TextEdit sourceEdit= getCopySourceEdit(copySource);
1040
					TextEdit sourceEdit= getCopySourceEdit(copySource);
1114
					doTextCopy(sourceEdit, insertOffset, srcIndentLevel, destIndentString, editGroup);
1041
					doTextCopy(sourceEdit, insertOffset, srcIndentLevel, destIndentString, editGroup);
1115
					currPos= offset + curr.length; // continue to insert after the replaced string
1042
					currPos= offset + curr.length; // continue to insert after the replaced string
Lines 1297-1303 Link Here
1297
				TextEdit edit= getCopySourceEdit(curr);
1224
				TextEdit edit= getCopySourceEdit(curr);
1298
				addEdit(edit);
1225
				addEdit(edit);
1299
				this.currentEdit= edit;
1226
				this.currentEdit= edit;
1300
				nodeEndStack.push(curr.getEndNode());
1227
				nodeEndStack.push(curr.getNode());
1301
			}
1228
			}
1302
		}
1229
		}
1303
	}
1230
	}
(-)dom/org/eclipse/jdt/internal/core/dom/rewrite/RewriteEventStore.java (-122 / +282 lines)
Lines 10-32 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.core.dom.rewrite;
11
package org.eclipse.jdt.internal.core.dom.rewrite;
12
12
13
import java.util.ArrayList;
13
import java.util.*;
14
import java.util.Arrays;
15
import java.util.Collections;
16
import java.util.Comparator;
17
import java.util.HashSet;
18
import java.util.IdentityHashMap;
19
import java.util.Iterator;
20
import java.util.List;
21
import java.util.Map;
22
import java.util.Set;
23
24
import org.eclipse.text.edits.TextEditGroup;
25
14
26
import org.eclipse.jdt.core.Signature;
15
import org.eclipse.jdt.core.Signature;
27
16
import org.eclipse.jdt.core.dom.*;
28
import org.eclipse.jdt.core.dom.ASTNode;
17
import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
29
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
18
import org.eclipse.text.edits.TextEditGroup;
30
19
31
20
32
/**
21
/**
Lines 37-44 Link Here
37
	
26
	
38
27
39
	public final class PropertyLocation {
28
	public final class PropertyLocation {
40
		private ASTNode parent;
29
		private final ASTNode parent;
41
		private StructuralPropertyDescriptor property;
30
		private final StructuralPropertyDescriptor property;
42
		
31
		
43
		public PropertyLocation(ASTNode parent, StructuralPropertyDescriptor property) {
32
		public PropertyLocation(ASTNode parent, StructuralPropertyDescriptor property) {
44
			this.parent= parent;
33
			this.parent= parent;
Lines 52-57 Link Here
52
		public StructuralPropertyDescriptor getProperty() {
41
		public StructuralPropertyDescriptor getProperty() {
53
			return this.property;
42
			return this.property;
54
		}
43
		}
44
		
45
		public boolean equals(Object obj) {
46
			if (obj != null && obj.getClass().equals(this.getClass())) {
47
				PropertyLocation other= (PropertyLocation) obj;
48
				return other.getParent().equals(getParent()) && other.getProperty().equals(getProperty());
49
			}
50
			return false;
51
		}
52
		
53
		public int hashCode() {
54
			return getParent().hashCode() + getProperty().hashCode();
55
		}
56
		
55
	}
57
	}
56
	
58
	
57
	/**
59
	/**
Lines 92-110 Link Here
92
		}
94
		}
93
	}
95
	}
94
	
96
	
95
	public static class CopySourceInfo {
97
	public static class CopySourceInfo implements Comparable {
96
		public final ASTNode parent;
98
		public final PropertyLocation location; // can be null, only used to mark as removed on move
97
		public final StructuralPropertyDescriptor childProperty;
99
		private final ASTNode node;
100
		public final boolean isMove;
101
		
102
		public CopySourceInfo(PropertyLocation location, ASTNode node, boolean isMove) {
103
			this.location= location;
104
			this.node= node;
105
			this.isMove= isMove;
106
		}
107
		
108
		public ASTNode getNode() {
109
			return this.node;
110
		}
111
		
112
		public int compareTo(Object o2) {
113
			CopySourceInfo r2= (CopySourceInfo) o2;
114
		
115
			int startDiff= this.getNode().getStartPosition() - r2.getNode().getStartPosition();
116
			if (startDiff != 0) {
117
				return startDiff; // insert before if start node is first
118
			}
119
120
			if (r2.isMove != this.isMove) {
121
				return this.isMove ? -1 : 1; // first move then copy
122
			}
123
			return 0;
124
		}
125
		
126
		public String toString() {
127
			StringBuffer buf= new StringBuffer();
128
			if (this.isMove) {
129
				buf.append("move source: "); //$NON-NLS-1$
130
			} else {
131
				buf.append("copy source: "); //$NON-NLS-1$
132
			}
133
			buf.append(this.node);
134
			return buf.toString();
135
		}
136
	}
137
	
138
	private static class NodeRangeInfo implements Comparable {
98
		private final ASTNode first;
139
		private final ASTNode first;
99
		private final ASTNode last;
140
		private final ASTNode last;
100
		public final boolean isMove;
141
		public final CopySourceInfo copyInfo; // containing the internal placeholder and the 'isMove' flag
142
		public final ASTNode replacingNode;
143
		public final TextEditGroup editGroup;
101
		
144
		
102
		public CopySourceInfo(ASTNode parent, StructuralPropertyDescriptor childProperty, ASTNode first, ASTNode last, boolean isMove) {
145
		public NodeRangeInfo(ASTNode parent, StructuralPropertyDescriptor childProperty, ASTNode first, ASTNode last, CopySourceInfo copyInfo, ASTNode replacingNode, TextEditGroup editGroup) {
103
			this.parent= parent;
104
			this.childProperty= childProperty;
105
			this.first= first;
146
			this.first= first;
106
			this.last= last;
147
			this.last= last;
107
			this.isMove= isMove;
148
			this.copyInfo= copyInfo;
149
			this.replacingNode= replacingNode;
150
			this.editGroup= editGroup;
108
		}
151
		}
109
		
152
		
110
		public ASTNode getStartNode() {
153
		public ASTNode getStartNode() {
Lines 114-152 Link Here
114
		public ASTNode getEndNode() {
157
		public ASTNode getEndNode() {
115
			return this.last;
158
			return this.last;
116
		}
159
		}
117
160
		
161
		public boolean isMove() {
162
			return this.copyInfo.isMove;
163
		}
164
		
165
		public Block getInternalPlaceholder() {
166
			return (Block) this.copyInfo.getNode();
167
		}
168
				
169
		public int compareTo(Object o2) {
170
			NodeRangeInfo r2= (NodeRangeInfo) o2;
171
		
172
			int startDiff= this.getStartNode().getStartPosition() - r2.getStartNode().getStartPosition();
173
			if (startDiff != 0) {
174
				return startDiff; // insert before if start node is first
175
			}
176
			int endDiff= this.getEndNode().getStartPosition() - r2.getEndNode().getStartPosition();
177
			if (endDiff != 0) {
178
				return -endDiff; // insert before if length is longer
179
			}
180
			if (r2.isMove() != this.isMove()) {
181
				return this.isMove() ? -1 : 1; // first move then copy
182
			}
183
			return 0;
184
		}
185
		
186
		public void updatePlaceholderSourceRanges(TargetSourceRangeComputer sourceRangeComputer) {
187
			TargetSourceRangeComputer.SourceRange startRange= sourceRangeComputer.computeSourceRange(getStartNode());
188
			TargetSourceRangeComputer.SourceRange endRange= sourceRangeComputer.computeSourceRange(getEndNode());
189
			int startPos= startRange.getStartPosition();
190
			int endPos= endRange.getStartPosition() + endRange.getLength();
191
			
192
			Block internalPlaceholder= getInternalPlaceholder();
193
			internalPlaceholder.setSourceRange(startPos, endPos - startPos);
194
		}
195
		
118
		public String toString() {
196
		public String toString() {
119
			StringBuffer buf= new StringBuffer();
197
			StringBuffer buf= new StringBuffer();
120
			if (this.first != this.last) {
198
			if (this.first != this.last) {
121
				buf.append("range ");  //$NON-NLS-1$
199
				buf.append("range ");  //$NON-NLS-1$
122
			}
200
			}
123
			if (this.isMove) {
201
			if (isMove()) {
124
				buf.append("move source: "); //$NON-NLS-1$
202
				buf.append("move source: "); //$NON-NLS-1$
125
			} else {
203
			} else {
126
				buf.append("copy source: "); //$NON-NLS-1$
204
				buf.append("copy source: "); //$NON-NLS-1$
127
			}
205
			}
128
			buf.append(this.first);
206
			buf.append(this.first);
129
			if (this.first != this.last) {
207
			buf.append(" - "); //$NON-NLS-1$
130
				buf.append(" - "); //$NON-NLS-1$
208
			buf.append(this.last);
131
				buf.append(this.last);
132
			}
133
			return buf.toString();
209
			return buf.toString();
134
		}
210
		}
135
	}
136
211
137
	public static class CopySourceInfoSorter implements Comparator {
138
212
139
		public int compare(Object o1, Object o2) {
140
			CopySourceInfo e1= (CopySourceInfo) o1;
141
			CopySourceInfo e2= (CopySourceInfo) o2;
142
			if (e1.isMove) {
143
				return -1;
144
			} else if (e2.isMove) {
145
				return 1;
146
			}
147
			return e2.getEndNode().getStartPosition() - e1.getEndNode().getStartPosition();
148
		}
149
	
150
	}
213
	}
151
	
214
	
152
	/**
215
	/**
Lines 166-173 Link Here
166
			} else {
229
			} else {
167
				this.sourceNodeIter= Collections.EMPTY_LIST.iterator();
230
				this.sourceNodeIter= Collections.EMPTY_LIST.iterator();
168
			}
231
			}
169
			if (RewriteEventStore.this.rangeCopySources != null) {
232
			if (RewriteEventStore.this.nodeRangeInfos != null) {
170
				this.rangeNodeIter= RewriteEventStore.this.rangeCopySources.iterator();
233
				this.rangeNodeIter= RewriteEventStore.this.nodeRangeInfos.keySet().iterator();
171
			} else {
234
			} else {
172
				this.rangeNodeIter= Collections.EMPTY_LIST.iterator();
235
				this.rangeNodeIter= Collections.EMPTY_LIST.iterator();
173
			}
236
			}
Lines 193-202 Link Here
193
				return ((EventHolder) this.eventIter.next()).parent;
256
				return ((EventHolder) this.eventIter.next()).parent;
194
			}
257
			}
195
			if (this.sourceNodeIter.hasNext()) {
258
			if (this.sourceNodeIter.hasNext()) {
196
				return ((CopySourceInfo) this.sourceNodeIter.next()).getStartNode();
259
				return ((CopySourceInfo) this.sourceNodeIter.next()).getNode();
197
			}
260
			}
198
			if (this.rangeNodeIter.hasNext()) {
261
			if (this.rangeNodeIter.hasNext()) {
199
				return ((CopySourceInfo) this.rangeNodeIter.next()).parent;
262
				return ((PropertyLocation) this.rangeNodeIter.next()).getParent();
200
			}
263
			}
201
			return this.trackedNodeIter.next();
264
			return this.trackedNodeIter.next();
202
		}
265
		}
Lines 223-233 Link Here
223
	/** Maps events to group descriptions */
286
	/** Maps events to group descriptions */
224
	private Map editGroups;
287
	private Map editGroups;
225
		
288
		
226
	/** Stores which nodes are source of a copy or move (list of CopyRangeSourceInfo)*/
289
	/** Stores which nodes are source of a copy or move (list of CopySourceInfo)*/
227
	List nodeCopySources;
290
	List nodeCopySources;
228
	
291
	
229
	/** Stores which node ranges that are source of a copy or move (list of CopyRangeSourceInfo)*/
292
	/** Stores node ranges that are used to copy or move (map of <PropertyLocation, CopyRangeInfo>)*/
230
	List rangeCopySources;
293
	Map nodeRangeInfos;
231
	
294
	
232
	/** Stores which nodes are tracked and the corresponding edit group*/
295
	/** Stores which nodes are tracked and the corresponding edit group*/
233
	Map trackedNodes;
296
	Map trackedNodes;
Lines 250-255 Link Here
250
		
313
		
251
		this.nodePropertyMapper= null;
314
		this.nodePropertyMapper= null;
252
		this.nodeCopySources= null;
315
		this.nodeCopySources= null;
316
		this.nodeRangeInfos= null;
253
	}
317
	}
254
	
318
	
255
	/**
319
	/**
Lines 485-492 Link Here
485
		setTrackedNodeData(node, editGroup);
549
		setTrackedNodeData(node, editGroup);
486
	}	
550
	}	
487
	
551
	
488
	public final CopySourceInfo markAsCopySource(ASTNode parent, StructuralPropertyDescriptor property, ASTNode node, boolean isMove) {
552
	private final CopySourceInfo createCopySourceInfo(PropertyLocation location, ASTNode node, boolean isMove) {
489
		CopySourceInfo copySource= new CopySourceInfo(parent, property, node, node, isMove);
553
		CopySourceInfo copySource= new CopySourceInfo(location, node, isMove);
490
		
554
		
491
		if (this.nodeCopySources == null) {
555
		if (this.nodeCopySources == null) {
492
			this.nodeCopySources= new ArrayList();
556
			this.nodeCopySources= new ArrayList();
Lines 495-512 Link Here
495
		return copySource;
559
		return copySource;
496
	}
560
	}
497
	
561
	
498
	public final CopySourceInfo markAsRangeCopySource(ASTNode parent, StructuralPropertyDescriptor property, ASTNode first, ASTNode last, boolean isMove) {
562
	public final CopySourceInfo markAsCopySource(ASTNode parent, StructuralPropertyDescriptor property, ASTNode node, boolean isMove) {
499
		CopySourceInfo copySource= new CopySourceInfo(parent, property, first, last, isMove);
563
		return createCopySourceInfo(new PropertyLocation(parent, property), node, isMove);
500
		assertNoOverlap(copySource);
564
	}
565
	
566
	public final CopySourceInfo createRangeCopy(ASTNode parent, StructuralPropertyDescriptor childProperty, ASTNode first, ASTNode last, boolean isMove, ASTNode internalPlaceholder, ASTNode replacingNode, TextEditGroup editGroup) {
567
		CopySourceInfo copyInfo= createCopySourceInfo(null, internalPlaceholder, isMove);
501
		
568
		
502
		if (this.rangeCopySources == null) {
569
		NodeRangeInfo copyRangeInfo= new NodeRangeInfo(parent, childProperty, first, last, copyInfo, replacingNode, editGroup);
503
			this.rangeCopySources= new ArrayList();
570
		
571
		ListRewriteEvent listEvent= getListEvent(parent, childProperty, true);
572
		
573
		int indexFirst= listEvent.getIndex(first, ListRewriteEvent.OLD);
574
		if (indexFirst == -1) {
575
			throw new IllegalArgumentException("Start node is not a original child of the given list"); //$NON-NLS-1$
504
		}
576
		}
505
		this.rangeCopySources.add(copySource);
577
		int indexLast= listEvent.getIndex(last, ListRewriteEvent.OLD);
506
		return copySource;
578
		if (indexLast == -1) {
579
			throw new IllegalArgumentException("End node is not a original child of the given list"); //$NON-NLS-1$
580
		}
581
582
		if (indexFirst > indexLast) {
583
			throw new IllegalArgumentException("Start node must be before end node"); //$NON-NLS-1$
584
		}
585
		
586
		if (this.nodeRangeInfos == null) {
587
			this.nodeRangeInfos= new HashMap();
588
		}
589
		PropertyLocation loc= new PropertyLocation(parent, childProperty);
590
		List innerList= (List) this.nodeRangeInfos.get(loc);
591
		if (innerList == null) {
592
			innerList= new ArrayList(2);
593
			this.nodeRangeInfos.put(loc, innerList);
594
		} else {
595
			assertNoOverlap(listEvent, indexFirst, indexLast, innerList);
596
		}
597
		innerList.add(copyRangeInfo);
598
		
599
		
600
		return copyInfo;
507
	}
601
	}
508
	
602
	
509
	
510
	public CopySourceInfo[] getNodeCopySources(ASTNode node) {
603
	public CopySourceInfo[] getNodeCopySources(ASTNode node) {
511
		if (this.nodeCopySources == null) {
604
		if (this.nodeCopySources == null) {
512
			return null;
605
			return null;
Lines 514-618 Link Here
514
		return internalGetCopySources(this.nodeCopySources, node);
607
		return internalGetCopySources(this.nodeCopySources, node);
515
	}
608
	}
516
	
609
	
517
	public CopySourceInfo[] getRangeCopySources(ASTNode node) {
518
		if (this.rangeCopySources == null) {
519
			return null;
520
		}
521
		return internalGetCopySources(this.rangeCopySources, node);
522
	}
523
	
524
	public boolean hasRangeCopySources(ASTNode parent, StructuralPropertyDescriptor property) {
525
		if (this.rangeCopySources == null) {
526
			return false;
527
		}
528
		for (int i= 0; i < this.rangeCopySources.size(); i++) {
529
			CopySourceInfo curr= (CopySourceInfo) this.rangeCopySources.get(i);
530
			if (curr.parent == parent && curr.childProperty == property) {
531
				return true;
532
			}
533
		}
534
		return false;
535
	}
536
	
610
	
537
	public CopySourceInfo[] internalGetCopySources(List copySources, ASTNode node) {
611
	public CopySourceInfo[] internalGetCopySources(List copySources, ASTNode node) {
538
		ArrayList res= new ArrayList(3);
612
		ArrayList res= new ArrayList(3);
539
		for (int i= 0; i < copySources.size(); i++) {
613
		for (int i= 0; i < copySources.size(); i++) {
540
			CopySourceInfo curr= (CopySourceInfo) copySources.get(i);
614
			CopySourceInfo curr= (CopySourceInfo) copySources.get(i);
541
			if (curr.getStartNode() == node) {
615
			if (curr.getNode() == node) {
542
				res.add(curr);
616
				res.add(curr);
543
			}
617
			}
544
		}
618
		}
545
		if (res.isEmpty()) {
619
		if (res.isEmpty()) {
546
			return null;
620
			return null;
547
		}
621
		}
622
		
548
		CopySourceInfo[] arr= (CopySourceInfo[]) res.toArray(new CopySourceInfo[res.size()]);
623
		CopySourceInfo[] arr= (CopySourceInfo[]) res.toArray(new CopySourceInfo[res.size()]);
549
		if (arr.length > 1) {
624
		Arrays.sort(arr);
550
			Arrays.sort(arr, new CopySourceInfoSorter());
551
		}
552
		return arr;
625
		return arr;
553
	}
626
	}
554
	
627
	
555
	
628
	
556
	private void assertNoOverlap(CopySourceInfo copySource) {
629
	private void assertNoOverlap(ListRewriteEvent listEvent, int indexFirst, int indexLast, List innerList) {
557
		ASTNode parent= copySource.parent;
630
		for (Iterator iter= innerList.iterator(); iter.hasNext();) {
558
		StructuralPropertyDescriptor childProperty= copySource.childProperty;
631
			NodeRangeInfo curr= (NodeRangeInfo) iter.next();
559
		ASTNode first= copySource.getStartNode();
632
			int currStart= listEvent.getIndex(curr.getStartNode(), ListRewriteEvent.BOTH);
560
		ASTNode last= copySource.getEndNode();
633
			int currEnd= listEvent.getIndex(curr.getEndNode(), ListRewriteEvent.BOTH);
561
		
634
			if (currStart < indexFirst && currEnd < indexLast && currEnd >= indexFirst
562
		ListRewriteEvent listEvent= getListEvent(parent, childProperty, true);
635
					|| currStart > indexFirst && currStart <= currEnd && currEnd > indexLast) {
636
				throw new IllegalArgumentException("Range overlapps with an existing copy or move range"); //$NON-NLS-1$ 
637
			}
638
		}
639
	}
640
	
641
	public void prepareMovedNodes(TargetSourceRangeComputer sourceRangeComputer) {
642
		if (this.nodeCopySources != null) {
643
			prepareSingleNodeCopies();
644
		}
563
		
645
		
564
		int indexFirst= listEvent.getIndex(first, ListRewriteEvent.OLD);
646
		if (this.nodeRangeInfos != null) {
565
		if (indexFirst == -1) {
647
			prepareNodeRangeCopies(sourceRangeComputer);
566
			throw new IllegalArgumentException("Start node is not a original child of the given list"); //$NON-NLS-1$
567
		}
648
		}
568
		int indexLast= listEvent.getIndex(last, ListRewriteEvent.OLD);
649
	}
569
		if (indexLast == -1) {
650
	
570
			throw new IllegalArgumentException("End node is not a original child of the given list"); //$NON-NLS-1$
651
	public void revertMovedNodes() {
652
		if (this.nodeRangeInfos != null) {
653
			removeMoveRangePlaceholders();
571
		}
654
		}
572
655
	}
573
		if (indexFirst > indexLast) {
656
	
574
			throw new IllegalArgumentException("Start node must be before end node"); //$NON-NLS-1$
657
	private void removeMoveRangePlaceholders() {
658
		for (Iterator iter= this.nodeRangeInfos.entrySet().iterator(); iter.hasNext();) {
659
			Map.Entry entry= (Map.Entry) iter.next();
660
			Set placeholders= new HashSet(); // collect all placeholders
661
			List rangeInfos= (List) entry.getValue(); // list of CopySourceRange
662
			for (int i= 0; i < rangeInfos.size(); i++) {
663
				placeholders.add(((NodeRangeInfo) rangeInfos.get(i)).getInternalPlaceholder());
664
			}
665
			
666
			PropertyLocation loc= (PropertyLocation) entry.getKey();
667
			
668
			RewriteEvent[] children= getListEvent(loc.getParent(), loc.getProperty(), true).getChildren();
669
			List revertedChildren= new ArrayList();
670
			revertListWithRanges(children, placeholders, revertedChildren);
671
			RewriteEvent[] revertedChildrenArr= (RewriteEvent[]) revertedChildren.toArray(new RewriteEvent[revertedChildren.size()]);
672
			addEvent(loc.getParent(), loc.getProperty(), new ListRewriteEvent(revertedChildrenArr)); // replace the current edits
673
		}	
674
	}
675
	
676
	private void revertListWithRanges(RewriteEvent[] childEvents, Set placeholders, List revertedChildren) {
677
		for (int i= 0; i < childEvents.length; i++) {
678
			RewriteEvent event= childEvents[i];
679
			ASTNode node= (ASTNode) event.getOriginalValue();
680
			if (placeholders.contains(node)) {
681
				RewriteEvent[] placeholderChildren= getListEvent(node, Block.STATEMENTS_PROPERTY, false).getChildren();
682
				revertListWithRanges(placeholderChildren, placeholders, revertedChildren);
683
			} else {
684
				revertedChildren.add(event);
685
			}
575
		}
686
		}
576
		if (this.rangeCopySources != null) {
687
	}
577
			for (Iterator iter= this.rangeCopySources.iterator(); iter.hasNext();) {
688
578
				CopySourceInfo info= (CopySourceInfo) iter.next();
689
	private void prepareNodeRangeCopies(TargetSourceRangeComputer sourceRangeComputer) {
579
				if (info.parent == parent && info.childProperty == childProperty) {
690
		for (Iterator iter= this.nodeRangeInfos.entrySet().iterator(); iter.hasNext();) {
580
					int currStart= listEvent.getIndex(first, ListRewriteEvent.BOTH);
691
			Map.Entry entry= (Map.Entry) iter.next();
581
					int currEnd= listEvent.getIndex(first, ListRewriteEvent.BOTH);
692
			List rangeInfos= (List) entry.getValue(); // list of CopySourceRange
582
					if (currStart < indexFirst && currEnd < indexLast && currEnd >= indexFirst
693
			Collections.sort(rangeInfos); // sort by start index, length, move or copy
583
							|| currStart > indexFirst && currStart <= currEnd && currEnd > indexLast) {
694
			
584
						throw new IllegalArgumentException("Range overlapps with an existing copy or move range"); //$NON-NLS-1$ 
695
			PropertyLocation loc= (PropertyLocation) entry.getKey();
585
					}
696
			RewriteEvent[] children= getListEvent(loc.getParent(), loc.getProperty(), true).getChildren();
697
			
698
			RewriteEvent[] newChildren= processListWithRanges(rangeInfos, children, sourceRangeComputer);
699
			addEvent(loc.getParent(), loc.getProperty(), new ListRewriteEvent(newChildren)); // replace the current edits
700
		}		
701
	}
702
703
	private RewriteEvent[] processListWithRanges(List rangeInfos, RewriteEvent[] childEvents, TargetSourceRangeComputer sourceRangeComputer) {
704
		List newChildEvents= new ArrayList(childEvents.length);
705
		NodeRangeInfo topInfo= null;
706
		Stack newChildrenStack= new Stack();
707
		Stack topInfoStack= new Stack();
708
709
		Iterator rangeInfoIterator= rangeInfos.iterator();
710
		NodeRangeInfo nextInfo= (NodeRangeInfo) rangeInfoIterator.next();
711
		
712
		for (int k= 0; k < childEvents.length; k++) {
713
			RewriteEvent event= childEvents[k];
714
			ASTNode node= (ASTNode) event.getOriginalValue();
715
			// check for ranges and add a placeholder for them
716
			while (nextInfo != null && node == nextInfo.getStartNode()) { // is this child the beginning of a range?
717
				nextInfo.updatePlaceholderSourceRanges(sourceRangeComputer);
718
				
719
				Block internalPlaceholder= nextInfo.getInternalPlaceholder();
720
				RewriteEvent newEvent;
721
				if (nextInfo.isMove()) {
722
					newEvent= new NodeRewriteEvent(internalPlaceholder, nextInfo.replacingNode); // remove or replace
723
				} else {
724
					newEvent= new NodeRewriteEvent(internalPlaceholder, internalPlaceholder); // unchanged
725
				}
726
				newChildEvents.add(newEvent);
727
				if (nextInfo.editGroup != null) {
728
					setEventEditGroup(newEvent, nextInfo.editGroup);
586
				}
729
				}
730
				
731
				newChildrenStack.push(newChildEvents);
732
				topInfoStack.push(topInfo);
733
				
734
				newChildEvents= new ArrayList(childEvents.length);
735
				topInfo= nextInfo;
736
				
737
				nextInfo= rangeInfoIterator.hasNext() ? (NodeRangeInfo) rangeInfoIterator.next() : null;
738
			}
739
			
740
			newChildEvents.add(event);
741
742
			while (topInfo != null && node == topInfo.getEndNode()) {
743
				RewriteEvent[] placeholderChildEvents= (RewriteEvent[]) newChildEvents.toArray(new RewriteEvent[newChildEvents.size()]);
744
				Block internalPlaceholder= topInfo.getInternalPlaceholder();
745
				addEvent(internalPlaceholder, Block.STATEMENTS_PROPERTY, new ListRewriteEvent(placeholderChildEvents));
746
				
747
				newChildEvents= (List) newChildrenStack.pop();
748
				topInfo= (NodeRangeInfo) topInfoStack.pop();
587
			}
749
			}
588
		}
750
		}
751
		return (RewriteEvent[]) newChildEvents.toArray(new RewriteEvent[newChildEvents.size()]);
589
	}
752
	}
590
	
753
591
	/**
754
	/**
592
	 * Make sure all moved nodes are marked as removed or replaced.
755
	 * Make sure all moved nodes are marked as removed or replaced.
593
	 */
756
	 */
594
	public void markMovedNodesRemoved() {
757
	private void prepareSingleNodeCopies() {
595
		if (this.nodeCopySources == null) {
596
			return;
597
		}
598
		for (int i= 0; i < this.nodeCopySources.size(); i++) {
758
		for (int i= 0; i < this.nodeCopySources.size(); i++) {
599
			CopySourceInfo curr= (CopySourceInfo) this.nodeCopySources.get(i);
759
			CopySourceInfo curr= (CopySourceInfo) this.nodeCopySources.get(i);
600
			if (curr.isMove) {
760
			if (curr.isMove && curr.location != null) {
601
				doMarkMovedAsRemoved(curr);
761
				doMarkMovedAsRemoved(curr, curr.location.getParent(), curr.location.getProperty());
602
			}
762
			}
603
		}
763
		}
604
		
764
		
605
	}
765
	}
606
	
766
	
607
	private void doMarkMovedAsRemoved(CopySourceInfo curr) {
767
	private void doMarkMovedAsRemoved(CopySourceInfo curr, ASTNode parent, StructuralPropertyDescriptor childProperty) {
608
		if (curr.childProperty.isChildListProperty()) {
768
		if (childProperty.isChildListProperty()) {
609
			ListRewriteEvent event= getListEvent(curr.parent, curr.childProperty, true);
769
			ListRewriteEvent event= getListEvent(parent, childProperty, true);
610
			int index= event.getIndex(curr.getStartNode(), ListRewriteEvent.OLD);
770
			int index= event.getIndex(curr.getNode(), ListRewriteEvent.OLD);
611
			if (index != -1 && event.getChangeKind(index) == RewriteEvent.UNCHANGED) {
771
			if (index != -1 && event.getChangeKind(index) == RewriteEvent.UNCHANGED) {
612
				event.setNewValue(null, index);
772
				event.setNewValue(null, index);
613
			}
773
			}
614
		} else {
774
		} else {
615
			NodeRewriteEvent event= getNodeEvent(curr.parent, curr.childProperty, true);
775
			NodeRewriteEvent event= getNodeEvent(parent, childProperty, true);
616
			if (event.getChangeKind() == RewriteEvent.UNCHANGED) {
776
			if (event.getChangeKind() == RewriteEvent.UNCHANGED) {
617
				event.setNewValue(null);
777
				event.setNewValue(null);
618
			}
778
			}

Return to bug 91938